当前位置: 首页 > news >正文

门户网站属于数字媒体吗学做企业网站

门户网站属于数字媒体吗,学做企业网站,个人怎么做淘宝客网站,网站建设实践报告SpringBoot 嵌入了 Web 容器如 Tomcat/Jetty/Undertow#xff0c;——这是怎么做到的#xff1f;我们以 Tomcat 为例子#xff0c;尝试调用嵌入式 Tomcat。 调用嵌入式 Tomcat#xff0c;如果按照默认去启动#xff0c;一个 main 函数就可以了。 简单的例子 下面是启动…SpringBoot 嵌入了 Web 容器如 Tomcat/Jetty/Undertow——这是怎么做到的我们以 Tomcat 为例子尝试调用嵌入式 Tomcat。 调用嵌入式 Tomcat如果按照默认去启动一个 main 函数就可以了。 简单的例子 下面是启动 Tomcat 的一个简单例子。 Tomcat tomcat new Tomcat(); tomcat.enableNaming(); tomcat.getHost().setAutoDeploy(false); tomcat.getHost().setAppBase(webapp); // 在对应的 host 下面创建一个 context 并制定他的工作路径,会加载该目录下的所有 class 文件,或者静态文件 // tomcat.setBaseDir(Thread.currentThread().getContextClassLoader().getResource().getPath()); // 设置 tomcat 启动后的工作目录 // System.out.println(Thread.currentThread().getContextClassLoader().getResource().getPath());// 读取项目路径 System.out.println(System.getProperty(user.dir)); String jspDir System.getProperty(user.dir); StandardContext ctx (StandardContext) tomcat.addWebapp(/, new File(jspDir).getAbsolutePath()); ctx.setReloadable(false);// 禁止重新载入 WebResourceRoot resources new StandardRoot(ctx);// 创建WebRoot resources.addPreResources(new DirResourceSet(resources, /WEB-INF/classes, new File(target/classes).getAbsolutePath(), /));// tomcat 内部读取 Class 执行// 创建连接器并且添加对应的连接器同时连接器指定端口 设置 IO 协议 Connector connector new Connector(org.apache.coyote.http11.Http11NioProtocol); connector.setPort(port); connector.setThrowOnFailure(true);tomcat.getService().addConnector(connector);// 只能设置一个 service,直接拿默认的 tomcat.setConnector(connector); // 设置执行器try {tomcat.start(); // tomcat 启动 } catch (LifecycleException e) {throw new RuntimeException(e); }tomcat.getServer().await(); // 保持主线程不退出让其阻塞不让当前线程结束等待处理请求配置化你的 Tomcat 当然我们不会满足于默认的 Tomcat 配置。Tomcat 本身提供开放的配置选项一般是 server.xml 或 web.xml 的形式而换到嵌入式 Tomcat 的话那些 xml 配置则不可用了于是我们得采取手动编码Programmatically在 Java 完成配置。 面对众多的 Tomcat 配置我们选出下面若干最常见的。 import lombok.Data; import org.springframework.util.StringUtils;/*** Tomcat 配置参数*/ Data public class TomcatConfig {/*** 主机名称*/private String hostName localhost;/*** 访问的端口*/private Integer port 8082;/*** Web 上下文目录*/private String contextPath;/*** Web 目录的磁盘路径如 D:/1sync/static*/private String docBase;/*** Tomcat 临时文件的目录*/private String tomcatBaseDir;/*** 关闭的端口*/private Integer shutdownPort 8005;/*** 是否激活 SSI服务器端嵌入*/private Boolean enableSsi false;/*** 是否激活 JSP*/private Boolean enableJsp true;/*** 是否激活 JMX 监控*/private boolean enableJMX false;/*** 自定义连接器*/private boolean customerConnector false;/*** 最大工作线程数 Maximum amount of worker threads.*/private int maxThreads 0;/*** 最小工作线程数默认是 10。Minimum amount of worker threads. if not set, default value is 10*/private int minSpareThreads 0;/*** 当客户端从 Tomcat 获取数据时候距离关闭连接的等待时间* When Tomcat expects data from the client, this is the time Tomcat will wait for that data to arrive before closing the connection.*/private int connectionTimeout 0;/*** 最大连接数* 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;/*** Tomcat 临时文件的目录。如果不需要如不需要 jsp禁止 work dir。* Tomcat needs a directory for temp files. This should be the first method called.** p* By default, if this method is not called, we use:* ul* lisystem properties - catalina.base, catalina.home/li* li$PWD/tomcat.$PORT/li* /ul* (/tmp doesnt seem a good choice for security).** p* TODO: disable work dir if not needed ( no jsp, etc ).*/public void setTomcatBaseDir(String tomcatBaseDir) {this.tomcatBaseDir tomcatBaseDir;}public String getContextPath() {return StringUtils.hasText(contextPath) ? contextPath : ;} }hostName 主机名称、port 端口这些大家应该都知道就不多说了。其他有关配置说明如下 Web 上下文目录 contextPath。就是第一级的目录你可以不设但不要设为/否则会有警告设为空字符串就好。一般都加上。Web 目录的磁盘路径 docBase就是 WebRoot 对应的磁盘目录如 D:/1sync/static浏览器可以访问这里的静态文件和 JSP 文件等。Tomcat 临时文件的目录tomcatBaseDir。可不设默认system properties - catalina.base, catalina.home或$PWD/tomcat.$PORT。如果不需要运行 JSP或者可以禁止该目录enableSsi 是否激活 SSI服务器端嵌入关闭的端口 shutdownPort。可以通过 Socket 关闭 tomcattelnet 127.0.0.1 8005输入SHUTDOWN字符串后面有介绍方法是否激活 JSP enableJsp是否激活 JMX 监控 enableJMX。用于 JMX 监控关闭会提高启动速度其他并发的性能调优 maxThreads、minSpareThreads、connectionTimeout、maxConnections、acceptCount 启动 Tomcat 有了配置自然可以启动 Tomcat我们把TomcatConfig作为构造器参数传给TomcatStarter解析各个参数去配置 Tomcat 最终启动。 如下是按照默认参数启动。 TomcatConfig cfg new TomcatConfig(); TomcatStarter t new TomcatStarter(cfg); t.start();另外补充一下两个配置的地方 禁止 Tomcat 自动扫描 jar 包会提高启动速度Tomcat 的 startStopThreads 属性用于配置 Tomcat 服务器启动和关闭时的线程池大小。它决定了 Tomcat 在启动和关闭过程中能够同时处理的任务数。但对于 Tomcat 8没有直接的编程方式来设置 startStopThreads 属性下面设置设置核心线程数和最大线程数又不会走到这里这是悬而未决的问题 完整TomcatStarter源码如下。 import com.ajaxjs.Version; import com.ajaxjs.framework.embeded_tomcat.jar_scan.EmbededContextConfig; import com.ajaxjs.util.io.FileHelper; import com.ajaxjs.util.io.Resources; import com.ajaxjs.util.logger.LogHelper; import org.apache.catalina.*; import org.apache.catalina.WebResourceRoot.ResourceSetType; import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.webresources.DirResourceSet; import org.apache.catalina.webresources.StandardRoot; import org.apache.coyote.AbstractProtocol; import org.apache.coyote.ProtocolHandler; import org.apache.tomcat.util.descriptor.web.FilterDef; import org.apache.tomcat.util.descriptor.web.FilterMap; import org.apache.tomcat.util.scan.StandardJarScanFilter;import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import javax.servlet.Filter; import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.net.MalformedURLException; import java.net.URL; import java.rmi.registry.LocateRegistry; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor;/*** Tomcat 的功能*/ public class TomcatStarter {private static final LogHelper LOGGER LogHelper.getLog(TomcatStarter.class);public TomcatStarter(TomcatConfig cfg) {this.cfg cfg;}TomcatConfig cfg;Tomcat tomcat;/*** 获取监控信息用*/public static Tomcat TOMCAT;Context context;public static long startedTime;public static long springTime;public void start() {startedTime System.currentTimeMillis();initTomcat();initConnector();initContext();runTomcat();}private void initTomcat() {tomcat new Tomcat();tomcat.setPort(cfg.getPort());tomcat.setHostname(cfg.getHostName());tomcat.enableNaming();// String tomcatBaseDir cfg.getTomcatBaseDir(); // // if (tomcatBaseDir null) // tomcatBaseDir TomcatUtil.createTempDir(tomcat_embed_works_tmpdir).getAbsolutePath(); // // tomcat.setBaseDir(tomcatBaseDir);TOMCAT tomcat;}private void runTomcat() {try {tomcat.start(); // tomcat 启动} catch (LifecycleException e) {LOGGER.warning(e);throw new RuntimeException(e);}Runtime.getRuntime().addShutdownHook(new Thread(() - {try {LOGGER.info(关闭 Tomcat);tomcat.destroy();} catch (LifecycleException e) {LOGGER.warning(e);}}));// ac.register(clz); // ac.refresh(); // ac.registerShutdownHook();String tpl Web 服务启动完毕。Spring 耗时%sms总耗时%sms 127.0.0.1: cfg.getPort() cfg.getContextPath();tpl String.format(tpl, springTime, System.currentTimeMillis() - startedTime);LOGGER.info(tpl);// 注册关闭端口以进行关闭// 可以通过Socket关闭tomcat telnet 127.0.0.1 8005输入SHUTDOWN字符串tomcat.getServer().setPort(cfg.getShutdownPort());tomcat.getServer().await(); // 保持主线程不退出让其阻塞不让当前线程结束等待处理请求LOGGER.info(正在关闭 Tomcatshutdown......);try {tomcat.stop();} catch (LifecycleException e) {LOGGER.warning(e);}// 删除 tomcat 临时路径 // TomcatUtil.deleteAllFilesOfDir(tomcatBaseDirFile);}/*** 读取项目路径*/private void initContext() {String jspFolder getDevelopJspFolder();if (jspFolder null) {jspFolder Resources.getJarDir() /../webapp; // 部署阶段。这个并不会实际保存 jsp。因为 jsp 都在 META-INF/resources 里面。但因为下面的 addWebapp() 又需要FileHelper.mkDir(jspFolder);}// System.out.println(jspFolder:::::: Resources.getJarDir()); // StandardContext ctx (StandardContext) tomcat.addWebapp(/, new File(/mycar/mycar-service-4.0/security-oauth2-uam/sync/jsp).getAbsolutePath()); // context tomcat.addWebapp(contextPath, jspFolder);Host host tomcat.getHost();host.setAutoDeploy(false);host.setAppBase(webapp);context tomcat.addWebapp(host, cfg.getContextPath(), jspFolder, (LifecycleListener) new EmbededContextConfig());context.setReloadable(false);// 禁止重新载入context.addLifecycleListener(new Tomcat.FixContextListener());// required if you dont use web.xml// seems not workWebResourceRoot resources new StandardRoot(context);// 创建 WebRootString classDir new File(target/classes).getAbsolutePath();resources.addPreResources(new DirResourceSet(resources, /WEB-INF/classes, classDir, /));// tomcat 内部读取 Class 执行if (cfg.getEnableSsi())ssi();if (!cfg.getEnableJsp())disableJsp();// context.setJarScanner(new EmbeddedStandardJarScanner()); // context.setParentClassLoader(TomcatStarter.class.getClassLoader());// needs?addWebXmlMountListener();setTomcatDisableScan(); // initFilterByTomcat(UTF8CharsetFilter.class);}public static String getDevelopJspFolder() {return Resources.getResourcesFromClasspath(META-INF\\resources);// 开放调试阶段直接读取源码的}/*** 禁止 Tomcat 自动扫描 jar 包那样会很慢*/private void setTomcatDisableScan() {StandardJarScanFilter filter (StandardJarScanFilter) context.getJarScanner().getJarScanFilter();filter.setDefaultTldScan(false);/** 这个对启动 tomcat 时间影响很大 又 很多 Servlet 3.0 新特性不能禁掉比如在 jar 里面放* jsp部署时候就会这样但开放阶段不用。 故用 isDebug 判断下*/if (Version.isDebug)filter.setDefaultPluggabilityScan(false); // String oldTldSkip filter.getTldSkip(); // System.out.println(------- oldTldSkip); // String newTldSkip oldTldSkip null || oldTldSkip.trim().isEmpty() ? pdq.jar : oldTldSkip ,pdq.jar; // filter.setTldSkip(newTldSkip);}/*** 设置 Connector*/void initConnector() {Connector connector;if (cfg.isCustomerConnector()) {// 创建连接器并且添加对应的连接器同时连接器指定端口 设置 IO 协议connector new Connector(org.apache.coyote.http11.Http11NioProtocol);connector.setPort(cfg.getPort());connector.setThrowOnFailure(true);tomcat.getService().addConnector(connector);// 只能设置一个 service,直接拿默认的tomcat.setConnector(connector); // 设置执行器} elseconnector tomcat.getConnector();connector.setURIEncoding(UTF-8); // 设置 URI 编码支持中文ProtocolHandler handler connector.getProtocolHandler();// 设置 Tomcat 配置if (handler instanceof AbstractProtocol) {AbstractProtocol? protocol (AbstractProtocol?) handler;if (cfg.getMinSpareThreads() 0)protocol.setMinSpareThreads(cfg.getMinSpareThreads());if (cfg.getMaxThreads() 0)protocol.setMaxThreads(cfg.getMaxThreads());if (cfg.getConnectionTimeout() 0)protocol.setConnectionTimeout(cfg.getConnectionTimeout());if (cfg.getMaxConnections() 0)protocol.setMaxConnections(cfg.getMaxConnections());if (cfg.getAcceptCount() 0)protocol.setAcceptCount(cfg.getAcceptCount());}// Tomcat 的 startStopThreads 属性用于配置 Tomcat 服务器启动和关闭时的线程池大小。它决定了 Tomcat 在启动和关闭过程中能够同时处理的任务数。// 对于 Tomcat 8没有直接的编程方式来设置 startStopThreads 属性Executor executor handler.getExecutor();if (executor instanceof ThreadPoolExecutor) {// doesnt workThreadPoolExecutor threadPoolExecutor (ThreadPoolExecutor) executor;threadPoolExecutor.setCorePoolSize(3);// 设置核心线程数和最大线程数threadPoolExecutor.setMaximumPoolSize(3);}if (cfg.isEnableJMX()) {Connector jmxConnector new Connector(org.apache.coyote.jmx.JmxProtocol);jmxConnector.setPort(8999); // Set the desired JMX porttomcat.getService().addConnector(jmxConnector);}}/*** context load WEB-INF/web.xml from classpath*/void addWebXmlMountListener() {context.addLifecycleListener(event - {if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {Context context (Context) event.getLifecycle();WebResourceRoot resources context.getResources();if (resources null) {resources new StandardRoot(context);context.setResources(resources);}/** When run as embedded tomcat, context.getParentClassLoader() is AppClassLoader,so it can load WEB-INF/web.xml from app classpath.*/URL resource context.getParentClassLoader().getResource(WEB-INF/web.xml);if (resource ! null) {String webXmlUrlString resource.toString();try {URL root new URL(webXmlUrlString.substring(0, webXmlUrlString.length() - WEB-INF/web.xml.length()));resources.createWebResourceSet(ResourceSetType.RESOURCE_JAR, /WEB-INF, root, /WEB-INF);} catch (MalformedURLException e) {LOGGER.warning(e);}}}});}/*** 禁用 JSP*/void disableJsp() {LifecycleListener tmplf null;for (LifecycleListener lfl : context.findLifecycleListeners()) {if (lfl instanceof Tomcat.DefaultWebXmlListener) {tmplf lfl;break;}}if (tmplf ! null)context.removeLifecycleListener(tmplf);context.addLifecycleListener(event - {if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) {Context context (Context) event.getLifecycle();Tomcat.initWebappDefaults(context);// 去掉JSPcontext.removeServletMapping(*.jsp);context.removeServletMapping(*.jspx);context.removeChild(context.findChild(jsp));}});}/*** 在 Tomcat 初始化阶段设置 Filter*/SuppressWarnings(unused)private void initFilterByTomcat(Class? extends Filter filterClz) {FilterDef filter1definition new FilterDef();filter1definition.setFilterName(filterClz.getSimpleName());filter1definition.setFilterClass(filterClz.getName());context.addFilterDef(filter1definition);FilterMap filter1mapping new FilterMap();filter1mapping.setFilterName(filterClz.getSimpleName());filter1mapping.addURLPattern(/*);context.addFilterMap(filter1mapping);}/*** 将定义好的 Tomcat MBean 注册到 MBeanServer* 参见 a hrefhttps://blog.csdn.net/zhangxin09/article/details/132136748.../a*/private static void connectMBeanServer() {try {LocateRegistry.createRegistry(9011); //这个步骤很重要注册一个端口绑定url 后用于客户端通过 rmi 方式连接 JMXConnectorServerJMXConnectorServer cs JMXConnectorServerFactory.newJMXConnectorServer(new JMXServiceURL(service:jmx:rmi://localhost/jndi/rmi://localhost:9011/jmxrmi), null, ManagementFactory.getPlatformMBeanServer() // 获取当前 JVM 的 MBeanServerObjectName 是 MBean 的唯一标示一个 MBeanServer 不能有重复。// 完整的格式「自定义命名空间:type自定义类型,name自定义名称」。当然你可以只声明 type 不声明 name);cs.start();LOGGER.info(成功启动 JMXConnectorServer);} catch (IOException e) {LOGGER.warning(e);}}/*** SSI服务器端嵌入*/void ssi() {context.setPrivileged(true);Wrapper servlet Tomcat.addServlet(context, ssi, org.apache.catalina.ssi.SSIServlet);servlet.addInitParameter(buffered, 1);servlet.addInitParameter(inputEncoding, UTF-8);servlet.addInitParameter(outputEncoding, UTF-8);servlet.addInitParameter(debug, 0);servlet.addInitParameter(expires, 666);servlet.addInitParameter(isVirtualWebappRelative, 4);servlet.setLoadOnStartup(4);servlet.setOverridable(true);// Servlet mappingscontext.addServletMappingDecoded(*.html, ssi);context.addServletMappingDecoded(*.shtml, ssi);} }无非就是按部就班地执行如下 增强特性 下面特性好像用处不大大家视情况加入。 EmbededContextConfig 扫描包含 web-fragment.xml 文件的 JAR 文件以查看它们是否还包含静态资源并将其添加到上下文中。 如果找到静态资源则按照 web-fragment.xml 的优先级顺序添加。 import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.util.Set;import org.apache.catalina.WebResourceRoot; import org.apache.catalina.startup.ContextConfig; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.descriptor.web.WebXml; import org.apache.tomcat.Jar; import org.apache.tomcat.util.scan.JarFactory;/*** Support jar in jar. when boot by spring boot loader, jar url will be: fat.jar!/lib/!/test.jar!/ .*/ public class EmbededContextConfig extends ContextConfig {private static final Log log LogFactory.getLog(EmbededContextConfig.class);/*** 扫描包含 web-fragment.xml 文件的 JAR 文件以查看它们是否还包含静态资源并将其添加到上下文中。* 如果找到静态资源则按照 web-fragment.xml 的优先级顺序添加。* Scan JARs that contain web-fragment.xml files that will be used to* configure this application to see if they also contain static resources. If static resources are found,* add them to the context. Resources are added in web-fragment.xml priority order.*/Overrideprotected void processResourceJARs(SetWebXml fragments) {for (WebXml fragment : fragments) {URL url fragment.getURL();String urlString url.toString();// Its a nested jar, but we now dont want the suffix// because Tomcat is going to try and locate it as a root URL (not the resource inside it)if (isInsideNestedJar(urlString))urlString urlString.substring(0, urlString.length() - 2);try {url new URL(urlString);if (jar.equals(url.getProtocol())) {try (Jar jar JarFactory.newInstance(url)) {jar.nextEntry();String entryName jar.getEntryName();while (entryName ! null) {if (entryName.startsWith(META-INF/resources/)) {context.getResources().createWebResourceSet(WebResourceRoot.ResourceSetType.RESOURCE_JAR,/, url, /META-INF/resources);break;}jar.nextEntry();entryName jar.getEntryName();}}} else if (file.equals(url.getProtocol())) {File file new File(url.toURI());File resources new File(file, META-INF/resources/);if (resources.isDirectory())context.getResources().createWebResourceSet(WebResourceRoot.ResourceSetType.RESOURCE_JAR, /,resources.getAbsolutePath(), null, /);}} catch (IOException | URISyntaxException ioe) {log.error(sm.getString(contextConfig.resourceJarFail, url, context.getName()));}}}private static boolean isInsideNestedJar(String dir) {return dir.indexOf(!/) dir.lastIndexOf(!/);} }使用方式 context tomcat.addWebapp(host, cfg.getContextPath(), jspFolder, (LifecycleListener) new EmbededContextConfig());EmbeddedStandardJarScanner 老实说我也不太懂用来干嘛的。先记着 import java.io.File; import java.io.IOException; import java.net.JarURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.net.URLConnection; import java.util.HashSet; import java.util.Iterator; import java.util.Set;import javax.servlet.ServletContext;import lombok.Data; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.JarScanFilter; import org.apache.tomcat.JarScanType; import org.apache.tomcat.JarScanner; import org.apache.tomcat.JarScannerCallback; import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.descriptor.web.FragmentJarScannerCallback; import org.apache.tomcat.util.res.StringManager; import org.apache.tomcat.util.scan.Constants; import org.apache.tomcat.util.scan.JarFileUrlJar; import org.apache.tomcat.util.scan.StandardJarScanFilter; import org.apache.tomcat.util.scan.UrlJar;/*** When boot by SpringBoot loader, WebappClassLoader.getParent() is LaunchedURLClassLoader,* Just need to scan WebappClassLoader and LaunchedURLClassLoader.* When boot in IDE, WebappClassLoader.getParent() is AppClassLoader,* Just need to scan WebappClassLoader and AppClassLoader.*/ Data public class EmbeddedStandardJarScanner implements JarScanner {private static final Log log LogFactory.getLog(EmbeddedStandardJarScanner.class);/*** The string resources for this package.*/private static final StringManager sm StringManager.getManager(Constants.Package);/*** Controls the classpath scanning extension.*/private boolean scanClassPath true;/*** Controls the testing all files to see of they are JAR files extension.*/private boolean scanAllFiles false;/*** Controls the testing all directories to see of they are exploded JAR* files extension.*/private boolean scanAllDirectories false;/*** Controls the testing of the bootstrap classpath which consists of the* runtime classes provided by the JVM and any installed system extensions.*/private boolean scanBootstrapClassPath false;/*** Controls the filtering of the results from the scan for JARs*/private JarScanFilter jarScanFilter new StandardJarScanFilter();Overridepublic JarScanFilter getJarScanFilter() {return jarScanFilter;}Overridepublic void setJarScanFilter(JarScanFilter jarScanFilter) {this.jarScanFilter jarScanFilter;}/*** Scan the provided ServletContext and class loader for JAR files. Each JAR* file found will be passed to the callback handler to be processed.** param scanType The type of JAR scan to perform. This is passed to the filter which uses it to determine how to filter the results* param context The ServletContext - used to locate and access WEB-INF/lib* param callback The handler to process any JARs found*/Overridepublic void scan(JarScanType scanType, ServletContext context, JarScannerCallback callback) {if (log.isTraceEnabled())log.trace(sm.getString(jarScan.webinflibStart));SetURL processedURLs new HashSet();// Scan WEB-INF/libSetString dirList context.getResourcePaths(Constants.WEB_INF_LIB);if (dirList ! null) {IteratorString it dirList.iterator();while (it.hasNext()) {String path it.next();if (path.endsWith(Constants.JAR_EXT) getJarScanFilter().check(scanType, path.substring(path.lastIndexOf(/) 1))) {// Need to scan this JARif (log.isDebugEnabled())log.debug(sm.getString(jarScan.webinflibJarScan, path));URL url null;try {url context.getResource(path);processedURLs.add(url);process(scanType, callback, url, path, true);} catch (IOException e) {log.warn(sm.getString(jarScan.webinflibFail, url), e);}} else if (log.isTraceEnabled())log.trace(sm.getString(jarScan.webinflibJarNoScan, path));}}// Scan WEB-INF/classesif (isScanAllDirectories()) {try {URL url context.getResource(/WEB-INF/classes/META-INF);if (url ! null) {// Class path scanning will look at WEB-INF/classes since that is the URL that Tomcats web application class// loader returns. Therefore, it is this URL that needs to be added to the set of processed URLs.URL webInfURL context.getResource(/WEB-INF/classes);if (webInfURL ! null)processedURLs.add(webInfURL);try {callback.scanWebInfClasses();} catch (IOException e) {log.warn(sm.getString(jarScan.webinfclassesFail), e);}}} catch (MalformedURLException e) {// Ignore}}// Scan the classpathif (isScanClassPath()) {if (log.isTraceEnabled())log.trace(sm.getString(jarScan.classloaderStart));ClassLoader classLoader context.getClassLoader();ClassLoader stopLoader null;if (classLoader.getParent() ! null) {// there are two cases:// 1. boot by SpringBoot loader// 2. boot in IDE// in two case, just need to scan WebappClassLoader and// WebappClassLoader.getParent()stopLoader classLoader.getParent().getParent();}// JARs are treated as application provided until the common class// loader is reached.boolean isWebapp true;while (classLoader ! null classLoader ! stopLoader) {if (classLoader instanceof URLClassLoader) {URL[] urls ((URLClassLoader) classLoader).getURLs();for (URL url : urls) {if (processedURLs.contains(url))continue;// Skip this URL it has already been processedClassPathEntry cpe new ClassPathEntry(url);// JARs are scanned unless the filter says not to.// Directories are scanned for pluggability scans or if scanAllDirectories is enabled unless the filter says not to.if ((cpe.isJar() || scanType JarScanType.PLUGGABILITY || isScanAllDirectories()) getJarScanFilter().check(scanType, cpe.getName())) {if (log.isDebugEnabled())log.debug(sm.getString(jarScan.classloaderJarScan, url));try {process(scanType, callback, url, null, isWebapp);} catch (IOException ioe) {log.warn(sm.getString(jarScan.classloaderFail, url), ioe);}} else {// JAR / directory has been skippedif (log.isTraceEnabled())log.trace(sm.getString(jarScan.classloaderJarNoScan, url));}}}classLoader classLoader.getParent();}}}private boolean nestedJar(String url) {int idx url.indexOf(.jar!);int idx2 url.lastIndexOf(.jar!);return idx ! idx2;}/** Scan a URL for JARs with the optional extensions to look at all files and all directories.*/private void process(JarScanType scanType, JarScannerCallback callback, URL url, String webappPath, boolean isWebapp) throws IOException {if (log.isTraceEnabled())log.trace(sm.getString(jarScan.jarUrlStart, url));URLConnection conn url.openConnection();String urlStr url.toString();if (conn instanceof JarURLConnection) {System.out.println(-----scan UrlJar: urlStr);if (nestedJar(urlStr) !(callback instanceof FragmentJarScannerCallback)) {//JarFileUrlNestedJar.scanTest(new UrlJar(conn.getURL()), webappPath, isWebapp);//callback.scan(new JarFileUrlNestedJar(conn.getURL()), webappPath, isWebapp);} elsecallback.scan(new UrlJar(conn.getURL()), webappPath, isWebapp);// callback.scan((JarURLConnection) conn, webappPath, isWebapp);} else {System.out.println(-----scan: urlStr);if (urlStr.startsWith(file:) || urlStr.startsWith(http:) || urlStr.startsWith(https:)) {if (urlStr.endsWith(Constants.JAR_EXT)) { // URL jarURL new URL(jar: urlStr !/); // callback.scan((JarURLConnection) jarURL.openConnection(), webappPath, isWebapp); // System.out.println(----- jarURL); // callback.scan(new UrlJar(jarURL), webappPath, isWebapp);callback.scan(new JarFileUrlJar(url, false), webappPath, isWebapp);} else {File f;try {f new File(url.toURI());if (f.isFile() isScanAllFiles()) {// 把这个文件当作 JAR 包 Treat this file as a JARURL jarURL new URL(jar: urlStr !/); // callback.scan((JarURLConnection) jarURL.openConnection(), webappPath, isWebapp);callback.scan(new UrlJar(jarURL), webappPath, isWebapp);} else if (f.isDirectory()) {if (scanType JarScanType.PLUGGABILITY)callback.scan(f, webappPath, isWebapp);else {File metaInf new File(f.getAbsoluteFile() File.separator META-INF);if (metaInf.isDirectory())callback.scan(f, webappPath, isWebapp);}}} catch (Throwable t) {ExceptionUtils.handleThrowable(t);// Wrap the exception and re-throwIOException ioe new IOException();ioe.initCause(t);throw ioe;}}}}} }ClassPathEntry import java.net.URL;import org.apache.tomcat.util.scan.Constants;public class ClassPathEntry {private final boolean jar;private final String name;public ClassPathEntry(URL url) {String path url.getPath();int end path.indexOf(Constants.JAR_EXT);if (end ! -1) {jar true;int start path.lastIndexOf(/, end);name path.substring(start 1, end 4);} else {jar false;if (path.endsWith(/))path path.substring(0, path.length() - 1);int start path.lastIndexOf(/);name path.substring(start 1);}}public boolean isJar() {return jar;}public String getName() {return name;} }JarFileUrlNestedJar import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile;import org.apache.tomcat.Jar; import org.apache.tomcat.util.scan.AbstractInputStreamJar; import org.apache.tomcat.util.scan.JarFactory; import org.apache.tomcat.util.scan.NonClosingJarInputStream;/*** 这是一个实现了 {link org.apache.tomcat.Jar} 接口的类针对基于文件的 JAR URL 进行了优化* 这些 URL 引用了 WAR 内部嵌套的 JAR 文件例如形如 jar:file: ... .war!/ ... .jar 的 URL* Implementation of {link org.apache.tomcat.Jar} that is optimised for file* based JAR URLs that refer to a JAR file nested inside a WAR (e.g. URLs of the form jar:file: ... .war!/ ... .jar).*/ public class JarFileUrlNestedJar extends AbstractInputStreamJar {private final JarFile warFile;private final JarEntry jarEntry;public JarFileUrlNestedJar(URL url) throws IOException {super(url);JarURLConnection jarConn (JarURLConnection) url.openConnection();jarConn.setUseCaches(false);warFile jarConn.getJarFile();String urlAsString url.toString();int pathStart urlAsString.indexOf(!/) 2;String jarPath urlAsString.substring(pathStart);System.out.println( jarPath);jarEntry warFile.getJarEntry(jarPath);EnumerationJarEntry ens warFile.entries();while (ens.hasMoreElements()) {JarEntry e ens.nextElement();System.out.println(e.getName());}}Overridepublic void close() {closeStream();if (warFile ! null) {try {warFile.close();} catch (IOException ignored) {}}}Overrideprotected NonClosingJarInputStream createJarInputStream() throws IOException {return new NonClosingJarInputStream(warFile.getInputStream(jarEntry));}private static final String TLD_EXT .tld;public static void scanTest(Jar jar, String webappPath, boolean isWebapp) throws IOException {URL jarFileUrl jar.getJarFileURL();System.out.println(xxxx------ jarFileUrl.toString());jar.nextEntry();for (String entryName jar.getEntryName(); entryName ! null; jar.nextEntry(), entryName jar.getEntryName()) {if (!(entryName.startsWith(META-INF/) entryName.endsWith(TLD_EXT)))continue;URL entryUrl JarFactory.getJarEntryURL(jarFileUrl, entryName);System.out.println(entryName : entryUrl);entryUrl.openStream();}} }使用方式 context.setJarScanner(new EmbeddedStandardJarScanner());关闭 Tomcat 可以通过 Socket 关闭 tomcat telnet 127.0.0.1 8005输入 SHUTDOWN 字符串。 import java.io.*; import java.net.Socket;/*** 可以通过 Socket 关闭 tomcat telnet 127.0.0.1 8005输入 SHUTDOWN 字符串*/ public class TomcatUtil {public static void shutdown() {shutdown(localhost, 8005);}public static void shutdown(String serverHost, Integer serverPort) {send(SHUTDOWN, serverHost, serverPort);}/*** 小型 Socket 客户端*/public static String send(String msg, String host, int port) {try (Socket socket new Socket(host, port);BufferedOutputStream out new BufferedOutputStream(socket.getOutputStream())) {out.write(msg.getBytes());out.flush();socket.shutdownOutput();String ackMsg socketRead(socket);socket.shutdownInput();System.out.println([ System.currentTimeMillis() ] Reply from server host : port : );System.out.println(\t ackMsg);return ackMsg;} catch (IOException e) {e.printStackTrace();return null;}}static String socketRead(Socket socket) throws IOException {socket.setSoTimeout(5000);int byteCount 0;char[] buffer new char[4096];int bytesRead;try (InputStreamReader in new InputStreamReader(socket.getInputStream()); StringWriter out new StringWriter()) {while ((bytesRead in.read(buffer)) ! -1) {out.write(buffer, 0, bytesRead);byteCount bytesRead;} // out.flush();return out.toString();}}public static File createTempDir(String folderName) {File tmpdir new File(System.getProperty(java.io.tmpdir));tmpdir new File(tmpdir, folderName);if (!tmpdir.exists())tmpdir.mkdir();return tmpdir;}public static File createTempDir(String prefix, int port) {File tempDir;try {tempDir File.createTempFile(prefix ., . port);} catch (IOException e) {throw new RuntimeException(e);}tempDir.delete();tempDir.mkdir();tempDir.deleteOnExit();return tempDir;}public static void deleteAllFilesOfDir(File path) {if (!path.exists())return;try {if (path.isFile()) {java.nio.file.Files.delete(path.toPath());return;}File[] files path.listFiles();assert files ! null;for (File file : files) deleteAllFilesOfDir(file);java.nio.file.Files.delete(path.toPath());} catch (IOException e) {throw new RuntimeException(e);}} }整合 SpringMVC 本文只是讨论纯 Tomcat 的启动关于整合 Spring 我在另外一篇文章中介绍《轻量级仿 SpringBoot嵌入式 TomcatSpringMVC》。 参考 仿SpringBoot的启动方式
http://www.tj-hxxt.cn/news/226461.html

相关文章:

  • 网站建设的摘要wordpress 禁用评论
  • 超星网站开发实战答案凌云网招聘信息
  • 搭建好网站如何使用h5案例分享平台
  • 大型网站 解决方案 技术怎么做打码网站
  • 关于化妆品网站成功案例网站木马 代码
  • 网站上点击图片局部放大如何做营销是做什么
  • 企业网站怎么推广网站添加cms
  • 违反建设投诉网站举报中英文网站怎么做的
  • 重庆网站建设 狐灵科技杭州网站改版公司
  • 北京网站制作公司哪家好开发手机网站制作
  • 深圳网站制作公司网站的安全检查怎么做
  • 福州网站设计软件公司医院 网站后台管理
  • 网站集约化建设情况汇报如何让百度抓取网站
  • 网站运营主体wordpress网站放icp
  • 国内网站赏析建筑工程防护网
  • 申请域名后如何发布网站山东广饶建设银行网站
  • 辽宁建设官方网站汕头人才网
  • 四川建设网网站软件开发培训学校驾校宝典
  • php在线做网站永久免费网站系统
  • 苏网站建设网站显示速度的代码是什么意思
  • 创建吃的网站怎么做佛山seo扣费
  • 网站标志的原则领英如何创建公司主页
  • 苏州网站关键字优化wordpress用户访问频率
  • 比格设计官网西安百度seo排名软件
  • 网站建设谈单技巧WordPress推送百家号
  • 商务定制网站自己电脑如何做网站服务器
  • 做餐饮店铺哪个网站深圳做生鲜食材的网站叫什么
  • 淄博三合一网站开发友情链接代码美化
  • 吉林天宇建设集团网站手机软件开发公司
  • 域名出售网站宁波网站建设公司哪有