zoukankan      html  css  js  c++  java
  • jetty9内嵌到应用,并在启动后加载WebApplicationInitializer,可运行jsp

    声明:本文所介绍的两功能都已经测试通过。

    第一步先确保你用的是java 8,并依赖需要的相关jar包,以下是用gradle进行依赖的信息:

    ext {
    taglibsStandardVersion = "1.2.5"
    ecjVersion = "4.4.2"
    apacheJspVersion = "6.9.10"
    asmVersion = "5.0.1"
    tomcatVersion = "8.0.30"
    annotationApiVersion = "1.2"
    jettySchemasVersion = "3.1"
    jettyVersion = "9.3.7.v20160115"
    servletApiVersion = "3.1.0"
    hamcrestCoreVersion = "5.0.1"
    commonsLoggingVersion = "1.2"
    springVersion = "4.2.3.RELEASE"

    }

    dependencies {

      compile("spring-web:spring-web:${springVersion}")
        compile("spring-aop:spring-aop:${springVersion}")
        compile("spring-beans:spring-beans:${springVersion}")
        compile("spring-context:spring-context:${springVersion}")
        compile("spring-expression:spring-expression:${springVersion}")
        compile("spring-core:spring-core:${springVersion}")
        compile("commons-logging:commons-logging:${commonsLoggingVersion}")
        compile("javax.servlet-api:javax.servlet-api:${servletApiVersion}")
        compile("hamcrest-core:hamcrest-core:${hamcrestCoreVersion}")
        compile("jetty-annotations:jetty-annotations:${jettyVersion}")
        compile("jetty-plus:jetty-plus:${jettyVersion}")
        compile("jetty-jndi:jetty-jndi:${jettyVersion}")
        compile("jetty-webapp:jetty-webapp:${jettyVersion}")
        compile("jetty-xml:jetty-xml:${jettyVersion}")
        compile("jetty-servlet:jetty-servlet:${jettyVersion}")
        compile("jetty-servlet:jetty-security:${jettyVersion}")
        compile("jetty-servlet:jetty-util:${jettyVersion}")
        compile("jetty-servlet:jetty-server:${jettyVersion}")
        compile("jetty-servlet:jetty-http:${jettyVersion}")
        compile("jetty-servlet:jetty-io:${jettyVersion}")
        compile("jetty-servlet:jetty-schemas:${jettySchemasVersion}")
        compile("apache-jsp:apache-jsp:${jettyVersion}")
        compile("aopalliance:aopalliance:1.0")
        compile("javax.annotation-api:javax.annotation-api:${annotationApiVersion}")
        compile("asm:asm:${asmVersion}")
        compile("asm-tree:asm-tree:${asmVersion}")
        compile("asm-commons:asm-commons:${asmVersion}")    
        compile("jasper-apache-jsp:apache-jsp:${apacheJspVersion}")
        compile("apache-el:apache-el:${apacheJspVersion}")
        compile("ecj:ecj:${ecjVersion}")
        compile("taglibs-standard-spec:taglibs-standard-spec:${taglibsStandardVersion}")
        compile("taglibs-standard-impl:taglibs-standard-impl:${taglibsStandardVersion}")
    }

    1、jetty9内嵌到应用

     核心类代码如下:

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.tomcat.InstanceManager;
    import org.apache.tomcat.SimpleInstanceManager;
    import org.eclipse.jetty.annotations.AnnotationConfiguration;
    import org.eclipse.jetty.annotations.ClassInheritanceHandler;
    import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
    import org.eclipse.jetty.apache.jsp.JettyJasperInitializer;
    import org.eclipse.jetty.jsp.JettyJspServlet;
    import org.eclipse.jetty.plus.annotation.ContainerInitializer;
    import org.eclipse.jetty.server.ConnectionFactory;
    import org.eclipse.jetty.server.Handler;
    import org.eclipse.jetty.server.NCSARequestLog;
    import org.eclipse.jetty.server.NetworkConnector;
    import org.eclipse.jetty.server.RequestLog;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.ServerConnector;
    import org.eclipse.jetty.server.handler.HandlerCollection;
    import org.eclipse.jetty.server.handler.RequestLogHandler;
    import org.eclipse.jetty.server.handler.gzip.GzipHandler;
    import org.eclipse.jetty.servlet.DefaultServlet;
    import org.eclipse.jetty.servlet.ServletHolder;
    import org.eclipse.jetty.util.ConcurrentHashSet;
    import org.eclipse.jetty.util.log.JavaUtilLog;
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.resource.Resource;
    import org.eclipse.jetty.util.thread.QueuedThreadPool;
    import org.eclipse.jetty.util.thread.ThreadPool;
    import org.eclipse.jetty.webapp.Configuration;
    import org.eclipse.jetty.webapp.MetaData;
    import org.eclipse.jetty.webapp.WebAppContext;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.WebApplicationInitializer;
    
    import com.wangzhe.autojoin.wangfw.init.WebAppStrarUpInitializer;
    import com.wangzhe.autojoin.wangfw.server.Common;
    import com.wangzhe.autojoin.wangfw.server.ServerParam;
    import com.wangzhe.autojoin.wangfw.server.jetty9.test.DateServlet;
    import com.wangzhe.autojoin.wangfw.util.DateUtil;
    import com.wangzhe.autojoin.wangfw.util.ObjectUtil;
    import com.wangzhe.autojoin.wangfw.util.Pic2Char;
    
    /**
     * Example of using JSP's with embedded jetty and not requiring all of the
     * overhead of a WebAppContext
     */
    public class JettyRunner {
        private static final Logger LOG = LoggerFactory.getLogger(JettyRunner.class);
    
        // web容器相关参数
        private static final ServerParam param = new ServerParam();
    
        public static void main(String[] args) throws Exception {
            printFrameWorkLog();
            Common.initServerParam(args, param);
            LoggingUtil.config();
            Log.setLog(new JavaUtilLog());
            JettyRunner main = new JettyRunner();
            main.start();
            printStartSuccess();
            main.waitForInterrupt();
            
        }
    
        private static void printFrameWorkLog() throws IOException {
            String fileStr = new File("").getAbsolutePath()+"\src\main\webapp\pc\aj.wangfw\img\wang_font.png";
            Pic2Char.startPic2Char(fileStr);
        }
        private static void printStartSuccess() throws IOException {
            String fileStr = new File("").getAbsolutePath()+"\src\main\webapp\pc\aj.wangfw\img\startSuccess.png";
            System.out.println();
            Pic2Char.startPic2Char(fileStr);
        }
    
        private Server server;
        private URI serverURI;
    
        public JettyRunner() {
        }
    
        public URI getServerURI() {
            return serverURI;
        }
    
        public void start() throws Exception {
            server = new Server(createThreadPool());
            NetworkConnector connector = createConnector();
            server.addConnector(connector);
    
            URI baseUri = getWebRootResourceUri();
            // Set JSP to use Standard JavaC always
            System.setProperty("org.apache.jasper.compiler.disablejsr199", "false");
    
            server.setHandler(getWebAppContext(baseUri, getScratchDir()));
            server.addConnector(connector);
            server.setStopAtShutdown(true);
            // Start Server
            server.start();
    
            // Show server state
            // if (LOG.isDebugEnabled())
            String dump = server.dump();// 输出jetty部分dump信息
            LOG.info(dump.substring(dump.indexOf("> sun.misc.Launcher$AppClassLoader")));
            // }
    
            this.serverURI = getServerUri(connector);
        }
    
        private NetworkConnector createConnector() {
            ServerConnector connector = new ServerConnector(server);
            connector.setPort(param.getPort());
            connector.setHost(param.getHost());
            return connector;
        }
    
        private URI getWebRootResourceUri() throws FileNotFoundException, URISyntaxException {
            URL indexUri = this.getClass().getResource("" + param.getWebDir());
            if (indexUri == null) {
                return null;
            }
            // Points to wherever /webroot/ (the resource) is
            return indexUri.toURI();
        }
    
        /**
         * Establish Scratch directory for the servlet context (used by JSP
         * compilation)
         */
        private File getScratchDir() throws IOException {
            File tempDir = new File(System.getProperty("java.io.tmpdir"));
            File scratchDir = new File(tempDir.toString(), "embedded-jetty-jsp");
    
            if (!scratchDir.exists()) {
                if (!scratchDir.mkdirs()) {
                    throw new IOException("Unable to create scratch directory: " + scratchDir);
                }
            }
            return scratchDir;
        }
    
        /**
         * Setup the basic application "context" for this application at "/" This is
         * also known as the handler tree (in jetty speak)
         */
        private HandlerCollection getWebAppContext(URI baseUri, File scratchDir) {
            WebAppContext webappCtx = new WebAppContext();
            webappCtx.setContextPath("/");
            // webappCtx.setDescriptor(param.getWebDir()+"\WEB-INF\web.xml");
            // webappCtx.setWar(param.getWebDir());//for war
            webappCtx.setDisplayName("auto join");
            webappCtx.setTempDirectory(new File(param.getTempDir()));
            webappCtx.setWelcomeFiles(new String[] { param.getWebDir() + "\index.html" });// 欢迎页面
            webappCtx.setConfigurationDiscovered(true);
            webappCtx.setParentLoaderPriority(true);
            RequestLogHandler logHandler = new RequestLogHandler();
            logHandler.setRequestLog(createRequestLog());
    
            webappCtx.setAttribute("javax.servlet.context.tempdir", scratchDir);
            webappCtx.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                    ".*/[^/]*servlet-api-[^/]*\.jar$|.*/javax.servlet.jsp.jstl-.*\.jar$|.*/.*taglibs.*\.jar$");
            if (ObjectUtil.isNotEmpty(baseUri)) {
                webappCtx.setResourceBase(baseUri.toASCIIString());// for dir
            } else {
                webappCtx.setResourceBase(param.getWebDir());
            }
    
            webappCtx.setAttribute("org.eclipse.jetty.containerInitializers", jspInitializers());
            webappCtx.setAttribute(InstanceManager.class.getName(), new SimpleInstanceManager());
            webappCtx.addBean(new ServletContainerInitializersStarter(webappCtx), true);
            webappCtx.setClassLoader(getUrlClassLoader());
    
            webappCtx.addServlet(jspServletHolder(), "*.jsp");
            // Add Application Servlets
            webappCtx.addServlet(DateServlet.class, "/date/");
            webappCtx.addServlet(exampleJspFileMappedServletHolder(), "/test/foo/");
            webappCtx.addServlet(defaultServletHolder(baseUri), "/");
            
            setConfigurations(webappCtx);
            
            MetaData metaData = webappCtx.getMetaData();
            Resource webappInitializer = Resource.newResource(WebAppStrarUpInitializer.class.getProtectionDomain().getCodeSource().getLocation());
            metaData.addContainerResource(webappInitializer);
    
            HandlerCollection handlerCollection = new HandlerCollection();
            GzipHandler gzipHandler = new GzipHandler();
            handlerCollection.setHandlers(new Handler[] { webappCtx, logHandler, gzipHandler });
            return handlerCollection;
        }
    
        private void setConfigurations(WebAppContext webappCtx) {
            webappCtx.setConfigurations(new Configuration[] { 
                     new AnnotationConfiguration() {
                            @Override
                            public void preConfigure(WebAppContext context) throws Exception {
                                ClassInheritanceMap map = new ClassInheritanceMap();
                                ConcurrentHashSet<String> hashSet = new  ConcurrentHashSet<String>();
                                hashSet.add(WebAppStrarUpInitializer.class.getName());
                                map.put(WebApplicationInitializer.class.getName(), hashSet);
                                context.setAttribute(CLASS_INHERITANCE_MAP, map);
                                _classInheritanceHandler = new ClassInheritanceHandler(map);
                            }
                        } 
             });
        }
    
        /**
         * Ensure the jsp engine is initialized correctly
         */
        private List<ContainerInitializer> jspInitializers() {
            JettyJasperInitializer sci = new JettyJasperInitializer();
            ContainerInitializer initializer = new ContainerInitializer(sci, null);
            List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
            initializers.add(initializer);
            return initializers;
        }
    
        /**
         * Set Classloader of Context to be sane (needed for JSTL) JSP requires a
         * non-System classloader, this simply wraps the embedded System classloader
         * in a way that makes it suitable for JSP to use
         */
        private ClassLoader getUrlClassLoader() {
            ClassLoader jspClassLoader = new URLClassLoader(new URL[0], this.getClass().getClassLoader());
            // jspClassLoader=Thread.currentThread().getContextClassLoader();
            // //也可以用这种方式
            return jspClassLoader;
        }
    
        /**
         * Create JSP Servlet (must be named "jsp")
         */
        private ServletHolder jspServletHolder() {
            ServletHolder holderJsp = new ServletHolder("jsp", JettyJspServlet.class);
            holderJsp.setInitOrder(0);
            holderJsp.setInitParameter("logVerbosityLevel", "DEBUG");
            holderJsp.setInitParameter("fork", "false");
            holderJsp.setInitParameter("xpoweredBy", "false");
            holderJsp.setInitParameter("compilerTargetVM", "1.7");
            holderJsp.setInitParameter("compilerSourceVM", "1.7");
            holderJsp.setInitParameter("keepgenerated", "true");
            return holderJsp;
        }
    
        /**
         * Create Example of mapping jsp to path spec
         */
        private ServletHolder exampleJspFileMappedServletHolder() {
            ServletHolder holderAltMapping = new ServletHolder();
            holderAltMapping.setName("foo.jsp");
            holderAltMapping.setForcedPath("/test/foo/foo.jsp");
            return holderAltMapping;
        }
    
        /**
         * Create Default Servlet (must be named "default")
         */
        private ServletHolder defaultServletHolder(URI baseUri) {
            ServletHolder holderDefault = new ServletHolder("default", DefaultServlet.class);
            if (ObjectUtil.isNotEmpty(baseUri)) {
                LOG.info("Base URI: " + baseUri);
                holderDefault.setInitParameter("resourceBase", baseUri.toASCIIString());
            } else {
                holderDefault.setInitParameter("resourceBase", param.getWebDir());
            }
    
            holderDefault.setInitParameter("dirAllowed", "true");
            return holderDefault;
        }
    
        /**
         * Establish the Server URI
         */
        private URI getServerUri(NetworkConnector connector) throws URISyntaxException {
            String scheme = "http";
            for (ConnectionFactory connectFactory : connector.getConnectionFactories()) {
                if (connectFactory.getProtocol().equals("SSL-http")) {
                    scheme = "https";
                }
            }
            String host = connector.getHost();
            if (host == null) {
                host = "localhost";
            }
            int port = connector.getLocalPort();
            serverURI = new URI(String.format("%s://%s:%d/", scheme, host, port));
            LOG.info("start sucess on Server URI: " + serverURI);
        
            return serverURI;
        }
    
        public void stop() throws Exception {
            server.stop();
        }
    
        /**
         * Cause server to keep running until it receives a Interrupt.
         * <p>
         * Interrupt Signal, or SIGINT (Unix Signal), is typically seen as a result
         * of a kill -TERM {pid} or Ctrl+C
         * 
         * @throws InterruptedException
         *             if interrupted
         */
        public void waitForInterrupt() throws InterruptedException {
            server.join();
        }
    
        public static ServerParam getParam() {
            return param;
        }
    
        private RequestLog createRequestLog() {
            // 记录访问日志的处理
            NCSARequestLog requestLog = new NCSARequestLog();
            requestLog.setFilename(param.getLogDir() + "/jetty_log" + DateUtil.formatDate(DateUtil.YYYYMMDD) + ".log");
            requestLog.setRetainDays(90);
            requestLog.setExtended(false);
            requestLog.setAppend(true);
            // requestLog.setLogTimeZone("GMT");
            requestLog.setLogTimeZone("Asia/beijing");
            requestLog.setLogDateFormat("yyyy-MM-dd HH:mm:ss");
            requestLog.setLogLatency(true);
            return requestLog;
        }
    
        /**
         * 设置线程池
         * 
         * @return
         */
        private ThreadPool createThreadPool() {
            QueuedThreadPool threadPool = new QueuedThreadPool();
            threadPool.setMinThreads(10);
            threadPool.setMaxThreads(500);
            return threadPool;
        }
    }

    2、jetty9服务器启动时加载WebApplicationInitializer

     下面代码是WebApplicationInitializer的一个实现类

    @Order(Integer.MIN_VALUE) // 较低的值有更高的优先级 所以这个类的优先级是最高的
    public class WebAppStrarUpInitializer implements WebApplicationInitializer{
    
        public WebAppStrarUpInitializer() {
            
        }
    
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            System.out.println("hello WebAppStrarUpInitializer");
            
        }
         
    }

     下面代码是从上面第一部分的JettyRunner类中抽取的部分代码,即注册WebApplicationInitializer的地方

     private void setConfigurations(WebAppContext webappCtx) {
            webappCtx.setConfigurations(new Configuration[] { 
                     new AnnotationConfiguration() {
                            @Override
                            public void preConfigure(WebAppContext context) throws Exception {
                                ClassInheritanceMap map = new ClassInheritanceMap();
                                ConcurrentHashSet<String> hashSet = new  ConcurrentHashSet<String>();
                                hashSet.add(WebAppStrarUpInitializer.class.getName());//注册WebApplicationInitializer
                                map.put(WebApplicationInitializer.class.getName(), hashSet);
                                context.setAttribute(CLASS_INHERITANCE_MAP, map);
                                _classInheritanceHandler = new ClassInheritanceHandler(map);
                            }
                        } 
             });
        }

    完成代码编写后,请运行JettyRunner类的main方法,运行后请在浏览器输入localhost/index.jsp即可看到效果。如图:

    参考:

    https://github.com/orb15/embeddedjetty9-spring4

    https://github.com/langtianya/embedded-jetty-jsp

    https://github.com/yjmyzz/jetty-embed-demo

    本文代码托管:https://github.com/langtianya/autojion/tree/master/module_project

  • 相关阅读:
    Auto Generate Reflection Information for C++
    面向嵌入式的JavaScript引擎
    如何在unity3d的UGUI中给Text添加材质和艺术字
    获取Unity GLES版本
    PBR原理
    Unity双开
    Unity Shader各种效果
    Redis是什么
    其他地方拷贝过来的VS项目一直报错不能启动IIS
    IIS部署PHP项目并与mysql完美结合
  • 原文地址:https://www.cnblogs.com/langtianya/p/5824515.html
Copyright © 2011-2022 走看看