异常捕获
异常处理逻辑集中管理,易于维护和扩展,这边我的项目是用于jwt验证token时使用
-
项目结构
自定义异常类
-
用来表示jwt验证失败的情况,包含一个状态码和消息,这样就可以在捕获异常时使用这些信息
package com.example.englishhub.exception; /** * @Author: hahaha * @Date: 2024/4/11 14:09 */ public class JwtValidationException extends RuntimeException { private final String statusCode; public JwtValidationException(String statusCode, String message) { super(message); this.statusCode = statusCode; } public String getStatusCode() { return statusCode; } }
全局异常处理器
-
添加对
JwtValidationException
的处理逻辑,使用@ControllerAdvice
注解package com.example.englishhub.config; import com.example.englishhub.exception.JwtValidationException; import com.example.englishhub.utils.Result; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; /** * @Author: hahaha * @Date: 2024/4/11 14:10 */ // 全局异常处理 @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(JwtValidationException.class) public ResponseEntity<Result<String>> handleJwtValidationException(JwtValidationException ex) { Result<String> result = new Result<>(); result.setStatusCode(ex.getStatusCode()); result.setMessage(ex.getMessage()); return new ResponseEntity<>(result, HttpStatus.valueOf(Integer.parseInt(ex.getStatusCode()))); } }
添加拦截器
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object o) {
System.out.println("进入拦截器");
if ("OPTIONS".equals(req.getMethod())) {
return true;
}
// resp.setCharacterEncoding("utf-8");
// String token = req.getHeader("token");
String token = req.getHeader("token");
// JwtUtil.validateToken 方法内部会抛出自定义的 JwtValidationException 异常
String id = JwtUtil.validateToken(token);
// 认证成功
resp.setContentType("application/json; charset=utf-8");
System.out.println("认证成功:用户 " + id + " 访问资源");
return true;
}
}
跨域配置
// 跨域配置
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
@Override
public void addInterceptors(InterceptorRegistry reg) {
reg.addInterceptor(new AuthInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(excludePattern());
}
public List<String> excludePattern(){
List<String> ret = new ArrayList<String>();
ret.add("/user/**");
ret.add("/swagger-ui.html#/**");
ret.add("/**");
// , \"/webjars/**\", \"/v2/**\", \"/swagger-ui.html/**"
return ret;
}
}
修改jwt工具类中的逻辑
-
使其在验证失败时抛出上面定义的
JwtValidationException
异常。/** * 校验jwtToken * * @param token * @return */ // 优化验证逻辑 public static String validateToken(String token) { // 使用自定义异常 if (StringUtils.isBlank(token)) { throw new JwtValidationException(ResultType.UNAUTHORIZED.getCode(), "Token为空"); } try { Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody(); return claims.get(USER_ID, String.class); } catch (ExpiredJwtException e) { throw new JwtValidationException(ResultType.AGAIN_LOGIN.getCode(), "Token已过期,请重新登录"); } catch (JwtException e) { throw new JwtValidationException(ResultType.UNAUTHORIZED.getCode(), "无效的Token"); } }
测试
-
controller层编写验证token函数
/** * 验证Token */ @Operation(summary = "验证Token") @GetMapping("/validate") public Result validate() { Result result = new Result(); String token = request.getHeader("token"); System.out.println("token" + token); JwtUtil.validateToken(token); result.success("Token有效"); return result; }
-
postman发请求测试
后续也可以自定义其他异常类,在controller层其他方法抛出即可。
result.success(“Token有效”);
return result;
}
- postman发请求测试
[外链图片转存中...(img-jzNoq2Ac-1713494114064)]
后续也可以自定义其他异常类,在controller层其他方法抛出即可。