Springでは、オプションのパス変数を作成できますか?


187

Spring 3.0では、オプションのパス変数を使用できますか?

例えば

@RequestMapping(value = "/json/{type}", method = RequestMethod.GET)
public @ResponseBody TestBean testAjax(
        HttpServletRequest req,
        @PathVariable String type,
        @RequestParam("track") String track) {
    return new TestBean();
}

ここで、同じメソッドを呼び出す/json/abc/json、呼び出します。
明らかな回避策の1つtypeは、要求パラメーターとして宣言します。

@RequestMapping(value = "/json", method = RequestMethod.GET)
public @ResponseBody TestBean testAjax(
        HttpServletRequest req,
        @RequestParam(value = "type", required = false) String type,
        @RequestParam("track") String track) {
    return new TestBean();
}

そして、/json?type=abc&track=aaまたは/json?track=rr動作します

回答:


194

オプションのパス変数は使用できませんが、同じサービスコードを呼び出す2つのコントローラーメソッドを使用できます。

@RequestMapping(value = "/json/{type}", method = RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
        HttpServletRequest req,
        @PathVariable String type,
        @RequestParam("track") String track) {
    return getTestBean(type);
}

@RequestMapping(value = "/json", method = RequestMethod.GET)
public @ResponseBody TestBean testBean(
        HttpServletRequest req,
        @RequestParam("track") String track) {
    return getTestBean();
}

5
@Shamik:これは、私の意見では、パス変数を使用しないという説得力のある理由です。組み合わせの拡散はすぐに手に負えなくなる可能性があります。
skaffman

9
実際には、オプションのコンポーネントで満たされている間、パスをそれほど複雑にすることはできません。オプションのパス要素が1つまたは最大2つ以上ある場合は、そのうちのいくつかをリクエストパラメータに切り替えることを真剣に検討する必要があります。
Patrick Cornelissen

1
一部の人にとって、たとえば別のパラメーターが他の手段で提供できる場合、2番目のコントローラーメソッドが最初のコントローラーメソッドを呼び出すことも機能する可能性があります
chrismarx

3
代わりに、私たちは使用することができます春の新しいバージョンでは2つのコントローラのメソッドを作成するのではなく、あなたの答えを更新ご検討ください@RequestMapping:のように2つの値でstackoverflow.com/questions/17821731/...
csharpfolk

omgこれらのエンドポイントをどのように維持する予定ですか?そして、パス変数が1つだけではなく5つある場合、計算は私に代わって行われ、エンドポイントはいくつ実行されますか?私に好意を行うと、交換してください@PathVariable@RequestParam
ギリェルメAlencar

114

あなたは春4.1とJava 8を使用している場合は使用することができますjava.util.Optionalでサポートされている@RequestParam@PathVariable@RequestHeaderおよび@MatrixVariableSpring MVCのでは-

@RequestMapping(value = {"/json/{type}", "/json" }, method = RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
    @PathVariable Optional<String> type,
    @RequestParam("track") String track) {      
    if (type.isPresent()) {
        //type.get() will return type value
        //corresponds to path "/json/{type}"
    } else {
        //corresponds to path "/json"
    }       
}

あなたはこれがうまくいくと思いますか?ここでのあなた自身の答えは、{type}がパスに存在しない場合、コントローラーがヒットしないことを示唆しています。PathVariable Mapの方が良いアプローチだと思います、または個別のコントローラーを使用します。
Anshul Tiwari

4
はい、あなたが持っているだけ"/json/{type}"でタイプが存在しない場合はヒットしません(私のリンクされた回答が示唆するように)が、ここにはありvalue = {"/json/{type}", "/json" }ます。したがって、いずれかが一致すると、コントローラーメソッドがヒットします。
Aniket Thakur

同じ値などのタイプがRequestParamとRequestParamになる可能性はありますか?
zygimantus 2017

それは機能しますが、とにかくそれがそこにパラメーターを期待しているのでコントローラーの関数は呼び出されません
EliuX

15
これは機能し、Spring 4.3.3以降で@PathVariable(required = false)は、変数が存在しない場合でも、nullを取得できます。
Nicolai Ehemann 2017年

76

@PathVariableアノテーションを使用してパス変数のマップを挿入できることはよく知られていません。この機能がSpring 3.0で使用できるかどうか、または後で追加されたかどうかはわかりませんが、例を解決する別の方法を次に示します。

@RequestMapping(value={ "/json/{type}", "/json" }, method=RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
    @PathVariable Map<String, String> pathVariables,
    @RequestParam("track") String track) {

    if (pathVariables.containsKey("type")) {
        return new TestBean(pathVariables.get("type"));
    } else {
        return new TestBean();
    }
}

1
私はいつもそれを使用しています。これは、単一のメソッドでさまざまなURIタイプを処理する場合に便利ですex:{"/ json / {type}"、 "/ json / {type} / {xyz}"、 "/ json / {type} / {abc} "、" / json / {type} / {abc} / {something} "、" / json "}
Vaibs

25

あなたは使うことができます:

@RequestParam(value="somvalue",required=false)

pathVariableではなくオプションのパラメーター


1
これはバージョン固有のようです。ノー春3.のために行く
スチュ・トンプソン

5
現在、Spring 3.1プロジェクトでこのメソッドを使用しており、ドキュメントでは、このメソッドが2.5以降で機能するようになっているため、Spring 3で確実に機能します。編集:ソース
エヴァンB.

22
本当ですが、これは問題に関するものではありません。使用して、リクエストパラメータは、実際として、質問に記載されている「1つの明白な回避策」が、質問自体は約あるパスパラメータ。これは、オプションのパスパラメータのソリューションではありません。
Arjan 2013

9
PathVariableとRequestParamは異なります。
タイムレス

10

Spring 5 / Spring Boot 2の例:

ブロッキング

@GetMapping({"/dto-blocking/{type}", "/dto-blocking"})
public ResponseEntity<Dto> getDtoBlocking(
        @PathVariable(name = "type", required = false) String type) {
    if (StringUtils.isEmpty(type)) {
        type = "default";
    }
    return ResponseEntity.ok().body(dtoBlockingRepo.findByType(type));
}

反応

@GetMapping({"/dto-reactive/{type}", "/dto-reactive"})
public Mono<ResponseEntity<Dto>> getDtoReactive(
        @PathVariable(name = "type", required = false) String type) {
    if (StringUtils.isEmpty(type)) {
        type = "default";
    }
    return dtoReactiveRepo.findByType(type).map(dto -> ResponseEntity.ok().body(dto));
}

6

Nicolai Ehmannのコメントとwildloopの回答の簡略化された例(Spring 4.3.3以降で動作)、基本的にはrequired = false今使用できます:

  @RequestMapping(value = {"/json/{type}", "/json" }, method = RequestMethod.GET)
  public @ResponseBody TestBean testAjax(@PathVariable(required = false) String type) {
    if (type != null) {
      // ...
    }
    return new TestBean();
  }


0

以下は、baeldungのリファレンスページからの回答です。- https ://www.baeldung.com/spring-optional-path-variables


-5
$.ajax({
            type : 'GET',
            url : '${pageContext.request.contextPath}/order/lastOrder',
            data : {partyId : partyId, orderId :orderId},
            success : function(data, textStatus, jqXHR) });

@RequestMapping(value = "/lastOrder", method=RequestMethod.GET)
public @ResponseBody OrderBean lastOrderDetail(@RequestParam(value="partyId") Long partyId,@RequestParam(value="orderId",required=false) Long orderId,Model m ) {}

3
回答の一部のテキストを編集して、これが手元の問題の解決に貢献していると考える理由を説明することできます(4年後)。
Qirel、2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.