3
votes

Spring - Exécute le code avant que la méthode du contrôleur ne soit appelée

Y a-t-il une annotation similaire à @PreAuthorize ou @PreFilter que je peux utiliser pour exécuter du code avant qu'une méthode dans le contrôleur ne soit appelée?

Je dois ajouter des informations au contexte de la requête (spécifique à la méthode appelée) pour être ensuite récupérées par le ExceptionHandler.

Par exemple

@RestController
public MyController{

  @UnkwonwAnnotation("prepareContext(request.getAgentId())"){
  public ResponseEntity method1(RequestA requestA) {
    ...
  }

  @UnkwonwAnnotation("prepareContext(request.getUserName())"){
  public ResponseEntity method1(RequestB requestB) {
    ...
  }

}

Je pourrais simplement utiliser @PreAuthorize mais je ne me sens pas bien


1 commentaires

C'est à cela que sert un HandlerInterceptor . Implémentez la méthode preHandle et faites votre travail.


4 Réponses :


6
votes

Vous pouvez ajouter un intercepteur pour cet

Exemple d'intercepteur

@Configuration
public class MyConfig extends WebMvcConfigurerAdapter{
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(new MyCustomInterceptor()).addPathPatterns("/**");
    }
}

Configuration

Public class CustomInterceptor implements HandlerInterceptor{


    @Override
    public boolean preHandle(HttpServletRequest request,HttpServletResponse  response){
    //Add Login here 
        return true;
    }
} 

J'espère que cela vous aidera


0 commentaires

3
votes

Spring Aspect est également une bonne option pour exécuter du code avant le contrôleur.

@Component
@Aspect
public class TestAspect {

    @Before("execution(* com.test.myMethod(..)))")
    public void doSomethingBefore(JoinPoint jp) throws Exception {

        //code  
    }
}

Ici, myMethod () s'exécutera avant le contrôleur.

p >


0 commentaires

2
votes

Peut-être qu'une bonne option est d'implémenter un filtre personnalisé qui s'exécute à chaque fois qu'une requête est reçue.

Vous devez étendre "OncePerRequestFilter" et écraser la méthode "doFilterInternal"

public class CustomFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        //Add attributes to request
        request.getSession().setAttribute("attrName", new String("myValue"));

        // Run the method requested by petition
        filterChain.doFilter(request, response);

        //Do something after method runs if you need.

    }
}

Après avoir enregistré le filtre dans Spring avec FilterRegistrationBean. Si vous avez la sécurité Spring, vous devez ajouter votre filtre après le filtre de sécurité.


6 commentaires

Le filtre ne saurait pas quels paramètres la méthode a reçus


Oui, vous avez l'objet de requête dans la méthode oFilterInternal , ici il y a tous les paramètres ... vous pouvez travailler avec tous. Tapez simplement request.getParameterNames () // pour donner tous les noms. request.getParameter ("myParam") // pour obtenir la valeur d'un paramètre


De cette façon, le filtre serait encombré d'instructions IF. Je voudrais une annotation pour aller sur la méthode qui l'exige


Dans ce cas, la meilleure option est d'utiliser un intercepteur. Ma solution est globale, affecte toutes les demandes.


Cela signifie toujours que la logique de chaque contrôleur sera au même endroit


Oui, la logique que vous mettez dans le filtre fonctionnera pour les requêtes adressées à tous les contrôleurs.



1
votes

En développant la réponse de Sai Prateek, j'ai créé une annotation personnalisée:

@RestController
public class MyController {

  @OperationContext(clientId = '#request.getClientId', userId = '#request.getUserId', operation = "OPERATION_A")
  public ResponseEntity aMethod(MyRequest request) {
    ...
  }
}

et un composant pour la gérer:

@Aspect
@Component
public class OperationContextAspect {

  @Before(value = "@annotation(operationContext)", argNames = "operationContext")
  public void preHandle(OperationContext operationContext) {

    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

    requestAttributes.setAttribute("operation", operationContext.operation, RequestAttributes.SCOPE_REQUEST);
    requestAttributes.setAttribute("clientId", operationContext.clientId(), RequestAttributes.SCOPE_REQUEST);
    requestAttributes.setAttribute("userId", operationContext.userId(), RequestAttributes.SCOPE_REQUEST);

  }
}

J'annote ensuite les méthodes du contrôleur en fournissant les paramètres requis:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationContext {

  String clientId();

  String userId();

  String operation();
}


0 commentaires