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

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

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

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

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

[b](1)Servlet 2.5采用web.xml定义Servlet、Filter、Listener[/b]
<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>


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

[b]1)注解定义[/b]
@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() {}

}

[quote]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>[/quote]

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


[b]2)动态注册[/b]
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);
}

}


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

[b]1)通过@Component让Spring扫描到即可处理拦截处理所有请求[/b]
@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() { }
}


[b]2)通过@Configuration + @Bean来管理未被扫描到的Filter[/b]
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();
}
}


[b]3)通过@Configuration + @Bean + FilterRegistrationBean更灵活的设置Filter[/b]
@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;
}
}


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


[b]SpringBoot默认已经为应用添加了以下Servlet/Filter[/b]
[quote]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: [/*][/quote]

[b]定义Interceptor[/b]
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");
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值