├── .gitignore
├── README.md
├── pom.xml
└── src
└── main
├── java
└── org
│ └── aisframework
│ └── web
│ ├── annotation
│ ├── Controller.java
│ ├── MapURL.java
│ └── ResponseBody.java
│ ├── asm
│ ├── ReadMethodArgNameClassVisitor.java
│ └── ReadMethodArgNameMethodVisitor.java
│ ├── classcollection
│ └── ClassCollection.java
│ ├── param
│ ├── HandlerMapping.java
│ └── MethodResolver.java
│ ├── servlet
│ └── AisDispatcherServlet.java
│ ├── structure
│ ├── MethodPro.java
│ ├── ModelMap.java
│ └── RequestMethod.java
│ ├── test
│ └── test.java
│ └── utils
│ ├── AjaxUtils.java
│ ├── AsmUtils.java
│ ├── CollectionUtils.java
│ ├── Config.java
│ ├── FileUtils.java
│ ├── ReflectProcessor.java
│ ├── ReflectUtils.java
│ └── StringUtils.java
├── resources
└── config.ini
└── webapp
├── WEB-INF
├── page
│ ├── 404.html
│ └── succ.html
└── web.xml
├── ajaxtest.html
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Maven #
3 | target/
4 | # IDEA #
5 | .idea/
6 | *.iml
7 | # Eclipse #
8 | .settings/
9 | .metadata/
10 | .classpath
11 | .project
12 | Servers
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## AisMVC,一款仿SpringMVC框架的轻便快捷的Java MVC开发框架
2 |
3 | #### 前言
4 | * 写这个框架的意义在于过去使用springmvc框架作为项目中的Controller层,springmvc的简洁配置和使用让我们选择了它,但这个框架我用着也发现了它也有很多冗余功能的地方。我们团队开发web项目一般采用前后端分离,所以后端的的Controller层的功能仅仅只有提供ajax接口,页面集成后的跳转,过滤器和拦截器,所以我就想着自己写一款仿springmvc的mvc框架作为自己和团队以后的开发中小型项目的框架,舍掉冗余的部分,只要项目中实际需要的功能
5 |
6 | #### 这个框架暂时还没有经过严密的测试,所以想使用的同学我在这里说声抱歉,虽然我自己通过maven打成jar包测试过,但暂时没有用于实际开发的打算,第一是自己一个人的实力有限还是怕真实运用中出现自己不能解决的问题,其实我目前内心的真实想法是告诉大家一个mvc框架到底是怎么实现的,springmvc框架想一下吃透也不现实,如果通过我的这个框架大家也有写框架的动力和思路我也是我想看到的,也想告诉大家只要动起手来自己也能写框架,有些东西不是说说而已。很多人或许会说现在mvc框架这么多,你的这个算什么啊?但我想说现在很多时候我们百度搜索的资料来自前人,很多都是5,6年前的老资料了,我也不想以后我们的后辈通过搜索引擎搜出来的还是我们这个时候搜出来的前人总结,开发的资料。我想我也应该留点东西了。
7 | #### 框架流程图
8 |
9 | 
10 |
11 | #### 功能代码演示
12 |
13 | ```Java
14 |
15 | /**
16 | * Created by gaorui on 16/6/14.
17 | */
18 | @Controller
19 | public class test {
20 |
21 |
22 | /**
23 | * @author gaorui
24 | * @param s1
25 | * @param s2
26 | * @param request
27 | * @param response
28 | * @param session
29 | * 普通url处理
30 | */
31 | @MapURL(value = "get",RequestMethod = RequestMethod.GET)
32 | public void get(String s1,String s2,HttpServletRequest request, HttpServletResponse response, HttpSession session){
33 |
34 | return;
35 | }
36 |
37 |
38 | /**
39 | * @author gaorui
40 | * @return String
41 | * 服务端跳转页面处理,默认 web-inf下所有 .html文件
42 | */
43 | @MapURL(value="foward")
44 | public String foward(){
45 |
46 | return "page/succ";
47 |
48 | }
49 |
50 | /**
51 | * @author gaorui
52 | * @param userid
53 | * @return Object
54 | * 服务端处理前端ajax请求,返回json数据
55 | */
56 | @MapURL(value = "getUser", RequestMethod = RequestMethod.GET)
57 | @ResponseBody
58 | public JSONObject getUser(int userid){
59 |
60 | JSONObject jsonObject = new JSONObject();
61 | jsonObject.put("userid",userid);
62 | return jsonObject;
63 |
64 | }
65 | }
66 |
67 | ```
68 | #### mvc框架功能介绍
69 | * 注解实现
70 | * @MapURL注解实现http请求路由
71 | * 反射实现方法参数注入
72 | * String返回类型方法转发请求
73 | * @ResponseBody注解实现ajax接口
74 | * 增加config.ini配置文件,实现定向动态扫描项目中的@Controller 类
75 | * 增加注解参数RequestMethod 默认http请求类型,请求类型不合法返回405状态码
76 |
77 | #### commit log
78 | * 1.0 初始化项目
79 | * 1.1 dhy join
80 | * 1.2 mvc框架功能雏形
81 | * 1.3 增加handlerMapping处理器映射,控制器卸耦
82 | * 1.4 增加config.ini配置文件,实现定向动态扫描项目中的@Controller 类
83 | * 1.5 增加注解参数RequestMethod 默认http请求类型,请求类型不合法返回405状态码
84 | * 1.6 下一步准备做项目的容错处理,过滤器准备用原生的不准备加入框架
85 | * 1.7 修改部分目录结构,画框架整体流程图,后面继续做容错处理和性能优化
86 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.AisMVC
5 | AisMVC
6 | war
7 | 0.0.1-SNAPSHOT
8 | AisMVC Maven Webapp
9 | http://maven.apache.org
10 |
11 | 1.6
12 | 1.6
13 | UTF-8
14 | 3.0.1
15 |
16 |
17 |
18 |
19 | javax.servlet
20 | javax.servlet-api
21 | 3.1.0
22 | provided
23 |
24 |
25 |
26 | org.ow2.asm
27 | asm-all
28 | 5.0.3
29 |
30 |
31 | com.alibaba
32 | fastjson
33 | 1.1.42
34 |
35 |
36 |
37 |
38 |
39 |
40 | org.apache.maven.plugins
41 | maven-compiler-plugin
42 | 3.1
43 |
44 | 1.6
45 | 1.6
46 | UTF-8
47 |
48 |
49 | maven-assembly-plugin
50 |
51 |
52 |
53 | com.allen.capturewebdata.Main
54 |
55 |
56 |
57 | jar-with-dependencies
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/main/java/org/aisframework/web/annotation/Controller.java:
--------------------------------------------------------------------------------
1 | package org.aisframework.web.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 gaorui on 2016/6/14.
10 | */
11 | @Target(ElementType.TYPE)
12 | @Retention(RetentionPolicy.RUNTIME)
13 | public @interface Controller {}
14 |
--------------------------------------------------------------------------------
/src/main/java/org/aisframework/web/annotation/MapURL.java:
--------------------------------------------------------------------------------
1 | package org.aisframework.web.annotation;
2 |
3 | import org.aisframework.web.structure.RequestMethod;
4 |
5 | import java.lang.annotation.ElementType;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.RetentionPolicy;
8 | import java.lang.annotation.Target;
9 |
10 | /**
11 | * Created by gaorui on 2016/6/14.
12 | */
13 | @Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR})
14 | @Retention(RetentionPolicy.RUNTIME)
15 | public @interface MapURL {
16 | String value();
17 | String RequestMethod() default "GET";
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/org/aisframework/web/annotation/ResponseBody.java:
--------------------------------------------------------------------------------
1 | package org.aisframework.web.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 gaorui on 16/6/18.
10 | */
11 | @Target(ElementType.METHOD)
12 | @Retention(RetentionPolicy.RUNTIME)
13 | public @interface ResponseBody {
14 |
15 |
16 | }
--------------------------------------------------------------------------------
/src/main/java/org/aisframework/web/asm/ReadMethodArgNameClassVisitor.java:
--------------------------------------------------------------------------------
1 | package org.aisframework.web.asm;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import org.objectweb.asm.ClassVisitor;
9 | import org.objectweb.asm.MethodVisitor;
10 | import org.objectweb.asm.Opcodes;
11 | import org.objectweb.asm.Type;
12 |
13 | public class ReadMethodArgNameClassVisitor extends ClassVisitor {
14 |
15 | public Map> nameArgMap = new HashMap>();
16 |
17 | public ReadMethodArgNameClassVisitor() {
18 | super(Opcodes.ASM5);
19 | }
20 |
21 | @Override
22 | public MethodVisitor visitMethod(int access, String name, String desc,
23 | String signature, String[] exceptions) {
24 | Type methodType = Type.getMethodType(desc);
25 | int len = methodType.getArgumentTypes().length;
26 | List argumentNames = new ArrayList();
27 | nameArgMap.put(name, argumentNames);
28 | ReadMethodArgNameMethodVisitor visitor = new ReadMethodArgNameMethodVisitor(Opcodes.ASM5);
29 | visitor.argumentNames = argumentNames;
30 | visitor.argLen = len;
31 | return visitor;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/aisframework/web/asm/ReadMethodArgNameMethodVisitor.java:
--------------------------------------------------------------------------------
1 | package org.aisframework.web.asm;
2 |
3 | /**
4 | * Created by lenovo on 2016/5/19.
5 | */
6 |
7 | import org.objectweb.asm.Label;
8 | import org.objectweb.asm.MethodVisitor;
9 |
10 | import java.util.List;
11 |
12 | public class ReadMethodArgNameMethodVisitor extends MethodVisitor {
13 |
14 | public List argumentNames;
15 |
16 | public int argLen;
17 |
18 | public ReadMethodArgNameMethodVisitor(int api) {
19 | super(api);
20 | }
21 |
22 | @Override
23 | public void visitLocalVariable(String name, String desc, String signature,
24 | Label start, Label end, int index) {
25 | if("this".equals(name)) {
26 | return;
27 | }
28 | if(argLen-- > 0) {
29 | argumentNames.add(name);
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/aisframework/web/classcollection/ClassCollection.java:
--------------------------------------------------------------------------------
1 | package org.aisframework.web.classcollection;
2 |
3 |
4 |
5 | import org.aisframework.web.annotation.Controller;
6 | import org.aisframework.web.annotation.MapURL;
7 | import org.aisframework.web.annotation.ResponseBody;
8 | import org.aisframework.web.structure.MethodPro;
9 | import org.aisframework.web.utils.Config;
10 | import org.aisframework.web.utils.FileUtils;
11 | import org.aisframework.web.utils.StringUtils;
12 |
13 | import java.lang.reflect.Method;
14 | import java.util.HashMap;
15 | import java.util.HashSet;
16 | import java.util.Map;
17 | import java.util.Set;
18 |
19 | /**
20 | * Created by gaorui on 2016/6/14.
21 | */
22 | public class ClassCollection {
23 | public static Map methodMap;
24 | public static Set> classSet;
25 | public static Map> classMap;
26 | public static void scanClassSetByPackage(String packageName)
27 | {
28 | methodMap=new HashMap();
29 | classMap=new HashMap>();
30 | classSet=new HashSet>();
31 | String filePath= Config.getProPath()+ StringUtils.modifyPackagePath(packageName);
32 | FileUtils.getClassSet(filePath,classSet,packageName);
33 | for(Class> clazz:classSet)
34 | {
35 | if(clazz.isAnnotationPresent(Controller.class))
36 | {
37 | Method[] methods=clazz.getDeclaredMethods();
38 | for(Method method:methods)
39 | {
40 | if(method.isAnnotationPresent(MapURL.class))
41 | {
42 | MapURL mapURL=method.getAnnotation(MapURL.class);
43 | boolean b = false;
44 | if(method.isAnnotationPresent(ResponseBody.class)){
45 | b = true;
46 | }
47 | MethodPro mp=new MethodPro(method,mapURL.value(),mapURL.RequestMethod(),b);
48 |
49 | methodMap.put(mapURL.value(),mp);
50 | classMap.put(mapURL.value(),clazz);
51 |
52 | }
53 |
54 | }
55 | }
56 | }
57 | }
58 |
59 | public static Set> getClassSet() {
60 | return classSet;
61 | }
62 |
63 |
64 |
65 | public static Map getMethodMap() {
66 | return methodMap;
67 | }
68 |
69 | public static Map> getClassMap() {
70 | return classMap;
71 | }
72 |
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/org/aisframework/web/param/HandlerMapping.java:
--------------------------------------------------------------------------------
1 | package org.aisframework.web.param;
2 |
3 | import org.aisframework.web.structure.MethodPro;
4 | import org.aisframework.web.test.test;
5 | import org.aisframework.web.utils.CollectionUtils;
6 | import org.aisframework.web.utils.ReflectProcessor;
7 |
8 | import javax.servlet.http.HttpServletRequest;
9 | import javax.servlet.http.HttpServletResponse;
10 | import java.lang.reflect.Method;
11 | import java.util.List;
12 | import java.util.Map;
13 |
14 | /**
15 | * Created by gaorui on 16/6/19.
16 | */
17 | public class HandlerMapping {
18 |
19 | public static void HandlerMapping(HttpServletRequest req,HttpServletResponse resp, Map methodProMap, String key) {
20 |
21 | try {
22 |
23 | List paramlist = MethodResolver.getMethodNames(methodProMap.get(key).getMethod().getDeclaringClass().getName(), key);
24 | Map params = req.getParameterMap();
25 | MethodPro methodPro = methodProMap.get(key);
26 | Method method = methodPro.getMethod();
27 | List classNames = CollectionUtils.classArrToStringList(method.getParameterTypes());
28 | Object[] invokeParamVulue = MethodResolver.paramarray(paramlist, classNames, req, resp, params);;
29 | Method urlmethod = methodProMap.get(key).getMethod();
30 |
31 | String reqtype = req.getMethod().toUpperCase();
32 |
33 | //http请求处理
34 | if(methodPro.getUrlStyle().equals("POST")){
35 | if(!reqtype.equals("POST")) {
36 |
37 | resp.sendError(405);
38 | //resp.getWriter().print("405 not allowed");
39 | return;
40 | }
41 | }
42 |
43 | //String返回方法参数类型处理
44 | if (urlmethod.getReturnType().getName().equals("java.lang.String")) {
45 |
46 | String uri = ReflectProcessor.parseMethod(method,test.class, key, invokeParamVulue).toString();
47 | req.getRequestDispatcher("WEB-INF/" + uri + ".html").forward(req, resp);
48 | return;
49 |
50 | //ajax接口处理
51 | } else if (methodProMap.get(key).getAjax()) {
52 |
53 | Object o = ReflectProcessor.parseMethod(method,test.class, key, invokeParamVulue);
54 | resp.getWriter().print(o);
55 | return;
56 | }
57 |
58 | ReflectProcessor.parseMethod(method,test.class, key, invokeParamVulue);
59 | return;
60 | } catch (Exception e) {
61 | e.printStackTrace();
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/org/aisframework/web/param/MethodResolver.java:
--------------------------------------------------------------------------------
1 | package org.aisframework.web.param;
2 |
3 |
4 | import org.aisframework.web.asm.ReadMethodArgNameClassVisitor;
5 | import org.aisframework.web.structure.ModelMap;
6 | import org.aisframework.web.utils.Config;
7 | import org.objectweb.asm.ClassReader;
8 |
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletResponse;
11 | import java.io.File;
12 | import java.io.FileInputStream;
13 | import java.io.IOException;
14 | import java.io.InputStream;
15 | import java.util.*;
16 | import java.util.Map.Entry;
17 |
18 | public class MethodResolver {
19 |
20 |
21 |
22 | public static List getMethodNames(String className,String methodName) throws IOException {
23 | List list=new ArrayList();
24 | String cn= Config.getProPath()+className.replace(".", "/")+".class";
25 | InputStream is=new FileInputStream(new File(cn));
26 | ClassReader cr = new ClassReader(is);
27 | ReadMethodArgNameClassVisitor classVisitor = new ReadMethodArgNameClassVisitor();
28 | cr.accept(classVisitor, 0);
29 | for(Entry> entry : classVisitor.nameArgMap.entrySet()) {
30 | if(entry.getKey().equals(methodName)) {
31 | for (String s : entry.getValue()) {
32 | list.add(s);
33 | }
34 | }
35 | }
36 | return list;
37 | }
38 |
39 |
40 |
41 | public static Object[] paramarray(List paraNames, List classNames, HttpServletRequest req, HttpServletResponse resp, Map params) {
42 | List