JavaWeb @PathVariable 设置路由变量的默认值

拼搏现实的明天。 2022-11-08 14:15 499阅读 0赞

解决

如果我们遇到的问题相同,那你看完这段代码就可以知道解决方法。

  1. import org.springframework.web.bind.annotation.GetMapping;
  2. import org.springframework.web.bind.annotation.PathVariable;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. @RestController
  6. @RequestMapping("/api/user")
  7. public class UserController {
  8. @GetMapping(path = { "/{userId}", "/"})
  9. public void user(@PathVariable(value = "userId", required = false) String uid) {
  10. if (uid == null) {
  11. uid = "默认的id值";
  12. }
  13. String id = uid; // 获取到值
  14. // do something.
  15. }
  16. }

核心的两步:
@RequestMapping注解的path属性值可以是字符串数组,即多个URL模式。
@PathVariable注解的required属性表示该路由变量是否是必须的,需要设置为false

Intro

首先,依赖详情:org.springframework.spring-web:5.3.4
注解路径:org.springframework.web.bind.annotation.PathVariable

其次:HTTP 客户端向服务端传递参数的4种方式 SpringMVC的对应接收方式

设计RESTful风格的API如下
get /api/user/{userId}

get /api/user/1001 表示获取id为1001的用户信息
get /api/user/1003 表示获取id为1003的用户信息
get /api/user/1004 表示获取id为1004的用户信息

如果接口的调用方(前段/或其他消费端)未传入userId,能否在服务的提供段设置默认值?即:
get /api/user 后台会获取一个默认的用户信息(如id为1000的用户信息)
可以。

解决

  • V1

    @RequestMapping(path = “/api/user/{userId}”)
    public void user(@PathVariable(value = “userId”) String uid) {

    1. String id = uid; // 获取到值
    2. // do something.

    }

V1的缺点是: 只能处理 /api/user/xxx这样的请求,而对于/api/user这样的请求,他根本不处理(非己之责)

  • V2

    @RequestMapping(path = { “/api/user/{userId}”, “/api/user”})
    public void user(@PathVariable(value = “userId”, required = false) String uid) {

    1. if (uid == null) {
    2. uid = "默认的id值";
    3. }
    4. String id = uid; // 获取到值
    5. // do something.

    }

首先,@RequestMapping注解的path属性是这样定义的:

  1. @AliasFor("value")
  2. String[] path() default { };

即可以设置请求映射规则为对多个path值进行拦截处理。

只改path还不够。
还需要修改@PathVariablerequired属性为false
这样即使不传入这个路由变量。也可以被该方法拦截。

  • V3

通常,在Controller类上使用注解@RequestMapping指定基本路径,
而对于该控制器中的具体方法,可以使用以下几种指定了请求方法的、带有请求映射功能的注解去标记。

@PostMapping 增
@DeleteMapping 删
@PutMapping 改
@GetMapping 查
@PatchMapping 部分字段修改

修改后:

  1. import org.springframework.web.bind.annotation.GetMapping;
  2. import org.springframework.web.bind.annotation.PathVariable;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. @RestController
  6. @RequestMapping("/api/user")
  7. public class UserController {
  8. @GetMapping(path = { "/{userId}", "/"})
  9. public void user(@PathVariable(value = "userId", required = false) String uid) {
  10. if (uid == null) {
  11. uid = "默认的id值";
  12. }
  13. String id = uid; // 获取到值
  14. // do something.
  15. }
  16. }

这样,当请求格式为get /api/user/xxx/api/user时,都会进入该方法,执行一套逻辑。
相当于设置了路由变量{userId}的默认值。

思考

对处于路由路径path末端的路由单节路由变量可设置默认值,
那么对于路由路径path中,中间部分的某节路由变量,能否也设置默认值?

  1. @RequestMapping(path = { "/api/user/{userId}/profile", "/api/user/profile"})
  2. public void profile(@PathVariable(value = "userId", required = false) String uid) {
  3. System.out.println("拿到的路由变量:" + uid);
  4. if (uid == null) {
  5. uid = "默认的id值";
  6. }
  7. String id = uid;
  8. }

经测试可以。

get /api/user/id2002/profile可以返回userId为id2002的用户profile。
get /api/user/profile也可以返回一个userId为所设置默认值的用户profile。

源码

  1. package org.springframework.web.bind.annotation;
  2. import java.lang.annotation.Documented;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. import org.springframework.core.annotation.AliasFor;
  8. /** * Annotation which indicates that a method parameter should be bound to a URI template * variable. Supported for {@link RequestMapping} annotated handler methods. * * <p>If the method parameter is {@link java.util.Map Map<String, String>} * then the map is populated with all path variable names and values. * * @author Arjen Poutsma * @author Juergen Hoeller * @since 3.0 * @see RequestMapping * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter */
  9. @Target(ElementType.PARAMETER)
  10. @Retention(RetentionPolicy.RUNTIME)
  11. @Documented
  12. public @interface PathVariable {
  13. /** * Alias for {@link #name}. */
  14. @AliasFor("name")
  15. String value() default "";
  16. /** * The name of the path variable to bind to. * @since 4.3.3 */
  17. @AliasFor("value")
  18. String name() default "";
  19. /** * Whether the path variable is required. * <p>Defaults to {@code true}, leading to an exception being thrown if the path * variable is missing in the incoming request. Switch this to {@code false} if * you prefer a {@code null} or Java 8 {@code java.util.Optional} in this case. * e.g. on a {@code ModelAttribute} method which serves for different requests. * @since 4.3.3 */
  20. boolean required() default true;
  21. }

可以看到@PathVariable注解有三个属性值,其中namevalue互为同义词/别名。
required就是我们利用到的属性。

发表评论

表情:
评论列表 (有 0 条评论,499人围观)

还没有评论,来说两句吧...

相关阅读

    相关 配置默认

    配置接口IP地址并通过静态路由、默认路由配置实现全网互通 拓扑图如下;按照图上内容配置环境,pc机IP、子网掩码、网关 ![拓扑.PNG][.PNG] 路由器R1