├── .classpath ├── .gitignore ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs └── org.eclipse.m2e.core.prefs ├── LICENSE ├── README.md ├── pom.xml ├── src ├── main │ ├── java │ │ └── org │ │ │ └── eh │ │ │ └── core │ │ │ ├── annotation │ │ │ ├── AnnocationHandler.java │ │ │ ├── Controller.java │ │ │ └── RequestMapping.java │ │ │ ├── common │ │ │ ├── Constants.java │ │ │ └── ReturnType.java │ │ │ ├── http │ │ │ ├── ApplicationContext.java │ │ │ ├── EHHttpHandler.java │ │ │ ├── EHServer.java │ │ │ └── HttpSession.java │ │ │ ├── model │ │ │ ├── FileInfo.java │ │ │ └── ResultInfo.java │ │ │ ├── task │ │ │ └── SessionCleanTask.java │ │ │ ├── util │ │ │ ├── FileUploadContentAnalysis.java │ │ │ ├── IOUtil.java │ │ │ ├── PropertyUtil.java │ │ │ ├── StringUtil.java │ │ │ └── VelocityUtil.java │ │ │ └── web │ │ │ ├── controller │ │ │ └── Controller.java │ │ │ └── view │ │ │ └── ViewHandler.java │ └── resources │ │ ├── velocity.properties │ │ └── web.properties └── test │ └── java │ └── org │ └── eh │ ├── core │ ├── annotation │ │ └── AnnotationHandlerTest.java │ ├── controller │ │ ├── Test1Controller.java │ │ ├── Test2Controller.java │ │ ├── TestAnnocation.java │ │ └── pss │ │ │ └── Test3Controller.java │ ├── other │ │ └── StringTest.java │ └── util │ │ ├── FileUtilTest.java │ │ └── PropertyUtilTest.java │ ├── velocity │ ├── VelocityTest.java │ └── test.vm │ └── web │ ├── controller │ ├── Test1Controller.java │ └── TestController.java │ └── view │ └── test │ └── myinfo.page └── target ├── classes └── web.properties └── maven-archiver └── pom.properties /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | /target 8 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | easy-httpserver 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.maven.ide.eclipse.maven2Builder 15 | 16 | 17 | 18 | 19 | org.eclipse.m2e.core.maven2Builder 20 | 21 | 22 | 23 | 24 | 25 | org.maven.ide.eclipse.maven2Nature 26 | org.eclipse.jdt.core.javanature 27 | org.eclipse.m2e.core.maven2Nature 28 | 29 | 30 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/main/resources/velocity.properties=ISO-8859-1 5 | encoding//src/main/resources/web.properties=UTF-8 6 | encoding//src/test/java=UTF-8 7 | encoding/=UTF-8 8 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.7 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 12 | org.eclipse.jdt.core.compiler.source=1.7 13 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | easy-httpserver 2 | ================= 3 | 4 | 简介 5 | ----------------- 6 | 一个java实现的简单的web服务器,主要目的是为了理解web服务器的工作原理。http请求的接收和返回使用JDK自带的HttpServer,请求处理和页面解析是自己实现的。目前已经能够支持web服务器一些基本的功能。 7 | 8 | 功能 9 | ----------------- 10 | 目前项目已经能够完成一个动态网站的处理,并且采用类似jetty的嵌入启动方式,网站项目只需实现Controller和View页面并引入该项目jar包即可。 11 | 已完成主要功能如下: 12 | 20 | 21 | 如何使用 22 | ----------------- 23 | easy-httpserver项目内也有测试代码,可自行研究。这里介绍test-httpserver示例项目的使用,其中已经实现了一些例子,可参照这些例子实现。 24 | 54 | 55 | 项目结构 56 | ----------------- 57 | 项目采用eclipse开发,并使用maven构建。 58 |

~src/main/java
  --org.eh.core
      --annotation
           AnnocationHandler.java   注解处理类
           Controller.java    Controller注解
       RequestMapping    请求方法注解,用来标注Controller中的处理方法
      --common
           Constants.java    常量类,包括系统常量和配置文件对应信息
           ReturnType.java    枚举,返回类型
      --http
           EHHttpHandler.java    httpserver请求核心处理类,完成请求的接收、处理、返回
           EHServer.java    项目启动类,完成服务器启动
       ApplicationContext.java   全局数据和会话相关数据,单例
       HttpSession.java   session会话
      --model
           FileInfo.java    上传文件信息封装
           ResultInfo.java    Controller返回结果
      --util
           FileUploadContentAnalysis.java    上传请求解析类,从中提取表单中的域值和文件信息
           FileUtil.java   文件工具类
           IOUtil.java    IO工具类
           PropertyUtil.java    配置文件工具类
           StringUtil.java    字符串工具类
           VelocityUtil.java    Velocity工具类
      --web
         --controller
              Controller.java    Controller接口,实现类必须继承Controller且标记Controller注解,实现方法必须标记RequestMapping注解
         --view
              ViewHandler.java    View处理类,完成页面文件渲染
~src/main/resources
     velocity.properties
     web.properties

59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | org.eh.http 6 | easy-httpserver 7 | 0.0.1 8 | jar 9 | 10 | easy-httpserver 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | commons-logging 20 | commons-logging 21 | 1.1.3 22 | 23 | 24 | org.apache.velocity 25 | velocity 26 | 1.7 27 | 28 | 29 | org.apache.velocity 30 | velocity-tools 31 | 2.0 32 | 33 | 34 | junit 35 | junit 36 | 4.10 37 | 38 | 39 | 40 | 41 | easy-httpserver 42 | 43 | 44 | ${basedir}/src/main/resources 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/annotation/AnnocationHandler.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.annotation; 2 | 3 | import java.io.File; 4 | import java.lang.reflect.Method; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import org.eh.core.common.Constants; 10 | 11 | /** 12 | * 注解处理类 13 | * @author guojing 14 | * @date 2014-3-5 15 | */ 16 | public class AnnocationHandler { 17 | 18 | /** 19 | * 将所有注解Controller加入Constants.UrlClassMap 20 | * @param parkage 类名(包含包路径) 21 | */ 22 | @SuppressWarnings({ "unchecked", "rawtypes" }) 23 | public void paserControllerAnnocation(String parkage) throws ClassNotFoundException { 24 | List classlist = getPkgClass(parkage); 25 | for (String str : classlist) { 26 | Class c = Class.forName(str); 27 | if (c.isAnnotationPresent(Controller.class)) { 28 | Controller desc = (Controller) c.getAnnotation(Controller.class); 29 | Constants.UrlClassMap.put(desc.url(), str); 30 | } 31 | } 32 | } 33 | 34 | /** 35 | * 获取指定包下的所有类名(包含包名) 36 | * @param parkage 指定包名 37 | * @return 38 | */ 39 | public List getPkgClass(String parkage) { 40 | String path = Constants.CLASS_PATH + parkage.replace(".", "/") + "/"; 41 | List list = new ArrayList(); 42 | 43 | File file = new File(path); 44 | for (String str : file.list()) { 45 | if (str.endsWith(".class")) { 46 | list.add(parkage + "." + str.replace(".class", "")); 47 | } else if (str.indexOf(".") == -1) { 48 | list.addAll(getPkgClass(parkage + "." + str)); 49 | } 50 | } 51 | 52 | return list; 53 | } 54 | 55 | /** 56 | * 获取类的指定方法 57 | * @param c 58 | * @param methodName 59 | */ 60 | @SuppressWarnings({ "unchecked", "rawtypes" }) 61 | public Method getMethod(Class c, String methodName) throws NoSuchMethodException, 62 | SecurityException { 63 | Method method = c.getMethod(methodName, Map.class); 64 | return method.isAnnotationPresent(RequestMapping.class) ? method : null; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/annotation/Controller.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Controller注解 11 | * @author guojing 12 | * @date 2014-3-5 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.TYPE) 16 | @Documented 17 | public @interface Controller { 18 | 19 | /** 20 | * controller名,暂时无用 21 | */ 22 | public String name(); 23 | 24 | /** 25 | * 对应url请求路径,如htp://127.0.0.1/test/list.do 则对应 controller为:/test/,对应方法为:list 26 | */ 27 | public String url(); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/annotation/RequestMapping.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 方法映射注解 11 | * @author guojing 12 | * @date 2014-3-13 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.METHOD) 16 | @Documented 17 | public @interface RequestMapping { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/common/Constants.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.common; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import org.apache.commons.logging.Log; 10 | import org.apache.commons.logging.LogFactory; 11 | import org.eh.core.util.PropertyUtil; 12 | 13 | /** 14 | * 15 | * @author guojing 16 | * @date 2014-3-3 17 | */ 18 | public class Constants { 19 | private static final Log log = LogFactory.getLog(Constants.class); 20 | 21 | /* 配置信息 */ 22 | public static String PACKAGE_PREFIX = "org.eh.web."; // 包前缀 23 | public static String VIEW_BASE_PATH = ""; // 路径 24 | public static String STATIC_RESOURCE_PATH = ""; // 静态文件路径 25 | public static String CLASS_PATH = "";//classes文件夹路径 26 | 27 | public static Map UrlClassMap = new HashMap(); // url与class映射 28 | public static Map OTHER_CONFIG_INFO = new HashMap(); // 其他配置信息 29 | public static List STATIC_SUFFIXS = new ArrayList(Arrays.asList(".css", ".js", 30 | ".jpg", ".png", ".gif", ".html")); // 静态文件后缀 31 | 32 | /* 常量值 */ 33 | public static String PROPERTIES_NAME = "web.properties"; // 配置文件名 34 | public static String PROPERTIES_VELOCITY_NAME = "velocity.properties"; // 配置文件名 35 | public static String PROPERTIES_CONTROLLER_PACKAGE = "controller.package"; // controller配置文件中属性名 36 | public static String PROPERTIES_HPPTSERVER_PORT = "httpserver.port"; // 服务端口名 37 | public static String SESSION_TIMEOUT = "session_timeout"; // 服务端口名 38 | 39 | public static void loadFromProp(String path) { 40 | Map map = new HashMap(); 41 | try { 42 | map = PropertyUtil.analysisProperties(path); 43 | } catch (Exception e) { 44 | log.error("配置文件不存在!", e); 45 | } 46 | 47 | for (String key : map.keySet()) { 48 | if (key.equals("PACKAGE_PREFIX")) { 49 | PACKAGE_PREFIX = map.get(key).toString(); 50 | } else if (key.equals("VIEW_BASE_PATH")) { 51 | VIEW_BASE_PATH = map.get(key).toString(); 52 | } else if (key.startsWith("url")) { 53 | UrlClassMap.put(key.replace("url", ""), map.get(key).toString()); 54 | } else { 55 | OTHER_CONFIG_INFO.put(key, map.get(key).toString()); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/common/ReturnType.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.common; 2 | 3 | /** 4 | * 5 | * @author guojing 6 | * @date 2014-3-7 7 | */ 8 | public enum ReturnType { 9 | velocity, redirect, json 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/http/ApplicationContext.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.http; 2 | 3 | import java.util.Date; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Set; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | import java.util.concurrent.ConcurrentMap; 9 | 10 | import org.eh.core.util.StringUtil; 11 | 12 | import com.sun.net.httpserver.HttpExchange; 13 | 14 | /** 15 | * 全局数据和会话相关数据,单例 16 | * @author guojing 17 | * @date 2014-3-17 18 | */ 19 | public class ApplicationContext { 20 | 21 | private Map appMap = new HashMap(); // ApplicationContext全局数据 22 | 23 | /** 24 | * 这里自己也有点搞不清sessionMap是不是有必要考虑线程安全 25 | */ 26 | private ConcurrentMap sessionMap = new ConcurrentHashMap(); // session数据 27 | 28 | private ApplicationContext(){ 29 | 30 | } 31 | 32 | /** 33 | * 内部类实现单例 34 | */ 35 | private static class ApplicationContextHolder { 36 | private static ApplicationContext instance = new ApplicationContext(); 37 | } 38 | 39 | public static ApplicationContext getApplicationContext() { 40 | return ApplicationContextHolder.instance; 41 | } 42 | 43 | public void addAttribute(String name, Object value) { 44 | ApplicationContextHolder.instance.appMap.put(name, value); 45 | } 46 | 47 | public Object getAttribute(String name) { 48 | return ApplicationContextHolder.instance.appMap.get(name); 49 | } 50 | 51 | public Map getAllAttribute() { 52 | return ApplicationContextHolder.instance.appMap; 53 | } 54 | 55 | public Set getAllNames() { 56 | return ApplicationContextHolder.instance.appMap.keySet(); 57 | } 58 | 59 | public boolean containsName(String name) { 60 | return ApplicationContextHolder.instance.appMap.containsKey(name); 61 | } 62 | 63 | public void addSession(String sessionId) { 64 | HttpSession httpSession = new HttpSession(); 65 | httpSession.setLastVisitTime(new Date()); 66 | ApplicationContextHolder.instance.sessionMap.put(sessionId, httpSession); 67 | } 68 | 69 | /** 70 | * 获取session 71 | */ 72 | public HttpSession getSession(HttpExchange httpExchange) { 73 | String sessionId = getSessionId(httpExchange); 74 | if (StringUtil.isEmpty(sessionId)) { 75 | return null; 76 | } 77 | HttpSession httpSession = ApplicationContextHolder.instance.sessionMap.get(sessionId); 78 | if (null == httpSession) { 79 | httpSession = new HttpSession(); 80 | ApplicationContextHolder.instance.sessionMap.put(sessionId, httpSession); 81 | } 82 | return httpSession; 83 | } 84 | 85 | /** 86 | * 获取sessionId 87 | */ 88 | public String getSessionId(HttpExchange httpExchange) { 89 | String cookies = httpExchange.getRequestHeaders().getFirst("Cookie"); 90 | String sessionId = ""; 91 | if (StringUtil.isEmpty(cookies)) { 92 | cookies = httpExchange.getResponseHeaders().getFirst("Set-Cookie"); 93 | } 94 | 95 | if (StringUtil.isEmpty(cookies)) { 96 | return null; 97 | } 98 | 99 | String[] cookiearry = cookies.split(";"); 100 | for(String cookie : cookiearry){ 101 | cookie = cookie.replaceAll(" ", ""); 102 | if (cookie.startsWith("EH_SESSION=")) { 103 | sessionId = cookie.replace("EH_SESSION=", "").replace(";", ""); 104 | } 105 | } 106 | 107 | return sessionId; 108 | } 109 | 110 | /** 111 | * 获取所有session 112 | */ 113 | public ConcurrentMap getAllSession() { 114 | return ApplicationContextHolder.instance.sessionMap; 115 | } 116 | 117 | /** 118 | * 设置session最后访问时间 119 | */ 120 | public void setSessionLastTime(String sessionId) { 121 | HttpSession httpSession = ApplicationContextHolder.instance.sessionMap.get(sessionId); 122 | httpSession.setLastVisitTime(new Date()); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/http/EHHttpHandler.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.http; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.io.UnsupportedEncodingException; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | import java.net.URI; 9 | import java.net.URLDecoder; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import org.apache.commons.logging.Log; 14 | import org.apache.commons.logging.LogFactory; 15 | import org.eh.core.annotation.AnnocationHandler; 16 | import org.eh.core.common.Constants; 17 | import org.eh.core.common.ReturnType; 18 | import org.eh.core.model.ResultInfo; 19 | import org.eh.core.util.FileUploadContentAnalysis; 20 | import org.eh.core.util.IOUtil; 21 | import org.eh.core.util.StringUtil; 22 | import org.eh.core.web.controller.Controller; 23 | import org.eh.core.web.view.ViewHandler; 24 | 25 | import com.sun.net.httpserver.Headers; 26 | import com.sun.net.httpserver.HttpExchange; 27 | import com.sun.net.httpserver.HttpHandler; 28 | 29 | /** 30 | * 处理Http请求 31 | * @author guojing 32 | * @date 2014-3-3 33 | */ 34 | public class EHHttpHandler implements HttpHandler { 35 | private final Log log = LogFactory.getLog(EHHttpHandler.class); 36 | 37 | public void handle(HttpExchange httpExchange) throws IOException { 38 | try { 39 | String path = httpExchange.getRequestURI().getPath(); 40 | log.info("Receive a request,Request path:" + path); 41 | 42 | // 设置sessionId 43 | String sessionId = ApplicationContext.getApplicationContext() 44 | .getSessionId(httpExchange); 45 | if (StringUtil.isEmpty(sessionId)) { 46 | sessionId = StringUtil.creatSession(); 47 | ApplicationContext.getApplicationContext().addSession(sessionId); 48 | } 49 | 50 | httpExchange.getResponseHeaders().set("Set-Cookie", 51 | "EH_SESSION=" + sessionId + "; path=/"); 52 | 53 | // 根据后缀判断是否是静态资源 54 | String suffix = path.substring(path.lastIndexOf("."), path.length()); 55 | if (Constants.STATIC_SUFFIXS.contains(suffix)) { 56 | byte[] bytes = IOUtil.readFileByBytes(Constants.CLASS_PATH 57 | + "static" + path); 58 | responseStaticToClient(httpExchange, 200, bytes); 59 | return; 60 | } 61 | 62 | // 调用对应处理程序controller 63 | ResultInfo resultInfo = invokController(httpExchange); 64 | 65 | // 返回404 66 | if (resultInfo == null || StringUtil.isEmpty(resultInfo.getView())) { 67 | responseToClient(httpExchange, 200, "

页面不存在

"); 68 | return; 69 | } 70 | 71 | String viewPath = resultInfo.getView(); 72 | if (viewPath.startsWith(ReturnType.redirect.name())) {// redirect跳转 73 | String redirectUrl = viewPath.replace(ReturnType.redirect.name() + ":", ""); 74 | responseToClient(httpExchange, 302, redirectUrl); 75 | return; 76 | } else if (viewPath.startsWith(ReturnType.json.name())) { // 返回json数据 77 | String jsonContent = viewPath.replace(ReturnType.json.name() + ":", ""); 78 | responseToClient(httpExchange, 200, jsonContent); 79 | return; 80 | } else if (viewPath.startsWith(ReturnType.velocity.name())) { // 解析对应view并返回 81 | String content = invokViewHandler(resultInfo); 82 | if (content == null) { 83 | content = ""; 84 | } 85 | responseToClient(httpExchange, 200, content); 86 | return; 87 | } else { 88 | responseToClient(httpExchange, 200, resultInfo.getView()); 89 | return; 90 | } 91 | 92 | } catch (Exception e) { 93 | httpExchange.close(); 94 | log.error("响应请求失败:", e); 95 | } 96 | } 97 | 98 | /** 99 | * 响应请求 100 | * @param httpExchange 请求-响应的封装 101 | * @param code 返回状态码 102 | * @param msg 返回信息 103 | * @throws IOException 104 | */ 105 | private void responseToClient(HttpExchange httpExchange, Integer code, String msg) 106 | throws IOException { 107 | 108 | switch (code) { 109 | case 200: { // 成功 110 | byte[] bytes = msg.getBytes(); 111 | httpExchange.sendResponseHeaders(code, bytes.length); 112 | OutputStream out = httpExchange.getResponseBody(); 113 | out.write(bytes); 114 | out.flush(); 115 | httpExchange.close(); 116 | } 117 | break; 118 | case 302: { // 跳转 119 | Headers headers = httpExchange.getResponseHeaders(); 120 | headers.add("Location", msg); 121 | httpExchange.sendResponseHeaders(code, 0); 122 | httpExchange.close(); 123 | } 124 | break; 125 | case 404: { // 错误 126 | byte[] bytes = "".getBytes(); 127 | httpExchange.sendResponseHeaders(code, bytes.length); 128 | OutputStream out = httpExchange.getResponseBody(); 129 | out.write(bytes); 130 | out.flush(); 131 | httpExchange.close(); 132 | } 133 | break; 134 | default: 135 | break; 136 | } 137 | } 138 | 139 | /** 140 | * 响应请求,返回静态资源 141 | * @param httpExchange 142 | * @param code 143 | * @param bytes 144 | * @throws IOException 145 | */ 146 | private void responseStaticToClient(HttpExchange httpExchange, Integer code, byte[] bytes) 147 | throws IOException { 148 | httpExchange.sendResponseHeaders(code, bytes.length); 149 | OutputStream out = httpExchange.getResponseBody(); 150 | out.write(bytes); 151 | out.flush(); 152 | httpExchange.close(); 153 | } 154 | 155 | /** 156 | * 调用对应Controller处理业务 157 | */ 158 | @SuppressWarnings("rawtypes") 159 | private ResultInfo invokController(HttpExchange httpExchange) throws ClassNotFoundException, 160 | InstantiationException, IllegalAccessException, IOException, NoSuchMethodException, 161 | SecurityException, IllegalArgumentException, InvocationTargetException { 162 | String path = httpExchange.getRequestURI().getPath(); 163 | 164 | String classPath = Constants.UrlClassMap.get(path.substring(0, path.lastIndexOf("/") + 1)); 165 | if (classPath == null || classPath.length() == 0) { 166 | return null; 167 | } 168 | Class controllerClass = Class.forName(classPath); 169 | Controller controller = (Controller) controllerClass.newInstance(); 170 | 171 | String methodName = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf(".")); 172 | //通过反射获取对应方法 173 | AnnocationHandler annocationHandler = new AnnocationHandler(); 174 | Method method = annocationHandler.getMethod(controllerClass, methodName); 175 | 176 | Map map = null; // 参数 177 | // 判断表单类型,若是multipart/form-data,则是文件上传;否则做普通处理 178 | Headers headers = httpExchange.getRequestHeaders(); 179 | // 获取ContentType 180 | String contentType = ""; 181 | if(null != headers.get("Content-type")){ 182 | contentType = headers.get("Content-type").toString().replace("[", "") 183 | .replace("]", ""); 184 | } 185 | 186 | if (contentType.indexOf("multipart/form-data") != -1) { 187 | // 获取content长度 188 | int length = Integer.parseInt(headers.get("Content-length").toString().replace("[", "") 189 | .replace("]", "")); 190 | map = FileUploadContentAnalysis.parse(httpExchange.getRequestBody(), contentType, 191 | length); 192 | } else { 193 | map = analysisParms(httpExchange); 194 | } 195 | 196 | // 设置session 197 | HttpSession httpSession = ApplicationContext.getApplicationContext().getSession( 198 | httpExchange); 199 | map.put("session", httpSession); 200 | 201 | return (ResultInfo) method.invoke(controller, new Object[] { map }); 202 | } 203 | 204 | /** 205 | * 调用ViewHandler渲染视图 206 | */ 207 | private String invokViewHandler(ResultInfo resultInfo) throws IOException { 208 | ViewHandler viewHandler = new ViewHandler(); 209 | // return viewHandler.processView(resultInfo); 210 | return viewHandler.processVelocityView(resultInfo); 211 | } 212 | 213 | /** 214 | * 解析参数 215 | */ 216 | private Map analysisParms(HttpExchange httpExchange) 217 | throws UnsupportedEncodingException { 218 | Map map = new HashMap(); 219 | 220 | URI requestedUri = httpExchange.getRequestURI(); 221 | String queryGet = requestedUri.getRawQuery(); 222 | String queryPost = IOUtil.getRequestContent(httpExchange.getRequestBody()); 223 | String query = ""; 224 | if (!StringUtil.isEmpty(queryGet)) { 225 | query = queryGet; 226 | } 227 | if (!StringUtil.isEmpty(queryPost)) { 228 | query = StringUtil.isEmpty(query) ? queryPost : (query + "&" + queryPost); 229 | } 230 | if (StringUtil.isEmpty(query)) { 231 | return map; 232 | } 233 | 234 | for (String kv : query.split("&")) { 235 | String[] temp = kv.split("="); 236 | map.put(temp[0], URLDecoder.decode(temp[1], "utf-8")); 237 | } 238 | return map; 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/http/EHServer.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.http; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.util.Date; 6 | import java.util.Timer; 7 | 8 | import org.apache.commons.logging.Log; 9 | import org.apache.commons.logging.LogFactory; 10 | import org.apache.velocity.app.Velocity; 11 | import org.eh.core.annotation.AnnocationHandler; 12 | import org.eh.core.common.Constants; 13 | import org.eh.core.task.SessionCleanTask; 14 | 15 | import com.sun.net.httpserver.HttpServer; 16 | import com.sun.net.httpserver.spi.HttpServerProvider; 17 | 18 | /** 19 | * 主服务类 20 | * @author guojing 21 | * @date 2014-3-3 22 | */ 23 | public class EHServer { 24 | private final Log log = LogFactory.getLog(EHServer.class); 25 | 26 | /** 27 | * 初始化信息,并启动server 28 | */ 29 | public void startServer() throws IOException { 30 | log.info("Starting EHServer......"); 31 | log.info("Loading configuration......"); 32 | 33 | //设置classes文件夹路径 34 | Constants.CLASS_PATH = this.getClass().getResource("/").getPath().replace("bin", "classes"); 35 | // 加载配置文件 36 | String propPath = Constants.CLASS_PATH + Constants.PROPERTIES_NAME; 37 | Constants.loadFromProp(propPath); 38 | 39 | 40 | // 加载注解配置的controller 41 | if (Constants.OTHER_CONFIG_INFO.get(Constants.PROPERTIES_CONTROLLER_PACKAGE) != null) { 42 | AnnocationHandler annocationHandler = new AnnocationHandler(); 43 | try { 44 | annocationHandler.paserControllerAnnocation(Constants.OTHER_CONFIG_INFO.get( 45 | Constants.PROPERTIES_CONTROLLER_PACKAGE).toString()); 46 | } catch (Exception e) { 47 | log.error("加载controller配置出错!", e); 48 | return; 49 | } 50 | } 51 | 52 | // 初始化Velocity模板 53 | log.info("Initializing velocity......"); 54 | Velocity.init(Constants.CLASS_PATH 55 | + Constants.PROPERTIES_VELOCITY_NAME); 56 | 57 | for (String key : Constants.UrlClassMap.keySet()) { 58 | log.info("Add url-class:" + key + " " + Constants.UrlClassMap.get(key)); 59 | } 60 | 61 | int port = 8899; 62 | //设置端口号 63 | String portValue = Constants.OTHER_CONFIG_INFO.get(Constants.PROPERTIES_HPPTSERVER_PORT); 64 | log.info("Set port:" + portValue); 65 | if (portValue != null) { 66 | try { 67 | port = Integer.parseInt(portValue); 68 | } catch (Exception e) { 69 | log.error("端口错误!", e); 70 | return; 71 | } 72 | } 73 | 74 | //启动session过期清理定时器 75 | Timer timer = new Timer(); 76 | SessionCleanTask sessionCleanTask = new SessionCleanTask(); 77 | int session_timeout = Integer.parseInt(Constants.OTHER_CONFIG_INFO 78 | .get(Constants.SESSION_TIMEOUT)); 79 | log.info("Initializing SessionCleanTask,the session_out_time is " + session_timeout * 2 80 | + " minute."); 81 | timer.schedule(sessionCleanTask, new Date(), session_timeout * 30 * 1000); 82 | 83 | // 启动服务器 84 | HttpServerProvider provider = HttpServerProvider.provider(); 85 | HttpServer httpserver = provider.createHttpServer(new InetSocketAddress(port), 100); 86 | httpserver.createContext("/", new EHHttpHandler()); 87 | httpserver.setExecutor(null); 88 | httpserver.start(); 89 | log.info("EHServer has started"); 90 | } 91 | 92 | /** 93 | * 项目main 94 | */ 95 | public static void main(String[] args) throws IOException { 96 | new EHServer().startServer(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/http/HttpSession.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.http; 2 | 3 | import java.util.Date; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | /** 9 | * session数据 10 | * @author guojing 11 | * @date 2014-3-17 12 | */ 13 | public class HttpSession { 14 | 15 | Map map = new HashMap(); 16 | 17 | Date lastVisitTime = new Date(); // 最后访问时间 18 | 19 | public void addAttribute(String name, Object value) { 20 | map.put(name, value); 21 | } 22 | 23 | public Object getAttribute(String name) { 24 | return map.get(name); 25 | } 26 | 27 | public Map getAllAttribute() { 28 | return map; 29 | } 30 | 31 | public Set getAllNames() { 32 | return map.keySet(); 33 | } 34 | 35 | public boolean containsName(String name) { 36 | return map.containsKey(name); 37 | } 38 | 39 | public Map getMap() { 40 | return map; 41 | } 42 | 43 | public void setMap(Map map) { 44 | this.map = map; 45 | } 46 | 47 | public Date getLastVisitTime() { 48 | return lastVisitTime; 49 | } 50 | 51 | public void setLastVisitTime(Date lastVisitTime) { 52 | this.lastVisitTime = lastVisitTime; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/model/FileInfo.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.model; 2 | 3 | /** 4 | * 上传文件信息 5 | * @author guojing 6 | * @date 2014-3-3 7 | */ 8 | public class FileInfo { 9 | 10 | private String filename; //文件名 11 | private String fieldname; // 表单中参数名 12 | private int length; //文件长度 13 | private byte[] bytes; //文件字节数组 14 | 15 | public String getFilename() { 16 | return filename; 17 | } 18 | public void setFilename(String filename) { 19 | this.filename = filename; 20 | } 21 | public int getLength() { 22 | return length; 23 | } 24 | public void setLength(int length) { 25 | this.length = length; 26 | } 27 | public byte[] getBytes() { 28 | return bytes; 29 | } 30 | public void setBytes(byte[] bytes) { 31 | this.bytes = bytes; 32 | } 33 | 34 | public String getFieldname() { 35 | return fieldname; 36 | } 37 | 38 | public void setFieldname(String fieldname) { 39 | this.fieldname = fieldname; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/model/ResultInfo.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.model; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * Controller处理结果 7 | * @author guojing 8 | * @date 2014-3-3 9 | */ 10 | public class ResultInfo { 11 | 12 | private String view; // 对应页面路径 13 | private Map resultMap; // 返回参数值 14 | 15 | public String getView() { 16 | return view; 17 | } 18 | 19 | public void setView(String view) { 20 | this.view = view; 21 | } 22 | 23 | public Map getResultMap() { 24 | return resultMap; 25 | } 26 | 27 | public void setResultMap(Map resultMap) { 28 | this.resultMap = resultMap; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/task/SessionCleanTask.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.task; 2 | 3 | import java.util.Date; 4 | import java.util.Iterator; 5 | import java.util.Map; 6 | import java.util.Map.Entry; 7 | import java.util.TimerTask; 8 | import java.util.concurrent.ConcurrentMap; 9 | 10 | import org.apache.commons.logging.Log; 11 | import org.apache.commons.logging.LogFactory; 12 | import org.eh.core.common.Constants; 13 | import org.eh.core.http.ApplicationContext; 14 | import org.eh.core.http.HttpSession; 15 | 16 | /** 17 | * 定时清理过期session 18 | * @author guojing 19 | * @date 2014-3-17 20 | */ 21 | public class SessionCleanTask extends TimerTask { 22 | private final Log log = LogFactory.getLog(SessionCleanTask.class); 23 | 24 | @Override 25 | public void run() { 26 | log.info("清理session......"); 27 | ConcurrentMap sessionMap = ApplicationContext.getApplicationContext() 28 | .getAllSession(); 29 | 30 | Iterator> it = sessionMap.entrySet().iterator(); 31 | while (it.hasNext()) { 32 | ConcurrentMap.Entry entry= (Entry) it.next(); 33 | HttpSession httpSession= entry.getValue(); 34 | 35 | Date nowDate = new Date(); 36 | int diff = (int) ((nowDate.getTime() - httpSession.getLastVisitTime().getTime())/1000/60); 37 | 38 | if (diff > Integer.parseInt(Constants.OTHER_CONFIG_INFO.get(Constants.SESSION_TIMEOUT))) { 39 | it.remove(); 40 | } 41 | } 42 | 43 | log.info("清理session结束"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/util/FileUploadContentAnalysis.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.DataInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.StringReader; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import org.eh.core.model.FileInfo; 12 | 13 | /** 14 | * 解析content获取上传文件表单信息 15 | * @author 自己写的老有问题,一怒之下copy了一份。不过这个也有些问题,由于office不同版本的Content-Type格式不固定, 所以office文件上传生成的文件一般会少几个字节,以后有心情了再改吧 16 | * @date 2014-3-10 17 | */ 18 | public class FileUploadContentAnalysis { 19 | static final int NONE = 0; 20 | static final int DATAHEADER = 1; 21 | static final int FILEDATA = 2; 22 | static final int FIELDDATA = 3; 23 | static final int MXA_SEGSIZE = 1000 * 1024 * 10; //最大文件长度 24 | 25 | public static Map parse(InputStream ins, String contentType, int totalLength) 26 | throws IOException { 27 | 28 | FileInfo fileInfo =new FileInfo(); 29 | String fieldname = ""; // 表单域的名称 30 | String fieldvalue = ""; // 表单域的值 31 | String filename = ""; // 文件名 32 | String boundary = ""; // 分界符 33 | String lastboundary = ""; // 结束符 34 | String filefieldname = ""; // 文件表单域名 35 | Map formfields = new HashMap(); 36 | int filesize = 0; // 文件长度 37 | 38 | int pos = contentType.indexOf("boundary="); 39 | 40 | if (pos != -1) { // 取得分界符和结束符 41 | pos += "boundary=".length(); 42 | boundary = "--" + contentType.substring(pos); 43 | lastboundary = boundary + "--"; 44 | } 45 | int state = NONE; 46 | // 得到数据输入流reqbuf 47 | DataInputStream in = new DataInputStream(ins); 48 | // 将请求消息的实体送到b变量中 49 | int totalBytes = totalLength; 50 | if (totalBytes > MXA_SEGSIZE) {// 每批大于10m时 51 | return null; 52 | } 53 | byte[] b = new byte[totalBytes]; 54 | in.readFully(b); 55 | in.close(); 56 | String reqContent = new String(b, "UTF-8");// 57 | BufferedReader reqbuf = new BufferedReader(new StringReader(reqContent)); 58 | 59 | boolean flag = true; 60 | while (flag == true) { 61 | String s = reqbuf.readLine(); 62 | if ((s == null) || (s.equals(lastboundary))) 63 | break; 64 | 65 | switch (state) { 66 | case NONE: 67 | if (s.startsWith(boundary)) { 68 | state = DATAHEADER; 69 | } 70 | break; 71 | case DATAHEADER: 72 | pos = s.indexOf("filename="); 73 | if (pos == -1) { // 将表单域的名字解析出来 74 | pos = s.indexOf("name="); 75 | pos += "name=".length() + 1; 76 | s = s.substring(pos); 77 | int l = s.length(); 78 | s = s.substring(0, l - 1); 79 | fieldname = s; 80 | state = FIELDDATA; 81 | } else { 82 | String temp = s; 83 | // 将文件表单参数名解析出来 84 | pos = s.indexOf("name="); 85 | pos += "name=".length() + 1; 86 | s = s.substring(pos); 87 | int pos1 = s.indexOf("\";"); 88 | filefieldname = s.substring(0, pos1); 89 | 90 | // 将文件名解析出来 91 | pos = s.indexOf("filename="); 92 | pos += "filename=".length() + 1; 93 | s = s.substring(pos); 94 | int l = s.length(); 95 | s = s.substring(0, l - 1);// 去掉最后那个引号” 96 | pos = s.lastIndexOf("\\"); 97 | s = s.substring(pos + 1); 98 | filename = s; 99 | // 从字节数组中取出文件数组 100 | pos = byteIndexOf(b, temp, 0); 101 | b = subBytes(b, pos + temp.getBytes().length + 2, b.length);// 去掉前面的部分 102 | int n = 0; 103 | /** 104 | * 过滤boundary下形如 Content-Disposition: form-data; name="bin"; filename="12.pdf" Content-Type: 105 | * application/octet-stream Content-Transfer-Encoding: binary 的字符串 106 | */ 107 | while ((s = reqbuf.readLine()) != null) { 108 | if (n == 1) 109 | break; 110 | if (s.equals("")) 111 | n++; 112 | 113 | b = subBytes(b, s.getBytes().length + 2, b.length); 114 | } 115 | pos = byteIndexOf(b, boundary, 0); 116 | if (pos != -1) 117 | b = subBytes(b, 0, pos - 1); 118 | 119 | filesize = b.length - 1; 120 | state = FILEDATA; 121 | } 122 | break; 123 | case FIELDDATA: 124 | s = reqbuf.readLine(); 125 | fieldvalue = s; 126 | formfields.put(fieldname, fieldvalue); 127 | state = NONE; 128 | break; 129 | case FILEDATA: 130 | while ((!s.startsWith(boundary)) && (!s.startsWith(lastboundary))) { 131 | s = reqbuf.readLine(); 132 | if (s.startsWith(boundary)) { 133 | state = DATAHEADER; 134 | break; 135 | } 136 | } 137 | break; 138 | } 139 | } 140 | fileInfo.setFieldname(filefieldname); 141 | fileInfo.setBytes(b); 142 | fileInfo.setFilename(filename); 143 | fileInfo.setLength(filesize); 144 | formfields.put(filefieldname, fileInfo); 145 | return formfields; 146 | 147 | } 148 | 149 | // 字节数组中的INDEXOF函数,与STRING类中的INDEXOF类似 150 | public static int byteIndexOf(byte[] b, String s, int start) { 151 | return byteIndexOf(b, s.getBytes(), start); 152 | } 153 | 154 | // 字节数组中的INDEXOF函数,与STRING类中的INDEXOF类似 155 | public static int byteIndexOf(byte[] b, byte[] s, int start) { 156 | int i; 157 | if (s.length == 0) { 158 | return 0; 159 | } 160 | int max = b.length - s.length; 161 | if (max < 0) 162 | return -1; 163 | if (start > max) 164 | return -1; 165 | if (start < 0) 166 | start = 0; 167 | search: for (i = start; i <= max; i++) { 168 | if (b[i] == s[0]) { 169 | int k = 1; 170 | while (k < s.length) { 171 | if (b[k + i] != s[k]) { 172 | continue search; 173 | } 174 | k++; 175 | } 176 | return i; 177 | } 178 | } 179 | return -1; 180 | } 181 | 182 | // 用于从一个字节数组中提取一个字节数组 183 | public static byte[] subBytes(byte[] b, int from, int end) { 184 | byte[] result = new byte[end - from]; 185 | System.arraycopy(b, from, result, 0, end - from); 186 | return result; 187 | } 188 | 189 | // 用于从一个字节数组中提取一个字符串 190 | public static String subBytesString(byte[] b, int from, int end) { 191 | return new String(subBytes(b, from, end)); 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/util/IOUtil.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.InputStreamReader; 9 | import java.nio.ByteBuffer; 10 | import java.nio.channels.FileChannel; 11 | 12 | import org.apache.commons.logging.Log; 13 | import org.apache.commons.logging.LogFactory; 14 | 15 | /** 16 | * IO、文件处理 17 | * @author guojing 18 | * @date 2014-3-4 19 | */ 20 | public class IOUtil { 21 | private static final Log log = LogFactory.getLog(IOUtil.class); 22 | public static String getRequestContent(InputStream inputStream) { 23 | if (inputStream == null) { 24 | return null; 25 | } 26 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 27 | StringBuilder sb = new StringBuilder(); 28 | try { 29 | String temp = null; 30 | while ((temp = reader.readLine()) != null) { 31 | sb.append(temp); 32 | } 33 | } catch (IOException e) { 34 | log.error("读取请求内容错误:", e); 35 | } 36 | return sb.toString(); 37 | } 38 | 39 | public static boolean isExist(String path) { 40 | File file = new File(path); 41 | return file.exists(); 42 | } 43 | 44 | public static String readFile(String path) { 45 | if (!isExist(path)) { 46 | return ""; 47 | } 48 | FileInputStream fis = null; 49 | StringBuilder sb = new StringBuilder(); 50 | try { 51 | fis = new FileInputStream(path); 52 | FileChannel c = fis.getChannel(); 53 | ByteBuffer bc = ByteBuffer.allocate(1024); 54 | int i = c.read(bc); 55 | while (i != -1) { 56 | sb.append(new String(bc.array())); 57 | bc.clear(); 58 | i = c.read(bc); 59 | } 60 | c.close(); 61 | fis.close(); 62 | } catch (Exception e) { 63 | log.error("读取模板文件失败:", e); 64 | } 65 | return sb.toString(); 66 | } 67 | 68 | public static byte[] readFileByBytes(String path) { 69 | if (!isExist(path)) { 70 | return "".getBytes(); 71 | } 72 | byte[] bytes = null; 73 | FileInputStream fis = null; 74 | try { 75 | fis = new FileInputStream(path); 76 | FileChannel c = fis.getChannel(); 77 | ByteBuffer bc = ByteBuffer.allocate((int) c.size()); 78 | int i = c.read(bc); 79 | if (i != -1) { 80 | bytes = bc.array(); 81 | } 82 | c.close(); 83 | fis.close(); 84 | } catch (Exception e) { 85 | log.error("读取资源文件失败:", e); 86 | } 87 | return bytes; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/util/PropertyUtil.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.util; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.FileInputStream; 5 | import java.io.InputStream; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.Properties; 9 | 10 | import org.apache.commons.logging.Log; 11 | import org.apache.commons.logging.LogFactory; 12 | 13 | /** 14 | * 配置文件工具类 15 | * @author guojing 16 | * @date 2014-3-4 17 | */ 18 | public class PropertyUtil { 19 | private static final Log log = LogFactory.getLog(PropertyUtil.class); 20 | public static Map analysisProperties(String path) { 21 | Map map = new HashMap(); 22 | Properties props = new Properties(); 23 | try { 24 | InputStream in = new BufferedInputStream(new FileInputStream(path)); 25 | props.load(in); 26 | for (String key : props.stringPropertyNames()) { 27 | map.put(key, props.get(key).toString()); 28 | } 29 | } catch (Exception e) { 30 | log.error("配置文件解析错误:", e); 31 | } 32 | return map; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/util/StringUtil.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.util; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * 字符串工具类 7 | * @author guojing 8 | * @date 2014-3-4 9 | */ 10 | public class StringUtil { 11 | 12 | public static boolean isEmpty(String str) { 13 | return str == null || str.length() == 0; 14 | } 15 | 16 | public static String creatSession() { 17 | UUID uuid = UUID.randomUUID(); 18 | return uuid.toString(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/util/VelocityUtil.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.util; 2 | 3 | import java.io.IOException; 4 | import java.io.StringWriter; 5 | import java.util.Map; 6 | 7 | import org.apache.velocity.VelocityContext; 8 | import org.apache.velocity.app.Velocity; 9 | 10 | /** 11 | * Velocity解析类 12 | * @author guojing 13 | * @date 2014-3-10 14 | */ 15 | public class VelocityUtil { 16 | 17 | /** 18 | * 渲染Velocity模板 19 | * @param path 20 | * @param map 21 | */ 22 | public static String mergeTemplate(String path, Map map) throws IOException { 23 | VelocityContext vc = new VelocityContext(); 24 | if (null != map) { 25 | for (String key : map.keySet()) { 26 | vc.put(key, map.get(key)); 27 | } 28 | } 29 | StringWriter w = new StringWriter(); 30 | Velocity.mergeTemplate(path, "utf-8", vc, w); 31 | String content = w.toString(); 32 | w.close(); 33 | return content; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/web/controller/Controller.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.web.controller; 2 | 3 | 4 | /** 5 | * Controllrt接口 6 | * @author guojing 7 | * @date 2014-3-3 8 | */ 9 | public interface Controller { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/eh/core/web/view/ViewHandler.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.web.view; 2 | 3 | import java.io.IOException; 4 | 5 | import org.eh.core.common.Constants; 6 | import org.eh.core.common.ReturnType; 7 | import org.eh.core.model.ResultInfo; 8 | import org.eh.core.util.IOUtil; 9 | import org.eh.core.util.StringUtil; 10 | import org.eh.core.util.VelocityUtil; 11 | 12 | /** 13 | * 处理页面信息 14 | * @author guojing 15 | * @date 2014-3-3 16 | */ 17 | public class ViewHandler { 18 | 19 | /** 20 | * 处理View模板,只提供建单变量(格式${XXX})替换,已废弃 21 | * @return 22 | */ 23 | @Deprecated 24 | public String processView(ResultInfo resultInfo) { 25 | // 获取路径 26 | String path = analysisViewPath(resultInfo.getView()); 27 | String content = ""; 28 | if (IOUtil.isExist(path)) { 29 | content = IOUtil.readFile(path); 30 | } 31 | 32 | if (StringUtil.isEmpty(content)) { 33 | return ""; 34 | } 35 | 36 | // 替换模板中的变量,替换符格式:${XXX} 37 | for (String key : resultInfo.getResultMap().keySet()) { 38 | String temp = ""; 39 | if (null != resultInfo.getResultMap().get(key)) { 40 | temp = resultInfo.getResultMap().get(key).toString(); 41 | } 42 | content = content.replaceAll("\\$\\{" + key + "\\}", temp); 43 | } 44 | 45 | return content; 46 | } 47 | 48 | /** 49 | * 处理Velocity模板 50 | * @param resultInfo 51 | * @return 52 | * @throws IOException 53 | */ 54 | public String processVelocityView(ResultInfo resultInfo) throws IOException { 55 | if (StringUtil.isEmpty(resultInfo.getView())) { 56 | return ""; 57 | } 58 | 59 | // 获取路径 60 | String path = analysisVelocityViewPath(resultInfo.getView()); 61 | String content = VelocityUtil.mergeTemplate(path, resultInfo.getResultMap()); 62 | 63 | if (StringUtil.isEmpty(content)) { 64 | return ""; 65 | } 66 | 67 | return content; 68 | } 69 | 70 | /** 71 | * 解析路径(根据Controller返回ResultInfo的view),已废弃 72 | * @param viewPath 73 | * @return 74 | */ 75 | @Deprecated 76 | private String analysisViewPath(String viewPath) { 77 | String path = Constants.CLASS_PATH 78 | + (Constants.VIEW_BASE_PATH == null ? "/" : Constants.VIEW_BASE_PATH) 79 | + viewPath + ".page"; 80 | return path; 81 | } 82 | 83 | /** 84 | * 解析velocity路径(根据Controller返回ResultInfo的view) 85 | */ 86 | private String analysisVelocityViewPath(String viewPath) { 87 | String path = Constants.VIEW_BASE_PATH + "/" 88 | + viewPath.replace(ReturnType.velocity.name() + ":", "") + ".vm"; 89 | return path; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/resources/velocity.properties: -------------------------------------------------------------------------------- 1 | resource.loader=class 2 | class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader -------------------------------------------------------------------------------- /src/main/resources/web.properties: -------------------------------------------------------------------------------- 1 | #包前缀 2 | PACKAGE_PREFIX=org.eh.web 3 | 4 | #模板页面根路径(相对classes文件夹,项目src/main/view下) 5 | VIEW_BASE_PATH=page 6 | 7 | #静态资源路劲(相对classes文件夹,项目src/main/view下) 8 | STATIC_RESOURCE_PATH=static 9 | 10 | #端口 11 | httpserver.port=8888 12 | 13 | #controller包路径,配置后可通过annocation直接配置 14 | controller.package=com.gj.web.controller 15 | 16 | #url与controller类对应关系 17 | #url/list=com.gj.web.controller.MyController 18 | 19 | #session超时时间(分钟) 20 | session_timeout = 10 -------------------------------------------------------------------------------- /src/test/java/org/eh/core/annotation/AnnotationHandlerTest.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.annotation; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | import java.util.Map; 6 | 7 | import org.junit.Test; 8 | 9 | /** 10 | * 11 | * @author guojing 12 | * @date 2014-3-13 13 | */ 14 | public class AnnotationHandlerTest { 15 | 16 | @Test 17 | @SuppressWarnings("rawtypes") 18 | public void testMethods() { 19 | try { 20 | Class c = Class.forName("org.eh.core.controller.Test1Controller"); 21 | Method[] methods = c.getMethods(); 22 | for (Method method : methods) { 23 | if (method.isAnnotationPresent(RequestMapping.class)) { 24 | System.out.println(method.getName()); 25 | org.eh.core.web.controller.Controller controller = (org.eh.core.web.controller.Controller) c 26 | .newInstance(); 27 | method.invoke(controller, new Object[] { null }); 28 | } 29 | } 30 | } catch (ClassNotFoundException e) { 31 | e.printStackTrace(); 32 | } catch (IllegalAccessException e) { 33 | // TODO Auto-generated catch block 34 | e.printStackTrace(); 35 | } catch (IllegalArgumentException e) { 36 | // TODO Auto-generated catch block 37 | e.printStackTrace(); 38 | } catch (InvocationTargetException e) { 39 | // TODO Auto-generated catch block 40 | e.printStackTrace(); 41 | } catch (InstantiationException e) { 42 | // TODO Auto-generated catch block 43 | e.printStackTrace(); 44 | } 45 | } 46 | 47 | @Test 48 | public void testMethod() { 49 | try { 50 | Class c = Class.forName("org.eh.core.controller.Test1Controller"); 51 | Method methods = c.getMethod("add", Map.class); 52 | System.out.println(methods.getName()); 53 | } catch (ClassNotFoundException e) { 54 | e.printStackTrace(); 55 | } catch (NoSuchMethodException e) { 56 | e.printStackTrace(); 57 | } catch (SecurityException e) { 58 | e.printStackTrace(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/org/eh/core/controller/Test1Controller.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.controller; 2 | 3 | import java.util.Map; 4 | 5 | import org.eh.core.annotation.RequestMapping; 6 | import org.eh.core.web.controller.Controller; 7 | 8 | /** 9 | * 10 | * @author guojing 11 | * @date 2014-3-5 12 | */ 13 | @org.eh.core.annotation.Controller(name = "test1", url = "/test/show") 14 | public class Test1Controller implements Controller { 15 | 16 | @RequestMapping 17 | public String add(Map map) { 18 | System.out.println("aaa"); 19 | return null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/org/eh/core/controller/Test2Controller.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.controller; 2 | 3 | import org.eh.core.annotation.Controller; 4 | 5 | /** 6 | * 7 | * @author guojing 8 | * @date 2014-3-5 9 | */ 10 | @Controller(name = "test2", url = "/test/list") 11 | public interface Test2Controller { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/org/eh/core/controller/TestAnnocation.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.controller; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import org.junit.Test; 9 | 10 | /** 11 | * 12 | * @author guojing 13 | * @date 2014-3-5 14 | */ 15 | public class TestAnnocation { 16 | 17 | @Test 18 | public void getAnnontion() { 19 | List list = getPkgClass("org.eh.core.controller"); 20 | System.out.println(Arrays.toString(list.toArray())); 21 | } 22 | 23 | public List getPkgClass(String parkage) { 24 | String path = this.getClass().getResource("/").getPath() + parkage.replace(".", "/") + "/"; 25 | List list = new ArrayList(); 26 | 27 | File file = new File(path); 28 | for(String str :file.list()){ 29 | if (str.endsWith(".class")) { 30 | list.add(parkage + "." + str.replace(".class", "")); 31 | } else if (str.indexOf(".") == -1) { 32 | list.addAll(getPkgClass(parkage + "." + str)); 33 | } 34 | } 35 | 36 | return list; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/org/eh/core/controller/pss/Test3Controller.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.controller.pss; 2 | 3 | import org.eh.core.annotation.Controller; 4 | 5 | /** 6 | * 7 | * @author guojing 8 | * @date 2014-3-5 9 | */ 10 | @Controller(name = "test3", url = "/test/send") 11 | public class Test3Controller { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/org/eh/core/other/StringTest.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.other; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 7 | * @author guojing 8 | * @date 2014-3-6 9 | */ 10 | public class StringTest { 11 | 12 | @Test 13 | public void testSub() { 14 | // String path = "test/path/list.do"; 15 | // String suffix = path.substring(path.lastIndexOf("."), path.length()); 16 | System.out.println(System.getProperty("user.dir")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/eh/core/util/FileUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.util; 2 | 3 | import org.eh.core.common.Constants; 4 | import org.junit.Test; 5 | 6 | /** 7 | * 8 | * @author guojing 9 | * @date 2014-3-4 10 | */ 11 | public class FileUtilTest { 12 | 13 | @Test 14 | public void TestRead() { 15 | String path = Constants.CLASS_PATH 16 | + "org/eh/web/view/test/myinfo.page"; 17 | String content = IOUtil.readFile(path); 18 | System.out.println(content); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/org/eh/core/util/PropertyUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.eh.core.util; 2 | 3 | import org.eh.core.common.Constants; 4 | import org.eh.core.common.ReturnType; 5 | import org.junit.Test; 6 | 7 | /** 8 | * 9 | * @author guojing 10 | * @date 2014-3-4 11 | */ 12 | public class PropertyUtilTest { 13 | 14 | @Test 15 | public void testResd() { 16 | PropertyUtil.analysisProperties(Constants.CLASS_PATH 17 | + "web.properties"); 18 | } 19 | 20 | @Test 21 | public void testReflect() { 22 | System.out.println(ReturnType.redirect.name()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/org/eh/velocity/VelocityTest.java: -------------------------------------------------------------------------------- 1 | package org.eh.velocity; 2 | 3 | import java.io.StringWriter; 4 | import java.util.Properties; 5 | 6 | import org.apache.velocity.VelocityContext; 7 | import org.apache.velocity.app.Velocity; 8 | import org.junit.Test; 9 | 10 | /** 11 | * 12 | * @author guojing 13 | * @date 2014-3-10 14 | */ 15 | public class VelocityTest { 16 | 17 | @Test 18 | public void testVelocity() { 19 | Properties p =new Properties(); 20 | p.setProperty("resource.loader", "class"); 21 | p.setProperty("class.resource.loader.class", 22 | "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); 23 | 24 | Velocity.init(p); 25 | VelocityContext vc = new VelocityContext(); 26 | vc.put("name", "guojing"); 27 | StringWriter w = new StringWriter(); 28 | // Velocity.mergeTemplate("org/eh/velocity/test.vm", "utf-8", vc, w); 29 | System.out.println(w); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/org/eh/velocity/test.vm: -------------------------------------------------------------------------------- 1 | hello!$!{name}。 -------------------------------------------------------------------------------- /src/test/java/org/eh/web/controller/Test1Controller.java: -------------------------------------------------------------------------------- 1 | package org.eh.web.controller; 2 | 3 | import org.eh.core.annotation.Controller; 4 | 5 | /** 6 | * 7 | * @author guojing 8 | * @date 2014-3-5 9 | */ 10 | @Controller(name = "test1", url = "/test/mark") 11 | public class Test1Controller { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/org/eh/web/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package org.eh.web.controller; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.eh.core.model.ResultInfo; 7 | import org.eh.core.web.controller.Controller; 8 | 9 | /** 10 | * 11 | * @author guojing 12 | * @date 2014-3-3 13 | */ 14 | public class TestController implements Controller { 15 | 16 | public ResultInfo process(Map parms) { 17 | ResultInfo resultInfo = new ResultInfo(); 18 | Map map = new HashMap(); 19 | map.put("name", parms.get("name")); 20 | map.put("msg", parms.get("msg")); 21 | 22 | resultInfo.setResultMap(map); 23 | resultInfo.setView("test/myinfo"); 24 | return resultInfo; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/org/eh/web/view/test/myinfo.page: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

${msg},${name}

6 | 7 | -------------------------------------------------------------------------------- /target/classes/web.properties: -------------------------------------------------------------------------------- 1 | #包前缀 2 | PACKAGE_PREFIX=org.eh.web 3 | 4 | #模板页面根路径(相对classes文件夹,项目src/main/view下) 5 | VIEW_BASE_PATH=page 6 | 7 | #静态资源路劲(相对classes文件夹,项目src/main/view下) 8 | STATIC_RESOURCE_PATH=static 9 | 10 | #端口 11 | httpserver.port=8888 12 | 13 | #controller包路径,配置后可通过annocation直接配置 14 | controller.package=com.gj.web.controller 15 | 16 | #url与controller类对应关系 17 | #url/list=com.gj.web.controller.MyController 18 | 19 | #session超时时间(分钟) 20 | session_timeout = 10 -------------------------------------------------------------------------------- /target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven 2 | #Thu Mar 27 22:41:48 CST 2014 3 | version=0.0.1 4 | groupId=org.eh.http 5 | artifactId=easy-httpserver 6 | --------------------------------------------------------------------------------