up:: SpringBoot电商项目商品模块商品接口之图片
说明:
(1) 本篇博客内容:开发【更新商品】接口;
(2) 本篇博客需要注意的点:
● 【更新商品】时的时候,要编写对应的逻辑,以确保此次更新的结果不会导致商品名重名;
一:【更新商品】接口介绍;
(1)【更新商品】接口文档;
这个接口是需要管理员用户登录的,而我们在AdminFilterConfig中,也对其进行了统一的处理;
(2)更新商品,在页面上的表现;
(3)一个疑问?:【增加商品】接口和【更新商品】接口,这么像,为什么不统一写成一个接口?
二者的接口文档:请求方式一样、参数差不多(更新接口多了一个商品id)、参数都在POST请求的Body中、返回内容等,都差不多;
那么,为什么不建议把这两个接口开发成一个?这是因为:
● 这两个接口虽然很像,但二者是不同的;【新增商品】和【更新商品】这两个业务,现在看起来功能都差不多;但是,后面随着业务的发展,【新增商品】和【更新商品】这两个业务,会有更多不彼此同的功能;所以,如果把【新增商品】接口和【更新商品】接口合并的话,后期就不利于维护;
● 比如下面这个例子:
【新增商品】的时候,需要新增创建人这一个字段;而【更新商品】的时候,不允许更新创建人这个字段;通过这例子,能够感受到,以后随着业务的发展,【新增商品】和【更新商品】这两个业务,会有更多彼此同的功能;而如果强行把两个接口合并的话,后期维护就会比较困难;
二:正式开发;
1.在ProductAdminController类中,创建更新商品的方法:updateProduct()方法;
/**
* 更新商品
* @param updateProductReq
* @return
*/
@ApiOperation("更新商品")
@PostMapping("/admin/product/update")
@ResponseBody
public ApiRestResponse updateProduct(@Valid @RequestBody UpdateProductReq updateProductReq) {
Product product = new Product();
BeanUtils.copyProperties(updateProductReq, product);
productService.update(product);
return ApiRestResponse.success();
}
说明:
(1)因为接口参数很多,所以我们额外创建【UpdateProductReq】这个bean去接收参数;同时,因为这儿也需要一些参数校验,所以我们使用了Validation参数校验(@Valid);
UpdateProductReq:
package com.imooc.mall.model.request;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public class UpdateProductReq {
@NotNull(message = "商品id不能为null")
private Integer id;
// @NotNull(message = "商品名称不能为null")
private String name;
// @NotNull(message = "商品图片不能为null")
private String image;
private String detail;
// @NotNull(message = "商品分类不能为null")
private Integer categoryId;
// @NotNull(message = "商品价格不能为null")
@Min(value = 1, message = "价格不能小于1")
private Integer price;
// @NotNull(message = "商品库存不能为null")
@Max(value = 10000, message = "库存不能大于10000")
private Integer stock;
private Integer status;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public Integer getCategoryId() {
return categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}
● 因为更新接口的参数中,有商品id,所以这个类中也添加了id属性;而且,要求id这个参数是必必须传的,所以我们也使用了Validation的非空校验;
● 而究竟传那些参数、没有传那些参数,是由前端决定的;反正,后端的要求是:必须要传id,其他参数随便;
(2)方法的简单说明;
(3)service层的更新商品的update()方法,在下一部分介绍;
2.在ProductServiceImpl实现类中,编写更新商品的方法update();然后在ProductService接口中,反向生成方法的声明;
(1)在ProductServiceImpl实现类中,编写更新商品的方法update();
/**
* 更新商品
* @param product
*/
@Override
public void update(Product product) {
//先根据商品名,去数据库中查,看是否有叫这个名字的商品数据
Product productOld = productMapper.selectByName(product.getName());
//如果上面查到了
//而且【上面查到的商品的id】和【我们前台穿过来的商品id不一样】,那么不允许更新,抛出不允许重名异常;
// 很显然,这一条也是为了防止商品名重名;
if (productOld != null && productOld.getId() != product.getId())
{
throw new ImoocMallException(ImoocMallExceptionEnum.NAME_EXISTED);
}
//然后调用Dao层的更新方法,去更新数据
int count = productMapper.updateByPrimaryKeySelective(product);
//如果更新失败,就抛出更新失败异常;
if (count == 0) {
throw new ImoocMallException(ImoocMallExceptionEnum.UPDATE_FAILED);
}
}
说明:
(1) 更新商品的时候,也要防止【我们填写的更新信息】可能会导致商品名重名的情况;
(2) 确认不会重名后,就调用【我们通过mybatis-generator插件生成的,updateByPrimaryKeySelective()方法】去更新数据;至于为什么要使用这个方法,是因为:更新的时候,前端传的数据可能不全,这就导致Product对象可能很多属性没有值,所以用updateByPrimaryKeySelective这个方法,是合适的;
(2)然后在ProductService接口中,反向生成方法的声明;
三:测试【更新商品】接口;
比照【更新商品】接口对数据的要求和格式,然后根据id=46的那条数据,来组织数据;
先调用【管理员登录】接口,然后调用【更新商品】接口;