web-dev-qa-db-ja.com

複数のシナリオ@RequestMappingは、JSON / XMLとAcceptまたはResponseEntityを生成します

私はSpring 4.0.7で作業しています

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

Restfulについて私は次のようにしています

@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の場合、混在しています

ThroughRestTemplateAccept値を示すことができます

    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
                                     ); 

したがって、ここまでは、1つの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. ポスターHeadersボタンを使用して、Acceptを設定できます

質問1:

しかし、一般的なリンクの場合は? 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);
}

質問2:

戻り値の形式をカスタマイズするには、上記のメソッドのどのコードを追加する必要がありますか?つまり、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);
}

しかし:

URLを実行した場合:

  • 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と表示されることを確認できます

URLを実行した場合:

  • 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>

質問3

JSON出力を修正するには、上記のメソッドのどのコードを追加する必要がありますか?何が間違っているのか、何が欠けているのかわかりません。

3つの質問があります。

ありがとうございました

アルファ

@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);
}
34
Manuel Jordan

Acceptヘッダーを使用すると、RESTサービスからjsonまたはxml形式を簡単に取得できます。

これが私のコントローラーです。セクションをご覧ください。

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

RESTサービスを使用するために、ヘッダーを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>
36
Eddú Meléndez

すべての問題は、コンテンツタイプのネゴシエーションとパラメーターの受け渡しが混在していることです。それらは異なるレベルのものです。より具体的には、質問2について、返品するメディアタイプを使用して応答ヘッダーを作成しました。実際のコンテンツネゴシエーションは、応答ヘッダーではなく、要求ヘッダーの受け入れメディアタイプに基づいています。実行がメソッドgetPersonFormatの実装に到達した時点で、コンテンツネゴシエーションが完了したかどうかはわかりません。実装に依存します。そうでなくて、動作させる場合は、リクエストヘッダーの受け入れタイプを、返すもので上書きできます。

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

2
jljl

パラメーター中心のコンテンツタイプにはparamsフィルターを使用することをお勧めします。produces属性と連携して動作するはずです。

@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
}
0
M. Maraist