4
votes

Est-il possible d'attribuer conditionnellement la valeur de Required dans @RequestParam?

J'ai 2 paramètres @RequestParam dans mon contrôleur. Je souhaite définir la valeur requise des deux paramètres en fonction d'une condition. La condition pourrait être comme, si l'un des paramètres est passé, l'autre doit être passé. Alors, définissez l'exigence de l'autre comme vrai et vice-versa. Sinon, définissez les deux sur false si aucun des paramètres n'est passé.

@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,) {
     {

     }

}

La syntaxe d'utilisation du nom de variable dans @RequestParam () est incorrecte, mais je voulais expliquer ce que je veux. P >


2 commentaires

Non vous ne pouvez pas. Vous pouvez créer un objet, lier les deux variables et créer un validateur séparé pour cela. Mais cela ne fonctionnera pas avec des paramètres simples.


Pourquoi ne pas créer un haricot et y reporter le travail? Ensuite, vous pourriez avoir la méthode getter pour préformer votre chèque. myBean.getA et myBean.getB contenant chacun leur logique appropriée


4 Réponses :


-1
votes

En Java, vous ne pouvez transmettre que des constantes comme paramètres de toute annotation. C'est pourquoi il est impossible de le faire de cette façon. Cependant, vous pouvez valider tout ce genre de choses dans la méthode elle-même.


0 commentaires

4
votes

Vous pouvez le faire de l'une des 2 façons suivantes:

  1. Utilisation de Spring AOP et création d'un aspect environnant pour cette demande cartographie
  2. Utilisation de HandlerInterceptorAdapter pour intercepter les requêtes pour un URI donné

1. Utilisation de Spring AOP

Créez une annotation comme celle-ci:

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
    }
}

Ensuite, vous pouvez annoter votre méthode de mappage de requête avec: p >

@Configuration  
public class CustomInterceptor extends WebMvcConfigurerAdapter  {  

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

Créez un aspect autour de l'annotation. Quelque chose comme:

@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");
        }
    }
}

Notez que ce serait une bonne option de renvoyer 400 BAD REQUEST ici car la requête n’était pas valide. Cela dépend du contexte, bien sûr, mais c'est une règle générale pour commencer.

2. Utilisation de HandlerInterceptorAdapter

Créez un nouveau mappage d'intercepteur vers l'URI de votre choix (dans ce cas /test):

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

Définissez la logique de validation à l'intérieur de l'intercepteur personnalisé:

public @interface RequestParameterPairValidation {

}

Je dirais que la 2ème option est la meilleure car vous pouvez contrôler directement la réponse de la requête. Dans ce cas, il peut s'agir d'une 400 BAD REQUEST , ou de tout autre élément qui a plus de sens dans votre cas.


0 commentaires

0
votes

Vous pouvez utiliser Optionnel ici de manière intelligente ici comme ceci:

@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
}

J'espère que cela répond à vos besoins.


1 commentaires

Je me trompe peut-être dans cette hypothèse, mais je dirais que la question était davantage liée à un éventuel retour d'erreur de l'appel API si l'a / b ne répond pas à l'exigence d'exclusion mutuelle. Utiliser Optional Vous donnerait seulement un moyen sémantique de savoir si la valeur est là ou non. Il ne s'occupe pas de la validation.



0
votes

Vous pouvez utiliser l'annotation Java EE @Size Validation avec Spring (mais vous devez avoir un implémenteur d'API de validation Java EE sur le chemin de classe, c'est-à-dire hibernation). Avec hibernate, vous pouvez importer cette dépendance en utilisant maven

@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) {
     {

     }

}

Ensuite, tout devient:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.10.Final</version>
</dependency>


0 commentaires