web-dev-qa-db-ja.com

REST Springでのアプリケーションにマッピングされたあいまいなハンドラーメソッドの処理

私は以下のようにいくつかのコードを使用しようとしました:

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

しかし、私はこのようなエラーが発生しました、どうすればいいですか?

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はリクエスト_GET http://localhost:8080/api/brand/1_がgetBrand(Integer)によって処理されるか、getBrand(String)によって処理されるかを区別できません。

getBrand(String)メソッドのクエリパラメータを使用してみてください。クエリを実行しているので、より適切なようです。

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

上記のアプローチを使用する:

  • _GET http://localhost:8080/api/brand/1_のようなリクエストはgetBrand(Integer)によって処理されます。
  • _GET http://localhost:8080/api/brand?name=nike_のようなリクエストはgetBrand(String)によって処理されます。

単なるヒント:一般的な方法として、リソースのコレクションには複数の名詞を使用します。したがって、_/brand_の代わりに、_/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);
}

アプリを実行し、コーディングしてみたエンドポイントにアクセスすると、 ' http:// localhost:8086/brand/1 'および ' http:// localhost :8086/brand/FooBar 'は同じURL形式に対応します(これはprotocol + endpoint +' brand '+として説明できます)。そのため、SpringBootは、文字列データ型または整数を使用して関数「getBrand」を呼び出す必要がある場合、本質的に混乱します。したがって、これを回避するには、@ cassiomolinで言及されているクエリパラメータを使用するか、両方の呼び出しに別々のパスを設定することをお勧めします。これはREST=の原則に反する可能性がありますが、サンプルアプリを実行していると仮定すると、これは別の回避策です。

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

これでうまくいきました。