实战SSM_O2O商铺_30【商品】商品添加之Controller层的实现

概述

商品添加Controller层的逻辑如下:

1. 获取前端传递过来的Product对象,通过FastJson提供的api将其转换为Product对象

2. 获取前端传递过来的商品缩略图以及商品详情图片,通过CommonsMultipartResolver来处理

3. 调用Service层的服务来持久化数据及图片的操作


ProductController

package com.artisan.o2o.web.shopadmin;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import com.artisan.o2o.dto.ImageHolder;
import com.artisan.o2o.dto.ProductExecution;
import com.artisan.o2o.entity.Product;
import com.artisan.o2o.entity.Shop;
import com.artisan.o2o.enums.ProductStateEnum;
import com.artisan.o2o.exception.ProductOperationException;
import com.artisan.o2o.service.ProductService;
import com.artisan.o2o.util.HttPServletRequestUtil;
import com.artisan.o2o.util.VerifyCodeUtil;
import com.fasterxml.jackson.databind.ObjectMapper;

@Controller
@RequestMapping("/shopadmin")
public class ProductController {

    @Autowired
    private ProductService productService;

    // 最大上传图片数量
    private static final int IMAGEMAXCOUNT = 6;

    /**
     * 
     * 
     * @Title: addProduct
     * 
     * @Description: 1. 验证码校验
     * 
     *               2. 接收前端参数:包括 商品、 商品缩略图、商品详情图片实体类
     * 
     *               前端页面通过post方式传递一个包含文件上传的Form会以multipart/form-data请求发送给服务器,
     * 
     *               需要告诉DispatcherServlet如何处理MultipartRequest,我们在spring-web.
     *               xml中定义了multipartResolver。
     * 
     *               如果某个Request是一个MultipartRequest,它就会首先被MultipartResolver处理,
     *               然后再转发相应的Controller。
     * 
     *               在Controller中,
     *               将HttpServletRequest转型为MultipartHttpServletRequest
     *               ,可以非常方便的得到文件名和文件内容
     * 
     * @param request
     * 
     * @return: Map<String,Object>
     * 
     *          注解@ResponseBody 负责将返回的map对象转换为JSON,供前端使用
     */
    @RequestMapping(value = "/addproduct", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> addProduct(HttpServletRequest request) {
        Map<String, Object> modelMap = new HashMap<String, Object>();
        Product product = null;
        // 接收前端传递过来的product
        String productStr = null;
        // 商品图片缩略图(输入流和名称的封装类)
        ImageHolder thumbnail = null;

        // 将HttpServletRequest转型为MultipartHttpServletRequest,可以很方便地得到文件名和文件内容
        MultipartHttpServletRequest multipartHttpServletRequest = null;
        // 接收商品缩略图
        CommonsMultipartFile thumbnailFile = null;
        // 接收商品详情图片
        List<ImageHolder> productDetailImgList = new ArrayList<ImageHolder>();

        // 创建一个通用的多部分解析器
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());

        // Step1:校验验证码
        if (!VerifyCodeUtil.verifyCode(request)) {
            modelMap.put("success", false);
            modelMap.put("errMsg", "验证码不正确");
            return modelMap;
        }

        // Step2: 使用FastJson提供的api,实例化Product 构造调用service层的第一个参数
        ObjectMapper mapper = new ObjectMapper();
        // 获取前端传递过来的product,约定好使用productStr
        try {
            productStr = HttPServletRequestUtil.getString(request, "productStr");
            product = mapper.readValue(productStr, Product.class);
        } catch (Exception e) {
            modelMap.put("success", false);
            modelMap.put("errMsg", e.toString());
            return modelMap;
        }
        // Step3: 商品缩略图 和 商品详情图 构造调用service层的第二个参数和第三个参数
        try {
            // 判断 request 是否有文件上传,即多部分请求
            if (commonsMultipartResolver.isMultipart(request)) {
                // 将request转换成多部分request
                multipartHttpServletRequest = (MultipartHttpServletRequest) request;

                // 得到缩略图的CommonsMultipartFile ,和前端约定好使用thumbnail 传递
                // ,并构建ImageHolder对象
                thumbnailFile = (CommonsMultipartFile) multipartHttpServletRequest.getFile("thumbnail");
                // 转化为ImageHolder,使用service层的参数类型要求
                thumbnail = new ImageHolder(thumbnailFile.getInputStream() ,thumbnailFile.getOriginalFilename());

                // 得到 商品详情的列表,和前端约定使用productImg + i 传递 ,并构建ImageHolder对象
                for (int i = 0; i < IMAGEMAXCOUNT; i++) {
                    CommonsMultipartFile productDetailImgFile = (CommonsMultipartFile) multipartHttpServletRequest.getFile("productImg" + i);
                    if (productDetailImgFile != null) {
                        ImageHolder productDetailImg = new ImageHolder(productDetailImgFile.getInputStream(),productDetailImgFile.getOriginalFilename());
                        productDetailImgList.add(productDetailImg);
                    }else{
                        // 如果从请求中获取的到file为空,终止循环
                        break;
                    }
                }
            } else {
                modelMap.put("success", false);
                modelMap.put("errMsg", "上传图片不能为空");
                return modelMap;
            }
        } catch (Exception e) {
            modelMap.put("success", false);
            modelMap.put("errMsg", e.toString());
            return modelMap;
        }

        // Step4 调用Service层
        if (product != null && thumbnailFile != null && productDetailImgList.size() > 0) {
            try {
                // 从session中获取shop信息,不依赖前端的传递更加安全
                Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
                product.setShop(currentShop);
                // 调用addProduct
                ProductExecution pe = productService.addProduct(product, thumbnail, productDetailImgList);
                if (pe.getState() == ProductStateEnum.SUCCESS.getState()) {
                    modelMap.put("success", true);
                } else {
                    modelMap.put("success", false);
                    modelMap.put("errMsg", pe.getStateInfo());
                }
            } catch (ProductOperationException e) {
                modelMap.put("success", false);
                modelMap.put("errMsg", e.toString());
                return modelMap;
            }
        } else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "请输入商品信息");
        }
        return modelMap;
    }

}

单元测试

待前端页面开发完毕后,一并测试


Github地址

代码地址: https://github.com/yangshangwei/o2o

猜你喜欢

转载自blog.csdn.net/yangshangwei/article/details/80823201