-
Session 认证和 Token 认证
-
过滤器和拦截器
-
SpringBoot统一返回和统一异常处理
上篇文章我们学习了基于
一、统一返回结果
前后端分离时代,如果没有一个统一的数据返回格式,前后端调试时,前端开发人员会骂娘的,同时约定相同的返回接口数据也有助于高效的工作。
通常统一返回的格式包含三部分:
code :状态码,一般200 表示正常message :状态码对应的描述。data :返回的数据
1.1、统一返回对象
新建一个
package com.laoxiang.utils; import com.fasterxml.jackson.annotation.JsonInclude; import java.io.Serializable; /** * @author db * @version 1.0 * @description ResponseResult * @since 2023/7/12 */ @JsonInclude(JsonInclude.Include.NON_NULL) public class ResponseResult<T> implements Serializable { private static final long serialVersionUID = 2233637474601103587L; // 接口响应状态码 private Integer code; // 接口响应信息 private String msg; // 接口响应的数据 private T data; public ResponseResult() { this.code = AppHttpCodeEnum.SUCCESS.getCode(); this.msg = AppHttpCodeEnum.SUCCESS.getMsg(); } public ResponseResult(Integer code, T data) { this.code = code; this.data = data; } public ResponseResult(Integer code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } public ResponseResult(Integer code, String msg) { this.code = code; this.msg = msg; } public static ResponseResult errorResult(int code, String msg) { ResponseResult result = new ResponseResult(); return result.error(code, msg); } public static ResponseResult okResult() { ResponseResult result = new ResponseResult(); return result; } public static ResponseResult okResult(int code, String msg) { ResponseResult result = new ResponseResult(); return result.ok(code, null, msg); } public static ResponseResult okResult(Object data) { ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getMsg()); if (data != null) { result.setData(data); } return result; } public static ResponseResult errorResult(AppHttpCodeEnum enums) { return setAppHttpCodeEnum(enums, enums.getMsg()); } public static ResponseResult errorResult(AppHttpCodeEnum enums, String msg) { return setAppHttpCodeEnum(enums, msg); } public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums) { return okResult(enums.getCode(), enums.getMsg()); } private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String msg) { return okResult(enums.getCode(), msg); } public ResponseResult<?> error(Integer code, String msg) { this.code = code; this.msg = msg; return this; } public ResponseResult<?> ok(Integer code, T data) { this.code = code; this.data = data; return this; } public ResponseResult<?> ok(Integer code, T data, String msg) { this.code = code; this.data = data; this.msg = msg; return this; } public ResponseResult<?> ok(T data) { this.data = data; return this; } 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 T getData() { return data; } public void setData(T data) { this.data = data; } }
1.2、系统常量
上面代码中提到了常量
package com.laoxiang.utils; /** * @author db * @version 1.0 * @description AppHttpCodeEnum * @since 2023/7/12 */ public enum AppHttpCodeEnum { // 成功 SUCCESS(200,"操作成功"), // 失败 ERROR(500,"操作失败"), int code; String msg; AppHttpCodeEnum(int code, String errorMessage){ this.code = code; this.msg = errorMessage; } public int getCode() { return code; } public String getMsg() { return msg; } }
1.3、web 层统一响应结果
下面的例子,可以看到在实际项目中接口返回值。
二、统一异常处理
程序开发中不可避免的会遇到异常现象,如果不进行处理,遇到异常时,开发人员不能清晰地处理问题,或者使用
有没有更好的处理方式呢?全局统一异常处理应运而生。
2.1、@ControllerAdvice 注解
@ControllerAdvice 注解:用于声明一个全局控制器Advice ,相当于把@ExceptionHandler 、@InitBinder 和@ModelAttribute 注解的方法集中到一个地方。放在特定类上,被认为是全局异常处理器。
2.2、ExceptionHandler 注解
- 用于定义异常处理方法,处理特定类型的异常。放在全局异常处理器类中的具体方法上。
通过这两个注解的配合,可以实现全局的异常处理。当控制器中抛出异常时,SpringBoot 会自动调用匹配的@ExceptionHandler 方法来处理异常,并返回定义的响应。
步骤如下:
- 新建一个统一异常处理类
- 类上标注
@RestControllerAdvice 注解 - 在方法上标注
@ExceptionHandler 注解,并且指定需要捕获的异常,可以同时捕获多个。
新建
package com.duan.execption; import com.duan.pojo.AppHttpCodeEnum; import com.duan.pojo.ResponseResult; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; /** * @author db * @version 1.0 * @description GlobalExceptionHandler * @since 2023/7/23 */ @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { // 全局异常 @ExceptionHandler(Exception.class) public ResponseResult exceptionHandler(Exception e){ //打印异常信息 log.error("出现了异常! {}",e); //从异常对象中获取提示信息封装返回 return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),e.getMessage()); } // 自定义异常 @ExceptionHandler(LxAdminException.class) public ResponseResult LxAdminExceptionHandler(LxAdminException e){ //打印异常信息 log.error("出现了异常! {}",e); //从异常对象中获取提示信息封装返回 return ResponseResult.errorResult(e.getCode(),e.getMsg()); } }
在
package com.duan.execption; import com.duan.pojo.AppHttpCodeEnum; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author db * @version 1.0 * @description LxAdminException 自定义异常 * @since 2023/7/23 */ @Data @AllArgsConstructor @NoArgsConstructor public class LxAdminException extends RuntimeException{ private int code; private String msg; public LxAdminException(AppHttpCodeEnum httpCodeEnum) { super(httpCodeEnum.getMsg()); this.code = httpCodeEnum.getCode(); this.msg = httpCodeEnum.getMsg(); } }
2.3、统一异常处理使用
在业务开发中,可以在
package com.duan.controller; import com.duan.execption.LxAdminException; import com.duan.pojo.AppHttpCodeEnum; import com.duan.pojo.ResponseResult; import com.duan.pojo.User; import com.duan.utils.JWTUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.UUID; /** * @author db * @version 1.0 * @description LoginController * @since 2023/12/19 */ @RestController @Slf4j public class LoginController { @PostMapping("/login") public ResponseResult login(@RequestBody User user){ log.info("这是正常日志"); if(!"admin".equals(user.getUsername()) && !"123456".equals(user.getPassword())){ throw new LxAdminException(AppHttpCodeEnum.LOGIN_ERROR); }else{ HashMap<String, Object> map = new HashMap<>(); map.put("id", UUID.randomUUID().toString()); // 生成token String token = JWTUtils.generateJwt(map); return ResponseResult.okResult(token); } } }
当我们请求接口时,假如用户名称或者密码错误,接口就会响应:
{ "code": 505, "msg": "用户名或密码错误", "data": null }
实际开发中还有许多的异常需要捕获,比如
代码地址:
三、总结
在
下一篇我们来看看
改变你能改变的,接受你不能改变的,关注公众号:程序员康康,一起成长,共同进步。