一、 商品详情页展示

1.1京淘后台表设计

07-京淘项目 - 图1

1.2 准备POJO对象

07-京淘项目 - 图2

1.3 富文本编辑器介绍

KindEditor是一套开源的HTML可视化编辑器,主要用于让用户在网站上获得所见即所得编辑效果,兼容IE、Firefox、Chrome、Safari、Opera等主流浏览器

  1. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  2. <link href="/js/kindeditor-4.1.10/themes/default/default.css" type="text/css" rel="stylesheet">
  3. <script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/kindeditor-all-min.js"></script>
  4. <script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/lang/zh_CN.js"></script>
  5. <script type="text/javascript" charset="utf-8" src="/js/jquery-easyui-1.4.1/jquery.min.js"></script>
  6. <script type="text/javascript">
  7. $(function(){
  8. KindEditor.ready(function(){
  9. KindEditor.create("#editor")
  10. })
  11. })
  12. </script>
  13. </head>
  14. <body>
  15. <h1>富文本编辑器</h1>
  16. <textarea style="width:700px;height:350px" id="editor"></textarea>
  17. </body>
  18. </html>

07-京淘项目 - 图3

1.4 重构商品新增操作

1.4.1 编辑ItemController

  1. @RequestMapping("/save")
  2. public SysResult saveItem(Item item, ItemDesc itemDesc){
  3. itemService.saveItem(item,itemDesc);
  4. return SysResult.success();
  5. /*try {
  6. itemService.saveItem(item);
  7. return SysResult.success();
  8. }catch (Exception e){
  9. e.printStackTrace();
  10. return SysResult.fail();
  11. }*/
  12. }

1.4.2 编辑ItemService

  1. //xml文件配置 keyProperty="id" keyColumn="id" useGeneratedKeys="true"
  2. @Override
  3. @Transactional //控制事务
  4. public void saveItem(Item item, ItemDesc itemDesc) {
  5. //1.入库商品信息
  6. item.setStatus(1); //默认是正常状态
  7. itemMapper.insert(item); //执行数据库入库操作,动态生成ID
  8. //如何实现主键自增的回显功能? 可以通过标签的配置实现,但是MP已经实现该功能
  9. //2.入库详情信息 如何保证item与itemDesc主键信息一致?
  10. itemDesc.setItemId(item.getId());
  11. itemDescMapper.insert(itemDesc);
  12. }

1.5 商品详情回显

1.5.1 页面分析

  1. $.getJSON('/item/query/item/desc/'+data.id,function(_data){
  2. if(_data.status == 200){
  3. itemEditEditor.html(_data.data.itemDesc);
  4. }
  5. });

1.5.2 编辑ItemController

  1. /**
  2. * 需求: 根据商品Id,查询商品的详情信息.
  3. * url地址: http://localhost:8091/item/query/item/desc/1474392019
  4. * 参数: 商品Id号
  5. * 返回值: SysResult对象
  6. */
  7. @RequestMapping("/query/item/desc/{itemId}")
  8. public SysResult findItemDescById(@PathVariable Long itemId){
  9. ItemDesc itemDesc = itemService.findItemDescById(itemId);
  10. return SysResult.success(itemDesc);
  11. }

1.5.3 编辑ItemService

  1. @Override
  2. public ItemDesc findItemDescById(Long itemId) {
  3. return itemDescMapper.selectById(itemId);
  4. }

1.5.3 页面效果展现
07-京淘项目 - 图4

1.6 重构商品修改

1.6.1 编辑ItemController

  1. /**
  2. * 实现商品修改操作
  3. * 1.url地址: /item/update
  4. * 2.请求参数: form表单提交
  5. * 3.返回值: SysResult对象
  6. */
  7. @RequestMapping("/update")
  8. public SysResult updateItem(Item item,ItemDesc itemDesc){
  9. itemService.updateItem(item,itemDesc);
  10. return SysResult.success();
  11. }

1.6.2 编辑ItemService

  1. //一般更新操作都是根据主键更新
  2. //Sql: update tb_item set titel=#{xxxx},xx,x,x,x,x, where id=#{xxx}
  3. @Override
  4. @Transactional
  5. public void updateItem(Item item, ItemDesc itemDesc) {
  6. //根据对象中不为null的元素充当set条件
  7. itemMapper.updateById(item);
  8. itemDesc.setItemId(item.getId());
  9. itemDescMapper.updateById(itemDesc);
  10. }

1.6 重构商品删除

1.6.1 编辑ItemService

  1. //批量删除操作
  2. @Override
  3. @Transactional
  4. public void deleteItems(Long[] ids) {
  5. List<Long> longList = Arrays.asList(ids);
  6. //itemMapper.deleteBatchIds(longList);
  7. //手动的删除数据
  8. itemMapper.deleteItems(ids);
  9. itemDescMapper.deleteBatchIds(longList);
  10. }

二、实现文件上传操作

2.1 入门案例

2.1.1 编辑页面

  1. <body>
  2. <h1>实现文件长传</h1>
  3. <!--enctype="开启多媒体标签" -->
  4. <form action="http://localhost:8091/file" method="post"
  5. enctype="multipart/form-data">
  6. <input name="fileImage" type="file" />
  7. <input type="submit" value="提交"/>
  8. </form>
  9. </body>

2.1.2 编辑FileController

  1. @RestController
  2. public class FileController {
  3. /**
  4. * url地址: http://localhost:8091/file
  5. * 步骤:
  6. * 1.获取图片的名称
  7. * 2.准备文件目录
  8. * 3.拼接文件上传的路径
  9. * 4.实现文件上传.
  10. *
  11. * @param fileImage
  12. * @return
  13. */
  14. @RequestMapping("/file")
  15. public String file(MultipartFile fileImage) throws IOException {
  16. //1.获取图片名称
  17. String name = fileImage.getOriginalFilename();
  18. //2.准备文件上传目录
  19. String dir = "D:/JT-SOFT/images";
  20. //3.利用对象封装路径
  21. File dirFile = new File(dir);
  22. if(!dirFile.exists()){
  23. //如果不存在,则应该创建目录
  24. dirFile.mkdirs(); //创建多级目录
  25. }
  26. //4.实现文件上传
  27. File file = new File(dir+"/" +name);
  28. fileImage.transferTo(file);
  29. return "操作成功!!!";
  30. }
  31. }

2.2 封装文件上传VO对象-imageVO

  1. package com.jt.vo;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import lombok.experimental.Accessors;
  6. @Data
  7. @Accessors(chain = true)
  8. @NoArgsConstructor
  9. @AllArgsConstructor
  10. public class ImageVO {
  11. // {"error":0,"url":"图片的保存路径","width":图片的宽度,"height":图片的高度}
  12. private Integer error; //错误信息 0 正常 1 失败
  13. private String url; //图片网址
  14. private Integer width; //宽度
  15. private Integer height; //高度
  16. //准备API 简化用户操作
  17. public static ImageVO fail(){
  18. return new ImageVO(1, null, null, null);
  19. }
  20. public static ImageVO success(String url,Integer width,Integer height){
  21. return new ImageVO(0,url, width, height);
  22. }
  23. }

2.3 实现文件上传

2.3.1 页面url分析

07-京淘项目 - 图5
2.获取参数名称
07-京淘项目 - 图6

2.3.2 编辑FileController

  1. @Autowired
  2. private FileService fileService;
  3. /**
  4. * 业务需求: 实现文件上传
  5. * 1.url地址: http://localhost:8091/pic/upload?dir=image
  6. * 2.请求参数: uploadFile
  7. * 3.返回值结果: ImageVO
  8. */
  9. @RequestMapping("/pic/upload")
  10. public ImageVO upload(MultipartFile uploadFile) throws IOException {
  11. return fileService.upload(uploadFile);
  12. }

2.3.3 编辑FileService

  1. package com.jt.service;
  2. import com.jt.vo.ImageVO;
  3. import org.springframework.stereotype.Service;
  4. import org.springframework.web.multipart.MultipartFile;
  5. import javax.imageio.ImageIO;
  6. import java.awt.image.BufferedImage;
  7. import java.io.File;
  8. import java.io.IOException;
  9. import java.text.SimpleDateFormat;
  10. import java.util.Date;
  11. import java.util.HashSet;
  12. import java.util.Set;
  13. import java.util.UUID;
  14. @Service
  15. public class FileServiceImpl implements FileService{
  16. //定义文件存储的根目录
  17. private String fileLocalDir = "D:/JT-SOFT/images";
  18. private static Set<String> typeSet = new HashSet<>();
  19. static {
  20. typeSet.add(".jpg");
  21. typeSet.add(".png");
  22. typeSet.add(".gif");
  23. }
  24. /**
  25. * 注意事项:
  26. * 1.校验是否为图片类型 xxx.jpg|png|jpeg|gif.....
  27. * 2.校验是否为恶意程序 宽度/高度
  28. * 3.采用分目录方式进行数据的存储 1.hash方式 2.时间单位 yyyy/MM/dd/
  29. * 4.防止文件重名.... UUID.jpg
  30. * @param uploadFile
  31. * @return
  32. */
  33. @Override
  34. public ImageVO upload(MultipartFile uploadFile){
  35. //1.获取图片文件名称 a.jpg A.JPG
  36. String fileName = uploadFile.getOriginalFilename(); //123.jpg
  37. fileName = fileName.toLowerCase(); //全部小写.
  38. //2.获取图片的类型
  39. int index = fileName.lastIndexOf(".");
  40. String fileType = fileName.substring(index); //.jpg
  41. if(!typeSet.contains(fileType)){
  42. return ImageVO.fail(); //结束任务
  43. }
  44. //问题2: 防止恶意程序的攻击 图片 宽度和高度
  45. try {
  46. //获取图片对象类型
  47. BufferedImage bufferedImage =
  48. ImageIO.read(uploadFile.getInputStream());
  49. int width = bufferedImage.getWidth();
  50. int height = bufferedImage.getHeight();
  51. if(width ==0 || height == 0){
  52. return ImageVO.fail();
  53. }
  54. /**
  55. * 三: 分目录存储 以时间为维度截串 /yyyy/MM/dd/
  56. */
  57. String dateDir =
  58. new SimpleDateFormat("/yyyy/MM/dd/")
  59. .format(new Date());
  60. String fireDir = fileLocalDir + dateDir;
  61. File imageFileDir = new File(fireDir);
  62. if(!imageFileDir.exists()){
  63. //动态生成文件目录
  64. imageFileDir.mkdirs();
  65. }
  66. /**
  67. * 四: 防止文件重名,动态生成文件名称 uuid.jpg
  68. * uuid 32位16进制数 (2^4)^32= 2^128
  69. */
  70. String uuid = UUID.randomUUID()
  71. .toString().replace("-", "");
  72. String realFileName = uuid + fileType; //uuid.jpg
  73. //fireDir/uuid.jpg
  74. File realFile = new File(fireDir+realFileName);
  75. uploadFile.transferTo(realFile);
  76. //如果程序一切正常
  77. String url = "https://img14.360buyimg.com/n0/jfs/t1/112052/9/3699/127886/5ea9598dE40977b56/d3813bc086108a0b.jpg";
  78. return ImageVO.success(url, width, height);
  79. } catch (IOException e) {
  80. //将检查异常,转化为运行时异常
  81. e.printStackTrace();
  82. //throw new RuntimeException(e);
  83. return ImageVO.fail();
  84. }
  85. }
  86. }

2.3.4 页面效果展现

07-京淘项目 - 图7

三、总结

本节扩展商品增加功能里的商品详情页展示功能,图片上传功能以及文件上传功能,其中的逻辑和之前的增删改查有所不同,逻辑流程更加复杂,要考虑到实际业务情况和可能出现的bug.