在对商品添加的Controller层进行学习理解之前,一定要清楚,这一层与前端进行的数据交互,主要是为了调用Service接口做准备的。所以在Controller层学习的过程中,一定要清晰的明白获得Service接口的参数并最后成功调用Service方法,是需要Controller层完成的重点。
本节最后调用的Service层方法是:
ProductExecution addProduct(Product product, ImageHolder thumbnail, List<ImageHolder> productImgHolderList)
throws ProductOperationException;
web/shopadmin/ProductManagementController.java
@Controller
@RequestMapping("/shopadmin")
public class ProductManagementController {
@Autowired
private ProductService productService;
// 支持上传商品详情图的最大数量
private static final int IMAGEMAXCOUNT = 6;
@RequestMapping(value = "/addproduct", method = RequestMethod.POST)
@ResponseBody
private Map<String, Object> addProduct(HttpServletRequest request) {
Map<String, Object> modelMap = new HashMap<String, Object>();
// 验证码校验
if (!CodeUtil.checkVerifyCode(request)) {
modelMap.put("success", false);
modelMap.put("errMsg", "输入了错误的验证码");
return modelMap;
}
// 接收前端参数的变量的初始化,包括商品,缩略图,详情图列表实体类
ObjectMapper mapper = new ObjectMapper();
Product product = null;
MultipartHttpServletRequest multipartRequest = null;
ImageHolder thumbnail = null;
List<ImageHolder> productImgList = new ArrayList<ImageHolder>();
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
try {
// 若请求中存在文件流,则取出相关的文件(包括缩略图和详情图)
if (multipartResolver.isMultipart(request)) {
multipartRequest = (MultipartHttpServletRequest) request;
//取出缩略图并构建ImageHolder对象
CommonsMultipartFile thumbnailFile = (CommonsMultipartFile) multipartRequest
.getFile("thumbnail");
thumbnail = new ImageHolder(thumbnailFile.getOriginalFilename(),
thumbnailFile.getInputStream());
//取出详情图列表并构建List列表对象,最多支持六张图片上传
for(int i = 0; i < IMAGEMAXCOUNT; i++) {
CommonsMultipartFile productImgFile = (CommonsMultipartFile) multipartRequest
.getFile("productImg" + i);
if(productImgFile != null) {
//若取出的第i个详情图片文件流不为空,则将其加入到详情图列表
ImageHolder productImg = new ImageHolder(productImgFile.getOriginalFilename(),
productImgFile.getInputStream());
productImgList.add(productImg);
} else {
//若取出第i个详情图片文件流为空,则终止循环
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;
}
try {
String productStr = HttpServletRequestUtil.getString(request, "productStr");
// 尝试获取前端传过来的表单string流并将其转换成Product实体类
product = mapper.readValue(productStr, Product.class);
} catch (Exception e) {
modelMap.put("success", false);
modelMap.put("errMsg", e.toString());
return modelMap;
}
// 若Product信息,缩略图以及详情图列表为非空,则开始进行商品添加操作
if (product != null && thumbnail != null && productImgList.size() > 0) {
try {
// 从session中获取当前店铺的Id并赋值给product,减少对前端数据的依赖
Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
product.setShop(currentShop);
// 执行添加操作
ProductExecution pe = productService.addProduct(product, thumbnail, productImgList);
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;
}
所有店铺管理有关的操作都在/shopadmin/url下,这里给商品添加接口的url地址为/shopadmin/addproduct。
在方法实现之前先写了一个静态变量IMAGEMAXCOUNT,它定义了商品详情图最大的数量为6。
首先进行验证码校验工作,这里调用了CodeUtil工具类对验证码进行验证。
然后进行缩略图和详情图提取工作。这一过程获得了缩略图ImageHolder对象和ProductImgList对象。Service层的两个参数
定义了CommonsMultipartResolver对象获得request中Session的上下文,查看request中存不存在文件流。如果不存在文件流,封装Map返回错误提示“图片不能为空”。如果存在文件流,则将request转化为MultipartHttpServletRequest类型的对象,以便后面获得上传的图片文件流。
首先获得缩略图的图片文件流:
从MultipartHttpServletRequest对象中通过getFile(缩略图主键)的方法得到缩略图文件流,并将缩略图文件流转化为CommonsMultipartFile类型的对象,从CommonsMultipartFile类型的对象中,我们就可以得到图片流和图片名字,封装到ImageHolder中,存入Product对象里了。
然后通过循环的方式获得详情图的图片文件流:
循环6次,先从MultipartHttpServletRequest对象中通过getFile(详情图主键)的方法得到详情图文件流并将缩略图文件流转化为CommonsMultipartFile类型的对象。然后判断得到的详情图文件流是否为空。
如果非空,从CommonsMultipartFile类型的对象中,我们就可以得到图片流和图片名字,封装到ImageHolder中,存入ProductImgList对象里了。
如果为空说明详情图读取完毕结束循环。
接下来就是获得Product对象参数的步骤。
Product对象参数中包括前端传来的表单信息除图片以外所有的信息。
首先调用HttpServletRequestUtil类的getString方法获得前端传来的主键为"productStr"的数据,这里面存储的就是前端封装好的Json形式的Product对象,通过ObjectMapper类的readValue方法可以将获得的字符串直接转化为Product对象。
Service接口的三个参数全都获得成功啦,接下来就是对Service的调用步骤。
首先使用if语句确保三个参数都是合理的。其次,我们需要通过Session获得Shop对象赋值给Product。使用Session获得Shop对象的原因是减少前端的依赖,也防止用户乱传Shopid减少了安全隐患。
之后就可以调用Service接口productService.addProduct方法了。之后,通过返回的ProductExecution,进行操作状态的判断,并将最后的操作信息以Map的形式返回给前端。