exception
bizException.java
package com.shrimpking.exception;
import com.shrimpking.enums.CodeEnum;
import lombok.Data;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/4 21:58
* 自定义异常
*/
@Data
public class BizException extends RuntimeException
{
/**
* 状态码
*/
private Integer code;
public BizException(String msg){
super(msg);
}
public BizException(CodeEnum codeEnum){
super(codeEnum.getMsg());
this.code = codeEnum.getCode();
}
}
interceptor
authorizationInterceptor.java
package com.shrimpking.interceptor;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.shrimpking.constants.MyConstants;
import com.shrimpking.context.UserContext;
import com.shrimpking.dto.UserDTO;
import com.shrimpking.enums.CodeEnum;
import com.shrimpking.res.Result;
import com.shrimpking.util.JwtUtils;
import com.shrimpking.util.ResponseUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/4 22:20
* 认证校验 拦截器
*
*/
@Slf4j
public class AuthorizationInterceptor implements HandlerInterceptor
{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
//日志
log.info("请求路径:{}",request.getServletPath());
/*
axios对非简单请求(比如:application/json)有时会
通过options请求来判断服务器是否支持跨域
*/
String method = request.getMethod();
if(HttpMethod.OPTIONS.matches(method)){
//去执行剩余的filter
return true;
}
//获取token
String token = request.getHeader(HttpHeaders.AUTHORIZATION);
if(StringUtils.isBlank(token)){
//头部为空时,从请求参数获取token
token = request.getParameter(MyConstants.USER_TOKEN_KEY);
if(StringUtils.isBlank(token)){
//未登录,失败
ResponseUtils.respAppJson(response,Result.failure(CodeEnum.AUTH_ERROR));
return false;
}
}
//校验token
Result<DecodedJWT> verifyResult = JwtUtils.verifyToken(token);
//校验失败,不通过
if(verifyResult.isFailed()){
ResponseUtils.respAppJson(response,Result.failure(CodeEnum.AUTH_ERROR));
return false;
}
//解析,获取放入的对象
UserDTO userDTO = JwtUtils.parse(verifyResult.getData(),UserDTO.class);
//解析失败
if(userDTO == null){
ResponseUtils.respAppJson(response,Result.failure(CodeEnum.AUTH_ERROR));
return false;
}
//放入threadLocal中,在线程的任何地方可以获取到,使用
UserContext.set(userDTO);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
{
//线程中移除
UserContext.remove();
}
}
exceptionAdvice.java
package com.shrimpking.interceptor;
import com.shrimpking.enums.CodeEnum;
import com.shrimpking.exception.BizException;
import com.shrimpking.res.Result;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/4 21:12
* 异常统一处理类
*/
@RestControllerAdvice
public class ExceptionAdvice
{
/**
* 处理参数校验不通过的异常
* 提交类型是application/json的 + 后台使用RequestBody接收的情况
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<String> handleException(MethodArgumentNotValidException e){
//获取绑定的错误结果
BindingResult bindingResult = e.getBindingResult();
//获取到校验失败的字段的详情
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
String errorMsg = spliceErrorMsg(fieldErrors);
return Result.failure(errorMsg);
}
/**
*处理绑定异常的
* 表单提交时的,application/x-www-form-urlencoded
* @param e
* @return
*/
@ExceptionHandler(BindException.class)
public Result<String> handleException(BindException e){
//获取绑定的错误结果
BindingResult bindingResult = e.getBindingResult();
//获取到校验失败的字段的详情
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
String errorMsg = spliceErrorMsg(fieldErrors);
return Result.failure(errorMsg);
}
/**
* 处理非法参数的异常
*
* @param e
* @return
*/
@ExceptionHandler(IllegalArgumentException.class)
public Result<String> handleException(IllegalArgumentException e){
System.out.println(e.getMessage());
return Result.failure(CodeEnum.PARAM_ERROR);
}
/**
* 处理数据库的异常
*
* @param e
* @return
*/
@ExceptionHandler(BadSqlGrammarException.class)
public Result<String> handleException(BadSqlGrammarException e){
System.out.println(e.getMessage());
return Result.failure(CodeEnum.DB_ERROR);
}
/**
* 处理唯一约束的异常
*
* @param e
* @return
*/
@ExceptionHandler(DuplicateKeyException.class)
public Result<String> handleException(DuplicateKeyException e){
System.out.println(e.getMessage());
return Result.failure(CodeEnum.DUPLICATE_KEY_ERROR);
}
/**
* 处理业务异常
*
* @param e
* @return
*/
@ExceptionHandler(BizException.class)
public Result<String> handleException(BizException e){
System.out.println(e.getMessage());
return Result.failure(e.getCode(),e.getMessage());
}
/**
* 处理其他异常
*
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public Result<String> handleException(Exception e){
System.out.println(e.getMessage());
return Result.failure(CodeEnum.OTHER_ERROR);
}
/**
* 抽取为方法
* @param fieldErrors
* @return
*/
private String spliceErrorMsg(List<FieldError> fieldErrors){
//循环列表,获取错误原因
String errorMsg = fieldErrors.stream().map(field ->{
//
StringBuilder builder = new StringBuilder();
//
builder.append("属性:").append(field.getField())
.append(",传递的值:").append(field.getRejectedValue())
.append(",校验不通过的原因:").append(field.getDefaultMessage());
return builder.toString();
//多个字段属性使用分号隔开
}).collect(Collectors.joining(";"));
return errorMsg;
}
}