14.spring-mvc源码
1.前端控制器的架构:
前端控制器在web.xml的配置:拦截请求,智能派发,并启动spring容器!
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
前端控制器:DispatcherServlet
1.前端控制器的架构?DispatcherServlet
前端控制器的架构如上图:
1.DispatcherServlet 继承于FrameworkServlet类
public class DispatcherServlet extends FrameworkServlet{
}
2.FrameworkServlet继承于HttpServletBean,HttpServletBean继承于HttpServlet,并重写了doget和dopost方法
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
//发现doGet/doPost均调用了本类中的processRequest方法
protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
//本类中的processRequest方法,在方法中又调用了本类的doService方法
protected final void processRequest(HttpServletRequest request, HttpServletResponse response){
...
this.doService(request, response);
...
}
//发现doservice方法是个抽象方法,具体的实现由其子类DispatcherServlet 实现,即具体的处理在DispatcherServlet 的doservice方法中
protected abstract void doService(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}
3.DispatcherServlet 的doservice方法
public class DispatcherServlet extends FrameworkServlet{
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
//调用了本类的doDispatch来处理请求
this.doDispatch(request, response);
...
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//1.检查请求是否是文件上传请求
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//2.根据当前的请求地址查看哪个类能来处理
mappedHandler = this.getHandler(processedRequest);
//3.如果没有找到哪个处理器(控制器)可以处理该请求,就会抛出异常!,或报404
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
//4.拿到能执行这个类的所有方法的适配器(相当于反射工具,最终通过该适配器执行方法ha=AnnotationMethodHandlerAdapter)
HandlerAdapter ha = this.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 (this.logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
this.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 {
//执行目标方法:处理器(控制器的方法被执行) 处理器:handle 控制器:controler
//5.适配器执行目标方法,将目标方法执行完成后的返回值作为视图名,设置保存在ModealAndView中
//目标方法无论怎么执行,不管返回值是String/Modeal/ModealMap,其底层适配器都会将其将目标方法的执行结果封装到ModelAndView中
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
//6.如果没有视图名称,即目标方法没有返回视图名,则设置一个默认的视图名称
this.applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var28) {
dispatchException = var28;
}
//转发到页面
//7.根据方法最终执行后的封装的ModelAndView,转发到对应的页面,而且ModelAndView中的数据可以从请求域中获取
this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception var29) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var29);
} catch (Error var30) {
this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var30);
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
} else {
if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
}
}
请求处理的流程图:
1.DispatcherServlet 收到所有的请求
2.调用doDispatch()方法进行处理
2.1. mappedHandler =this.getHandler(processedRequest);根据当前的请求地址找到能处理这个请求的目标处理器类(处理器)
根据当前请求在handlerMapping中查找这个请求的映射信息,获取目标处理类
2.2.HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()):根据当前处理器类获取能执行这个处理器方法的适配器
根据当前处理器类,找到当前类的HandlerAdapter(适配器-->反射工具,用于最终处理目标方法)
2.3.使用刚才的适配器(AnnotationMethodHandlerAdapter)执行目标方法
2.4目标方法执行后会返回一个ModelAndView对象
2.5根据ModelAndView的信息转发到具体的页面,并在请求域中拿到ModelAndView中的模型数据
1.getHandler细节:获取请求处理器,怎么根据当前请求找到哪个类进行处理
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//通过下图知道:handlerMappings有两个属性值:BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping
//BeanNameUrlHandlerMapping:基于配置的
//DefaultAnnotationHandlerMapping:基于注解的@RequestMapping
//每次请求过来都会遍历BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping,拿到处理请求的处理类
//如果配置和注解标注了同一个方法,配置有效
Iterator var2 = this.handlerMappings.iterator();
HandlerExecutionChain handler;
do {
if (!var2.hasNext()) {
return null;
}
HandlerMapping hm = (HandlerMapping)var2.next();
if (this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
handler = hm.getHandler(request);
} while(handler == null);
return handler;
}
handlerMap如何有路径和处理类的对应关系:IOC创建每个Controler对象时,会扫描@RequestMapping,查看处理器能够处理什么请求,并保存在handlerMappings中的handlerMap中,下一次请求过来就直接看hadlermapping中有这个请求映射信息就行了
2.getHandlerAdapter拿到执行方法的适配器:
如何找到目标处理器类的适配器,要拿到适配器才能执行目标方法
适配器可以理解成是一种反射工具,使用第三个适配器
AnnotationMethodHandlerAdapter:能解析注解的适配器
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
Iterator var2 = this.handlerAdapters.iterator();
HandlerAdapter ha;
do {
if (!var2.hasNext()) {
throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
ha = (HandlerAdapter)var2.next();
if (this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler adapter [" + ha + "]");
}
} while(!ha.supports(handler));
return ha;
}
handlerAdapters的最后一项AnnotationMethodHandlerAdapter,会判断处理器中是否有@requesMapping标注而加载到容器中的方法,有方法就可以执行
ha.supports(handler)的细节:
前两项的细节均是:
1.
public boolean supports(Object handler) {
return handler instanceof HttpRequestHandler;
}
2.
public boolean supports(Object handler) {
return handler instanceof Controller;
}
最后一项:AnnotationMethodHandlerAdapter会判断处理器是否有带@requesMapping的方法
public final boolean hasHandlerMethods() {
return !this.handlerMethods.isEmpty();
}
handlerAdapters和handlerMappings是何时有值的呢,在上述在中,查找处理器遍历handlerMappings,查找适配器遍历handlerAdapters
DispatcherServlet中有以下9个引用类型变量:springmvc的九大组件
springmvc在工作的时候,关键位置都是由这些组件完成
//1.文件上传解析器
private MultipartResolver multipartResolver;
//2.国际化
private LocaleResolver localeResolver;
//3.主题解析器:强大的主题效果更换
private ThemeResolver themeResolver;
//4.handler映射信息:请求路径和处理类的对应关系
private List<HandlerMapping> handlerMappings;------->处理器
//5.handler的适配器
private List<HandlerAdapter> handlerAdapters;------->适配器
//6.springmcvc强大的异常解析功能:异常解析器
private List<HandlerExceptionResolver> handlerExceptionResolvers;
//7.不用
private RequestToViewNameTranslator viewNameTranslator;
//8.FlashMap+Manager,springmvcc在运行中允许重定向携带数据。将数据保存在session中
private FlashMapManager flashMapManager;
//9.视图解析器
private List<ViewResolver> viewResolvers;
,
以上的九大组件均是接口,将组件做成接口的好处?接口就是规范,提供了强大的扩展性
九大组件初始化的地方
DispatcherServlet中:
springmvc在启动时会调用onRefresh方法,initStrategies方法中有九大组件的初始化
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
1.handlerMappings 的初始化
可以在web.xml中更改DispatcherServlet某些属性的默认值,但尽量不改,除非特别熟悉该属性的作用
public class DispatcherServlet extends FrameworkServlet {
...
private boolean detectAllHandlerMappings = true;
...
}
在web.xml中可以更改其默认值:
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>detectAllHandlerMappings</param-name>------------->更改其默认值时false
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
//1.使用bean工厂,按照类型查找所有的HandlerMapping组件
Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList(matchingBeans.values());
OrderComparator.sort(this.handlerMappings);
}
} else {
try {
//2.如果找不到,按照id去容器中查找HandlerMapping组件
HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
} catch (NoSuchBeanDefinitionException var3) {
}
}
//3.如果上述的均没有找到HandlerMapping组件,就使用默认配置
if (this.handlerMappings == null) {
this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
if (this.logger.isDebugEnabled()) {
this.logger.debug("No HandlerMappings found in servlet '" + this.getServletName() + "': using default");
}
}
}
组件的初始化:
有些组件在容器中是按照类型查找的,有些组件是按照id查找的
去容器中找这个组件,如果没有就使用默认配置
ha.handle()执行目标方法
spring底层是通过反射来执行目标方法的,但是若让我们写method.invoke(this,args)最难确定的就是参数,因为spring对参数要求较低
例如下述请求包含了四种请求参数
@RequestMapping("/hello")
public String updateBook(
@RequestParam(value = "bookName") String bookName,
Map<String, Object> map,
HttpServletRequest request,
@ModelAttribute("hhh") Book book){
}
执行目标方法细节
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.判断目标处理器类中是否包含@SessionAttributes注解
....
//2.执行目标方法
return this.invokeHandlerMethod(request, response, handler);
}
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.拿到方法的解析器
AnnotationMethodHandlerAdapter.ServletHandlerMethodResolver methodResolver = this.getMethodResolver(handler);
//2.方法解析器根据当前路径拿到真正的目标方法
Method handlerMethod = methodResolver.resolveHandlerMethod(request);
//3.创建一个方法执行器
AnnotationMethodHandlerAdapter.ServletHandlerMethodInvoker methodInvoker = new AnnotationMethodHandlerAdapter.ServletHandlerMethodInvoker(methodResolver);
//4.封装原生的request, response对象
ServletWebRequest webRequest = new ServletWebRequest(request, response);
//5.创建一个BindingAwareModelMap:由之前可知,在带@RequestMapping目标方法中传入的map/modelMap,最终的类型都是BindingAwareModelMap,这就是原因
//创建了一个隐含的模型
ExtendedModelMap implicitModel = new BindingAwareModelMap();
//6.真正的执行目标方法
//目标方法利用反射执行期间,通过反射确定参数值,提前执行@ModelAttribute等的操作都在这个方法中
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;
}
其中:具体的执行代码如下:
public final Object invokeHandlerMethod(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
//1.获取执行的目标方法
Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
try {
boolean debug = logger.isDebugEnabled();
//2.获取带@SessionAttribute注解的方法
Iterator var7 = this.methodResolver.getActualSessionAttributeNames().iterator();
while(var7.hasNext()) {
String attrName = (String)var7.next();
Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
if (attrValue != null) {
//3.若session中有值,会将其存储在上面创建的隐含模型中:ExtendedModelMap implicitModel = new BindingAwareModelMap();
implicitModel.addAttribute(attrName, attrValue);
}
}
//4.获取@ModelAttribute的方法
var7 = this.methodResolver.getModelAttributeMethods().iterator();
while(true) {
Object[] args;
String attrName;
Method attributeMethodToInvoke;
do {
if (!var7.hasNext()) {
Object[] args = this.resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
}
ReflectionUtils.makeAccessible(handlerMethodToInvoke);
//执行目标方法
return handlerMethodToInvoke.invoke(handler, args);
}
//5.获取到需要执行的@ModelAttribute的方法
Method attributeMethod = (Method)var7.next();
attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
//5.重要:获取执行方法的参数---------------------------->获取执行目标方法的参数
args = this.resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
}
//6.获取带@ModelAttribute(value="")的value值
attrName = ((ModelAttribute)AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class)).value();
} while(!"".equals(attrName) && implicitModel.containsAttribute(attrName));
ReflectionUtils.makeAccessible(attributeMethodToInvoke);
//6.执行目标方法
Object attrValue = attributeMethodToInvoke.invoke(handler, args);
//7.这里会获取到@ModelAttribute(value="")的value值
/**
* 1.如果带@ModelAttribute(value="abc")有值:attrName="abc"
* @ModelAttribute(value = "abc")
* public void selectBookByBookname(Map <String,Object> map,Book book,@RequestParam(value = "bookName") String bookName){
* ...
* }
* 2.没标value值,attrName="";
*/
if ("".equals(attrName)) {
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
//8. @ModelAttribute没标value时,attrName 是返回值的首字母小写,若为void,attrName="void",若返回值是Book,attrName="book"
attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
}
//9.判断隐含模型中是否包含:attrName ="void",不包含就将其放入在隐含模型中:void=null
if (!implicitModel.containsAttribute(attrName)) {
implicitModel.addAttribute(attrName, attrValue);
}
}
} catch (IllegalStateException var14) {
throw new HandlerMethodInvocationException(handlerMethodToInvoke, var14);
} catch (InvocationTargetException var15) {
ReflectionUtils.rethrowException(var15.getTargetException());
return null;
}
【分析源码得知】
@ModelAttribute标签的另外一个作用:
可以将方法执行返回返回值按照方法上@ModelAttribute("abc")指定的key放到隐含模型中
没有这个key,就按方法返回值的小写
确定目标方法的参数个数和类型:
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
//1.获取参数类型,返回数组
Class<?>[] paramTypes = handlerMethod.getParameterTypes();
//2.创建一个和参数长度相同的数组
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();
Annotation[] var21 = paramAnns;
int var22 = paramAnns.length;
//找到目标方法的所有注解,例如@RequestParam,如果有注解就解析并保存信息
for(int var23 = 0; var23 < var22; ++var23) {
Annotation paramAnn = var21[var23];
if (RequestParam.class.isInstance(paramAnn)) {
RequestParam requestParam = (RequestParam)paramAnn;
paramName = requestParam.value();
required = requestParam.required();
defaultValue = this.parseDefaultValueAttribute(requestParam.defaultValue());
++annotationsFound;
} else if (RequestHeader.class.isInstance(paramAnn)) {
RequestHeader requestHeader = (RequestHeader)paramAnn;
headerName = requestHeader.value();
required = requestHeader.required();
defaultValue = this.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 = this.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[])((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) {
//解析普通参数---->最终这个方法会进入:Object value = this.resolveStandardArgument(paramType, webRequest);解析标准参数
Object argValue = this.resolveCommonArgument(methodParam, webRequest);
if (argValue != WebArgumentResolver.UNRESOLVED) {
args[i] = argValue;
} else if (defaultValue != null) {
args[i] = this.resolveDefaultValue(defaultValue);
} else {
Class<?> paramType = methodParam.getParameterType();
//判断参数是否是Model和Map旗下的,如果不是就将创建的对象:bindingAwareModelMap赋值给参数
if (!Model.class.isAssignableFrom(paramType) && !Map.class.isAssignableFrom(paramType)) {
if (SessionStatus.class.isAssignableFrom(paramType)) {
args[i] = this.sessionStatus;
} else if (HttpEntity.class.isAssignableFrom(paramType)) {
args[i] = this.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!");
}
if (BeanUtils.isSimpleProperty(paramType)) {
paramName = "";
} else {
attrName = "";
}
}
} else {
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.");
}
//将隐含对象BindingAwareModelMap赋值给参数值!
args[i] = implicitModel;
}
}
}
if (paramName != null) {
args[i] = this.resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
} else if (headerName != null) {
args[i] = this.resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
} else if (requestBodyFound) {
args[i] = this.resolveRequestBody(methodParam, webRequest, handler);
} else if (cookieName != null) {
args[i] = this.resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
} else if (pathVarName != null) {
args[i] = this.resolvePathVariable(pathVarName, methodParam, webRequest, handler);
} else if (attrName != null) {
WebDataBinder binder = this.resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
boolean assignBindingResult = args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]);
if (binder.getTarget() != null) {
this.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)方法中,会先调用自定义参数解析器(customArgumentResolvers)->无用,然后会调用标准参数解析器(resolveStandardArgument)->判断是否是原生api
标准参数解析器细节如下:发现其是判断参数是否为servlet原生的参数:如request /response 等
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = (HttpServletResponse)webRequest.getNativeResponse(HttpServletResponse.class);
Object nativeResponse;
if (!ServletRequest.class.isAssignableFrom(parameterType) && !MultipartRequest.class.isAssignableFrom(parameterType)) {
if (ServletResponse.class.isAssignableFrom(parameterType)) {
this.responseArgumentUsed = true;
nativeResponse = webRequest.getNativeResponse(parameterType);
if (nativeResponse == null) {
throw new IllegalStateException("Current response is not of type [" + parameterType.getName() + "]: " + response);
} else {
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();
} else {
return super.resolveStandardArgument(parameterType, webRequest);
}
} else {
nativeResponse = webRequest.getNativeRequest(parameterType);
if (nativeResponse == null) {
throw new IllegalStateException("Current request is not of type [" + parameterType.getName() + "]: " + request);
} else {
return nativeResponse;
}
}
}
总结:
运行两件事:
1.运行流程简单版
2.确定方法上每个参数值
2.1标了注解:保存注解信息,最终得到这个注解应该对应解析的值
2.2没标注解:
2.2.1看是否是原生的api
2.2.2看是否是Model或者Map,xxxx
2.2.3都不是,看是否是简单类型
2.2.4给attrName赋值;attename(参数标注了@ModelAttribute(""))就是指定的,没标就是""
确定自定义类型参数:
1.attrName用参数类型首字母小写,或者用之前@ModelAttribute("")的值,
2.确定隐含模型中每个attrname作为key的值;如果有就从隐含模型中拿值
3.看是否是@SessionAttribute(value="hhh")标注的属性,如果是就从session中拿,如果拿不到就会抛异常!
4.如果不是@SessionAttribute标注的,利用反射创建一个对象
2.2.5.拿到之前创建好的对象,使用数据绑定器(webDataBinder)将请求中的每个数据绑定到这个对象中