前提:当找到handler以后,那么就要让handler发挥作用,这个时候handlerAdapter就派上用场了

这里面比较复杂就是requestMappingHandlerAdapter了,其他的由于handler比较固定,基本上之前调用他们实现的接口的方法。

@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
supportsInternal方法子类实现,用于扩展,但在requestMappingHandlerAdapter子类中并没有做什么,直接返回true。 @Override
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception { return handleInternal(request, response, (HandlerMethod) handler);
} handleInternal方法也有子类实现。在调用handler之前,会做一些数据绑定,比如会查找@ControllerAdvice注解,查找@InitBinder,@ModuleAttribute,查找实现了RequestBodyAdvice的类等等。
初始化一些参数解析器,校验器 RequestMappingHandlerAdapter实现了InitializingBean接口,所以在初始化这个adapter并且设置了相应的属性之后就会调用afterPropertiesSet方法
@Override
public void afterPropertiesSet() {
// Do this first, it may add ResponseBody advice beans
//初始化@ControllerAdvice标注的类
initControllerAdviceCache(); if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
} private void initControllerAdviceCache() {
if (getApplicationContext() == null) {
return;
}
if (logger.isInfoEnabled()) {
logger.info("Looking for @ControllerAdvice: " + getApplicationContext());
}
//在applicationContext容器中找到被@controllerAdvice标注的bean,并排序
List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
AnnotationAwareOrderComparator.sort(beans);
//创建实现了@responseBodyAdvice的bean
List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>(); for (ControllerAdviceBean bean : beans) {
//查找被@ModelAttribute注解标注的方法
Set<Method> attrMethods = MethodIntrospector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(bean, attrMethods);
if (logger.isInfoEnabled()) {
logger.info("Detected @ModelAttribute methods in " + bean);
}
}
//查找被@InitBinder注解标注的方法
Set<Method> binderMethods = MethodIntrospector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(bean, binderMethods);
if (logger.isInfoEnabled()) {
logger.info("Detected @InitBinder methods in " + bean);
}
}
//查找父类是RequestBodyAdvice的bean
if (RequestBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
requestResponseBodyAdviceBeans.add(bean);
if (logger.isInfoEnabled()) {
logger.info("Detected RequestBodyAdvice bean in " + bean);
}
}
//查找父类是ResponseBodyAdvice的bean
if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
requestResponseBodyAdviceBeans.add(bean);
if (logger.isInfoEnabled()) {
logger.info("Detected ResponseBodyAdvice bean in " + bean);
}
}
}
if (!requestResponseBodyAdviceBeans.isEmpty()) {
//将使用@ControllerAdvice注解找的bean放到最前面
this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
} 方法返回后
接下来就开始初始化解析器了
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
} getDefaultArgumentResolvers方法
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>(); // Annotation-based argument resolution基于注解参数解析器
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); // Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); // Custom arguments自定义参数解析器
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
} // Catch-all可以处理所有类型的参数解析器
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true)); return resolvers;
} 准备就绪之后,开始调用handleInternal方法 @Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav;
//检查是否支持当前请求的方法,检查session是否为必须的
checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required.
//执行session同步
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
} if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
} return mav;
} protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response);
//创建data绑定工厂,数据绑定是用来与String进行参数转换的
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
} invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
} return getModelAndView(mavContainer, modelFactory, webRequest);
} private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
Class<?> handlerType = handlerMethod.getBeanType();
//从缓存中查找是否已经存在这个类型对应的@InitBinder方法
Set<Method> methods = this.initBinderCache.get(handlerType);
if (methods == null) {
//如果为空,就对当前handler进行遍历查找@InitBinder的方法
methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
//保存到缓存中
this.initBinderCache.put(handlerType, methods);
}
List<InvocableHandlerMethod> initBinderMethods = new ArrayList<InvocableHandlerMethod>();
// Global methods first遍历全局(也就是@ControllerAdvice标注的类的@InitBinder方法,这个在adapter的afterPropertiesSet方法中初始化的)
for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache.entrySet()) {
if (entry.getKey().isApplicableToBeanType(handlerType)) {
Object bean = entry.getKey().resolveBean();
for (Method method : entry.getValue()) {
//创建InvocableHandlerMethod对象并添加
initBinderMethods.add(createInitBinderMethod(bean, method));
}
}
}
//添加完全局的之后,再添加当前处理器的
for (Method method : methods) {
Object bean = handlerMethod.getBean();
initBinderMethods.add(createInitBinderMethod(bean, method));
}
return createDataBinderFactory(initBinderMethods);
} public boolean isApplicableToBeanType(Class<?> beanType) {
//如果@controllerAdvice什么属性都没有写,说明将所有配置的方法应用到所有的handler中
if (!hasSelectors()) {
return true;
}
else if (beanType != null) {
for (String basePackage : this.basePackages) {
if (beanType.getName().startsWith(basePackage)) {
return true;
}
}
for (Class<?> clazz : this.assignableTypes) {
if (ClassUtils.isAssignable(clazz, beanType)) {
return true;
}
}
for (Class<? extends Annotation> annotationClass : this.annotations) {
if (AnnotationUtils.findAnnotation(beanType, annotationClass) != null) {
return true;
}
}
}
return false;
} private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {
//InvocableHandlerMethod 是handlerMethod的子类
InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);
binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));
binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
return binderMethod;
} 最后返回一个createDataBinderFactory(initBinderMethods); 回到invokeHandlerMethod方法,创建了DataBinderFactory后,接下来就是创建ModelFactory了 private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
//获取SessionAttributesHandler,这个处理器用来处理@SessionAttributes注解的方法
SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
Class<?> handlerType = handlerMethod.getBeanType();
//获取标注了@ModelAttribute的方法
Set<Method> methods = this.modelAttributeCache.get(handlerType);
if (methods == null) {
//如果缓存中没有就重新查找当前标注了@ModelAttribute的方法,并存到缓存中
methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
this.modelAttributeCache.put(handlerType, methods);
}
List<InvocableHandlerMethod> attrMethods = new ArrayList<InvocableHandlerMethod>();
// Global methods first添加全局的@ModelAttribute注解的方法
for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) {
if (entry.getKey().isApplicableToBeanType(handlerType)) {
Object bean = entry.getKey().resolveBean();
for (Method method : entry.getValue()) {
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
}
}
for (Method method : methods) {
Object bean = handlerMethod.getBean();
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
//创建ModelFactory工厂
return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
} //第一个参数传入的是标记了@ModelAttribute的方法,第二个参数数据绑定,第三个是@SessionAttributes注解对应的处理器
public ModelFactory(List<InvocableHandlerMethod> handlerMethods,
WebDataBinderFactory binderFactory, SessionAttributesHandler attributeHandler) { if (handlerMethods != null) {
for (InvocableHandlerMethod handlerMethod : handlerMethods) {
this.modelMethods.add(new ModelMethod(handlerMethod));
}
}
this.dataBinderFactory = binderFactory;
this.sessionAttributesHandler = attributeHandler;
} private ModelMethod(InvocableHandlerMethod handlerMethod) {
this.handlerMethod = handlerMethod;
for (MethodParameter parameter : handlerMethod.getMethodParameters()) {
if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
this.dependencies.add(getNameForParameter(parameter));
}
}
} 当缓存什么的都弄好了之后就开始处理当前handleMethod了
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer();
//将FlashMap中的属性添加到mav容器中
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); public void initModel(NativeWebRequest request, ModelAndViewContainer container,
HandlerMethod handlerMethod) throws Exception {
//从sessionAttribute中回复参数到mavContainer中
Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
//合并参数,因为sessionAttribute中的参数可能会与flashmap中的参数冲突,但不会覆盖原来的参数
container.mergeAttributes(sessionAttributes);
//调用modelAttribute注解的方法
invokeModelAttributeMethods(request, container); for (String name : findSessionAttributeArguments(handlerMethod)) {
if (!container.containsAttribute(name)) {
Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
if (value == null) {
throw new HttpSessionRequiredException("Expected session attribute '" + name + "'");
}
container.addAttribute(name, value);
}
}
} invokeModelAttributeMethods(request, container); private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container)
throws Exception { while (!this.modelMethods.isEmpty()) {
//获取第一个modelMethod方法,并将其移除,等下次调用的时候就就是第二个modelMethod,如果参数有@ModelAttribute,则优先处理
InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod();
//获取模型值,即属性key值
String modelName = modelMethod.getMethodAnnotation(ModelAttribute.class).value();
//如果已经存在了就不再调用
if (container.containsAttribute(modelName)) {
continue;
}
//调用方法
Object returnValue = modelMethod.invokeForRequest(request, container);
if (!modelMethod.isVoid()){
String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType());
if (!container.containsAttribute(returnValueName)) {
container.addAttribute(returnValueName, returnValue);
}
}
}
} private ModelMethod getNextModelMethod(ModelAndViewContainer container) {
//遍历所有的modelmethod,如果他们的依赖存在,就优先使用这个方法参数与中有@ModelAttribute注解的modelmethod方法,否则就直接返回第一个modelmethod
for (ModelMethod modelMethod : this.modelMethods) {
if (modelMethod.checkDependencies(container)) {
if (logger.isTraceEnabled()) {
logger.trace("Selected @ModelAttribute method " + modelMethod);
}
this.modelMethods.remove(modelMethod);
return modelMethod;
}
}
//获取第一个modelmethod,并将它已移除
ModelMethod modelMethod = this.modelMethods.get(0);
if (logger.isTraceEnabled()) {
logger.trace("Selected @ModelAttribute method (not present: " +
modelMethod.getUnresolvedDependencies(container)+ ") " + modelMethod);
}
this.modelMethods.remove(modelMethod);
return modelMethod;
} //
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//获取方法参数值
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
StringBuilder sb = new StringBuilder("Invoking [");
sb.append(getBeanType().getSimpleName()).append(".");
sb.append(getMethod().getName()).append("] method with arguments ");
sb.append(Arrays.asList(args));
logger.trace(sb.toString());
}
Object returnValue = doInvoke(args);
if (logger.isTraceEnabled()) {
logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
}
return returnValue;
} private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//获取方法参数数组
MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
//给当前参数封装对象设置参数名解析器
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
//给当前参数封装对象设置参数类型
GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
//尝试从给定的providedArgs参数查找对应类型的参数,如果找到就设置这个值到args数组中,这个providedArgs在这里是没有传递任何值的
args[i] = resolveProvidedArgument(parameter, providedArgs);
//如果不为空就continue,表示已经有值了
if (args[i] != null) {
continue;
}
//查找有没有支持此参数解析的解析器
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
//解析参数
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
}
throw ex;
}
}
if (args[i] == null) {
String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
throw new IllegalStateException(msg);
}
}
return args;
} (this.argumentResolvers.supportsParameter(parameter)
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
//先从缓存中找,如果没有找到,在遍历所有的解析器,这个解析器集合保存在一个解析器Composite类中,SpringMVC中这样的类一般是使用的责任链模式
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
if (logger.isTraceEnabled()) {
logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +
parameter.getGenericParameterType() + "]");
}
if (methodArgumentResolver.supportsParameter(parameter)) {
result = methodArgumentResolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
} this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);方法体如下 @Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//获取参数解析器,如果没有获取到就抛出错误
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
if (resolver == null) {
throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]");
}
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
} HandlerMethodArgumentResolver的实现类有很多,这里选几个分析一下 首先先分析一下RequestResponseBodyMethodProcessor,这是一个集argumentResolve和handlerReturnValue于一身的类 直接看解析方法resolveArgument: @Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//使用转化器进行参数的转换
Object arg = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType());
String name = Conventions.getVariableNameForParameter(parameter); WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
if (arg != null) {
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
}
}
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); return arg;
} protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter methodParam,
Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException { HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest); Object arg = readWithMessageConverters(inputMessage, methodParam, paramType);
if (arg == null) {
if (methodParam.getParameterAnnotation(RequestBody.class).required()) {
throw new HttpMessageNotReadableException("Required request body is missing: " +
methodParam.getMethod().toGenericString());
}
}
return arg;
} readWithMessageConverters方法
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter param,
Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException { MediaType contentType;
boolean noContentType = false;
try {
//获取请求的ContentType
contentType = inputMessage.getHeaders().getContentType();
}
catch (InvalidMediaTypeException ex) {
throw new HttpMediaTypeNotSupportedException(ex.getMessage());
}
if (contentType == null) {
noContentType = true;
//设置默认的contentType
contentType = MediaType.APPLICATION_OCTET_STREAM;
}
//获取类的类型
Class<?> contextClass = (param != null ? param.getContainingClass() : null);
//获取的参数的泛型类型
Class<T> targetClass = (targetType instanceof Class<?> ? (Class<T>) targetType : null);
//如果没有就再次尝试设置一遍
if (targetClass == null) {
ResolvableType resolvableType = (param != null ?
ResolvableType.forMethodParameter(param) : ResolvableType.forType(targetType));
targetClass = (Class<T>) resolvableType.resolve();
}
//获取请求方法
HttpMethod httpMethod = ((HttpRequest) inputMessage).getMethod();
Object body = NO_VALUE; try {
inputMessage = new EmptyBodyCheckingHttpInputMessage(inputMessage);
//遍历这个解析器中的所有的converter,判断是否是泛化的转换器
for (HttpMessageConverter<?> converter : this.messageConverters) {
Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
if (converter instanceof GenericHttpMessageConverter) {
GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
//判断是否能够进行解析
if (genericConverter.canRead(targetType, contextClass, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
}
if (inputMessage.getBody() != null) {
//如果请求体有值,那么就尝试调用实现了RequestAdvice的类,对请求体进行预先处理
inputMessage = getAdvice().beforeBodyRead(inputMessage, param, targetType, converterType);
//使用converter进行转化
body = genericConverter.read(targetType, contextClass, inputMessage);
//对处理完的body进行后置处理,就是使用实现了ResponseAdvice的类进行处理
body = getAdvice().afterBodyRead(body, inputMessage, param, targetType, converterType);
}
else {
body = null;
//处理空请求体
body = getAdvice().handleEmptyBody(body, inputMessage, param, targetType, converterType);
}
break;
}
}
//如果不是泛化的转换器,那么就判断目标class是否为空。
else if (targetClass != null) {
if (converter.canRead(targetClass, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
}
if (inputMessage.getBody() != null) {
inputMessage = getAdvice().beforeBodyRead(inputMessage, param, targetType, converterType);
body = ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage);
body = getAdvice().afterBodyRead(body, inputMessage, param, targetType, converterType);
}
else {
body = null;
body = getAdvice().handleEmptyBody(body, inputMessage, param, targetType, converterType);
}
break;
}
}
}
}
catch (IOException ex) {
throw new HttpMessageNotReadableException("Could not read document: " + ex.getMessage(), ex);
}
//如果body没有被处理过
if (body == NO_VALUE) {
if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod) ||
(noContentType && inputMessage.getBody() == null)) {
return null;
}
throw new HttpMediaTypeNotSupportedException(contentType, this.allSupportedMediaTypes);
} canRead,判断是否可以处理这个请求类型的数据,对于json来说text/html肯定是不能进行处理的
protected boolean canRead(MediaType mediaType) {
if (mediaType == null) {
return true;
}
for (MediaType supportedMediaType : getSupportedMediaTypes()) {
if (supportedMediaType.includes(mediaType)) {
return true;
}
}
return false;
} 解析好后继续
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { Object arg = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType());
//如果指定的参数名为URL,连续两个大写字母的那么就保持它原来的样子,其他的就把第一个字母变成小写,如果是集合类的那么将泛型类型加上list字符串
String name = Conventions.getVariableNameForParameter(parameter);
//创建数据绑定器
WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
if (arg != null) {
//对参数进行校验
validateIfApplicable(binder, parameter);
//查看是否发生了异常
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
//抛出参数校验不通过的异常
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
}
}
//保存绑定数据后的结果信息
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); return arg;
} public static String getVariableNameForParameter(MethodParameter parameter) {
Assert.notNull(parameter, "MethodParameter must not be null");
Class<?> valueClass;
boolean pluralize = false; if (parameter.getParameterType().isArray()) {
//获取数组的元素类型
valueClass = parameter.getParameterType().getComponentType();
pluralize = true;
}
else if (Collection.class.isAssignableFrom(parameter.getParameterType())) {
//获取集合的泛型参数类型
valueClass = GenericCollectionTypeResolver.getCollectionParameterType(parameter);
if (valueClass == null) {
throw new IllegalArgumentException(
"Cannot generate variable name for non-typed Collection parameter type");
}
//设置为TRUE
pluralize = true;
}
else {
valueClass = parameter.getParameterType();
}
//获取名字,出去包名
String name = ClassUtils.getShortNameAsProperty(valueClass);
//如果pluralize为true,那么就在名字候命加上list字符串
return (pluralize ? pluralize(name) : name);
} @Override
public final WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
throws Exception {
//创建webdata 绑定
WebDataBinder dataBinder = createBinderInstance(target, objectName, webRequest);
if (this.initializer != null) {
this.initializer.initBinder(dataBinder, webRequest);
}
//开始调用绑定方法
initBinder(dataBinder, webRequest);
return dataBinder;
}
initBinder方法 public void initBinder(WebDataBinder binder, NativeWebRequest request) throws Exception {
for (InvocableHandlerMethod binderMethod : this.binderMethods) {
if (isBinderMethodApplicable(binderMethod, binder)) {
//跟前面调用方法是一样的,不过这次传入了一个提供的参数,那就是webDataBinder的实例,所以我们可以在@initBinder方法中添加一些校验器,编辑器等等操作。
Object returnValue = binderMethod.invokeForRequest(request, null, binder);
if (returnValue != null) {
throw new IllegalStateException("@InitBinder methods should return void: " + binderMethod);
}
}
}
} 创建了webDataBinder之后,并且如果我们在@initBinder注解的方法中做了一些事情,比如添加了校验器啥的,接下来的代码如下
if (arg != null) {
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
}
}
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); //校验
protected void validateIfApplicable(WebDataBinder binder, MethodParameter methodParam) {
Annotation[] annotations = methodParam.getParameterAnnotations();
for (Annotation ann : annotations) {
//只有注释了@valid的参数才会进行校验
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
//获取注解中value值,这些值可以最为校验分组用,SpringMVC的校验使用的JSR303校验和自定义校验器
Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann));
Object[] validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
//开始校验
binder.validate(validationHints);
break;
}
}
} //遍历校验器进行校验
public void validate(Object... validationHints) {
for (Validator validator : getValidators()) {
//使用JSR303的方式校验
if (!ObjectUtils.isEmpty(validationHints) && validator instanceof SmartValidator) {
((SmartValidator) validator).validate(getTarget(), getBindingResult(), validationHints);
}
else if (validator != null) {
//使用自定义校验器校验
validator.validate(getTarget(), getBindingResult());
}
}
} 好了,对于RequestBody注解的参数就是这么解析的。 来研究一下ModelAttributeMethodProcessor是怎么解析的 @Override
public boolean supportsParameter(MethodParameter parameter) {
//判断参数是否有@ModelAttribute注解
if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
return true;
}
else if (this.annotationNotRequired) {
return !BeanUtils.isSimpleProperty(parameter.getParameterType());
}
else {
return false;
}
} //解析参数
public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//获取参数名,先从注解的指定的名称找,如果没有就用Conventions.getVariableNameForParameter(parameter)方法获取参数名,这个在前面就已经使用过了
String name = ModelFactory.getNameForParameter(parameter);
//判断这个参数是否在MavContainer中已经存在了,如果存在就直接获取这个参数值,如果没有找到就去request中寻找参数
Object attribute = (mavContainer.containsAttribute(name) ?
mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, webRequest));
//创建WebDataBinder ,调用@initBinder注解的绑定方法
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
if (binder.getTarget() != null) {
//这里是绑定请求的参数
bindRequestParameters(binder, webRequest);
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
} // Add resolved attribute and BindingResult at the end of the model
Map<String, Object> bindingResultModel = binder.getBindingResult().getModel();
mavContainer.removeAttributes(bindingResultModel);
mavContainer.addAllAttributes(bindingResultModel); return binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);
} protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class);
ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
servletBinder.bind(servletRequest);
} public void bind(ServletRequest request) {
//解析创建成一个MutablePropertyValues
MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request);
//判断是否为MultipartRequest 类型,如果是就获取这种类型的请求
MultipartRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartRequest.class);
if (multipartRequest != null) {
bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
}
//获取url中的变量Map用url定义的参数值,如果已经在mpvs存在的参数将不会覆盖
addBindValues(mpvs, request);
//绑定参数
doBind(mpvs);
} //创建MutablePropertyValues时的解析,解析成一个去掉指定前缀的Map,当然这里没有设置前缀
public static Map<String, Object> getParametersStartingWith(ServletRequest request, String prefix) {
Assert.notNull(request, "Request must not be null");
Enumeration<String> paramNames = request.getParameterNames();
Map<String, Object> params = new TreeMap<String, Object>();
if (prefix == null) {
prefix = "";
}
while (paramNames != null && paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
if ("".equals(prefix) || paramName.startsWith(prefix)) {
String unprefixed = paramName.substring(prefix.length());
String[] values = request.getParameterValues(paramName);
if (values == null || values.length == 0) {
// Do nothing, no values found at all.
}
else if (values.length > 1) {
params.put(unprefixed, values);
}
else {
params.put(unprefixed, values[0]);
}
}
}
return params;
} 然后在传入这个paramMap到构造器
public MutablePropertyValues(Map<?, ?> original) {
// We can optimize this because it's all new:
// There is no replacement of existing property values.
if (original != null) {
this.propertyValueList = new ArrayList<PropertyValue>(original.size());
for (Map.Entry<?, ?> entry : original.entrySet()) {
//propertyValueList是一个list,存储着PropertyValue对象,这个对象存着请求参数的名称和对应的值。
this.propertyValueList.add(new PropertyValue(entry.getKey().toString(), entry.getValue()));
}
}
else {
this.propertyValueList = new ArrayList<PropertyValue>(0);
}
} protected void bindMultipart(Map<String, List<MultipartFile>> multipartFiles, MutablePropertyValues mpvs) {
for (Map.Entry<String, List<MultipartFile>> entry : multipartFiles.entrySet()) {
String key = entry.getKey();
List<MultipartFile> values = entry.getValue();
if (values.size() == 1) {
MultipartFile value = values.get(0);
//默认情况下会保存空的MultipartFiles,所以即使你的上传文件框没有上传文件,也会存在空的文件
if (isBindEmptyMultipartFiles() || !value.isEmpty()) {
mpvs.add(key, value);
}
}
else {
mpvs.add(key, values);
}
}
} 开始绑定参数
@Override
protected void doBind(MutablePropertyValues mpvs) {
//检查有default值前缀的参数
checkFieldDefaults(mpvs);
//检查有标记前缀的参数
checkFieldMarkers(mpvs);
真正绑定参数的方法
super.doBind(mpvs);
} checkFieldDefaults方法:
protected void checkFieldDefaults(MutablePropertyValues mpvs) {
//如果字段默认的前缀不为空,那么就去掉前缀,然后判断这个属性在对应的参数对象中是否可写,并且在mpvs中不存在这个属性参会加入到mvps中,并且移除之前的
if (getFieldDefaultPrefix() != null) {
String fieldDefaultPrefix = getFieldDefaultPrefix();
PropertyValue[] pvArray = mpvs.getPropertyValues();
for (PropertyValue pv : pvArray) {
if (pv.getName().startsWith(fieldDefaultPrefix)) {
String field = pv.getName().substring(fieldDefaultPrefix.length());
if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) {
mpvs.add(field, pv.getValue());
}
mpvs.removePropertyValue(pv);
}
}
}
}
这个方法和上面的是一样的道理
protected void checkFieldMarkers(MutablePropertyValues mpvs) {
if (getFieldMarkerPrefix() != null) {
String fieldMarkerPrefix = getFieldMarkerPrefix();
PropertyValue[] pvArray = mpvs.getPropertyValues();
for (PropertyValue pv : pvArray) {
if (pv.getName().startsWith(fieldMarkerPrefix)) {
String field = pv.getName().substring(fieldMarkerPrefix.length());
if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) {
Class<?> fieldType = getPropertyAccessor().getPropertyType(field);
mpvs.add(field, getEmptyValue(field, fieldType));
}
mpvs.removePropertyValue(pv);
}
}
}
} 接下来调用了 protected void doBind(MutablePropertyValues mpvs) {
//检查是否是运行的字段,这些字段都可以在@initBinder注解的方法中指定
checkAllowedFields(mpvs);
//判断是否为必须的字段
checkRequiredFields(mpvs);
//应用属性值
applyPropertyValues(mpvs);
} //应用指定的值到对应的对象中
protected void applyPropertyValues(MutablePropertyValues mpvs) {
try {
// Bind request parameters onto target object.
//绑定请求参数到目标参数中
getPropertyAccessor().setPropertyValues(mpvs, isIgnoreUnknownFields(), isIgnoreInvalidFields());
}
catch (PropertyBatchUpdateException ex) {
// Use bind error processor to create FieldErrors.
for (PropertyAccessException pae : ex.getPropertyAccessExceptions()) {
getBindingErrorProcessor().processPropertyAccessException(pae, getInternalBindingResult());
}
}
} 接下来就是对参数进行类型转换 return binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter); public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException { // Custom editor for this type?获取@initBinder注解的方法中自定义的参数编辑器
PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName); ConversionFailedException conversionAttemptEx = null; // No custom editor but custom ConversionService specified?
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
try {
//如果可以转换就进行转换
return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
}
catch (ConversionFailedException ex) {
// fallback to default conversion logic below
conversionAttemptEx = ex;
}
}
} Object convertedValue = newValue;
。。。。。。。。。。。。。。。。。。。。。。。(代码较长,省略) 当所有的参数都解析完毕后,调用方法
Object returnValue = doInvoke(args);
//如果不出例外,就直接使用放射方法调用
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
return getBridgedMethod().invoke(getBean(), args);
}
catch (IllegalArgumentException ex) {
assertTargetBean(getBridgedMethod(), getBean(), args);
String message = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
throw new IllegalStateException(getInvocationErrorMessage(message, args), ex);
}
catch (InvocationTargetException ex) {
// Unwrap for HandlerExceptionResolvers ...
Throwable targetException = ex.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException) targetException;
}
else if (targetException instanceof Error) {
throw (Error) targetException;
}
else if (targetException instanceof Exception) {
throw (Exception) targetException;
}
else {
String msg = getInvocationErrorMessage("Failed to invoke controller method", args);
throw new IllegalStateException(msg, targetException);
}
}
}

handlerAdapter与方法调用(参数的解析)的更多相关文章

  1. JAVA方法调用中的解析与分派

    JAVA方法调用中的解析与分派 本文算是<深入理解JVM>的读书笔记,参考书中的相关代码示例,从字节码指令角度看看解析与分派的区别. 方法调用,其实就是要回答一个问题:JVM在执行一个方法 ...

  2. Atitit  记录方法调用参数上下文arguments

    Atitit  记录方法调用参数上下文arguments 1.1. java  java8  新的对象Parameter LocalVariableTable 本地变量表 MethodParamete ...

  3. 关于Cocos2d-x中addchild和removeChild方法的参数的解析

    一.addchild virtual void addchild( Node * child , int localZOrder , int tag )添加一个子节点到容器中,有Z轴顺序和一个标记. ...

  4. SetACL 使用方法详细参数中文解析

    示例: SetACL.exe c:\nihao /dir /deny everyone /read_ex 设置E:\wxDesktop 文件夹 everyone 用户为读取和运行权限 SetACL M ...

  5. springMVC框架核心方法调用源码解析

  6. 深入解析多态和方法调用在JVM中的实现

    深入解析多态和方法调用在JVM中的实现 1. 什么是多态 多态(polymorphism)是面向对象编程的三大特性之一,它建立在继承的基础之上.在<Java核心技术卷>中这样定义: 一个对 ...

  7. java类加载机制及方法调用

    类加载机制 概述 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading).验证(Verification).准备(Preparation).解析(Resoluti ...

  8. JVM(十二):方法调用

    JVM(十二):方法调用 在 JVM(七):JVM内存结构 中,我们说到了方法执行在何种内存结构上执行:Java 方法活动在虚拟机栈中的栈帧上,栈帧的具体结构在内存结构中已经详细讲解过了,下面就让我们 ...

  9. Java方法调用机制

    最近在编程时,修改方法传入对象的对象引用,并没有将修改反映到调用方法中.奇怪为什么结果没有变化,原因是遗忘了Java对象引用和内存分配机制.本文介绍3个点: ① 该问题举例说明 ② 简要阐述Java内 ...

随机推荐

  1. ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据(转)

    转载来源:https://www.cnblogs.com/sunddenly/p/4092654.html 引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...

  2. spring 5.x 系列第1篇 —— springmvc基础 (xml配置方式)

    文章目录 一.搭建hello spring工程 1.1 项目搭建 1.2 相关配置讲解 二.配置自定义拦截器 三.全局异常处理 四.参数绑定 4.1 参数绑定 4.2 关于日期格式转换的三种方法 五. ...

  3. Google浏览器插件之闪存过滤器

    一件很有意思的事情引发的无聊尝试. 博客园有个很有趣的功能,就是闪存,翻阅到07年园长对闪存的定义:      记录一闪而过的想法,高兴或者不高兴都可以发一下.我用这个一直以来的想法就是,想到点啥发点 ...

  4. Linux 配置 history 命令显示操作时间、用户和登录 IP

    一.在配置文件中(/etc/bashrc 或者 /etc/profile 或者~/.bash_profile 或者 ~/.bashrc)添加如下配置 #vim /etc/bashrc    // 进到 ...

  5. TCP/IP协议栈---网络基础篇(3)

    TCP/IP协议栈 在网络中实际使用的是TCP/IP,OSI是参考模型. TCP/IP协议栈 – 是由一组不同功能的协议组合在一起构成的协议栈 – 利用一组协议完成OSI所实现的功能 应用层协议 传输 ...

  6. 学习kafka自己发生的几个小错误记录

    一.  The method iterator() is ambiguous ConsumerIterator<byte[],byte[]> it =stream.iterator(); ...

  7. C/C++应用程序内存泄漏检查统计方案

    一.前绪 C/C++程序给某些程序员的几大印象之一就是内存自己管理容易泄漏容易崩,笔者曾经在一个产品中使用C语言开发维护部分模块,只要产品有内存泄漏和崩溃的问题,就被甩锅“我的程序是C#开发的内存都是 ...

  8. C# 异步转同步 TaskCompletionSource

    本文通过TaskCompletionSource,实现异步转同步 首先有一个异步方法,如下异步任务延时2秒后,返回一个结果 private static async Task<string> ...

  9. code forces 1176 D. Recover it!

    原题链接:https://codeforces.com/contest/1176/problem/D 题目大意是 两个个数列 a , b 相同 ,如果 ai 是素数,那么b数列里添加上第ai个素数(2 ...

  10. canvas实现有递增动画的环形进度条

    哈?标题不知道啥意思? 老规矩,直接看图! 效果如下: 高清大图! 码农多年,老眼昏花,动图看不清?!那就看静态截图!!! 不同分值效果如下:          看完了卖家秀,我们来看产品的制作过程吧 ...