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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springboot的Filter,HandlerInterceptor,Aspect与异常处理相关的知识,希望对你有一定的参考价值。

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

要说清它们关系得加上异常处理,在 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报文响应回去。

SpringBoot: 3.SpringBoot整合filter(转)

整合方式一:通过注解扫描完成 Filter 组件的注册

1、编写filter

技术图片
package com.bjsxt.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * Created by Administrator on 2019/2/4.
 */
@WebFilter(filterName = "FirstFilter",urlPatterns = {"/first"}) //filter名字和拦截的路径
public class FirstFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("进入FirstFilter.......");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("离开FirstFilter.......");
    }

    @Override
    public void destroy() {

    }
}
技术图片

2、编写启动类

技术图片
package com.bjsxt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

/**
 * Created by Administrator on 2019/2/4.
 */
@SpringBootApplication
@ServletComponentScan   //在springboot启动时,会扫描@WebServlet、@WebFilter等,并将该类实例化
public class App {

    public static void main(String[] args){
        SpringApplication.run(App.class,args);
    }
}
技术图片

 

整合方式二:通过方法完成 Filter 组件的注册

1、编写filter

技术图片
package com.bjsxt.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * Created by Administrator on 2019/2/4.
 */
public class SecondFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("进入SecondFilter.......");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("离开SecondFilter.......");
    }

    @Override
    public void destroy() {

    }
}
技术图片

2、编写启动类

技术图片
package com.bjsxt;

import com.bjsxt.filter.SecondFilter;
import com.bjsxt.servlet.SecondServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

/**
 * Created by Administrator on 2019/2/4.
 */
@SpringBootApplication
public class App2 {

    public static void main(String[] args){
        SpringApplication.run(App2.class,args);
    }

    /**
     * 注册Servlet
     * @return
     */
    @Bean
    public ServletRegistrationBean getServletRegistrationBean(){
        ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet());
        bean.addUrlMappings("/second");
        return bean;
    }

    /**
     * 注册Filter
     * @return
     */
    @Bean
    public FilterRegistrationBean getFilterRegistrationBean(){
        FilterRegistrationBean bean = new FilterRegistrationBean(new SecondFilter());
        bean.addUrlPatterns(new String[]{"/second"});
        return bean;
    }
}

以上是关于Springboot的Filter,HandlerInterceptor,Aspect与异常处理的主要内容,如果未能解决你的问题,请参考以下文章

某队列积压问题分析解决

使用篇SpringBoot整合Filter

SpringBoot SpringBoot过滤器Filter

SpringBoot学习3:springboot整合filter

SpringBoot: 3.SpringBoot整合filter(转)

SpringBoot自定义Filter