1.问题背景
代码采用了若依springboot前后端分离开发的开源框架,在自定义异常的时候始终没有找到完美解决方案,恰巧今天看到一篇文章,验证后比较符合要求,记录一下。
2.代码详情
因为代码逻辑需要,所以在拦截器层要在token失效的情况下直接返回失效结果,
而直接进行普通的自定义异常,又都会被若依自带的异常拦截为
{
"code":500,
"msg":null
}
JwtInterceptor.java
import com.ruoyi.wx.back.ErrorCodeException;
import com.ruoyi.wx.back.ResultCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* token验证拦截器
*/
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private JwtUtil jwtUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从 http 请求头中取出 token
String token = request.getHeader("token");
// 如果不是映射到方法直接通过
if(!(handler instanceof HandlerMethod)){
return true;
}
int checkResult=jwtUtil.checkToken(token);
if(token==null || token.equals("")){
throw new ErrorCodeException(ResultCode.FAIL_SIGN_IN,
"无token,请重新登陆!");
}else if(checkResult==0){
throw new ErrorCodeException(ResultCode.FAIL_SIGN_IN,
"token失效,请重新登陆!");
}else if(checkResult==2 || checkResult==3){
throw new ErrorCodeException(ResultCode.FAIL_SIGN_IN,
"本账号登陆失效,请重新登陆!");
}
return jwtUtil.checkToken(token)==1;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
ResultCode.java
public enum ResultCode {
SUCCESS(200),//成功
FAIL(400),//失败
FAIL_SIGN_IN(401),//登录失败
TOKEN_OVERDUE(402),//token过期
NOT_FOUND(404),//接口不存在
INTERNAL_SERVICE_ERROR(500);//服务器内部错误
private final Integer code;
ResultCode(Integer code){
this.code=code;
}
private Integer code(){
return code;
}
public Integer getCode() {
return code;
}
}
ErrorCodeException.java
public class ErrorCodeException extends RuntimeException{
private Integer code;
private String message;
public ErrorCodeException(ResultCode resultCode, String msg){
this.code=resultCode.getCode();
this.message=msg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
鉴于若依框架会拦截我们写的自定义异常,因此可以采取折衷办法,利用若依自带的异常处理。
通过全局搜索Ctrl+Shift+F
查找异常代码401,然后通过401找到调用它的方法,逐步找到统一处理异常的类及规范方法。
若依自带的异常处理类路径如下(com.ruoyi.framework.web.exception.GlobalExceptionHandler
):
而我们只需要复制一份异常代码,随便改个方法名,后面直接调用即可。(我的自定义ErrorCodeException没有放在ruoyi.common
包下,也没报错,可以运行。)
GlobalExceptionHandler.java
package com.ruoyi.framework.web.exception;
/**
* 全局异常处理器
*/
@RestControllerAdvice
public class GlobalExceptionHandler{
...
/**
* 业务异常
*/
@ExceptionHandler(CustomException.class)
public AjaxResult businessException(CustomException e){
if (StringUtils.isNull(e.getCode()))
{
return AjaxResult.error(e.getMessage());
}
return AjaxResult.error(e.getCode(), e.getMessage());
}
/**
* 仿照业务异常——自定义异常抛出
*/
@ExceptionHandler(ErrorCodeException.class)
public AjaxResult UserDefinedException(ErrorCodeException e){
System.out.println("StringUtils.isNull(e.getCode()):"+StringUtils.isNull(e.getCode()));
if (StringUtils.isNull(e.getCode()))
{
return AjaxResult.error(e.getMessage());
}
return AjaxResult.error(e.getCode(), e.getMessage());
}
...
}
3.效果
完成后效果如下: