SpringMVC源码分析

SpringMVC 执行流程源码分析


用户发出请求到前端控制器 DispatcherServlet,DispatcherServlet收到请求后,调用 HandlerMapping(处理器映射器),HandlerMapping 找到具体的处理器(通过 XML 或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给 DispatcherServlet,然后 DispatcherServlet 调用 HandlerAdpter(处理器适配器),HandlerAdpter 经过适配调用具体的 Controller/Handler 的某个方法,Controller 执行完成返回 ModelAndView 对象。HandlerAdapter 将 Controller 返回的 ModelAndView 返回给 DispatcherServlet,然后再传递给 ViewReslover(视图解析器),最后解析后返回具体 View。DispatcherServlet 根据 View 进行渲染视图(将模型数据填充至视图中),响应用户。

之所以把单个映射器、适配器、视图解析器都分离开,是为了解耦。

源码分析 DispatcherServlet


DispatcherServlet 会拦截所有的前端请求,然后进行分发,继承了 HttpServlet。其父类 FrameworkServlet 重写了 service 方法。

RequestContextHolder

当一个请求被拦截后,进入了 service 方法中,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 做分发,一般请求是 GET POST
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
processRequest(request, response);
}
else {
// 进入 HttpServlet.service 方法调用 doGet、doPost
super.service(request, response);
}
}

@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 进入到该方法去一探究竟
processRequest(request, response);
}

发现,FrameworkServlet 覆盖了 doGet、doPOST 方法,所以是调用子类的 doGet、doPOST 方法。
一般来说,框架设计中 使用 do 开头的方法是回调方法,或者是勾子方法,指的是触发某个事件时,会调用该方法

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
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取上一个请求保存的 LocaleContext
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
// 建立新的 LocaleContext
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
// 获取上一个请求保存的 RequestAttributes
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
// 建立新的RequestAttributes
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
// 把新的 RequestAttributes 设置进 LocalThread,实际上保存类型为
// ServletRequestAttributes LocalThread 为 Key 表示当前线程
initContextHolders(request, localeContext, requestAttributes);

// 其他都不重要
try {
// processRequest 方法又调用了 doService 方法,可以想到 doGet 也会调用该方法
doService(request, response);
}
// 处理异常
finally {
// 恢复
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}

processRequest(request, response) 的具体实现可以分为以下几步:

  1. 获取上一个请求的参数
  2. 重新建立新的参数
  3. 设置新的参数到 XXContextHolder, Key 为当前的线程 值为请求对象
  4. 处理新的请求,如果出现异常,恢复 request
  5. 发布请求处理事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void initContextHolders(HttpServletRequest request, 
LocaleContext localeContext,
RequestAttributes requestAttributes) {
if (localeContext != null) {
LocaleContextHolder.setLocaleContext(localeContext,
this.threadContextInheritable);
}
if (requestAttributes != null) {
RequestContextHolder.setRequestAttributes(requestAttributes,
this.threadContextInheritable);
}
if (logger.isTraceEnabled()) {
logger.trace("Bound request context to thread: " + request);
}
}

doService 中又调用了关键方法 doDispatch,看来分发步骤应该是在 doDispatch 方法中执行的。点进去看看:看注释分析

doDispatch

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
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
// 声明处理链对象(HandlerControllers)
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {
// 声明 ModelAndView 对象
ModelAndView mv = null;
Exception dispatchException = null;

try {
// 判断请求是否是上传或者下载 Multipart,这里肯定是 false
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

// [1] 经过下面分析得出,该方法返回的对象掌握了整个处理链的处理请求的顺序
// HandlerExecutionChain 包含2个 interceptor 和一个 handler 成员变量
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// [2] 得到一个 HandlerAdapter,看适配器中 该请求是匹配哪个适配器去适配。
// 实际上就是看 handler 实现了哪个适配器需要的接口
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 如果前置拦截器返回 false,就中断请求。
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 调用 adaptor 的 handle 方法,如果你使用的是 Controller 方法,则就是调用
// Controller 中对应的 处理方法。获得一个 ModelAndView。 此时还未渲染视图
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 是否申请默认的 viewName,如果 viewName 为空执行。
applyDefaultViewName(processedRequest, mv);
// 后置拦截器,视图渲染前,执行拦截方法。
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// [3] 处理分发结果。
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}

[1]getHandler(processedRequest)

mappedHandler = getHandler(processedRequest); 方法中做的事情

1
2
3
4
5
6
7
8
9
10
11
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}

我们自己配的 BeanNameUrlHandlerMapping,按照 bean name 和 url 来映射 Handler。现在进入 getHandler(request) 看看做了什么,返回了一个 处理链。

getHandler(request)

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
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 根据 request 返回 handler 对象
// 这个 handler 对象就是 Controller 中的对应的方法、路径、参数等等等等描述了。
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}

if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
// 获取处理链,这里是核心代码(本质是一个 handler,两个 interceptors 拦截器集合)
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}

if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}

return executionChain;
}

可以看到 handler 对象包含以下属性。

根据后续代码的分析,发现 getHandler 方法最终返回的 HandlerExecutionChain 对象,本质上就是两个拦截器链和一个 handler。

HandlerExecutionChain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class HandlerExecutionChain {

private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);

private final Object handler;

@Nullable
private HandlerInterceptor[] interceptors;

@Nullable
private List<HandlerInterceptor> interceptorList;

...
}
  • 类中包含 handler 用于描述 映射方法的详细信息。
  • HandlerInterceptor[] 数组,拦截器链条,执行 handler 前,会按照该链条执行所有拦截器的 preHandle() 方法
  • List 链表,拦截器链条,执行 handler 前,会按照该链条执行所有拦截器的 preHandle() 方法

[2] getHandlerAdapter(Object handler)

1
2
3
4
5
6
7
8
9
10
11
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

遍历适配器,看适配器中是否有可以支持 handler 的执行。supports(handler) 方法实际上就是,看 handler 是否实现了 this.handlerAdapters 中对应的 Adapter 需要实现的接口。例如:SimpleControllerHandlerAdapter 需要 handler 实现 Controller 接口。

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

返回的 ModelAndView,view 表示路径,这里只是逻辑路径,后续方法中会为其加入前缀和后缀,编程物理路径,model 中存放所有的共享数据

[3]processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

处理分发的结果。

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
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {

boolean errorView = false;

if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}

if (mv != null && !mv.wasCleared()) {
// 渲染,render,根据 request、response 渲染视图
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No view rendering, null ModelAndView returned.");
}
}

if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}

if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}

继续往下走

render(mv, request, response);

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
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 本地化
Locale locale =
(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
response.setLocale(locale);

View view; // 视图 View
String viewName = mv.getViewName();
if (viewName != null) {
// 根据 ViewName 生成一个 View 对象
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
else {
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}

if (logger.isTraceEnabled()) {
logger.trace("Rendering view [" + view + "] ");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
// 渲染 View
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "]", ex);
}
throw ex;
}
}

view.render(mv.getModelInternal(), request, response);

1
2
3
4
5
6
7
8
9
10
11
12
13
public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {

if (logger.isDebugEnabled()) {
logger.debug("View " + formatViewName() +
", model " + (model != null ? model : Collections.emptyMap()) +
(this.staticAttributes.isEmpty() ? "" : ", static attributes " + this.staticAttributes));
}
// 处理数据,将我们设置的数据添加到视图中去
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
prepareResponse(request, response);
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}

renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);

Output,可以看出,这一步就是将数据和视图输出了。

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
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

exposeModelAsRequestAttributes(model, request);

exposeHelpers(request);

String dispatcherPath = prepareForRendering(request, response);
// RequestDispatcher 对象
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
if (rd == null) {
throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
"]: Check that the corresponding file exists within your web application archive!");
}

if (useInclude(request, response)) {
response.setContentType(getContentType());
if (logger.isDebugEnabled()) {
logger.debug("Including [" + getUrl() + "]");
}
rd.include(request, response);
}

else {
if (logger.isDebugEnabled()) {
logger.debug("Forwarding to [" + getUrl() + "]");
}
// 转发,实际上就是 DispatcherServlet.forward。
rd.forward(request, response);
}
}

至此,就完成了整个请求在 SpringMVC 中执行的整个过程。

手写 springMVC 框架


只编写一个 Servlet 去进行请求分发,后台只需要编写普通的处理器去处理不同的请求。

  1. 接收客户端发送过来的请求
  2. 根据请求URL查找对应的请求处理类
  3. 调用请求处理类的方法处理请求
  4. 处理响应结果
1
2
3
4
5
6
7
8
public class DispatcherServlet {
public void doDispatch() {
// 请求分发(分发给普通的 javabean)
if ("/user".equals(url)) {
// 将请求交给 UserHandler 类去处理该请求()
}
}
}

url-parttern 的配置方式:完整路径/xxx//**.后缀
/ 可以撇配除JSP之外的所有请求,在tomcat中web.xml文件规定 / 会交给 DefaultServlet 处理,还会匹配*.jsp交给 JspServlet 处理。

主流程

  • 浏览器输入 /query URI 时,http://localhost/query?id=1&username=ammar
  • 程序会进入我们在 web.xml 中配置的 servlet

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>cn.lizhaoloveit.springmvc.servlet.DispatchServlet</servlet-class>
<!-- 在DispatcherServlet类初始化的时候,可以获取以下参数 -->
<init-param>
<!-- 指定spring配置文件的路径 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

DispatcherServlet

  • 此时,使用了抽象模板的设计模式来构建 DispatcherServlet,创建抽象类 AbstractHttpServlet 继承 HttpServlet
1
2
3
4
5
6
7
8
9
10
11
public abstract class AbstractHttpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doDispatch(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
public abstract void doDispatch(HttpServletRequest request, HttpServletResponse response);
}

使用钩子方法 doDispatch 处理所有的请求。

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
public class DispatchServlet extends AbstractHttpServlet {

private List<HandlerMapping> handlerMappings = new ArrayList<>();
private List<HandlerAdapter> handlerAdapters = new ArrayList<>();

@Override
public void init(ServletConfig config) {
String contextConfigLocation = config.getInitParameter("contextConfigLocation");
BeanFactory beanFactory = new DefaultListableBeanFactory(contextConfigLocation);
beanFactory.getBeanNamesByType(Object.class); // 初始化所有的bean
handlerMappings = beanFactory.getBeansByType(HandlerMapping.class);
handlerAdapters = beanFactory.getBeansByType(HandlerAdapter.class);
}

@Override
public void doDispatch(HttpServletRequest request, HttpServletResponse response) {
// 1. 根据请求获取对应的处理器
Object handler = null;
for (HandlerMapping handlerMapping : handlerMappings) {
Object handlerTemp = handlerMapping.getHandler(request);
if (handlerTemp != null) handler = handlerTemp;
}
// 2. 找到匹配的适配器
HandlerAdapter ha = null;
for (HandlerAdapter handlerAdapter : handlerAdapters) {
if (handlerAdapter.support(handler)) {
ha = handlerAdapter;
}
}

try {
ha.handleRequest(handler, request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
  • 此时,由于处理请求的处理器多种多样,无法用一个接口来概括所有的处理方式,所以采用了策略设计模式,用我们预先写好的 request 和 handler 的映射器 HandlerRequestMapping 去匹配请求,如果可以找到映射。就可以找到处理器。

HandlerMapping

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
public class RequestMappingHandlerMapping implements HandlerMapping, BeanFactoryAware {

// 建立URL 和 Controller 下的 Method 的映射关系
private Map<String, HandlerMethod> urlHandlerMethodMap = new HashMap<>();
private BeanFactory beanFactory;

// 通过 beanFactoryAware 在初始化的时候注入 工厂
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

public void initMethod() {
// 获取 spring 中所有的 bean
List<String> beanNames = beanFactory.getBeanNamesByType(Object.class);
for (String beanName : beanNames) {
Map<String, BeanDefinition> beanDefinitions = beanFactory.getBeanDefiitions();
BeanDefinition beanDefinition = beanDefinitions.get(beanName);
String beanClassName = beanDefinition.getBeanClassName();
try {
Class<?> clazz = Class.forName(beanClassName);
// 判断 clazz 是否带有 Controller 注解
if (clazz.isAnnotationPresent(Controller.class)) {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String url = requestMapping.value();
HandlerMethod handlerMethod = new HandlerMethod(method, beanFactory.getBean(beanName));
urlHandlerMethodMap.put(url, handlerMethod);
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

}
}
@Override
public Object getHandler(HttpServletRequest request) {
String uri = request.getRequestURI();
return urlHandlerMethodMap.get(uri);
}
}

HandlerMapping 类在初始化时就已经将项目中所有的映射关系保存在 Map 中了,在拿到请求后,只需要判断 Map 中是否有 url key。

HandlerAdapter

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
public class RequestMappingHandlerAdapter implements HandlerAdapter {
@Override
public boolean support(Object handler) {
return handler instanceof HandlerMethod;
}

@Override
public void handleRequest(Object handler, HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Object object = handlerMethod.getHandler();
// 获取方法参数
Map<String, String[]> paramMap = request.getParameterMap();
List<Object> args = new ArrayList<>();
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
// 获取的参数名称如果不做特殊处理,获取的是 arg0 arg1
String name = parameter.getName();
Class<?> type = parameter.getType();
String[] value = paramMap.get(name);
if (value == null) {
args.add(null);
continue;
}
if (type == Integer.class) {
args.add(Integer.valueOf(value[0]));
} else if (type == String.class) {
args.add(value[0]);
}
}
Object[] argsObj = args.toArray();

// 执行处理方法
Object returnValue = method.invoke(object, argsObj);

// 处理返回值
if (method.isAnnotationPresent(ResponseBody.class)) {
if (returnValue instanceof String) {
response.setContentType("text/plain;charset=utf8");
response.getWriter().write(returnValue.toString());
} else if (returnValue instanceof Map) {
response.setContentType("application/json;charset=utf8");
String s = JsonUtils.object2Json(returnValue);
response.getWriter().write(s);
}
} else {
// 展示视图
}
}
}

Adapter 是 springmvc 框架中处理器输入输出的中转站。将数据按规则过滤和处理。

最终的效果:

url: http://localhost/query?id=3&username=ammar
浏览器返回

1
2
3
4
{
"id": 3,
"username": "ammar"
}

代码地址:手写springmvc框架

文章作者: Ammar
文章链接: http://lizhaoloveit.cn/2020/06/12/SpringMVC%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ammar's Blog
打赏
  • 微信
  • 支付宝

评论