web-dev-qa-db-fra.com

Gestion des méthodes de gestionnaire ambiguë mappées dans REST avec Spring

J'ai essayé d'utiliser du code comme ci-dessous:

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Brand getBrand(@PathVariable Integer id) {
    return brandService.getOne(id);
}

@RequestMapping(value = "/{name}", method = RequestMethod.GET)
public List<Brand> getBrand(@PathVariable String name) {
    return brandService.getSome(name);
}

Mais j'ai une erreur comme ça, comment faire?

Java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path 'http://localhost:8080/api/brand/1': {public Java.util.List com.zangland.controller.BrandController.getBrand(Java.lang.String), public com.zangland.entity.Brand com.zangland.controller.BrandController.getBrand(Java.lang.Integer)}
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.Java:375) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
11
mikezang

Spring ne peut pas distinguer si la requête GET http://localhost:8080/api/brand/1 Sera traitée par getBrand(Integer) ou par getBrand(String) car votre mappage est ambigu.

Essayez d'utiliser un paramètre de requête pour la méthode getBrand(String). Cela semble plus approprié, car vous effectuez une requête:

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Brand getBrand(@PathVariable Integer id) {
    return brandService.getOne(id);
}

@RequestMapping(method = RequestMethod.GET)
public List<Brand> getBrand(@RequestParam(value="name") String name) {
    return brandService.getSome(name);
}

En utilisant l'approche décrite ci-dessus:

  • Les demandes comme GET http://localhost:8080/api/brand/1 Seront traitées par getBrand(Integer).
  • Les demandes comme GET http://localhost:8080/api/brand?name=nike Seront traitées par getBrand(String).

Juste un indice: Comme pratique courante, préférez les noms pluriels pour les collections de ressources. Donc, au lieu de /brand, Utilisez /brands.

23
cassiomolin
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Brand getBrand(@PathVariable Integer id) {
    return brandService.getOne(id);
}

@RequestMapping(value = "/{name}", method = RequestMethod.GET)
public List<Brand> getBrand(@PathVariable String name) {
    return brandService.getSome(name);
}

Lorsque vous exécutez l'application et accédez aux points de terminaison que vous avez essayé de coder, vous réalisez ce qui suit, ' http: // localhost: 8086/brand/1 ' et ' http: // localhost : 8086/brand/FooBar 'correspond au même format URL (qui peut être décrit comme protocole + endpoint +' brand '+). Donc SpringBoot est essentiellement confus s'il doit appeler la fonction 'getBrand' avec un type de données String ou un Integer. Donc, pour surmonter cela, je vous suggère d'utiliser un paramètre de requête tel que mentionné par @cassiomolin ou d'avoir des chemins séparés pour les deux invocations. Cela peut être contraire aux principes REST mais en supposant que vous faites juste un exemple d'application, c'est une autre solution de contournement.

@RequestMapping(value = "/id/{id}", method = RequestMethod.GET)
public Brand getBrand(@PathVariable Integer id) {
    return brandService.getOne(id);
}

@RequestMapping(value = "/name/{name}", method = RequestMethod.GET)
public List<Brand> getBrand(@PathVariable String name) {
    return brandService.getSome(name);
}

Cela a fonctionné pour moi.