Добавить все функции для WordPress сайта в версии AMP

Если мы посмотрим, что пытается сделать OP, он пытается опубликовать два (возможно, несвязанных) объекта JSON. Прежде всего, любое решение попробовать и отправить одну часть в качестве тела, а одна часть как другой параметр IMO - это ужасные решения. Данные POST должны поступать в тело. Неправильно делать что-то только потому, что оно работает. Некоторые работы могут нарушать основные принципы REST.

Я вижу несколько решений

  1. Использовать приложение / x-www-form-urlencoded
  2. Использовать Multipart
  3. Просто обернуть их в одном родительском объекте

1. Использовать приложение / x-www-form-urlencoded

Другой вариант - просто использовать application/x-www-form-urlencoded. Фактически мы можем иметь значения JSON. Для примера

curl -v http://localhost:8080/api/model \
     -d 'one={"modelOne":"helloone"}' \
     -d 'two={"modelTwo":"hellotwo"}'

public class ModelOne {
    public String modelOne;
}

public class ModelTwo {
    public String modelTwo;
}

@Path("model")
public class ModelResource {

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public String post(@FormParam("one") ModelOne modelOne,
                       @FormParam("two") ModelTwo modelTwo) {
        return modelOne.modelOne + ":" + modelTwo.modelTwo;
    }
}

Единственное, что нам нужно, чтобы заставить это работать, - это ParamConverterProvider, чтобы заставить это работать. Ниже приведена версия, которая была реализована Михалом Гаджосом из команды Джерси (здесь была найдена ).

@Provider
public class JacksonJsonParamConverterProvider implements ParamConverterProvider {

    @Context
    private Providers providers;

    @Override
    public  ParamConverter getConverter(final Class rawType,
                                              final Type genericType,
                                              final Annotation[] annotations) {
        // Check whether we can convert the given type with Jackson.
        final MessageBodyReader mbr = providers.getMessageBodyReader(rawType,
                genericType, annotations, MediaType.APPLICATION_JSON_TYPE);
        if (mbr == null
              || !mbr.isReadable(rawType, genericType, annotations, MediaType.APPLICATION_JSON_TYPE)) {
            return null;
        }

        // Obtain custom ObjectMapper for special handling.
        final ContextResolver contextResolver = providers
                .getContextResolver(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE);

        final ObjectMapper mapper = contextResolver != null ?
                contextResolver.getContext(rawType) : new ObjectMapper();

        // Create ParamConverter.
        return new ParamConverter() {

            @Override
            public T fromString(final String value) {
                try {
                    return mapper.reader(rawType).readValue(value);
                } catch (IOException e) {
                    throw new ProcessingException(e);
                }
            }

            @Override
            public String toString(final T value) {
                try {
                    return mapper.writer().writeValueAsString(value);
                } catch (JsonProcessingException e) {
                    throw new ProcessingException(e);
                }
            }
        };
    }
}

Если вы не просматриваете ресурсы и поставщиков, просто зарегистрируйте этого поставщика, и приведенный выше пример должен работать.

2. Использование Multipart

Одно из решений, о котором никто не упомянул, заключается в использовании multipart . Это позволяет нам отправлять произвольные части в запрос. Поскольку каждый запрос может иметь только один объект, многопроцессор - это работа вокруг, поскольку он позволяет иметь разные части (с их собственными типами контента) как часть тела сущности.

Вот пример использования Джерси (см. официальный doc здесь )

Зависимость


    org.glassfish.jersey.media
    jersey-media-multipart
    ${jersey-2.x.version}

Зарегистрируйте класс MultipartFeature

import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;

@ApplicationPath("/api")
public class JerseyApplication extends ResourceConfig {

    public JerseyApplication() {
        packages("stackoverflow.jersey");
        register(MultiPartFeature.class);
    }
}

Resource

g32]

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.media.multipart.FormDataParam;

@Path("foobar")
public class MultipartResource {

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response postFooBar(@FormDataParam("foo") Foo foo,
                               @FormDataParam("bar") Bar bar) {
        String response = foo.foo + "; " + bar.bar;
        return Response.ok(response).build();
    }

    public static class Foo {
        public String foo;
    }

    public static class Bar {
        public String bar;
    }
}

Теперь сложная часть с некоторыми клиентами заключается в том, что не существует способа установить Content-Type каждой части тела, что требуется для работы вышеприведенного. Многостраничный провайдер будет искать устройство чтения сообщений, основанное на типе каждой части. Если он не установлен на application/json или тип, для Foo или Bar будет читатель, это не удастся. Мы будем использовать JSON здесь. Нет никакой дополнительной конфигурации, кроме как иметь доступный читатель. Я буду использовать Джексона. При использовании следующей зависимости никакая другая конфигурация не требуется, так как поставщик будет обнаружен через сканирование классов.


    org.glassfish.jersey.media
    jersey-media-json-jackson
    ${jersey-2.x.version}

Теперь тест. Я буду использовать cURL . Вы можете видеть, что я явно установил Content-Type для каждой части с type. -F означает разную часть. (См. Очень низкую позицию для представления о том, как выглядит тело запроса.)

curl -v -X POST \ -H "Content-Type:multipart/form-data" \ -F "bar={\"bar\":\"BarBar\"};type=application/json" \ -F "foo={\"foo\":\"FooFoo\"};type=application/json" \ http://localhost:8080/api/foobar Результат: FooFoo; BarBar

blockquote>

Результат как мы и ожидали. Если вы посмотрите на метод ресурса, все, что мы делаем, это вернуть эту строку foo.foo + "; " + bar.bar, собранную из двух объектов JSON.

Вы можете увидеть некоторые примеры, используя несколько разных клиентов JAX-RS, в ссылках ниже , Вы также увидите пример на стороне сервера из этих различных реализаций JAX-RS. В каждой ссылке должно быть где-то в нем ссылка на официальную документацию для этой реализации

Там есть другие реализации JAX-RS, но вам нужно будет найти документацию для него самостоятельно. Вышеупомянутые три являются единственными, с которыми у меня есть опыт.

Что касается клиентов Javascript, то большинство примеров, которые я вижу (например, , некоторые из этих включают установку Content-Type на undefined / false (используя FormData), позволяя обозревателю обработать его, но это не сработает для нас, так как браузер не будет устанавливать Content-Type для каждой части. И тип по умолчанию - text/plain.

Я уверен, что есть библиотеки, которые позволяют устанавливать тип для каждой части, но просто чтобы показать вам, как это можно сделать вручную, я отправлю пример (получил небольшую помощь от здесь . Я буду использовать Angular, но ворчание работы по созданию тела объекта будет простым старым Javascript.



    
        
        
    
    
        

{{result}}

Интересной частью является функция createRequest. где мы построим multipart, установив Content-Type каждой части в application/json и объединив стробированные объекты foo и bar к каждой части. Если вы не знакомы с многостраничным см. здесь для получения дополнительной информации . Другая интересная часть - это заголовок. t до multipart/form-data.

Ниже приведен результат. В Angular я использовал результат, чтобы показать в HTML, с $scope.result = response.data. Кнопка, которую вы видите, просто должна была сделать запрос. Вы также увидите данные запроса в firebug

enter image description here [/g15]

3. Просто заверните их в один родительский объект

Этот параметр должен быть понятным, как это уже упоминалось другими.

0
задан Hugo Sum 18 January 2019 в 09:58
поделиться