springboot项目记录2用户注册功能


七、注册-业务层

7.1规划异常

7.1.1用户在进行注册的时候,可能会产生用户名被占用的错误,抛出一个异常;

RuntimeException异常,作为该异常的子类,然后再去定义具体的异常类型继承这个异常。

写一个业务层异常的基类,ServiceException异常,这个异常继承RuntimeException异常。

package com.example.store.service.ex;

/**
 * @Description:业务层异常的基类 throws new ServiceException("业务层产生未知的异常")
 * @Author:
 * @Date:
 */
public class ServiceException extends RuntimeException{
    public ServiceException() {
        super();
    }

    public ServiceException(String message) {
        super(message);
    }

    public ServiceException(String message, Throwable cause) {
         super(message, cause);
    }

    public ServiceException(Throwable cause) {
        super(cause);
    }

    protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

根据业务层不同的功能来详细定义具体的异常类型,统一的去继承ServiceException异常类。

7.1.2用户在注册的时候可能会产生用户名被占用的错误,抛出一个异常:UsernameDuplicatedException异常

public class UsernameDuplicatedException extends ServiceException{
    public UsernameDuplicatedException() {
        super();
    }

    public UsernameDuplicatedException(String message) {
        super(message);
    }

    public UsernameDuplicatedException(String message, Throwable cause) {
        super(message, cause);
    }

    public UsernameDuplicatedException(Throwable cause) {
        super(cause);
    }

    protected UsernameDuplicatedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

7.1.3正在执行数据插入操作的时候,服务器、数据库宕机。处于正在执行插入操作过程中所产生的异常:

InsertException异常。

public class InsertException extends ServiceException {
    public InsertException() {
        super();
    }

    public InsertException(String message) {
        super(message);
    }

    public InsertException(String message, Throwable cause) {
        super(message, cause);
    }

    public InsertException(Throwable cause) {
        super(cause);
    }

    protected InsertException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

7.2设计接口和抽象方法

7.2.1在service包下创建一个IUserService

/**用户模块业务层接口**/
public interface IUserService {
    /**
     *用户注册方法
     * @param user用户的数据对象
     */
    void reg(User user);
}

7.2.2创建一个实现类UserServiceImpl类,需要实现这个接口,并且实现抽象方法。

7.2.3在单元测试包下创建一个UserServiceTests类,在这个类中添加单元测试的功能。

八、注册-控制层

8.1创建响应

状态码,状态描述信息,数据。这部分功能封装在一个类中,将这个类作为方法返回值,返回给前端浏览器。

/**
 * @Description:Json格式的数据进行响应
 * @Author:
 * @Date:
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JsonResult implements Serializable {//Serializable接口
    /**状态码*/
    private Integer state;
    /**描述信息*/
    private String message;
    /**泛型数据*/
    private E data;
}

8.2 设计请求

依据当前的业务功能模块进行请求的设计。
请求路径:/user/reg
请求参数:user user
请求类型:POST(有敏感数据就用POST,没有就用get)
响应结果:JsonResult

8.3处理请求

8.3.1创建一个控制层对应的类UserController类。依赖于业务层的接口。

package com.example.store.controller;
import org.springframework.stereotype.Controller;
import com.example.store.entity.User;
import com.example.store.service.IUserService;
import com.example.store.service.ex.InsertException;
import com.example.store.service.ex.UsernameDuplicatedException;
import com.example.store.util.JsonResult;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
 * @Description:
 * @Author:
 * @Date:
 */
//@Controller //当前类交给Spring来管理、
@RestController//等效于@Controller+@ResponseBody
@RequestMapping("/users")
public class UserController {
    @Autowired
    private IUserService userService;//依赖于业务层的接口,即userService接口,然后交给Spring自动装配,最后什么样的请求被拦截在子类当中呢。

    @RequestMapping("/reg")
    //@ResponseBody //表示此方法的响应结果以json格式进行数据的响应给到前端
    //如果在这个类中编写了大量的请求处理方法,也就意味着每个类中都要编写一个ResponseBody,是很麻烦的,所以并不建议这样写,这里写组合注解
    public JsonResult reg(User user){ //声明一个User对象,作为方法的参数列表,来接收前端的数据
        //创建响应结果对象
        JsonResult result = new JsonResult<>();
        try {
            userService.reg(user);//在调这个方法的时候,如果抛异常,在Code里面点Surround With 的try/catch
            result.setState(200);
            result.setMessage("用户名注册成功");
        } catch (UsernameDuplicatedException e) { //抛的异常即我们在业务层所定义的异常,这里是两个
            result.setState(4000);
            result.setMessage("用户名被占用");
        }
        catch (InsertException e) { //抛的异常即我们在业务层所定义的异常,这里是两个
            result.setState(5000);
            result.setMessage("注册时产生未知的异常");
        }
        return result;
    }
}

8.4 控制层优化设计

在控制层抽离一个父类,在这个父类中统一的去处理关于异常的相关操作。编写一个BaseController类,统一处理异常。

重新构建了reg()方法。

package com.example.store.controller;
import org.springframework.stereotype.Controller;
import com.example.store.entity.User;
import com.example.store.service.IUserService;
import com.example.store.service.ex.InsertException;
import com.example.store.service.ex.UsernameDuplicatedException;
import com.example.store.util.JsonResult;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
 * @Description:
 * @Author:
 * @Date:
 */
//@Controller //当前类交给Spring来管理、
@RestController//等效于@Controller+@ResponseBody
@RequestMapping("/users")
public class UserController extends BaseController{
    @Autowired
    private IUserService userService;//依赖于业务层的接口,即userService接口,然后交给Spring自动装配,最后什么样的请求被拦截在子类当中呢。
    @RequestMapping("/reg")
    //@ResponseBody //表示此方法的响应结果以json格式进行数据的响应给到前端
    //如果在这个类中编写了大量的请求处理方法,也就意味着每个类中都要编写一个ResponseBody,是很麻烦的,所以并不建议这样写,这里写组合注解
    public JsonResult reg(User user){ //声明一个User对象,作为方法的参数列表,来接收前端的数据
        userService.reg(user);
        return new JsonResult<>(OK);
    }

??此为UserController类

??此为BaseController类

package com.example.store.controller;

import com.example.store.service.ex.InsertException;
import com.example.store.service.ex.ServiceException;
import com.example.store.service.ex.UsernameDuplicatedException;
import com.example.store.util.JsonResult;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * @Description:控制层的基类
 * @Author:
 * @Date:
 */
public class BaseController {
    /**操作成功的状态码**/
    public static final int OK =200;
    //请求处理方法,这个方法的返回值就是需要传递给全端的数据
    //自动将异常对象传递给此方法的参数列表上
    //当前项目中产生了异常,被统一拦截到此方法中,这个方法此时就充当的是请求处理方法,方法的返回值直接给到前端
    @ExceptionHandler(ServiceException.class)//用于统一处理抛出的异常
    public JsonResult handleException(Throwable e){
        JsonResult result = new JsonResult<>(e);
        if(e instanceof UsernameDuplicatedException){
            result.setState(400);
            result.setMessage("用户名已经被占用");
        } else if(e instanceof InsertException){
            result.setState(5000);
            result.setMessage("注册时产生了未知的异常");
        }
        return result;
    }
}