基本介绍
考虑到实际开发业务非常复杂和兼容,Spring-Boot支持将Servlet、Filter、Listener注入Spring容器,成为Spring bean
也就是说明Spring-Boot开放了和原生WEB组件(Servlet、Filter、Listener)的兼容
当使用嵌入式容器时,自动注册含有注解@WebServlet,@WebFilter,@WebListener的类,使用注解@ServletComponentScan(是另外注解到Application.class上的)才会注入到spring容器。
需要在Application.class添加注解@ServletComponentScan(basePackages = "com.stein.springboot"),并设置扫描包,这样才能将这三大组件添加到ioc容器。
@ServletComponentScan(basePackages = "com.stein.springboot")
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext ioc
= SpringApplication.run(Application.class, args);
System.out.println("hello");
//ioc.close();//销毁context,查看ServletContextListener监听情况
}
}
@WebServlet(urlPatterns = {"/servlet01","/servlet02"})
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write("doGet()被执行");
}
}
@Slf4j
@WebFilter(urlPatterns = {"/css/*","/images/*"})
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("filter_init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("doFilter");
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
log.info("过滤器处理的uri={}",httpServletRequest.getRequestURI());
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
log.info("filter-destroy");
}
}
注意:过滤器配置的urlPatterns也会经过Spring-Boot拦截器(根据拦截器的规则)
所以为了看到效果,请在拦截器配置放行/css/**
在servlet匹配全部是/*,在Spring-Boot是/**
监听器有8种,这儿只是选取了较为常用的ServletContextListener来进行演示。Destroy方法需要在Application.class中调用ioc.close( )才能看到。
@Slf4j
@WebListener
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("ServletContextListener监听到上下文初始化");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("ServletContextListener监听到上下文销毁");
}
}
创建一个配置类,使用@Configuration注解,然后新建一个方法使用@Bean注入,返回XXXRegistrationBean类型的方式来注入。
@Configuration
public class MyServletConfig { }
@Bean
public ServletRegistrationBean servlet(){
MyServlet myServlet = new MyServlet();
return new ServletRegistrationBean(myServlet,"/servlet01","/servlet02");
}
通过在浏览器输入:localhost:8080/servlet01 或 servlet02 来查看是否正确执行
@Bean
public FilterRegistrationBean filter(){
MyFilter myFilter = new MyFilter();
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/css/*","/images/*"));
return filterRegistrationBean;
}
通过在浏览器输入: localhost:8080/css/t.css或者localhost:8080/images/logo.png来查看是否注入成功
@Bean
public ServletListenerRegistrationBean listener(){
MyListener myListener = new MyListener();
return new ServletListenerRegistrationBean(myListener);
}
通过查看SpringApplication.run(Application.class, args)的运行或者ioc.close()的关闭来查看Context的监听情况。
1.请求Servlet时,不会到达DispatherServlet,因此也不会达到拦截器
2.原因分析
注入的Servlet会存在Spring容器中
DispatherServlet也存在Spring容器中
3.回忆一下Tomcat在对Servlet url匹配的原则,多个servlet都能处理到同一层路径,精确优先原则/最长前缀匹配原则
4. debug源码
5.在SpringBoot中,去调用@Controller目标方法是按照DispatherServlet分发匹配的机制,请回顾一下我们自己实现SpringMVC的底层机制的程序。