├── .classpath
├── .project
├── .settings
├── .jsdtscope
├── org.eclipse.core.resources.prefs
├── org.eclipse.jdt.core.prefs
├── org.eclipse.m2e.core.prefs
├── org.eclipse.wst.common.component
├── org.eclipse.wst.common.project.facet.core.xml
├── org.eclipse.wst.jsdt.ui.superType.container
├── org.eclipse.wst.jsdt.ui.superType.name
└── org.eclipse.wst.validation.prefs
├── README.md
├── pom.xml
├── src
└── main
│ ├── java
│ └── com
│ │ └── liugh
│ │ ├── annotation
│ │ ├── MyController.java
│ │ ├── MyRequestMapping.java
│ │ └── MyRequestParam.java
│ │ ├── core
│ │ └── controller
│ │ │ └── TestController.java
│ │ └── servlet
│ │ └── MyDispatcherServlet.java
│ ├── resources
│ └── application.properties
│ └── webapp
│ └── WEB-INF
│ └── web.xml
└── target
├── classes
├── application.properties
└── com
│ └── liugh
│ ├── annotation
│ ├── MyController.class
│ ├── MyRequestMapping.class
│ └── MyRequestParam.class
│ ├── core
│ └── controller
│ │ └── TestController.class
│ └── servlet
│ └── MyDispatcherServlet.class
└── m2e-wtp
└── web-resources
└── META-INF
├── MANIFEST.MF
└── maven
└── com.liugh
└── liughMVC
├── pom.properties
└── pom.xml
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | liughMVC
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.wst.common.project.facet.core.builder
15 |
16 |
17 |
18 |
19 | org.eclipse.wst.validation.validationbuilder
20 |
21 |
22 |
23 |
24 | org.eclipse.m2e.core.maven2Builder
25 |
26 |
27 |
28 |
29 |
30 | org.eclipse.jem.workbench.JavaEMFNature
31 | org.eclipse.wst.common.modulecore.ModuleCoreNature
32 | org.eclipse.jdt.core.javanature
33 | org.eclipse.m2e.core.maven2Nature
34 | org.eclipse.wst.common.project.facet.core.nature
35 | org.eclipse.wst.jsdt.core.jsNature
36 |
37 |
38 |
--------------------------------------------------------------------------------
/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//src/main/java=UTF-8
3 | encoding//src/main/resources=UTF-8
4 | encoding//src/main/webapp=UTF-8
5 | encoding//src/test/java=UTF-8
6 | encoding//src/test/resources=UTF-8
7 | encoding/=UTF-8
8 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.compliance=1.8
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
8 | org.eclipse.jdt.core.compiler.source=1.8
9 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.common.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Window
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.validation.prefs:
--------------------------------------------------------------------------------
1 | disabled=06target
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### [博客地址](https://my.oschina.net/liughDevelop/blog/1622646)
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.liugh
4 | liughMVC
5 | 0.0.1-SNAPSHOT
6 | war
7 |
8 |
9 | UTF-8
10 | 1.8
11 | 1.8
12 | 1.8
13 |
14 |
15 |
16 |
17 | javax.servlet
18 | javax.servlet-api
19 | 3.0.1
20 | provided
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/main/java/com/liugh/annotation/MyController.java:
--------------------------------------------------------------------------------
1 | package com.liugh.annotation;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | @Target(ElementType.TYPE)
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Documented
12 | public @interface MyController {
13 | /**
14 | * 表示给controller注册别名
15 | * @return
16 | */
17 | String value() default "";
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/liugh/annotation/MyRequestMapping.java:
--------------------------------------------------------------------------------
1 | package com.liugh.annotation;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | @Target({ElementType.TYPE,ElementType.METHOD})
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Documented
12 | public @interface MyRequestMapping {
13 | /**
14 | * 表示访问该方法的url
15 | * @return
16 | */
17 | String value() default "";
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/liugh/annotation/MyRequestParam.java:
--------------------------------------------------------------------------------
1 | package com.liugh.annotation;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | @Target(ElementType.PARAMETER)
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Documented
12 | public @interface MyRequestParam {
13 | /**
14 | * 表示参数的别名,必填
15 | * @return
16 | */
17 | String value();
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/liugh/core/controller/TestController.java:
--------------------------------------------------------------------------------
1 | package com.liugh.core.controller;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 |
8 | import com.liugh.annotation.MyController;
9 | import com.liugh.annotation.MyRequestMapping;
10 | import com.liugh.annotation.MyRequestParam;
11 |
12 | @MyController
13 | @MyRequestMapping("/test")
14 | public class TestController {
15 |
16 |
17 |
18 | @MyRequestMapping("/doTest")
19 | public void test1(HttpServletRequest request, HttpServletResponse response,
20 | @MyRequestParam("param") String param){
21 | System.out.println(param);
22 | try {
23 | response.getWriter().write( "doTest method success! param:"+param);
24 | } catch (IOException e) {
25 | e.printStackTrace();
26 | }
27 | }
28 |
29 |
30 | @MyRequestMapping("/doTest2")
31 | public void test2(HttpServletRequest request, HttpServletResponse response){
32 | try {
33 | response.getWriter().println("doTest2 method success!");
34 | } catch (IOException e) {
35 | e.printStackTrace();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/liugh/servlet/MyDispatcherServlet.java:
--------------------------------------------------------------------------------
1 | package com.liugh.servlet;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.lang.reflect.Method;
7 | import java.net.URL;
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.HashMap;
11 | import java.util.List;
12 | import java.util.Map;
13 | import java.util.Map.Entry;
14 | import java.util.Properties;
15 |
16 | import javax.servlet.ServletConfig;
17 | import javax.servlet.ServletException;
18 | import javax.servlet.http.HttpServlet;
19 | import javax.servlet.http.HttpServletRequest;
20 | import javax.servlet.http.HttpServletResponse;
21 |
22 | import com.liugh.annotation.MyController;
23 | import com.liugh.annotation.MyRequestMapping;
24 |
25 | public class MyDispatcherServlet extends HttpServlet{
26 |
27 | private Properties properties = new Properties();
28 |
29 | private List classNames = new ArrayList<>();
30 |
31 | private Map ioc = new HashMap<>();
32 |
33 | private Map handlerMapping = new HashMap<>();
34 |
35 | private Map controllerMap =new HashMap<>();
36 |
37 |
38 | @Override
39 | public void init(ServletConfig config) throws ServletException {
40 |
41 | //1.加载配置文件
42 | doLoadConfig(config.getInitParameter("contextConfigLocation"));
43 |
44 | //2.初始化所有相关联的类,扫描用户设定的包下面所有的类
45 | doScanner(properties.getProperty("scanPackage"));
46 |
47 | //3.拿到扫描到的类,通过反射机制,实例化,并且放到ioc容器中(k-v beanName-bean) beanName默认是首字母小写
48 | doInstance();
49 |
50 | //4.初始化HandlerMapping(将url和method对应上)
51 | initHandlerMapping();
52 |
53 |
54 | }
55 |
56 |
57 |
58 | @Override
59 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
60 | this.doPost(req,resp);
61 | }
62 |
63 | @Override
64 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
65 | try {
66 | //处理请求
67 | doDispatch(req,resp);
68 | } catch (Exception e) {
69 | resp.getWriter().write("500!! Server Exception");
70 | }
71 |
72 | }
73 |
74 |
75 | private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
76 | if(handlerMapping.isEmpty()){
77 | return;
78 | }
79 |
80 | String url =req.getRequestURI();
81 | String contextPath = req.getContextPath();
82 |
83 | //拼接url并把多个/替换成一个
84 | url=url.replace(contextPath, "").replaceAll("/+", "/");
85 |
86 | if(!this.handlerMapping.containsKey(url)){
87 | resp.getWriter().write("404 NOT FOUND!");
88 | return;
89 | }
90 |
91 | Method method =this.handlerMapping.get(url);
92 |
93 | //获取方法的参数列表
94 | Class>[] parameterTypes = method.getParameterTypes();
95 |
96 | //获取请求的参数
97 | Map parameterMap = req.getParameterMap();
98 |
99 | //保存参数值
100 | Object [] paramValues= new Object[parameterTypes.length];
101 |
102 | //方法的参数列表
103 | for (int i = 0; i param : parameterMap.entrySet()) {
119 | String value =Arrays.toString(param.getValue()).replaceAll("\\[|\\]", "").replaceAll(",\\s", ",");
120 | paramValues[i]=value;
121 | }
122 | }
123 | }
124 | //利用反射机制来调用
125 | try {
126 | method.invoke(this.controllerMap.get(url), paramValues);//obj是method所对应的实例 在ioc容器中
127 | } catch (Exception e) {
128 | e.printStackTrace();
129 | }
130 | }
131 |
132 |
133 |
134 | private void doLoadConfig(String location){
135 | //把web.xml中的contextConfigLocation对应value值的文件加载到留里面
136 | InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(location);
137 | try {
138 | //用Properties文件加载文件里的内容
139 | properties.load(resourceAsStream);
140 | } catch (IOException e) {
141 | e.printStackTrace();
142 | }finally {
143 | //关流
144 | if(null!=resourceAsStream){
145 | try {
146 | resourceAsStream.close();
147 | } catch (IOException e) {
148 | e.printStackTrace();
149 | }
150 | }
151 | }
152 |
153 | }
154 |
155 | private void doScanner(String packageName) {
156 | //把所有的.替换成/
157 | URL url =this.getClass().getClassLoader().getResource("/"+packageName.replaceAll("\\.", "/"));
158 | File dir = new File(url.getFile());
159 | for (File file : dir.listFiles()) {
160 | if(file.isDirectory()){
161 | //递归读取包
162 | doScanner(packageName+"."+file.getName());
163 | }else{
164 | String className =packageName +"." +file.getName().replace(".class", "");
165 | classNames.add(className);
166 | }
167 | }
168 | }
169 |
170 |
171 |
172 | private void doInstance() {
173 | if (classNames.isEmpty()) {
174 | return;
175 | }
176 | for (String className : classNames) {
177 | try {
178 | //把类搞出来,反射来实例化(只有加@MyController需要实例化)
179 | Class> clazz =Class.forName(className);
180 | if(clazz.isAnnotationPresent(MyController.class)){
181 | ioc.put(toLowerFirstWord(clazz.getSimpleName()),clazz.newInstance());
182 | }else{
183 | continue;
184 | }
185 |
186 |
187 | } catch (Exception e) {
188 | e.printStackTrace();
189 | continue;
190 | }
191 | }
192 | }
193 |
194 |
195 | private void initHandlerMapping(){
196 | if(ioc.isEmpty()){
197 | return;
198 | }
199 | try {
200 | for (Entry entry: ioc.entrySet()) {
201 | Class extends Object> clazz = entry.getValue().getClass();
202 | if(!clazz.isAnnotationPresent(MyController.class)){
203 | continue;
204 | }
205 |
206 | //拼url时,是controller头的url拼上方法上的url
207 | String baseUrl ="";
208 | if(clazz.isAnnotationPresent(MyRequestMapping.class)){
209 | MyRequestMapping annotation = clazz.getAnnotation(MyRequestMapping.class);
210 | baseUrl=annotation.value();
211 | }
212 | Method[] methods = clazz.getMethods();
213 | for (Method method : methods) {
214 | if(!method.isAnnotationPresent(MyRequestMapping.class)){
215 | continue;
216 | }
217 | MyRequestMapping annotation = method.getAnnotation(MyRequestMapping.class);
218 | String url = annotation.value();
219 |
220 | url =(baseUrl+"/"+url).replaceAll("/+", "/");
221 | //这里应该放置实例和method
222 | handlerMapping.put(url,method);
223 | controllerMap.put(url,clazz.newInstance());
224 | System.out.println(url+","+method);
225 | }
226 |
227 | }
228 |
229 | } catch (Exception e) {
230 | e.printStackTrace();
231 | }
232 |
233 | }
234 |
235 |
236 | /**
237 | * 把字符串的首字母小写
238 | * @param name
239 | * @return
240 | */
241 | private String toLowerFirstWord(String name){
242 | char[] charArray = name.toCharArray();
243 | charArray[0] += 32;
244 | return String.valueOf(charArray);
245 | }
246 |
247 |
248 | }
249 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | scanPackage=com.liugh.core
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | MySpringMVC
8 | com.liugh.servlet.MyDispatcherServlet
9 |
10 | contextConfigLocation
11 | application.properties
12 |
13 | 1
14 |
15 |
16 | MySpringMVC
17 | /*
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/target/classes/application.properties:
--------------------------------------------------------------------------------
1 | scanPackage=com.liugh.core
--------------------------------------------------------------------------------
/target/classes/com/liugh/annotation/MyController.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qq53182347/liughMVC/a6559383071053fa04088303b02193088b24fdab/target/classes/com/liugh/annotation/MyController.class
--------------------------------------------------------------------------------
/target/classes/com/liugh/annotation/MyRequestMapping.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qq53182347/liughMVC/a6559383071053fa04088303b02193088b24fdab/target/classes/com/liugh/annotation/MyRequestMapping.class
--------------------------------------------------------------------------------
/target/classes/com/liugh/annotation/MyRequestParam.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qq53182347/liughMVC/a6559383071053fa04088303b02193088b24fdab/target/classes/com/liugh/annotation/MyRequestParam.class
--------------------------------------------------------------------------------
/target/classes/com/liugh/core/controller/TestController.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qq53182347/liughMVC/a6559383071053fa04088303b02193088b24fdab/target/classes/com/liugh/core/controller/TestController.class
--------------------------------------------------------------------------------
/target/classes/com/liugh/servlet/MyDispatcherServlet.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qq53182347/liughMVC/a6559383071053fa04088303b02193088b24fdab/target/classes/com/liugh/servlet/MyDispatcherServlet.class
--------------------------------------------------------------------------------
/target/m2e-wtp/web-resources/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Built-By: Administrator
3 | Build-Jdk: 1.8.0_101
4 | Created-By: Maven Integration for Eclipse
5 |
6 |
--------------------------------------------------------------------------------
/target/m2e-wtp/web-resources/META-INF/maven/com.liugh/liughMVC/pom.properties:
--------------------------------------------------------------------------------
1 | #Generated by Maven Integration for Eclipse
2 | #Fri Feb 23 17:11:07 CST 2018
3 | version=0.0.1-SNAPSHOT
4 | groupId=com.liugh
5 | m2e.projectName=liughMVC
6 | m2e.projectLocation=D\:\\javaSoft\\eclipse-neon\\eclipse\\workspace\\liughMVC
7 | artifactId=liughMVC
8 |
--------------------------------------------------------------------------------
/target/m2e-wtp/web-resources/META-INF/maven/com.liugh/liughMVC/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.liugh
4 | liughMVC
5 | 0.0.1-SNAPSHOT
6 | war
7 |
8 |
9 | UTF-8
10 | 1.8
11 | 1.8
12 | 1.8
13 |
14 |
15 |
16 |
17 | javax.servlet
18 | javax.servlet-api
19 | 3.0.1
20 | provided
21 |
22 |
23 |
--------------------------------------------------------------------------------