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

网站可信淘宝代运营1个月多少钱

网站可信,淘宝代运营1个月多少钱,广州网站建设联系电话,视频网站咋么做前言 PathVariable 注解是我们进行JavaEE开发,最常见的几个注解之一,这篇博文我们以案例和源码相结合,帮助大家更好的了解PathVariable 注解 使用案例 1.获取 URL 上的值 RequestMapping("/id/{id}") public Object getId(Path…

前言

@PathVariable 注解是我们进行JavaEE开发,最常见的几个注解之一,这篇博文我们以案例和源码相结合,帮助大家更好的了解@PathVariable 注解

使用案例

1.获取 URL 上的值

@RequestMapping("/id/{id}")
public Object getId(@PathVariable(value = "id") Integer id) {return id;
}

2.获取 URL 上的多个值

多个值以 / 分割,可以相邻也可以不相邻

2.1 多个值相邻
@GetMapping("/info/{id}/{name}")
public Object getInfo(@PathVariable(value = "id") Integer id, @PathVariable(value = "name") String name) {return "id:" + id + ",name:" + name;
}

2.1 多个值不相邻
@GetMapping("/info/{id}/delimiter/{name}")
public Object getDelimiterInfo(@PathVariable(value = "id") Integer id, @PathVariable(value = "name") String name) {return "id:" + id + ",name:" + name;
}

3. 不指定value(name)

@RequestMapping("/default/{id}")
public Object getDefaultId(@PathVariable Integer id) {return id;
}

4. 使用 Map 接受多个 URL 上的值

@GetMapping("/info_map/{id}/{name}")
public Object getInfoToMap(@PathVariable Map<String, Object> map) {StringBuilder sb = new StringBuilder();map.forEach((key, value) -> sb.append(key).append(":").append(value).append(","));return sb.substring(0, sb.length() - 1);
}

源码解析

 InvocableHandlerMethod#getMethodArgumentValues

参数的处理分为两个阶段:

  1. 判断当前环境中存在的resolvers,是否支持解析当前参数
  2. 处理参数

判断是否支持解析当前参数

我的环境中存在27个resolvers,通过命名我们大概可以猜测出 PathVariableMethodArgumentResolverPathVariableMapMethodArgumentResolver 是处理 @PathVariable 注解的 resolver 

PathVariableMethodArgumentResolver#supportsParameter
@Override
public boolean supportsParameter(MethodParameter parameter) {if (!parameter.hasParameterAnnotation(PathVariable.class)) {return false;}if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {PathVariable pathVariable = parameter.getParameterAnnotation(PathVariable.class);return (pathVariable != null && StringUtils.hasText(pathVariable.value()));}return true;
}

如果参数存在 @PathVariable 注解,并且指定了 value(name),则支持解析

PathVariableMapMethodArgumentResolver#supportsParameter
@Override
public boolean supportsParameter(MethodParameter parameter) {PathVariable ann = parameter.getParameterAnnotation(PathVariable.class);return (ann != null && Map.class.isAssignableFrom(parameter.getParameterType()) &&!StringUtils.hasText(ann.value()));
}

如果参数存在 @PathVariable 注解,并且未指定了 value(name),则支持解析

处理参数

接来下我们将重点分析 PathVariableMethodArgumentResolver 的 resolveArgument 方法,PathVariableMapMethodArgumentResolver 的 resolveArgument 方法大家可以自行阅读,相关源码如下:

大概分为以下六个步骤:

  1. 构建NamedValueInfo对象
  2. 处理Spel表达式
  3. 解析参数
  4. 处理默认值
  5. 类型转换
  6. 给 Request 域赋值
构建NamedValueInfo对象

创建NamedValueInfo对象

@PathVariable 注解的默认值是 ValueConstants.DEFAULT_NONE,并且无法手动设置

更新NamedValueInfo对象

updateNamedValueInfo 方法主要针对 @PathVariable 注解未指定 value(name)的情况,比如上文中的案例3,NamedValueInfo对象的 name 属性值为方法的参数名

处理Spel表达式

默认情况下,@PathVariable 注解是不支持解析 Spel 表达式的,我们通过源码分析一下。

如果 resolver 的 configurableBeanFactory 或 expressionContext 属性为 null ,则不进行Spel表达式的解析工作

RequestMappingHandlerAdapter#getDefaultArgumentResolvers

默认注册 PathVariableMethodArgumentResolver 使用的是无参构造方法,也就是  configurableBeanFactory 和 expressionContext 属性为 null,所以默认情况下,@PathVariable 注解不支持解析Spel表达式。可能有的小伙伴说我可以利用 WebMvcConfigurer ,自定义一个resolver,这里存在一个优先级问题,自定义的 resolver 优先级低于 mvc 手动注册的 resolver,所以一般情况下 @PathVariable 注解都不支持解析Spel表达式

我们可以看到手动注册的 resolver 优先级很低,一般情况下都是利用 mvc 内置的 resolver 进行解析

如何让 @PathVariable 注解支持解析 Spel 表达式 ?
替换内置的 PathVariableMapMethodArgumentResolver
@SpringBootApplication
@PropertySource("classpath:keys.properties")
public class BootApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(BootApplication.class);ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();RequestMappingHandlerAdapter adapter = context.getBean(RequestMappingHandlerAdapter.class);List<HandlerMethodArgumentResolver> resolvers = adapter.getArgumentResolvers();if (!CollectionUtils.isEmpty(resolvers)) {try {List<HandlerMethodArgumentResolver> newResolvers = new ArrayList<>();for (HandlerMethodArgumentResolver resolver : resolvers) {if (resolver instanceof PathVariableMethodArgumentResolver) {PathVariableMethodArgumentResolver pathVariableMethodArgumentResolver = new PathVariableMethodArgumentResolver();Field factoryField = AbstractNamedValueMethodArgumentResolver.class.getDeclaredField("configurableBeanFactory");factoryField.setAccessible(true);factoryField.set(pathVariableMethodArgumentResolver, beanFactory);Field expressionField = AbstractNamedValueMethodArgumentResolver.class.getDeclaredField("expressionContext");expressionField.setAccessible(true);expressionField.set(pathVariableMethodArgumentResolver, new BeanExpressionContext(beanFactory, new RequestScope()));newResolvers.add(pathVariableMethodArgumentResolver);} else {newResolvers.add(resolver);}}adapter.setArgumentResolvers(Collections.unmodifiableList(newResolvers));} catch (Exception ignore) {}}}
}

这里我们引用了一个 keys.properties 文件,为下文中演示解析Spel表达式做准备,文件明细如下

key=a
解析 ${}
@RequestMapping("/spel_1/{a}/{b}")
public Object spel1(@PathVariable(value = "${key}") String key) {return key;
}

解析 #{}

创建 RequestKey

@Component
public class RequestKey {private String key = "b";public String getKey() {return key;}public void setKey(String key) {this.key = key;}
}

接口及响应

@RequestMapping("/spel_2/{a}/{b}")
public Object spel2(@PathVariable(value = "#{requestKey['key']}") String key) {return key;
}

参数解析

主要就是获取 URL 上的值

处理默认值

@PathVariable 注解不支持设置默认值,源码这里又处理默认值,感觉有点突兀。其实这里使用了模板模式,@RequestParam 注解的处理步骤是和 @PathVariable 注解一致的,然而 @RequestParam 注解是可以设置默认值的。我的上一篇博文写了@RequestParam 注解的使用和源码解析,有兴趣的小伙伴可以阅读一下,它们的处理流程基本是一致的,就是细节有差别。博文链接 : @RequestParam注解的使用及源码解析

类型转换

SpringBoot 会提前内置很多 convert,当存在一个 convert 可以将当前类型转换为目标类型,则会进行转换。案例演示:

创建实体类 Dog

public class Dog {private String name;public Dog(String name) {this.name = name;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +'}';}
}

创建配置类 WebConfig

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverter(new Converter<String, Dog>() {@Overridepublic <U> Converter<String, U> andThen(Converter<? super Dog, ? extends U> after) {return Converter.super.andThen(after);}@Overridepublic Dog convert(String source) {return new Dog(source);}});}}

接口及响应

@GetMapping("/convert/{dog}")
public String getDog(@PathVariable(value = "dog") Dog dog) {return dog.toString();
}

给 Request 域赋值

案例演示
@GetMapping("/attribute/{id}")
public String getAttribute(@PathVariable(value = "id") Integer id, HttpServletRequest request) {return request.getAttribute(View.PATH_VARIABLES).toString();
}

http://www.fp688.cn/news/144425.html

相关文章:

  • 网站发送邮件连接怎么做百度账号快速注册入口
  • 俄罗斯代购网站免费二级域名平台
  • 35互联做网站好吗东莞营销网站建设
  • 网站公告模板代码宁德市公共资源交易中心
  • 建设银行网站网页丢失关键词优化推广公司
  • 英文b2c网站建设百度网页网址
  • 珠海市网站建设公司推广资源seo
  • 深圳罗湖网站设计搭建网站
  • 网站建设发布设需求抖音seo搜索引擎优化
  • 烟台网站制作手机端seo
  • 做直播网站宽带朋友圈营销
  • 国内做网站的公司二级域名网址查询
  • 江苏神禹建设有限公司网站资源网站优化排名软件公司
  • 宿迁网站建设报价各大搜索引擎提交入口
  • 天津网站建设座机号灰色行业怎么推广引流
  • 怎样做联盟网站想做电商怎么入手
  • 外贸网站建设怎么制作聊城seo整站优化报价
  • 网站制作源码百度关键词优化推广
  • 深圳公司 网站建设香港疫情最新情况
  • 网站管理建站搜索引擎优化策略不包括
  • 教你做吃的网站江门seo网站推广
  • 大理公司网站建设百度推荐现在为什么不能用了
  • 网站成本网站流量统计
  • 北京校园网站建设种子资源
  • 做文案看什么网站在运营中seo是什么意思
  • 素材网站的图可以做海报吗百度竞价关键词价格查询工具
  • 个人主体可以做网站吗百度收录怎么查询
  • 做新疆网站应该做哪方面的长沙网站推广和优化
  • 重庆江北营销型网站建设公司推荐山东seo推广
  • 网站详情页怎么做成品网站1688入口网页版怎样