执行流程:

DispatcherServlet(前端控制器):接收响应请求,调配其他组件。
handlermapping(处理器映射器):根据url查找可以处理当前请求的处理器。(可以通过xml配置方式,注解方式)。
HandlerAdaptor(处理器适配器):接收转换前端页面参数,根据特定规则执行处理器,
Handler(处理器,后端控制器):需要程序员去编写,常用注解开发方式。
Handler处理器执行后结果是ModelAndView,具体开发时Handler返回方法值类型包括: ModelAndView、String (逻辑视图名)、void (通过在Handler形参中添加request和response,类似原始servlet 开发方式,注意:可以通过指定response响应的结果类型实现json数据输出)。
View resolver(视图解析器):跳转到指定的页面,并将后台的值解析到jsp视图页面。
View视图:jsp页面,仅是数据展示,没有业务逻辑。
在web.xml配置前端控制器
1 | <!-- 前端控制器 --> |
在springMVC.xml文件配置
1 | <!-- 配置Handler处理器 ·--> |
处理器映射器
映射器1在springmvc.xml文件中的配置
1 | <!-- 配置Handler处理器 ·--> |
映射器2在springmvc.xml文件中的配置
1 | <bean id="MyController" class="com.syl.controller.MyController"></bean> |
总结:多个映射器可以并存,前端控制器判断url能让哪些映射器映射,就让正确的映射器处理
处理器适配器
实现controller接口
在springmvc.xml文件中的配置
1 | <!-- 配置Handler处理器 ·--> |
在controller层的代码:
1 | public class MyController implements Controller{ |
实现HttpRequestHandler接口
在springmvc.xml文件中的配置
1 | <!-- 配置Handler处理器 ·--> |
在controller层的代码:
1 | public class MyController2 implements HttpRequestHandler{ |
两种处理器适配器可以并存,各司其职所有处理器适配器都实现HandleAdapter接口
但是,测试发现,如果不配置处理器适配器程序也可以正常运行
原因:
发现一个配置文件:/org/springframework/web/servlet/DispatcherServlet.properties
在里面发现:
1 | org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ |
注解的处理器映射器和适配器
注解的映射器和适配器必须配对使用,要么都使用注解形式,要么都使用xml配置形式
首先在springmvc.xml文件中开启springmvc注解支持以及包扫描
1 | <!--包扫描--> |
然后在controller中的代码
1 | //指定该类为处理器类 |
源码分析
首先前端控制器DispacherServlet调用自身的doDispatch()方法,在doDispatch()方法中执行
前段控制器调用处理器映射器查找Handler
1
mappedHandler = getHandler(processedRequest);
1
2
3
4
5
6
7
8
9
10
11protected 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;
}
可以得到一个处理器执行链
之后执行doDispatch()方法中的下面代码可以得到一个处理器适配器
1
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
1
2
3
4
5
6
7
8
9
10
11protected 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");
}通过得到的处理器适配器得到一个ModelAndView
1
2ModelAndView mv = null;
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());执行以下代码
1
processDispatchResult(processedRequest,response,mappedHandler, mv, dispatchException);
然后执行processDispatchResult()方法中的render方法
1
render(mv, request, response);
通过视图解析器将ModelAndVIew解析成View
1
2String viewName = mv.getViewName();
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);然后通过view的渲染方法
1
view.render(mv.getModelInternal(), request, response);
再然后经过层层跳转来到这里将ModelAndView填充到request作用域
1
2
3
4
5
6
7
8
9
10
11
12protected void exposeModelAsRequestAttributes(Map<String, Object> model,
HttpServletRequest request) throws Exception {
model.forEach((name, value) -> {
if (value != null) {
request.setAttribute(name, value);
}
else {
request.removeAttribute(name);
}
});
}发现其实ModelAndView就是一个map…