JayFighting 2019-10-23
springboot中默认使用的是tomcat容器,也叫做嵌入式的servlet容器。因为它和我们平常使用的tomcat容器不一样,这个tomcat直接嵌入到的springboot,平常我们使用tomcat容器是一个独立的应用,配置的时候需要在tomcat中的xml中配置,而使用springboot就不一样了,本文我们来学习怎么配置和替换servlet容器、以及注册传统的servlet组件。
我们可以在application.properties中按照传统的配置方式设置,如下:
server.port=8081 server.context-path=/crud server.tomcat.uri-encoding=UTF-8 //通用的Servlet容器设置 server.xxx //Tomcat的设置 server.tomcat.xxx
其中server开头的是web容器统一的配置,因为我们以后可以使用其他的web容器,带tomcat的是特定为tomcat容器的配置。
编写一个EmbeddedServletContainerCustomizer:嵌入式的Servlet容器的定制器,来修改Servlet容器的配置。我们可以添加一个MyServerConfig类,用注解的方式来配置我们的Server配置。
package com.example.demo.config; import org.springframework.boot.web.server.ConfigurableWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyServerConfig { @Bean public WebServerFactoryCustomizer embeddedServletContainerCustomizer(){ return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() { @Override public void customize(ConfigurableWebServerFactory factory) { factory.setPort(8085); } }; } }
启动之后我们就把端口设置到了8085。
由于springboot默认是以jar包的方式启动嵌入式的web服务器来启动springboot应用,没有web.xml文件。传统情况下我们配置三大组件都是在web.xml中添加配置,现在就不能这么做了。
我们使用ServletRegistrationBean类来往容器中添加Servlet组件,在MyServerConfig中添加一个方法:
@Bean public ServletRegistrationBean myServlet(){ ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet"); return registrationBean; }
添加一个MyServlet类来处理/myServlet的请求:
public class MyServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().write("hello,my servlet"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
启动后浏览器访问http://localhost:8085/myServlet,被我们的MyServlet接管处理,因为配置的时候我们要处理的urlPatterns是/myServlet。
一样的原理,我们使用FilterRegistrationBean类来往容器中添加Filter组件:
@Bean public FilterRegistrationBean myFilter(){ FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new MyFilter()); registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet")); return registrationBean; }
添加一个MyFilter的类来处理映射的url:
@WebFilter(filterName = "MyFilter") public class MyFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { resp.getWriter().write("hello,my filter"); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
使用ServletListenerRegistrationBean类来往容器中添加Listener组件:
@Bean public ServletListenerRegistrationBean myListener(){ ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener()); return registrationBean; }
添加一个MyListenner的类来处理逻辑:
public class MyListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("contextInitialized...web应用启动"); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("contextDestroyed...当前web项目销毁"); } }
这就是我们注册传统三大组件的方法。
有了以上的基础,我们就可以看一下,其实springboot为我们启动springmvc的时候也是通过这种方式注册了DispatcherServlet,这就是我们springmvc中核心的servlet。
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public ServletRegistrationBean dispatcherServletRegistration( DispatcherServlet dispatcherServlet) { ServletRegistrationBean registration = new ServletRegistrationBean( dispatcherServlet, this.serverProperties.getServletMapping()); //默认拦截: / 所有请求;包静态资源,但是不拦截jsp请求; /*会拦截jsp //可以通过server.servletPath来修改SpringMVC前端控制器默认拦截的请求路径 registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); registration.setLoadOnStartup( this.webMvcProperties.getServlet().getLoadOnStartup()); if (this.multipartConfig != null) { registration.setMultipartConfig(this.multipartConfig); } return registration; }
这次我们学些了怎样注册传统的三大组件,虽然用到的机会可能不会那么多了,但是springboot的设计理念还是很好的。