отправка списка / карты в качестве параметра POST

Я хочу отправить объект HashMap в ресурс ReST как переменную POST. Я использовал class Form для отправки объекта. Код клиента:

 public static void main(String[] args) { ClientConfig config = new DefaultClientConfig(); Client client = Client.create(config); WebResource service = client.resource(getBaseURI()); HashMap hashmap = new HashMap(); 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 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 newProj(@FormParam("data1") HashMap postVarMap, @Context HttpServletResponse response) { System.out.println(postVarMap); MultivaluedMap 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 предназначен для получения общей карты параметров формы, например параметров, представленных вашей службе через HTTP-запрос POST. Предполагается, что он будет использоваться следующим образом:

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

Однако, когда вашему клиентскому приложению необходимо предоставить вашему REST-сервису какие-то данные (в вашем случае HashMap содержащий, я полагаю, много важной информации), он сначала выполнит Сериализацию XML, а затем отправит его в службу, которая затем десериализует и использовать его. К сожалению, Джерси не в состоянии автоматически маршалировать / разворачивать HashMap поэтому, если вы только что предоставили параметр HashMap в вашем методе newProj , вы получите исключение.

Итак, как отправить HashMap на ваш сервис? Ну, ключ – JAXB @XmlRootElement и пользовательский XmlAdapter 🙂

Сначала вам нужно написать свою собственную оболочку для карты. @XmlRootElement будет аннотирована с помощью @XmlRootElement

 @XmlRootElement public class MyHashMapObject { private Map mapProperty; public MyHashMapObject() { mapProperty = new HashMap(); } @XmlJavaTypeAdapter(MapAdapter.class) // NOTE: Our custom XmlAdaper public Map getMapProperty() { return mapProperty; } public void setMapProperty(Map 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> { public MapElement[] marshal(Map arg0) throws Exception { MapElement[] mapElements = new MapElement[arg0.size()]; int i = 0; for (Map.Entry entry : arg0.entrySet()) mapElements[i++] = new MapElement(entry.getKey(), entry.getValue()); return mapElements; } public Map unmarshal(MapElement[] arg0) throws Exception { Map r = new HashMap(); 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 post( MyHashMapObject 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 map = new MyHashMapObject(); 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 myMap = response.getEntity(MyHashMapObject.class).getMapProperty(); for(Map.Entry 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 в службу REST. Вы также можете сделать реализацию более универсальной. Надеюсь это поможет.

отправить карту как тело запроса POST

 @POST @Produces("application/json") @Consumes("application/json") @Path("/sendUser") public Response sendUser(Map 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 usersMap = new HashMap<>(); usersMap.put("Name","Johm"); usersMap.put("Family","WRKlein"); usersMap.put("Phone","87540255"); usersMap.put("Mobile", "112458033"); return Response.ok(usersMap).build(); } 

Вы можете использовать JSON.stringify (myMap) в javascript и, таким образом, передать строчную карту в качестве параметра формы.

В java вы разбираете строку обратно на такую ​​карту:

  @Path("doStuff") @POST @Produces(MediaType.APPLICATION_JSON) public void doStuff(@FormParam("mapAsJson") String mapAsJson) throws JsonParseException, JsonMappingException, IOException { @SuppressWarnings("unchecked") HashMap mapFromJson = (HashMap)new ObjectMapper().readValue(mapAsJson, HashMap.class); //add your processing } 
  • Сочетание весеннего проекта и Джерси
  • Как обрабатывать redirect Spring Boot в / error?
  • Как использовать поддержку JSON POJO в Джерси?
  • Инъекционная инъекция с Джерси 2.0
  • JAX-RS с использованием механизмов исключения
  • Аутентификация пользователя на службе Джерси REST
  • RESTful на Play! фреймворк
  • Поймать все Исключения, а также вернуть пользовательские ошибки в Джерси
  • Как установить соединение и тайм-аут чтения с помощью Jersey 2.x?
  • AbstractMethodError с использованием UriBuilder на JAX-RS
  • Джерси + jackson JSON формат даты формат - как изменить формат или использовать пользовательские JacksonJsonProvider
  • Interesting Posts

    Что означает int argc, char * argv ?

    Обновление конфликта конфликтов для игровых сервисов 9.4.0 Android studio 2.2

    Bootstrap 3 точки останова и медиа-запросы

    Копирование базы данных PostgreSQL на другой сервер

    Окно 8: использование ОЗУ (память)

    Матричная обратная точность

    Ethernet (интранет) и Wi-Fi (Интернет) для совместной работы

    Процедура с аргументом фиктивного аргумента предполагаемой формы должна иметь явный интерфейс

    Не удается избежать обратного слэша с помощью регулярного выражения?

    Завершение сеанса StopWatch с помощью делегата или lambda?

    Решение «Экземпляр ObjectContext был удален и больше не может использоваться для операций, требующих подключения» InvalidOperationException

    Невозможно выполнить загрузку после удаленного системного зарезервированного раздела

    Символ не найден: __PyCodecInfo_GetIncrementalDecoder

    Gradle для выполнения Java-classа (без изменения build.gradle)

    Прокрутка страницы вверх или вниз в Selenium WebDriver (Selenium 2) с использованием java

    Давайте будем гением компьютера.