2017-07-07 1 views
0

Pour remplacer un système existant et ne pas casser l'interface, je suis à la recherche d'un moyen de mettre en œuvre le scénario suivant:copie RequestParams à requestHeaders avant de manipuler dans RestController

Si un client REST n'a pas fixé HTTP spécifique header (applicationId) mais l'envoie en tant que paramètre de requête (aka RequestParameter), cette valeur doit être considérée comme un paramètre de méthode dans un Spring Boot RestController.

La méthode actuelle ressemble à ceci:

@RequestMapping(value = "/something", method = RequestMethod.GET) 
    public void doSomething(@RequestHeader("applicationId") String applicationId) { } 

Je pense qu'il pourrait y avoir deux façons possibles:

  1. Annoter la méthode en quelque sorte pour mapper une requête paramètre ou d'un en-tête à un paramètre de méthode
  2. Ecrivez un Interceptor qui lit tous les paramètres de requête d'une requête et définit les en-têtes non existants avec leurs valeurs. De cette façon, la méthode n'aurait pas du être touchée du tout.

Dans les deux sens, je ne suis pas sûr de savoir comment les mettre en œuvre (ne sais pas si 1. est même possible). J'ai essayé avec un HandlerInterceptor qui lit les paramètres de requête dans preHandle (avec succès) mais n'est pas en mesure de définir des en-têtes dans la demande avant qu'il ne soit transmis au RestController.

+1

Ecrire un 'Filter' qui enveloppe la requête, remplacer la méthode' getHeader', d'abord déléguer à la demande actuelle, sinon vérifier les paramètres. Vous voulez probablement limiter cela à quelques paramètres bien connus ... –

+0

Semble raisonnable. Voulez-vous parler d'un 'javax.servlet.Filter'? Si oui, où substitueriez-vous la méthode 'getHeader()'? Je pense que je devrais ajouter une certaine logique à 'doFilter()' – user3105453

+0

@ user3105453, En option, vous pouvez définir votre propre annotation pour le paramètre method (similaire à '@ RequestParam' ou' @ RequestHeader') et écrire votre propre 'HandlerMethodArgumentResolver' (similaire à 'RequestHeaderMethodArgumentResolver' ou' RequestParamMethodArgumentResolver'). Votre implémentation recherchera une valeur dans les en-têtes ET dans les paramètres de requête. Bien sûr, dans ce cas, vous devrez marquer les paramètres dans toutes vos méthodes. Ne sait pas ce que ça va être avec vous – Leffchik

Répondre

1

Ecrivez un Filter qui enveloppe la demande entrante en utilisant un HttpServletRequestWrapper. Ce wrapper doit remplacer la méthode getHeader.

public ParameterToHeaderWrappingRequestFilter extends OncePerRequestFilter { 

    protected void doFilterInternal(
     HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 
     throws ServletException, IOException { 
     filterChain.doFilter(new ParameterToHeaderWrappingRequest(request), response, filterChain); 
    } 
} 

Enregistrer ce filtre en @Bean dans votre application de démarrage de printemps et il sera appliqué automatiquement.

public class ParameterToHeaderWrappingRequest extends HttpServletRequestWrapper { 

    public String getHeader(String name) { 
     String header = super.getHeader(name); 
     if (header == null) { 
      header = getParameter(name); 
     } 
     return header; 
    } 
} 

Quelque chose comme ça devrait faire l'affaire. En fonction de vos besoins, vous pouvez avoir besoin de remplacer certaines méthodes supplémentaires basées sur l'en-tête et vous souhaitez probablement limiter le nombre d'en-têtes à remplacer par des paramètres.

Le reste de votre code peut maintenant être écrit tel quel.

+0

Merci pour votre code.J'ai réussi à le faire en changeant 'getHeader()' en 'getHeaders()' et en surchargeant 'getHeaderNames()' aussi. On dirait que 'RestController' recherche d'abord tous les HeaderNames, puis les parcourt en appelant' getHeaders() ' – user3105453