JFinal本事内置的jetty8已经基本满足开发需求。由于本人是版本控,同时想在某些小型项目中直接用内置的jetty运行。
于是将内置的jetty升级到9.由于jetty9盒jetty8变化很大。所以几乎需要重写com.jfinal.server.JettyServer的doStart方法。需要引入jetty9的jar包。
最新的Jetty 9.3.0.v20150612 最低要求java8
代码如下:
/** * Copyright (c) 2011-2015, James Zhan 詹波 ([email protected]). * * 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 com.jfinal.server; import java.io.File; import java.io.IOException; import java.net.DatagramSocket; import java.net.ServerSocket; import java.util.EnumSet; import javax.servlet.DispatcherType; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SessionManager; import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.session.HashSessionManager; import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.webapp.WebAppContext; import com.jfinal.core.Const; import com.jfinal.kit.FileKit; import com.jfinal.kit.PathKit; import com.jfinal.kit.StrKit; /** * JettyServer is used to config and start jetty web server. * Jetty version 8.1.8 */ class JettyServer implements IServer { private String webAppDir; private int port; private String context; private int scanIntervalSeconds; private boolean running = false; private Server server; private WebAppContext webApp; private String keyStorePath = null; private String keyStorePassword = null; private String keyManagerPassword = null; JettyServer(String webAppDir, int port, String context, int scanIntervalSeconds) { if (webAppDir == null) throw new IllegalStateException("Invalid webAppDir of web server: " + webAppDir); if (port < 0 || port > 65536) throw new IllegalArgumentException("Invalid port of web server: " + port); if (StrKit.isBlank(context)) throw new IllegalStateException("Invalid context of web server: " + context); this.webAppDir = webAppDir; this.port = port; this.context = context; this.scanIntervalSeconds = scanIntervalSeconds; } JettyServer(String webAppDir, int port, String context, String keyStorePath,String keyStorePassword,String keyManagerPassword) { this(webAppDir,port,context,0); this.keyManagerPassword = keyManagerPassword; this.keyStorePassword = keyStorePassword; this.keyStorePath = keyStorePath; } public void start() { if (!running) { try {doStart();} catch (Exception e) {e.printStackTrace();} running = true; } } public void stop() { if (running) { try {webApp.stop();server.stop();} catch (Exception e) {e.printStackTrace();} running = false; } } private void doStart() { if (!available(port)) throw new IllegalStateException("port: " + port + " already in use!"); deleteSessionData(); System.out.println("Starting JFinal " + Const.JFINAL_VERSION); server = new Server(); //httl配置。 if(null == this.keyStorePath){ HttpConfiguration http_config = new HttpConfiguration(); // HTTP connector ServerConnector connector = new ServerConnector(server,new HttpConnectionFactory(http_config)); connector.setReuseAddress(true); connector.setIdleTimeout(30000); connector.setPort(port); server.addConnector(connector); }else{ //https 配置 HttpConfiguration https_config = new HttpConfiguration(); https_config.setSecureScheme("https"); https_config.setSecurePort(port); https_config.setOutputBufferSize(32768); https_config.addCustomizer(new SecureRequestCustomizer()); SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(this.keyStorePath); sslContextFactory.setKeyStorePassword(this.keyStorePassword); sslContextFactory.setKeyManagerPassword(this.keyManagerPassword); ServerConnector httpsConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory,"http/1.1"), new HttpConnectionFactory(https_config)); httpsConnector.setPort(port); httpsConnector.setIdleTimeout(500000); server.addConnector(httpsConnector); } webApp = new WebAppContext(); /** * 增加gzip支持 */ FilterHolder fh = new FilterHolder(); fh.setAsyncSupported(true); fh.setClassName("org.eclipse.jetty.servlets.GzipFilter"); fh.setInitParameter("mimeTypes", "text/html,text/plain,text/xml,text/css,text/javascript,application/javascript,image/gif,image/png"); EnumSet<DispatcherType> set = EnumSet.noneOf(DispatcherType.class); set.add(DispatcherType.REQUEST); set.add(DispatcherType.FORWARD); set.add(DispatcherType.INCLUDE); set.add(DispatcherType.ERROR); set.add(DispatcherType.ASYNC); webApp.addFilter(fh, "/*", set); webApp.setContextPath(context); webApp.setResourceBase(webAppDir); webApp.setMaxFormContentSize(81920000); webApp.getInitParams().put("org.eclipse.jetty.servlet.Default.dirAllowed", "false"); webApp.getInitParams().put("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "true"); webApp.getInitParams().put("org.eclipse.jetty.server.Request.maxFormContentSize", "-1"); persistSession(webApp); server.setHandler(webApp); changeClassLoader(webApp); // configureScanner if (scanIntervalSeconds > 0) { Scanner scanner = new Scanner(PathKit.getRootClassPath(), scanIntervalSeconds) { public void onChange() { try { System.err.println("\nLoading changes ......"); webApp.stop(); JFinalClassLoader loader = new JFinalClassLoader(webApp, getClassPath()); webApp.setClassLoader(loader); webApp.start(); System.err.println("Loading complete."); } catch (Exception e) { System.err.println("Error reconfiguring/restarting webapp after change in watched files"); e.printStackTrace(); } } }; System.out.println("Starting scanner at interval of " + scanIntervalSeconds + " seconds."); scanner.start(); } try { System.out.println("Starting web server on port: " + port); server.start(); System.out.println("Starting Complete. Welcome To The JFinal World :)"); server.join(); } catch (Exception e) { e.printStackTrace(); System.exit(100); } return; } @SuppressWarnings("resource") private void changeClassLoader(WebAppContext webApp) { try { String classPath = getClassPath(); JFinalClassLoader wacl = new JFinalClassLoader(webApp, classPath); wacl.addClassPath(classPath); } catch (IOException e) { e.printStackTrace(); } } private String getClassPath() { return System.getProperty("java.class.path"); } private void deleteSessionData() { try { FileKit.delete(new File(getStoreDir())); } catch (Exception e) { } } private String getStoreDir() { String storeDir = PathKit.getWebRootPath() + "/../../session_data" + context; if ("\\".equals(File.separator)) storeDir = storeDir.replaceAll("/", "\\\\"); return storeDir; } private void persistSession(WebAppContext webApp) { String storeDir = getStoreDir(); SessionManager sm = webApp.getSessionHandler().getSessionManager(); if (sm instanceof HashSessionManager) { try { ((HashSessionManager)sm).setStoreDirectory(new File(storeDir)); } catch (IOException e) { e.printStackTrace(); } return ; } HashSessionManager hsm = new HashSessionManager(); try { hsm.setStoreDirectory(new File(storeDir)); } catch (IOException e) { e.printStackTrace(); } SessionHandler sh = new SessionHandler(); sh.setSessionManager(hsm); webApp.setSessionHandler(sh); } private static boolean available(int port) { if (port <= 0) { throw new IllegalArgumentException("Invalid start port: " + port); } ServerSocket ss = null; DatagramSocket ds = null; try { ss = new ServerSocket(port); ss.setReuseAddress(true); ds = new DatagramSocket(port); ds.setReuseAddress(true); return true; } catch (IOException e) { } finally { if (ds != null) { ds.close(); } if (ss != null) { try { ss.close(); } catch (IOException e) { // should not be thrown, just detect port available. } } } return false; } }
为了支持ssl还得修改com.jfinal.core.JFinal实现,增加相应的方法。
public static void startSSLServer(String webAppDir, int port, String context, String keyStorePath,String keyStorePassword,String keyManagerPassword) { server = ServerFactory.getHttpsServer(webAppDir, port, context, keyStorePath, keyStorePassword, keyManagerPassword); server.start(); }
jetty-all下载地址
http://repo1.maven.org/maven2/org/eclipse/jetty/aggregate/jetty-all/