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; @NestedConfigurationProperty private 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). */ private String 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的用法,倒入哪個,那個生效。