接着2中登录模块补充一个点:
java
//可以看到这里返回给前端控制器的是一个类而不是html页面
public RespBean doLogin(@Valid LoginVo loginVo, HttpServletRequest request,HttpServletResponse response){
return userService.doLogin(loginVo, request, response);
}
首先:在本项目中,所有的Controller类返回给前端控制器的都是ResBean对象,下面是这个类的实现,属性包括返回代码,提示信息以及一个Object类。
java
package com.example.seckilldemo.vo;
import lombok.Data;
/**
* @Author wuyifan
* @Date 2024/4/22 16:17
* @Version 1.0
*/
@Data
public class RespBean {
private long code;
private String message;
private Object object;
public static RespBean success() {
return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), null);
}
public static RespBean success(Object object) {
return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), object);
}
public static RespBean error(RespBeanEnum respBeanEnum) {
return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), null);
}
public static RespBean error(RespBeanEnum respBeanEnum, Object object) {
return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), object);
}
public RespBean(long code, String message, Object object) {
this.code = code;
this.message = message;
this.object = object;
}
public RespBean(){
}
public long getCode() {
return code;
}
public void setCode(long code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}
其中返回代码和信息是自定义一个枚举类实现的,用于优雅的处理全局异常信息,其类代码如下:
java
package com.example.seckilldemo.vo;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* @Author wuyifan
* @Date 2024/4/22 16:17
* @Version 1.0
*/
@ToString
@Getter
@AllArgsConstructor
public enum RespBeanEnum {
//通用
SUCCESS(200, "SUCCESS"),
ERROR(500, "服务端异常"),
//登录模块
LOGIN_ERROR(500210, "用户名或者密码不正确"),
MOBILE_ERROR(500211, "手机号码格式不正确"),
BIND_ERROR(500212, "参数校验异常"),
MOBILE_NOT_EXIST(500213, "手机号码不存在"),
PASSWORD_UPDATE_FAIL(500214, "更新密码失败"),
SESSION_ERROR(500215, "用户SESSION不存在"),
//秒杀模块
EMPTY_STOCK(500500, "库存不足"),
REPEATE_ERROR(500501, "该商品每人限购一件"),
REQUEST_ILLEGAL(500502, "请求非法,请重新尝试"),
ERROR_CAPTCHA(500503, "验证码错误,请重新输入"),
ACCESS_LIMIT_REACHED(500504, "访问过于频繁,请稍后重试"),
//订单模块5003xx
ORDER_NOT_EXIST(500300, "订单不存在"),
;
private final Integer code;
private final String message;
public Integer getCode() {
return code;
}
public String getMessage() {
return message;
}
}
最后:介绍本项目使用上述枚举类封装一个优雅的 Spring Boot 全局异常处理的过程。
即使用 @ControllerAdvice 和 @ExceptionHandler 处理全局异常:
- 新建异常信息实体类(即RespBean )
- 自定义异常类型。
一般我们处理的都是 RuntimeException ,所以如果你需要自定义异常类型的话直接集成这个类就可以了。
java
package com.example.seckilldemo.exception;
import com.example.seckilldemo.vo.RespBean;
import com.example.seckilldemo.vo.RespBeanEnum;
/**
* 全局异常
*
* @author: wuyifan
* @date 2024/5/2 5:32 下午
* @ClassName: GlobalException
*/
public class GlobalException extends RuntimeException {
private RespBeanEnum respBeanEnum;
public RespBeanEnum getRespBeanEnum() {
return respBeanEnum;
}
public void setRespBeanEnum(RespBeanEnum respBeanEnum) {
this.respBeanEnum = respBeanEnum;
}
public GlobalException(RespBeanEnum respBeanEnum) {
this.respBeanEnum = respBeanEnum;
}
}
- 新建异常处理类
我们只需要在类上加上@ControllerAdvice注解这个类就成为了全局异常处理类,当然你也可以通过 assignableTypes指定特定的 Controller 类,让异常处理类只处理特定类抛出的异常。
java
package com.example.seckilldemo.exception;
import com.example.seckilldemo.vo.RespBean;
import com.example.seckilldemo.vo.RespBeanEnum;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理类
*
* @author: wuyifan
* @date 2024/5/2 5:33 下午
* @ClassName: GlobalExceptionHandler
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public RespBean ExceptionHandler(Exception e) {
if (e instanceof GlobalException) {
GlobalException exception = (GlobalException) e;
return RespBean.error(exception.getRespBeanEnum());
} else if (e instanceof BindException) {
BindException bindException = (BindException) e;
RespBean respBean = RespBean.error(RespBeanEnum.BIND_ERROR);
respBean.setMessage("参数校验异常:" + bindException.getBindingResult().getAllErrors().get(0).getDefaultMessage());
return respBean;
}
// System.out.println("异常信息" + e);
return RespBean.error(RespBeanEnum.ERROR);
}
}
这样使用枚举类优雅的封装异常信息,通过自定义异常类型,最后交给全局异常类处理就可以啦啦啦啦啦!