package com.fr.start.server; import com.fr.design.DesignerEnvManager; import com.fr.log.FineLoggerFactory; import com.fr.module.Activator; import com.fr.module.ModuleRole; import com.fr.stable.EncodeConstants; import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; import com.fr.startup.FineWebApplicationInitializer; import com.fr.third.springframework.web.SpringServletContainerInitializer; import com.fr.third.springframework.web.context.support.AnnotationConfigWebApplicationContext; import com.fr.workspace.WorkContext; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.webresources.StandardRoot; import java.io.File; import java.util.HashSet; import java.util.Set; /** * Created by juhaoyu on 2018/6/5. */ public class FineEmbedServerActivator extends Activator { private static final String TOMCAT_MAX_HEADER_SIZE = "tomcat-maxHttpHeaderSize"; private Tomcat tomcat; @Override public synchronized void start() { try { FineEmbedServerMonitor.getInstance().reset(); //初始化tomcat initTomcat(); tomcat.start(); } catch (LifecycleException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } finally { FineEmbedServerMonitor.getInstance().setComplete(); } } @Override public synchronized void stop() { try { stopSpring(); stopServerActivator(); stopTomcat(); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } } private void initTomcat() { tomcat = new Tomcat(); tomcat.setPort(DesignerEnvManager.getEnvManager().getEmbedServerPort()); // 设置解码uri使用的字符编码 tomcat.getConnector().setURIEncoding(EncodeConstants.ENCODING_UTF_8); // 参考 https://jira.atlassian.com/browse/CONFSERVER-57582 // https://tomcat.apache.org/tomcat-8.5-doc/config/http.html // 8.5.x 请求参数带特殊字符被tomcat拒绝 []|{}^\`"<> tomcat.getConnector().setProperty("relaxedQueryChars", "[]|{}^\`"<>"); setMaxPostSize(); setMaxHttpHeaderSize(); String docBase = new File(WorkContext.getCurrent().getPath()).getParent(); //内置的上下文使用工程目录比如webroot String contextPath = "/" + ProductConstants.getAppFolderName(); final Context context = tomcat.addContext(contextPath, docBase); context.setResources(new StandardRoot(context)); Tomcat.initWebappDefaults(context); //覆盖tomcat的WebAppClassLoader context.setLoader(new FRTomcatLoader()); //直接指定initializer,tomcat就不用再扫描一遍了 SpringServletContainerInitializer initializer = new SpringServletContainerInitializer(); Set> classes = new HashSet>(); classes.add(FineWebApplicationInitializer.class); context.addServletContainerInitializer(initializer, classes); } // tomcat的maxPostSize会影响到post参数获取,默认2M private void setMaxPostSize() { if (System.getProperty("tomcat-maxPostSize") != null) { try { tomcat.getConnector().setMaxPostSize(Integer.parseInt(System.getProperty("tomcat-maxPostSize"))); } catch (Exception e) { FineLoggerFactory.getLogger().error("maxPostSize error: " + e.getMessage(), e); } } } private void setMaxHttpHeaderSize() { String value = System.getProperty(TOMCAT_MAX_HEADER_SIZE); if (StringUtils.isNotEmpty(value)) { try { tomcat.getConnector().setProperty("maxHttpHeaderSize", value); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } } } private void stopServerActivator() { ModuleRole.ServerRoot.stop(); } private void stopSpring() { AnnotationConfigWebApplicationContext context = ModuleRole.ServerRoot.findSingleton(AnnotationConfigWebApplicationContext.class); if (context != null) { context.stop(); context.destroy(); } } private void stopTomcat() throws LifecycleException { tomcat.stop(); tomcat.destroy(); } /** * Created by juhaoyu on 2018/6/5. * 自定义的tomcat loader,主要用于防止内置服务器再加载一遍class */ private static class FRTomcatLoader extends WebappLoader { @Override public ClassLoader getClassLoader() { return this.getClass().getClassLoader(); } } }