嵌入式的Web应用容器Jetty (第一篇)

1、自己写了一个嵌入类对Jetty进行封装

 <1> Maven 的pom.xml需要引入 Jetty库

<dependency>
		<groupId>org.mortbay.jetty</groupId>
		<artifactId>jetty</artifactId>
		<version>6.1.5</version>
		<scope>test</scope>
	</dependency>

  <2> 接口类定义

public interface EmbedingServer {

	
	/**
	 * Setup server.
	 * @return
	 */
	EmbedingServer startServer();
	
	
	/**
	 * Shutdown server. 
	 */
	void stopServer();
}

 <3> 具体实现类

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Servlet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.xml.XmlConfiguration;

/**
 * 
 */
public class SimpleEmbedingServer implements EmbedingServer {

	protected static final  Log log = LogFactory.getLog(SimpleEmbedingServer.class);
	
	private int serverPort = 8080; 
	private String configXml;  //Jetty xml configuration.
	private String rootContextPath = "/";
	
	private String webAppDir = null; 
	private String handleClass; 
	private Server server ; 
	private boolean hasStarted = false;
	
	private String contextPathServletClassMap;
	
	private static SimpleEmbedingServer instance;
	/**
	 * 
	 */
	public SimpleEmbedingServer() {
		
	}
	
	public synchronized static SimpleEmbedingServer getInstance() {
		
		if(instance ==null) {
			instance = new SimpleEmbedingServer();
		}
		return instance;
	}

	

	/* (non-Javadoc)
	 * 
	 */
	@Override
	public EmbedingServer startServer() {
		
		ServerFactory sf = null;
		if(isNotEmpty(this.configXml)) { 
			sf = new XmlConfigurationServer(this.configXml);
			
		}else if(isNotEmpty(this.handleClass)) { 
			sf = new SingleHandlerServer(this.handleClass);
			
		}else if(isNotEmpty(this.contextPathServletClassMap)){ 
			sf  = new ContextServletMapServer(this.parsePathServletNameMap(this.contextPathServletClassMap),
												rootContextPath, 
												this.webAppDir
											  );
			
		} else {
			throw new EmbedingServerInitialException("Unable to build server.");
		} 
		log.info("Starting embeding server.");
		server = sf.getServer();
		try {
			server.start();
			this.hasStarted = true;
		} catch (Exception e) { 
			throw new EmbedingServerInitialException("Started server failure!" , e);
		}
		
		return this;
	}

	/* (non-Javadoc)
	 * 
	 */
	@Override
	public void stopServer() {
		
		if(hasStarted && server!=null) {
			try {
				server.stop();
				log.info("Stopped embeding server.");
			} catch (Exception e) {
				log.error("Fail to stop embeding server.", e);
			}
		}  
	}
 
	
	/**
	 *  Parsing the input string into mapping context path and servlet name .
	 *  <br> With format : <i>path1:servlet1;path2:servlet2...</i>
	 *  
	 * @param mapString 
	 * @return
	 */
	private Map<String, String> parsePathServletNameMap(String mapString) {
		
		 Map<String, String> m = new HashMap<String, String>();
		for (String group : mapString.split(";")) {
			String[] items  = group.split(":");
			if(items.length ==2) {
				m.put(items[0].trim(), items[1].trim());
			}
		}
		return m;
		
	}
	
 
	
	/**
	 * @param s
	 * @return
	 */
	public static boolean isNotEmpty(String s) {
		return (s!=null && s.trim().length()>0);
	}
	
	/**
	 * @param clazzName
	 * @return
	 */
	public static Class initClass(String clazzName) {
		
		Class clazz  = null;
		try {
			try {
				clazz = Thread.currentThread().getContextClassLoader().loadClass(clazzName);
			}catch(ClassNotFoundException ce) {
				//Ignore!
				 log.trace(ce);				
			}
			if(clazz == null) {
				clazz  = SimpleEmbedingServer.class.getClassLoader().loadClass(clazzName);
			}
		}catch(ClassNotFoundException ce) {
			//Ignore!
			 log.trace(ce);
		}
		
		if(clazz == null) {
			throw new IllegalArgumentException("Cannot find class named '" + clazzName + "'");
		}
		return clazz;
	}
	
	/**
	 * @param clazz
	 * @return
	 */
	public static <T> T newInstance(Class<T> clazz) {
		
		try {
			return (T)clazz.newInstance();
		} catch (Exception e) {
			throw new EmbedingServerInitialException(String.format("New instance for class %s failure!", clazz) , e);
		}
	}
	
	/**
	 * 
	 * @param path
	 * @param assertNotNull
	 * @return
	 */
	public static InputStream readFile(String path, boolean assertNotNull) {
		
		InputStream is  = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
		if(is ==null) {
			is = SimpleEmbedingServer.class.getClassLoader().getResourceAsStream(path);
		}
		if(is == null) {
			try {
				is = new FileInputStream(path);
			} catch (FileNotFoundException e) { 
				//ignore!
			}
		}
		if(is == null && assertNotNull) {
			throw new EmbedingServerInitialException("Can't read from path '" + path + "'");
		}
		return is;
	}
	
	/**
	 * 
	 * @param path
	 * @param assertNotNull
	 * @return
	 */
	public static URL getFilePath(String path, boolean assertNotNull) {
		
		URL url  = Thread.currentThread().getContextClassLoader().getResource(path);
		if(url == null) {
			url = SimpleEmbedingServer.class.getClassLoader().getResource(path);
		}
		if(url == null) {
			URI uri = new File(path).toURI();
			if(uri !=null) {
				try {
					url = uri.toURL();
				} catch (MalformedURLException e) {
					//ignore!
				}
			}
		}
		if(url == null && assertNotNull) {
			throw new EmbedingServerInitialException("Find the URL from  path '" + path + "'");
		}
		return url;
	}
	
	
	/**
	 * @param className
	 * @param supperclazz
	 * @return
	 */
	public <T> Class<T> assertClass(String className, Class<T> supperclazz) {
		
		Class t=  initClass(className); 
		if(!supperclazz.isAssignableFrom(t)) {
			   throw new IllegalAccessError("Handler's class must implement '" + supperclazz + "'");
		   }
		return t;
	}
	
	//**
	private interface ServerFactory {
		Server getServer();
	}
	
	private abstract class BaseServer implements ServerFactory {
		
		/**
		 * 
		 */
		public BaseServer() {
		}
		/* (non-Javadoc)
		 * 
		 */
		@Override
		public Server getServer() {
			
			Server server = new Server(serverPort);
			intializeServerInstance(server);
			return server;
		}
		
		/**
		 * @param server
		 * @return
		 */
		protected abstract void intializeServerInstance(Server server);
	}
	/**
	 * 
	 */
	private class SingleHandlerServer extends BaseServer {
		
		Handler handler  = null;
		
		public SingleHandlerServer(String className) {
			
		   Class handlerClazz = assertClass(className, org.mortbay.jetty.Handler.class);
		   handler = newInstance(handlerClazz);
		} 
		
		
		/* (non-Javadoc)
		 * 
		 */
		@Override
		protected void intializeServerInstance(Server server) {
			server.setHandler(handler);
		}
	}
	
	/**
	 *
	 */
	private class ContextServletMapServer extends BaseServer {
		
		private Map<String, String> pathServletHandleMap;
		private String rootCxtPath;
		private String webAppDir;

		/**
		 * @param contextPathServletMap
		 * @param rootContextPath
		 * @param webAppDir
		 */
		public ContextServletMapServer(Map<String, String> contextPathServletMap, String rootContextPath, String webAppDir) {
			
			this.pathServletHandleMap = contextPathServletMap;
			this.rootCxtPath = rootContextPath;
			this.webAppDir = webAppDir;
		}
		
		/**
		 * @param contextPathServletMap
		 * @param rootContextPath
		 */
		public ContextServletMapServer(Map<String, String> contextPathServletMap, String rootContextPath) {
			
			this.pathServletHandleMap = contextPathServletMap;
			this.rootCxtPath = rootContextPath;
		}
		
		/* (non-Javadoc)
		 * 
		 */
		@Override
		protected void intializeServerInstance(Server server) {
			
			if(isNotEmpty(this.webAppDir)) {
				server.setHandler(new WebAppContext(getFilePath(this.webAppDir, true).toExternalForm(), this.rootCxtPath));
			}else {
				Context cxt = new Context(server, this.rootCxtPath,Context.SESSIONS);
				for (Map.Entry<String, String> se : this.pathServletHandleMap.entrySet()) {
					
					Class<Servlet> clzz = assertClass(se.getValue(), Servlet.class);
					cxt.addServlet(new ServletHolder(clzz), se.getKey());
				}
			}
			
		}
		
	}
	
	public class XmlConfigurationServer extends BaseServer {
		
		private String xmlFilePath;
		
		/**
		 * @param xmlFilePath
		 */
		public XmlConfigurationServer(String xmlFilePath) {
			this.xmlFilePath = xmlFilePath;
		}
		
		/* (non-Javadoc)
		 * 
		 */
		@Override
		protected void intializeServerInstance(Server server) {
			
			try {
				XmlConfiguration configuration = new XmlConfiguration(readFile(this.xmlFilePath, true)); 
				configuration.configure(server);
			}catch(Exception e ) {
				if(e instanceof EmbedingServerInitialException) {
					throw (EmbedingServerInitialException)e;
				}else {
					throw new EmbedingServerInitialException("Load xml configuration failure!" , e);
				}
			}
		}
	}
	
	
	/**
	 *
	 */
	private static class EmbedingServerInitialException extends RuntimeException {
		
		/**
		 * @param msg
		 */
		public EmbedingServerInitialException(String msg) {
			super(msg);
		}
		
		/**
		 * 
		 */
		public EmbedingServerInitialException(String msg, Throwable e) {
			super(msg, e);
		}
	}


	/**
	 * @return the serverPort
	 */
	public int getServerPort() {
		return serverPort;
	}

	/**
	 * @param serverPort
	 * @return
	 */
	public SimpleEmbedingServer setServerPort(int serverPort) {
		this.serverPort = serverPort;
		return this;
	}

	/**
	 * @return the configXml
	 */
	public String getConfigXml() {
		return configXml;
	}

	/**
	 * It supports in {@link org.mortbay.jetty.Server} configuration.
	 * <br>
	 * {@link org.mortbay.jetty.webapp.WebAppContext} doesn't support temperately.
	 * 
	 * @param configXml
	 * @return
	 */
	public SimpleEmbedingServer setConfigXml(String configXml) {
		this.configXml = configXml;
		return this;
	}

	/**
	 * @return the rootContextPath
	 */
	public String getRootContextPath() {
		return rootContextPath;
	}

	/**
	 * @param rootContextPath
	 * @return
	 */
	public SimpleEmbedingServer setRootContextPath(String rootContextPath) {
		this.rootContextPath = rootContextPath;
		return this;
	}

	/**
	 * @return the webAppDir
	 */
	public String getWebAppDir() {
		return webAppDir;
	}

	/**
	 * @param webAppDir
	 * @return
	 */
	public SimpleEmbedingServer setWebAppDir(String webAppDir) {
		this.webAppDir = webAppDir;
		return this;
	}

	/**
	 * @return the handleClass
	 */
	public String getHandleClass() {
		return handleClass;
	}

	/**
	 * @param handleClass
	 * @return
	 */
	public SimpleEmbedingServer setHandleClass(String handleClass) {
		this.handleClass = handleClass;
		return this;
	}
	

	/**
	 * @return the contextPathServletClassMap
	 */
	public String getContextPathServletClassMap() {
		return contextPathServletClassMap;
	}

	/**
	 * @param contextPathServletClassMap
	 * @return
	 */
	public SimpleEmbedingServer setContextPathServletClassMap(String contextPathServletClassMap) {
		this.contextPathServletClassMap = contextPathServletClassMap;
		return this;
	}


}

 


你可能感兴趣的:(嵌入式的Web应用容器Jetty (第一篇))