为了账号安全,请及时绑定邮箱和手机立即绑定

是否可以有条件地在@RequestParam 中分配Required 的值?

是否可以有条件地在@RequestParam 中分配Required 的值?

慕娘9325324 2022-06-04 10:59:08
我的控制器中有 2 个 @RequestParam 参数。我想根据条件设置两个参数的必需值。条件可能是,如果传递了一个参数,则必须传递另一个参数。所以将 other 的 required 设置为 true ,反之亦然。否则,如果没有传递任何参数,则将两者都设置为 false。@RestControllerpublic class TestController {@GetMapping("/test")public void test(@RequestParam(value = "a", required = (b !=null) String a, @RequestParam(value = "b", required = (a !=null) )  String b,) {     {     }}在@RequestParam() 中使用变量名的语法是错误的,但我想解释一下我想要什么。
查看完整描述

3 回答

?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

您可以使用以下 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或任何其他对您的情况更有意义的东西。


查看完整回答
反对 回复 2022-06-04
?
holdtom

TA贡献1805条经验 获得超10个赞

您可以在这里以智能的方式使用 Optional,如下所示:


@GetMapping("/test")

@RequestParameterPairValidation

public void test(@RequestParam("a") Optional<String> a,

    @RequestParam("b") Optional<String> b){



    String aVal = a.isPresent() ? a.get() : null;

    String bVal = b.isPresent() ? b.get() : null;


    //go for service call here based on your logic

}

我希望这可以满足您的要求。


查看完整回答
反对 回复 2022-06-04
?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

您可以在 Spring 中使用 Java EE @Size Validation 注解(但您必须在类路径上有一个 Java EE 验证 API 实现器,即 hibernate )。使用休眠,您可以使用 maven 导入此依赖项


<dependency>

    <groupId>org.hibernate</groupId>

    <artifactId>hibernate-validator</artifactId>

    <version>6.0.10.Final</version>

</dependency>

那么整个事情就变成了:


@RestController

@Validated

public class TestController {


@GetMapping("/test")

public void test(@RequestParam(value = "a", required = true )  @Size(min=1) String a, 

@RequestParam(value = "b", required = true) @Size(min=1)   String b) {

     {


     }


}


查看完整回答
反对 回复 2022-06-04
  • 3 回答
  • 0 关注
  • 142 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信