POST JSON与Jersey REST服务的问题

时间:2022-10-07 16:36:45

I have a problem with posting JSON to a Jersey REST service - GET is working perfectly but POST seems tricky. I've been working on this problem for awhile now, with no solution so far. Any help is much appreciated!

将JSON发布到Jersey REST服务时遇到问题 - GET工作正常但POST似乎很棘手。我一直在研究这个问题,到目前为止还没有解决方案。任何帮助深表感谢!

It seems it cant find the U RL to send the json?Here is what FireBug console shows:

它似乎无法找到U RL发送json?这是FireBug控制台显示的内容:

    POST http://localhost:9998/data 400 Bad Request
    Post source: name=Tony
    **Response Headers**
    Connection  close
    Content-Length  0
    Content-Type    text/html; charset=iso-8859-1
    Date    Fri, 20 Apr 2012 10:13:24 GMT
    **Request Headers**
    Accept  application/json, text/javascript, */*; q=0.01
    Accept-Encoding gzip, deflate
    Accept-Language sv-se,sv;q=0.8,en-us;q=0.5,en;q=0.3
    Connection  keep-alive
    Content-Length  9
    Content-Type    application/json; charset=UTF-8
    Host    localhost:9998
    Referer http://localhost:9998/static/page.html
    User-Agent  Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20100101 Firefox/11.0
    X-Requested-With    XMLHttpRequest

I'm doing the POST as follows:

我按照以下方式进行POST:

<button id='btn' value="knapp" name="knapp" />
    <script type="text/javascript">
    $('#btn').click(function(){
        $.ajax({
            url: '/data',
            type: 'POST',
            contentType: 'application/json',
            data: {name:"Tony"},
            dataType: 'json'
        });
    })
</script>

Javabean class with @XmlRootElement:

带有@XmlRootElement的Javabean类:

@XmlRootElement
public class StatusBean {
    private String name;

    public StatusBean() {
    }

    public String getName() {
        return name;
    }

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

Resource method:

资源方法:

@Path("/data")
public class PostData {
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public StatusBean post(StatusBean sb) {
        System.out.println(sb);
        return sb;
    }
}

The server, set up with Grizzly:

服务器,与Grizzly一起设置:

public class Main {
    public static final URI BASE_URI = getBaseURI();

    public static void main(String[] args) throws IOException {
        HttpServer httpServer = startServer();

        Map<String,String> initParams = new HashMap<String, String>();
        initParams.put("com.sun.jersey.config.property.packages", "server");
        SelectorThread selector = GrizzlyWebContainerFactory.create("http://localhost:9998/", initParams );

        System.out.println(String.format("Jersey app started with WADL available at "
                + "%sapplication.wadl\nTry out %shelloworld\nHit enter to stop it...",
                BASE_URI, BASE_URI));

        System.in.read();
        httpServer.stop();
    }

    protected static HttpServer startServer() throws IOException {
        System.out.println("Starting grizzly...");

        ClassNamesResourceConfig rc = new ClassNamesResourceConfig(PostData.class);

//        rc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, true);

        HttpServer server = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);

        server.getServerConfiguration().addHttpHandler(new StaticHttpHandler(new File(".").getAbsolutePath()), "/static");

        return server;
    }

    private static int getPort(int defaultPort) {
        String port = System.getProperty("jersey.test.port");
        if (null != port) {
            try {
                return Integer.parseInt(port);
            } catch (NumberFormatException e) {
            }
        }
        return defaultPort;
    }

    private static URI getBaseURI() {
        return UriBuilder.fromUri("http://localhost/").port(getPort(9998)).build();
    }
}

5 个解决方案

#1


2  

  1. Try making your bean serializable.

    尝试使您的bean可序列化。

    @XmlRootElement
    
    public class StatusBean implements Serializable {
    ....
    }
    
  2. Check your POST url. It should be `

    检查你的POST网址。它应该是`

    http://localhost:9998/{projectname}/{restservletmapping}/data

    HTTP://本地主机:9998 / {项目名称} / {restservletmapping} /数据

    For example, if my web.xml looks like this and my project name is SampleProject

    例如,如果我的web.xml看起来像这样,我的项目名称是SampleProject

    <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    

    URL would be : http://localhost:9998/SampleProject/rest/data

    URL将是:http:// localhost:9998 / SampleProject / rest / data

    You can use tools for testing REST services like SOAP UI or browser addons like POSTMAN, REST CONSOLE, etc.

    您可以使用工具来测试REST服务,如SOAP UI或浏览器插件,如POSTMAN,REST CONSOLE等。

  3. If above things are fine and REST service is giving response with testing tools. Then it could be problem of Cross Origin Policy in ajax.

    如果上面的事情很好,REST服务就会通过测试工具给出响应。那么它可能是ajax中的跨源策略问题。

#2


2  

I had the same problem. The issue is that your data is not converted to JSON string automatically. So you just need to call JSON.stringify(...) on your data before posting it:

我有同样的问题。问题是您的数据未自动转换为JSON字符串。所以你只需要在发布数据之前调用JSON.stringify(...):

<button id='btn' value="knapp" name="knapp" />
<script type="text/javascript">
$('#btn').click(function(){
    $.ajax({
        url: '/data',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({name:"Tony"}),
        dataType: 'json'
    });
})
</script>

This should work.

这应该工作。

#3


1  

From your server config I see that you haven't configured JAX-RS with Grizzly. On the base of that example you should somehow pass such property

从您的服务器配置中我发现您还没有使用Grizzly配置JAX-RS。在该示例的基础上,您应该以某种方式传递此类属性

Map<String,String> initParams = new HashMap<String, String>();
initParams.put( "com.sun.jersey.config.property.packages", "package.with.your.StatusBean.class" );

Another configuration option is to use

另一种配置选项是使用

ResourceConfig rc = new PackagesResourceConfig("your.package.with.resources");

and start grizzly server:

并启动grizzly服务器:

GrizzlyServerFactory.createHttpServer(BASE_URI, rc);

See details: http://jersey.java.net/nonav/documentation/latest/user-guide.html (Chapter "Deploying the root resource"). Try to run first example they have.

请参阅详细信息:http://jersey.java.net/nonav/documentation/latest/user-guide.html(“部署根资源”一章)。尝试运行他们拥有的第一个示例。

#4


0  

Are you sure that the path you're posting to is complete? You should define another Path annotation on the post method and use that in the URL you're posting to:

您确定要发布的路径是否完整?您应该在post方法上定义另一个Path注释,并在您要发布到的URL中使用它:

@Path("/data")
public class PostData {
    @Path("/postStatus")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public StatusBean post(StatusBean sb) {
        System.out.println(sb);
        return sb;
    }
}

Then use the /data/postStatus path to post your request to:

然后使用/ data / postStatus路径将您的请求发布到:

<button id='btn' value="knapp" name="knapp" />
<script type="text/javascript">
    $('#btn').click(function(){
        $.ajax({
            url: '/data/postStatus',

            type: 'POST',
            contentType: 'application/json',
            data: {name:"Tony"},
            dataType: 'json'
        });
    })
</script>

#5


0  

You have probably forgotten to register the JSON mapper, i.e. Jackson (or whatever mapper you use). The feature is not enabled automatically, you have to load the class in your ResourceConfig:

您可能忘记注册JSON映射器,即Jackson(或您使用的任何映射器)。该功能未自动启用,您必须在ResourceConfig中加载该类:

org.glassfish.jersey.jackson.JacksonFeature.class

sample

样品

also, see JSON howto

另外,请参阅JSON howto

#1


2  

  1. Try making your bean serializable.

    尝试使您的bean可序列化。

    @XmlRootElement
    
    public class StatusBean implements Serializable {
    ....
    }
    
  2. Check your POST url. It should be `

    检查你的POST网址。它应该是`

    http://localhost:9998/{projectname}/{restservletmapping}/data

    HTTP://本地主机:9998 / {项目名称} / {restservletmapping} /数据

    For example, if my web.xml looks like this and my project name is SampleProject

    例如,如果我的web.xml看起来像这样,我的项目名称是SampleProject

    <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    

    URL would be : http://localhost:9998/SampleProject/rest/data

    URL将是:http:// localhost:9998 / SampleProject / rest / data

    You can use tools for testing REST services like SOAP UI or browser addons like POSTMAN, REST CONSOLE, etc.

    您可以使用工具来测试REST服务,如SOAP UI或浏览器插件,如POSTMAN,REST CONSOLE等。

  3. If above things are fine and REST service is giving response with testing tools. Then it could be problem of Cross Origin Policy in ajax.

    如果上面的事情很好,REST服务就会通过测试工具给出响应。那么它可能是ajax中的跨源策略问题。

#2


2  

I had the same problem. The issue is that your data is not converted to JSON string automatically. So you just need to call JSON.stringify(...) on your data before posting it:

我有同样的问题。问题是您的数据未自动转换为JSON字符串。所以你只需要在发布数据之前调用JSON.stringify(...):

<button id='btn' value="knapp" name="knapp" />
<script type="text/javascript">
$('#btn').click(function(){
    $.ajax({
        url: '/data',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({name:"Tony"}),
        dataType: 'json'
    });
})
</script>

This should work.

这应该工作。

#3


1  

From your server config I see that you haven't configured JAX-RS with Grizzly. On the base of that example you should somehow pass such property

从您的服务器配置中我发现您还没有使用Grizzly配置JAX-RS。在该示例的基础上,您应该以某种方式传递此类属性

Map<String,String> initParams = new HashMap<String, String>();
initParams.put( "com.sun.jersey.config.property.packages", "package.with.your.StatusBean.class" );

Another configuration option is to use

另一种配置选项是使用

ResourceConfig rc = new PackagesResourceConfig("your.package.with.resources");

and start grizzly server:

并启动grizzly服务器:

GrizzlyServerFactory.createHttpServer(BASE_URI, rc);

See details: http://jersey.java.net/nonav/documentation/latest/user-guide.html (Chapter "Deploying the root resource"). Try to run first example they have.

请参阅详细信息:http://jersey.java.net/nonav/documentation/latest/user-guide.html(“部署根资源”一章)。尝试运行他们拥有的第一个示例。

#4


0  

Are you sure that the path you're posting to is complete? You should define another Path annotation on the post method and use that in the URL you're posting to:

您确定要发布的路径是否完整?您应该在post方法上定义另一个Path注释,并在您要发布到的URL中使用它:

@Path("/data")
public class PostData {
    @Path("/postStatus")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public StatusBean post(StatusBean sb) {
        System.out.println(sb);
        return sb;
    }
}

Then use the /data/postStatus path to post your request to:

然后使用/ data / postStatus路径将您的请求发布到:

<button id='btn' value="knapp" name="knapp" />
<script type="text/javascript">
    $('#btn').click(function(){
        $.ajax({
            url: '/data/postStatus',

            type: 'POST',
            contentType: 'application/json',
            data: {name:"Tony"},
            dataType: 'json'
        });
    })
</script>

#5


0  

You have probably forgotten to register the JSON mapper, i.e. Jackson (or whatever mapper you use). The feature is not enabled automatically, you have to load the class in your ResourceConfig:

您可能忘记注册JSON映射器,即Jackson(或您使用的任何映射器)。该功能未自动启用,您必须在ResourceConfig中加载该类:

org.glassfish.jersey.jackson.JacksonFeature.class

sample

样品

also, see JSON howto

另外,请参阅JSON howto