Spring 4 mvc REST XML and JSON response

2019-05-24 07:41发布

问题:

I am trying to produce XML and JSON response from the same method in my controller. I googled and found that JSON is the default for spring, as the jackson is on classpath. But for XML, I had to add the JAXB dependency and then annotate my model with JAXB annotation. Also, I had to change the produces attribute of the @RequestMapping annotation.

Now, my default behavior has changed, it returns an XML response. I thought after adding the content-Type header to my request with the value application/json, my response will be JSON, but sadly this is not the case. Below is my code:-

package com.example.controller;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.domain.Person;

@RestController("person")
public class PersonController {

    @RequestMapping(name ="getperson", produces = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE})
    public Person getPerson() {
        Person p = new Person();
        p.setAge(28);
        p.setEmail("email@gmail.com");
        p.setName("Amar");
        return p;
    }

}

Model class :-

package com.example.domain;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Person {

    //@XmlElement
    private String name;
    //@XmlElement
    private int age;
    private String email;

    public String getName() {
        return name;
    }
    @XmlElement
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    @XmlElement
    public void setAge(int age) {
        this.age = age;
    }
    public String getEmail() {
        return email;
    }
    @XmlElement
    public void setEmail(String email) {
        this.email = email;
    }
}

Build file:-

buildscript {
    ext {
        springBootVersion = '1.3.6.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot' 

jar {
    baseName = 'demo'
    version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-aop')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('javax.xml.bind:jaxb-api:2.2.12')
    testCompile('org.springframework.boot:spring-boot-starter-test') 
}


eclipse {
    classpath {
         containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
         containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
    }
}

What am I doing wrong ??? Any help here is much appreciated.

Thanks,

Amar

回答1:

In order to get json response from the server your request must contain Accept header set to application/json.



回答2:

In order to send response in Json or XML, one solution might be to use Content Negotiation Strategy. You could use urls such as /person.json or /person.xml. These will produces json or xml response. But first, you have to configure your Main Spring boot Class :

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

  @Override

      public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false).
                favorParameter(true).
                parameterName("mediaType").
                ignoreAcceptHeader(true).
                useJaf(false).
                defaultContentType(MediaType.APPLICATION_JSON).
                mediaType("xml", MediaType.APPLICATION_XML).
                mediaType("json", MediaType.APPLICATION_JSON);
      }
    }

No need to add produces = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE} in your controller. Here is an example Hope this will help