Spring Boot电商项目(四)

简介: Spring Boot电商项目

四.商品分类管理模块的开发


1.分类模块地主要功能


第一个,我们先要实现分类数据的设置,这个设置包括通常增删改。除了增删改之外,分类模块的一大重点就在于查找。查找的主要难点就在于他的分类的父一级目录查找和递归查找。比如说车厘子的父目录为进口水果,而进口水果的父目录为新鲜水果。而对于列表而言,他的顺序相反,他是先从形象水果开始递归。先查询到进口水果,再往下一层到车厘子。并且前后台展现是不一样的,后台商品平铺,前台要有层级分类。


2.后台新增分类功能的实现


我们先来实现后台新增分类。

要创建的代码和类如下,没有什么新知识点的类我就不进行解释了。


先要创建一个request包,用来存放请求参数的封装的类。里面新增一个AddCategoryReq类:


package com.haiexijun.mall.model.request;
/**
 * 描述: 添加目录时的一个请求类
 */
public class AddCategoryReq {
    private String name;
    private Integer type;
    private Integer parentId;
    private Integer orderNum;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public Integer getParentId() {
        return parentId;
    }
    public void setParentId(Integer parentId) {
        this.parentId = parentId;
    }
    public Integer getOrderNum() {
        return orderNum;
    }
    public void setOrderNum(Integer orderNum) {
        this.orderNum = orderNum;
    }
}


CategoryMapper接口中新增一个selectByName方法,用来后面CategoryServiceImpl校验要添加的目录是否存在。


package com.haiexijun.mall.model.dao;
import com.haiexijun.mall.model.pojo.Category;
import org.springframework.stereotype.Repository;
@Repository
public interface CategoryMapper {
    int deleteByPrimaryKey(Integer id);
    int insert(Category record);
    int insertSelective(Category record);
    Category selectByPrimaryKey(Integer id);
    int updateByPrimaryKeySelective(Category record);
    int updateByPrimaryKey(Category record);
    Category selectByName(String name);
}


这个方法的xml映射为:


  <select id="selectByName" parameterType="java.lang.String" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from mall_category
    where name=#{name,jdbcType=VARCHAR}
  </select>


然后下面是CategoryService和CategoryServiceImpl的相关代码:


package com.haiexijun.mall.service;
import com.haiexijun.mall.exception.MallException;
import com.haiexijun.mall.model.request.AddCategoryReq;
/**
 * 商品分类目录Service
 */
public interface CateGoryService {
    void add(AddCategoryReq addCateGoryReq) throws MallException;
}
package com.haiexijun.mall.service.impl;
import com.haiexijun.mall.exception.MallException;
import com.haiexijun.mall.exception.MallExceptionEnum;
import com.haiexijun.mall.model.dao.CategoryMapper;
import com.haiexijun.mall.model.pojo.Category;
import com.haiexijun.mall.model.request.AddCategoryReq;
import com.haiexijun.mall.service.CateGoryService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CateGoryServiceImpl implements CateGoryService {
    @Autowired
    CategoryMapper categoryMapper;
    @Override
    public void add(AddCategoryReq addCateGoryReq) throws MallException {
        Category category=new Category();
        //通过spring提供的BeanUtils.copyProperties(),把addCateGoryReq拷贝到category中
        BeanUtils.copyProperties(addCateGoryReq,category);
        Category categoryOld= categoryMapper.selectByName(addCateGoryReq.getName());
        if (categoryOld!=null){
            //如果查询到的目录存在,则不允许创建
            throw new MallException(MallExceptionEnum.NAME_EXISTED);
        }
        int count= categoryMapper.insertSelective(category);
        if (count==0){
            throw new MallException(MallExceptionEnum.CREATE_FAILED);
        }
    }
}

下面就是CategoryController的相关代码:

package com.haiexijun.mall.controller;
import com.haiexijun.mall.common.ApiRestResponse;
import com.haiexijun.mall.common.Constant;
import com.haiexijun.mall.exception.MallException;
import com.haiexijun.mall.exception.MallExceptionEnum;
import com.haiexijun.mall.model.pojo.User;
import com.haiexijun.mall.model.request.AddCategoryReq;
import com.haiexijun.mall.service.CateGoryService;
import com.haiexijun.mall.service.UserService;
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.servlet.http.HttpSession;
/**
 * 描述 :商品目录Controller
 */
@Controller
public class CategoryController {
    @Autowired
    UserService userService;
    @Autowired
    CateGoryService cateGoryService;
    //新增目录
    // 传入一个Httpsession,判断用户是否登录了
    @PostMapping("/admin/category/add")
    @ResponseBody
    public ApiRestResponse addCategory(HttpSession session,@RequestBody AddCategoryReq addCategoryReq){
        // 判断传来的参数有没有空的
        if (addCategoryReq.getName()==null||addCategoryReq.getOrderNum()==null||addCategoryReq.getType()==null||addCategoryReq.getParentId()==null){
            //参数不能为空
            return ApiRestResponse.error(MallExceptionEnum.PARAM_NOT_NULL);
        }
        //判断用户是否为管理员,只有管理员才能对后台目录进行操作
        User currentUser=(User) session.getAttribute(Constant.MALL_USER);
        boolean adminRole=userService.checkAdminRole(currentUser);
        if (adminRole){
            //是管理员
            try {
                cateGoryService.add(addCategoryReq);
            } catch (MallException e) {
                e.printStackTrace();
            }
            return ApiRestResponse.success();
        }else {
            //不是管理员
            return ApiRestResponse.error(MallExceptionEnum.NEED_ADMIN);
        }
    }
}


3. 使用@Valid注解进行参数校验


之前我们controller里面是一个一个参数进行校验是否传入空值,这一点都不优雅。下面学习几个常用的用于参数校验的注解。


98393ec7097c4b78b52fc2b6b9c52e5c.png

4a74102d256f46838988923772e6262d.png


当然,@Valid校验肯定不止这么点注解,我们用到去查就行了。

首先第一个就是@Valid注解,一旦我们给某一个传入的参数加上这一个注解之后,那就意味着他需要校验。当加上这个注解之后,我们再去给他的字段加下面的3个注解。


下面我们来实际操作一下,这些注解如何使用,我们把之前校验目录传参是否为空进行改造一下:

先要导入一个依赖:


 <dependency>
     <groupId>org.hibernate.validator</groupId>
     <artifactId>hibernate-validator</artifactId>
     <version>6.1.0.Final</version>
 </dependency>


一定要导入这个依赖不然会报错。


之后,就要在controller的请求参数前添加@Valid注解:


public ApiRestResponse addCategory(HttpSession session,@Valid @RequestBody AddCategoryReq addCategoryReq){····省略···}


我们还要在AddCategoryReq这个请求参数类中添加其他一些校验注解:


package com.haiexijun.mall.model.request;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
 * 描述: 添加目录时的一个请求类
 */
public class AddCategoryReq {
    @Size(min = 2,max = 5,message = "name应该大于2位小于5位")
    @NotNull(message = "name不能为null")
    private String name;
    @NotNull(message = "type不能为null")
    @Max(value = 3,message = "type最大值为3")
    private Integer type;
    @NotNull(message = "parentId不能为null")
    private Integer parentId;
    @NotNull(message = "order不能为null")
    private Integer orderNum;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public Integer getParentId() {
        return parentId;
    }
    public void setParentId(Integer parentId) {
        this.parentId = parentId;
    }
    public Integer getOrderNum() {
        return orderNum;
    }
    public void setOrderNum(Integer orderNum) {
        this.orderNum = orderNum;
    }
}


既然@Valid会帮助我们检查出参数的错误并抛出异常,但是异常结果会直接返回为系统异常。我们先要在GlobalExceptionHandler类中编写他的异常返回


package com.haiexijun.mall.exception;
import com.haiexijun.mall.common.ApiRestResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.naming.Binding;
import java.util.ArrayList;
import java.util.List;
/**
 * 描述 : 用于统一处理异常的类
 */
//@ControllerAdvice的作用就是拦截异常的
@ControllerAdvice
public class GlobalExceptionHandler {
    private final Logger log= LoggerFactory.getLogger(GlobalExceptionHandler.class);
    //处理@Valid处理的异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ApiRestResponse HandleMethodArgumentNotValidException(MethodArgumentNotValidException e){
        log.error("MethodArgumentNotValidException : "+e);
        return handleBindingResult(e.getBindingResult());
    }
    private ApiRestResponse handleBindingResult(BindingResult result){
        //把异常处理为对外暴露的提示
        List<String> list=new ArrayList<String>();
        if (result.hasErrors()) {
            List<ObjectError> allErrors= result.getAllErrors();
            for (int i=0;i<allErrors.size();i++){
                ObjectError objectError=allErrors.get(i);
                String message= objectError.getDefaultMessage();
                list.add(message);
            }
        }
        if (list.size()==0){
            //参数异常
            return ApiRestResponse.error(MallExceptionEnum.REQUEST_PARAM_ERROR);
        }else {
            //@Valid的参数异常
            return ApiRestResponse.error(MallExceptionEnum.REQUEST_PARAM_ERROR.getCode(),list.toString());
        }
    }
}


这样就可以了。


相关文章
|
4天前
|
Java 应用服务中间件 Maven
Spring Boot项目打war包(idea:多种方式)
Spring Boot项目打war包(idea:多种方式)
16 1
|
3天前
|
消息中间件 Java 数据安全/隐私保护
Spring Cloud 项目中实现推送消息到 RabbitMQ 消息中间件
Spring Cloud 项目中实现推送消息到 RabbitMQ 消息中间件
|
4天前
|
Java 应用服务中间件 Spring
【JavaEE】Spring Boot - 项目的创建和使用(下)
【JavaEE】Spring Boot - 项目的创建和使用
8 0
|
4天前
|
数据可视化 Java 应用服务中间件
【JavaEE】Spring Boot - 项目的创建和使用(上)
【JavaEE】Spring Boot - 项目的创建和使用
9 0
|
4天前
|
存储 Java 对象存储
【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取
【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取
9 0
|
4天前
|
Java 关系型数据库 MySQL
【Java Spring开源项目】新蜂(NeeBee)商城项目运行、分析、总结
【Java Spring开源项目】新蜂(NeeBee)商城项目运行、分析、总结
51 4
|
4天前
|
XML Java 数据格式
Spring 项目如何使用AOP
Spring 项目如何使用AOP
25 2
|
4天前
|
Java Spring
Spring boot项目如何发送邮件
Spring boot项目如何发送邮件
20 2
|
4天前
|
Java API 数据安全/隐私保护
【亮剑】如何在Java项目中结合Spring框架实现邮件发送功能
【4月更文挑战第30天】本文介绍了如何在Java项目中结合Spring框架实现邮件发送功能。首先,需在`pom.xml`添加Spring和JavaMail依赖。然后,在`applicationContext.xml`配置邮件发送器,包括SMTP服务器信息。接着,创建一个使用依赖注入的`EmailService`类,通过`JavaMailSender`发送邮件。最后,调用`EmailService`的`sendSimpleEmail`方法即可发送邮件。最佳实践包括:使用配置管理敏感信息,利用`MimeMessage`构造复杂邮件,异常处理和日志记录,以及在大量发送时考虑使用邮件队列。
|
4天前
|
Java Maven Docker
0.07 秒启动一个 SpringBoot 项目!Spring Native 很强!!
0.07 秒启动一个 SpringBoot 项目!Spring Native 很强!!
29 2