`
rensanning
  • 浏览: 3513943 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
Efef1dba-f7dd-3931-8a61-8e1c76c3e39f
使用Titanium Mo...
浏览量:37478
Bbab2146-6e1d-3c50-acd6-c8bae29e307d
Cordova 3.x入门...
浏览量:604304
C08766e7-8a33-3f9b-9155-654af05c3484
常用Java开源Libra...
浏览量:678049
77063fb3-0ee7-3bfa-9c72-2a0234ebf83e
搭建 CentOS 6 服...
浏览量:87250
E40e5e76-1f3b-398e-b6a6-dc9cfbb38156
Spring Boot 入...
浏览量:399811
Abe39461-b089-344f-99fa-cdfbddea0e18
基于Spring Secu...
浏览量:69066
66a41a70-fdf0-3dc9-aa31-19b7e8b24672
MQTT入门
浏览量:90468
社区版块
存档分类
最新评论

Spring Boot 入门 - 进阶篇(1)- Servlet、Filter、Listener、Interceptor

 
阅读更多
用户认证授权、日志记录MDC、编码解码、UA检查、多端对应等都需要通过拦截请求来共通处理,这时就需要Filter、Listener、Interceptor。而把非Spring Boot项目转换成Spring Boot项目需要沿用以前的这些代码,所以有必要了解这几个东西的用法。

通常来说,用户通过浏览器发起Request进入服务器后侧处理顺序如下:
引用
Client -> Listener -> ServletContainer -> Filter -> Servlet -> Interceptor


具体可以看看这里:http://rensanning.iteye.com/blog/2355214

大部分框架采用一个servlet分发请求到不同controller去处理,只有极个别场景会定义多个servlet来处理比较特殊需求。而Filter、Listener、Interceptor按需求一般来说都会是多个。

(1)Servlet 2.5采用web.xml定义Servlet、Filter、Listener
<web-app ...>

  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>com.rensanning.springtest.HelloWorldServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  </filter>
  <filter-mapping>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener> 
    <listener-class>com.rensanning.springtest.TestServletContextListener</listener-class>
  </listener>

</web-app>


(2)Servlet 3.0开始不再需要web.xml,可以通过注解或Java代码定义Servlet/Filter等。

1)注解定义
@WebServlet(name="HelloWorldServlet",urlPatterns={"/HelloWorld"},
        initParams={@WebInitParam(name="name",value="rensanning")})
public class HelloWorldServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.getWriter().print("Hello " + getInitParameter("name"));
    }
}

@WebFilter(filterName="HelloWorldFilter", urlPatterns="/HelloWorld")
public class HelloWorldFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        chain.doFilter(request, response);
    }

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

}

引用
Servlet规范不支持注解Filter的执行顺序,仍需在 web.xml 中定义,web.xml中定义的<filter-mapping>的顺序就是他们的执行顺序。

@WebFilter(filterName="filter1", urlPatterns="/url1/*")
public class Filter1 implements Filter {}

@WebFilter(filterName="filter2", urlPatterns="/url2/*")
public class Filter2 implements Filter {}

<filter-mapping>
    <filter-name>filter1</filter-name>
    <url-pattern />
</filter-mapping>
<filter-mapping>
    <filter-name>filter2</filter-name>
    <url-pattern />
</filter-mapping>


@WebListener
public class TestServletContextListener implements ServletContextListener {
    @Override
    public void contextDestroyed(ServletContextEvent event) { }
    @Override
    public void contextInitialized(ServletContextEvent event) { }
}


2)动态注册
public class WebInitializer implements WebApplicationInitializer {

    public void onStartup(Set<Class<?>> classes, ServletContext servletContext) throws ServletException {
        // Servlet
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
        dispatcher.addMapping("/");
        dispatcher.setLoadOnStartup(1);
        dispatcher.setInitParameter("defaultHtmlEscape", "true");

        // Filter
        FilterRegistration.Dynamic filter = container.addFilter("encodingFilter", CharacterEncodingFilter.class);
        filter.addMappingForUrlPatterns(null, false, "/*");
        filter.setInitParameter("encoding", "UTF-8");
        filter.setInitParameter("forceEncoding", "true");

        // Listener
        servletContext.addListener(TestServletContextListener.class);
    }

}


(3)Spring Boot也采用无web.xml,以Filter为例,添加方法如下:

1)通过@Component让Spring扫描到即可处理拦截处理所有请求
@Component
public class TestFilter implements Filter {
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
         throws IOException, ServletException {
    chain.doFilter(request, response);
  }
  @Override
  public void init(FilterConfig filterConfig) throws ServletException { }
  @Override
  public void destroy() { }
}


2)通过@Configuration + @Bean来管理未被扫描到的Filter
public class MultipleFilter1 implements Filter { }
public class MultipleFilter2 implements Filter { }

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public Filter filter1() {
        return new MultipleFilter1();
    }

    @Bean
    public Filter filter2() {
        return new MultipleFilter2();
    }
}


3)通过@Configuration + @Bean + FilterRegistrationBean更灵活的设置Filter
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
  @Bean
  public FilterRegistrationBean filter1() {
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setFilter(new MultipleFilter1());
    bean.setOrder(2);
    return bean;
  }
  @Bean
  public FilterRegistrationBean filter2() {
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setFilter(new MultipleFilter2());
    bean.setOrder(1);
    return bean;
  }
}


4)通过@ServletComponentScan自动扫描@WebServlet, @WebFilter, @WebListener
@SpringBootApplication
@ServletComponentScan 
public class Application {
   public static void main(String[] args) {
       SpringApplication.run(Application.class, args);
   }
}


SpringBoot默认已经为应用添加了以下Servlet/Filter
引用
o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]


定义Interceptor
public class TraceLoggingInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {    }

}

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // <mvc:interceptors>     
        registry.addInterceptor(traceLoggingInterceptor())
                .addPathPatterns("/**/*.do")
                .addPathPatterns("/**/*.json");
    }
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics