Java Spring JSON Response issue

2019-08-09 05:48发布

问题:

I want to create some Spring based REST service sample. I want to get JSON based on Foo object, but when I try to send request using curl, it shows 406 error: "The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.". Here is my code: RestControl.java

package hello;

import org.springframework.stereotype.*;

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

@Controller
@RequestMapping("/app")
public class RestControl {
    @RequestMapping(value="/get",produces="application/json", method=RequestMethod.GET)
    @ResponseBody
    public Foo getFoo(){
        Foo f = new Foo();
        f.setId(new Long(1));
        f.setName("lol");
        return f;
    }
}

Foo.java:

package hello;

public class Foo {
    private Long id;
    private String name;

    public void setId(Long id){
        this.id=id;
    }

    public void setName(String name){
        this.name=name;
    }

    public Long getId(){
        return this.id;
    }

    public String getName(){
        return this.name;
    }

}

web.xml:

<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>Spring Web MVC Application</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

mvc-dispatcher-servlet.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">


    <mvc:annotation-driven />

    <bean id="RestControl" 
          class="hello.RestControl" />

    <bean id="foo"
          class="hello.Foo" />

</beans>

Upd:

Upd2: org.codehaus.jackson jackson-mapper-asl 1.9.13

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.2.12</version>
    </dependency>

    <!-- Spring ORM support -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>


    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>

回答1:

Spring by itself does not know how to correctly serialize and deserialize your domain objects, you need to include Jackson in your project to handle that:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.2.2</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.2.2</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.2.2</version>
    </dependency>

There is no special configuration required to tell Jackson to handle your JSON translation, unless you want to add some customization in the process.



回答2:

It looks like the problem is that what you are actually returning is not in JSON format. And I don't really see anything in your configs that would be handling this.

It's been a year or two since I dealt with this, so forgive me if this has changed, but from what I remember Spring doesn't implicitly translate Objects into JSON just from specifying that the response type is "application/json."

You should probably look into a library that can integrate with Spring to do this. The one I remember using is called Jackson.



回答3:

You should set the accept headers while using curl command as below. Hope this helps.

curl -i -H "Accept: application/json" <your curl url>