SpringBoot Boot內嵌Tomcat
Spring Boot:
SpringBoot-start-web 裏面依賴的環境中
如果是外部的Tomcat 容器,可以通過修改config進行配置
內嵌的呢?
如何定制和修改Servlet容器的相關配置;
1、修改和server有關的配置(ServerProperties類【也是EmbeddedServletContainerCustomizer】);
經常用的:
server.port=8081
server.context‐path=/crud
server.tomcat.uri‐encoding=UTF‐8
//通用的Servlet容器設置 server.xxx //Tomcat的設置 server.tomcat.xxx 最大連接數等等
原理:
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties { /** * Server HTTP port. */ private Integer port; /** * Network address to which the server should bind. */ private InetAddress address; @NestedConfigurationPropertyprivate final ErrorProperties error = new ErrorProperties(); /** * Whether X-Forwarded-* headers should be applied to the HttpRequest. */ private Boolean useForwardHeaders; /** * Value to use for the Server response header (if empty, no header is sent). */ privateString serverHeader; /** * Maximum size of the HTTP message header. */ private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8); /** * Time that connectors wait for another HTTP request before closing the connection. * When not set, the connector‘s container-specific default is used. Use a value of -1 * to indicate no (that is, an infinite) timeout. */ private Duration connectionTimeout; @NestedConfigurationProperty private Ssl ssl; @NestedConfigurationProperty private final Compression compression = new Compression(); @NestedConfigurationProperty private final Http2 http2 = new Http2(); private final Servlet servlet = new Servlet(); private final Tomcat tomcat = new Tomcat(); private final Jetty jetty = new Jetty(); private final Undertow undertow = new Undertow(); public Integer getPort() { return this.port; } public void setPort(Integer port) { this.port = port; } public InetAddress getAddress() { return this.address; }
2、編寫一個EmbeddedServletContainerCustomizer:嵌入式的Servlet容器的定制器;來修改Servlet容器的配置 (已經過時了)
@Bean //一定要將這個定制器加入到容器中 public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){ return new EmbeddedServletContainerCustomizer() { //定制嵌入式的Servlet容器相關的規則 @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.setPort(8083); } }; }
註冊Servlet的三大組件 Servlet Filter Listener
Spring boot 默認以jar包的方式 啟動嵌入式tomcat,而不是標準的web應用。 webapp/WEB-INF/web.xml
沒有web.xml 也可以註冊哦
ServletRegistrationBean
//註冊三大組件 @Bean public ServletRegistrationBean myServlet(){ ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet"); return registrationBean; }
舉個栗子:
MyServlet:
public class MyServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("hello MyServlet"); } }
config:
@Configuration public class MyConfig { @Bean public ServletRegistrationBean<Servlet> myServlet(){ //是個class 直接new出來 ServletRegistrationBean<Servlet> servletServletRegistrationBean = new ServletRegistrationBean<>(new MyServlet(),"/myServlet"); return servletServletRegistrationBean; } }
運行後:註冊成功
FilterRegistrationBean
@Bean public FilterRegistrationBean myFilter(){ FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new MyFilter()); registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet")); return registrationBean; }
舉個栗子:
config中加入組件:
@Bean public FilterRegistrationBean myFilter(){ FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>(); filterFilterRegistrationBean.setFilter(new MyFilter()); filterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet")); return filterFilterRegistrationBean; }
過濾器:
public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("doFilter 方法執行"); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
請求後:
ServletListenerRegistrationBean
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean<MyListener> registrationBean = new
ServletListenerRegistrationBean<>(new MyListener());
return registrationBean;
}
舉個栗子:
/** * listener 有好多的! */ public class MyListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("contextInitialized..............."); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("contextDestroyed.................."); } }
組件註冊進去:
@Bean public ServletListenerRegistrationBean myListener(){ ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>( new MyListener()); //通過構造函數 s return registrationBean; }
啟動和退出
總結:
Spring boot 幫我們自動配置Spring mvc的時候,自動註冊了前端控制器,DispatcherServlet。 (DispatcherServletAutoConfiguration類)
這個類中有個方法:
@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; }
總結一個思路:
經常在看源碼時候,發現定義一個接口,然後實現類是個中Factory命名的。通過某個工廠創建組件 xxFactory 是用來得到xx的!
condition的用法,倒入哪個,那個生效。
SpringBoot Boot內嵌Tomcat