up:: SpringBoot电商项目商品模块介绍
说明:
(1) 本篇博客内容:后台的【增加商品】接口;
(2) 本篇博客需要注意的点:
● 需要注意:【增加商品】接口:本篇博客还没有完全开发完;这是因为图片的地址,还无法上传;
有关,上传图片的内容,在后面几篇博客介绍;
● 新增商品的时候,也要防止商品名称重名;
一:【增加商品】接口介绍;
该接口是后台系统的;
(1)【增加商品】接口文档;
(2)【增加商品】接口:在界面上的效果;
(3)【增加商品】接口:和【上传图片】接口的关系;
因为增加商品时候,需要附带上传商品图片;所以,就【增加商品】接口来说,其中的image属性,就是我们【把图片上传到服务器后的,图片的地址】;
而,这个地址,是只要把图片上传到服务器后,才能得到的;
所以,我们在开发【增加商品】接口时,也要开发【上传图片】接口;
【上传图片】接口会把图片上传到服务器,并返回图片在服务器上的地址;然后我们在把这个地址拿过来,作为【增加商品】接口的image参数;
二:正式开发;
1.创建ProductAdminController类;创建增加商品的方法:addProduct()方法;
ProductAdminController类:
package com.imooc.mall.controller;
import com.imooc.mall.common.ApiRestResponse;
import com.imooc.mall.model.request.AddProductReq;
import com.imooc.mall.service.ProductService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.Valid;
/**
* 描述:【商品模块】后台的Controller
*/
@Controller
public class ProductAdminController {
@Autowired
ProductService productService;
@ApiOperation("新增商品")
@PostMapping("/admin/product/add")
@ResponseBody
public ApiRestResponse addProduct(@Valid @RequestBody AddProductReq addProductReq) {
productService.add(addProductReq);
return ApiRestResponse.success();
}
}
说明:
(1)【url、请求方式:要符合接口规范】,【Swagger文档,添加接口说明】,【返回值要序列化为JSON】;
(2)因为接口参数很多,所以我们额外创建【AddProductRequest】这个bean去接收参数;同时,因为这儿需要参数校验,所以我们使用了Validation参数校验(@Valid);
AddProductReq类:
package com.imooc.mall.model.request;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.Date;
public class AddProductReq {
@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 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;
}
}
首先,这个类就是用来接收前端传过来的参数的;所以,这个类要比照接口的参数来写;
然后,这儿校验规则:
● 我们即参考了实际的业务需求:比如image;虽然在数据库中这个对应的字段,我们要求不能为null,但是我们是设有默认值的;所以,纯技术来说,这个接口的image参数可以不传;但是,从业务的角度来说,我们又要求用户传image;所以,我们的image也要求不为空了;
● 又比如status,虽然数据库要求是非空,但其设置了默认值;所以,综合业务角度来说,可以不传status,如果不传,我们就使用默认值1就行了;
● 又比如,我们要求price不能低于1分,stock库存不能超过10000;否则就给出对应的提示信息;
(3)因为要用到Validation参数校验,所以,需要使用@Valid注解;;因为这儿是POST请求,而且参数是放在Body中的,所以需要使用@RequestBody注解;
(4)有关Service层的listCategoryForCustomer()方法,在下一部分介绍;
(5)【新增商品】接口,其实还没开发完;完整的增加商品,需要上传图片,而这就涉及到了后面要介绍的【上传图片】接口;
2.创建ProductService接口和ProductServiceImpl实现类;在ProductServiceImpl实现类中,编写新增商品的方法add();然后在ProductService接口中,反向生成方法的声明;
(1)在ProductServiceImpl实现类中,编写新增商品的方法add();
package com.imooc.mall.service.impl;
import com.imooc.mall.exception.ImoocMallException;
import com.imooc.mall.exception.ImoocMallExceptionEnum;
import com.imooc.mall.model.dao.ProductMapper;
import com.imooc.mall.model.pojo.Product;
import com.imooc.mall.model.request.AddProductReq;
import com.imooc.mall.service.ProductService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 描述:商品Service实现类;
*/
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
ProductMapper productMapper;
/**
* 新增商品
* @param addProductReq
*/
@Override
public void add(AddProductReq addProductReq) {
//因为,我们是通过Product这个类,和数据库打交道的;
//所以,我们把addProductReq的内容,复制成一个product;
Product product = new Product();
BeanUtils.copyProperties(addProductReq, product);
//首先,我们要看下,商品时候重名
Product productOld = productMapper.selectByName(product.getName());
//如果查出来了,表示数据库中已经有叫这个名字的商品了;那么我们就抛出一个名字已存在的异常
if (productOld != null) {
throw new ImoocMallException(ImoocMallExceptionEnum.NAME_EXISTED);
}
//如果上面没问题,就去调用方法,向数据库中插入数据;
int count = productMapper.insertSelective(product);
//如果count=0,表示插入失败了;我们就抛出一个新增失败的异常;
if (count == 0) {
throw new ImoocMallException(ImoocMallExceptionEnum.CREATE_FAILED);
}
}
}
说明:
(1) 看注释;
(2) 其中,在看商品是否重名的时候,我们在Mapper中创建了一个根据name查商品的方法;有关这个方法在下一部分介绍;
(3) 其中用到的insertSelective()方法,是我们前面利用【mybatis-generator】插件生成的;
(2)然后在ProductService接口中,反向生成方法的声明;
3.在ProductMapper接口中,定义【根据】name查询商品】的方法selectByName();然后在ProductMapper.xml中编写方法的SQL;
(1)在ProductMapper接口中,定义【根据】name查询商品】的方法selectByName();
(2)然后在ProductMapper.xml中编写方法的SQL;
<select id="selectByName" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from imooc_mall_product
where name = #{name,jdbcType=VARCHAR}
</select>
三:启动项目,测试【增加商品】接口;
启动项目;
然后,这儿仅仅出于出于测试【增加商品】接口;这儿先不涉及后面的【上传文件】,所以为了省事,不用自己写JSON,我们可以直接复制接口文档中的内容;(PS:等到后面开发了【上传图片】接口后,这个image属性需要是,【上传图片】接口返回给前端的那个地址;这儿,我们仅仅演示【增加商品】接口,所以这儿我们就暂时伪造了一个实际上不存在的image属性)