SprngMVC源码学习

SprngMVC源码学习

运行helloWorld示例进入调试界面。

SprngMVC源码学习

DispatcherServlet:前端控制器

DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) line: 945
DispatcherServlet.doService(HttpServletRequest, HttpServletResponse) line: 876
DispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest, HttpServletResponse) line: 931
DispatcherServlet(FrameworkServlet).doGet(HttpServletRequest, HttpServletResponse) line: 822
DispatcherServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 624
DispatcherServlet(FrameworkServlet).service(HttpServletRequest, HttpServletResponse) line: 807
DispatcherServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 731

由上进入源码查看

DispatcherServlet(FrameworkServlet).service(HttpServletRequest, HttpServletResponse) line: 807
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
  ...
service();
}

  

HttpServletBean 的实现
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {}

 SprngMVC源码学习

 接下来重点关注doDispatch()

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try {
ModelAndView mv = null;
Exception dispatchException = null; try {
processedRequest = checkMultipart(request);
multipartRequestParsed = processedRequest != request; // Determine handler for the current request.
//1、根据当前请求地址找到哪个处理器来处理请求
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
//2、如果找不到报错
noHandlerFound(processedRequest, response);
return;
} // Determine handler adapter for the current request.
//2\为当前请求确定适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
} if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
} try {
// Actually invoke the handler.
//真正执行方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
} applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
//处理响应结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
}
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
四步:
1)、所有请求进来都经过DispatcherServlet的900:doDispatch()方法(包含了处理请求以及响应的所有流程)
2)、916;getHandler(processedRequest);根据当前请求获取到能处理这个请求的Controller对象
3)、923:找到能执行这个Controller对象里面每一个方法的适配器
4)、945:ha.handle适配器调用目标方法(利用反射调用方法)
5)、959:转发到页面(处理响应结果)processDispatchResult
 
1、根据当前请求地址找到哪个处理器来处理请求
mappedHandler = getHandler(processedRequest);
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}

  

SprngMVC源码学习
SpringfMVC启动的时候扫描所有的注解,将每一个类的每一个方法能处理什么请求都已经保存在handlerMapping中了;DefaultAnnotationHandlerMapping;
SprngMVC源码学习
2、为当前请求确定适配器
 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
找到能调用这个类里面每个方法的适配器;适配器利用反射调用方法;
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

  

我们都使用注解模式的所以适配器使用第三个;
SprngMVC源码学习
3、SpringMVC中DispatcherServlet的几个重要属性,以及赋值
SpringMVC九大组件;
/** MultipartResolver used by this servlet 文件上传解析器*/
private MultipartResolver multipartResolver; /** LocaleResolver used by this servlet 国际化解析器*/
private LocaleResolver localeResolver; /** ThemeResolver used by this servlet 主题解析器*/
private ThemeResolver themeResolver; /** List of HandlerMappings used by this servlet 保存了请求与类的映射关系(哪个请求用哪个类来处理)*/
private List<HandlerMapping> handlerMappings; /** List of HandlerAdapters used by this servlet适配器;用来执行控制器(处理器)目标方法的*/
private List<HandlerAdapter> handlerAdapters; /** List of HandlerExceptionResolvers used by this servlet 异常解析器*/
private List<HandlerExceptionResolver> handlerExceptionResolvers; /** RequestToViewNameTranslator used by this servlet 转化器*/
private RequestToViewNameTranslator viewNameTranslator; /** FlashMapManager used by this servletFlashMap 管理器 */
private FlashMapManager flashMapManager; /** List of ViewResolvers used by this servlet视图解析器 */
private List<ViewResolver> viewResolvers;
SprngMVC源码学习
SprngMVC源码学习
SprngMVC源码学习
SprngMVC源码学习
文件上传组件默认没值;
默认赋值;
    protected void initStrategies(ApplicationContext context) {
         //默认从ioc容器中获取id为multipartResolver的组件,如果没有获取到就赋值为null;
        initMultipartResolver(context);
         //按照id获取localeResolver;如果没有;
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }
 
//1、有些组件是这么》?先获取用户配置的,如果没有可以使用默认的(MultipartResolver )
//2、有些组件是拿id获取的;有些是拿类型获取的,
//3、给SpringMVC中配置九大之一的某个组件;如果是拿id'获取的?id不要乱写,用指定id;
//如果是用类型获取,id可以不用写;
     
 
 
在于DispatcherServlet.class同目录下有一个properties文件,这里封装了所有组件默认的类型;
4、目标方法的运行
 
AnnotationMethodHandlerAdapter----》handle()
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception { Class<?> clazz = ClassUtils.getUserClass(handler);
Boolean annotatedWithSessionAttributes = this.sessionAnnotatedClassesCache.get(clazz);
if (annotatedWithSessionAttributes == null) {
annotatedWithSessionAttributes = (AnnotationUtils.findAnnotation(clazz, SessionAttributes.class) != null);
this.sessionAnnotatedClassesCache.put(clazz, annotatedWithSessionAttributes);
} if (annotatedWithSessionAttributes) {
// Always prevent caching in case of session attribute management.
checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
// Prepare cached set of session attributes names.
}
else {
// Uses configured default cacheSeconds setting.
checkAndPrepare(request, response, true);
} // Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return invokeHandlerMethod(request, response, handler);
}
}
}
//执行处理器(控制器Controller)的目标方法
return invokeHandlerMethod(request, response, handler);
}

  

protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//获取方法解析器
ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
//根据当前请求路径,匹配每个方法的requestMapping值;并解析方法的详细信息
Method handlerMethod = methodResolver.resolveHandlerMethod(request);
//获取方法的执行器
ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
//包装request和response;
ServletWebRequest webRequest = new ServletWebRequest(request, response);
//创建了一个隐含模型
ExtendedModelMap implicitModel = new BindingAwareModelMap();
//真正执行目标方法; handlerMethod.invoke(handler,args)
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
ModelAndView mav =
methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
return mav;
}
invokeHandlerMethod
public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception { Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
try {
boolean debug = logger.isDebugEnabled();
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
if (attrValue != null) {
implicitModel.addAttribute(attrName, attrValue);
}
} //找到标注了ModelAttribute注解的所有方法,并执行
for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
//解析处理器的参数;确定当前方法要执行时要使用的所有参数;
Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
}
//找到getBook方法的ModelAttribute注解的value值;
String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
continue;
}
ReflectionUtils.makeAccessible(attributeMethodToInvoke);
//执行方法,ModelAttribute标注的所有方法提前执行
Object attrValue = attributeMethodToInvoke.invoke(handler, args);
if ("".equals(attrName)) {
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
}
if (!implicitModel.containsAttribute(attrName)) {
//将ModelAttribute标注的提前运行的方法的返回值放入隐含模型;
implicitModel.addAttribute(attrName, attrValue);
}
} //确定目标方法每一个参数的值;
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
}
ReflectionUtils.makeAccessible(handlerMethodToInvoke);
//处理器目标方法执行,利用反射执行
return handlerMethodToInvoke.invoke(handler, args);
}
catch (IllegalStateException ex) {
// Internal assertion failed (e.g. invalid signature):
// throw exception with full handler method context...
throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
}
catch (InvocationTargetException ex) {
// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
ReflectionUtils.rethrowException(ex.getTargetException());
return null;
}
}
HandlerMethodInvoker-->resolveHandlerArguments(确定目标方法使用的每一个参数值)
//确定参数值
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception { Class<?>[] paramTypes = handlerMethod.getParameterTypes();
Object[] args = new Object[paramTypes.length]; for (int i = 0; i < args.length; i++) {
MethodParameter methodParam = new MethodParameter(handlerMethod, i);
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
String paramName = null;
String headerName = null;
boolean requestBodyFound = false;
String cookieName = null;
String pathVarName = null;
String attrName = null;
boolean required = false;
String defaultValue = null;
boolean validate = false;
Object[] validationHints = null;
int annotationsFound = 0;
Annotation[] paramAnns = methodParam.getParameterAnnotations();
//解析参数的所有注解,把注解的信息保存起来
for (Annotation paramAnn : paramAnns) {
if (RequestParam.class.isInstance(paramAnn)) {
RequestParam requestParam = (RequestParam) paramAnn;
paramName = requestParam.value();
required = requestParam.required();
defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
annotationsFound++;
}
else if (RequestHeader.class.isInstance(paramAnn)) {
RequestHeader requestHeader = (RequestHeader) paramAnn;
headerName = requestHeader.value();
required = requestHeader.required();
defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());
annotationsFound++;
}
else if (RequestBody.class.isInstance(paramAnn)) {
requestBodyFound = true;
annotationsFound++;
}
else if (CookieValue.class.isInstance(paramAnn)) {
CookieValue cookieValue = (CookieValue) paramAnn;
cookieName = cookieValue.value();
required = cookieValue.required();
defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());
annotationsFound++;
}
else if (PathVariable.class.isInstance(paramAnn)) {
PathVariable pathVar = (PathVariable) paramAnn;
pathVarName = pathVar.value();
annotationsFound++;
}
else if (ModelAttribute.class.isInstance(paramAnn)) {
ModelAttribute attr = (ModelAttribute) paramAnn;
attrName = attr.value();
annotationsFound++;
}
else if (Value.class.isInstance(paramAnn)) {
defaultValue = ((Value) paramAnn).value();
}
else if (paramAnn.annotationType().getSimpleName().startsWith("Valid")) {
validate = true;
Object value = AnnotationUtils.getValue(paramAnn);
validationHints = (value instanceof Object[] ? (Object[]) value : new Object[] {value});
}
} //以上注解不能标注多个
if (annotationsFound > 1) {
throw new IllegalStateException("Handler parameter annotations are exclusive choices - " +
"do not specify more than one such annotation on the same parameter: " + handlerMethod);
} //当前参数没有找到注解
if (annotationsFound == 0) {
//解析普通参数(原生API);
Object argValue = resolveCommonArgument(methodParam, webRequest);
if (argValue != WebArgumentResolver.UNRESOLVED) {
args[i] = argValue;
}
else if (defaultValue != null) {
args[i] = resolveDefaultValue(defaultValue);
}
else { Class<?> paramType = methodParam.getParameterType();
//判断是否Model和Map旗下的,将隐含模型交给这个map类型的参数
if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {
if (!paramType.isAssignableFrom(implicitModel.getClass())) {
throw new IllegalStateException("Argument [" + paramType.getSimpleName() + "] is of type " +
"Model or Map but is not assignable from the actual model. You may need to switch " +
"newer MVC infrastructure classes to use this argument.");
}
args[i] = implicitModel;//存到map中
}
else if (SessionStatus.class.isAssignableFrom(paramType)) {
args[i] = this.sessionStatus;
}
else if (HttpEntity.class.isAssignableFrom(paramType)) {
args[i] = resolveHttpEntityRequest(methodParam, webRequest);
}
else if (Errors.class.isAssignableFrom(paramType)) {
throw new IllegalStateException("Errors/BindingResult argument declared " +
"without preceding model attribute. Check your handler method signature!");
} //确定当前参数是否简单的基本类型参数;String,Integer ...
else if (BeanUtils.isSimpleProperty(paramType)) {
paramName = "";
}
//赋值为attrName="";
else {
attrName = "";
}
}
} //其他情况,有注解的情况,下边的某个if可能是成功的就会进行; if (paramName != null) {
args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
}
else if (headerName != null) {
args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
}
else if (requestBodyFound) {
args[i] = resolveRequestBody(methodParam, webRequest, handler);
}
else if (cookieName != null) {
args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
}
else if (pathVarName != null) {
args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
} //自定义类型对象的封装以及取值
else if (attrName != null) {
WebDataBinder binder =
resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);//后面重点介绍
boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
if (binder.getTarget() != null) {
doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
}
args[i] = binder.getTarget();
if (assignBindingResult) {
args[i + 1] = binder.getBindingResult();
i++;
}
implicitModel.putAll(binder.getBindingResult().getModel());
}
} return args;
}
resolveCommonArgument(解析普通参数)----resolveStandardArgument
确定参数是否可以传入的原生ServletAPI
@Override
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); if (ServletRequest.class.isAssignableFrom(parameterType) ||
MultipartRequest.class.isAssignableFrom(parameterType)) {
Object nativeRequest = webRequest.getNativeRequest(parameterType);
if (nativeRequest == null) {
throw new IllegalStateException(
"Current request is not of type [" + parameterType.getName() + "]: " + request);
}
return nativeRequest;
}
else if (ServletResponse.class.isAssignableFrom(parameterType)) {
this.responseArgumentUsed = true;
Object nativeResponse = webRequest.getNativeResponse(parameterType);
if (nativeResponse == null) {
throw new IllegalStateException(
"Current response is not of type [" + parameterType.getName() + "]: " + response);
}
return nativeResponse;
}
else if (HttpSession.class.isAssignableFrom(parameterType)) {
return request.getSession();
}
else if (Principal.class.isAssignableFrom(parameterType)) {
return request.getUserPrincipal();
}
else if (Locale.class.equals(parameterType)) {
return RequestContextUtils.getLocale(request);
}
else if (InputStream.class.isAssignableFrom(parameterType)) {
return request.getInputStream();
}
else if (Reader.class.isAssignableFrom(parameterType)) {
return request.getReader();
}
else if (OutputStream.class.isAssignableFrom(parameterType)) {
this.responseArgumentUsed = true;
return response.getOutputStream();
}
else if (Writer.class.isAssignableFrom(parameterType)) {
this.responseArgumentUsed = true;
return response.getWriter();
}
return super.resolveStandardArgument(parameterType, webRequest);
}
结论一:
提前运行的ModelAttribute方法的参数和目标方法的参数写法规则是一模一样的;
提前运行了ModelAttribute方法,隐含模型中会有两种东西?
1)、ModelAttribute方法Map作为参数时,给里面put的数据
2)、ModelAttribute方法返回值也放入map。
3)、都是给隐含模型中放置值
 
流程:
1)、获取所有参数类型,挨个确定每个参数对应值
2)、确定当前参数是否有注解;
          有:保存注解的详细信息;
          没有:往下走
3)、注解大于1抛异常(注解不合法),
4)、注解=0(没有注解),if -- else if
          1)确定这个参数是否原生API;是则返回,
          2)是否有默认值@Value("");没有
          3)其他情况
               1)、是否Model或者Map旗下的,是则将隐含模型赋值过来
               2)、
5)、注解正好的情况(注解ok)
          1)、其他注解
          2)、ModelAttribute注解;
                    将ModelAttribute注解的value值赋值给attrName
 
6)、确定自定义类型对象;attrName肯定不是null
       attrName的值:
          1)、参数有ModelAttribute注解attrName就是注解标注的值
          2)、参数没有ModelAttribute注解,attrName就是"";
private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception { // Bind request parameter onto object...
String name = attrName;
if ("".equals(name)) {
name = Conventions.getVariableNameForParameter(methodParam);
}
Class<?> paramType = methodParam.getParameterType(); //
Object bindObject;
//1、判断隐含模型中是否有这个key,有则从隐含模型中获取到这个值赋值給bindObject;
if (implicitModel.containsKey(name)) {
bindObject = implicitModel.get(name);
}
//2、如果隐含模型中没有看是否是SessionAttributes标注的属性,如果是从Session中获取这个key的值,赋值给bindObject
else if (this.methodResolver.isSessionAttribute(name, paramType)) {
bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
//如果Session中没有查到这个值。抛异常;
if (bindObject == null) {
raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
}
}
//3、隐含模型中也没有这个key,SessionAttributes也没说它有。
else {
// 利用反射创建出一个对象
bindObject = BeanUtils.instantiateClass(paramType);
} //把bindObject传入,返回一个WebDataBinder(将请求传入的参数绑定到刚才创建的对象中);
WebDataBinder binder = createBinder(webRequest, bindObject, name);
initBinder(handler, name, binder, webRequest);
return binder;
}
执行目标方法并返回;
 
 
1)、确定自定义类型参数的值流程;
     1、确定Book对象的attrName;  获取标注了ModelAttribute注解的value值;如果没有就是"";(给Book对象确定一个key)
     2、一但key是"";把Book的类型首字符小写作为key
     3、查这个key的值:
          1)、判断隐含模型中是否存在这个key;如果有则返回,没有继续
          2)、看是否是SessionAttributes标注的属性;是则查询(查不到抛异常)
          3)、都不是,则利用反射创建对象;
     4、将请求带来的每一个参数封装进这个对象中;
SprngMVC源码学习
【7、SpringMVC如何解析方法返回值(视图)】
逻辑视图(方法返回值)转为物理视图(真实页面地址)的过程;
1)、任意方法的任意返回值,最终都会被包装成一个ModelAndView对象;返回出去;既包含了视图信息又包含了模型数据;
          1)、方法执行完成以后,根据方法的返回值包装ModelAndView对象;
               方法的返回值就是页面地址。隐含模型中的所有数据就是要给页面携带的数据;
 AnnotationMethodHandlerAdapter----》handle()-----》invokeHandlerMethod()-----》 resolveModelAttribute()
//真正执行目标方法;    handlerMethod.invoke(handler,args)
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
ModelAndView mav =
methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
//各种数据类型最终都会转换成ModelAndView 类型
@SuppressWarnings("unchecked")
public ModelAndView getModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue,
ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception { ResponseStatus responseStatusAnn = AnnotationUtils.findAnnotation(handlerMethod, ResponseStatus.class);
if (responseStatusAnn != null) {
HttpStatus responseStatus = responseStatusAnn.value();
String reason = responseStatusAnn.reason();
if (!StringUtils.hasText(reason)) {
webRequest.getResponse().setStatus(responseStatus.value());
}
else {
webRequest.getResponse().sendError(responseStatus.value(), reason);
} // to be picked up by the RedirectView
webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, responseStatus); responseArgumentUsed = true;
} // Invoke custom resolvers if present...
if (customModelAndViewResolvers != null) {
for (ModelAndViewResolver mavResolver : customModelAndViewResolvers) {
ModelAndView mav = mavResolver.resolveModelAndView(
handlerMethod, handlerType, returnValue, implicitModel, webRequest);
if (mav != ModelAndViewResolver.UNRESOLVED) {
return mav;
}
}
} if (returnValue instanceof HttpEntity) {
handleHttpEntityResponse((HttpEntity<?>) returnValue, webRequest);
return null;
}
else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
handleResponseBody(returnValue, webRequest);
return null;
}
else if (returnValue instanceof ModelAndView) {
ModelAndView mav = (ModelAndView) returnValue;
mav.getModelMap().mergeAttributes(implicitModel);
return mav;
}
else if (returnValue instanceof Model) {
return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap());
}
else if (returnValue instanceof View) {
return new ModelAndView((View) returnValue).addAllObjects(implicitModel);
}
else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) {
addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
return new ModelAndView().addAllObjects(implicitModel);
}
else if (returnValue instanceof Map) {
return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map<String, ?>) returnValue);
}
else if (returnValue instanceof String) {
return new ModelAndView((String) returnValue).addAllObjects(implicitModel);
}
else if (returnValue == null) {
// Either returned null or was 'void' return.
if (this.responseArgumentUsed || webRequest.isNotModified()) {
return null;
}
else {
// Assuming view name translation...
return new ModelAndView().addAllObjects(implicitModel);
}
}
else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) {
// Assume a single model attribute...
addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
return new ModelAndView().addAllObjects(implicitModel);
}
else {
throw new IllegalArgumentException("Invalid handler method return value: " + returnValue);
}
}

  

2、959:处理返回值processDispatchResult;
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
          1)、视图解析器负责将返回值解析创建出视图对象
          2)、视图对象决定模型数据如何渲染(数据怎么展示);页面如何跳转;
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception { boolean errorView = false; //1、有异常处理异常
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);
}
} // Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
//渲染流程
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
} if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
} if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
Render方法的内部
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale); View view;
if (mv.isReference()) {
// 1)We need to resolve the view name.视图解析器要根据返回值创建视图对象了
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException(
"Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" +
getServletName() + "'");
}
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
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() + "'");
}
} // Delegate to the View object for rendering.
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
}
try {
        //2)、视图对象进行渲染
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '"
+ getServletName() + "'", ex);
}
throw ex;
}
}
1)We need to resolve the view name.视图解析器要根据返回值创建视图对象了
View:这是一个接口;
ViewResolver:也是一个接口;
ViewResolver创建出View对象,View对象负责页面信息的渲染
SprngMVC源码学习
ViewResolver:用户可以配置多个
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
HttpServletRequest request) throws Exception { //多个视图解析器依次解析,如果某个解析成功就直接返回值;如果没有成功下一个解析器继续
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);//createView()在里面
if (view != null) {
return view;
}
}
return null;
}
viewResolver 根据视图名得到视图对象;resolveViewName细节;在InternalResourceViewResovler的父类中定义了创建视图对象这个方法
view = createView(viewName, locale);
@Override
protected View createView(String viewName, Locale locale) throws Exception {
// If this resolver is not supposed to handle the given view,
// return null to pass on to the next resolver in the chain.
if (!canHandle(viewName, locale)) {
return null;
} // Check for special "redirect:" prefix.如果是redirect:开始的、创建一个有重定向功能的视图对象;
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
return applyLifecycleMethods(viewName, view);
}
// Check for special "forward:" prefix.如果是以forward:前缀开始,创建一个具有转发功能的视图对象;
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
return new InternalResourceView(forwardUrl);
}
// Else fall back to superclass implementation: calling loadView.否则创建一个默认的View对象
//InternalResourceView;默认的是有国际化功能的;
return super.createView(viewName, locale);
}
2)、视图对象进行渲染
视图对象进行渲染:DispatcherServlet---1225
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
" and static attributes " + this.staticAttributes);
} Map<String, Object> mergedModel = createMergedOutputModel(model, request, response); prepareResponse(request, response); //渲染模型数据;Merged:合并
  renderMergedOutputModel(mergedModel, request, response); }
视图对象如何渲染;
 @Override
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine which request handle to expose to the RequestDispatcher.
HttpServletRequest requestToExpose = getRequestToExpose(request); // Expose the model object as request attributes.将模型中的数据暴露到request域中;底层也是把隐含模型这个map中所有的key遍历都放在request域中
exposeModelAsRequestAttributes(model, requestToExpose); // Expose helpers as request attributes, if any.
exposeHelpers(requestToExpose); // Determine the path for the request dispatcher.拿到转发的地址
String dispatcherPath = prepareForRendering(requestToExpose, response); // Obtain a RequestDispatcher for the target resource (typically a JSP).
RequestDispatcher rd = getRequestDispatcher(requestToExpose, 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 already included or response already committed, perform include, else forward.
if (useInclude(requestToExpose, response)) {
response.setContentType(getContentType());
if (logger.isDebugEnabled()) {
logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.include(requestToExpose, response);
} else {
// Note: The forwarded resource is supposed to determine the content type itself.
if (logger.isDebugEnabled()) {
logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
//转发到页面
rd.forward(requestToExpose, response);
}
}
1、视图解析器负责根据返回值作为页面地址得到视图对象
2、视图对象调用渲染方法;
3、视图对象渲染(页面跳转逻辑,模型数据放在请求域中)
InternalResourceView:转发到页面
RedirectView:重定向到页面
JSTLView:快速国际化;只要导入了jstl的jar包,以前默认创建的InternalResouceView都会被使用jstlView替代;
     国际化的新步骤:
          1)、写好国际化资源文件
          2)、在SpringMVC配置文件中配置管理国际化资源文件的消息管理器组件
<!-- 注册一个国际化资源管理器;id必须是messageSource -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
   3)、去页面 使用fmt:message标签取值即可
 
 
 SprngMVC源码学习
 
上一篇:shell的重定向


下一篇:EWM ODO清理功能