上面的是 springMVC 的工作原理图:
1,客户端发出一个 http 请求给 web 服务器,web 服务器对 http 请求进行解析,如果匹配 DispatcherServlet 的请求映射路径(在 web.xml 中指定),web 容器将请求转交给 DispatcherServlet.
2,DipatcherServlet 接收到这个请求之后将根据请求的信息(包括 URL,Http 方法,请求报文头和请求参数 Cookie 等)以及 HandlerMapping 的配置找到处理请求的处理器(Handler).
3-4,DispatcherServlet 根据 HandlerMapping 找到对应的 Handler, 将处理权交给 Handler(Handler 将具体的处理进行封装),再由具体的 HandlerAdapter 对 Handler 进行具体的调用.
5,Handler 对数据处理完成以后将返回一个 ModelAndView() 对象给 DispatcherServlet.
6,Handler 返回的 ModelAndView() 只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet 通过 ViewResolver 将逻辑视图转化为真正的视图 View.
7,Dispatcher 通过 model 解析出 ModelAndView() 中的参数进行解析最终展现出完整的 view 并返回给客户端.
工作机制是什么
Control 的调用(续)
接着对于(二)的补充:主要是小结下 Control 的处理逻辑的关键操作;
对于 control 的处理关键就是:DispatcherServlet 的 handlerMappings 集合中根据请求的 URL 匹配每一个 handlerMapping 对象中的某个 handler, 匹配成功之后将会返回这个 handler 的处理连接 handlerExecutionChain 对象.而这个 handlerExecutionChain 对象中将会包含用户自定义的多个 handlerInterceptor 对象.
"Testing
/**
*
Return the HandlerExecutionChain for this request.
*
Tries all handler mappings in order.
*
@param request current HTTP request
*
@return the HandlerExecutionChain, or null if no handler could be found
*/
protected
HandlerExecutionChain
getHandler(HttpServletRequest request)
throws
Exception
{
for
(HandlerMapping
hm :
this
.handlerMappings)
{
if
(logger.isTraceEnabled())
{
logger.trace(
handler map ["
+
hm +
"]in DispatcherServlet with name '"
而对于 handlerInterceptor 接口中定义的三个方法中,preHandler 和 postHandler 分别在 handler 的执行前和执行后执行,afterCompletion 在 view 渲染完成,在 DispatcherServlet 返回之前执行.
+
getServletName() +
"'"
);
}
HandlerExecutionChain
handler = hm.getHandler(request);
if
(handler
!=
null
)
{
return
handler;
}
}
return
null
;
}
PS: 这么我们需要注意的是:当 preHandler 返回 false 时,当前的请求将在执行完 afterCompletion 后直接返回, handler 也将不会执行.
在类 HandlerExecutionChain 中的 getHandler() 方法是返回 object 对象的;
这里的 handler 是没有类型的,handler 的类型是由 handlerAdapter 决定的.dispatcherServlet 会根据 handler 对象在其 handlerAdapters 集合中匹配哪个 HandlerAdapter 实例支持该对象.接下来去执行 handler 对象的相应方法了,如果该 handler 对象的相应方法返回一个 ModelAndView 对象接下来就是去执行 View 渲染了.
/**
*
Return the handler object to execute.
*
@return the handler object
*/
public
Object
getHandler() {
return
this
.handler;
}
--------------------------------------- 邪恶的分割线 ---------------------------------------------
/**
*
Return the handler object to execute.
*
@return the handler object
*/
public
Object
getHandler() {
return
this
.handler;
}
Model 设计
如果 handler 兑现返回了 ModelAndView 对象,那么说明 Handler 需要传一个 Model 实例给 view 去渲染模版.除了渲染页面需要 model 实例,在业务逻辑层通常也有 Model 实例.
ModelAndView 对象是连接业务逻辑层与 view 展示层的桥梁,对 spring MVC 来说它也是连接 Handler 与 view 的桥梁.ModelAndView 对象顾名思义会持有一个 ModelMap 对象和一个 View 对象或者 View 的名称.ModelMap 对象就是执行模版渲染时候所需要的变量对应的实例,如 jsp 的通过 request.getAttribute(String) 获取的 JSTL 标签名对应的对象.velocity 中 context.get(String) 获取 $foo 对应的变量实例.
对于 ViewResolver,前面有写到了,就不写了;
public
class
ModelAndView
{
/**
View instance or view name String */
private
Object
view;
/**
Model Map */
private
ModelMap
model;
/**
Indicates whether or not this instance has been cleared with a call to {@link #clear()} */
private
boolean
cleared
=
false
;
.....
}
ModelMap 其实也是一个 Map,Handler 中将模版中需要的对象存在这个 Map 中,然后传递到 view 对应的 ViewResolver 中.
public
interface
ViewResolver
{
View
resolveViewName(String viewName, Locale locale)
throws
Exception;
}
不同的 ViewResolver 会对这个 Map 中的对象有不同的处理方式;
velocity 中将这个 Map 保存到 VelocityContext 中.
JSP 中将每一个 ModelMap 中的元素分别设置到 request.setAttribute(modelName,modelValue);
----------------------- 邪恶的分割线 -----------------------------------------------
view 设计
在 spring MVC 中,view 模块需要两个组件来支持:RequestToViewNameTranslator 和 ViewResolver
public
interface
RequestToViewNameTranslator
{
/**
*
Translate the given {@link HttpServletRequest} into a view name.
*
@param request the incoming {@link HttpServletRequest} providing
*
the context from which a view name is to be resolved
*
@return the view name (or null if no default found)
*
@throws Exception if view name translation fails
*/
String
getViewName(HttpServletRequest request)
throws
Exception;
}
----------------------- 邪恶的分割线 -------------------------------------------------
RequestToViewNameTranslator:主要支持用户自定义对 viewName 的解析,如将请求的 ViewName 加上前缀或者后缀,或者替换成特定的字符串等.
ViewResolver:主要是根据用户请求的 viewName 创建适合的模版引擎来渲染最终的页面,ViewResolver 会根据 viewName 创建一个 view 对象,调用 view 对象的 Void render 方法渲染出页面;
下面来总结下 Spring MVC 解析 View 的逻辑:
public
interface
View
{
void
render(Map model, HttpServletRequest request, HttpServletResponse response)
throws
Exception;
}
dispatcherServlet 方法调用 getDefaultViewName()方法;
调用了 RequestToViewNameTranslator 的 getViewName 方法;
/**
*
Translate the supplied request into a default view name.
*
@param request current HTTP servlet request
*
@return the view name (or null if no default found)
*
@throws Exception if view name translation failed
*/
protected
String
getDefaultViewName(HttpServletRequest request)
throws
Exception
{
return
this
.viewNameTranslator.getViewName(request);
}
调用 LocaleResolver 接口的 resolveLocale 方法;
public
interface
RequestToViewNameTranslator
{
/**
*
Translate the given {@link HttpServletRequest} into a view name.
*
@param request the incoming {@link HttpServletRequest} providing
*
the context from which a view name is to be resolved
*
@return the view name (or null if no default found)
*
@throws Exception if view name translation fails
*/
String
getViewName(HttpServletRequest request)
throws
Exception;
}
调用 ViewResolver 接口的 resolveViewName 方法,返回 view 对象
Locale
resolveLocale(HttpServletRequest request);
调用 render 方法渲染出页面
View
resolveViewName(String viewName, Locale locale)
throws
Exception;
转载自:https://www.cnblogs.com/zbf1214/p/5265117.html
来源: http://blog.csdn.net/ahou2468/article/details/79059115