0

REST サーバーに Spring MVC を使用しています。私の pom.xml の spring.version は 3.2.1.RELEASE です。

私は多くの RESTful API を作成し、PathVariables を広範囲に使用しました。それは正常に動作します。

しかし、次のシナリオでは壊れているようです。次のような場合、REST リクエストでリソースが見つかりません。

@Controller
@RequestMapping(value = { "/resourceA/{resourceAId}/resourceB/{resourceBId}/resourceC/{resourceCId}" })
public class TenderController {

    @RequestMapping(value = "", method = RequestMethod.POST)
    @ResponseBody
    public Tender capture(
        @PathVariable long resourceAId,
        @PathVariable long resourceBId,
        @PathVariable long resourceCId,
        @RequestBody Map<String, Object> requestBody) {

        ...
    }
}

編集:

以下は、失敗した REST 要求のサンプルです。

POST /resourceA/1/resourceB/2/resourceC/3 HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Cache-Control: no-cache

{ "bodyParam1": 400, "bodyParam2": 0 }

ただし、Java コードから {resourceCId} を削除し、それに応じて REST 要求を調整すると、リソースが正常に検出されます。

改訂された Java コード:

@RequestMapping(value = { "/resourceA/{resourceAId}/resourceB/{resourceBId}/resourceC" })

新しい (成功した) REST 要求:

POST /resourceA/1/resourceB/2/resourceC HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Cache-Control: no-cache

{ "bodyParam1": 400, "bodyParam2": 0 }

基本的に、パス変数が 3 つあるとすぐに、物事がバラバラになったように見えます。ここで何が起こっているのかについてのアイデアはありますか? Spring MVC のバグに遭遇しましたか? 3 つのパス変数はかなり一般的なシナリオであるはずなので、いいえだと思います (コーナー ケースの資格はほとんどありません)。

更新: これは、サーバー コードではなく、HTTP クライアント (chrome postman) の問題のようです。curl 経由で同じリクエストを送信すると、期待どおりの結果を得ることができました。

更新: 実際には、エラーが戻ってきて、クライアント (postman、curl など) に関係なく発生しています。したがって、これは間違いなくサーバー側の問題です。ここにログがあります

01:35:39.409 [http-bio-8080-exec-5] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'mvc-dispatcher' processing POST request for [/resourceA/1/resourceB/1/resourceC/1]
01:35:39.411 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /resourceA/1/resourceB/1/resourceC/1
01:35:39.414 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Returning handler method [public void com.sample.controller.DefaultController.unmappedRequest()]
01:35:39.414 [http-bio-8080-exec-5] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'defaultController'
01:35:39.422 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [public void com.sample.controller.DefaultController.unmappedRequest()]: com.sample.exception.APIException: Url pattern is invalid.
01:35:39.423 [http-bio-8080-exec-5] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'globalControllerExceptionHandler'
01:35:39.423 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Invoking @ExceptionHandler method: public com.sample.model.ErrorInfo com.sample.controller.GlobalControllerExceptionHandler.handleAPIException(com.sample.exception.APIException)
01:35:39.460 [http-bio-8080-exec-5] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Written [com.sample.model.ErrorInfo@df27cd5] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter@2ae18b1a]
01:35:39.460 [http-bio-8080-exec-5] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'mvc-dispatcher': assuming HandlerAdapter completed request handling
01:35:39.460 [http-bio-8080-exec-5] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request

問題の原因を見つけた:
さまざまなことをいじくり回した後、この問題の原因を見つけました。私は DefaultController.java を持っています。これは、他のどのコントローラーとも一致しなかったすべての URL をキャッチし、REST サービスのエラー応答で見つからない適切なリソースを報告することを目的としていました。DefaultController には次のコードがあります。

package com.sample.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.sample.exception.APIException;
import com.sample.exception.APIException.Code;

@Controller
public class DefaultController {

    @RequestMapping("/**")
    public void unmappedRequest() {
        throw new APIException(Code.INVALID_URL_PATTERN,
            "There is no resource for this path");
    }
}

これは私にとってはうまくいきました。しかし、この場合、どういうわけか、この DefaultController "/**" は、"/resourceA/{resourceAId}/resourceB/{resourceBId}/resourceC/{resourceCId}" を受け取るように実際に設定されたコントローラーの前に、私の Url を選択していました。DefaultController を削除すると、問題が解決しました。ここで私の質問は、TenderController の前にトリガーされずに DefaultController 機能を保持するにはどうすればよいかということです。

4

1 に答える 1

0

これは、おそらくある時点で修正される Spring のバグである可能性が高いと思います。まったく同じ問題に遭遇しました。私たちの場合、マップされていないリクエストを処理する Default Spring Controller をプレーンなバニラ サーブレットに置き換えて 404 を処理することで、これを回避することができました - 方法の詳細はこちら.

于 2014-06-27T20:37:08.280 に答える