zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    [LeetCode] Max Increase to Keep City Skyline 保持城市天际线的最大增高
    [LeetCode] Bricks Falling When Hit 碰撞时砖头掉落
    [LeetCode] Number of Lines To Write String 写字符串需要的行数
    [LeetCode] Unique Morse Code Words 独特的摩斯码单词
    [LeetCode] Find Eventual Safe States 找到最终的安全状态
    [LeetCode] Minimum Swaps To Make Sequences Increasing 使得序列递增的最小交换
    [LeetCode] Similar RGB Color 相似的红绿蓝颜色
    [LeetCode] Champagne Tower 香槟塔
    [LeetCode] Smallest Rotation with Highest Score 得到最高分的最小旋转
    [LeetCode] All Paths From Source to Target 从起点到目标点到所有路径
  • 原文地址:https://www.cnblogs.com/windbag7/p/9403277.html
Copyright © 2011-2022 走看看