SpringMVC——表现层数据封装、异常处理器

发布于:2025-03-18 ⋅ 阅读:(20) ⋅ 点赞:(0)

目录

数据封装协议

为什么要进行数据封装

 实现数据封装

测试

异常处理器

实现异常处理器 

项目异常处理

实现处理不同的异常


数据封装协议

为什么要进行数据封装

当接口响应格式不一致时:

  1. 前端需要为不同接口编写多种解析逻辑

  2. 错误处理逻辑难以统一

  3. 接口文档维护成本增加

  4. 客户端难以快速判断请求结果


 那如何进行数据封装?

   前端接收数据格式——创建模型类,封装数据到data属性中、封装特殊消息到message中、封装操作结果到code中。

code:标识状态码

  •     告知客户请求处理的结果(成功/失败/异常)
  •     通过编码快速定位问题类型(参数错误、权限不足、系统异常)
  •     程序化处理:便于客户端编写统一的状态处理逻辑(根据code跳转页面或弹窗)

设计规范

状态码范围 典型示例 适用场景
2XX 200 业务成功
4XX 400 客户端错误
5XX 500 服务端错误
自定义业务码 10011 具体的业务错误

 msg:状态描述信息   

  •     可读提示:给开发者或用户展示友好提示信息

  •     问题定位辅助:配合 code 提供具体错误描述

  •     动态信息传递:支持参数化消息(如"用户 {userId} 不存在"

data:业务数据载体

  •     响应主体:承载接口实际返回的业务数据

  •     结构统一:保证不同接口的数据结构一致性

  •     空值处理:无数据时返回 null 或空对象({}/[]

 根据上面的原则就可以设置同一数据返回结果类:

public class Result {
    private Object data;
    private Integer code;
    private String msg;
}

    可以根据需要自行增减,提供方法方便操作。

 实现数据封装

    在controller包下面新建Result类,添加属性code、msg、data,加上对应的set和get方法,以及根据需求写出对应的构造方法:

public class Result {
    private Object data;
    private Integer code;
    private String msg;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Result(Integer code, Object data, String msg) {
        this.data = data;
        this.code = code;
        this.msg = msg;
    }
    public Result( Integer code,Object data) {    //先码值再数据
        this.data = data;
        this.code = code;
    }

    public Result() {
    }
}

接下类设置状态码类:

同样是在contorller包下,新建code包:

public class Code {
    //1表示成功、0表示失败
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;

    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;

}

 这两项完成后,开始改变之前写的控制类:

@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping
    public Result save(@RequestBody User user) {
        boolean flag = userService.save(user);
        return new Result(flag?Code.SAVE_OK:Code.SAVE_ERR,flag);
    }

    @PutMapping
    public Result update(@RequestBody User user) {
        boolean flag = userService.update(user);
        return new Result(flag?Code.UPDATE_OK:Code.UPDATE_ERR,flag);
    }

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        boolean flag = userService.delete(id);
        return new Result(flag?Code.DELETE_OK:Code.DELETE_ERR,flag);
    }

    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id) {
        User user = userService.getById(id);
        Integer code = user != null ? Code.GET_OK : Code.GET_ERR;
        String msg = user != null ? "" : "数据查询失败";
        return new Result(code,user,msg);

    }

    @GetMapping
    public Result getAll() {

        List<User> users = userService.getAll();
        Integer code = users != null ? Code.GET_OK : Code.GET_ERR;
        String msg = users != null ? "" : "数据查询失败";
        return new Result(code,users,msg);

    }
}

和以前的代码对比:

测试

新增测试:

查询单个 

 

异常处理器

     在程序开发中,难免会出现异常情况:

    

    通常要根据异常现象的常见位置与诱因来处理。

常见的异常位置有:

  • 框架内部抛出的异常:因使用不合规导致
  • 数据层抛出的异常:因外部服务器故障导致(服务器访问超时)
  • 业务层抛出的异常:因业务逻辑书写错误导致(索引异常)
  • 表现层抛出的异常:因数据收集、校验等规则导致(不匹配的数据类型间接导致异常)
  • 工具类抛出的异常:因工具类书写不严谨不够健壮导致(必要释放的连接长期未释放)

SpringMVC提供了快速处理这些异常的方法,就是异常处理器。

实现异常处理器 

异常处理器就是集中,统一的处理项目中的异常。

    @RestControllerAdvice是Spring框架中的一个注解,该类中可以定义多个方法来处理不同类型的异常。这些方法使用@ExceptionHandler注解来指定要处理的异常类型。当控制器中抛出异常时,Spring会根据异常的类型调用相应的异常处理方法,将异常信息以RESTful的方式返回给客户端。

    异常处理器写在控制层,当出现异常时就会被拦截:

@RestControllerAdvice  //声明这个类用于异常处理
public class ProjectExceptionAdvice {

    @ExceptionHandler(Exception.class)  //拦截Exception异常
    public Result deException(Exception exception){
        System.out.println("拦截异常...");
        return new Result(666,null);
    }
}

    先写一个错误在查询所有的请求中,然后运行,发送请求:

 

项目异常处理

项目异常分类

业务异常

  • 规范用户行为产生的异常
  • 不规范用户行为操作产生的异常

系统异常

  • 项目运行过程中可预计且无法避免的异常

其他异常

  • 编程人员为预期到的异常

项目异常处理方案

业务异常

  • 发送对应消息传递给用户,提醒规范操作

系统异常

  • 发送固定信息传递给用户,安抚用户
  • 发送特定信息给运维人员,提醒维护 
  • 记录日志

其他异常

  • 发送固定信息传递给用户,安抚用户
  • 发送特定信息给编程人员,提醒维护
  •  记录日志

 

实现处理不同的异常

  • 创建exception包
  • 新建分别用于处理系统异常和业务异常类 
//继承RuntimeException,可以出现异常不处理向上抛
//系统异常
public class SystemException extends RuntimeException {
    private Integer code;  //帮助识别是哪种异常

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public SystemException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public SystemException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

}
//业务异常
public class BusinessException extends RuntimeException {
    private Integer code;  //帮助识别是哪种异常

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public BusinessException(Integer code,String message, Throwable cause ) {
        super(message, cause);
        this.code = code;
    }
    public BusinessException(Integer code,String message ) {
        super(message);
        this.code = code;
    }

}

回到异常处理器,对不同的异常分别进行处理:

@RestControllerAdvice  //声明这个类用于异常处理
public class ProjectExceptionAdvice {

    @ExceptionHandler(Exception.class)  //拦截Exception异常
    public Result deException(Exception exception){
        //记录日志
        //发送消息到运维
        //发送消息给开发人员
        System.out.println("拦截异常...");
        return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙请稍后再试");
    }

    //拦截到系统异常
    @ExceptionHandler(SystemException.class)
    public Result deSystemException(SystemException exception){
        //记录日志
        //发送消息到运维
        //发送消息给开发人员
        return new Result(exception.getCode(),exception.getMessage());
    }

    //处理业务异常
    @ExceptionHandler(BusinessException.class)
    public Result deBusinessException(BusinessException exception){
        return new Result(exception.getCode(),exception.getMessage());
    }
}