我想将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变量发送?
答案 0 :(得分:31)
只是为了清楚一点。 MultivaluedMap<String, String>
旨在用于获取表单参数的一般映射,例如通过POST HTTP请求提交给您的服务的参数。它应该像这样使用:
@POST
@Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
// Store the message
}
但是,当您的客户端应用程序需要为您的REST服务提供某种数据时(在您的情况下,HashMap
包含我认为很多重要信息)它会先将其序列化为XML,然后发送它到服务,然后反序列化和使用它。不幸的是,泽西岛无法自动编组/解组HashMap
,因此,如果您在HashMap
方法中提供newProj
参数,则会出现例外情况。
那么如何将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;
}
}
一旦你完成了所有这些(它必须由你的服务和客户端使用,所以把它放到一些shard jar),你可以像这样定义你的服务:
@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服务。您还可以使实现更通用。希望这会有所帮助。
答案 1 :(得分:2)
将Map作为POST请求正文发送
@POST
@Produces("application/json")
@Consumes("application/json")
@Path("/sendUser")
public Response sendUser(Map<String,String> usersMap) {
String name = usersMap.get("Name");
// first check for existing key
String family = usersMap.get("Family");
String phone = usersMap.get("Phone");
String mobile = usersMap.get("Mobile");
return Response.ok("Get user attributes successfully !").build();
}
从POST获取地图响应
@POST
@Produces("application/json")
@Consumes("application/json")
@Path("/getUser")
public Response getUser(String searchInputJsonString) {
Map<String,String> usersMap = new HashMap<>();
usersMap.put("Name","Johm");
usersMap.put("Family","W.R.Klein");
usersMap.put("Phone","87540255");
usersMap.put("Mobile", "112458033");
return Response.ok(usersMap).build();
}
答案 2 :(得分:2)
您可以在javascript中使用JSON.stringify(myMap),从而将stringyfied地图作为表单参数传递。
在java中,您将字符串解析回如下地图:
@Path("doStuff")
@POST
@Produces(MediaType.APPLICATION_JSON)
public void doStuff(@FormParam("mapAsJson") String mapAsJson) throws JsonParseException, JsonMappingException, IOException {
@SuppressWarnings("unchecked")
HashMap<String,String> mapFromJson = (HashMap<String,String>)new ObjectMapper().readValue(mapAsJson, HashMap.class);
//add your processing
}