一、修改Spring Boot 中内嵌Servlet容器的默认配置
Spring Boot提供了默认提供了内嵌的Tomcat,可以通过命令行运行jar包的方式运行Spring Boot应用,spring-boot-start-web依赖中包含了Tomcat依赖,最新版本为9.0.62。
以往通过Tomcat容器运行Spring应用时,可以通过修改Tomcat的一些配置文件来修改Tomcat的运行状态,比如说端口号等,那么Spring Boot内嵌的Tomcat要如何修改?
有两种方式修改内置Tomcat的配置,第一种是在application.properties中添加tomcat配置和server配置
第二种方式是编写一个WebServerFactoryCustomizer来进行tomcat的配置,在SpringBoot1.x的时候使用的是EmbeddedServletContainerCustomizer到SpringBoot2.x后WebServerFactoryCustomizer替代了EmbeddedServletContainerCustomizer。
@Configuration public class LilithMvcConfig implements WebMvcConfigurer { @Bean public WebServerFactoryCustomizer<ConfigurableWebServerFactory> customizer(){ return factory -> { factory.setPort(8083); }; } } 复制代码
注释application.properties中的配置,重新启动该应用
配置生效,tomcat在8083端口启动
这两种配置的优先级是怎样的?
在application.properties中配置
server.port=8081 server.servlet.context-path=/servlet 复制代码
保持WebServerFactoryCustomizer中配置的端口不变,重启应用
控制台输出端口号为8083,路径为/servlet,可以确定重写WebServerFactoryCustomizer配置Tomcat的优先级更高,并且和application.properties是互补的。
二、Spring Boot中注册Servlet、Filter、Listener
在Java Web项目中,我们书写的Servlet、Filter、Listener组件都可以通过web.xml将这些组件配置到Tomcat容器中,那么在Spring Boot项目中使用内置Tomcat并且没有web.xml的情况如何注册这些组件?
Spring Boot为Java Web三大组件提供了通过XxxRegistrationBean的方式进行注册
ServletRegistrationBean注册Servlet
创建一个HalloServelet类继承HttpServlet类,并重写doGet()和doPost()方法
public class HalloServlet extends HttpServlet { // 处理get请求 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("Hallo Servlet"); } } 复制代码
使用ServletRegisterBean,代替在web.xml中注册Servlet,在LilithMvcConfig中增加代码
// 注册Servlet @Bean public ServletRegistrationBean<HalloServlet> halloServletServletRegistrationBean(){ ServletRegistrationBean registrationBean = new ServletRegistrationBean(); registrationBean.setServlet(new HalloServlet()); registrationBean.setUrlMappings(Collections.singleton("/hallo")); return registrationBean; } 复制代码
重启应用,在浏览器访问/hallo
浏览器能够正常显示内容,自定义的Servlet成功注册。
FilterRegistrationBean注册Filter
首先自定义一个LilithFilter类实现Filter接口,在打印日志后放行请求
public class LilithFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("LilithFilter running"); chain.doFilter(request,response); } } 复制代码
在LilithMvcConfig配置类中通过FilterRegistrationBean注册自定义的LilithFilter,并在其中设置过滤器要拦截的请求路径
// 注册Filter @Bean public FilterRegistrationBean<LilithFilter> lilithFilterFilterRegistrationBean(){ FilterRegistrationBean<LilithFilter> filterFilterRegistrationBean = new FilterRegistrationBean<>(); filterFilterRegistrationBean.setFilter(new LilithFilter()); // 设置拦截的请求路径 filterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/hallo")); return filterFilterRegistrationBean; } 复制代码
重启应用,在浏览器输入 /hallo
控制台输出自定义的LilithFilter类中的日志信息,自定义的LilithFilter注册成功并生效
在controller包中新增一个HiController,增加一个hi()方法,请求映射路径为/hi
@Controller public class HiController { @RequestMapping("/hi") @ResponseBody public String hi(){ return "Hi Lilith!"; } } 复制代码
重启应用,浏览器访问/hi,看是否会拦截
控制台没有输出LilithFilter中设置的日志信息,说明没有被拦截,因为LilithFilter过滤器中没有设置拦截该请求,需要注意的是如果LilithFilter中没有设置拦截任何请求,默认拦截所有请求包括静态资源,但是不会jsp请求; /* 会拦截jsp请求。
ServletListenerRegistrationBean注册Listener
增加一个LilithListener类实现Listener接口,实现contextInitialized()方法和contextDestroyed()方法,并打印日志信
public class LilithListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("Web 应用启动了......."); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("Web 应用销毁了......."); } } 复制代码
在LilithMvcConfig配置类中通过ServletListenerRegistrationBean注册自定义的监听器LilithListener
@Bean public ServletListenerRegistrationBean<LilithListener> servletListenerRegistrationBean(){ ServletListenerRegistrationBean<LilithListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>(); servletListenerRegistrationBean.setListener(new LilithListener()); return servletListenerRegistrationBean; } 复制代码
重启应用,查看控制台输出的日志信息
应用启动和关闭时都输出了自定义监听器LilithListener中定义的内容,说明自定义的监听器生效
Spring MVC的前端控制器DispatcherServlet就是通过这种方式来注册的,首先定义了DispatcherServlet类
接着通过DispatcherServletRegistrationBean注册了DispatcherServlet