首页 > 解决方案 > 是否可以有条件地在@RequestParam 中分配Required 的值?

问题描述

我的控制器中有 2 个 @RequestParam 参数。我想根据条件设置两个参数的必需值。条件可能是,如果传递了一个参数,则必须传递另一个参数。所以将 other 的 required 设置为 true ,反之亦然。否则,如果没有传递任何参数,则将两者都设置为 false。

@RestController
public class TestController {

@GetMapping("/test")
public void test(@RequestParam(value = "a", required = (b !=null) String a, 
@RequestParam(value = "b", required = (a !=null) )  String b,) {
     {

     }

}

在@RequestParam() 中使用变量名的语法是错误的,但我想解释一下我想要什么。

标签: javaspringrestspring-boot

解决方案


您可以使用以下 2 种方式之一来执行此操作:

  1. 使用 Spring AOP 并为该请求映射创建一个环绕方面
  2. 使用 HandlerInterceptorAdapter 拦截给定 URI 的请求

1.使用Spring AOP

创建如下注释:

public @interface RequestParameterPairValidation {

}

然后你可以用它来注释你的请求映射方法:

@GetMapping("/test")
@RequestParameterPairValidation
public void test(
   @RequestParam(value = "a", required = false) String a, 
   @RequestParam(value = "b", required = false)  String b) {
      // API code goes here...
}

围绕注释创建一个方面。就像是:

@Aspect
@Component
public class RequestParameterPairValidationAspect {
    @Around("@annotation(x.y.z.RequestParameterPairValidation) && execution(public * *(..))")
    public Object time(final ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] requestMappingArgs = joinPoint.getArgs();
        String a = (String) requestMappingArgs[0];
        String b = (String) requestMappingArgs[1];

        boolean requestIsValid = //... execute validation logic here

        if (requestIsValid) {
           return joinPoint.proceed();
        } else {
           throw new IllegalArgumentException("illegal request");
        }
    }
}

400 BAD REQUEST请注意,由于请求无效,因此返回此处是一个不错的选择。当然,这取决于上下文,但这是一般的经验法则。

2.使用HandlerInterceptorAdapter

创建一个新的拦截器映射到您想要的 URI(在本例中/test):

@Configuration  
public class CustomInterceptor extends WebMvcConfigurerAdapter  {  

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       registry
         .addInterceptor(new CustomRequestParameterPairInterceptor())
         .addPathPatterns("/test");
    }
} 

在自定义拦截器中定义验证逻辑:

public class CustomRequestParameterPairInterceptor extends HandlerInterceptorAdapter {

    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object obj, Exception exception) throws Exception {

    }

    @Override
    public void postHandle(HttpServletRequest req, HttpServletResponse res, Object obj, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
       // Run your validation logic here
    }
}

我会说第二个选项是最好的,因为您可以直接控制请求的答案。在这种情况下,它可能是 a400 BAD REQUEST或任何其他对您的情况更有意义的东西。


推荐阅读