web-dev-qa-db-ja.com

JSONを生成および消費するコントローラーのSpring RequestMapping

application/jsonを消費および生成する複数のSpringコントローラーを使用すると、私のコードには次のような長い注釈が散らばっています。

    @RequestMapping(value = "/foo", method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)

defaultconsumesおよびproducesの値を持つ「合成/​​継承/集計」アノテーションを作成する方法はありますか。

    @JSONRequestMapping(value = "/foo", method = RequestMethod.POST)

上記の@JSONRequestMappingのようなものをどのように定義しますか? valuemethod@RequestMappingと同じように渡されることに注意してください。デフォルトが適切でない場合は、consumesまたはproducesを渡すこともできます。

返すものを制御する必要があります。適切なContent-Typeヘッダーを取得するために、produces/consumesアノテーションメソッドが必要です。

36
Roshan Mathews

Spring 4.2.xでは、@RequestMappingをメタ注釈として使用して、カスタムマッピング注釈を作成できます。そう:

消費と生成のデフォルト値を使用して「合成/継承/集約」注釈を作成する方法はありますか?

@JSONRequestMapping(value = "/foo", method = RequestMethod.POST)

はい、そのような方法があります。次のようなメタ注釈を作成できます。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@RequestMapping(consumes = "application/json", produces = "application/json")
public @interface JsonRequestMapping {
    @AliasFor(annotation = RequestMapping.class, attribute = "value")
    String[] value() default {};

    @AliasFor(annotation = RequestMapping.class, attribute = "method")
    RequestMethod[] method() default {};

    @AliasFor(annotation = RequestMapping.class, attribute = "params")
    String[] params() default {};

    @AliasFor(annotation = RequestMapping.class, attribute = "headers")
    String[] headers() default {};

    @AliasFor(annotation = RequestMapping.class, attribute = "consumes")
    String[] consumes() default {};

    @AliasFor(annotation = RequestMapping.class, attribute = "produces")
    String[] produces() default {};
}

次に、デフォルト設定を使用するか、必要に応じてそれらを上書きすることもできます。

@JsonRequestMapping(method = POST)
public String defaultSettings() {
    return "Default settings";
}

@JsonRequestMapping(value = "/override", method = PUT, produces = "text/plain")
public String overrideSome(@RequestBody String json) {
    return json;
}

AliasForの詳細については、春の javadoc および github wiki をご覧ください。

54
Ali Dehghani

あなたの質問に対する簡単な答えは、 Javaのアノテーション-継承 がないということです。ただし、問題の解決に役立つと思う方法でSpringアノテーションを使用する方法があります。

@ RequestMapping は、タイプレベルとメソッドレベルの両方でサポートされています。

@RequestMappingを型レベルに配置すると、そのクラスの各メソッドのほとんどの属性が「継承」されます。これは、Springリファレンスドキュメントの 言及 です。タイプに@RequestMappingを追加するときの各属性の処理方法の詳細については、 api docs をご覧ください。以下に、各属性についてこれをまとめました。

  • name:タイプレベルの値は、 '#'をセパレータとして使用してメソッドレベルの値と連結されます。
  • value:タイプレベルの値はメソッドによって継承されます。
  • path:タイプレベルの値はメソッドによって継承されます。
  • method:タイプレベルの値はメソッドによって継承されます。
  • params:タイプレベルの値はメソッドによって継承されます。
  • headers:タイプレベルの値はメソッドによって継承されます。
  • consumes:タイプレベルの値はメソッドによってオーバーライドされます。
  • produces:タイプレベルの値はメソッドによってオーバーライドされます。

これを使用する方法を示す簡単なコントローラーの例を次に示します。

package com.example;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(path = "/", 
        consumes = MediaType.APPLICATION_JSON_VALUE, 
        produces = MediaType.APPLICATION_JSON_VALUE, 
        method = {RequestMethod.GET, RequestMethod.POST})
public class JsonProducingEndpoint {

    private FooService fooService;

    @RequestMapping(path = "/foo", method = RequestMethod.POST)
    public String postAFoo(@RequestBody ThisIsAFoo theFoo) {
        fooService.saveTheFoo(theFoo);
        return "http://myservice.com/foo/1";
    }

    @RequestMapping(path = "/foo/{id}", method = RequestMethod.GET)
    public ThisIsAFoo getAFoo(@PathVariable String id) {
        ThisIsAFoo foo = fooService.getAFoo(id);
        return foo;
    }

    @RequestMapping(path = "/foo/{id}", produces = MediaType.APPLICATION_XML_VALUE, method = RequestMethod.GET)
    public ThisIsAFooXML getAFooXml(@PathVariable String id) {
        ThisIsAFooXML foo = fooService.getAFoo(id);
        return foo;
    }
}
20
FGreg

@RestControllerアノテーションの代わりに@Controllerを使用できます。

9
Wim Deblauwe

消費または生成属性を設定する必要はまったくありません。 Springは、次の要因に基づいてJSONを自動的に提供します。

  • リクエストのacceptsヘッダーはapplication/jsonです
  • @ ResponseBodyアノテーション付きメソッド
  • クラスパス上のジャクソンライブラリ

また、Wimの提案に従い、コントローラーを@ RestControllerアノテーションで定義する必要があります。これにより、各リクエストメソッドに@ ResponseBodyで注釈を付ける必要がなくなります。

このアプローチのもう1つの利点は、クライアントがJSONではなくXMLを必要とする場合、それを取得することです。 Acceptsヘッダーでxmlを指定するだけです。

6
hyness

Springには2つの注釈があります:@ RequestBody@ ResponseBodyこれらの注釈は、それぞれJSONを生成します。詳細情報 こちら

0
alexandrum