SpringBoot - 过滤异常处理程序

时间:2017-05-16 11:12:17

标签: spring spring-boot spring-filter

我有一个 spring-boot 应用程序。我有一个ControllerAdvice类来处理应用程序抛出的异常。

我创建了一个filter,我想用它来验证我所有请求的标头。当我从该过滤器抛出自定义异常时,它不会通过我的异常处理程序,它使用默认的Spring错误控件。

有没有办法以我自己的方式处理过滤器中的错误?

2 个答案:

答案 0 :(得分:1)

您可以编写一个扩展BasicErrorController的控制器,并编写一个具有@GetMapping注释的方法,如下所示:

@RestController
public class FilterExceptionController extends BasicErrorController {

    private static final Logger LOGGER = LoggerFactory.getLogger(FilterExceptionController.class);

    public FilterExceptionController(){
        super(new DefaultErrorAttributes(),new ErrorProperties());
    }

    @GetMapping
    private <T> ResponseResult<T> serviceExceptionHandler(HttpServletRequest request) {
        Map<String,Object> body= getErrorAttributes(request,isIncludeStackTrace(request,MediaType.ALL));
        String message = String.valueOf(body.get("message"));
        body.forEach((k,v)->LOGGER.info("{} ==> {}",k,v));
        return RestResultGenerator.genError(500,"Filter Error Occurred, Message: [ "+message+" ]");
    }

    @Override
    public String getErrorPath() {
        return "/error";
    }
}

有我的测试过滤器:

@WebFilter(filterName = "ipFilter",urlPatterns = "/*")
public class IpFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        if(!Arrays.asList(new String[]{"127.0.0.1"}).contains(servletRequest.getRemoteAddr())){
            throw new ServiceException(403,"ip forbid");
        }
    }

    @Override
    public void destroy() {

    }
}

这是结果(但只获取异常消息而不是代码): enter image description here

答案 1 :(得分:1)

如果你在过滤器中捕获异常,然后用HandlerExceptionResolver处理,@ControllerAdvice就会开始工作

import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class HystrixRequestContextServletFilter extends OncePerRequestFilter {

    private static final String API_KEY = "apiKey";

    private final HandlerExceptionResolver handlerExceptionResolver;

    @Autowired
    public HystrixRequestContextServletFilter(HandlerExceptionResolver handlerExceptionResolver) {
        this.handlerExceptionResolver = handlerExceptionResolver;
    }

    @Override
    public void doFilterInternal(HttpServletRequest httpRequest, HttpServletResponse httpResponse, FilterChain filterChain) {
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        try {
            String apiKey = httpRequest.getHeader(API_KEY);
            if (apiKey == null) {
                throw new AuthenticationException("no apikey in request, path [" + httpRequest.getRequestURI() + "]");
            }
            ApiKeyHystrixRequestVariable.set(apiKey);
            filterChain.doFilter(httpRequest, httpResponse);
        } catch (Exception e) {
            handlerExceptionResolver.resolveException(httpRequest, httpResponse, null, e);
        } finally {
            context.shutdown();
        }
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        return request.getRequestURI().startsWith("/internal");
    }

}