<SpringMVC源码分析(1)标签解析>:介绍了解析过程中,初始化若干组件。
<SpringMVC源码分析(2)DispatcherServlet的初始化>:初始化DispatcherServlet的多个组件。
本文继续分析DispatcherServlet解析请求的过程。
概览
①:DispatcherServlet是springmvc中的前端控制器(front controller),负责接收request并将request转发给对应的处理组件.
②:HanlerMapping是springmvc中完成url到controller映射的组件.DispatcherServlet接收request,然后从HandlerMapping查找处理request的controller.
③:Cntroller处理request,并返回ModelAndView对象,Controller是springmvc中负责处理request的组件(类似于struts2中的Action),ModelAndView是封装结果视图的组件.
④ ⑤ ⑥:视图解析器解析ModelAndView对象并返回对应的视图给客户端.
要点
-
维护url和controller的映射
这部分工作由的父类
实现。具体方法为detectHandlers
protected void detectHandlers() throws BeansException {
if (()) {
("Looking for URL mappings in application context: " + getApplicationContext());
}
String[] beanNames = ( ?
(getApplicationContext(), ) :
getApplicationContext().getBeanNamesForType());
// Take any bean name that we can determine URLs for.
for (String beanName : beanNames) {
String[] urls = determineUrlsForHandler(beanName);
if (!(urls)) {
// URL paths found: Let's consider it a handler.
registerHandler(urls, beanName);
}
else {
if (()) {
("Rejected bean name '" + beanName + "': no URL paths identified");
}
}
}
}
2.准确定位处理请求的具体方法(在AnnotationMethodHandlerAdapter中实现)
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
Method handlerMethod = (request);//具体实现方法的匹配
ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ExtendedModelMap implicitModel = new BindingAwareModelMap();
Object result = (handlerMethod, handler, webRequest, implicitModel);
ModelAndView mav =
(handlerMethod, (), result, implicitModel, webRequest);
(handler, (mav != null ? () : null), implicitModel, webRequest);
return mav;
}
1.请求入口
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Delegate POST requests to {@link #processRequest}.
* @see #doService
*/
@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = ();
Throwable failureCause = null;
// Expose current LocaleResolver and request as LocaleContext.
LocaleContext previousLocaleContext = ();
(buildLocaleContext(request), );
// Expose current RequestAttributes to current thread.
RequestAttributes previousRequestAttributes = ();
ServletRequestAttributes requestAttributes = null;
if (previousRequestAttributes == null || ().equals()) {
requestAttributes = new ServletRequestAttributes(request);
(requestAttributes, );
}
if (()) {
("Bound request context to thread: " + request);
}
try {
doService(request, response);
}
catch (ServletException ex) {
failureCause = ex;
throw ex;
}
catch (IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
// Clear request attributes and reset thread-bound context.
(previousLocaleContext, );
if (requestAttributes != null) {
(previousRequestAttributes, );
();
}
if (()) {
("Cleared thread-bound request context: " + request);
}
if (failureCause != null) {
("Could not complete request", failureCause);
}
else {
("Successfully completed request");
}
if () {
// Whether or not we succeeded, publish an event.
long processingTime = () - startTime;
(
new ServletRequestHandledEvent(this,
(), (),
(), getServletConfig().getServletName(),
(request), getUsernameForRequest(request),
processingTime, failureCause));
}
}
}
processRequest方法主要做4项工作。
-
得到当前线程的LocaleContext和RequestAttributes,创建新的LocaleContext和RequestAttributes并重新绑定到当前线程。
-
调用子类实现的doService()
-
重置当前线程的LocaleContext和RequestAttributes
-
执行成功后,发布ServletRequestHandledEvent事件。
自定义的doService方法
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (()) {
String requestUri = (request);
("DispatcherServlet with name '" + getServletName() + "' processing " + () +
" request for [" + requestUri + "]");
}
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map<String, Object> attributesSnapshot = null;
if ((request)) {
("Taking snapshot of request attributes before include");
attributesSnapshot = new HashMap<String, Object>();
Enumeration attrNames = ();
while (()) {
String attrName = (String) ();
if ( || ("")) {
(attrName, (attrName));
}
}
}
// Make framework objects available to handlers and view objects.
(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
(LOCALE_RESOLVER_ATTRIBUTE, );
(THEME_RESOLVER_ATTRIBUTE, );
(THEME_SOURCE_ATTRIBUTE, getThemeSource());
try {
doDispatch(request, response);
}
finally {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
主要做两部分工作
-
如果是include请求,先保存一份request域数据的快照,doDispatch执行过后,将会用快照数据恢复。
-
调用doDispatch方法,完成请求转发。
方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
try {
ModelAndView mv;
boolean errorView = false;
try {
// 1.检查是否是文件上传的请求
processedRequest = checkMultipart(request);
// Determine handler for the current request.
// 2.取得处理当前请求的controller,这里也称为hanlder,处理器,第一个步骤的意义就在这里体现了.
//这里并不是直接返回controller,而是返回的HandlerExecutionChain请求处理器链对象,该对象封装了handler和interceptors.
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || () == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
//3. 获取处理request的处理器适配器handler adapter
HandlerAdapter ha = getHandlerAdapter(());
// Process last-modified header, if supported by the handler.
String method = ();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = (request, ());
if (()) {
String requestUri = (request);
("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// Apply preHandle methods of registered interceptors.
// 4.拦截器的预处理方法
HandlerInterceptor[] interceptors = ();
if (interceptors != null) {
for (int i = 0; i < ; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!(processedRequest, response, ())) {
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
return;
}
interceptorIndex = i;
}
}
// Actually invoke the handler.
// 5.实际的处理器处理请求,返回结果视图对象
mv = (processedRequest, response, ());
// Do we need view name translation?
if (mv != null && !()) {
(getDefaultViewName(request));
}
// Apply postHandle methods of registered interceptors.
// 6.拦截器的后处理方法
if (interceptors != null) {
for (int i = - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
(processedRequest, response, (), mv);
}
}
}
catch (ModelAndViewDefiningException ex) {
("ModelAndViewDefiningException encountered", ex);
mv = ();
}
catch (Exception ex) {
Object handler = (mappedHandler != null ? () : null);
mv = processHandlerException(processedRequest, response, handler, ex);
errorView = (mv != null);
}
// Did the handler return a view to render?
if (mv != null && !()) {
render(mv, processedRequest, response);
if (errorView) {
(request);
}
}
else {
if (()) {
("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
// Trigger after-completion for successful outcome.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
}
catch (Exception ex) {
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
catch (Error err) {
ServletException ex = new NestedServletException("Handler processing failed", err);
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
finally {
// Clean up any resources used by a multipart request.
if (processedRequest != request) {
cleanupMultipart(processedRequest);
}
}
}
很明显这儿是SpringMVC核心。
1.根据请求的路径找到HandlerMethod(带有Method反射属性,也就是对应Controller中的方法)(完成)
2.匹配路径对应的拦截器(完成)
3.获得HandlerExecutionChain对象(完成)
4.通过HandlerAdapter对象进行处理得到ModelAndView对象(HandlerAdapter.handle)
5.调用
6.调用HandlerInterceptor.postHandle
7. 渲染
4.总结
简单粗暴的总结下
step1-6: 获取controller
step5-15 :调用controller方法
step17-20:渲染view
其他:aop方式处理拦截统一处理。