Java手写MVC实现过程

Java手写MVC实现过程

参考:手写MVC实现过程

手写mvc前基础知识

mvc是什么

MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。

mvc能帮我们做什么

1.让我们能非常简单的设计出干净的Web层和薄薄的Web层;

2.进行更简洁的Web层的开发;

3.提供强大的约定大于配置的契约式编程支持;

4.能简单的进行Web层的单元测试;

5.支持灵活的URL到页面控制器的映射;

6.非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API

7.更加简单的异常处理。

spring mvc 架构图

image-20231013105503650

image-20231013105516843

手写mvc实现过程

image-20231013105547725

定义配置标记

1.@RequestMapping:标识Controller的方法与请求路径和请求方法的映射关系

2.@RequestParam:请求的方法参数名称

3.@ResponseBody:用于标记自动对返回值进行json处理

转发控制器

核心流程:

1.初始化

  • 1.初始化容器
  • 2.doAop
  • 3.doIoc
  • 4.初始化请求处理器责任链

2.处理请求

  • 1.创建责任链对象实例
  • 2.通过责任链模式来依次调用请求处理器对请求进行处理
  • 3.对处理结果进行渲染
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package org.simplespring.mvc;
import org.simplespring.aop.AspectWeaver;
import org.simplespring.core.BeanContainer;
import org.simplespring.inject.DependencyInjector;
import org.simplespring.mvc.processor.RequestProcessor;
import org.simplespring.mvc.processor.impl.ControllerRequestProcessor;
import org.simplespring.mvc.processor.impl.JspRequestProcessor;
import org.simplespring.mvc.processor.impl.PreRequestProcessor;
import org.simplespring.mvc.processor.impl.StaticResourceRequestProcessor;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
* 请求转发器
*/
@WebServlet("/*")
public class DispatcherServlet extends HttpServlet {
List<RequestProcessor> PROCESSOR = new ArrayList<>();

/**
* 初始化
* 1.初始化容器
* 2.doAop
* 3.doIoc
* 4.初始化请求处理器责任链
*/
@Override
public void init(){
//1.初始化容器
BeanContainer beanContainer = BeanContainer.getInstance();
beanContainer.loadBeans("com.zhangtianci");
new AspectWeaver().doAop();
new DependencyInjector().doIoc();
//2.初始化请求处理器责任链
PROCESSOR.add(new PreRequestProcessor());
PROCESSOR.add(new StaticResourceRequestProcessor(getServletContext()));
PROCESSOR.add(new JspRequestProcessor(getServletContext()));
PROCESSOR.add(new ControllerRequestProcessor());
}

/**
* 1.创建责任链对象实例
* 2.通过责任链模式来依次调用请求处理器对请求进行处理
* 3.对处理结果进行渲染
* @param req
* @param resp
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) {
//1.创建责任链对象实例
RequestProcessorChain requestProcessorChain = new RequestProcessorChain(PROCESSOR.iterator(), req, resp);
//2.通过责任链模式来依次调用请求处理器对请求进行处理
requestProcessorChain.doRequestProcessorChain();
//3.对处理结果进行渲染
requestProcessorChain.doRender();
}
}

请求处理责任链

1.以责任链的模式执行注册的请求处理器

2.委派给特定的Render实例对处理后的结果进行渲染

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package org.simplespring.mvc;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.simplespring.mvc.processor.RequestProcessor;
import org.simplespring.mvc.render.DefaultResultRender;
import org.simplespring.mvc.render.InternalErrorResultRender;
import org.simplespring.mvc.render.ResultRender;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;

/**
* 请求处理责任链
*
* 1.以责任链的模式执行注册的请求处理器
* 2.委派给特定的Render实例对处理后的结果进行渲染
*/
@Data
@Slf4j
public class RequestProcessorChain {
//请求处理器迭代器
private Iterator<RequestProcessor> requestProcessorIterator;
//请求request
private HttpServletRequest request;
//请求response
private HttpServletResponse response;
//http请求方法
private String requestMethod;
//http请求路径
private String requestPath;
//http响应状态码
private int responseCode;
//请求结果渲染器
private ResultRender resultRender;

public RequestProcessorChain(Iterator<RequestProcessor> iterator, HttpServletRequest req, HttpServletResponse resp) {
this.requestProcessorIterator = iterator;
this.request = req;
this.response = resp;
this.requestMethod = req.getMethod();
this.requestPath = req.getPathInfo();
this.responseCode = HttpServletResponse.SC_OK;
}
/**
* 以责任链的模式执行请求链
*/
public void doRequestProcessorChain() {
//1.通过迭代器遍历注册的请求处理器实现类列表
try{
while(requestProcessorIterator.hasNext()){
//2.直到某个请求处理器执行后返回为false为止
if(!requestProcessorIterator.next().process(this)){
break;
}
}} catch (Exception e){
//3.期间如果出现异常,则交由内部异常渲染器处理
this.resultRender = new InternalErrorResultRender(e.getMessage());
log.error("doRequestProcessorChain error:", e);
}


}
/**
* 执行处理器
*/
public void doRender() {
//1.如果请求处理器实现类均未选择合适的渲染器,则使用默认的
if(this.resultRender == null){
this.resultRender = new DefaultResultRender();
}
//2.调用渲染器的render方法对结果进行渲染
try {
this.resultRender.render(this);
} catch (Exception e) {
log.error("doRender error: ", e);
throw new RuntimeException(e);
}
}
}

定义RequestProcessor矩阵

定义处理动作规范

1
2
3
4
5
6
/**
* 请求执行器接口
*/
public interface RequestProcessor {
boolean process(RequestProcessorChain requestProcessorChain) throws Exception;
}

请求预处理器

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
package org.simplespring.mvc.processor.impl;

import lombok.extern.slf4j.Slf4j;
import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.processor.RequestProcessor;

/**
* 请求预处理,包括编码以及路径处理
*/
@Slf4j
public class PreRequestProcessor implements RequestProcessor {
@Override
public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
// 1.设置请求编码,将其统一设置成UTF-8
requestProcessorChain.getRequest().setCharacterEncoding("UTF-8");
// 2.将请求路径末尾的/剔除,为后续匹配Controller请求路径做准备
// (一般Controller的处理路径是/aaa/bbb,所以如果传入的路径结尾是/aaa/bbb/,
// 就需要处理成/aaa/bbb)
String requestPath = requestProcessorChain.getRequestPath();
//http://localhost:8080/simpleframework requestPath="/"
if(requestPath.length() > 1 && requestPath.endsWith("/")){
requestProcessorChain.setRequestPath(requestPath.substring(0, requestPath.length() - 1));
}
log.info("preprocess request {} {}", requestProcessorChain.getRequestMethod(), requestProcessorChain.getRequestPath());
return true;
}
}

静态资源请求处理器

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
package org.simplespring.mvc.processor.impl;

import lombok.extern.slf4j.Slf4j;
import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.processor.RequestProcessor;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;

/**
* 静态资源请求处理,包括但不限于图片、css、以及js文件等 - DefaultServlet
*/
@Slf4j
public class StaticResourceRequestProcessor implements RequestProcessor {
public static final String DEFAULT_TOMCAT_SERVLET = "default";
public static final String STATIC_RESOURCE_PREFIX = "/static/";
//tomcat默认请求派发器RequestDispatcher的名称
RequestDispatcher defaultDispatcher;

public StaticResourceRequestProcessor(ServletContext servletContext) {
this.defaultDispatcher = servletContext.getNamedDispatcher(DEFAULT_TOMCAT_SERVLET);
if(this.defaultDispatcher == null){
throw new RuntimeException("There is no default tomcat servlet");
}
log.info("The default servlet for static resource is {}", DEFAULT_TOMCAT_SERVLET);
}

@Override
public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
//1.通过请求路径判断是否是请求的静态资源 webapp/static
if(isStaticResource(requestProcessorChain.getRequestPath())){
//2.如果是静态资源,则将请求转发给default servlet处理
defaultDispatcher.forward(requestProcessorChain.getRequest(), requestProcessorChain.getResponse());
return false;
}
return true;
}
//通过请求路径前缀(目录)是否为静态资源 /static/
private boolean isStaticResource(String path){
return path.startsWith(STATIC_RESOURCE_PREFIX);
}
}

jsp资源请求处理器

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
44
45
46
47
package org.simplespring.mvc.processor.impl;

import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.processor.RequestProcessor;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;

/**
* jsp资源请求处理
*/
public class JspRequestProcessor implements RequestProcessor {

//jsp请求的RequestDispatcher的名称
private static final String JSP_SERVLET = "jsp";
//Jsp请求资源路径前缀
private static final String JSP_RESOURCE_PREFIX = "/templates/";

/**
* jsp的RequestDispatcher,处理jsp资源
*/
private RequestDispatcher jspServlet;

public JspRequestProcessor(ServletContext servletContext) {
jspServlet = servletContext.getNamedDispatcher(JSP_SERVLET);
if (null == jspServlet) {
throw new RuntimeException("there is no jsp servlet");
}
}

@Override
public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
if (isJspResource(requestProcessorChain.getRequestPath())) {
jspServlet.forward(requestProcessorChain.getRequest(), requestProcessorChain.getResponse());
return false;
}
return true;
}

/**
* 是否请求的是jsp资源
*/
private boolean isJspResource(String url) {
return url.startsWith(JSP_RESOURCE_PREFIX);
}

}

Controller请求处理器

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package org.simplespring.mvc.processor.impl;

import lombok.extern.slf4j.Slf4j;
import org.simplespring.core.BeanContainer;
import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.annotation.RequestMapping;
import org.simplespring.mvc.annotation.RequestParam;
import org.simplespring.mvc.annotation.ResponseBody;
import org.simplespring.mvc.processor.RequestProcessor;
import org.simplespring.mvc.render.JsonResultRender;
import org.simplespring.mvc.render.ResourceNotFoundResultRender;
import org.simplespring.mvc.render.ResultRender;
import org.simplespring.mvc.render.ViewResultRender;
import org.simplespring.mvc.type.ControllerMethod;
import org.simplespring.mvc.type.RequestPathInfo;
import org.simplespring.util.ConverterUtil;
import org.simplespring.util.ValidationUtil;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
* Controller请求处理器
*/
@Slf4j
public class ControllerRequestProcessor implements RequestProcessor {
//IOC容器
private BeanContainer beanContainer;
//请求和controller方法的映射集合
private Map<RequestPathInfo, ControllerMethod> pathControllerMethodMap = new ConcurrentHashMap<>();

/**
* 依靠容器的能力,建立起请求路径、请求方法与Controller方法实例的映射
*/
public ControllerRequestProcessor() {
this.beanContainer = BeanContainer.getInstance();
Set<Class<?>> requestMappingSet = beanContainer.getClassesByAnnotation(RequestMapping.class);
initPathControllerMethodMap(requestMappingSet);
}

private void initPathControllerMethodMap(Set<Class<?>> requestMappingSet) {
if (ValidationUtil.isEmpty(requestMappingSet)) {
return;
}
//1.遍历所有被@RequestMapping标记的类,获取类上面该注解的属性值作为一级路径
for (Class<?> requestMappingClass : requestMappingSet) {
RequestMapping requestMapping = requestMappingClass.getAnnotation(RequestMapping.class);
String basePath = requestMapping.value();
if (!basePath.startsWith("/")) {
basePath = "/" + basePath;
}
//2.遍历类里所有被@RequestMapping标记的方法,获取方法上面该注解的属性值,作为二级路径
Method[] methods = requestMappingClass.getDeclaredMethods();
if (ValidationUtil.isEmpty(methods)) {
continue;
}
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping methodRequest = method.getAnnotation(RequestMapping.class);
String methodPath = methodRequest.value();
if (!methodPath.startsWith("/")) {
methodPath = "/" + basePath;
}
String url = basePath + methodPath;
//3.解析方法里被@RequestParam标记的参数,
// 获取该注解的属性值,作为参数名,
// 获取被标记的参数的数据类型,建立参数名和参数类型的映射
Map<String, Class<?>> methodParams = new HashMap<>();
Parameter[] parameters = method.getParameters();
if (!ValidationUtil.isEmpty(parameters)) {
for (Parameter parameter : parameters) {
RequestParam param = parameter.getAnnotation(RequestParam.class);
//目前暂定为Controller方法里面所有的参数都需要@RequestParam注解
if (param == null) {
throw new RuntimeException("The parameter must have @RequestParam");
}
methodParams.put(param.value(), parameter.getType());
}
}
//4.将获取到的信息封装成RequestPathInfo实例和ControllerMethod实例,放置到映射表里
String httpMethod = String.valueOf(methodRequest.method());
RequestPathInfo requestPathInfo = new RequestPathInfo(httpMethod, url);
if (this.pathControllerMethodMap.containsKey(requestPathInfo)) {
log.warn("duplicate url:{} registration,current class {} method{} will override the former one",
requestPathInfo.getHttpPath(), requestMappingClass.getName(), method.getName());
}
ControllerMethod controllerMethod = new ControllerMethod(requestMappingClass, method, methodParams);
this.pathControllerMethodMap.put(requestPathInfo, controllerMethod);
}
}
}

}

@Override
public boolean process(RequestProcessorChain requestProcessorChain) throws Exception {
//1.解析HttpSevletRequest的请求方法,请求路径,获取对应的ControllerMethod实例
String method = requestProcessorChain.getRequestMethod();
String path = requestProcessorChain.getRequestPath();
ControllerMethod controllerMethod = this.pathControllerMethodMap.get(new RequestPathInfo(method, path));
if (controllerMethod == null) {
requestProcessorChain.setResultRender(new ResourceNotFoundResultRender(method, path));
return false;
}
//2.解析请求参数,并传递给获取到的ControllerMethod实例去执行
Object result = invokeControllerMethod(controllerMethod, requestProcessorChain.getRequest());
//3.根据处理的结果,选择对应的render进行渲染
setResultRender(result, controllerMethod, requestProcessorChain);
return true;
}

/**
* 根据不同情况设置不同的渲染器
*/
private void setResultRender(Object result, ControllerMethod controllerMethod, RequestProcessorChain requestProcessorChain) {
if (result == null) {
return;
}
ResultRender resultRender;
boolean isJson = controllerMethod.getInvokeMethod().isAnnotationPresent(ResponseBody.class);
if (isJson) {
resultRender = new JsonResultRender(result);
} else {
resultRender = new ViewResultRender(result);
}
requestProcessorChain.setResultRender(resultRender);
}

private Object invokeControllerMethod(ControllerMethod controllerMethod, HttpServletRequest request) {
//1.从请求里获取GET或者POST的参数名及其对应的值
Map<String, String> requestParamMap = new HashMap<>();
//GET,POST方法的请求参数获取方式
Map<String, String[]> parameterMap = request.getParameterMap();
for (Map.Entry<String, String[]> parameter : parameterMap.entrySet()
) {
if (!ValidationUtil.isEmpty(parameter.getValue())) {
//只支持一个参数对应一个值的形式
requestParamMap.put(parameter.getKey(), parameter.getValue()[0]);
}
}
//2.根据获取到的请求参数名及其对应的值,以及controllerMethod里面的参数和类型的映射关系,去实例化出方法对应的参数
List<Object> methodParams = new ArrayList<>();
Map<String, Class<?>> methodParamMap = controllerMethod.getMethodParameters();
for (String paramName : methodParamMap.keySet()) {
Class<?> type = methodParamMap.get(paramName);
String requestValue = requestParamMap.get(paramName);
Object value;
//只支持String 以及基础类型char,int,short,byte,double,long,float,boolean,及它们的包装类型
if (requestValue == null) {
//将请求里的参数值转成适配于参数类型的空值
value = ConverterUtil.primitiveNull(type);
} else {
value = ConverterUtil.convert(type, requestValue);
}
methodParams.add(value);
}
//3.执行Controller里面对应的方法并返回结果
Object controller = beanContainer.getBean(controllerMethod.getControllerClass());
Method invokeMethod = controllerMethod.getInvokeMethod();
invokeMethod.setAccessible(true);
Object result;
try {
if (methodParams.size() == 0) {
result = invokeMethod.invoke(controller);
} else {
result = invokeMethod.invoke(controller, methodParams.toArray());
}
} catch (InvocationTargetException e) {
//如果是调用异常的话,需要通过e.getTargetException()
// 去获取执行方法抛出的异常
throw new RuntimeException(e.getTargetException());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return result;
}
}

定义Render矩阵

定义渲染动作规范

1
2
3
4
5
6
7
/**
* 渲染请求结果
*/
public interface ResultRender {
//执行渲染
void render(RequestProcessorChain requestProcessorChain) throws Exception;
}

默认渲染器

1
2
3
4
5
6
7
8
9
/**
* 默认渲染器
*/
public class DefaultResultRender implements ResultRender {
@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
requestProcessorChain.getResponse().setStatus(requestProcessorChain.getResponseCode());
}
}

内部异常渲染器

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 内部异常渲染器
*/
public class InternalErrorResultRender implements ResultRender{
private String errorMsg;
public InternalErrorResultRender(String errorMsg){
this.errorMsg = errorMsg;
}
@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
requestProcessorChain.getResponse().sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg);
}
}

Json渲染器

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
package org.simplespring.mvc.render;

import com.google.gson.Gson;
import org.simplespring.mvc.RequestProcessorChain;

import java.io.PrintWriter;

/**
* Json渲染器
*/
public class JsonResultRender implements ResultRender {
private Object jsonData;
public JsonResultRender(Object jsonData) {
this.jsonData = jsonData;
}

@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
// 设置响应头
requestProcessorChain.getResponse().setContentType("application/json");
requestProcessorChain.getResponse().setCharacterEncoding("UTF-8");
// 响应流写入经过gson格式化之后的处理结果
try(PrintWriter writer = requestProcessorChain.getResponse().getWriter()){
Gson gson = new Gson();
writer.write(gson.toJson(jsonData));
writer.flush();
}
}
}

资源找不到时使用的渲染器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package org.simplespring.mvc.render;


import org.simplespring.mvc.RequestProcessorChain;

import javax.servlet.http.HttpServletResponse;

/**
* 资源找不到时使用的渲染器
*/
public class ResourceNotFoundResultRender implements ResultRender {
private String httpMethod;
private String httpPath;
public ResourceNotFoundResultRender(String method, String path) {
this.httpMethod = method;
this.httpPath = path;
}

@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
requestProcessorChain.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND,
"获取不到对应的请求资源:请求路径[" + httpPath + "]" + "请求方法[" + httpMethod + "]");
}
}

页面渲染器

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
44
45
46
47
48
49
50
package org.simplespring.mvc.render;

import org.simplespring.mvc.RequestProcessorChain;
import org.simplespring.mvc.type.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
* 页面渲染器
*/
public class ViewResultRender implements ResultRender{
public static final String VIEW_PATH = "/templates/";
private ModelAndView modelAndView;
/**
* 对传入的参数进行处理,并赋值给ModelAndView成员变量
* @param mv
*/
public ViewResultRender(Object mv) {
if(mv instanceof ModelAndView){
//1.如果入参类型是ModelAndView,则直接赋值给成员变量
this.modelAndView = (ModelAndView)mv;
} else if(mv instanceof String){
//2.如果入参类型是String,则为视图,需要包装后才赋值给成员变量
this.modelAndView = new ModelAndView().setView((String)mv);
} else {
//3.针对其他情况,则直接抛出异常
throw new RuntimeException("illegal request result type");
}
}
/**
* 将请求处理结果按照视图路径转发至对应视图进行展示
* @param requestProcessorChain
* @throws Exception
*/
@Override
public void render(RequestProcessorChain requestProcessorChain) throws Exception {
HttpServletRequest request = requestProcessorChain.getRequest();
HttpServletResponse response = requestProcessorChain.getResponse();
String path = modelAndView.getView();
Map<String, Object> model = modelAndView.getModel();
for(Map.Entry<String, Object> entry : model.entrySet()){
request.setAttribute(entry.getKey(), entry.getValue());
}
//JSP
request.getRequestDispatcher(VIEW_PATH +path).forward(request, response);

}
}

其他数据封装包装类和工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 待执行的Controller及其方法实例和参数的映射
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ControllerMethod {
//Controller对应的Class对象
private Class<?> controllerClass;
//执行的Controller方法实例
private Method invokeMethod;
//方法参数名称以及对应的参数类型
private Map<String, Class<?>> methodParameters;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 存储处理完后的结果数据,以及显示该数据的视图
*/
public class ModelAndView {
//页面所在的路径
@Getter
private String view;
//页面的data数据
@Getter
private Map<String, Object> model = new HashMap<>();

public ModelAndView setView(String view){
this.view = view;
return this;
}
//modelAndView.setView("addheadline.jsp").addViewData("aaa", "bbb");
public ModelAndView addViewData(String attributeName, Object attributeValue){
model.put(attributeName, attributeValue);
return this;
}
}
1
2
3
4
5
6
7
/**
* 目前支持的请求方法
*/
public enum RequestMethod {
GET,
POST
}
1
2
3
4
5
6
7
8
9
10
11
12
/**
* 存储http请求路径和请求方法
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RequestPathInfo {
//http请求方法
private String httpMethod;
//http请求路径
private String httpPath;
}
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package org.simplespring.util;

public class ConverterUtil {
/**
* 返回基本数据类型的空值
*需要特殊处理的基本类型即int\double\short\long\byte\float\boolean
* @param type 参数类型
* @return 对应的空值
*/
public static Object primitiveNull(Class<?> type) {
if (type == int.class || type == double.class ||
type == short.class || type == long.class ||
type == byte.class || type == float.class) {
return 0;
} else if(type == boolean.class){
return false;
}
return null;
}
/**
* String类型转换成对应的参数类型
*
* @param type 参数类型
* @param requestValue 值
* @return 转换后的Object
*/
public static Object convert(Class<?> type, String requestValue) {
if(isPrimitive(type)){
if(ValidationUtil.isEmpty(requestValue)){
return primitiveNull(type);
}
if (type.equals(int.class) || type.equals(Integer.class)) {
return Integer.parseInt(requestValue);
} else if (type.equals(String.class)) {
return requestValue;
} else if (type.equals(Double.class) || type.equals(double.class)) {
return Double.parseDouble(requestValue);
} else if (type.equals(Float.class) || type.equals(float.class)) {
return Float.parseFloat(requestValue);
} else if (type.equals(Long.class) || type.equals(long.class)) {
return Long.parseLong(requestValue);
} else if (type.equals(Boolean.class) || type.equals(boolean.class)) {
return Boolean.parseBoolean(requestValue);
} else if (type.equals(Short.class) || type.equals(short.class)) {
return Short.parseShort(requestValue);
} else if (type.equals(Byte.class) || type.equals(byte.class)) {
return Byte.parseByte(requestValue);
}
return requestValue;
} else {
throw new RuntimeException("count not support non primitive type conversion yet");
}
}
/**
* 判定是否基本数据类型(包括包装类以及String)
*
* @param type 参数类型
* @return 是否为基本数据类型
*/
private static boolean isPrimitive(Class<?> type) {
return type == boolean.class
|| type == Boolean.class
|| type == double.class
|| type == Double.class
|| type == float.class
|| type == Float.class
|| type == short.class
|| type == Short.class
|| type == int.class
|| type == Integer.class
|| type == long.class
|| type == Long.class
|| type == String.class
|| type == byte.class
|| type == Byte.class
|| type == char.class
|| type == Character.class;
}
}

总结一下大致流程

  1. 定义配置标记

    • @RequestMapping:标识Controller的方法与请求路径和请求方法的映射关系
    • @RequestParam:请求的方法参数名称
    • @ResponseBody:用于标记自动对返回值进行json处理
  2. 转发控制器

    核心流程:

    • 初始化
      1. 初始化容器
      2. doAop
      3. doIoc
      4. 初始化请求处理器责任链
    • 处理请求
      1. 创建责任链对象实例
      2. 通过责任链模式来依次调用请求处理器对请求进行处理
      3. 对处理结果进行渲染
  3. 请求处理责任链

    • 以责任链的模式执行注册的请求处理器
    • 委派给特定的Render实例对处理后的结果进行渲染
  4. 定义RequestProcessor矩阵

    请求预处理器/静态资源请求处理器/jsp资源请求处理器/Controller请求处理器

  5. 定义Render矩阵

    默认渲染器/内部异常渲染器/Json渲染器/资源找不到时使用的渲染器/页面渲染器/

  6. 其他数据封装包装类和工具类