SpringMVC(四)【SSM 整合、统一结果封装、异常处理、前后台协议联调】(2)

简介: SpringMVC(四)【SSM 整合、统一结果封装、异常处理、前后台协议联调】

SpringMVC(四)【SSM 整合、统一结果封装、异常处理、前后台协议联调】(1)https://developer.aliyun.com/article/1534216

1.5、接口测试

业务层接口测试(Junit)、表现层接口测试(Postman)

1.5.1、业务层接口测试

这里使用 Spring 整合了 Junit:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class BookServiceTest {
 
    @Autowired
    private BookService bookService;
 
    @Test
    public void testGetById(){
        Book book = bookService.getById(1);
        System.out.println(book);
    }
 
    @Test
    public void testGetAll(){
        for(Book book: bookService.getAll())
            System.out.println(book);
    }
}

测试结果:

1.6、表现层数据封装模型

       现在当前端发送请求后返回的数据格式并不一致:

       所以现在我们需要对前后端数据进行整合,统一格式。我们把前端需要接收的数据统一封装到 data 属性中;为了区分不同的操作,还会将操作类型封装到 code 属性中;对于失败的消息还会把后端希望返回的错误信息封装到一个 message(msg)属性中:

所以,以后我们要把需要所有返回给前端的结果进行统一封装,我们定义一个 Result 类:

  • 这个类名和字段可以随便增改

1.6.1、表现层与前端数据传输协议实现

       其实也就是把上一节后端返回给前端的结果类型实现一下,我们需要把这些类型写在 controller 包下,毕竟是和表现层相关的:

1.6.2、Result

package com.lyh.controller;
 
public class Result {
    private Object data; // 数据
    private Integer code;   // 状态码
    private String msg; // 消息
 
    public Result(){}
 
    public Result(Integer code,Object data) {
        this.data = data;
        this.code = code;
    }
 
    public Result(Integer code,Object data, String msg) {
        this.data = data;
        this.code = code;
        this.msg = 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;
    }
}

1.6.3、Code

状态类(编码结果为0代表失败,结果为1代表成功,越细越好):

package com.lyh.controller;
 
public class Code {
    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;
    
}

        定义好了返回给前端的类型后,我们当然要把 BookController 中所有控制器方法的返回值改为 Result 类型:

@RestController
@RequestMapping("/books")
public class BookController {
 
    @Autowired
    private BookService bookService;
 
    @PostMapping
    public Result save(@RequestBody Book book) {
        boolean flag = bookService.save(book);
        return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERR,flag);
    }
 
    @PutMapping
    public Result update(@RequestBody Book book) {
        boolean flag = bookService.update(book);
        return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERR,flag);
    }
 
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        boolean flag = bookService.delete(id);
        return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag);
    }
 
    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id) {
        Book book = bookService.getById(id);
        Integer code = book != null ? Code.GET_OK:Code.GET_ERR;
        String msg = book != null ? "":"查询失败,请重试!";
        return new Result(code,book,msg);
    }
 
    @GetMapping
    public Result getAll() {
        List<Book> books = bookService.getAll();
        Integer code = books != null ? Code.GET_OK:Code.GET_ERR;
        String msg = books != null ? "":"查询失败,请重试!";
        return new Result(code,books,msg);
    }
 
}

测试:

查询所有书籍:

查询 id=10 的书籍:

       可以看到,现在不管是查询什么内容,成功或失败,返回的结果都是 json 格式,至于返回的 Result 对象有哪些属性,这是我们后端程序员和前端需要商量的。

1.7、异常处理器

       如果我们的后端返回没有问题倒也没事,如果我们后端程序出现了异常,那么将会给前端返回一个 html 页面(404或者500等),所以我们就得处理这种不可避免的异常问题:

1.7.1、常见异常出现的位置及原因

  • 框架内部:使用不合规
  • 数据层:外部服务器故障(访问超时)
  • 业务层:业务逻辑书写错误(下标越界)
  • 表现层(和用户交互的层):数据收集、校验规则导致(不匹配的数据类型)
  • 工具类:工具类不够严谨不够健壮(连接没有及时释放)

问题1:各个层都可能会出现异常,那异常处理代码写到哪一层?

所有的异常均抛出到表现层进行处理

问题2:让表现层处理异常,每个方法都去 try-catch 代码量太大了,怎么办?

:用 AOP 思想解决。

事实是 SpringMVC 帮我们提供了异常处理器,而并不需要我们自己实现:

1.7.2、创建异常处理器

在 controller(表现层)下创建一个异常处理器类:

// 这个类必须被 SpringMVC 加载
@RestControllerAdvice
public class ProjectExceptionAdvice {
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public Result doException(IndexOutOfBoundsException e){
        System.out.println("下标越界异常"+e.getMessage());
        return new Result(666,null,"报错啦");
    }
}
  • 这里的类注解代表使用 REST 风格开发控制器的话用这种注解来进行异常处理,如果不是 REST 风格的话换成 @ControllerAdvice 即可;这里的方法注解 @ExceptionHandler 相当于声明这个方法会把捕获到的哪种异常类传进去 。
  • 这里我们返回的类型同样是 Rsult 类,毕竟是返回给前端的,不然前端得不到返回值会一直等。

测试

异常处理器添加返回值(Result类型)后:

       这样,我们的前端程序媛就可以根据返回值把异常界面做的漂亮一点。

1.7.3、项目异常处理

项目异常分类
  • 业务异常:比如程序员故意发一些错误的请求故意折腾我们的系统,或者老实人发一些不规则的数据比如 age=谢永强
  • 系统异常:比如数据库服务器宕机、服务器炸了
  • 其它异常:文件找不到(未预期到的异常)
项目异常处理方案
  1. 业务异常:发送消息给用户,让它老实点,别瞎弄
  2. 系统异常:安抚用户,然后赶紧告诉运维人员,并记录日志
  3. 其它异常:安抚用户,然后开发人员,并记录日志

SpringMVC(四)【SSM 整合、统一结果封装、异常处理、前后台协议联调】(3)https://developer.aliyun.com/article/1534220

相关文章
|
6月前
|
缓存 NoSQL Java
在 SSM 架构(Spring + SpringMVC + MyBatis)中,可以通过 Spring 的注解式缓存来实现 Redis 缓存功能
【6月更文挑战第18天】在SSM(Spring+SpringMVC+MyBatis)中集成Redis缓存,涉及以下步骤:添加Spring Boot的`spring-boot-starter-data-redis`依赖;配置Redis连接池(如JedisPoolConfig)和连接工厂;在Service层使用`@Cacheable`注解标记缓存方法,指定缓存名和键生成策略;最后,在主配置类启用缓存注解。通过这些步骤,可以利用Spring的注解实现Redis缓存。
83 2
|
6月前
|
前端开发
SpringMVC(四)【SSM 整合、统一结果封装、异常处理、前后台协议联调】(3)
SpringMVC(四)【SSM 整合、统一结果封装、异常处理、前后台协议联调】
|
7月前
|
设计模式 前端开发 JavaScript
Spring MVC(一)【什么是Spring MVC】
Spring MVC(一)【什么是Spring MVC】
|
6月前
|
设计模式 前端开发 Java
【Spring MVC】快速学习使用Spring MVC的注解及三层架构
【Spring MVC】快速学习使用Spring MVC的注解及三层架构
95 1
|
6月前
|
前端开发 Java 应用服务中间件
Spring框架第六章(SpringMVC概括及基于JDK21与Tomcat10创建SpringMVC程序)
Spring框架第六章(SpringMVC概括及基于JDK21与Tomcat10创建SpringMVC程序)
|
7月前
|
前端开发 Java 关系型数据库
基于ssm框架旅游网旅游社交平台前后台管理系统(spring+springmvc+mybatis+maven+tomcat+html)
基于ssm框架旅游网旅游社交平台前后台管理系统(spring+springmvc+mybatis+maven+tomcat+html)
|
6月前
|
XML Java 数据格式
SpringMVC的XML配置解析-spring18
SpringMVC的XML配置解析-spring18
|
6月前
|
应用服务中间件
从代码角度戳一下springMVC的运行过程-spring16
从代码角度戳一下springMVC的运行过程-spring16
|
前端开发 Java Go
Spring MVC 和 Spring Boot 的区别
Spring MVC 和 Spring Boot 的区别
232 0
|
7月前
|
移动开发 Java 测试技术
Spring MVC+Spring+Mybatis实现支付宝支付功能(附完整代码)
Spring MVC+Spring+Mybatis实现支付宝支付功能(附完整代码)
187 1