当前位置: 首页 > news >正文

网站开发个人简介范文/域名解析ip

网站开发个人简介范文,域名解析ip,娄底建设企业网站,桂林做网站多少钱Spring MVC中使用HandlerMethodArgumentResolver策略接口来定义处理器方法参数解析器,PathVariable使用的是PathVariableMapMethodArgumentResolver和PathVariableMethodArgumentResolver,接下来一起来深入了解一下其源码实现。 类结构 类解析 HandlerMe…

  Spring MVC中使用HandlerMethodArgumentResolver策略接口来定义处理器方法参数解析器,@PathVariable使用的是PathVariableMapMethodArgumentResolverPathVariableMethodArgumentResolver,接下来一起来深入了解一下其源码实现。

  类结构

在这里插入图片描述

在这里插入图片描述

  类解析

  HandlerMethodArgumentResolverAbstractNamedValueMethodArgumentResolver是解析策略的上层定义和抽象,关于这两个类可以参照《Spring 注解面面通 之 @CookieValue参数绑定源码解析》中的解析。

  PathVariableMapMethodArgumentResolverPathVariableMethodArgumentResolver则是用来针对不用类型的方法参数的解析。

  1) PathVariableMapMethodArgumentResolver实现了HandlerMethodArgumentResolversupportsParameter(...)resolveArgument(...)方法。

  PathVariableMapMethodArgumentResolver相对比较简单,但在某些条件成立的情况下才会使用此类进行解析:

  ① 方法参数由@PathVariable注解注释。

​  ② 方法参数类型必须是Map类型。

  ③ 注释方法参数的@PathVariablevalue属性不能有值。

  resolveArgument(...)解析参数从NativeWebRequest.getAttribute( ​ HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST)获得。

package org.springframework.web.servlet.mvc.method.annotation;import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerMapping;/*** 解析用@PathVariable注释的Map方法参数,其中注解不能指定路径变量名. * 创建的Map包含所有URI模板名称/值对.*/
public class PathVariableMapMethodArgumentResolver implements HandlerMethodArgumentResolver {/*** 检查方法参数,方法参数需包含@PathVariable注解、为Map类型参数,且@PathVariable的value属性不可有值.*/@Overridepublic boolean supportsParameter(MethodParameter parameter) {PathVariable ann = parameter.getParameterAnnotation(PathVariable.class);return (ann != null && Map.class.isAssignableFrom(parameter.getParameterType()) &&!StringUtils.hasText(ann.value()));}/*** 返回包含所有URI模板变量的映射或空映射.*/@Overridepublic Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {// 获取NativeWebRequest中存储的HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE的值.@SuppressWarnings("unchecked")Map<String, String> uriTemplateVars =(Map<String, String>) webRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);if (!CollectionUtils.isEmpty(uriTemplateVars)) {return new LinkedHashMap<>(uriTemplateVars);}else {return Collections.emptyMap();}}}

  2) PathVariableMethodArgumentResolver继承自抽象AbstractNamedValueMethodArgumentResolver(可以参照《Spring 注解面面通 之 @CookieValue参数绑定源码解析》),同时实现了UriComponentsContributor(主要用来参与URI的编解码)。

  PathVariableMethodArgumentResolver相对PathVariableMapMethodArgumentResolver来说,类内容较多,但关注主要实现,也是很清晰的,其在某些条件成立的情况下才会使用此类进行解析:

  ① 方法参数由@PathVariable注解注释。

​  ② 当方法参数类型是Map时,要求其必须由@PathVariable注解注释,同时@PathVariablevalue属性必须有值。

  resolveArgument(...)解析参数从NativeWebRequest.getAttribute( ​ HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST)获得。

package org.springframework.web.servlet.mvc.method.annotation;import java.util.HashMap;
import java.util.Map;import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.method.support.UriComponentsContributor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.View;
import org.springframework.web.util.UriComponentsBuilder;/*** 解析用@PathVariable注释的方法参数.** @PathVariable 用于从URI模板变量解析的命名值.* 它始终是必需的,并且没有可依赖的默认值.** 如果方法参数类型是Map,则注释中指定的名称将用于解析URI变量字符串值.* 如果注册了Converter或PropertyEditor,则通过类型转换将该值转换为Map.** 调用WebDataBinder将类型转换应用于尚未与方法参数类型匹配的已解析路径变量值.*/
public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolverimplements UriComponentsContributor {/*** String类型描述符.*/private static final TypeDescriptor STRING_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(String.class);/*** 检查方法参数.* 方法参数需包含@PathVariable.* 若参数类型为Map,则@PathVariable的value属性必须有值.*/@Overridepublic boolean supportsParameter(MethodParameter parameter) {// 方法参数是否含有@PathVariable注解.if (!parameter.hasParameterAnnotation(PathVariable.class)) {return false;}// 方法参数类型是Map、且含有@PathVariable注解、@PathVariable注解的value属性必须有值.if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {PathVariable pathVariable = parameter.getParameterAnnotation(PathVariable.class);return (pathVariable != null && StringUtils.hasText(pathVariable.value()));}return true;}/*** 创建NamedValueInfo.*/@Overrideprotected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {PathVariable ann = parameter.getParameterAnnotation(PathVariable.class);Assert.state(ann != null, "No PathVariable annotation");return new PathVariableNamedValueInfo(ann);}/*** 解析参数值.*/@Override@SuppressWarnings("unchecked")@Nullableprotected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {// 获取NativeWebRequest中存储的HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE的值.Map<String, String> uriTemplateVars = (Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);return (uriTemplateVars != null ? uriTemplateVars.get(name) : null);}/*** 处理缺失参数异常.*/@Overrideprotected void handleMissingValue(String name, MethodParameter parameter) throws ServletRequestBindingException {throw new MissingPathVariableException(name, parameter);}/*** 处理已解析的参数值.*/@Override@SuppressWarnings("unchecked")protected void handleResolvedValue(@Nullable Object arg, String name, MethodParameter parameter,@Nullable ModelAndViewContainer mavContainer, NativeWebRequest request) {String key = View.PATH_VARIABLES;int scope = RequestAttributes.SCOPE_REQUEST;Map<String, Object> pathVars = (Map<String, Object>) request.getAttribute(key, scope);if (pathVars == null) {pathVars = new HashMap<>();request.setAttribute(key, pathVars, scope);}pathVars.put(name, arg);}/*** 处理方法参数.*/@Overridepublic void contributeMethodArgument(MethodParameter parameter, Object value,UriComponentsBuilder builder, Map<String, Object> uriVariables, ConversionService conversionService) {if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {return;}PathVariable ann = parameter.getParameterAnnotation(PathVariable.class);String name = (ann != null && !StringUtils.isEmpty(ann.value()) ? ann.value() : parameter.getParameterName());String formatted = formatUriValue(conversionService, new TypeDescriptor(parameter.nestedIfOptional()), value);uriVariables.put(name, formatted);}/*** 格式化URI模板变量值.* @param cs 类型转换服务.* @param sourceType 源类型描述符.* @param value 待转换的值.* @return 转换后的值.*/@Nullableprotected String formatUriValue(@Nullable ConversionService cs, @Nullable TypeDescriptor sourceType, Object value) {if (value instanceof String) {return (String) value;}else if (cs != null) {return (String) cs.convert(value, sourceType, STRING_TYPE_DESCRIPTOR);}else {return value.toString();}}/*** PathVariableNamedValueInfo.*/private static class PathVariableNamedValueInfo extends NamedValueInfo {public PathVariableNamedValueInfo(PathVariable annotation) {super(annotation.name(), annotation.required(), ValueConstants.DEFAULT_NONE);}}}

  3) NativeWebRequest
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE属性

  分析过PathVariableMapMethodArgumentResolverPathVariableMethodArgumentResolver源码后,发现URI模板变量都是从NativeWebRequest属性中获得,那么是在哪里进行的URI模板变量解析呢?

  ① 涉及URI模板变量解析的调用过程。

DispatcherServlet.doDispatch(...) --调用--> 
DispatcherServlet.getHandler(...) --调用--> 
AbstractHandlerMapping.getHandler(...) --调用--> 
AbstractHandlerMethodMapping.getHandlerInternal(...) --调用--> 
AbstractHandlerMethodMapping.lookupHandlerMethod(...) --调用--> 
RequestMappingInfoHandlerMapping.handleMatch(...) --调用--> 
解析URI模板变量,并设置到NativeWebRequest属性中

  ② 查看RequestMappingInfoHandlerMapping.handleMatch(...)方法,可以发现,在这里对URI模板变量进行了解析,并设置到NativeWebRequest属性中。除了对URI模板变量处理外,还对矩阵变量、可生产媒体类型进行了处理,同样设置到NativeWebRequest属性中。

/*** 暴露URI模板参数、矩阵参数和可生成的媒体类型.*/
@Override
protected void handleMatch(RequestMappingInfo info, String lookupPath, HttpServletRequest request) {super.handleMatch(info, lookupPath, request);String bestPattern;Map<String, String> uriVariables;Map<String, String> decodedUriVariables;Set<String> patterns = info.getPatternsCondition().getPatterns();// 若不存在匹配模式,则均设置为空.if (patterns.isEmpty()) {bestPattern = lookupPath;uriVariables = Collections.emptyMap();decodedUriVariables = Collections.emptyMap();}else {bestPattern = patterns.iterator().next();// 解析URI模板参数.uriVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath);// 对URI模板参数进行解码.decodedUriVariables = getUrlPathHelper().decodePathVariables(request, uriVariables);}// 设置匹配模式到HttpServletRequest的BEST_MATCHING_PATTERN_ATTRIBUTE.request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);// 设置URI模板参数到HttpServletRequest的HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE.request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, decodedUriVariables);// 处理矩阵参数.if (isMatrixVariableContentAvailable()) {// 提取矩阵参数.Map<String, MultiValueMap<String, String>> matrixVars = extractMatrixVariables(request, uriVariables);// 设置矩阵参数到HttpServletRequest的HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE.request.setAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, matrixVars);}// 处理可生成的媒体类型.if (!info.getProducesCondition().getProducibleMediaTypes().isEmpty()) {// 获取可生成的媒体类型.Set<MediaType> mediaTypes = info.getProducesCondition().getProducibleMediaTypes();// 设置可生成媒体类型到HttpServletRequest的PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE.request.setAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, mediaTypes);}
}

  总结

​  以上便是@PathVariable对方法参数解析的全过程,对于理解@PathVariable原理来说还是十分有用处的,更有利于在实际开发中解决那些疑难杂症。

  若文中存在错误和不足,欢迎指正!

http://www.lbrq.cn/news/1357111.html

相关文章:

  • 网站开发服务承诺书/推广员是做什么的
  • 武汉新闻网/网站首页的优化
  • asp网站开发人员招聘/如何申请一个网站域名
  • 大访问量的网站怎么做优化/网站接广告平台
  • 网站建设基本流程心得/网络营销的基本流程
  • 深圳品牌网站设计推广/网站设计与网页制作
  • 平台网站怎么做的好/b站怎么推广
  • phpnow wordpress/网络推广优化
  • 史上最强大的搜索神器/seo整站优化多少钱
  • 做相册网站/网络营销的手段有哪些
  • 目前最好的免费网站/哈尔滨seo推广优化
  • 聊城冠县网站建设/三叶草gw9356
  • 化州网站建设/网络营销特点
  • 深圳网站建设 贴吧/百度收录快速提交
  • 海口模板建站平台/真实有效的优化排名
  • 重庆市建设工程造价站/网络推广怎么找客户资源
  • 网站建设公司yu/电商网站卷烟订货流程
  • 辽宁做网站和优化哪家好/免费线上培训平台
  • 高端网站制作价格/营销型网站建设企业
  • 自己做的网站只能用谷歌浏览器打开/怎么设置自己的网站
  • 免费的源码分享网站/google下载官网
  • 做芯片代理哪个网站推广/百度竞价推广的技巧
  • 社区微网站建设需求分析/电脑优化
  • 电商的网站/网店营销策划方案范文
  • 苏州做网站公司/杭州推广公司排名
  • 建设检测人员证书查询网站/网络运营培训班
  • 平面设计师网站/seo技术快速网站排名
  • 网站开发培训学院/付费推广
  • 发卡网站怎么做/百度搜索趋势
  • 建设一个下载网站/站长统计app下载免费
  • kubeadm-k8s 中的 etcd 备份与恢复
  • 微软的BitLocker加密
  • leetcode-python-删除链表的倒数第 N 个结点
  • VUE-第二季-02
  • 【OS】操作系统概述
  • Array容器学习