一、何谓BeanProcessor

  BeanPostProcessor是SpringFramework里非常重要的核心接口之一,我先贴出一段源代码:

/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.beans.factory.config; import org.springframework.beans.BeansException; /**
* Factory hook that allows for custom modification of new bean instances,
* e.g. checking for marker interfaces or wrapping them with proxies.
*
* <p>ApplicationContexts can autodetect BeanPostProcessor beans in their
* bean definitions and apply them to any beans subsequently created.
* Plain bean factories allow for programmatic registration of post-processors,
* applying to all beans created through this factory.
*
* <p>Typically, post-processors that populate beans via marker interfaces
* or the like will implement {@link #postProcessBeforeInitialization},
* while post-processors that wrap beans with proxies will normally
* implement {@link #postProcessAfterInitialization}.
*
* @author Juergen Hoeller
* @since 10.10.2003
* @see InstantiationAwareBeanPostProcessor
* @see DestructionAwareBeanPostProcessor
* @see ConfigurableBeanFactory#addBeanPostProcessor
* @see BeanFactoryPostProcessor
*/
public interface BeanPostProcessor { /**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; /**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
* instance and the objects created by the FactoryBean (as of Spring 2.0). The
* post-processor can decide whether to apply to either the FactoryBean or created
* objects or both through corresponding {@code bean instanceof FactoryBean} checks.
* <p>This callback will also be invoked after a short-circuiting triggered by a
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other BeanPostProcessor callbacks.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }

  在这里我先简单解释一下其注释的含义:

  这个接口允许我们自定义修改新bean的一个实例,比如说:检查它们的接口或者将他们包装成代理对象等,ApplicationContexts能自动察觉到我们在BeanProcessor里对对象作出的改变,并在后来创建该对象时应用其对应的改变。

  这两个方法分别对应IOC容器对对象初始化前的操作和对象初始化后的操作

  下面我们来演示一个例子:

  StudentEntity:

package org.hzgj.spring.study.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; public class StudentEntity { private Integer id; private String name; private Map<String,String> memerories= new HashMap<>(); public Map<String, String> getMemerories() {
return memerories;
} public void setMemerories(Map<String, String> memerories) {
this.memerories = memerories;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public StudentEntity() {
// System.out.println("studentEntity initializer....");
} @Override
public String toString() {
return "StudentEntity{" +
"id=" + id +
", name='" + name + '\'' +
'}';
} private List<String> hobbies=new ArrayList<>(); public List<String> getHobbies() {
return hobbies;
} public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
}

  

  TestBeanPostProcessor:

package org.hzgj.spring.study.context;

import org.hzgj.spring.study.entity.StudentEntity;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor; public class TestBeanPostProcessor implements BeanPostProcessor { @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof StudentEntity) {
StudentEntity studentEntity = new StudentEntity();
studentEntity.setName(beanName);
return studentEntity;
}
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof StudentEntity)
System.out.println(bean);
return bean;
}
}

  Main方法:

package org.hzgj.spring.study;

import org.hzgj.spring.study.entity.StudentEntity;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-config.xml");
StudentEntity studentEntity = applicationContext.getBean(StudentEntity.class);
System.out.println(studentEntity.getName()); }
}

  

  spring-config.xml关键代码:

    <bean id="studentEntity"  class="org.hzgj.spring.study.entity.StudentEntity" depends-on="studentServiceWithFactory">
<property name="hobbies" ref="hobbies">
</property>
<property name="memerories">
<map>
<entry key="glad" value="play"/>
<entry key="cry" value="cry"/>
</map>
</property>
<property name="name" value="admin"/>
</bean> <bean id="beanPostProcessor" class="org.hzgj.spring.study.context.TestBeanPostProcessor" />

  运行得到如下结果:

  我们可以看到在配置文件里定义的bean属性已经发生改变

二、SpringFramework中BeanPostProcessor经典应用场景

1.初始化BeanPostProcessor的源码

根据 ClassPathXmlApplicationContext的构造方法,我们可以看到该类初始化的时候会调用refresh():

/**
* Create a new ClassPathXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of resource locations
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException { super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}

那么紧接着在AbstractApplicationContext中找到refresh()方法:

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
initMessageSource(); // Initialize event multicaster for this context.
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
onRefresh(); // Check for listener beans and register them.
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

那么在这里Spring会进行一系列的初始化操作,我们请留意registerBeanPostProcessors(beanFactory);这句代码,追踪一下我们可以看到在该方法里注册Processor:

public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
} // First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors); // Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors); // Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

2.@Autowired实现的代码跟踪

注意AutowiredAnnotationBeanPostProcessor最终也是BeanPostProcessor的实现类,具体类的描述我就不再这里阐述了,大家可自行查看源码

3、SpringBoot中的定制化内嵌web容器

这个EmbeddedServletContainerCustomizerBeanPostProcessor直接实现的就是BeanPostProcessor,该类下请关注如下方法:

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof ConfigurableEmbeddedServletContainer) {
postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
}
return bean;
}
private void postProcessBeforeInitialization(
ConfigurableEmbeddedServletContainer bean) {
for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
customizer.customize(bean);
}
}
private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
this.beanFactory
.getBeansOfType(EmbeddedServletContainerCustomizer.class,
false, false)
.values());
Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}

这里面有一个接口:EmbeddedServletContainerCustomizer 该接口有个实现类 ServerProperties 熟悉springboot外部化配置原理的同胞们其实一看便知

/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.boot.autoconfigure.web; import java.io.File;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set; import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode; import io.undertow.Undertow.Builder;
import io.undertow.UndertowOptions;
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.valves.ErrorReportValve;
import org.apache.catalina.valves.RemoteIpValve;
import org.apache.coyote.AbstractProtocol;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper; import org.springframework.boot.autoconfigure.web.ServerProperties.Session.Cookie;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.context.embedded.Compression;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.InitParameterConfiguringServletContextInitializer;
import org.springframework.boot.context.embedded.JspServlet;
import org.springframework.boot.context.embedded.Ssl;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.undertow.UndertowBuilderCustomizer;
import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; /**
* {@link ConfigurationProperties} for a web server (e.g. port and path settings). Will be
* used to customize an {@link EmbeddedServletContainerFactory} when an
* {@link EmbeddedServletContainerCustomizerBeanPostProcessor} is active.
*
* @author Dave Syer
* @author Stephane Nicoll
* @author Andy Wilkinson
* @author Ivan Sopov
* @author Marcos Barbero
* @author Eddú Meléndez
* @author Quinten De Swaef
* @author Venil Noronha
* @author Aurélien Leboulanger
*/
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties
implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered { /**
* Server HTTP port.
*/
private Integer port; /**
* Network address to which the server should bind to.
*/
private InetAddress address; /**
* Context path of the application.
*/
private String contextPath; /**
* Display name of the application.
*/
private String displayName = "application"; @NestedConfigurationProperty
private ErrorProperties error = new ErrorProperties(); /**
* Path of the main dispatcher servlet.
*/
private String servletPath = "/"; /**
* ServletContext parameters.
*/
private final Map<String, String> contextParameters = new HashMap<String, String>(); /**
* If X-Forwarded-* headers should be applied to the HttpRequest.
*/
private Boolean useForwardHeaders; /**
* Value to use for the Server response header (no header is sent if empty).
*/
private String serverHeader; /**
* Maximum size in bytes of the HTTP message header.
*/
private int maxHttpHeaderSize = 0; // bytes /**
* Maximum size in bytes of the HTTP post content.
*/
private int maxHttpPostSize = 0; // bytes /**
* Time in milliseconds that connectors will wait for another HTTP request before
* closing the connection. When not set, the connector's container-specific default
* will be used. Use a value of -1 to indicate no (i.e. infinite) timeout.
*/
private Integer connectionTimeout; private Session session = new Session(); @NestedConfigurationProperty
private Ssl ssl; @NestedConfigurationProperty
private Compression compression = new Compression(); @NestedConfigurationProperty
private JspServlet jspServlet; private final Tomcat tomcat = new Tomcat(); private final Jetty jetty = new Jetty(); private final Undertow undertow = new Undertow(); private Environment environment; @Override
public int getOrder() {
return 0;
} @Override
public void setEnvironment(Environment environment) {
this.environment = environment;
} @Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (getPort() != null) {
container.setPort(getPort());
}
if (getAddress() != null) {
container.setAddress(getAddress());
}
if (getContextPath() != null) {
container.setContextPath(getContextPath());
}
if (getDisplayName() != null) {
container.setDisplayName(getDisplayName());
}
if (getSession().getTimeout() != null) {
container.setSessionTimeout(getSession().getTimeout());
}
container.setPersistSession(getSession().isPersistent());
container.setSessionStoreDir(getSession().getStoreDir());
if (getSsl() != null) {
container.setSsl(getSsl());
}
if (getJspServlet() != null) {
container.setJspServlet(getJspServlet());
}
if (getCompression() != null) {
container.setCompression(getCompression());
}
container.setServerHeader(getServerHeader());
if (container instanceof TomcatEmbeddedServletContainerFactory) {
getTomcat().customizeTomcat(this,
(TomcatEmbeddedServletContainerFactory) container);
}
if (container instanceof JettyEmbeddedServletContainerFactory) {
getJetty().customizeJetty(this,
(JettyEmbeddedServletContainerFactory) container);
} if (container instanceof UndertowEmbeddedServletContainerFactory) {
getUndertow().customizeUndertow(this,
(UndertowEmbeddedServletContainerFactory) container);
}
container.addInitializers(new SessionConfiguringInitializer(this.session));
container.addInitializers(new InitParameterConfiguringServletContextInitializer(
getContextParameters()));
} public String getServletMapping() {
if (this.servletPath.equals("") || this.servletPath.equals("/")) {
return "/";
}
if (this.servletPath.contains("*")) {
return this.servletPath;
}
if (this.servletPath.endsWith("/")) {
return this.servletPath + "*";
}
return this.servletPath + "/*";
} public String getPath(String path) {
String prefix = getServletPrefix();
if (!path.startsWith("/")) {
path = "/" + path;
}
return prefix + path;
} public String getServletPrefix() {
String result = this.servletPath;
if (result.contains("*")) {
result = result.substring(0, result.indexOf("*"));
}
if (result.endsWith("/")) {
result = result.substring(0, result.length() - 1);
}
return result;
} public String[] getPathsArray(Collection<String> paths) {
String[] result = new String[paths.size()];
int i = 0;
for (String path : paths) {
result[i++] = getPath(path);
}
return result;
} public String[] getPathsArray(String[] paths) {
String[] result = new String[paths.length];
int i = 0;
for (String path : paths) {
result[i++] = getPath(path);
}
return result;
} public void setLoader(String value) {
// no op to support Tomcat running as a traditional container (not embedded)
} public Integer getPort() {
return this.port;
} public void setPort(Integer port) {
this.port = port;
} public InetAddress getAddress() {
return this.address;
} public void setAddress(InetAddress address) {
this.address = address;
} public String getContextPath() {
return this.contextPath;
} public void setContextPath(String contextPath) {
this.contextPath = cleanContextPath(contextPath);
} private String cleanContextPath(String contextPath) {
if (StringUtils.hasText(contextPath) && contextPath.endsWith("/")) {
return contextPath.substring(0, contextPath.length() - 1);
}
return contextPath;
} public String getDisplayName() {
return this.displayName;
} public void setDisplayName(String displayName) {
this.displayName = displayName;
} public String getServletPath() {
return this.servletPath;
} public void setServletPath(String servletPath) {
Assert.notNull(servletPath, "ServletPath must not be null");
this.servletPath = servletPath;
} public Map<String, String> getContextParameters() {
return this.contextParameters;
} public Boolean isUseForwardHeaders() {
return this.useForwardHeaders;
} public void setUseForwardHeaders(Boolean useForwardHeaders) {
this.useForwardHeaders = useForwardHeaders;
} public String getServerHeader() {
return this.serverHeader;
} public void setServerHeader(String serverHeader) {
this.serverHeader = serverHeader;
} public int getMaxHttpHeaderSize() {
return this.maxHttpHeaderSize;
} public void setMaxHttpHeaderSize(int maxHttpHeaderSize) {
this.maxHttpHeaderSize = maxHttpHeaderSize;
} @Deprecated
@DeprecatedConfigurationProperty(reason = "Use dedicated property for each container.")
public int getMaxHttpPostSize() {
return this.maxHttpPostSize;
} @Deprecated
public void setMaxHttpPostSize(int maxHttpPostSize) {
this.maxHttpPostSize = maxHttpPostSize;
this.jetty.setMaxHttpPostSize(maxHttpPostSize);
this.tomcat.setMaxHttpPostSize(maxHttpPostSize);
this.undertow.setMaxHttpPostSize(maxHttpPostSize);
} protected final boolean getOrDeduceUseForwardHeaders() {
if (this.useForwardHeaders != null) {
return this.useForwardHeaders;
}
CloudPlatform platform = CloudPlatform.getActive(this.environment);
return (platform == null ? false : platform.isUsingForwardHeaders());
} public Integer getConnectionTimeout() {
return this.connectionTimeout;
} public void setConnectionTimeout(Integer connectionTimeout) {
this.connectionTimeout = connectionTimeout;
} public ErrorProperties getError() {
return this.error;
} public Session getSession() {
return this.session;
} public void setSession(Session session) {
this.session = session;
} public Ssl getSsl() {
return this.ssl;
} public void setSsl(Ssl ssl) {
this.ssl = ssl;
} public Compression getCompression() {
return this.compression;
} public JspServlet getJspServlet() {
return this.jspServlet;
} public void setJspServlet(JspServlet jspServlet) {
this.jspServlet = jspServlet;
} public Tomcat getTomcat() {
return this.tomcat;
} public Jetty getJetty() {
return this.jetty;
} public Undertow getUndertow() {
return this.undertow;
} public static class Session { /**
* Session timeout in seconds.
*/
private Integer timeout; /**
* Session tracking modes (one or more of the following: "cookie", "url", "ssl").
*/
private Set<SessionTrackingMode> trackingModes; /**
* Persist session data between restarts.
*/
private boolean persistent; /**
* Directory used to store session data.
*/
private File storeDir; private Cookie cookie = new Cookie(); public Cookie getCookie() {
return this.cookie;
} public Integer getTimeout() {
return this.timeout;
} public void setTimeout(Integer sessionTimeout) {
this.timeout = sessionTimeout;
} public Set<SessionTrackingMode> getTrackingModes() {
return this.trackingModes;
} public void setTrackingModes(Set<SessionTrackingMode> trackingModes) {
this.trackingModes = trackingModes;
} public boolean isPersistent() {
return this.persistent;
} public void setPersistent(boolean persistent) {
this.persistent = persistent;
} public File getStoreDir() {
return this.storeDir;
} public void setStoreDir(File storeDir) {
this.storeDir = storeDir;
} public static class Cookie { /**
* Session cookie name.
*/
private String name; /**
* Domain for the session cookie.
*/
private String domain; /**
* Path of the session cookie.
*/
private String path; /**
* Comment for the session cookie.
*/
private String comment; /**
* "HttpOnly" flag for the session cookie.
*/
private Boolean httpOnly; /**
* "Secure" flag for the session cookie.
*/
private Boolean secure; /**
* Maximum age of the session cookie in seconds.
*/
private Integer maxAge; public String getName() {
return this.name;
} public void setName(String name) {
this.name = name;
} public String getDomain() {
return this.domain;
} public void setDomain(String domain) {
this.domain = domain;
} public String getPath() {
return this.path;
} public void setPath(String path) {
this.path = path;
} public String getComment() {
return this.comment;
} public void setComment(String comment) {
this.comment = comment;
} public Boolean getHttpOnly() {
return this.httpOnly;
} public void setHttpOnly(Boolean httpOnly) {
this.httpOnly = httpOnly;
} public Boolean getSecure() {
return this.secure;
} public void setSecure(Boolean secure) {
this.secure = secure;
} public Integer getMaxAge() {
return this.maxAge;
} public void setMaxAge(Integer maxAge) {
this.maxAge = maxAge;
} } } public static class Tomcat { /**
* Access log configuration.
*/
private final Accesslog accesslog = new Accesslog(); /**
* Regular expression that matches proxies that are to be trusted.
*/
private String internalProxies = "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" // 10/8
+ "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" // 192.168/16
+ "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" // 169.254/16
+ "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" // 127/8
+ "172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" // 172.16/12
+ "172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|"
+ "172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}"; /**
* Header that holds the incoming protocol, usually named "X-Forwarded-Proto".
*/
private String protocolHeader; /**
* Value of the protocol header that indicates that the incoming request uses SSL.
*/
private String protocolHeaderHttpsValue = "https"; /**
* Name of the HTTP header used to override the original port value.
*/
private String portHeader = "X-Forwarded-Port"; /**
* Name of the http header from which the remote ip is extracted..
*/
private String remoteIpHeader; /**
* Tomcat base directory. If not specified a temporary directory will be used.
*/
private File basedir; /**
* Delay in seconds between the invocation of backgroundProcess methods.
*/
private int backgroundProcessorDelay = 30; // seconds /**
* Maximum amount of worker threads.
*/
private int maxThreads = 0; // Number of threads in protocol handler /**
* Minimum amount of worker threads.
*/
private int minSpareThreads = 0; // Minimum spare threads in protocol handler /**
* Maximum size in bytes of the HTTP post content.
*/
private int maxHttpPostSize = 0; // bytes /**
* Maximum size in bytes of the HTTP message header.
*/
private int maxHttpHeaderSize = 0; // bytes /**
* Whether requests to the context root should be redirected by appending a / to
* the path.
*/
private Boolean redirectContextRoot; /**
* Character encoding to use to decode the URI.
*/
private Charset uriEncoding; /**
* Maximum number of connections that the server will accept and process at any
* given time. Once the limit has been reached, the operating system may still
* accept connections based on the "acceptCount" property.
*/
private int maxConnections = 0; /**
* Maximum queue length for incoming connection requests when all possible request
* processing threads are in use.
*/
private int acceptCount = 0; /**
* Comma-separated list of additional patterns that match jars to ignore for TLD
* scanning. The special '?' and '*' characters can be used in the pattern to
* match one and only one character and zero or more characters respectively.
*/
private List<String> additionalTldSkipPatterns = new ArrayList<String>(); public int getMaxThreads() {
return this.maxThreads;
} public void setMaxThreads(int maxThreads) {
this.maxThreads = maxThreads;
} public int getMinSpareThreads() {
return this.minSpareThreads;
} public void setMinSpareThreads(int minSpareThreads) {
this.minSpareThreads = minSpareThreads;
} public int getMaxHttpPostSize() {
return this.maxHttpPostSize;
} public void setMaxHttpPostSize(int maxHttpPostSize) {
this.maxHttpPostSize = maxHttpPostSize;
} public Accesslog getAccesslog() {
return this.accesslog;
} public int getBackgroundProcessorDelay() {
return this.backgroundProcessorDelay;
} public void setBackgroundProcessorDelay(int backgroundProcessorDelay) {
this.backgroundProcessorDelay = backgroundProcessorDelay;
} public File getBasedir() {
return this.basedir;
} public void setBasedir(File basedir) {
this.basedir = basedir;
} public String getInternalProxies() {
return this.internalProxies;
} public void setInternalProxies(String internalProxies) {
this.internalProxies = internalProxies;
} public String getProtocolHeader() {
return this.protocolHeader;
} public void setProtocolHeader(String protocolHeader) {
this.protocolHeader = protocolHeader;
} public String getProtocolHeaderHttpsValue() {
return this.protocolHeaderHttpsValue;
} public void setProtocolHeaderHttpsValue(String protocolHeaderHttpsValue) {
this.protocolHeaderHttpsValue = protocolHeaderHttpsValue;
} public String getPortHeader() {
return this.portHeader;
} public void setPortHeader(String portHeader) {
this.portHeader = portHeader;
} public Boolean getRedirectContextRoot() {
return this.redirectContextRoot;
} public void setRedirectContextRoot(Boolean redirectContextRoot) {
this.redirectContextRoot = redirectContextRoot;
} public String getRemoteIpHeader() {
return this.remoteIpHeader;
} public void setRemoteIpHeader(String remoteIpHeader) {
this.remoteIpHeader = remoteIpHeader;
} public Charset getUriEncoding() {
return this.uriEncoding;
} public void setUriEncoding(Charset uriEncoding) {
this.uriEncoding = uriEncoding;
} public int getMaxConnections() {
return this.maxConnections;
} public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
} public int getAcceptCount() {
return this.acceptCount;
} public void setAcceptCount(int acceptCount) {
this.acceptCount = acceptCount;
} public List<String> getAdditionalTldSkipPatterns() {
return this.additionalTldSkipPatterns;
} public void setAdditionalTldSkipPatterns(List<String> additionalTldSkipPatterns) {
this.additionalTldSkipPatterns = additionalTldSkipPatterns;
} void customizeTomcat(ServerProperties serverProperties,
TomcatEmbeddedServletContainerFactory factory) {
if (getBasedir() != null) {
factory.setBaseDirectory(getBasedir());
}
factory.setBackgroundProcessorDelay(Tomcat.this.backgroundProcessorDelay);
customizeRemoteIpValve(serverProperties, factory);
if (this.maxThreads > 0) {
customizeMaxThreads(factory);
}
if (this.minSpareThreads > 0) {
customizeMinThreads(factory);
}
int maxHttpHeaderSize = (serverProperties.getMaxHttpHeaderSize() > 0
? serverProperties.getMaxHttpHeaderSize() : this.maxHttpHeaderSize);
if (maxHttpHeaderSize > 0) {
customizeMaxHttpHeaderSize(factory, maxHttpHeaderSize);
}
if (this.maxHttpPostSize != 0) {
customizeMaxHttpPostSize(factory, this.maxHttpPostSize);
}
if (this.accesslog.enabled) {
customizeAccessLog(factory);
}
if (getUriEncoding() != null) {
factory.setUriEncoding(getUriEncoding());
}
if (serverProperties.getConnectionTimeout() != null) {
customizeConnectionTimeout(factory,
serverProperties.getConnectionTimeout());
}
if (this.redirectContextRoot != null) {
customizeRedirectContextRoot(factory, this.redirectContextRoot);
}
if (this.maxConnections > 0) {
customizeMaxConnections(factory);
}
if (this.acceptCount > 0) {
customizeAcceptCount(factory);
}
if (!ObjectUtils.isEmpty(this.additionalTldSkipPatterns)) {
factory.getTldSkipPatterns().addAll(this.additionalTldSkipPatterns);
}
if (serverProperties.getError()
.getIncludeStacktrace() == ErrorProperties.IncludeStacktrace.NEVER) {
customizeErrorReportValve(factory);
}
} private void customizeErrorReportValve(
TomcatEmbeddedServletContainerFactory factory) {
factory.addContextCustomizers(new TomcatContextCustomizer() { @Override
public void customize(Context context) {
ErrorReportValve valve = new ErrorReportValve();
valve.setShowServerInfo(false);
valve.setShowReport(false);
context.getParent().getPipeline().addValve(valve);
} });
} private void customizeAcceptCount(TomcatEmbeddedServletContainerFactory factory) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override
@SuppressWarnings("deprecation")
public void customize(Connector connector) {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) {
AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
protocol.setBacklog(Tomcat.this.acceptCount);
}
} });
} private void customizeMaxConnections(
TomcatEmbeddedServletContainerFactory factory) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override
public void customize(Connector connector) {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) {
AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
protocol.setMaxConnections(Tomcat.this.maxConnections);
}
} });
} private void customizeConnectionTimeout(
TomcatEmbeddedServletContainerFactory factory,
final int connectionTimeout) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override
public void customize(Connector connector) {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) {
AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
protocol.setConnectionTimeout(connectionTimeout);
}
} });
} private void customizeRemoteIpValve(ServerProperties properties,
TomcatEmbeddedServletContainerFactory factory) {
String protocolHeader = getProtocolHeader();
String remoteIpHeader = getRemoteIpHeader();
// For back compatibility the valve is also enabled if protocol-header is set
if (StringUtils.hasText(protocolHeader) || StringUtils.hasText(remoteIpHeader)
|| properties.getOrDeduceUseForwardHeaders()) {
RemoteIpValve valve = new RemoteIpValve();
valve.setProtocolHeader(StringUtils.hasLength(protocolHeader)
? protocolHeader : "X-Forwarded-Proto");
if (StringUtils.hasLength(remoteIpHeader)) {
valve.setRemoteIpHeader(remoteIpHeader);
}
// The internal proxies default to a white list of "safe" internal IP
// addresses
valve.setInternalProxies(getInternalProxies());
valve.setPortHeader(getPortHeader());
valve.setProtocolHeaderHttpsValue(getProtocolHeaderHttpsValue());
// ... so it's safe to add this valve by default.
factory.addEngineValves(valve);
}
} @SuppressWarnings("rawtypes")
private void customizeMaxThreads(TomcatEmbeddedServletContainerFactory factory) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) { ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) {
AbstractProtocol protocol = (AbstractProtocol) handler;
protocol.setMaxThreads(Tomcat.this.maxThreads);
} }
});
} @SuppressWarnings("rawtypes")
private void customizeMinThreads(TomcatEmbeddedServletContainerFactory factory) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) { ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) {
AbstractProtocol protocol = (AbstractProtocol) handler;
protocol.setMinSpareThreads(Tomcat.this.minSpareThreads);
} }
});
} @SuppressWarnings("rawtypes")
private void customizeMaxHttpHeaderSize(
TomcatEmbeddedServletContainerFactory factory,
final int maxHttpHeaderSize) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override
public void customize(Connector connector) {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractHttp11Protocol) {
AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) handler;
protocol.setMaxHttpHeaderSize(maxHttpHeaderSize);
}
} });
} private void customizeMaxHttpPostSize(
TomcatEmbeddedServletContainerFactory factory,
final int maxHttpPostSize) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override
public void customize(Connector connector) {
connector.setMaxPostSize(maxHttpPostSize);
} });
} private void customizeAccessLog(TomcatEmbeddedServletContainerFactory factory) {
AccessLogValve valve = new AccessLogValve();
valve.setPattern(this.accesslog.getPattern());
valve.setDirectory(this.accesslog.getDirectory());
valve.setPrefix(this.accesslog.getPrefix());
valve.setSuffix(this.accesslog.getSuffix());
valve.setRenameOnRotate(this.accesslog.isRenameOnRotate());
valve.setRequestAttributesEnabled(
this.accesslog.isRequestAttributesEnabled());
valve.setRotatable(this.accesslog.isRotate());
valve.setBuffered(this.accesslog.isBuffered());
valve.setFileDateFormat(this.accesslog.getFileDateFormat());
factory.addEngineValves(valve);
} private void customizeRedirectContextRoot(
TomcatEmbeddedServletContainerFactory factory,
final boolean redirectContextRoot) {
factory.addContextCustomizers(new TomcatContextCustomizer() { @Override
public void customize(Context context) {
context.setMapperContextRootRedirectEnabled(redirectContextRoot);
} });
} public static class Accesslog { /**
* Enable access log.
*/
private boolean enabled = false; /**
* Format pattern for access logs.
*/
private String pattern = "common"; /**
* Directory in which log files are created. Can be relative to the tomcat
* base dir or absolute.
*/
private String directory = "logs"; /**
* Log file name prefix.
*/
protected String prefix = "access_log"; /**
* Log file name suffix.
*/
private String suffix = ".log"; /**
* Enable access log rotation.
*/
private boolean rotate = true; /**
* Defer inclusion of the date stamp in the file name until rotate time.
*/
private boolean renameOnRotate; /**
* Date format to place in log file name.
*/
private String fileDateFormat = ".yyyy-MM-dd"; /**
* Set request attributes for IP address, Hostname, protocol and port used for
* the request.
*/
private boolean requestAttributesEnabled; /**
* Buffer output such that it is only flushed periodically.
*/
private boolean buffered = true; public boolean isEnabled() {
return this.enabled;
} public void setEnabled(boolean enabled) {
this.enabled = enabled;
} public String getPattern() {
return this.pattern;
} public void setPattern(String pattern) {
this.pattern = pattern;
} public String getDirectory() {
return this.directory;
} public void setDirectory(String directory) {
this.directory = directory;
} public String getPrefix() {
return this.prefix;
} public void setPrefix(String prefix) {
this.prefix = prefix;
} public String getSuffix() {
return this.suffix;
} public void setSuffix(String suffix) {
this.suffix = suffix;
} public boolean isRotate() {
return this.rotate;
} public void setRotate(boolean rotate) {
this.rotate = rotate;
} public boolean isRenameOnRotate() {
return this.renameOnRotate;
} public void setRenameOnRotate(boolean renameOnRotate) {
this.renameOnRotate = renameOnRotate;
} public String getFileDateFormat() {
return this.fileDateFormat;
} public void setFileDateFormat(String fileDateFormat) {
this.fileDateFormat = fileDateFormat;
} public boolean isRequestAttributesEnabled() {
return this.requestAttributesEnabled;
} public void setRequestAttributesEnabled(boolean requestAttributesEnabled) {
this.requestAttributesEnabled = requestAttributesEnabled;
} public boolean isBuffered() {
return this.buffered;
} public void setBuffered(boolean buffered) {
this.buffered = buffered;
} } } public static class Jetty { /**
* Maximum size in bytes of the HTTP post or put content.
*/
private int maxHttpPostSize = 0; // bytes /**
* Number of acceptor threads to use.
*/
private Integer acceptors; /**
* Number of selector threads to use.
*/
private Integer selectors; public int getMaxHttpPostSize() {
return this.maxHttpPostSize;
} public void setMaxHttpPostSize(int maxHttpPostSize) {
this.maxHttpPostSize = maxHttpPostSize;
} public Integer getAcceptors() {
return this.acceptors;
} public void setAcceptors(Integer acceptors) {
this.acceptors = acceptors;
} public Integer getSelectors() {
return this.selectors;
} public void setSelectors(Integer selectors) {
this.selectors = selectors;
} void customizeJetty(final ServerProperties serverProperties,
JettyEmbeddedServletContainerFactory factory) {
factory.setUseForwardHeaders(serverProperties.getOrDeduceUseForwardHeaders());
if (this.acceptors != null) {
factory.setAcceptors(this.acceptors);
}
if (this.selectors != null) {
factory.setSelectors(this.selectors);
}
if (serverProperties.getMaxHttpHeaderSize() > 0) {
customizeMaxHttpHeaderSize(factory,
serverProperties.getMaxHttpHeaderSize());
}
if (this.maxHttpPostSize > 0) {
customizeMaxHttpPostSize(factory, this.maxHttpPostSize);
} if (serverProperties.getConnectionTimeout() != null) {
customizeConnectionTimeout(factory,
serverProperties.getConnectionTimeout());
}
} private void customizeConnectionTimeout(
JettyEmbeddedServletContainerFactory factory,
final int connectionTimeout) {
factory.addServerCustomizers(new JettyServerCustomizer() { @Override
public void customize(Server server) {
for (org.eclipse.jetty.server.Connector connector : server
.getConnectors()) {
if (connector instanceof AbstractConnector) {
((AbstractConnector) connector)
.setIdleTimeout(connectionTimeout);
}
}
} });
} private void customizeMaxHttpHeaderSize(
JettyEmbeddedServletContainerFactory factory,
final int maxHttpHeaderSize) {
factory.addServerCustomizers(new JettyServerCustomizer() { @Override
public void customize(Server server) {
for (org.eclipse.jetty.server.Connector connector : server
.getConnectors()) {
try {
for (ConnectionFactory connectionFactory : connector
.getConnectionFactories()) {
if (connectionFactory instanceof HttpConfiguration.ConnectionFactory) {
customize(
(HttpConfiguration.ConnectionFactory) connectionFactory);
}
}
}
catch (NoSuchMethodError ex) {
customizeOnJetty8(connector, maxHttpHeaderSize);
}
} } private void customize(HttpConfiguration.ConnectionFactory factory) {
HttpConfiguration configuration = factory.getHttpConfiguration();
configuration.setRequestHeaderSize(maxHttpHeaderSize);
configuration.setResponseHeaderSize(maxHttpHeaderSize);
} private void customizeOnJetty8(
org.eclipse.jetty.server.Connector connector,
int maxHttpHeaderSize) {
try {
connector.getClass().getMethod("setRequestHeaderSize", int.class)
.invoke(connector, maxHttpHeaderSize);
connector.getClass().getMethod("setResponseHeaderSize", int.class)
.invoke(connector, maxHttpHeaderSize);
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
} });
} private void customizeMaxHttpPostSize(
JettyEmbeddedServletContainerFactory factory, final int maxHttpPostSize) {
factory.addServerCustomizers(new JettyServerCustomizer() { @Override
public void customize(Server server) {
setHandlerMaxHttpPostSize(maxHttpPostSize, server.getHandlers());
} private void setHandlerMaxHttpPostSize(int maxHttpPostSize,
Handler... handlers) {
for (Handler handler : handlers) {
if (handler instanceof ContextHandler) {
((ContextHandler) handler)
.setMaxFormContentSize(maxHttpPostSize);
}
else if (handler instanceof HandlerWrapper) {
setHandlerMaxHttpPostSize(maxHttpPostSize,
((HandlerWrapper) handler).getHandler());
}
else if (handler instanceof HandlerCollection) {
setHandlerMaxHttpPostSize(maxHttpPostSize,
((HandlerCollection) handler).getHandlers());
}
}
} });
} } public static class Undertow { /**
* Maximum size in bytes of the HTTP post content.
*/
private long maxHttpPostSize = 0; // bytes /**
* Size of each buffer in bytes.
*/
private Integer bufferSize; /**
* Number of buffer per region.
*/
@Deprecated
private Integer buffersPerRegion; /**
* Number of I/O threads to create for the worker.
*/
private Integer ioThreads; /**
* Number of worker threads.
*/
private Integer workerThreads; /**
* Allocate buffers outside the Java heap.
*/
private Boolean directBuffers; private final Accesslog accesslog = new Accesslog(); public long getMaxHttpPostSize() {
return this.maxHttpPostSize;
} public void setMaxHttpPostSize(long maxHttpPostSize) {
this.maxHttpPostSize = maxHttpPostSize;
} public Integer getBufferSize() {
return this.bufferSize;
} public void setBufferSize(Integer bufferSize) {
this.bufferSize = bufferSize;
} @DeprecatedConfigurationProperty(reason = "The property is not used by Undertow. See https://issues.jboss.org/browse/UNDERTOW-587 for details")
public Integer getBuffersPerRegion() {
return this.buffersPerRegion;
} public void setBuffersPerRegion(Integer buffersPerRegion) {
this.buffersPerRegion = buffersPerRegion;
} public Integer getIoThreads() {
return this.ioThreads;
} public void setIoThreads(Integer ioThreads) {
this.ioThreads = ioThreads;
} public Integer getWorkerThreads() {
return this.workerThreads;
} public void setWorkerThreads(Integer workerThreads) {
this.workerThreads = workerThreads;
} public Boolean getDirectBuffers() {
return this.directBuffers;
} public void setDirectBuffers(Boolean directBuffers) {
this.directBuffers = directBuffers;
} public Accesslog getAccesslog() {
return this.accesslog;
} void customizeUndertow(final ServerProperties serverProperties,
UndertowEmbeddedServletContainerFactory factory) {
if (this.bufferSize != null) {
factory.setBufferSize(this.bufferSize);
}
if (this.ioThreads != null) {
factory.setIoThreads(this.ioThreads);
}
if (this.workerThreads != null) {
factory.setWorkerThreads(this.workerThreads);
}
if (this.directBuffers != null) {
factory.setDirectBuffers(this.directBuffers);
}
if (this.accesslog.enabled != null) {
factory.setAccessLogEnabled(this.accesslog.enabled);
}
factory.setAccessLogDirectory(this.accesslog.dir);
factory.setAccessLogPattern(this.accesslog.pattern);
factory.setAccessLogPrefix(this.accesslog.prefix);
factory.setAccessLogSuffix(this.accesslog.suffix);
factory.setAccessLogRotate(this.accesslog.rotate);
factory.setUseForwardHeaders(serverProperties.getOrDeduceUseForwardHeaders());
if (serverProperties.getMaxHttpHeaderSize() > 0) {
customizeMaxHttpHeaderSize(factory,
serverProperties.getMaxHttpHeaderSize());
}
if (this.maxHttpPostSize > 0) {
customizeMaxHttpPostSize(factory, this.maxHttpPostSize);
} if (serverProperties.getConnectionTimeout() != null) {
customizeConnectionTimeout(factory,
serverProperties.getConnectionTimeout());
}
} private void customizeConnectionTimeout(
UndertowEmbeddedServletContainerFactory factory,
final int connectionTimeout) {
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
@Override
public void customize(Builder builder) {
builder.setSocketOption(UndertowOptions.NO_REQUEST_TIMEOUT,
connectionTimeout);
}
});
} private void customizeMaxHttpHeaderSize(
UndertowEmbeddedServletContainerFactory factory,
final int maxHttpHeaderSize) {
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() { @Override
public void customize(Builder builder) {
builder.setServerOption(UndertowOptions.MAX_HEADER_SIZE,
maxHttpHeaderSize);
} });
} private void customizeMaxHttpPostSize(
UndertowEmbeddedServletContainerFactory factory,
final long maxHttpPostSize) {
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() { @Override
public void customize(Builder builder) {
builder.setServerOption(UndertowOptions.MAX_ENTITY_SIZE,
maxHttpPostSize);
} });
} public static class Accesslog { /**
* Enable access log.
*/
private Boolean enabled; /**
* Format pattern for access logs.
*/
private String pattern = "common"; /**
* Log file name prefix.
*/
protected String prefix = "access_log."; /**
* Log file name suffix.
*/
private String suffix = "log"; /**
* Undertow access log directory.
*/
private File dir = new File("logs"); /**
* Enable access log rotation.
*/
private boolean rotate = true; public Boolean getEnabled() {
return this.enabled;
} public void setEnabled(Boolean enabled) {
this.enabled = enabled;
} public String getPattern() {
return this.pattern;
} public void setPattern(String pattern) {
this.pattern = pattern;
} public String getPrefix() {
return this.prefix;
} public void setPrefix(String prefix) {
this.prefix = prefix;
} public String getSuffix() {
return this.suffix;
} public void setSuffix(String suffix) {
this.suffix = suffix;
} public File getDir() {
return this.dir;
} public void setDir(File dir) {
this.dir = dir;
} public boolean isRotate() {
return this.rotate;
} public void setRotate(boolean rotate) {
this.rotate = rotate;
} } } /**
* {@link ServletContextInitializer} to apply appropriate parts of the {@link Session}
* configuration.
*/
private static class SessionConfiguringInitializer
implements ServletContextInitializer { private final Session session; SessionConfiguringInitializer(Session session) {
this.session = session;
} @Override
public void onStartup(ServletContext servletContext) throws ServletException {
if (this.session.getTrackingModes() != null) {
servletContext.setSessionTrackingModes(this.session.getTrackingModes());
}
configureSessionCookie(servletContext.getSessionCookieConfig());
} private void configureSessionCookie(SessionCookieConfig config) {
Cookie cookie = this.session.getCookie();
if (cookie.getName() != null) {
config.setName(cookie.getName());
}
if (cookie.getDomain() != null) {
config.setDomain(cookie.getDomain());
}
if (cookie.getPath() != null) {
config.setPath(cookie.getPath());
}
if (cookie.getComment() != null) {
config.setComment(cookie.getComment());
}
if (cookie.getHttpOnly() != null) {
config.setHttpOnly(cookie.getHttpOnly());
}
if (cookie.getSecure() != null) {
config.setSecure(cookie.getSecure());
}
if (cookie.getMaxAge() != null) {
config.setMaxAge(cookie.getMaxAge());
}
} } }
在这个类里我们可以找到customizeTomcat方法,大家自行看看喽,类图如下:


  

Spring中的BeanPostProcessor的更多相关文章

  1. Spring中的BeanPostProcessor详解

    Spring中的BeanPostProcessor详解 概述 BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初 ...

  2. 谈谈Spring中的BeanPostProcessor接口

    一.前言   这几天正在复习Spring的相关内容,在了解bean的生命周期的时候,发现其中涉及到一个特殊的接口--BeanPostProcessor接口.由于网上没有找到比较好的博客,所有最后花了好 ...

  3. Spring中的BeanPostProcessor和BeanFactoryPostProcessor

    BeanPostProcessor BeanFactoryPostProcessor 标准ioc容器初始化之后的后置处理器 BeanDefintionRegisterPostProcessor 在所有 ...

  4. Spring中BeanPostProcessor

    Spring中BeanPostProcessor 前言: 本文旨在介绍Spring动态配置数据源的方式,即对一个DataSource的配置诸如jdbcUrl,user,password,driverC ...

  5. spring(三):spring中BeanPostProcessor的使用

    spring中实现BeanPostProcessor的后置处理器 ApplicationContextAwareProcessor 进入该实现类内部 可以看到:该类帮我们组建IOC容器,判断我们的be ...

  6. Spring点滴五:Spring中的后置处理器BeanPostProcessor讲解

    BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...

  7. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

  8. Spring点滴十一:Spring中BeanFactoryPostProcessor和BeanPostProcessor区别

    Spring中BeanFactoryPostProcessor和BeanPostProcessor都是Spring初始化bean时对外暴露的扩展点.两个接口从名字看起来很相似,但是作用及使用场景却不同 ...

  9. Spring中的后置处理器BeanPostProcessor讲解

    Spring中提供了很多PostProcessor供开发者进行拓展,例如:BeanPostProcessor.BeanFactoryPostProcessor.BeanValidationPostPr ...

随机推荐

  1. BZOJ 1009 [HNOI2008]GT考试 (KMP + 矩阵快速幂)

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4266  Solved: 2616[Submit][Statu ...

  2. LA 4670 Dominating Patterns (AC自动机)

    题意:给定n个字符串和一个文本串,查找哪个字符串出现的次数的最多. 析:一匹配多,很明显是AC自动机.只需要对原来的进行修改一下,就可以得到这个题的答案, 计算过程中,要更新次数,并且要映射字符串.如 ...

  3. 用Git将项目发布在GitHub里

    转载自http://blog.csdn.net/u011572517/article/details/50537407,个人加了一些注意事项和解释. githud是一个程序员以后成长都会使用到的,先不 ...

  4. C++和Python混合编程

    为何人工智能(AI)首选Python?读完这篇文章你就知道了:https://blog.csdn.net/qq_41769259/article/details/79419322 C++调用Pytho ...

  5. Win窗口坐标二维坐标与OpenGl的世界坐标系的之间的相互转换

    Win窗口坐标二维坐标与OpenGl的世界坐标系的转换 几何处理管线擅长于使用视图和投影矩阵以及用于裁剪的视口把顶点的世界坐标变换为窗口坐标. 但是,在有些情况下,需要逆转这个过程.一种常见的情形是: ...

  6. How Many Tables HDOJ

    How Many Tables Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  7. Swiper使用方法(向前和向后按钮在swiper-container外面)

    Swiper插件的使用 1.HTML <!-- Swiper --> <section class="swipper"> <div class=&qu ...

  8. 关于ListBox的几个问题

    Winfrom ListBox绑定数据源list界面不更新问题与绑定数据源不可CRUD问题 场景:获取一个listbox的选中项添加到另一个listbox中 解决方案-1:不要直接绑定DataSour ...

  9. linux系统编程之信号(二):信号处理流程(产生、注册、注销、执行)

        对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个阶段: 信号诞生 信号在进程中注册 信号在进程中的注销 信号处理函数执行 1    信号诞生     信号事件 ...

  10. DBCC--LOG

    DBCC LOGTo retrieve the transaction log for a given database.对应日志文件较大的数据库,慎用该命令Uasge:DBCC LOG(<db ...