写在前面:


使用Spring-Boot时,嵌入式Servlet容器可以通过扫描注解(@ServletComponentScan)的方式注册Servlet、Filter和Servlet规范的所有监听器(如HttpSessionListener监听器)。 

Spring boot 的主 Servlet 为
DispatcherServlet,其默认的url-pattern为“/”。一般情况系统默认的Servlet就够用了,如果需要自定义Servlet,可以继承系统抽象类HttpServlet,重写方法来实现自己的Servlet。关于Servlet、过滤器、拦截器、监听器可以参考:
(转)servlet、filter、listener、interceptor之间的区别和联系
<http://www.cnblogs.com/mr-yang-localhost/p/7775195.html>

Spring-Boot有两种方法注册Servlet、Filter和Listener :

1、代码注册:通过ServletRegistrationBean、 FilterRegistrationBean 和
ServletListenerRegistrationBean 获得控制。

2、在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener
可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。

一、Servlet

Servlet匹配规则:匹配的优先级是从精确到模糊,复合条件的Servlet并不会都执行。

1、通过@ServletComponentScan自动扫描

a、springboot的启动入口添加注解:@ServletComponentScan;

 
@SpringBootApplication @ServletComponentScan public class ApplicationMain {
public static void main(String[] args) { SpringApplication.run(ApplicationMain.
class, args); } }
 

b、@WebServlet 自定义Servlet,配置处理请求路径 /demo/myServlet 
@WebServlet(name = "myServletDemo1",urlPatterns =
"/demo/myServlet",description = "自定义的servlet") public class MyServletDemo1
extends HttpServlet { @Override protected void doGet(HttpServletRequest req,
HttpServletResponse resp)throws ServletException, IOException {
System.out.println("==========myServletDemo Get Method==========");
resp.getWriter().println("my myServletDemo1 process request"); super.doGet(req,
resp); } @Overrideprotected void doPost(HttpServletRequest req,
HttpServletResponse resp)throws ServletException, IOException {
System.out.println("==========myServletDemo1 POST Method=========="); super
.doPost(req, resp); } }
 

2、使用@ServletRegistrationBean注解

a、@ServletRegistrationBean注入自定义的Servlet,配置处理的路径为 /demo/servletDemo2 
@Configuration public class ServletConfiguration { /** * 代码注入 */ @Bean public
ServletRegistrationBean myServletDemo() {return new ServletRegistrationBean(new
MyServletDemo2(), "/demo/servletDemo2"); } }
b、自定义的Servlet
public class MyServletDemo2 extends HttpServlet { @Override protected void
doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException,
IOException { System.out.println("==========myServletDemo2 Get Method=========="
); resp.getWriter().println("my myServletDemo2 process request"); super
.doGet(req, resp); } @Overrideprotected void doPost(HttpServletRequest req,
HttpServletResponse resp)throws ServletException, IOException {
System.out.println("==========myServletDemo2 POST Method=========="); super
.doPost(req, resp); } }
 

二、Filter

完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

Filter有如下几个用处。

* 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。
* 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
* 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。
* 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。
多个FIlter可以组成过滤器调用链,按设置的顺序逐一进行处理,形成Filter调用链。

1、通过@ServletComponentScan自动扫描

a、springboot的启动入口添加注解:@ServletComponentScan;

b、@WebFilter 配置处理全部url的Filter
@WebFilter(filterName = "myFilter",urlPatterns = "/*") public class MyFilter
implements Filter { public void init(FilterConfig filterConfig) throws
ServletException { System.out.println(">>>>>>myFilter init ……"); } public void
doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain)throws IOException, ServletException {
System.out.println(">>>>>>执行过滤操作"); filterChain.doFilter(servletRequest,
servletResponse); }public void destroy() { System.out.println(">>>>>>myFilter
destroy ……"); } }

 * doFilter()方法是过滤器的核心方法,实现该方法就可实现对用户请求进行预处理,也可实现对服务器响应进行后处理——它们的分界线为是否调用了filterChain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。

2、通过@FilterRegistrationBean注册

a、@Bean注入自定义的Filter
@Configuration public class ServletConfiguration { @Bean public
FilterRegistrationBean myFilterDemo(){ FilterRegistrationBean registration= new
FilterRegistrationBean(); registration.setFilter(new MyFilter2());
registration.addUrlPatterns("/demo/myFilter2"); registration.addInitParameter(
"paramName", "paramValue"); registration.setName("myFilter2");
registration.setOrder(2);//指定filter的顺序 return registration; } }


b、自定义的Filter
public class MyFilter2 implements Filter { public void init(FilterConfig
filterConfig)throws ServletException { System.out.println("======MyFilter2 init
……"); } public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain filterChain)throws IOException, ServletException {
System.out.println("======MyFilter2执行过滤操作");
filterChain.doFilter(servletRequest, servletResponse); }public void destroy() {
System.out.println("======MyFilter2 destroy ……"); } }
三、Listener

目前 Servlet 中提供了 6 种两类事件的观察者接口,它们分别是:4 个 EventListeners
类型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener
和 2 个 LifecycleListeners 类型的,ServletContextListener、HttpSessionListener。

* ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。
*
ServletContextListener监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEvent
sce)方法;当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。
* HttpSessionListener监听HttpSession的操作。当创建一个Session时,激发session
Created(HttpSessionEvent se)方法;当销毁一个Session时,激发sessionDestroyed
(HttpSessionEvent se)方法。
*
HttpSessionAttributeListener监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent
se) 方法;当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent
se)方法;当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。
1、通过@ServletComponentScan自动扫描

a、ServletListenerRegistrationBean 注入自定义的Listener;

b、自定义的Listener
@WebListener public class MyLisener implements ServletContextListener { public
void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("MyLisener contextInitialized method"); } public void
contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println(
"MyLisener contextDestroyed method"); } }
2、通过@ServletListenerRegistrationBean 注册

a、@Bean注入自定义的Listener;
@Configuration public class ServletConfiguration { @Bean public
ServletListenerRegistrationBean myListener(){return new
ServletListenerRegistrationBean(new MyLisener()); } }
b、自定义的Listener
public class MyLisener implements ServletContextListener { public void
contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("MyLisener contextInitialized method"); } public void
contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println(
"MyLisener contextDestroyed method"); } } 
四、验证servlet、filter、listener的顺序

a、使用MyServletDemo2、MyFilter2、MyFilter3、MyLisener做测试;

b、设置servlet处理url格式为 /demo/*;设置MyFilter2顺序为2;MyFilter3的顺序为3;
@Configuration public class ServletConfiguration { /**代码注入*/ @Bean public
ServletRegistrationBean myServletDemo(){return new ServletRegistrationBean(new
MyServletDemo2(),"/demo/*"); } @Bean public FilterRegistrationBean
myFilterDemo(){ FilterRegistrationBean registration= new
FilterRegistrationBean(); registration.setFilter(new MyFilter2());
registration.addUrlPatterns("/demo/myFilter"); registration.addInitParameter(
"paramName", "paramValue"); registration.setName("myFilter2");
registration.setOrder(2);//指定filter的顺序 return registration; } @Bean public
FilterRegistrationBean myFilterDemo2(){ FilterRegistrationBean registration= new
FilterRegistrationBean(); registration.setFilter(new MyFilter3());
registration.addUrlPatterns("/demo/*"); registration.addInitParameter(
"paramName", "paramValue"); registration.setName("myFilter3");
registration.setOrder(1); return registration; } @Bean public
ServletListenerRegistrationBean myListener(){return new
ServletListenerRegistrationBean(new MyLisener()); } } View Code
c、启动项目后输出:(FIlter2先执行init,因为@Ben在前)

MyLisener contextInitialized method
======MyFilter2 init ……
======MyFilter3 init ……

d、浏览器输入地址地址:http://localhost:8080/demo/myFilter,输出:

======MyFilter3执行过滤操作
======MyFilter2执行过滤操作
>>>>>>>>>>test Get Method==========

可以看出:

* Filter3比Filter2先执行;
* Filter可以匹配上的url都会执行,并且按顺序执行(Filter的调用链);
* Filter比servlet先执行。
* servlet先按具体匹配,然后模糊匹配,并且只能有一个servlet匹配上,没有servlet调用链。
执行顺序是:Listener》Filter》Servlet

五、ApplicationListener自定义侦听器类

参考:http://blog.csdn.net/liaokailin/article/details/48186331
<http://blog.csdn.net/liaokailin/article/details/48186331>

六、Interceptor

拦截器只会处理DispatcherServlet处理的url

a、自定义拦截器
public class MyInterceptor implements HandlerInterceptor { public boolean
preHandle(HttpServletRequest httpServletRequest, HttpServletResponse
httpServletResponse, Object o)throws Exception { System.out.println(
">>>>MyInterceptor preHandle"); return true; } public void
postHandle(HttpServletRequest httpServletRequest, HttpServletResponse
httpServletResponse, Object o, ModelAndView modelAndView)throws Exception {
System.out.println(">>>>MyInterceptor postHandle"); } public void
afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse
httpServletResponse, Object o, Exception e)throws Exception {
System.out.println(">>>>MyInterceptor afterCompletion"); } }
 

b、注册拦截器
@Configuration public class WebMvcConfiguration extends
WebMvcConfigurerAdapter { @Overridepublic void
addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new
MyInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry); } }
c、拦截器验证

输入地址:http://localhost:8080/home/test

>>>>MyInterceptor preHandle
>>>>MyInterceptor postHandle
>>>>MyInterceptor afterCompletion

输入地址:http://localhost:8080/demo/myFilter (自定义的Servlet处理了请求,此时拦截器不处理)

拦截器不处理。

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信