栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Springboot的Filter,HandlerInterceptor,Aspect与异常处理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Springboot的Filter,HandlerInterceptor,Aspect与异常处理

问题

不知你在Springboot应用开发中有没有遇到过这样的情况,http请求进来却没有到达指定的controller就返回响应了,这是有可能在哪里拦截了呢。
答案是Filter,HandlerInterceptor,Aspect都有可能拦截,下面简单分析一下它们几个。

定义
  • Filter是Tomcat中定义的过滤器,基于调用链调用,可以对request和response处理,使用场景基本有鉴权验证,日志记录,跨域处理等。
  • HandlerInterceptor是Spring中定义的过滤器,基于调用链调用,作用类似于Filter,也可以对request和response处理,另外可以对ModelAndView对象进行处理。
  • Aspect是Spring中定义的切面,由切点和处理方法组成,切点可以是注解,类名,方法名等,可以对方法的入参出参处理。
使用方式 Filter
@Component
@Order(1)
public class TestFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
HandlerInterceptor
public class TestHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
    @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 {
    }
}

@Component
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TestHandlerInterceptor());
    }
}
Aspect
@Aspect
@Component
public class TestAspect {
    @Pointcut("execution(* *..*Controller.*(..))")
    public void pointcut() {
    }
    @Before(value = "pointcut()")
    public void before(JoinPoint joinPoint) {
    }

    @After("pointcut()")
    public void after(JoinPoint joinPoint) {
    }

    @Around(value = "pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = proceedingJoinPoint.proceed();
        return result;
    }
}
三者关系与异常处理

要说清它们关系得加上异常处理,在Springboot开发中默认的异常处理有三层,分别有ErrorPage,ErrorController,RestControllerAdvice,一次请求的调用链路简化图如下

① DispatcherServlet是Spring框架定义的Servlet,在Tomcat中作为默认的Servlet,是联通Tomcat和Spring的关键节点,负责分发http请求到对应的Controller中处理。
② 请求建立socket链接后,先经过Tomcat的数个valve,开始进入Filter,再到HandlerInterceptor,Aspect,最后才到达Controller的,而相应的返回路径正好相反,先从Controller,最后到Filter。
③ 当在HandlerInterceptor和Aspect发生异常时,如果我们定义了@RestControllerAdvice和@ExceptionHandler,那么会在DispatcherServlet处理中,把异常交给我们定义的方法来处理。如果没有定义则往上抛异常。
④ 如果没有定义@ExceptionHandler或者Filter中发生异常时,将会在StandardHostValve中寻找匹配的ErrorPage,默认情况下,会将请求交给定义了/error路径的Controller处理,在Springboot中,默认会交给BasicErrorController处理,
因为是在StandardHostValve发起的链路,所以Filter,HandlerInterceptor,Aspect都会重新走一遍,但是有一点不同的是,这条链路只会调用类型为error的Filter,所以我们自定义的Filter不会重新调用。
⑤ 如果前面两道防线都失守了,或者③的异常处理链路中再次发生异常,那么将会在ErrorReportValve中处理异常,这时候处理异常比较简单粗暴,直接读取匹配的html文件,如果没有找到html文件,就会拼接一个固定样式的html报文响应回去。

延伸
  • 从调用流程图上我们可以看到,要做请求响应的日志,采用Filter是比较合适的,因为可以拿到原始报文,而且只会执行一次,而HandlerInterceptor和Aspect是有可能执行两遍的。
  • 如果要自定义异常的话,比较合适的介入点是③,编写@ExceptionHandler的处理方法,但是这种方式是不能处理404等异常,因为这种异常是在DispatcherServlet抛出的,所以还要在④介入异常处理,Springboot提供了两种方式,一是实现ErrorAttributes,二是实现ErrorController。
  • 在④的异常处理默认是跳转到/error路径的Controller,如果需要根据状态码跳转到不同的路径处理,可以实现ErrorPageRegistrar指定状态码和路径
  • 在⑤的异常处理,是固定样式的html报文,在Springboot中目前没有发现可以自定义的切入点。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1020636.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号