簡體   English   中英

Spring RequestMapping用於生成和使用JSON的控制器

[英]Spring RequestMapping for controllers that produce and consume JSON

使用多個Spring控制器來使用和生成application/json ,我的代碼充滿了長注釋,如:

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

有沒有辦法生成一個“復合/繼承/聚合”注釋,其中包含consumesproduces 默認值,這樣我就可以編寫如下內容:

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

我們如何定義上面的@JSONRequestMapping 注意傳遞的valuemethod就像在@RequestMapping中一樣,如果默認值不合適,也可以傳入consumesproduces

我需要控制我要回來的東西。 我想produces / consumes注釋的方法,使我獲得相應Content-Type頭。

從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;
}

您可以在spring的javadocgithub wiki中閱讀有關AliasFor更多信息。

您的問題的簡單答案是Java中沒有Annotation-Inheritance 但是,有一種方法可以以我認為有助於解決問題的方式使用Spring注釋。

類型級別和方法級別都支持@RequestMapping

當你在類型級別放置@RequestMapping ,對於該類中的每個方法,大多數屬性都是“繼承的”。 這在Spring參考文檔中提到 查看api文檔 ,了解在將@RequestMapping添加到類型時如何處理每個屬性的詳細信息。 我已經為下面的每個屬性總結了這個:

  • name :Type級別的值與方法級別的值連接,使用'#'作為分隔符。
  • value :類型級別的值由方法繼承。
  • path :類型級別的值由方法繼承。
  • method :類型級別的值由方法繼承。
  • params :類型級別的值由方法繼承。
  • headers :Type級別的值由方法繼承。
  • 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;
    }
}

您可以使用@RestController而不是@Controller注釋。

您根本不需要配置消耗或生成屬性。 Spring將根據以下因素自動提供JSON。

  • 請求的接受標頭是application / json
  • @ResponseBody注釋方法
  • 類路徑的傑克遜圖書館

您還應該遵循Wim的建議並使用@RestController注釋定義控制器。 這將使您免於使用@ResponseBody注釋每個請求方法

這種方法的另一個好處是,如果客戶端需要XML而不是JSON,他們就會得到它。 他們只需要在接受標頭中指定xml。

Spring中有2個注釋: @RequestBody@ResponseBody 這些注釋消耗,分別產生JSON。 這里有更多信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM