├── fast-sample ├── src │ └── main │ │ ├── resources │ │ ├── fast.properties │ │ └── log4j.properties │ │ ├── webapp │ │ ├── error │ │ │ ├── 403.html │ │ │ ├── 404.html │ │ │ └── 500.html │ │ ├── index.html │ │ └── WEB-INF │ │ │ └── web.xml │ │ └── java │ │ └── org │ │ └── bysocket │ │ ├── entity │ │ └── User.java │ │ └── controller │ │ ├── HelloWorldController.java │ │ └── RestfulJSONController.java └── pom.xml ├── doc └── img │ ├── json-post.png │ ├── sample-result.png │ └── sample-json-result.png ├── fast-core ├── src │ ├── test │ │ ├── resources │ │ │ └── fast.properties │ │ └── java │ │ │ └── org │ │ │ └── fastframework │ │ │ ├── mvc │ │ │ ├── ControllerCollectionTest.java │ │ │ └── DispatcherServletTest.java │ │ │ └── util │ │ │ ├── ClassUtilTest.java │ │ │ ├── ReflectUtilTest.java │ │ │ ├── TimeUtilTest.java │ │ │ ├── PropertyUtilTest.java │ │ │ └── JSONUtilTest.java │ └── main │ │ ├── java │ │ └── org │ │ │ └── fastframework │ │ │ ├── mvc │ │ │ ├── annotation │ │ │ │ ├── RequestMethod.java │ │ │ │ ├── PostParam.java │ │ │ │ ├── Controller.java │ │ │ │ ├── RequestMapping.java │ │ │ │ └── MediaTypes.java │ │ │ ├── bean │ │ │ │ ├── RequestBody.java │ │ │ │ └── HandlerBody.java │ │ │ ├── HandlerMapping.java │ │ │ ├── util │ │ │ │ └── MVCHelper.java │ │ │ ├── ViewResolver.java │ │ │ ├── DispatcherServlet.java │ │ │ ├── HandlerInvoker.java │ │ │ └── ControllerCollection.java │ │ │ ├── util │ │ │ ├── ReflectUtil.java │ │ │ ├── JSONUtil.java │ │ │ └── WebUtil.java │ │ │ └── core │ │ │ ├── Config.java │ │ │ └── util │ │ │ ├── PropertiesUtil.java │ │ │ ├── TimeUtil.java │ │ │ └── ClassUtil.java │ │ └── resources │ │ └── log4j.properties └── pom.xml ├── .gitignore ├── README_EN.md ├── ChangeLog.txt ├── .editorconfig ├── README.md ├── pom.xml └── LICENSE /fast-sample/src/main/resources/fast.properties: -------------------------------------------------------------------------------- 1 | ## 扫描包目录 2 | package.scan=org.bysocket -------------------------------------------------------------------------------- /doc/img/json-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffLi1993/fast-framework/HEAD/doc/img/json-post.png -------------------------------------------------------------------------------- /doc/img/sample-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffLi1993/fast-framework/HEAD/doc/img/sample-result.png -------------------------------------------------------------------------------- /doc/img/sample-json-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeffLi1993/fast-framework/HEAD/doc/img/sample-json-result.png -------------------------------------------------------------------------------- /fast-core/src/test/resources/fast.properties: -------------------------------------------------------------------------------- 1 | fast.framework.name=fast 2 | fast.framework.author=bysocket 3 | fast.framework.age=1 4 | package.scan=org.fastframework -------------------------------------------------------------------------------- /fast-sample/src/main/webapp/error/403.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 403 6 | 7 | 8 |

Hello,403!

9 | 10 | -------------------------------------------------------------------------------- /fast-sample/src/main/webapp/error/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 6 | 7 | 8 |

Hello,404!

9 | 10 | -------------------------------------------------------------------------------- /fast-sample/src/main/webapp/error/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 500 6 | 7 | 8 |

Hello,500!

9 | 10 | -------------------------------------------------------------------------------- /fast-sample/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |

Hello,BYSocket!

9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/annotation/RequestMethod.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc.annotation; 2 | 3 | /** 4 | * HTTP Request Method 5 | *

6 | * Created by bysocket on 16/8/4. 7 | */ 8 | public enum RequestMethod { 9 | GET, POST, PUT, PATCH, DELETE 10 | } 11 | -------------------------------------------------------------------------------- /fast-core/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=DEBUG, stdout 2 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 3 | log4j.appender.stdout.Target=System.out 4 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 5 | log4j.appender.stdout.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n -------------------------------------------------------------------------------- /fast-core/src/test/java/org/fastframework/mvc/ControllerCollectionTest.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc; 2 | 3 | /** 4 | * Created by bysocket on 16/8/4. 5 | */ 6 | public class ControllerCollectionTest { 7 | public static void main(String[] args) { 8 | ControllerCollection.init(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /fast-sample/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=DEBUG, stdout 2 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 3 | log4j.appender.stdout.Target=System.out 4 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 5 | log4j.appender.stdout.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | [![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) 2 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) 3 | [中文文档](https://github.com/JeffLi1993/fast-framework/blob/master/README.md) 4 | 5 | # fast-framework -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/annotation/PostParam.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by duqi on 16/8/26. 10 | */ 11 | @Target(ElementType.PARAMETER) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface PostParam { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/annotation/Controller.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Controller 注解 10 | *

11 | * Created by bysocket on 16/7/20. 12 | */ 13 | @Target(ElementType.TYPE) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface Controller { 16 | } 17 | -------------------------------------------------------------------------------- /fast-core/src/test/java/org/fastframework/util/ClassUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.util; 2 | 3 | import org.fastframework.core.util.ClassUtil; 4 | import org.fastframework.mvc.annotation.Controller; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by bysocket on 16/7/21. 10 | */ 11 | public class ClassUtilTest { 12 | public static void main(String[] args) { 13 | // ClassUtil.getClassList("org.fastframework"); 14 | List> controllerClassList = ClassUtil.getClassListByAnnotation("org.fastframework", Controller.class); 15 | return; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ChangeLog.txt: -------------------------------------------------------------------------------- 1 | ========================================================================================== 2 | v0.1.1 更新: 3 | ========================================================================================== 4 | 5 | > Bug 修复: 6 | ----------------- 7 | 1、修复入参多参数无序问题 8 | 2、修复 POM 项目格式问题 9 | 3、修复返回值 JSON 内容格式未处理问题 10 | 11 | > 增加 RESTful 支持: 12 | ----------------- 13 | 1、支持响应格式 Content-Type: application/json; charset=UTF-8 14 | 2、支持 POST Content-Type: application/json 传输 15 | 3、基于 JDK 8 time包的时间工具类 16 | 17 | > 增加 fast-framework sample: 18 | ----------------- 19 | 1、新增 JSON 响应 demo 案例 20 | 2、新增 POST 请求 User Bean 案例 -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 4 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | 22 | [{package,bower}.json] 23 | indent_style = space 24 | indent_size = 2 25 | 26 | [pom.xml] 27 | indent_style = tab 28 | -------------------------------------------------------------------------------- /fast-core/src/test/java/org/fastframework/util/ReflectUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.util; 2 | 3 | /** 4 | * Created by bysocket on 16/8/9. 5 | */ 6 | public class ReflectUtilTest { 7 | public static void main(String[] args) { 8 | // TestController controller = new TestController(); 9 | // Class controllerClazz = controller.getClass(); 10 | // Method controllerMethod = controllerClazz.getMethods()[0]; 11 | // List paramList = new ArrayList<>(); 12 | // paramList.add("BYSocket"); 13 | // Object ret = ReflectUtil.invokeControllerMethod(controller.getClass(),controllerMethod,paramList); 14 | // return; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /fast-sample/src/main/java/org/bysocket/entity/User.java: -------------------------------------------------------------------------------- 1 | package org.bysocket.entity; 2 | 3 | /** 4 | * Created by bysocket on 16/8/15. 5 | */ 6 | public class User { 7 | 8 | private Integer age; 9 | 10 | private String name; 11 | 12 | private String desc; 13 | 14 | public Integer getAge() { 15 | return age; 16 | } 17 | 18 | public void setAge(Integer age) { 19 | this.age = age; 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public void setName(String name) { 27 | this.name = name; 28 | } 29 | 30 | public String getDesc() { 31 | return desc; 32 | } 33 | 34 | public void setDesc(String desc) { 35 | this.desc = desc; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/annotation/RequestMapping.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * RequestMapping 注解 10 | *

11 | * Created by bysocket on 16/8/4. 12 | */ 13 | @Target(ElementType.METHOD) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface RequestMapping { 16 | 17 | /** 18 | * URL 19 | */ 20 | String value() default ""; 21 | 22 | /** 23 | * application/json,text/html {@link MediaTypes} 24 | */ 25 | String produces() default MediaTypes.TEXT_PLAIN_UTF_8; 26 | 27 | /** 28 | * GET, POST, PUT, PATCH, DELETE {@link RequestMethod} 29 | */ 30 | RequestMethod method() default RequestMethod.GET; 31 | } 32 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/bean/RequestBody.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc.bean; 2 | 3 | import org.fastframework.mvc.annotation.RequestMethod; 4 | 5 | /** 6 | * 请求体 7 | *

8 | * Created by bysocket on 16/7/19. 9 | */ 10 | public class RequestBody { 11 | 12 | /** 13 | * 请求方法 [POST] [GET] {@link org.fastframework.mvc.annotation.RequestMethod} 14 | */ 15 | private RequestMethod requestMethod; 16 | 17 | /** 18 | * 请求路由 19 | */ 20 | private String requestPath; 21 | 22 | public RequestBody(RequestMethod requestMethod, String requestPath) { 23 | this.requestMethod = requestMethod; 24 | this.requestPath = requestPath; 25 | } 26 | 27 | public RequestMethod getRequestMethod() { 28 | return requestMethod; 29 | } 30 | 31 | public String getRequestPath() { 32 | return requestPath; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/util/ReflectUtil.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.util; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | import java.util.List; 6 | 7 | /** 8 | * 反射工具类 9 | *

10 | * Created by bysocket on 16/8/9. 11 | */ 12 | public class ReflectUtil { 13 | 14 | public static Object invokeControllerMethod(Class clazz, Method method, List paramList) { 15 | 16 | try { 17 | method.setAccessible(true);// 取消类型安全检测(可提高反射性能) 18 | Object instance = clazz.newInstance(); 19 | return method.invoke(instance, paramList.toArray()); 20 | } catch (InstantiationException e) { 21 | e.printStackTrace(); 22 | } catch (IllegalAccessException e) { 23 | e.printStackTrace(); 24 | } catch (InvocationTargetException e) { 25 | e.printStackTrace(); 26 | } 27 | return null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/bean/HandlerBody.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc.bean; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * 处理方法体 7 | *

8 | * Created by bysocket on 16/7/19. 9 | */ 10 | public class HandlerBody { 11 | 12 | private Class controllerClass; 13 | 14 | private Method controllerMethod; 15 | 16 | private String responseMediaType; 17 | 18 | public HandlerBody(Class controllerClass, Method controllerMethod, String responseMediaType) { 19 | this.controllerClass = controllerClass; 20 | this.controllerMethod = controllerMethod; 21 | this.responseMediaType = responseMediaType; 22 | } 23 | 24 | public Class getControllerClass() { 25 | return controllerClass; 26 | } 27 | 28 | public Method getControllerMethod() { 29 | return controllerMethod; 30 | } 31 | 32 | public String getResponseMediaType() { 33 | return responseMediaType; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/annotation/MediaTypes.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc.annotation; 2 | 3 | /** 4 | * 带 UTF-8 charset 定义的 MediaType 5 | *

6 | * Created by bysocket on 16/8/4. 7 | */ 8 | public interface MediaTypes { 9 | String APPLICATION_XML = "application/xml"; 10 | String APPLICATION_XML_UTF_8 = "application/xml; charset=UTF-8"; 11 | 12 | String JSON = "application/json"; 13 | String JSON_UTF_8 = "application/json; charset=UTF-8"; 14 | 15 | String JAVASCRIPT = "application/javascript"; 16 | String JAVASCRIPT_UTF_8 = "application/javascript; charset=UTF-8"; 17 | 18 | String APPLICATION_XHTML_XML = "application/xhtml+xml"; 19 | String APPLICATION_XHTML_XML_UTF_8 = "application/xhtml+xml; charset=UTF-8"; 20 | 21 | String TEXT_PLAIN = "text/plain"; 22 | String TEXT_PLAIN_UTF_8 = "text/plain; charset=UTF-8"; 23 | 24 | String TEXT_XML = "text/xml"; 25 | String TEXT_XML_UTF_8 = "text/xml; charset=UTF-8"; 26 | 27 | String TEXT_HTML = "text/html"; 28 | String TEXT_HTML_UTF_8 = "text/html; charset=UTF-8"; 29 | } 30 | -------------------------------------------------------------------------------- /fast-sample/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 18 | 19 | 20 | 403 21 | /error/403.html 22 | 23 | 24 | 404 25 | /error/404.html 26 | 27 | 28 | 500 29 | /error/500.html 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /fast-sample/src/main/java/org/bysocket/controller/HelloWorldController.java: -------------------------------------------------------------------------------- 1 | package org.bysocket.controller; 2 | 3 | import org.bysocket.entity.User; 4 | import org.fastframework.mvc.annotation.Controller; 5 | import org.fastframework.mvc.annotation.MediaTypes; 6 | import org.fastframework.mvc.annotation.RequestMapping; 7 | import org.fastframework.mvc.annotation.RequestMethod; 8 | 9 | @Controller 10 | public class HelloWorldController { 11 | 12 | /** 13 | * GET http://localhost:8080/hello?name=BYSocket 14 | * 15 | * @param name 16 | * @return 17 | */ 18 | @RequestMapping(value = "/hello", 19 | method = RequestMethod.GET, 20 | produces = MediaTypes.TEXT_PLAIN_UTF_8) 21 | public String hello(String name) { 22 | return "Hello," + name + "!"; 23 | } 24 | 25 | /** 26 | * GET http://localhost:8080/user/hello?name=BYSocket&age=23 27 | * 28 | * @param name 29 | * @param age 30 | * @return 31 | */ 32 | @RequestMapping(value = "/user/hello", 33 | method = RequestMethod.GET, 34 | produces = MediaTypes.TEXT_PLAIN_UTF_8) 35 | public String helloUser(String name, Integer age) { 36 | User user = new User(); 37 | user.setName(name); 38 | return "Hello," + name + "!" + age; 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/HandlerMapping.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc; 2 | 3 | import org.fastframework.mvc.annotation.RequestMethod; 4 | import org.fastframework.mvc.bean.HandlerBody; 5 | import org.fastframework.mvc.bean.RequestBody; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * 处理器映射 11 | *

12 | * Created by bysocket on 16/8/9. 13 | */ 14 | public class HandlerMapping { 15 | 16 | /** 17 | * 处理方法体 18 | * 19 | * @param requestMethod 20 | * @param requestPath 21 | * @return 22 | */ 23 | public static HandlerBody getHandler(String requestMethod, String requestPath) { 24 | HandlerBody handler = null; 25 | 26 | // Controller Map 请求 -> 方法体 的映射 27 | Map methodMap = ControllerCollection.getMethodMap(); 28 | for (Map.Entry methodEntry : methodMap.entrySet()) { 29 | RequestBody req = methodEntry.getKey(); 30 | String reqPath = req.getRequestPath(); 31 | RequestMethod reqMethod = req.getRequestMethod(); 32 | 33 | if (reqPath.equals(requestPath) && reqMethod.name().equalsIgnoreCase(requestMethod)) { 34 | handler = methodEntry.getValue(); 35 | if (handler != null) { 36 | return handler; 37 | } 38 | } 39 | } 40 | 41 | return handler; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/core/Config.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.core; 2 | 3 | import org.fastframework.core.util.PropertiesUtil; 4 | 5 | import java.util.Properties; 6 | 7 | /** 8 | * 系统配置类 9 | *

10 | * Created by bysocket on 16/7/19. 11 | */ 12 | public class Config { 13 | 14 | /** 15 | * .properties属性文件默认名 16 | */ 17 | public static final String PROPERTY_FILE_DEFAULT_NAME = "fast"; 18 | /** 19 | * 默认扫描包key ,不存在默认扫描全部 20 | */ 21 | public static final String PROPERTY_PACKAGE_SCAN = "package.scan"; 22 | public static final String PROPERTY_PACKAGE_SCAN_DEFAULT = ""; 23 | 24 | private static final Properties configProperties = PropertiesUtil.getProperties(PROPERTY_FILE_DEFAULT_NAME); 25 | 26 | /** 27 | * 获取扫描包的目录 28 | * 29 | * @return 30 | */ 31 | public static String getScanPackage() { 32 | return getStringOrDefault(PROPERTY_PACKAGE_SCAN, PROPERTY_PACKAGE_SCAN_DEFAULT); 33 | } 34 | 35 | /** 36 | * 根据key,获取属性值 37 | * 38 | * @param key 39 | * @return 40 | */ 41 | public static String getString(String key) { 42 | return PropertiesUtil.getString(configProperties, key); 43 | } 44 | 45 | /** 46 | * 根据key,获取属性值 47 | * 48 | * @param key 49 | * @return 50 | */ 51 | public static String getStringOrDefault(String key, String defaultValue) { 52 | return PropertiesUtil.getStringOrDefault(configProperties, key, defaultValue); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/util/JSONUtil.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.util; 2 | 3 | import org.codehaus.jackson.map.ObjectMapper; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | 8 | /** 9 | * JSON 工具类 10 | *

11 | * Created by bysocket on 16/7/19. 12 | */ 13 | public class JSONUtil { 14 | 15 | private static final Logger LOGGER = LoggerFactory.getLogger(JSONUtil.class); 16 | 17 | /** 18 | * 默认JSON类 19 | **/ 20 | private static final ObjectMapper mapper = new ObjectMapper(); 21 | 22 | /** 23 | * 将 Java 对象转换为 JSON 字符串 24 | * 25 | * @param object 26 | * @param 27 | * @return 28 | */ 29 | public static String toJSONString(T object) { 30 | String jsonStr; 31 | try { 32 | jsonStr = mapper.writeValueAsString(object); 33 | } catch (Exception e) { 34 | LOGGER.error("Java Object Can't covert to JSON String!"); 35 | throw new RuntimeException(e); 36 | } 37 | return jsonStr; 38 | } 39 | 40 | 41 | /** 42 | * 将 JSON 字符串转化为 Java 对象 43 | * 44 | * @param json 45 | * @param clazz 46 | * @param 47 | * @return 48 | */ 49 | public static T toObject(String json, Class clazz) { 50 | T object; 51 | try { 52 | object = mapper.readValue(json, clazz); 53 | } catch (Exception e) { 54 | LOGGER.error("JSON String Can't covert to Java Object!"); 55 | throw new RuntimeException(e); 56 | } 57 | return object; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /fast-core/src/test/java/org/fastframework/util/TimeUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.util; 2 | 3 | import org.fastframework.core.util.TimeUtil; 4 | import org.junit.FixMethodOrder; 5 | import org.junit.Test; 6 | import org.junit.runners.MethodSorters; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | 12 | @FixMethodOrder(MethodSorters.NAME_ASCENDING) 13 | public class TimeUtilTest { 14 | 15 | @Test 16 | public void testParseSpecificTimeStringByUsingDefaultPattern() throws Exception { 17 | LocalDateTime expectedDateTime = LocalDateTime.of(2014, 11, 11, 10, 11, 11); 18 | LocalDateTime parsedTime = TimeUtil.parseTime("2014-11-11 10:11:11"); 19 | assertEquals(expectedDateTime, parsedTime); 20 | } 21 | 22 | @Test 23 | public void testParseSpecificTimeStringUsingTimeFormat() throws Exception { 24 | LocalDateTime expectedDateTime = LocalDateTime.of(2014, 11, 11, 10, 11, 11); 25 | LocalDateTime parsedTime = TimeUtil.parseTime("2014/11/11 10:11:11", TimeUtil.TimeFormat.LONG_DATE_PATTERN_SLASH); 26 | assertEquals(expectedDateTime, parsedTime); 27 | } 28 | 29 | @Test 30 | public void testParseLocalDateTimeByUsingDefaultFormatter() throws Exception { 31 | LocalDateTime time = LocalDateTime.of(2014, 11, 11, 10, 11, 11); 32 | assertEquals(TimeUtil.parseTime(time), "2014-11-11 10:11:11"); 33 | } 34 | 35 | @Test 36 | public void testParseLocalDateTimeByUsingTimeFormat() throws Exception { 37 | LocalDateTime time = LocalDateTime.of(2014, 11, 11, 10, 11, 11); 38 | assertEquals(TimeUtil.parseTime(time, TimeUtil.TimeFormat.LONG_DATE_PATTERN_DOUBLE_SLASH), "2014\\11\\11 10:11:11"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /fast-sample/src/main/java/org/bysocket/controller/RestfulJSONController.java: -------------------------------------------------------------------------------- 1 | package org.bysocket.controller; 2 | 3 | import org.bysocket.entity.User; 4 | import org.fastframework.mvc.annotation.*; 5 | 6 | @Controller 7 | public class RestfulJSONController { 8 | 9 | /** 10 | * GET http://localhost:8080/json?name=BYSocket 11 | * 12 | * @param name 13 | * @return 14 | */ 15 | @RequestMapping(value = "/json", 16 | method = RequestMethod.GET, 17 | produces = MediaTypes.JSON_UTF_8) 18 | public User json(String name) { 19 | User user = new User(); 20 | user.setName(name); 21 | user.setAge(23); 22 | return user; 23 | } 24 | 25 | /** 26 | * GET http://localhost:8080/user/get?name=BYSocket&age=23 27 | * 28 | * @param name 29 | * @param age 30 | * @return 31 | */ 32 | @RequestMapping(value = "/user/get", 33 | method = RequestMethod.GET, 34 | produces = MediaTypes.JSON_UTF_8) 35 | public User getUser(String name, Integer age) { 36 | User user = new User(); 37 | user.setName(name); 38 | user.setAge(age); 39 | return user; 40 | } 41 | 42 | /** 43 | * POST http://localhost:8080/user/add 44 | * Content-Type: application/json 45 | * { 46 | * "name":"BYSocket", 47 | * "age":23 48 | * } 49 | * 50 | * @param user 51 | * @return 52 | */ 53 | @RequestMapping(value = "/user/add", 54 | method = RequestMethod.POST, 55 | produces = MediaTypes.JSON_UTF_8) 56 | public User addUser(@PostParam User user) { 57 | user.setDesc("Blog: http://www.bysocket.com https://github.com/JeffLi1993"); 58 | return user; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/util/MVCHelper.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | /** 11 | * MVC 相关的帮助类 12 | *

13 | * Created by bysocket on 16/7/19. 14 | */ 15 | public class MVCHelper { 16 | 17 | /** 18 | * URL 目录分隔符 19 | */ 20 | public static final String URL_PATH_SEPARATOR = "/"; 21 | /** 22 | * 请求编码 UTF-8 23 | */ 24 | public static final String REQ_CHARACTER_UTF_8 = "UTF-8"; 25 | /** 26 | * 请求默认主页地址 27 | */ 28 | public static final String REQ_DEFAULT_HOME_PAGE = "/index.html"; 29 | private static final Logger LOGGER = LoggerFactory.getLogger(MVCHelper.class); 30 | 31 | /** 32 | * 获取请求路径 33 | * /servlet/MyServlet/a/b 34 | * 35 | * @param request 36 | * @return 37 | */ 38 | public static String getRequestPath(HttpServletRequest request) { 39 | String servletPath = request.getServletPath(); // /servlet/MyServlet 40 | String pathInfo = request.getPathInfo(); // /a/b 41 | 42 | return (null != servletPath ? servletPath : "") + StringUtils.defaultIfEmpty(pathInfo, StringUtils.EMPTY); 43 | } 44 | 45 | /** 46 | * 重定向请求 47 | * 48 | * @param path 49 | * @param request 50 | * @param response 51 | */ 52 | public static void redirectRequest(String path, HttpServletRequest request, HttpServletResponse response) { 53 | try { 54 | response.sendRedirect(request.getContextPath() + path); 55 | } catch (Exception e) { 56 | LOGGER.error("重定向请求失败!", e); 57 | throw new RuntimeException(e); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /fast-sample/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | 9 | org.fast 10 | fast-framework 11 | 0.0.1-SNAPSHOT 12 | 13 | 14 | fast-sample 15 | fast-sample 16 | war 17 | http://www.bysocket.com 18 | fast framework core 19 | 20 | 21 | 22 | The Apache Software License, Version 2.0 23 | http://www.apache.org/licenses/LICENSE-2.0.txt 24 | 25 | 26 | 27 | 28 | BYSocket Open Source 29 | http://www.bysocket.com 30 | 31 | 32 | 33 | 34 | BYSocket Open Source 35 | bysocket@aliyun.com 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.fast 44 | fast-core 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | org.eclipse.jetty 54 | jetty-maven-plugin 55 | 9.2.11.v20150529 56 | 57 | 10 58 | 59 | / 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/ViewResolver.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc; 2 | 3 | import org.fastframework.mvc.annotation.MediaTypes; 4 | import org.fastframework.mvc.bean.HandlerBody; 5 | import org.fastframework.mvc.util.MVCHelper; 6 | import org.fastframework.util.JSONUtil; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | 14 | /** 15 | * 视图解析器 16 | *

17 | * Created by bysocket on 16/8/9. 18 | */ 19 | public class ViewResolver { 20 | 21 | private static final Logger LOGGER = LoggerFactory.getLogger(ViewResolver.class); 22 | 23 | public static void resolveView(HttpServletRequest request, HttpServletResponse response, 24 | Object controllerMethodResult, HandlerBody handler) { 25 | // TODO 根据返回值返回 26 | try { 27 | // 请求路由 28 | String requestPath = MVCHelper.getRequestPath(request); 29 | String responseMediaType = handler.getResponseMediaType(); 30 | 31 | if (MediaTypes.TEXT_PLAIN_UTF_8.equals(responseMediaType)) { 32 | LOGGER.debug("[fast framework] {} : 返回格式CharSet = {}, 返回结果 = {}", requestPath, 33 | MediaTypes.TEXT_PLAIN_UTF_8, controllerMethodResult); 34 | response.getWriter().print(controllerMethodResult); 35 | return; 36 | } else if (MediaTypes.JSON_UTF_8.equals(responseMediaType)) { 37 | String resultJSON = JSONUtil.toJSONString(controllerMethodResult); 38 | LOGGER.debug("[fast framework] {} : 返回格式CharSet = {}, 返回结果 = {}", requestPath, 39 | MediaTypes.JSON_UTF_8, resultJSON); 40 | response.getWriter().print(resultJSON); 41 | return; 42 | } 43 | } catch (IOException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /fast-core/src/test/java/org/fastframework/util/PropertyUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.util; 2 | 3 | import org.fastframework.core.Config; 4 | import org.fastframework.core.util.PropertiesUtil; 5 | import org.junit.Test; 6 | 7 | import java.util.Properties; 8 | 9 | /** 10 | * {@link PropertiesUtil} 测试用例 11 | *

12 | * Created by bysocket on 16/7/19. 13 | */ 14 | public class PropertyUtilTest { 15 | 16 | @Test 17 | public void testGetProperties() { 18 | Properties properties = PropertiesUtil.getProperties("fast"); 19 | String fastFrameworkName = properties.getProperty("fast.framework.name"); 20 | String authorName = properties.getProperty("fast.framework.author"); 21 | Object age = properties.getOrDefault("fast.framework.age", 10); 22 | Object defaultVal = properties.getOrDefault("fast.framework.null", 10); 23 | System.out.println(fastFrameworkName); 24 | System.out.println(authorName); 25 | System.out.println(age.toString()); 26 | System.out.println(defaultVal.toString()); 27 | } 28 | 29 | @Test 30 | public void testGetString() { 31 | Properties properties = PropertiesUtil.getProperties("fast"); 32 | String fastFrameworkName = PropertiesUtil.getString(properties, "fast.framework.name"); 33 | String authorName = PropertiesUtil.getString(properties, "fast.framework.author"); 34 | System.out.println(fastFrameworkName); 35 | System.out.println(authorName); 36 | } 37 | 38 | @Test 39 | public void testGetOrDefault() { 40 | Properties properties = PropertiesUtil.getProperties("fast"); 41 | Object age = PropertiesUtil.getOrDefault(properties, "fast.framework.age", 10); 42 | Object defaultVal = PropertiesUtil.getOrDefault(properties, "fast.framework.null", 10); 43 | System.out.println(age.toString()); 44 | System.out.println(defaultVal.toString()); 45 | } 46 | 47 | @Test 48 | public void testGetScanPackage() { 49 | System.out.println(Config.getScanPackage()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /fast-core/src/test/java/org/fastframework/util/JSONUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.util; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | /** 7 | * {@link JSONUtil} 测试用例 8 | *

9 | * Created by bysocket on 16/7/19. 10 | */ 11 | public class JSONUtilTest { 12 | 13 | @Test 14 | public void testToJSONString() { 15 | JSONObject jsonObject = new JSONObject(1, "bysocket", 33); 16 | String jsonStr = JSONUtil.toJSONString(jsonObject); 17 | Assert.assertEquals("{\"age\":1,\"name\":\"bysocket\",\"id\":33}", jsonStr); 18 | } 19 | 20 | @Test(expected = RuntimeException.class) 21 | public void testToJSONStringError() { 22 | JSONUtil.toJSONString(System.out); 23 | } 24 | 25 | @Test 26 | public void testToObject() { 27 | JSONObject jsonObject = new JSONObject(1, "bysocket", 33); 28 | String jsonStr = JSONUtil.toJSONString(jsonObject); 29 | JSONObject resultObject = JSONUtil.toObject(jsonStr, JSONObject.class); 30 | Assert.assertEquals(jsonObject.toString(), resultObject.toString()); 31 | } 32 | 33 | @Test(expected = RuntimeException.class) 34 | public void testToObjectError() { 35 | JSONUtil.toObject("{int:1}", JSONObject.class); 36 | } 37 | } 38 | 39 | class JSONObject { 40 | int age; 41 | String name; 42 | Integer id; 43 | 44 | public JSONObject() { 45 | } 46 | 47 | public JSONObject(int age, String name, Integer id) { 48 | this.age = age; 49 | this.name = name; 50 | this.id = id; 51 | } 52 | 53 | public int getAge() { 54 | return age; 55 | } 56 | 57 | public void setAge(int age) { 58 | this.age = age; 59 | } 60 | 61 | public String getName() { 62 | return name; 63 | } 64 | 65 | public void setName(String name) { 66 | this.name = name; 67 | } 68 | 69 | public Integer getId() { 70 | return id; 71 | } 72 | 73 | public void setId(Integer id) { 74 | this.id = id; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "JSONObject{" + 80 | "age=" + age + 81 | ", name='" + name + '\'' + 82 | ", id=" + id + 83 | '}'; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/DispatcherServlet.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc; 2 | 3 | import org.fastframework.mvc.bean.HandlerBody; 4 | import org.fastframework.mvc.util.MVCHelper; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.annotation.WebServlet; 10 | import javax.servlet.http.HttpServlet; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | /** 16 | * MVC 前端控制器 17 | * 1. 初始化相关配置: 类扫描/路由匹配 18 | * 2. 转发请求到 HandlerMapping 19 | * 3. 反射调用Controller方法,并解耦 20 | * 4. 根据返回值,响应视图或数据 21 | *

22 | * Created by bysocket on 16/7/19. 23 | */ 24 | @WebServlet(urlPatterns = "/*", loadOnStartup = 0) 25 | public class DispatcherServlet extends HttpServlet { 26 | 27 | private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); 28 | 29 | /** 30 | * 初始化相关配置 31 | * 扫描类 - 路由Map 32 | * 33 | * @throws ServletException 34 | */ 35 | @Override 36 | public void init() throws ServletException { 37 | ControllerCollection.init(); 38 | } 39 | 40 | @Override 41 | protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 42 | // 设置请求默认编码 43 | request.setCharacterEncoding(MVCHelper.REQ_CHARACTER_UTF_8); 44 | // 请求相关信息 45 | // 请求方法 [POST] [GET] 46 | String requestMethod = request.getMethod(); 47 | // 请求路由 48 | String requestPath = MVCHelper.getRequestPath(request); 49 | 50 | LOGGER.debug("[fast framework] {} : {}", requestMethod, requestPath); 51 | 52 | // "/" 请求重定向到默认首页 53 | if (MVCHelper.URL_PATH_SEPARATOR.equals(requestPath)) { 54 | MVCHelper.redirectRequest(MVCHelper.REQ_DEFAULT_HOME_PAGE, request, response); 55 | return; 56 | } 57 | 58 | // 处理器映射 59 | // 获取 handler 60 | HandlerBody handler = HandlerMapping.getHandler(requestMethod, requestPath); 61 | 62 | // null == handler 63 | if (null == handler) { 64 | response.sendError(HttpServletResponse.SC_NOT_FOUND); 65 | return; 66 | } 67 | 68 | // 调用 Handler 69 | HandlerInvoker.invokeHandler(request, response, handler); 70 | return; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /fast-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.fast 9 | fast-framework 10 | 0.0.1-SNAPSHOT 11 | 12 | 13 | fast-core 14 | fast-core 15 | http://www.bysocket.com 16 | fast framework core 17 | 18 | 19 | 20 | The Apache Software License, Version 2.0 21 | http://www.apache.org/licenses/LICENSE-2.0.txt 22 | 23 | 24 | 25 | 26 | BYSocket Open Source 27 | http://www.bysocket.com 28 | 29 | 30 | 31 | 32 | BYSocket Open Source 33 | bysocket@aliyun.com 34 | 35 | 36 | 37 | 38 | 39 | 40 | javax.servlet 41 | javax.servlet-api 42 | provided 43 | 44 | 45 | 46 | 47 | org.slf4j 48 | slf4j-log4j12 49 | 50 | 51 | 52 | 53 | 54 | org.codehaus.jackson 55 | jackson-mapper-asl 56 | 57 | 58 | 59 | org.codehaus.jackson 60 | jackson-jaxrs 61 | 62 | 63 | 64 | 65 | org.apache.commons 66 | commons-lang3 67 | 68 | 69 | 70 | commons-collections 71 | commons-collections 72 | 73 | 74 | 75 | commons-io 76 | commons-io 77 | 78 | 79 | 80 | 81 | junit 82 | junit 83 | test 84 | 85 | 86 | 87 | 88 | cglib 89 | cglib 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 泥瓦匠本意:
2 | " 生产暂时不要用fast-framework, 3 | 是想让大家如何理解 MVC 框架的核心, 4 | 以后会带上系列实现文章" 5 | 6 | [![maven-central](https://img.shields.io/maven-central/v/com.bladejava/blade-core.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.bladejava%22) 7 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) 8 |
9 | [[English Document]](https://github.com/JeffLi1993/fast-framework/blob/master/README_EN.md) 10 | 11 | # fast-framework 12 | 轻量级 Java Web 框架 13 | 14 | - 基于 JDK 8 规范 15 | - 基于 Servlet 3.0 规范 16 | - 零配置 17 | - REST 服务接口 基于 JSON 传输 18 | - 目前提供 MVC ... 解决方案 19 |

20 | 21 | ## 作者与学习乐园 22 | 源码地址:我的[GitHub地址](https://github.com/JeffLi1993 "GitHub")
23 | 作者: [李强强](http://www.bysocket.com/ "李强强") 也叫 泥瓦匠
24 | QQ群:编程之美 365234583 [立即加入](http://jq.qq.com/?_wv=1027&k=Sx4s4U "编程之美")
25 | 欢迎阅读以下博文:
26 | Fast-FrameWork系列文章:[传送门](http://www.bysocket.com/?cat=102) 27 |

28 | 29 | ## 快速入门 30 | #### 1. 必备环境 31 | - [Git 环境搭建](http://) 32 | - [Maven 环境搭建](http://www.bysocket.com/?p=1267)
33 | 34 | #### 2. 下载 fast-framework 项目及 sample 案例 35 | ```` 36 | git clone https://github.com/JeffLi1993/fast-framework.git 37 | ```` 38 | 39 | #### 3. Maven 编译 sample 案例 40 | ```` 41 | cd fast-framework // cd 到工程根目录 42 | 43 | mvn clean install // 编译工程 44 | ```` 45 | 46 | #### 4. 启动 sample 案例 47 | ```` 48 | cd fast-sample // cd 到 sample 案例工程根目录 49 | mvn jetty:run // 启动 sample 工程 50 | ```` 51 | Console 出现如下结果,表示服务器成功启动: 52 | ```` 53 | ... 54 | [INFO] Started ServerConnector@f1a45f8{HTTP/1.1}{0.0.0.0:8080} 55 | [INFO] Started @5133ms 56 | [INFO] Started Jetty Server 57 | [INFO] Starting scanner at interval of 10 seconds. 58 | ```` 59 | 60 | #### 5. 访问 sample 61 | ##### GET 方式 62 | 在浏览器中打开 - text/plain; charset=UTF-8 : 63 | ```` 64 | GET http://localhost:8080/hello?name=BYSocket 65 | ```` 66 | 会得到如下结果:
67 | ![sample结果图](https://github.com/JeffLi1993/fast-framework/blob/master/doc/img/sample-result.png) 68 | 69 | 在浏览器中打开 - application/json; charset=UTF-8 : 70 | ```` 71 | GET http://localhost:8080/json?name=BYSocket 72 | ```` 73 | 会得到如下结果:
74 | ![sample结果图](https://github.com/JeffLi1993/fast-framework/blob/master/doc/img/sample-json-result.png) 75 | 76 | ##### POST 方式 77 | 在 POSTMan 或者 HTTP 客户端 : 78 | ```` 79 | POST localhost:8080/user/add HTTP/1.1 80 | Content-Type: application/json 81 | Cache-Control: no-cache 82 | { 83 | "name":"BYSocket", 84 | "age":23 85 | } 86 | ```` 87 | 会得到如下结果:
88 | ![sample结果图](https://github.com/JeffLi1993/fast-framework/blob/master/doc/img/json-post.png) 89 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/HandlerInvoker.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc; 2 | 3 | import org.fastframework.mvc.annotation.PostParam; 4 | import org.fastframework.mvc.annotation.RequestMethod; 5 | import org.fastframework.mvc.bean.HandlerBody; 6 | import org.fastframework.util.ReflectUtil; 7 | import org.fastframework.util.WebUtil; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.lang.reflect.Method; 12 | import java.lang.reflect.Parameter; 13 | import java.util.List; 14 | import java.util.ArrayList; 15 | 16 | /** 17 | * Handler 调用器 18 | *

19 | * Created by bysocket on 16/8/9. 20 | */ 21 | public class HandlerInvoker { 22 | 23 | /** 24 | * 请求处理器 25 | * 根据请求,获取请求参数 26 | * 调用Method,获取返回值 27 | * 调用View,返回响应 28 | * 29 | * @param request 30 | * @param response 31 | * @param handler 32 | */ 33 | public static void invokeHandler(HttpServletRequest request, HttpServletResponse response, HandlerBody handler) { 34 | List controllerMethodParamList = new ArrayList<>(); 35 | Method controllerMethod = handler.getControllerMethod(); 36 | 37 | // POST 请求 38 | if (request.getMethod().equals(RequestMethod.POST.toString())) { 39 | List> getParameterTypes = new ArrayList(); 40 | Class postParamType = null; 41 | 42 | for (Parameter p : controllerMethod.getParameters()) { 43 | if (p.isAnnotationPresent(PostParam.class)) { 44 | postParamType = p.getType(); 45 | } else { 46 | getParameterTypes.add(p.getType()); 47 | } 48 | } 49 | controllerMethodParamList = WebUtil.getRequestParamMap(request, getParameterTypes.toArray(new Class[0])); 50 | Object postParamObject = WebUtil.getRequestBody(request, postParamType); 51 | controllerMethodParamList.add(0, postParamObject); 52 | 53 | } 54 | // GET 请求 55 | else if (request.getMethod().equals(RequestMethod.GET.toString())) { 56 | // 从 Request 获取参数 - Controller.Method 的 ParamList 57 | controllerMethodParamList = WebUtil.getRequestParamMap(request, controllerMethod.getParameterTypes()); 58 | } 59 | 60 | // ReflectUtil 获取 Controller.Method 的返回值 61 | Object controllerMethodResult = ReflectUtil.invokeControllerMethod(handler.getControllerClass(), 62 | handler.getControllerMethod(), controllerMethodParamList); 63 | 64 | // View 处理 65 | ViewResolver.resolveView(request, response, controllerMethodResult, handler); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/core/util/PropertiesUtil.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.core.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.util.Properties; 10 | 11 | /** 12 | * .properties属性文件操作工具类 13 | *

14 | * Created by bysocket on 16/7/19. 15 | */ 16 | public class PropertiesUtil { 17 | 18 | /** 19 | * .properties属性文件名后缀 20 | */ 21 | public static final String PROPERTY_FILE_SUFFIX = ".properties"; 22 | private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesUtil.class); 23 | 24 | /** 25 | * 根据属性文件名,获取属性 26 | * 27 | * @param propsFileName 28 | * @return 29 | */ 30 | public static Properties getProperties(String propsFileName) { 31 | if (StringUtils.isEmpty(propsFileName)) 32 | throw new IllegalArgumentException(); 33 | 34 | Properties properties = new Properties(); 35 | InputStream inputStream = null; 36 | 37 | try { 38 | 39 | try { 40 | /** 加入文件名后缀 */ 41 | if (propsFileName.lastIndexOf(PROPERTY_FILE_SUFFIX) == -1) { 42 | propsFileName += PROPERTY_FILE_SUFFIX; 43 | } 44 | 45 | inputStream = Thread.currentThread().getContextClassLoader() 46 | .getResourceAsStream(propsFileName); 47 | if (null != inputStream) 48 | properties.load(inputStream); 49 | } finally { 50 | if (null != inputStream) { 51 | inputStream.close(); 52 | } 53 | } 54 | 55 | } catch (IOException e) { 56 | LOGGER.error("加载属性文件出错!", e); 57 | throw new RuntimeException(e); 58 | } 59 | 60 | return properties; 61 | } 62 | 63 | /** 64 | * 根据key,获取属性值 65 | * 66 | * @param properties 67 | * @param key 68 | * @return 69 | */ 70 | public static String getString(Properties properties, String key) { 71 | return properties.getProperty(key); 72 | } 73 | 74 | /** 75 | * 根据key,获取属性值 76 | * 77 | * @param properties 78 | * @param key 79 | * @param defaultValue 80 | * @return 81 | */ 82 | public static String getStringOrDefault(Properties properties, String key, String defaultValue) { 83 | return properties.getProperty(key, defaultValue); 84 | } 85 | 86 | /** 87 | * 根据key,获取属性值 88 | * 89 | * @param properties 90 | * @param key 91 | * @param defaultValue 92 | * @param 93 | * @return 94 | */ 95 | public static V getOrDefault(Properties properties, String key, V defaultValue) { 96 | return (V) properties.getOrDefault(key, defaultValue); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/mvc/ControllerCollection.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc; 2 | 3 | import org.apache.commons.collections.CollectionUtils; 4 | import org.apache.commons.lang3.ArrayUtils; 5 | import org.fastframework.core.Config; 6 | import org.fastframework.core.util.ClassUtil; 7 | import org.fastframework.mvc.annotation.Controller; 8 | import org.fastframework.mvc.annotation.RequestMapping; 9 | import org.fastframework.mvc.annotation.RequestMethod; 10 | import org.fastframework.mvc.bean.HandlerBody; 11 | import org.fastframework.mvc.bean.RequestBody; 12 | 13 | import java.lang.reflect.Method; 14 | import java.util.LinkedHashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | /** 19 | * Controller类收集器 20 | *

21 | * Created by bysocket on 16/7/20. 22 | */ 23 | public class ControllerCollection { 24 | 25 | /** 26 | * Controller Map 请求 -> 方法体 的映射 27 | */ 28 | public static final Map methodMap = new LinkedHashMap<>(); 29 | 30 | /** 31 | * Controller扫描包的目录 32 | */ 33 | private static final String scanPackage = Config.getScanPackage(); 34 | 35 | /** 36 | * 初始化 37 | */ 38 | public static void init() { 39 | // 获取到 @Controller 注解的类列表 40 | List> controllerClassList = ClassUtil.getClassListByAnnotation(scanPackage, Controller.class); 41 | if (CollectionUtils.isNotEmpty(controllerClassList)) { 42 | for (Class controllerClass : controllerClassList) { 43 | // 获取并遍历所有 Controller 类中的所有方法 44 | Method[] controllerMethods = controllerClass.getMethods(); 45 | if (ArrayUtils.isNotEmpty(controllerMethods)) { 46 | for (Method controllerMethod : controllerMethods) { 47 | handlerControllerMethod(controllerMethod, controllerClass); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | /** 55 | * 根据 Method 的注解加入 Controller Map 请求 -> 方法体 的映射 56 | * 57 | * @param controllerMethod 58 | * @param controllerClass 59 | */ 60 | private static void handlerControllerMethod(Method controllerMethod, Class controllerClass) { 61 | if (controllerMethod.isAnnotationPresent(RequestMapping.class)) { 62 | String requestPath = controllerMethod.getAnnotation(RequestMapping.class).value(); 63 | RequestMethod requestMethod = controllerMethod.getAnnotation(RequestMapping.class).method(); 64 | String responseMediaType = controllerMethod.getAnnotation(RequestMapping.class).produces(); 65 | methodMap.put(new RequestBody(requestMethod, requestPath), 66 | new HandlerBody(controllerClass, controllerMethod, responseMediaType)); 67 | } 68 | } 69 | 70 | public static Map getMethodMap() { 71 | return methodMap; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/util/WebUtil.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.util; 2 | 3 | import org.apache.commons.io.IOUtils; 4 | import org.fastframework.mvc.annotation.MediaTypes; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.nio.charset.Charset; 10 | import java.util.ArrayList; 11 | import java.util.Enumeration; 12 | import java.util.List; 13 | 14 | /** 15 | * Created by bysocket on 16/8/9. 16 | */ 17 | public class WebUtil { 18 | 19 | public static final String CHARSET_UTF_8 = "UTF-8"; 20 | 21 | /** 22 | * 从请求中获取所有参数 23 | * 24 | * @param request 25 | * @return 26 | */ 27 | public static List getRequestParamMap(HttpServletRequest request, Class[] controllerParamTypes) { 28 | 29 | List requestParamList = new ArrayList<>(); 30 | Enumeration paramNames = request.getParameterNames(); 31 | int i = 0; 32 | while (paramNames.hasMoreElements()) { 33 | String paramName = paramNames.nextElement(); 34 | String[] paramValues = request.getParameterValues(paramName); 35 | if (paramValues != null) { 36 | if (1 == paramValues.length) { 37 | // 获取请求参数 38 | String paramValue = paramValues[0]; 39 | Class paramType = controllerParamTypes[i]; 40 | // 支持四种类型:int/Integer、long/Long、double/Double、String 41 | if (paramType.equals(int.class) || paramType.equals(Integer.class)) { 42 | requestParamList.add(Integer.parseInt(paramValue)); 43 | } else if (paramType.equals(long.class) || paramType.equals(Long.class)) { 44 | requestParamList.add(Long.parseLong(paramValue)); 45 | } else if (paramType.equals(double.class) || paramType.equals(Double.class)) { 46 | requestParamList.add(Double.parseDouble(paramValue)); 47 | } else if (paramType.equals(String.class)) { 48 | requestParamList.add(paramValue); 49 | } 50 | } 51 | // TODO 数组 52 | } 53 | i++; 54 | } 55 | return requestParamList; 56 | } 57 | 58 | /** 59 | * 从请求体重获取对应的对象 60 | * 61 | * @param request 62 | * @param clzz 63 | * @return 64 | */ 65 | public static Object getRequestBody(HttpServletRequest request, Class clzz) { 66 | InputStream is; 67 | String tempStr; 68 | Object result = null; 69 | try { 70 | is = request.getInputStream(); 71 | if (request.getContentType().equals(MediaTypes.TEXT_PLAIN)) { 72 | result = IOUtils.toString(is); 73 | } else if (request.getContentType().equals(MediaTypes.JSON_UTF_8)) { 74 | tempStr = IOUtils.toString(is, Charset.forName(CHARSET_UTF_8)); 75 | result = JSONUtil.toObject(tempStr, clzz); 76 | } else if (request.getContentType().equals(MediaTypes.JSON)) { 77 | tempStr = IOUtils.toString(is); 78 | result = JSONUtil.toObject(tempStr, clzz); 79 | } 80 | } catch (IOException e) { 81 | e.printStackTrace(); 82 | } 83 | return result; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/core/util/TimeUtil.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.core.util; 2 | 3 | import java.time.LocalDateTime; 4 | import java.time.format.DateTimeFormatter; 5 | 6 | /** 7 | * 基于 JDK 8 time包的时间工具类 8 | *

9 | * Created by bysocket on 16/8/23. 10 | */ 11 | public final class TimeUtil { 12 | 13 | /** 14 | * 获取默认时间格式: yyyy-MM-dd HH:mm:ss 15 | */ 16 | private static final DateTimeFormatter DEFAULT_DATETIME_FORMATTER = TimeFormat.LONG_DATE_PATTERN_LINE.formatter; 17 | 18 | private TimeUtil() { 19 | // no construct function 20 | } 21 | 22 | /** 23 | * String 转时间 24 | * 25 | * @param timeStr 26 | * @return 27 | */ 28 | public static LocalDateTime parseTime(String timeStr) { 29 | return LocalDateTime.parse(timeStr, DEFAULT_DATETIME_FORMATTER); 30 | } 31 | 32 | /** 33 | * String 转时间 34 | * 35 | * @param timeStr 36 | * @param format 时间格式 37 | * @return 38 | */ 39 | public static LocalDateTime parseTime(String timeStr, TimeFormat format) { 40 | return LocalDateTime.parse(timeStr, format.formatter); 41 | } 42 | 43 | /** 44 | * 时间转 String 45 | * 46 | * @param time 47 | * @return 48 | */ 49 | public static String parseTime(LocalDateTime time) { 50 | return DEFAULT_DATETIME_FORMATTER.format(time); 51 | } 52 | 53 | /** 54 | * 时间转 String 55 | * 56 | * @param time 57 | * @param format 时间格式 58 | * @return 59 | */ 60 | public static String parseTime(LocalDateTime time, TimeFormat format) { 61 | return format.formatter.format(time); 62 | } 63 | 64 | /** 65 | * 获取当前时间 66 | * 67 | * @return 68 | */ 69 | public static String getCurrentDatetime() { 70 | return DEFAULT_DATETIME_FORMATTER.format(LocalDateTime.now()); 71 | } 72 | 73 | /** 74 | * 获取当前时间 75 | * 76 | * @param format 时间格式 77 | * @return 78 | */ 79 | public static String getCurrentDatetime(TimeFormat format) { 80 | return format.formatter.format(LocalDateTime.now()); 81 | } 82 | 83 | /** 84 | * 时间格式 85 | */ 86 | public enum TimeFormat { 87 | 88 | /** 89 | * 短时间格式 90 | */ 91 | SHORT_DATE_PATTERN_LINE("yyyy-MM-dd"), 92 | SHORT_DATE_PATTERN_SLASH("yyyy/MM/dd"), 93 | SHORT_DATE_PATTERN_DOUBLE_SLASH("yyyy\\MM\\dd"), 94 | SHORT_DATE_PATTERN_NONE("yyyyMMdd"), 95 | 96 | /** 97 | * 长时间格式 98 | */ 99 | LONG_DATE_PATTERN_LINE("yyyy-MM-dd HH:mm:ss"), 100 | LONG_DATE_PATTERN_SLASH("yyyy/MM/dd HH:mm:ss"), 101 | LONG_DATE_PATTERN_DOUBLE_SLASH("yyyy\\MM\\dd HH:mm:ss"), 102 | LONG_DATE_PATTERN_NONE("yyyyMMdd HH:mm:ss"), 103 | 104 | /** 105 | * 长时间格式 带毫秒 106 | */ 107 | LONG_DATE_PATTERN_WITH_MILSEC_LINE("yyyy-MM-dd HH:mm:ss.SSS"), 108 | LONG_DATE_PATTERN_WITH_MILSEC_SLASH("yyyy/MM/dd HH:mm:ss.SSS"), 109 | LONG_DATE_PATTERN_WITH_MILSEC_DOUBLE_SLASH("yyyy\\MM\\dd HH:mm:ss.SSS"), 110 | LONG_DATE_PATTERN_WITH_MILSEC_NONE("yyyyMMdd HH:mm:ss.SSS"); 111 | 112 | private transient DateTimeFormatter formatter; 113 | 114 | TimeFormat(String pattern) { 115 | formatter = DateTimeFormatter.ofPattern(pattern); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /fast-core/src/main/java/org/fastframework/core/util/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.core.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.io.File; 8 | import java.lang.annotation.Annotation; 9 | import java.net.JarURLConnection; 10 | import java.net.URL; 11 | import java.util.ArrayList; 12 | import java.util.Enumeration; 13 | import java.util.List; 14 | import java.util.jar.JarEntry; 15 | import java.util.jar.JarFile; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * 类扫描工具类 20 | *

21 | * Created by bysocket on 16/7/20. 22 | */ 23 | public class ClassUtil { 24 | 25 | /** 26 | * 包目录分隔符:点 27 | */ 28 | public static final String PACKAGE_PATH_POINT = "."; 29 | /** 30 | * 包目录分隔符:点 31 | */ 32 | public static final String PACKAGE_PATH_SEPARATOR = "/"; 33 | /** 34 | * URL 协议名:file 35 | */ 36 | public static final String URL_PROTOCOL_FILE = "file"; 37 | /** 38 | * URL 协议名:jar 39 | */ 40 | public static final String URL_PROTOCOL_JAR = "jar"; 41 | /** 42 | * class 文件名后缀 43 | */ 44 | public static final String CLASS_FILE_END = ".class"; 45 | /** 46 | * class 文件分隔符:点 47 | */ 48 | public static final String CLASS_FILE_POINT = PACKAGE_PATH_POINT; 49 | private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class); 50 | /** 51 | * 当前线程的类加载 52 | */ 53 | private static final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); 54 | 55 | public static ClassLoader getCurrentClassLoader() { 56 | return currentClassLoader; 57 | } 58 | 59 | /** 60 | * 根据包名和注解,获取包下的有该注解的类列表 61 | * 62 | * @param packageName 63 | * @param annotationClass 64 | * @return 65 | */ 66 | public static List> getClassListByAnnotation(String packageName, Class annotationClass) { 67 | List> classList = getClassList(packageName); 68 | return classList.stream().filter(clazz -> 69 | clazz.isAnnotationPresent(annotationClass)).collect(Collectors.toList()); 70 | } 71 | 72 | /** 73 | * 根据包名,获取包下的类列表 74 | * 75 | * @param packageName 76 | * @return 77 | */ 78 | public final static List> getClassList(String packageName) { 79 | List> classList = new ArrayList<>(); 80 | try { 81 | // 从包名获取 URL 类型的资源 82 | Enumeration urlList = getCurrentClassLoader() 83 | .getResources(packageName.replace(PACKAGE_PATH_POINT, PACKAGE_PATH_SEPARATOR)); 84 | while (urlList.hasMoreElements()) { 85 | URL url = urlList.nextElement(); 86 | if (url != null) { 87 | // 获取 URL 协议名 [file] [jar] 88 | String protocol = url.getProtocol(); 89 | if (URL_PROTOCOL_FILE.equals(protocol)) { 90 | // 若在 class 目录,添加类 91 | String packagePath = url.getPath().replaceAll("%20", " "); 92 | addClass(classList, packagePath, packageName); 93 | } else if (URL_PROTOCOL_JAR.equals(protocol)) { 94 | // TODO 若在 jar 包中,则解析 jar 包中的 entry 95 | JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); 96 | JarFile jarFile = jarURLConnection.getJarFile(); 97 | Enumeration jarEntryEnumeration = jarFile.entries(); 98 | while (jarEntryEnumeration.hasMoreElements()) { 99 | JarEntry jarEntry = jarEntryEnumeration.nextElement(); 100 | String jarEntryName = jarEntry.getName(); 101 | } 102 | } 103 | } 104 | } 105 | } catch (Exception e) { 106 | LOGGER.error("获取扫描类错误"); 107 | } 108 | return classList; 109 | } 110 | 111 | /** 112 | * 根据 包路径 和 包名称,添加类到类列表(递归扫描) 113 | * 114 | * @param classList 115 | * @param packagePath 116 | * @param packageName 117 | */ 118 | private static void addClass(List> classList, String packagePath, String packageName) { 119 | try { 120 | // 获取 包路径 下的所有 class文件列表或目录 121 | File[] fileList = new File(packagePath).listFiles(file -> 122 | file.isFile() && file.getName().endsWith(CLASS_FILE_END) || file.isDirectory() 123 | ); 124 | // 遍历文件或目录 125 | for (File file : fileList) { 126 | String fileName = file.getName(); 127 | // 是文件 128 | if (file.isFile()) { 129 | // 是类名 130 | String className = fileName.substring(0, fileName.lastIndexOf(CLASS_FILE_POINT)); 131 | if (StringUtils.isNoneEmpty(className)) { 132 | className = packageName + PACKAGE_PATH_POINT + className; 133 | } 134 | 135 | Class clazz = loadClass(className, false); 136 | classList.add(clazz); 137 | } 138 | // 是目录 139 | else { 140 | // 子包 141 | String subPackagePath = fileName; 142 | if (StringUtils.isNotEmpty(packagePath)) { 143 | subPackagePath = packagePath + PACKAGE_PATH_SEPARATOR + subPackagePath; 144 | } 145 | 146 | // 子包名 147 | String subPackageName = fileName; 148 | if (StringUtils.isNotEmpty(packageName)) { 149 | subPackageName = packageName + PACKAGE_PATH_POINT + subPackageName; 150 | } 151 | 152 | // 递归调用添加类 153 | addClass(classList, subPackagePath, subPackageName); 154 | } 155 | } 156 | 157 | } catch (Exception e) { 158 | LOGGER.error("添加类错误"); 159 | } 160 | } 161 | 162 | /** 163 | * 加载类 164 | * 165 | * @param className 166 | * @param initialize 167 | * @return 168 | */ 169 | public static Class loadClass(String className, Boolean initialize) { 170 | Class clazz; 171 | try { 172 | clazz = Class.forName(className, initialize, getCurrentClassLoader()); 173 | } catch (ClassNotFoundException e) { 174 | LOGGER.error("加载类错误"); 175 | throw new RuntimeException(e); 176 | } 177 | return clazz; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.fast 7 | fast-framework 8 | 0.0.1-SNAPSHOT 9 | pom 10 | 11 | fast-project 12 | http://www.bysocket.com 13 | Fast Powerful Java Full-Stack Framework 14 | 15 | 16 | 17 | The Apache Software License, Version 2.0 18 | http://www.apache.org/licenses/LICENSE-2.0.txt 19 | 20 | 21 | 22 | 23 | BYSocket Open Source 24 | http://www.bysocket.com 25 | 26 | 27 | 28 | 29 | BYSocket Open Source 30 | bysocket@aliyun.com 31 | 32 | 33 | 34 | 35 | fast-core 36 | fast-sample 37 | 38 | 39 | 40 | 3.1 41 | 4.12 42 | 1.9.13 43 | 1.7.7 44 | 3.1.0 45 | 3.4 46 | 3.2.2 47 | 2.4 48 | 49 | 2.7.1 50 | 0.7.6.201602180812 51 | 1.4.1 52 | 53 | 1.8 54 | ${java.version} 55 | ${java.version} 56 | false 57 | UTF-8 58 | ${project.build.directory}/test-results 59 | 60 | 61 | 62 | 63 | 64 | org.fast 65 | fast-core 66 | 0.0.1-SNAPSHOT 67 | 68 | 69 | 70 | 71 | javax.servlet 72 | javax.servlet-api 73 | ${servlet.version} 74 | 75 | 76 | 77 | 78 | org.slf4j 79 | slf4j-log4j12 80 | ${slf4j.version} 81 | 82 | 83 | 84 | 85 | 86 | org.codehaus.jackson 87 | jackson-mapper-asl 88 | ${jackson.version} 89 | 90 | 91 | org.codehaus.jackson 92 | jackson-jaxrs 93 | ${jackson.version} 94 | 95 | 96 | 97 | 98 | org.apache.commons 99 | commons-lang3 100 | ${commons-lang.version} 101 | 102 | 103 | commons-collections 104 | commons-collections 105 | ${commons-collections.version} 106 | 107 | 108 | commons-io 109 | commons-io 110 | ${commons-io.version} 111 | 112 | 113 | 114 | 115 | junit 116 | junit 117 | ${junit.version} 118 | 119 | 120 | 121 | 122 | cglib 123 | cglib 124 | ${cglib.version} 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | org.jacoco 133 | jacoco-maven-plugin 134 | ${jacoco-maven-plugin.version} 135 | 136 | 137 | pre-unit-tests 138 | 139 | prepare-agent 140 | 141 | 142 | 143 | ${project.testResult.directory}/coverage/jacoco/jacoco.exec 144 | 145 | surefireArgLine 146 | 147 | 148 | 149 | 150 | post-unit-test 151 | test 152 | 153 | report 154 | 155 | 156 | ${project.testResult.directory}/coverage/jacoco/jacoco.exec 157 | ${project.testResult.directory}/coverage/jacoco 158 | 159 | 160 | 161 | 162 | 163 | org.codehaus.mojo 164 | sonar-maven-plugin 165 | ${sonar-maven-plugin.version} 166 | 167 | 168 | org.apache.maven.plugins 169 | maven-release-plugin 170 | 2.5.1 171 | 172 | 173 | org.apache.maven.plugins 174 | maven-javadoc-plugin 175 | 2.9 176 | 177 | 178 | attach-javadocs 179 | 180 | jar 181 | 182 | 183 | -Xdoclint:none 184 | 185 | 186 | 187 | 188 | 189 | org.apache.maven.plugins 190 | maven-enforcer-plugin 191 | ${maven-enforcer-plugin.version} 192 | 193 | 194 | enforce-versions 195 | 196 | enforce 197 | 198 | 199 | 200 | 201 | 202 | 203 | You are running an older version of Maven. fast-framework requires at least Maven 204 | 3.0 205 | 206 | [3.0.0,) 207 | 208 | 209 | You are running an older version of Java. fast-framework requires at least JDK 210 | ${java.version} 211 | 212 | [${java.version}.0,) 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /fast-core/src/test/java/org/fastframework/mvc/DispatcherServletTest.java: -------------------------------------------------------------------------------- 1 | package org.fastframework.mvc; 2 | 3 | import javax.servlet.*; 4 | import javax.servlet.http.*; 5 | import java.io.BufferedReader; 6 | import java.io.IOException; 7 | import java.io.UnsupportedEncodingException; 8 | import java.security.Principal; 9 | import java.util.*; 10 | 11 | /** 12 | * Created by bysocket on 16/8/9. 13 | */ 14 | public class DispatcherServletTest { 15 | public static void main(String[] args) throws Exception { 16 | DispatcherServlet d = new DispatcherServlet(); 17 | d.init(); 18 | d.service(getHttpServletRequest(), null); 19 | } 20 | 21 | public static HttpServletRequest getHttpServletRequest() { 22 | HttpServletRequest mock = new HttpServletRequest() { 23 | private final Map params = new HashMap<>(); 24 | 25 | @Override 26 | public String getAuthType() { 27 | return null; 28 | } 29 | 30 | @Override 31 | public Cookie[] getCookies() { 32 | return new Cookie[0]; 33 | } 34 | 35 | @Override 36 | public long getDateHeader(String name) { 37 | return 0; 38 | } 39 | 40 | @Override 41 | public String getHeader(String name) { 42 | return null; 43 | } 44 | 45 | @Override 46 | public Enumeration getHeaders(String name) { 47 | return null; 48 | } 49 | 50 | @Override 51 | public Enumeration getHeaderNames() { 52 | return null; 53 | } 54 | 55 | @Override 56 | public int getIntHeader(String name) { 57 | return 0; 58 | } 59 | 60 | @Override 61 | public String getMethod() { 62 | return "GET"; 63 | } 64 | 65 | @Override 66 | public String getPathInfo() { 67 | return "/hello"; 68 | } 69 | 70 | @Override 71 | public String getPathTranslated() { 72 | return null; 73 | } 74 | 75 | @Override 76 | public String getContextPath() { 77 | return null; 78 | } 79 | 80 | @Override 81 | public String getQueryString() { 82 | return null; 83 | } 84 | 85 | @Override 86 | public String getRemoteUser() { 87 | return null; 88 | } 89 | 90 | @Override 91 | public boolean isUserInRole(String role) { 92 | return false; 93 | } 94 | 95 | @Override 96 | public Principal getUserPrincipal() { 97 | return null; 98 | } 99 | 100 | @Override 101 | public String getRequestedSessionId() { 102 | return null; 103 | } 104 | 105 | @Override 106 | public String getRequestURI() { 107 | return null; 108 | } 109 | 110 | @Override 111 | public StringBuffer getRequestURL() { 112 | return null; 113 | } 114 | 115 | @Override 116 | public String getServletPath() { 117 | return null; 118 | } 119 | 120 | @Override 121 | public HttpSession getSession(boolean create) { 122 | return null; 123 | } 124 | 125 | @Override 126 | public HttpSession getSession() { 127 | return null; 128 | } 129 | 130 | @Override 131 | public String changeSessionId() { 132 | return null; 133 | } 134 | 135 | @Override 136 | public boolean isRequestedSessionIdValid() { 137 | return false; 138 | } 139 | 140 | @Override 141 | public boolean isRequestedSessionIdFromCookie() { 142 | return false; 143 | } 144 | 145 | @Override 146 | public boolean isRequestedSessionIdFromURL() { 147 | return false; 148 | } 149 | 150 | @Override 151 | public boolean isRequestedSessionIdFromUrl() { 152 | return false; 153 | } 154 | 155 | @Override 156 | public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { 157 | return false; 158 | } 159 | 160 | @Override 161 | public void login(String username, String password) throws ServletException { 162 | 163 | } 164 | 165 | @Override 166 | public void logout() throws ServletException { 167 | 168 | } 169 | 170 | @Override 171 | public Collection getParts() throws IOException, ServletException { 172 | return null; 173 | } 174 | 175 | @Override 176 | public Part getPart(String name) throws IOException, ServletException { 177 | return null; 178 | } 179 | 180 | @Override 181 | public T upgrade(Class handlerClass) throws IOException, ServletException { 182 | return null; 183 | } 184 | 185 | public Map getParameterMap() { 186 | return params; 187 | } 188 | 189 | @Override 190 | public String getProtocol() { 191 | return null; 192 | } 193 | 194 | @Override 195 | public String getScheme() { 196 | return null; 197 | } 198 | 199 | @Override 200 | public String getServerName() { 201 | return null; 202 | } 203 | 204 | @Override 205 | public int getServerPort() { 206 | return 0; 207 | } 208 | 209 | @Override 210 | public BufferedReader getReader() throws IOException { 211 | return null; 212 | } 213 | 214 | @Override 215 | public String getRemoteAddr() { 216 | return null; 217 | } 218 | 219 | @Override 220 | public String getRemoteHost() { 221 | return null; 222 | } 223 | 224 | @Override 225 | public void setAttribute(String name, Object o) { 226 | 227 | } 228 | 229 | @Override 230 | public void removeAttribute(String name) { 231 | 232 | } 233 | 234 | @Override 235 | public Locale getLocale() { 236 | return null; 237 | } 238 | 239 | @Override 240 | public Enumeration getLocales() { 241 | return null; 242 | } 243 | 244 | @Override 245 | public boolean isSecure() { 246 | return false; 247 | } 248 | 249 | @Override 250 | public RequestDispatcher getRequestDispatcher(String path) { 251 | return null; 252 | } 253 | 254 | @Override 255 | public String getRealPath(String path) { 256 | return null; 257 | } 258 | 259 | @Override 260 | public int getRemotePort() { 261 | return 0; 262 | } 263 | 264 | @Override 265 | public String getLocalName() { 266 | return null; 267 | } 268 | 269 | @Override 270 | public String getLocalAddr() { 271 | return null; 272 | } 273 | 274 | @Override 275 | public int getLocalPort() { 276 | return 0; 277 | } 278 | 279 | @Override 280 | public ServletContext getServletContext() { 281 | return null; 282 | } 283 | 284 | @Override 285 | public AsyncContext startAsync() throws IllegalStateException { 286 | return null; 287 | } 288 | 289 | @Override 290 | public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { 291 | return null; 292 | } 293 | 294 | @Override 295 | public boolean isAsyncStarted() { 296 | return false; 297 | } 298 | 299 | @Override 300 | public boolean isAsyncSupported() { 301 | return false; 302 | } 303 | 304 | @Override 305 | public AsyncContext getAsyncContext() { 306 | return null; 307 | } 308 | 309 | @Override 310 | public DispatcherType getDispatcherType() { 311 | return null; 312 | } 313 | 314 | @Override 315 | public Object getAttribute(String name) { 316 | return null; 317 | } 318 | 319 | @Override 320 | public Enumeration getAttributeNames() { 321 | return null; 322 | } 323 | 324 | @Override 325 | public String getCharacterEncoding() { 326 | return null; 327 | } 328 | 329 | @Override 330 | public void setCharacterEncoding(String env) throws UnsupportedEncodingException { 331 | 332 | } 333 | 334 | @Override 335 | public int getContentLength() { 336 | return 0; 337 | } 338 | 339 | @Override 340 | public long getContentLengthLong() { 341 | return 0; 342 | } 343 | 344 | @Override 345 | public String getContentType() { 346 | return null; 347 | } 348 | 349 | @Override 350 | public ServletInputStream getInputStream() throws IOException { 351 | return null; 352 | } 353 | 354 | public String getParameter(String name) { 355 | String[] matches = params.get(name); 356 | if (matches == null || matches.length == 0) return null; 357 | return matches[0]; 358 | } 359 | 360 | @Override 361 | public Enumeration getParameterNames() { 362 | Set set = new HashSet(); 363 | set.add("name"); 364 | return Collections.enumeration(set); 365 | } 366 | 367 | @Override 368 | public String[] getParameterValues(String name) { 369 | if (name.equals("name")) 370 | return new String[]{"BYSocket"}; 371 | return new String[]{""}; 372 | } 373 | 374 | }; 375 | 376 | return mock; 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------