当前位置: 首页 > 面试题库 >

发送列表/地图作为POST参数jersey

上官砚文
2023-03-14
问题内容

我想将HashMap对象作为POST变量发送到ReST资源。我使用Form该类发送对象。客户端代码:

public static void main(String[] args)
    {
        ClientConfig config = new DefaultClientConfig();
        Client client = Client.create(config);
        WebResource service = client.resource(getBaseURI());

        HashMap<String, String> hashmap = new HashMap<String, String>();
        hashmap.put("Key1", "value1");
        hashmap.put("Key2", "value2");
        Form form = new Form();

        form.add("data1", hashmap);

        ClientResponse response = service.path("hello2").path("hello2").type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, form);
        @SuppressWarnings("unchecked")
        MultivaluedMap<String, String> map = response.getEntity(MultivaluedMap.class);
        System.out.println(map.get("response").get(0));
        System.out.println(map.get("response2"));
    }

REST资源如下:

@Path("/hello2")
public class FormResource
{
    @Context
    UriInfo uriInfo;
    @Context
    Request request;

    public FormResource()
    {
    }

    public FormResource(UriInfo uriInfo, Request request)// , String data1)
    {
        this.uriInfo = uriInfo;
        this.request = request;
    }

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public MultivaluedMap<String, String> newProj(@FormParam("data1") HashMap<String, String> postVarMap, @Context HttpServletResponse response)
    {

        System.out.println(postVarMap);
        MultivaluedMap<String, String> hash = new MultivaluedMapImpl();
        hash.add("response", "response1");
        hash.add("response", "response2");
        hash.add("response2", "fbshabfsdb");
        URI uri = uriInfo.getAbsolutePathBuilder().build();
        Response.created(uri).build();
        return hash;
    }

}

我在Tomcat 6.0日志中收到以下异常

Dec 7, 2011 3:38:39 PM org.apache.catalina.core.StandardContext reload
INFO: Reloading Context with name [/JerCDemo] has started
Dec 7, 2011 3:38:40 PM com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
  com.reflexis.nbe.jersey
Dec 7, 2011 3:38:40 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
  class com.reflexis.nbe.jersey.FormResource
Dec 7, 2011 3:38:40 PM com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
Dec 7, 2011 3:38:40 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.9.1 09/14/2011 02:05 PM'
Dec 7, 2011 3:38:40 PM com.sun.jersey.spi.inject.Errors processErrorMessages
SEVERE: The following errors and warnings have been detected with resource and/or provider classes:
  SEVERE: Missing dependency for method public javax.ws.rs.core.MultivaluedMap com.reflexis.nbe.jersey.FormResource.newProj(java.util.HashMap,javax.servlet.http.HttpServletResponse) at parameter at index 0
  SEVERE: Missing dependency for method public javax.ws.rs.core.MultivaluedMap com.reflexis.nbe.jersey.FormResource.newProj(java.util.HashMap,javax.servlet.http.HttpServletResponse) at parameter at index 0
  SEVERE: Method, public javax.ws.rs.core.MultivaluedMap com.reflexis.nbe.jersey.FormResource.newProj(java.util.HashMap,javax.servlet.http.HttpServletResponse), annotated with POST of resource, class com.reflexis.nbe.jersey.FormResource, is not recognized as valid resource method.
Dec 7, 2011 3:38:40 PM org.apache.catalina.core.ApplicationContext log
SEVERE: StandardWrapper.Throwable
com.sun.jersey.spi.inject.Errors$ErrorMessagesException
    at com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170)
    at com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:136)
    at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:199)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:771)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:766)
    at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:488)
    at com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.initiate(ServletContainer.java:318)
    at com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:609)
    at com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:210)
    at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:373)
    at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:556)
    at javax.servlet.GenericServlet.init(GenericServlet.java:212)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4420)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4733)
    at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3460)
    at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426)
    at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1357)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1649)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1658)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1658)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1638)
    at java.lang.Thread.run(Thread.java:619)
Dec 7, 2011 3:38:40 PM org.apache.catalina.core.StandardContext loadOnStartup
SEVERE: Servlet /JerCDemo threw load() exception
com.sun.jersey.spi.inject.Errors$ErrorMessagesException
    at com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170)
    at com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:136)
    at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:199)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:771)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:766)
    at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:488)
    at com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.initiate(ServletContainer.java:318)
    at com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:609)
    at com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:210)
    at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:373)
    at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:556)
    at javax.servlet.GenericServlet.init(GenericServlet.java:212)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4420)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4733)
    at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3460)
    at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426)
    at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1357)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1649)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1658)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1658)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1638)
    at java.lang.Thread.run(Thread.java:619)

我写的客户代码正确吗?还有其他方法可以将HashMap对象作为POST变量发送吗?


问题答案:

只是为了清除一些东西。本MultivaluedMap<String, String>是为了用于获得通过的HTTP
POST请求提交到您的服务形式参数如参数一般地图。应该这样使用:

   @POST
   @Consumes("application/x-www-form-urlencoded")
   public void post(MultivaluedMap<String, String> formParams) {
     // Store the message
   }

但是,当您的客户端应用程序需要向REST服务提供某种数据(在您的情况下HashMap,我想包含很多重要信息)时,它将首先将其序列化为XML,然后将其发送到该服务,然后反序列化并用它。不幸的是,Jersey无法自动编组/
unmmarshal,HashMap因此,如果您仅HashMapnewProj方法中提供了参数,则会出现异常。

那么如何将HashMap发送到您的服务呢?好吧,关键是JAXB @XmlRootElement和自定义XmlAdapter:-)

首先,您需要为地图编写自己的包装器。包装器将带有注释@XmlRootElement

@XmlRootElement
public class MyHashMapObject<T, U> {
    private Map<T, U> mapProperty;

    public MyHashMapObject() {
        mapProperty = new HashMap<T, U>();
    }

    @XmlJavaTypeAdapter(MapAdapter.class) // NOTE: Our custom XmlAdaper
    public Map<T, U> getMapProperty() {
        return mapProperty;
    }

    public void setMapProperty(Map<T, U> map) {
        this.mapProperty = map;
    }
}

然后,您需要定义“启用了JAXB”的地图元素:

public class MapElement {
    @XmlElement
    public String key;
    @XmlElement
    public String value;

    private MapElement() {
    }

    public MapElement(String key, String value) {
        this.key = key;
        this.value = value;
    }
}

最后定义您的自定义XmlAdapter:

public class MapAdapter extends XmlAdapter<MapElement[], Map<String, String>> {
    public MapElement[] marshal(Map<String, String> arg0) throws Exception {
        MapElement[] mapElements = new MapElement[arg0.size()];
        int i = 0;
        for (Map.Entry<String, String> entry : arg0.entrySet())
            mapElements[i++] = new MapElement(entry.getKey(), entry.getValue());

        return mapElements;
    }

    public Map<String, String> unmarshal(MapElement[] arg0) throws Exception {
        Map<String, String> r = new HashMap<String, String>();
        for (MapElement mapelement : arg0)
            r.put(mapelement.key, mapelement.value);
        return r;
    }
}

一旦所有这些都就绪(必须由您的服务和客户端使用,因此将其放入一个碎片罐中),就可以像下面这样定义您的服务:

@Path("/hello")
public class FormResource
{
    //@GET
    @POST
    @Produces(MediaType.APPLICATION_XML)
    @Consumes(MediaType.APPLICATION_XML)
    public MyHashMapObject<String, String> post(
                MyHashMapObject<String, String> anotherMap) {

        anotherMap.getMapProperty().put("e", "10");
        anotherMap.getMapProperty().put("f", "11");
        anotherMap.getMapProperty().put("g", "12");

        return anotherMap;
    }
}

你们都准备好了。您的客户应该这样:

   public class Test {  
      public static void main(String[] args) {
            ClientConfig config = new DefaultClientConfig();
            Client client = Client.create(config);
            WebResource service = client.resource(getBaseURI());

            // Now do the MAP stuff
            MyHashMapObject<String, String> map = new MyHashMapObject<String, String>();
            map.getMapProperty().put("a", "1");
            map.getMapProperty().put("b", "2");

            ClientResponse response = service.path("rest").path("hello2")
                .type(MediaType.APPLICATION_XML)
                .accept(MediaType.APPLICATION_XML)
                .post(ClientResponse.class, map);

            Map<String, String> myMap = response.getEntity(MyHashMapObject.class).getMapProperty();     
            for(Map.Entry<String, String> entry : myMap.entrySet())
                System.out.format("Key: %s, Value: %s\n", entry.getKey(), entry.getValue());

        }

        private static URI getBaseURI() {
            return UriBuilder.fromUri(
                    "http://localhost:8080/org.nowaq.jersey.first").build();
        }
    }

现在,您可以轻松地将您的数据传递HashMap<String, String>给REST服务。您还可以使实现更加通用。希望这可以帮助。



 类似资料:
  • 问题内容: 我想发送一个字符串作为ajax Post参数。 如下代码: 不管用。为什么? 问题答案: 尝试这样:

  • 我正在尝试使用Chrome扩展Postman测试一个简单的PHP页面。当我发送URL参数时,脚本运行良好(例如变量在参数中可用)。当我将它们作为参数发送时,参数仅包含。 剧本: 我错过了什么?

  • 我是Android的新手,现在我在做一个应用,这个应用我需要把数据发送到服务器上,现在我用的是Volley post方法,但是当我用Volley发送数据到服务器上的时候,参数总是显示为空,这里我附上了代码,请检查一下,这里我用的是片段。

  • 问题内容: 是否可以在GET调用中将map作为参数发送?我搜索了,我可以找到列表并设置集合。但是没有找到任何要收集地图的东西。 我尝试了以下方法,我的控制器方法如下所示。 我从邮递员发送了以下请求 一切正常,没有错误和异常。但是我收到的地图看起来像 我希望收到的地图像 问题答案: 这在Spring MVC指南中有记录: 当将注释声明为或参数时,将使用所有请求参数填充地图。 这意味着您当前得到的响应

  • 我有一个api URL:https://orderingspace.com/api/search Body parameter:lat:48.8834553 log:2.3399433 miles:6

  • 问题内容: 我有一个非常长的数组和字符串,我想通过Alamofire发送,尽管我不知道如何将原始JSON作为参数发送。JSON看起来有点像 除了让它表现得像Swift数组然后进行序列化外,还有什么方法可以将这个JSON作为Alamofire中的参数传递? 谢谢! 编辑: 我能够在文本编辑器中发挥一些魔力来获取以Swift数组样式设置的参数(如所示),因此根据Eric的建议,将和制作成Diction