1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > springBoot 在过滤器中如何捕获抛出的异常并自定义返回信息

springBoot 在过滤器中如何捕获抛出的异常并自定义返回信息

时间:2023-08-13 16:04:36

相关推荐

springBoot 在过滤器中如何捕获抛出的异常并自定义返回信息

一般springBoot自带的全局异常捕获机制都是在业务层发生的异常来进行捕获的,因为过滤器的执行顺序是在全局异常机制启动之前执行的,所以一旦过滤器中发生异常,全局异常捕获机制无法使用

现在有一个围魏救赵的思路

在过滤器中try-catch掉需要捕获的异常,然后转发到controller在重新抛出,这样全局异常机制可以起作用,返回自定义信息

举个例子:

SpringSecurity使用过滤器链来实现用户校验,一旦签名出错,过滤器链中抛出响应的异常,我们不想抛出异常,而是返回相关错误信息。此时使用上述思路很容易做到

下面是真实代码:

这是一个过滤器,我们try-catch掉异常,然后转发给相应的controller

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {private static final String LOGIN_URL = "/login";private static String token = null;public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {super(authenticationManager);}@Overrideprotected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain chain) throws IOException, ServletException {String tokenHeader = request.getHeader(TokenEnum.TOKEN_HEADER.getValue());// 如果请求头中没有Authorization信息或者是登录接口直接放行了if (tokenHeader == null || !tokenHeader.startsWith(TokenEnum.TOKEN_PREFIX.getValue()) || request.getRequestURL().toString().contains(LOGIN_URL)) {chain.doFilter(request, response);return;}// 如果请求头中有token,则进行解析,并且设置认证信息try {if (JWTAuthorizationFilter.token != null) {refreshToken(token);SecurityContextHolder.getContext().setAuthentication(getAuthentication(token));} else {refreshToken(tokenHeader);SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));}} catch (RefreshTokenException | ExpiredJwtException e) {// 异常捕获,发送到expiredJwtExceptionrequest.setAttribute("expiredJwtException", e);//将异常分发到/expiredJwtException控制器request.getRequestDispatcher("/expiredJwtException").forward(request, response);} catch (AccessDeniedException | SignatureException e) {// 异常捕获,发送到signatureExceptionrequest.setAttribute("signatureException", e);//将异常分发到/signatureException控制器request.getRequestDispatcher("/signatureException").forward(request, response);}super.doFilterInternal(request, response, chain);}

异常controller

package com.hongseng.app.controller;import com.hongseng.app.config.exception.RefreshTokenException;import io.jsonwebtoken.ExpiredJwtException;import io.jsonwebtoken.security.SignatureException;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;/*** @program: fire_control* @description:* @author: fbl* @create: -01-18 07:54**/@RestControllerpublic class JwtExceptionController {/*** 重新抛出异常*/@RequestMapping("/expiredJwtException")public void expiredJwtException(HttpServletRequest request) throws ExpiredJwtException, RefreshTokenException {if (request.getAttribute("expiredJwtException") instanceof ExpiredJwtException) {throw ((ExpiredJwtException) request.getAttribute("expiredJwtException"));} else {throw new RefreshTokenException();}}@RequestMapping("/signatureException")public void signatureException(HttpServletRequest request) throws SignatureException {throw ((SignatureException) request.getAttribute("signatureException"));}}

然后在使用全局异常机制捕获并返回自定义信息即可

package com.hongseng.app.config.exception;import enums.ErrorCodeEnum;import io.jsonwebtoken.ExpiredJwtException;import io.jsonwebtoken.security.SignatureException;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import result.Result;/*** @program: fire_control* @description: 处理自定义的业务异常* @author: fbl* @create: -01-15 16:21**/@ControllerAdvicepublic class GlobalExceptionHandler {/*** token过期** @return*/@ExceptionHandler(value = {ExpiredJwtException.class, RefreshTokenException.class})@ResponseBodypublic Result expiredJwtException() {return Result.failure(ErrorCodeEnum.SYS_ERR_TOKEN_EXPIRED);}/*** token错误** @return*/@ExceptionHandler(value = SignatureException.class)@ResponseBodypublic Result signatureException() {return Result.failure(ErrorCodeEnum.SYS_ERR_TOKEN_SIGNATURE);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。