网站开发外包售后维护合同,ae模板下载网站推荐,工作英语,高德vr全景地图统一响应结果和全局异常处理 前言统一响应结果定义响应结构定义响应对象定义响应状态对象统一返回响应对象定义 Controller 拦截类 全局异常处理 前言 做个功能之前我们想一下为什么要做统一响应结果和全局异常处理呢#xff1f; 这是因为我们的项目采用的是前后端分离开发 这是因为我们的项目采用的是前后端分离开发并且使用 Restful 风格的接口形式返回的业务数据以及异常都是以 JSON 的格式返回但是目前我们返回的数据格式都是不一致的比如如下的代码
GetMapping(/{id})
Operation(summary 根据用户ID查询用户)
public UserEntity get(PathVariable Long id) {return userService.get(id);
}GetMapping(/list)
Operation(summary 查询全部)
public ListUserEntity lists() {return userService.lists();
}GetMapping(/page)
Operation(summary 分页查询)
public PageUserEntity page(int page, int size) {return userService.page(PageRequest.of(page - 1, size));
}PostMapping
Operation(summary 新增用户)
public void save(RequestBody UserEntity user) {userService.save(user);
}由上面的接口返回值可以看出我们4个接口就有4中返回数据格式这时前端工作人员在对接的时候就接口她们就会很难受需要写很多的处理来处理不同的返回数据非常的不方便而且我们自己使用起来也不好管理所以在实际开发中为了降低开发人员之间的沟通成本一般返回结果会定义成一个统一格式具体的格式根据实际开发业务不同有所区别。
统一响应结果
定义响应结构
从前端的角度思考调用后端接口后如果成功了则拿到想要的数据或者对应的信息提示如果不成功也应该有相应的信息提示。从这个角度出发我们将响应结果设计为 code响应状态码根据状态码判断是否成功 message提示信息根据调用的接口自定义 body返回的数据 响应的结构如下
{code: 200,message: 成功,body: [{createUser: admin,updateUser: admin,createTime: 2023-12-09 14:14:20,updateTime: 2023-12-09 14:14:20,id: 2,name: 金克斯,nickname: 爆爆,age: 18,email: null,password: 666}]
}定义响应对象
Spring 官方源码里面也有一个类似的对象类名为 ResponseEntity如果你想直接用这个类也行的但是这个类我使用起来有点不合我的习惯所以还是自定义一个好点。
Data
public class ResponseT implements Serializable {Schema(description 响应状态)private Integer code;Schema(description 响应信息)private String message;Schema(description 响应数据)private T body;/*** 私有化构造函数*/private Response() {}/*** 构建 ResponseT 对象** param body 响应数据* param code 响应状态对象*/public static T ResponseT build(Nullable T body, ResponseCode code) {return build(body, code.getCode(), code.getMessage());}/*** 构建 ResponseT 对象** param body 响应数据* param code 响应状态* param message 响应信息*/public static T ResponseT build(Nullable T body, Integer code, String message) {ResponseT response new Response();response.setCode(code);response.setMessage(message);response.setBody(body);return response;}/*** 请求成功返回不带数据*/public static T ResponseT ok() {return build(null, ResponseCode.OK);}/*** 请求成功返回带数据*/public static T ResponseT ok(T body) {return build(body, ResponseCode.OK);}/*** 请求失败返回500*/public static T ResponseT error() {return build(null, ResponseCode.ERROR);}/*** 请求失败状态码*/public static T ResponseT error(ResponseCode code) {return build(null, code);}/*** 自定义请求失败信息*/public static T ResponseT error(Integer code, String message) {return build(null, code, message);}}定义响应状态对象
public enum ResponseCode {/*** 成功*/OK(200, OK),/*** 失败*/ERROR(500,系统异常请稍后重试);private final int code;private final String message;ResponseCode(int code, String message) {this.code code;this.message message;}public int getCode() {return code;}public String getMessage() {return message;}
}统一返回响应对象
这里有两种方式可以做到全局返回我们定义好的 Response 对象第一种就是在定义方法的时候返回值都定义为 Resopnse 对象这是可以完成的但是我们还有更高级一点的用法使用 Spring ResponseBodyAdvice类即可ResponseBodyAdvice的作用就是拦截Controller方法的返回值统一处理返回值/响应体一般用来统一返回格式加解密签名等等。
我们这里采用第二种方式来完成统一响应结果。
定义 Controller 拦截类
RestControllerAdvice(basePackages {com.xm.module})
public class ResponseAdviceHandler implements ResponseBodyAdviceObject {Overridepublic boolean supports(MethodParameter returnType, Class? extends HttpMessageConverter? converterType) {// 响应都需要被拦截return true;}Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class? extends HttpMessageConverter? selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {if (body instanceof String) {// String 类型不能封装成 Response 返回return JSONUtil.toJsonStr(Response.ok(body));} else if (body instanceof Response) {// 如果是 Response 就直接返回了return body;} else {// 统一响应对象return Response.ok(body);}}
}RestControllerAdvice是 RestController注解的增强可以实现三个方面的功能 全局异常处理全局数据绑定全局数据预处理 basePackages 表示是只拦截 com.xm.module 下的响应 JSONUtil.toJsonStr(Response.ok(body));这个 JSONUtil 我是用的 hutool 工具包里面的好用滴很。有需要的自己导入。Hutool 官网 启动程序测试一下 这里报了一个异常而且我们发现异常信息的响应结果和我们预想的不一致这个我们在下面全局异常拦截的时候在进行处理先把这个接口异常给解决一下。
异常的大致意思是不能初始化代理没有 session这是因为我们使用了懒加载的方法修改一下这个接口方法。
Override
public UserEntity get(Long id) {return userRepository.findById(id).orElse(null);
}ok接口请求成功并且响应的结构和我们预想的一致nice。
全局异常处理
刚才我们看到在接口抛出异常的时候我们的响应结构和我们预想的不一致我们希望在抛出异常的时候也能返回我们的 Response 对象怎么实现呢还是老办法上面我们提到了 RestControllerAdvice是 RestController注解的增强可以实现全局异常处理那我们就在使用这个注解进行全局异常的拦截处理吧。
RestControllerAdvice
public class GlobalExceptionHandler {/*** 全局异常处理。* ExceptionHandler(Exception.class) 表示拦截 Exception 异常这是所有异常都拦截* 我们还可以配置 ExceptionHandler(XXException.class) 等等进行更加精细的拦截操作** param e 异常* return Response*/ExceptionHandler(Exception.class)public ResponseString exception(Exception e) {return Response.error(ResponseCode.ERROR);}}编写好了这个之后我们再来测试一下异常的情况下返回值是什么样的 ok异常拦截成功关于更多的异常可以自己定义拦截即可本节内容就到这里了bye~