2014-10-31 43 views
24

我與春天一起工作產生JSON/XML有多個方案4.0.7@RequestMapping(Accept)或ResponseEntity

關於Spring MVC的,用於研究目的,我有以下幾點:

@RequestMapping(value="/getjsonperson", 
       method=RequestMethod.GET, 
       produces=MediaType.APPLICATION_JSON_VALUE) 
public @ResponseBody Person getJSONPerson(){ 
    logger.info("getJSONPerson - getjsonperson"); 
    return PersonFactory.createPerson(); 
} 

@RequestMapping(value="/getperson.json", method=RequestMethod.GET) 
public @ResponseBody Person getPersonJSON(){ 
    logger.info("getPerson - getpersonJSON"); 
    return PersonFactory.createPerson(); 
} 

每一個做工精細,同時觀察了JSON,有和沒有擴展名:

  • /getjsonperson
  • /getperson.json

同爲XML

@RequestMapping(value="/getxmlperson", 
       method=RequestMethod.GET, 
       produces=MediaType.APPLICATION_XML_VALUE 
       ) 
public @ResponseBody Person getXMLPerson(){ 
    logger.info("getXMLPerson - getxmlperson"); 
    return PersonFactory.createPerson(); 
} 

@RequestMapping(value="/getperson.xml", method=RequestMethod.GET) 
@ResponseBody 
public Person getPersonXML(){ 
    logger.info("getPerson - getpersonXML"); 
    return PersonFactory.createPerson(); 
} 

每一個工作正常,同時觀察了XML,有和沒有擴展名:

  • /getxmlperson
  • /getperson.xml

現在約寧靜我有以下幾點:

@RequestMapping(value="/person/{id}/", 
       method=RequestMethod.GET, 
       produces={MediaType.APPLICATION_JSON_VALUE, 
          MediaType.APPLICATION_XML_VALUE}) 
public ResponseEntity<Person> getPersonCustomizedRestrict(@PathVariable Integer id){ 
    Person person = personMapRepository.findPerson(id); 
    return new ResponseEntity<>(person, HttpStatus.FOUND);//302  
} 

觀察MediaType,它是混合了JSON和XML

通過RestTemplate我可以表明Accept

if(type.equals("JSON")){ 
     logger.info("JSON"); 
     headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); 
    } 
    else if(type.equals("XML")){ 
     logger.info("XML"); 
     headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML)); 
    } 
    …. 

    ResponseEntity<Person> response = 
       restTemplate.exchange("http://localhost:8080/spring-utility/person/{id}/customizedrestrict", 
             HttpMethod.GET, 
             new HttpEntity<Person>(headers), 
             Person.class, 
             id 
            ); 

直到這裏,因此我可以使用一個URL/URI來獲取XML或JSON格式的一些數據。它工作正常

我的問題是與Spring MVC ...只是考慮

@RequestMapping(value="/{id}/person", 
       method=RequestMethod.GET, 
       produces={MediaType.APPLICATION_JSON_VALUE, 
          MediaType.APPLICATION_XML_VALUE}) 
public @ResponseBody Person getPerson(@PathVariable Integer id){ 
    return personMapRepository.findPerson(id); 
} 

我可以通過電話或通過激活該處理方法(@RequestMapping):

  1. jQuery的使用Ajax的工作,我能以指示Accept的值(例如JSON)
  2. Poster,通過Headers按鈕,我可以設置Accept

問題一:

但爲了一個共同的鏈接?我如何設置Accept值?有可能嗎?

我以另一種方式想到解決這個問題。

  • http://localhost:8080/spring-utility/person/getpersonformat?format=json
  • http://localhost:8080/spring-utility/person/getpersonformat?format=xml

觀察:

  • ?format

因此

@RequestMapping(value="/getpersonformat", 
       method=RequestMethod.GET, 
       produces={MediaType.APPLICATION_JSON_VALUE, 
          MediaType.APPLICATION_XML_VALUE}) 
public @ResponseBody Person getPerson(@RequestParam String format){ 
    return personMapRepository.findPerson(id); 
} 

問題二:

上面顯示的方法是什麼代碼必須被添加到自定義返回類型格式? 我的意思是,JSON或XML,可能嗎?

我認爲在以下幾點:

@RequestMapping(value="/getpersonformataltern", 
     method=RequestMethod.GET 
     produces={MediaType.APPLICATION_JSON_VALUE, 
        MediaType.APPLICATION_XML_VALUE} 
     ) 
public ResponseEntity<Person> getPersonFormat(@RequestParam String format){ 
    logger.info("getPersonFormat - format: {}", format); 
    HttpHeaders httpHeaders = new HttpHeaders(); 
    if(format.equals("json")){ 
     logger.info("Ok JSON"); 
     httpHeaders.setContentType(MediaType.APPLICATION_JSON); 
    } 
    else{ 
     logger.info("Ok XML"); 
     httpHeaders.setContentType(MediaType.APPLICATION_XML); 
    } 
    return new ResponseEntity<>(PersonFactory.createPerson(), httpHeaders, HttpStatus.OK); 
} 

但是:

如果我執行的網址:

  • http://localhost:8080/spring-utility/person/getpersonformataltern?format=json

我得到

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<person> 
    <id>1</id> 
    <firstName>Manuel</firstName> 
    <lastName>Jordan</lastName> 
… 
</person> 

是的XML

注意:我可以證實控制檯打印Ok JSON

如果我執行的網址:

  • http://localhost:8080/spring-utility/person/getpersonformataltern?format=xml

我得到

This XML file does not appear to have any style information associated with it. 
The document tree is shown below. 

<person> 
    <id>1</id> 
    <firstName>Manuel</firstName> 
    <lastName>Jordan</lastName> 
    … 
</person> 

問題三

必須添加上面顯示的方法的哪些代碼才能修復JSON輸出? 我不知道什麼是錯的或丟失..

有三個問題。

謝謝

阿爾法

@Override 
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 
    Map<String,MediaType> mediaTypes = new LinkedHashMap<>(); 
    mediaTypes.put("json", MediaType.APPLICATION_JSON); 
    mediaTypes.put("xml", MediaType.APPLICATION_XML); 
    configurer.mediaTypes(mediaTypes); 
    configurer.defaultContentType(MediaType.TEXT_HTML); 
} 
+0

查看內容協商。 – 2014-10-31 15:38:23

+0

請參閱'Alpha'部分。它的工作原理,記得我在URL中使用.json和.xml。 – 2014-10-31 18:39:58

+0

如果你想使用URL,你不能設置內容類型,你只能這樣做,如果你控制呼叫(如在JavaScript中)。你可以做的一件事是將服務器上的默認內容類型設置爲JSON(而不是現在的HTML)。不能控制內容類型是合乎邏輯的,因爲來自HTML的鏈接應該導致HTML。 – 2014-11-06 06:37:50

回答

21

使用接受頭是很容易得到REST服務的格式JSON或XML。

這是我的控制器,看看生成部分。

@RequestMapping(value = "properties", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, method = RequestMethod.GET) 
    public UIProperty getProperties() { 
     return uiProperty; 
    } 

爲了消耗我們可以使用下面,其中報頭可以是MediaType.APPLICATION_JSON_VALUE或MediaType.APPLICATION_XML_VALUE

HttpHeaders headers = new HttpHeaders(); 
headers.add("Accept", header); 

HttpEntity entity = new HttpEntity(headers); 

RestTemplate restTemplate = new RestTemplate(); 
ResponseEntity<String> response = restTemplate.exchange("http://localhost:8080/properties", HttpMethod.GET, entity,String.class); 
return response.getBody(); 

編輯01代碼的其餘部分的服務:

爲了與application/xml一起工作,增加這種依賴關係

<dependency> 
    <groupId>com.fasterxml.jackson.dataformat</groupId> 
    <artifactId>jackson-dataformat-xml</artifactId> 
</dependency> 
+0

當時間適當,讓我測試你的解決方案。現在我又在服務器端了。謝謝 – 2015-02-22 19:04:33

+1

節省我的時間!忘記將'jackson-dataformat-xml'添加到pom – bob 2016-03-20 09:50:40

2

你所有的問題是你正在混合內容類型協商和參數傳遞。他們是不同層次的事物。更具體地說,對於你的問題2,你用你想要返回的媒體類型構造了響應頭。實際的內容協商基於請求頭中的接受媒體類型,而不是響應頭。在執行到達方法getPersonFormat的實現時,我不確定內容協商是否已完成。取決於實施。如果沒有,並且你想讓這個工作起作用,你可以用你想返回的東西來覆蓋請求頭接受類型。

return new ResponseEntity <>(PersonFactory.createPerson(),httpHeaders,HttpStatus.OK);

0

我更喜歡使用params過濾器參數爲中心的內容類型..我相信應該與生產屬性一起工作。

@GetMapping(value="/person/{id}/", 
      params="format=json", 
      produces=MediaType.APPLICATION_JSON_VALUE) 
public ResponseEntity<Person> getPerson(@PathVariable Integer id){ 
    Person person = personMapRepository.findPerson(id); 
    return ResponseEntity.ok(person); 
} 
@GetMapping(value="/person/{id}/", 
      params="format=xml", 
      produces=MediaType.APPLICATION_XML_VALUE) 
public ResponseEntity<Person> getPersonXML(@PathVariable Integer id){ 
    return GetPerson(id); // delegate 
} 
+2

如果所有其餘控制器中的所有REST URI都使用format參數,則其中的代碼將增加很多倍 – Rui 2017-01-27 08:30:47