文档章节

基于jetty 自制Java Web Server 容器

张宋付
 张宋付
发布于 2010/04/13 14:25
字数 1121
阅读 1604
收藏 7
点赞 0
评论 3

 

1.main class 如下;
public final class Bootstrap {
	//~ Static fields/initializers ============================================= 
	
	private static final String SHUTDOWN = "SHUTDOWN";
    private static final String RELOAD = "RELOAD";
	
	//~ Instance fields ========================================================

	private Logger logger;
	
	private Server server;
	
    /**
     * The port number on which we wait for shutdown commands.
     */
    private int port;

    /**
     * A random number generator that is only used if
     * the shutdown command string is longer than 1024 characters.
     */
    private Random random = null;
	
	//~ Constructors ===========================================================
	
	private Bootstrap() {
		
	}

	//~ Methods ================================================================
	
	private Logger getLogger() {
		if (logger == null) {
			logger = LoggerFactory.getLogger(getClass());
		}
		return logger;
	}
	
	public void init() {
		String painiuHome = System.getProperty("net365.home", System.getProperty("user.dir", "."));

		String configDir = System.getProperty("net365.config.dir");
		if (configDir == null) {
			configDir = painiuHome + File.separator + "etc" + File.separator;
		}
		if (!configDir.endsWith(File.separator)) {
			configDir += File.separator;
		}
		
		String configFile = configDir + "net365.properties";
		Map vars = new HashMap();
		vars.put("home", painiuHome);
		Configuration.initialize(configFile, vars);
		
		initLoggingSystem(configDir);
		
		port = Configuration.getInteger("server.shutdown.port", 8014);
	}
	
	private void initLoggingSystem(String configDir) {
		File loggingConfigFile = new File(configDir, "logging.properties");
		if (loggingConfigFile.exists()) {
			System.setProperty("java.util.logging.config.file", loggingConfigFile.getAbsolutePath());
		}
		File log4jConfigFile = new File(configDir, "log4j.properties");
		if (log4jConfigFile.exists()) {
			PropertyConfigurator.configure(log4jConfigFile.getAbsolutePath());
		}
	}
	
	public void startServer() throws Exception {
		getLogger().info("Bootstrap: Starting Server...");
		
		server = new Server();
		server.initialize();
		
		server.setGracefulShutdown(Configuration.getInteger("server.shutdown.timeout", 0));
		server.setStopAtShutdown(true);
		
		server.start();
	}
	
	public void stopServer() throws Exception {
		getLogger().info("Bootstrap: Stopping Server...");
		server.stop();
	}
	
	public static void main(String[] args) {
		Bootstrap bootstrap = new Bootstrap();
		
		try {
			bootstrap.init();
			
			String command = "start";
			if (args.length > 0) {
				command = args[args.length - 1];
			}

			if (command.equals("start")) {
				bootstrap.startServer();
				bootstrap.await();
				bootstrap.stopServer();
			} else if (command.equals("stop")) {
				bootstrap.stop();
			} else if (command.equals("restart")) {
				bootstrap.stop();
				// give me 2 seconds to shutdown the server
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {}
				bootstrap.startServer();
				bootstrap.await();
				bootstrap.stopServer();
			} else if (command.equals("reload")) {
				bootstrap.reload();
			}
			
			System.exit(0);
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}
	
	public void stop() {
		sendCommand(SHUTDOWN);
	}

	public void reload() {
		sendCommand(RELOAD);
	}
	
	private void sendCommand(String command) {
		try {
            Socket socket = new Socket("127.0.0.1", port);
            OutputStream stream = socket.getOutputStream();
            for (int i = 0; i < command.length(); i++) {
                stream.write(command.charAt(i));
            }
            stream.flush();
            stream.close();
            socket.close();
        } catch (IOException e) {
            getLogger().error("IOException occurred: ", e);
        }
	}
	
	public void await() {
		// Set up a server socket to wait on
        ServerSocket serverSocket = null;
        try {
            serverSocket =
                new ServerSocket(port, 1,
                                 InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) {
            getLogger().error("Bootstrap.await: create[" + port + "]: ", e);
            System.exit(1);
        }

        // Loop waiting for a connection and a valid command
        while (true) {

            // Wait for the next connection
            Socket socket = null;
            InputStream stream = null;
            try {
                socket = serverSocket.accept();
                socket.setSoTimeout(10 * 1000);  // Ten seconds
                stream = socket.getInputStream();
            } catch (AccessControlException ace) {
                getLogger().warn("StandardServer.accept security exception: " + ace.getMessage(), ace);
                continue;
            } catch (IOException e) {
                getLogger().error("StandardServer.await: accept: ", e);
                System.exit(1);
            }

            // Read a set of characters from the socket
            StringBuffer command = new StringBuffer();
            int expected = 1024; // Cut off to avoid DoS attack
            while (expected < SHUTDOWN.length()) {
                if (random == null)
                    random = new Random(System.currentTimeMillis());
                expected += (random.nextInt() % 1024);
            }
            while (expected > 0) {
                int ch = -1;
                try {
                    ch = stream.read();
                } catch (IOException e) {
                    getLogger().warn("Bootstrap.await: read: ", e);
                    ch = -1;
                }
                if (ch < 32)  // Control character or EOF terminates loop
                    break;
                command.append((char) ch);
                expected--;
            }

            // Close the socket now that we are done with it
            try {
                socket.close();
            } catch (IOException e) {
            }

            // Match against our command string
            if (command.toString().equals(SHUTDOWN)) {
                break;
            } else if (command.toString().equals(RELOAD)) {
            	try {
					server.reload();
				} catch (Exception e) {
					getLogger().error("Bootstrap.reloading failed", e);
				}
            } else {
                getLogger().warn("Bootstrap.await: Invalid command '" +
                                   command.toString() + "' received");
            }
        }

        // Close the server socket and return
        try {
            serverSocket.close();
        } catch (IOException e) {
        }

	}

}


2.server class 如下:

public class Server extends org.mortbay.jetty.Server {
	//~ Static fields/initializers =============================================

	private static final Logger logger = LoggerFactory.getLogger(Server.class);
	
	//~ Instance fields ========================================================
	
	private ClassPathXmlApplicationContext applicationContext;
	private Handler webapp;
	private RemotingServer remotingServer;
	
	
	//~ Constructors ===========================================================

	public Server() {
	}
	
	//~ Methods ================================================================
	
	private void initApplicationContext() {
		String configLocation = Configuration.get("spring.config.location", "applicationContext*.xml");
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
		context.setConfigLocation(context.CLASSPATH_ALL_URL_PREFIX + configLocation);
		context.refresh();
		applicationContext = context;
	}
	
	//private void initYPFS() {
	//	YPFS.initialize(null);
	//}
	
	private SecurityHandler createSecurityHandler() {
		return new SecurityHandler();
	}

	private SessionHandler createSessionHandler() {
		//SessionManager sessionManager = (SessionManager) applicationContext.getBean("jettySessionManager");
		//if (sessionManager == null) {
		//	logger.error("SessionManager not configured! use default: HashSessionManager");
		SessionManager sessionManager = new HashSessionManager();
		//}
		sessionManager.setSessionDomain("." + Configuration.get("webapp.domain"));
		return new SessionHandler(sessionManager);
	}
	
	private ErrorHandler createErrorHandler() {
		ErrorHandler handler = new ErrorHandler();
		handler.setShowStacks(Configuration.getBoolean("devmode", false));
		return handler;
	}
	
	public void reload() throws Exception {
		applicationContext.refresh();
		webapp.stop();
		webapp.start();
	}
	
	public void initialize() throws Exception {
		initApplicationContext();
		//initYPFS();
		
		Connector connector = new SelectChannelConnector();
		connector.setPort(Configuration.getInteger("server.port", 8080));
		setConnectors(new Connector[] { connector });
		
		webapp = initWebAppHandler();
		
		if (Configuration.getBoolean("devmode", false)) {
			// setup static context for development
			List handlers = new ArrayList(3);
			handlers.add(webapp);
			if (Configuration.get("server.media.vhosts") != null) {
				handlers.add(initStaticContext());
			}
			
			ContextHandlerCollection contexts = new ContextHandlerCollection();
			contexts.setHandlers(handlers.toArray(new Handler[handlers.size()]));
			setHandler(contexts);
		} else {
			setHandler(webapp);
		}
	}
	
	private Handler initStaticContext() {
		ResourceHandler staticHandler = new ResourceHandler();
		ContextHandler staticContext = new ContextHandler();
		staticContext.setContextPath("/");
		staticContext.setResourceBase(Configuration.get("server.media.war"));
		staticContext.setHandler(staticHandler);
		
		String vhosts = Configuration.get("server.media.vhosts", "");
		logger.info("Starting media server, vhosts: {}", vhosts);
		staticContext.setVirtualHosts(StringUtils.split(vhosts));

		return staticContext;
	}
	
	/* (non-Javadoc)
	 * @see org.mortbay.jetty.Server#doStop()
	 */
	@Override
	protected void doStop() throws Exception {
		logger.info("Shutting down...");
		super.doStop();
		
		if (remotingServer != null) {
			logger.info("Stopping remoting server...");
			remotingServer.stop();
		}
		
		applicationContext.destroy();
	}

	
	private Handler initWebAppHandler() throws IOException {
		WebAppContext context = new WebAppContext(createSecurityHandler(), createSessionHandler(), null, createErrorHandler());
		context.setDefaultsDescriptor("com/net365/server/jetty/webdefault.xml");
		context.setContextPath(Configuration.get("webapp.contextPath", "/"));
		context.setWar(Configuration.get("server.war"));
		context.setExtractWAR(false);
		context.setParentLoaderPriority(true);
		context.setTempDirectory(new File(Configuration.get("server.tmpDir")));
		context.setAttribute(B2CEshop.APPLICATION_CONTEXT_KEY, applicationContext);

		if (Configuration.getBoolean("devmode", false)) {
			String vhosts = Configuration.get("server.vhosts", "");
			logger.info("Starting server in DevMode, vhosts: {}", vhosts);
			context.setVirtualHosts(StringUtils.split(vhosts));
		}
		
		InputStream in = null;
		
		try {
			Resource resource = context.getWebInf().addPath("urlrewrite.xml");
			if (resource == null || !resource.exists()) {
				logger.error("Url rewrite rules not found, url rewrite will not be supported");
				return context;
			}
			in = resource.getInputStream();
			
			RewriteHandler handler = new RewriteHandler();
			handler.setHandler(context);
			handler.setRules(loadRewriteRules(in));
			handler.setActionExtension(Configuration.get("webapp.action.extension"));
			
			return handler;
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					logger.error("Error closing urlrewrite configuration file", e);
				}
			}
		}
	}
	
	private static Rule[] loadRewriteRules(InputStream in) {		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setValidating(true);
        factory.setNamespaceAware(true);
        factory.setIgnoringComments(true);
        factory.setIgnoringElementContentWhitespace(true);
        
        DocumentBuilder parser;
        try {
            parser = factory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            logger.error("Unable to setup XML parser for reading conf", e);
            return null;
        }
        
        DefaultHandler handler = new DefaultHandler();
        parser.setErrorHandler(handler);
        parser.setEntityResolver(handler);

        List rules = new ArrayList();
        
        try {
            Document doc = parser.parse(in);
            
            Element rootElement = doc.getDocumentElement();
            NodeList categoryList = rootElement.getChildNodes();
            for (int i = 0; i < categoryList.getLength(); i++) {
                Node node = categoryList.item(i);

                if (node.getNodeType() == Node.ELEMENT_NODE &&
                        ((Element) node).getTagName().equals("category")) {
                	String categoryName = getAttrValue(node, "name");
                	
                	NodeList ruleList = node.getChildNodes();
                	
                	for (int j = 0; j < ruleList.getLength(); j++) {
                		Node subNode = ruleList.item(j);
                		
                		if (subNode.getNodeType() == Node.ELEMENT_NODE &&
                				((Element) subNode).getTagName().equals("rule")) {
                			Element ruleElement = (Element) subNode;
                			
                			RewriteRegexRule rule = new RewriteRegexRule();
                			rule.setCategory(categoryName);
                			rule.setRegex(getNodeValue(ruleElement.getElementsByTagName("from").item(0)));
                			rule.setReplacement(getNodeValue(ruleElement.getElementsByTagName("to").item(0)));

                			rules.add(rule);
                		}
                	}
                }
            }
        } catch (SAXParseException e) {
            logger.error("Parse error on line " + e.getLineNumber() + " " + e.getMessage(), e);
        } catch (Exception e) {
            logger.error("Exception loading conf " + e.getMessage(), e);
        }
        
        return rules.toArray(new Rule[rules.size()]);
	}
	
	private static String getNodeValue(Node node) {
        if (node == null) return null;
        NodeList nodeList = node.getChildNodes();
        if (nodeList == null) return null;
        Node child = nodeList.item(0);
        if (child == null) return null;
        if ((child.getNodeType() == Node.TEXT_NODE)) {
            String value = ((Text) child).getData();
            return value.trim();
        }
        return null;
    }
	
    private static String getAttrValue(Node n, String attrName) {
        if (n == null) return null;
        NamedNodeMap attrs = n.getAttributes();
        if (attrs == null) return null;
        Node attr = attrs.getNamedItem(attrName);
        if (attr == null) return null;
        String val = attr.getNodeValue();
        if (val == null) return null;
        return val.trim();
    }
}

这个其中一个小段,还有一些我的应用中加入的。哈哈。。

© 著作权归作者所有

共有 人打赏支持
张宋付
粉丝 28
博文 15
码字总数 11591
作品 0
杭州
程序员
加载中

评论(3)

张宋付
张宋付
呵呵。hsqldb是一个小型DB系统。对于内嵌也是相当不错的。
红薯
红薯
俺多年以前的作品: http://www.ibm.com/developerworks/cn/java/l-hsqldb/index.html
张宋付
张宋付
选用jetty原因就是想让在分布式中能有更快成本更低JAVA WEB服务器。哈哈。
Servlet 容器 Jetty 9.4.10 发布,大量错误修复和改进

Servlet 容器 Jetty 9.4.10 已发布,官方发布说明显示,该版本包含大量错误修复和改进,建议所有用户尽快升级。 获取更新 Eclipse: https://www.eclipse.org/jetty/download.html Maven Cen...

局长
05/08
0
0
Jetty 9.4.11.v20180605 发布,开源的 Servlet 容器

Jetty 9.4.11.v20180605 已发布,Jetty 是一个开源的 servlet 容器,它为基于 Java 的 web 内容,例如 JSP 和 servlet 提供运行环境。Jetty 是使用 Java 语言编写的,它的 API 以一组 JAR 包...

淡漠悠然
06/11
0
0
storm/java web项目引用的jar该放容器的lib下吗?

不要把第三方jar包放到容器的lib中,把容器不提供的第三方jar打包到项目中,容器提供的jar就不打包到jar包中。项目运行时,会先检测项目本身打入的jar包,然后再去容器的lib下面寻找jar包。 ...

cjun1990
2015/01/08
0
0
Apache/Tomcat/JBOSS/Nginx区别

先说Apache和Tomcat的区别: Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。 ...

Sheamus
2015/02/06
0
0
Spring Boot 内嵌 Servlet 容器

Web容器名称 Servlet版本 Java版本 Tomcat 8 3.1 Java 7.0 + Tomcat 7 3.0 Java 6.0 + Jetty 9 3.1 Java 7.0 + Jetty 8 3.0 Java 6.0 + Undertow 1.1 3.1 Java 7.0 +...

WorriedFox
05/02
0
0
小轮子一枚-高仿express的Java服务器

之前做了个Java项目MockSocks,要做UI,用Swing写实在是又low又费劲,跟前端同事聊起node-webkit,觉得很不错。但是我大部分业务都在Java上,于是就涉及到Java与js通信问题。 当然最常用的解...

黄亿华
2013/11/17
0
0
关于Apache/Tomcat/JBOSS/Neginx/lighttpd/Jetty等一些常见服务器的区别比较和理解

先说Apache和Tomcat的区别: Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。 ...

进取的菜鸟
07/04
0
0
结合Dynamic .NET TWAIN和Jetty,实现基于网页的TWAIN文件扫描

网页TWAIN扫描是通过多种技术结合实现的,看下流程图: 参考原文: Web-based Document Imaging Capture with .Net TWAIN and Jetty 准备工作 阅读: 如何通过jni4net,在Java应用中调用C#接...

yushulx
2014/08/18
0
0
构建Gradle范例项目之构建web项目

Gradle提供了开箱即用的插件,用来组装WAR文件和将web应用部署到本地Servlet容器中。Gradle对构建和运行web应用都提供了扩展性支持。这里我们学习使用两个web应用程序部署插件:War和Jetty。...

柳哥
2015/10/26
0
0
Eclipse Jetty GWT 同时调试多个项目的配置方法

  阅读: 43 评论: 2 作者: blackcore 发表于 2009-11-30 10:05 原文链接 GWT应用程序有两种方式运行: Hosted Model 在Hosted Model方式下,Java程序并不会被编译成JavaScript,GWT只是创造...

agile
2009/12/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java基础——异常

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 异常处理: 可以挖很多个陷阱,但是不要都是一样...

凯哥学堂
8分钟前
0
0
180723-Quick-Task 动态脚本支持框架之结构设计篇

Quick-Task 动态脚本支持框架之结构设计篇 相关博文: 180702-QuickTask动态脚本支持框架整体介绍篇 180719-Quick-Task 动态脚本支持框架之使用介绍篇 前面两篇博文,主要是整体介绍和如何使用...

小灰灰Blog
12分钟前
0
0
SBT 常用开发技巧

SBT 一直以来都是 Scala 开发者不可言说的痛,最主要的原因就是官方文档维护质量较差,没有经过系统的、循序渐进式的整理,导致初学者入门门槛较高。虽然也有其它构建工具可以选择(例如 Mill...

joymufeng
16分钟前
0
0
HBase in Practice - 性能、监控及问题解决

李钰(社区ID:Yu Li),阿里巴巴计算平台事业部高级技术专家,HBase开源社区PMC&committer。开源技术爱好者,主要关注分布式系统设计、大数据基础平台建设等领域。连续4年基于HBase/HDFS设计和...

中国HBase技术社区
17分钟前
1
0
ES18-JAVA API 批量操作

1.批量查询 Multi Get API public static void multiGet() {// 批量查询MultiGetResponse response = getClient().prepareMultiGet().add("my_person", "my_index", "1")// 查......

贾峰uk
22分钟前
0
0
SpringBoot2.0使用health

1,引入actuator <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency> 2,application.properties ......

暗中观察
29分钟前
0
0
阿里巴巴Java开发规约

###编程规约 命名风格 【强制】代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束 【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。...

简心
33分钟前
0
0
如何用TypeScript来创建一个简单的Web应用

转载地址 如何用TypeScript来创建一个简单的Web应用 安装TypeScript 获取TypeScript工具的方式: 通过npm(Node.js包管理器) npm install -g typescript 构建你的第一个TypeScript文件 创建...

durban
38分钟前
0
0
分享好友,朋友圈自定义分享链接无效

这个问题是微信6.5.6版本以后,修改了分享规则:分享的连接必须在公众号后台设定的js安全域名内

LM_Mike
55分钟前
0
0
2018年7月23日课程

一、LVS-DR介绍 director分配请求到不同的real server。real server 处理请求后直接回应给用户,这样director负载均衡器仅处理客户机与服务器的一半连接。负载均衡器仅处理一半的连接,避免了...

人在艹木中
59分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部