2016-11-23 2 views
1

Ich schreibe eine API mit Spring MVC und ich habe ein Problem mit Apps in verschiedenen Sprachen geschrieben, um meine API zu verbrauchen.Spring MVC RestController erlauben Params mit unterschiedlichen Namen in Methoden

Es stellt sich heraus, dass die "Ruby-Benutzer" gerne ihre Parameter in snake_case und unsere "Java-Benutzer" ihre Param-Namen in camel_case haben möchten.

Ist es möglich, meine Methoden zu erstellen, die ermöglichen, dass Parameternamen mehrfach benannt, aber auf die gleiche Methodenvariable abgebildet werden?

Zum Beispiel ... Wenn ich eine Methode habe, die eine Anzahl von Variablen akzeptiert, von denen dort eine Postleitzahl zugeordnet ist. Kann ich meine Methode mit einem @RequestParam schreiben, das sowohl "postal_code" als auch "postalCode" akzeptiert und auf dieselbe Variable abbildet?

+0

warum Sie Ihren Code komplizierter bacause von "Ruby-Benutzer" behelfen. API sollte Client-unabhängig sein. – dit

Antwort

1

Weder JAX-RS @QueryParam noch Frühling @RequestParam unterstützt Ihre Anforderung, dh Zuordnung mehrerer Anforderungsparameternamen zu derselben Variablen. Ich empfehle, dies nicht zu tun, da es sehr schwierig sein wird, aufgrund der Verwirrung zu unterstützen, welcher Parameter von welchem ​​Client kommt.

Aber wenn Sie wirklich, dies umgehen wollte ((weil Sie nicht die URL aus der 3. Parteien kommen ändern können, vereinbart lange zurück), dann die alternative Verwendung von HandlerMethodArgumentResolver zu machen, die unsere eigenen Wunsch Argument nebenbei hilft (wie @MyRequestParam) an die Steuerung Verfahren wie wie in dem unten gezeigten Code:

Controller-Klasse:

@Controller 
public class MyController { 
    @RequestMapping(value="/xyz") 
    public void train1(@MyRequestParam String postcode) {//custom method argument injected 
     //Add your code here 
    } 
} 

MyRequestParam:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.PARAMETER) 
public @interface MyRequestParam { 
} 

HandlerMethodArgumentResolver Impl Klasse:

public class MyRequestParamWebArgumentResolver implements HandlerMethodArgumentResolver { 

    @Override 
    public Object resolveArgument(MethodParameter parameter, 
      ModelAndViewContainer mavContainer, 
      NativeWebRequest webRequest, 
      WebDataBinderFactory binderFactory) { 

     MyRequestParam myRequestParam = 
       parameter.getParameterAnnotation(MyRequestParam.class); 

     if(myRequestParam != null) { 

      HttpServletRequest request = 
       (HttpServletRequest) webRequest.getNativeRequest(); 

      String myParamValueToBeSentToController = ""; 
      //set the value from request.getParameter("postal_code") 
      //or request.getParameter("postalCode") 

      return myParamValueToBeSentToController; 
     }   
     return null; 
    } 

    @Override 
    public boolean supportsParameter(MethodParameter parameter) { 
     return (parameter.getParameterAnnotation(MyRequestParam.class) != null); 
    }  
} 

WebMvcConfigurerAdapter Klasse:

@Configuration 
class WebMvcContext extends WebMvcConfigurerAdapter { 

    @Override 
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { 
     argumentResolvers.add(new MyRequestParamWebArgumentResolver()); 
    } 
} 
0

Ich denke, was Sie tun wollen, ist nicht von Spring-Framework mit der Annotation RequestParam erlaubt.

Aber wenn Sie den Code ändern kann, oder sagen Sie Ihre Dritten, die Anrufe zu ändern, ich würde Sie 2 Möglichkeiten vorschlagen

Option 1:

Verwenden @PathVariable Eigenschaft

@RequestMapping(value = "/postalcode/{postalCode}", method = RequestMethod.GET) 
public ModelAndView yourMethod(@PathVariable("postalCode") String postalCode) { 
//...your code 

Hier ist es egal, ob Ihre URL wie folgt lautet:

http://domain/app/postalcode/E1-2ES 
http://domain/app/postalcode/23580 

Option 2:

erstellen 2 Methoden in Ihrem Controller und verwenden den gleichen Service

@RequestMapping(value = "/postalcode", method = RequestMethod.GET, params={"postalCode"}) 
public ModelAndView yourMethod(@RequestParam("postalCode") String postalCode) { 
    //...call the service 


@RequestMapping(value = "/postalcode", method = RequestMethod.GET, params={"postal_code"}) 
public ModelAndView yourMethodClient2(@RequestParam("postal_code") String postalCode) { 
    //...call the service 

Wenn möglich, würde ich vorschlagen, dass Sie die Option 1 ist viel skalierbare

+0

Was macht Option 1 besser skalierbar? Wie funktioniert es zB mit 5 Parametern? Warum ruft 'yourMethodClient2' nicht einfach' yourMethod' auf? – zeroflagL

+0

Mit 5, 10 oder mehr Parametern wird es gut funktionieren, die zweite Option ist nicht sehr gut, vor allem wegen doppelten Code. – yt61

+0

ist immer abhängig von der Art der Methoden, Anzahl der Parameter, Möglichkeit, die Anzahl der Dritten zu erhöhen, ... – cralfaro

Verwandte Themen