1

私は春のRESTAPIに取り組んでいます。要件には、同じURLでリクエスト本文が異なる2つのPOSTリクエストがあります。Spring MVCはコントローラー全体で一意のマッピングを持っている必要があるため、特定のPOJOにマッピングするためにリクエスト本文を前処理する必要があります。

リクエスト本文のsession_typeに基づいて、リクエストを特定のPOJO(JSON-> JAVA POJO)にマップする必要があります。

たとえば、リクエスト本文の「session_type」が「typeX」の場合、リクエストはClassXPOJOにマップする必要があります。リクエスト本文の「session_type」が「typeY」の場合、リクエストはClassYPOJOにマップする必要があります。

ある種のrequestbodyアノテーションを使用してそれを行う方法はありますか?

4

4 に答える 4

5

typeXとをバインドする場合はtypeY、必ず2つのハンドラーが必要です。しかし、なぜ私たちは:paramのオプションを使用しないのですか?@RequestMapping

@RequestMapping(method = RequestMethod.POST, 
        value = "/url", params = "session_type=typeX")
public String handleTypeX(@RequestBody @ModelAttribute TypeX typeX){
    //TODO implement
}

@RequestMapping(method = RequestMethod.POST,
        value = "/url", params = "session_type=typeY")
public String handleTypeY(@RequestBody @ModelAttribute TypeY typeY){
    //TODO implement
}

いくつかの準備が必要な場合(パラメーターを正規化するか、モデルバインディングを手動で実行する)、上記のアプローチをと組み合わせることができますが、ハンドラーのパラメーターとともに正確なULRのルールが必要@InitBinderであることに注意してください。@InitBinder@ModelAttribute

編集:Spring MVCでは、正確なURLに2つのハンドラーを使用することはできません。つまり、method / URL / params/consumesタイプが同じ場合です。

したがって、必要なパラメーターを確認してから手動で対応するクラスに変換する統合ハンドラーを使用することをお勧めします。必要なクラスを見つけるには、ストラテジーパターンを使用する方が良いと思います。

//class resolver according "session_type" parameter
//note, that you can use Spring autowiring capabilities
private final Map<String, Class> TYPES_CONTEXT = new HashMap<String, Class>(){
    {
        this.put("x", TypeX.class);
        this.put("y", TypeY.class);
        //TODO probably other classes
    }
}


@RequestMapping(method = RequestMethod.POST,
        value = "/url")
public @ResponseBody String handleAnyType(@RequestBody Map<String, String> body){
    String sessionType = body.get("session_type");

    //TODO handle case if sessionType is NULL

    Class convertedClass = TYPES_CONTEXT.get(sessionType);

    //TODO handle case if class is not found

    Object actualObject = objectMapper.convertValue(body, convertedClass);

    //now we use reflection for actual handlers, but you may refactor this in the way you want, f.e. again with Strategy pattern
    //note that current approach there should be contract for methods names
    Method actualHandler = this.getClass().getMethod("handle" + actualObject.getClass().getSimpleName());

    return (String)actualHandler.invoke(this, actualObject);
}

public String handleTypeX(TypeX typeX){
    //TODO implement
}

public String handleTypeY(TypeY typeY){
    //TODO implement
}

//TODO probably other methods

このアプローチは検証を処理せず、いくつかのことが省略されましたが、これは役立つかもしれないと思います。

于 2013-03-13T21:07:39.690 に答える
0

typeX両方のタイプに対して1つのメソッドを使用してコントローラーを作成し、またはに応じて必要なcomponent\methodを呼び出す必要があると思いますtypeY

于 2013-03-13T20:58:47.013 に答える
0

GETにはリクエスト本文を含めるべきではありません。少なくとも、リクエスト本文がある場合は、サーバー側でリクエスト本文を使用する必要はありません。あなたがそれを説明するように、このAPIはRESTfulではありません。

それを気にしないと仮定して、TypeXとTypeYの親クラス、またはTypeXとTypeYの両方が実装するインターフェイスを取得するコントローラーメソッドを作成し、@ SomethingMeaningfulToYouで注釈を付けてから、Web引数メソッドリゾルバーを使用して子をインスタンス化します。あなたが望むクラス。

ただし、これは壊れたAPIを回避するためのハックです。

于 2013-03-13T21:37:28.713 に答える
0

同じURLでリクエスト本文が異なる2つのPOSTリクエストがあります

RESTfulインターフェースの場合、同じURLは常に同じリソースを示す必要があります。リクエストの本文には、そのリソースのさまざまな表現が含まれる場合があります。HttpMessageContverter2つの異なる種類の表現に対して異なるクラスを作成できます。

于 2013-05-23T15:51:52.080 に答える