shop--10.商品--商品添加(后端)

商品添加dao层

1     /**
2      * 插入商品
3      * 
4      * @param product
5      * @return
6      */
7     int insertProduct(Product product);

商品添加映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper 
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ryanxu.o2o.dao.ProductDao">
    <insert id="insertProduct"
        parameterType="com.ryanxu.o2o.entity.Product" useGeneratedKeys="true"
        keyProperty="productId" keyColumn="product_id">
        INSERT INTO
        tb_product(product_name,product_desc,img_addr,
        normal_price,promotion_price,priority,create_time,
        last_edit_time,enable_status,product_category_id,
        shop_id)
        VALUES
        (#{productName},#{productDesc},#{imgAddr},
        #{normalPrice},#{promotionPrice},#{priority},#{createTime},
        #{lastEditTime},#{enableStatus},#{productCategory.productCategoryId},
        #{shop.shopId})
    </insert>
</mapper>

批量添加商品图片dao层

    /**
     * 批量添加商品详情图片
     * @param productImgList
     * @return
     */
    int batchInsertProductImg(List<ProductImg> productImgList);

批量添加商品图片映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper 
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  <mapper namespace="com.ryanxu.o2o.dao.ProductImgDao">
      <insert id="batchInsertProductImg" parameterType="java.util.List">
          INSERT INTO
          tb_product_img(img_addr,img_desc,priority,
          create_time,product_id)
          VALUES
          <foreach collection="list" item="productImg" index="index"
              separator=",">
              (
               #{productImg.imgAddr},
               #{productImg.imgDesc},
               #{productImg.priority},
               #{productImg.createTime},
               #{productImg.productId}
              )    
          </foreach>
      </insert>
  </mapper>
在做单元测试的时候需要继承BaseTest


Service层

步骤如下:

  • 1.处理商品的缩略图,获取相对路径,为了调用dao层的时候写入 tb_product中的 img_addr字段有值

  • 2.写入tb_product ,得到product_id(Mybatis自动映射进去的)

  • 3.集合product_id 批量处理商品详情图片

  • 4.将商品详情图片 批量更新到 tb_proudct_img表

 1     /**
 2      * 添加商品信息以及图片处理
 3      * 
 4      * @param product
 5      * @param thumbnail 缩略图
 6      * @param productImgs 详情图
 7      * @return
 8      * @throws ProductCategoryOperationException
 9      */
10     ProductExecution addProduct(Product product,ImageHolder thumbanil,List<ImageHolder> productImgList) throws ProductCategoryOperationException;
因为每次都需要传入文件流和文件名 所以使用ImageHolder来专门包装这两个属性
public class ImageHolder {
    private String imageName;
    private InputStream image;
    
    public ImageHolder(String imageName, InputStream image) {
        this.imageName = imageName;
        this.image = image;
    }

    public String getImageName() {
        return imageName;
    }

    public void setImageName(String imageName) {
        this.imageName = imageName;
    }

    public InputStream getImage() {
        return image;
    }

    public void setImage(InputStream image) {
        this.image = image;
    }
    
    
}

Service层的实现类

 1 @Service
 2 public class ProductServiceImpl implements ProductService{
 3     @Autowired
 4     private ProductDao productDao;
 5     @Autowired
 6     private ProductImgDao productImgDao;
 7     
 8     @Override
 9     @Transactional
10     //1.处理缩略图,获取缩略图相对路径并赋值给product
11     //2.往tb_product写入商品信息,获取productId
12     //3.结合productId批量处理商品详情图
13     //4.将商品详情图列表批量插入tb_product_img中
14     public ProductExecution addProduct(Product product, ImageHolder thumbanil, List<ImageHolder> productImgList)
15             throws ProductCategoryOperationException {
16         //空值判断
17         if(product!=null&&product.getShop()!=null&&product.getShop().getShopId()!=null) {
18             //给商品设置默认属性
19             product.setCreateTime(new Date());
20             product.setLastEditTime(new Date());
21             //默认为上架的状态
22             product.setEnableStatus(1);
23             //若商品缩略图不为空则添加
24             if(thumbanil!=null) {
25                 addThumbnail(product,thumbanil);
26             }
27             try {
28                 //创建商品信息
29                 int effectedNum = productDao.insertProduct(product);
30                 if(effectedNum<=0) {
31                     throw new ProductOperationException("创建商品失败");
32                 }
33             }catch (Exception e) {
34                 throw new ProductOperationException("创建商品失败 :" +e.toString());
35             }
36             //若商品详情图不为空则添加
37             if(productImgList != null && productImgList.size() >0) {
38                 addProductImgList(product,productImgList);
39             }
40             return new ProductExecution(ProductStateEnum.SUCCESS,product);
41         }else {
42             //传参为空则返回空值错误信息
43             return new ProductExecution(ProductStateEnum.NULL_PRODUCT);
44         }
45     }
46     
47 
48     /**
49      * 将商品缩略图添加到用户相对的文件夹下,并将店铺信息中的商品图片信息更新
50      * 
51      * @param product
52      * @param imageHolder
53      */
54     private void addThumbnail(Product product,ImageHolder imageHolder) {
55         //获取缩略图的存储途径,直接存储在店铺的文件夹下
56         String dest = PathUtil.getShopImagePath(product.getShop().getShopId());
57         //返回相对路径
58         String thumbnailAddr = ImageUtil.generateThumbnail(imageHolder, dest);
59         product.setImgAddr(thumbnailAddr);
60     }
61     
62     /**
63      * 批量添加商品详情图片到用户相对的文件夹下,并将其批量插入到数据库中
64      * 
65      * @param product
66      * @param productImgHolderList
67      */
68     private void addProductImgList(Product product, List<ImageHolder> productImgHolderList) {
69         //获取图片存储路径,这里直接存放到相应店铺的文件夹底下
70         String dest = PathUtil.getShopImagePath(product.getShop().getShopId());
71         List<ProductImg> productImgList = new ArrayList<>();
72         //遍历图片一次去处理,并添加进productImg实体类里
73         for(ImageHolder productImgHolder:productImgHolderList) {
74             String imgAddr = ImageUtil.generateNormalImg(productImgHolder,dest);
75             ProductImg productImg  = new ProductImg();
76             productImg.setImgAddr(imgAddr);
77             productImg.setProductId(product.getProductId());
78             productImg.setCreateTime(new Date());
79             productImgList.add(productImg);
80         }
81         //如果确实是有图片需要添加的,就执行批量添加操作
82         if(productImgList.size() > 0) {
83             try {
84                 int effectedNum = productImgDao.batchInsertProductImg(productImgList);
85                 if(effectedNum <= 0) {
86                     throw new ProductOperationException("创建商品详情图片失败");
87                 }
88             }catch (Exception e) {
89                 throw new ProductOperationException("创建商品详情图片失败: "+e.toString());
90             }
91         }
92     }
93 }

Controller层

步骤如下:

  • 获取前端传递过来的Product对象,通过FastJson提供的api将其转换为Product对象
  • 获取前端传递过来的商品缩略图以及商品详情图片,通过CommonsMultipartResolver来处理
  • 调用Service层的服务来持久化数据及图片的操作
  1 @Controller
  2 @RequestMapping("/shopadmin")
  3 public class ProductManagementController {
  4     @Autowired
  5     private ProductService productService;
  6     
  7     //支持上传商品详情图的最大数量
  8     private static final int IMAGEMAXCOUNT=6;
  9     
 10     /**
 11      *     前端页面通过post方式传递一个包含文件上传的Form会以multipart/form-data请求发送给服务器,
 12      * 
 13      *  需要告诉DispatcherServlet如何处理MultipartRequest,我们在spring-web.
 14      *  xml中定义了multipartResolver。
 15      * 
 16      *  如果某个Request是一个MultipartRequest,它就会首先被MultipartResolver处理,
 17      *  然后再转发相应的Controller。
 18      * 
 19      *  在Controller中,
 20      *  将HttpServletRequest转型为MultipartHttpServletRequest
 21      *  ,可以非常方便的得到文件名和文件内容
 22      * @param request
 23      * @return    
 24      * @throws IOException
 25      */
 26     @RequestMapping(value="/addproduct",method=RequestMethod.POST)
 27     @ResponseBody
 28     private Map<String, Object> addproduct(HttpServletRequest request) throws IOException{
 29         Map<String, Object> modelMap = new HashMap<>();
 30         
 31         //初始化各种参数!!!!
 32         //接收前端传递过来的product
 33         Product product = null;
 34         String productStr = HttpServletRequestUtil.getString(request, "productStr");
 35         //处理文件流
 36         MultipartHttpServletRequest multipartHttpServletRequest = null;
 37         //接收前端传递过来的product
 38         ImageHolder thumbnail = null;
 39         // 接收商品详情图片
 40         List<ImageHolder> productImgList = new ArrayList<>();
 41         //在本次会话的上下文获取上传的文件
 42         CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
 43         
 44         //步骤1:验证码校验
 45         if(!CodeUtil.checkVerifyCode(request)) {
 46             modelMap.put("success", false);
 47             modelMap.put("errMsg", "验证码错误");
 48             return modelMap;
 49         }
 50         //步骤2:使用FastJson提供的api,实例化Product 构造调用service层的第一个参数
 51         //接受前端参数变量的初始化,商品,缩略图,详情图列表实体类
 52         ObjectMapper objectMapper = new ObjectMapper();
 53         // 获取前端传递过来的product,约定好使用productStr
 54         try {
 55             product = objectMapper.readValue(productStr, Product.class);
 56         } catch (Exception e) {
 57             modelMap.put("success", false);
 58             modelMap.put("errMsg", e.toString());
 59             return modelMap;
 60         }
 61         //步骤3: 商品缩略图 和 商品详情图 构造调用service层的第二个参数和第三个参数
 62         try {
 63             //若请求中存在文件流,则取出相关的文件(包括缩略图和详情图)
 64             if(commonsMultipartResolver.isMultipart(request)) {
 65                 // 将HttpServletRequest转型为MultipartHttpServletRequest,可以很方便地得到文件名和文件内容
 66                 multipartHttpServletRequest = (MultipartHttpServletRequest) request;
 67                 
 68                 //1.接收商品缩略图  取出缩略图并构建ImageHolder对象 
 69                 CommonsMultipartFile thumbnailFile = (CommonsMultipartFile) multipartHttpServletRequest.getFile("thumbnail");
 70                 //2.转化为ImageHolder,使用service层的参数类型要求
 71                 thumbnail = new ImageHolder(thumbnailFile.getOriginalFilename(), thumbnailFile.getInputStream());
 72                 //3.取出详情图列表并构建List<ImageHolder>列表对象,最多支持六张图上传
 73                 for(int i = 0; i < IMAGEMAXCOUNT; i++){
 74                     CommonsMultipartFile commonsMultipartFile = (CommonsMultipartFile) multipartHttpServletRequest.getFile("productImg" + i);
 75                     if(commonsMultipartFile != null){
 76                         //若取出的第i个详情图片文件流不为空,则将其加入详情图列表
 77                         ImageHolder productImg = new ImageHolder(commonsMultipartFile.getOriginalFilename(), commonsMultipartFile.getInputStream());
 78                         productImgList.add(productImg);
 79                     } else {
 80                         //若取出的第i个详情图片文件流为空,则终止循环
 81                         break;
 82                     }
 83                 }
 84  
 85             } else{
 86                 modelMap.put( "success", false );
 87                 modelMap.put( "errMsg", "上传图片不能为空" );
 88             }
 89         } catch (Exception e){
 90             modelMap.put( "success", false );
 91             modelMap.put( "errMsg", e.toString() );
 92             return modelMap;
 93         }
 94 
 95         //步骤4:调用service层
 96         //若product,thumbnail(缩略图),productImgList(商品详情图片列表)不为空,则进行商品添加
 97         if(product != null && thumbnail != null && productImgList.size() > 0){
 98             try{
 99                 //从session中获取当前shop的id赋值给product,减少对前端数据的依赖
100                 Shop currentShop = (Shop) request.getSession().getAttribute( "currentShop" );
101                
102 /*                Shop currentShop = new Shop();
103                 currentShop.setShopId( 1L );*/
104                 Shop shop = new Shop();
105                 shop.setShopId(currentShop.getShopId());
106                 product.setShop(shop);
107                 //执行添加操作
108                 ProductExecution productExecution = productService.addProduct( product, thumbnail, productImgList );
109                 if(productExecution.getState() == ProductStateEnum.SUCCESS.getState()){
110                     modelMap.put( "success", true );
111                 }else{
112                     modelMap.put( "success", false );
113                     modelMap.put( "errMsg", productExecution.getStateInfo() );
114                 }
115             } catch(ProductOperationException e){
116                 modelMap.put( "success", false );
117                 modelMap.put( "errMsg", e.toString() );
118                 return modelMap;
119             }
120         }else{
121             modelMap.put( "success", false );
122             modelMap.put( "errMsg", "请输入商品信息" );
123         }
124         return modelMap;
125     }
126 }
原文地址:https://www.cnblogs.com/windbag7/p/9403277.html