Это не совсем из коробки, но CXF поддерживает привязки JSON к остальным сервисам.См. cxf jax-rs json документы здесь. Вам все равно нужно будет выполнить некоторую минимальную настройку, чтобы поставщик был доступен, и вам нужно быть знакомым с Jettison, если вы хотите иметь больше контроля над тем, как работает JSON.сформированный.
РЕДАКТИРОВАТЬ: Для запроса комментария, вот некоторый код.У меня нет большого опыта с этим, но следующий код работал в качестве примера в системе быстрого тестирования.
//TestApi parts
@GET
@Path ( "test" )
@Produces ( "application/json" )
public Demo getDemo () {
Demo d = new Demo ();
d.id = 1;
d.name = "test";
return d;
}
//client config for a TestApi interface
List providers = new ArrayList ();
JSONProvider jsonProvider = new JSONProvider ();
Map<String, String> map = new HashMap<String, String> ();
map.put ( "http://www.myserviceapi.com", "myapi" );
jsonProvider.setNamespaceMap ( map );
providers.add ( jsonProvider );
TestApi proxy = JAXRSClientFactory.create ( url, TestApi.class,
providers, true );
Demo d = proxy.getDemo ();
if ( d != null ) {
System.out.println ( d.id + ":" + d.name );
}
//the Demo class
@XmlRootElement ( name = "demo", namespace = "http://www.myserviceapi.com" )
@XmlType ( name = "demo", namespace = "http://www.myserviceapi.com",
propOrder = { "name", "id" } )
@XmlAccessorType ( XmlAccessType.FIELD )
public class Demo {
public String name;
public int id;
}
Примечания:
- Список поставщиков, гдеВы настраиваете код JSON-провайдера на клиенте.В частности, вы видите отображение пространства имен.Это должно соответствовать конфигурации вашего сервера.Я не очень разбираюсь в параметрах Jettison, поэтому я не сильно помогаю манипулировать всеми различными регуляторами для управления процессом маршаллинга.
- Jettison в CXF работает путем маршаллинга XML из JAXB-провайдера в JSON.Таким образом, вы должны убедиться, что все объекты полезной нагрузки размечены (или иным образом сконфигурированы) для маршалинга как application / xml, прежде чем вы сможете сделать так, чтобы они маршалировали как JSON.Если вы знаете, как обойти это (кроме написания собственного автора тела сообщения), я хотел бы услышать об этом.
- Я использую Spring на сервере, поэтому в моей конфигурации есть все, что связано с XML.По сути, вам нужно пройти через тот же процесс, чтобы добавить JSONProvider в службу с той же конфигурацией пространства имен.У меня нет кода для этого, но я думаю, что он достаточно хорошо отразит на стороне клиента.
В качестве примера это немного грязно, но, надеюсь, поможет вам.
Edit2: Пример средства записи тела сообщения, основанного на xstream, чтобы избежать jaxb.
@Produces ( "application/json" )
@Consumes ( "application/json" )
@Provider
public class XstreamJsonProvider implements MessageBodyReader<Object>,
MessageBodyWriter<Object> {
@Override
public boolean isWriteable ( Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType ) {
return MediaType.APPLICATION_JSON_TYPE.equals ( mediaType )
&& type.equals ( Demo.class );
}
@Override
public long getSize ( Object t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType ) {
// I'm being lazy - should compute the actual size
return -1;
}
@Override
public void writeTo ( Object t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream )
throws IOException, WebApplicationException {
// deal with thread safe use of xstream, etc.
XStream xstream = new XStream ( new JettisonMappedXmlDriver () );
xstream.setMode ( XStream.NO_REFERENCES );
// add safer encoding, error handling, etc.
xstream.toXML ( t, entityStream );
}
@Override
public boolean isReadable ( Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType ) {
return MediaType.APPLICATION_JSON_TYPE.equals ( mediaType )
&& type.equals ( Demo.class );
}
@Override
public Object readFrom ( Class<Object> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream )
throws IOException, WebApplicationException {
// add error handling, etc.
XStream xstream = new XStream ( new JettisonMappedXmlDriver () );
return xstream.fromXML ( entityStream );
}
}
//now your client just needs this
List providers = new ArrayList ();
XstreamJsonProvider jsonProvider = new XstreamJsonProvider ();
providers.add ( jsonProvider );
TestApi proxy = JAXRSClientFactory.create ( url, TestApi.class,
providers, true );
Demo d = proxy.getDemo ();
if ( d != null ) {
System.out.println ( d.id + ":" + d.name );
}
В примере кода отсутствуют части для поддержки надежного типа носителя, обработки ошибок, потокабезопасность и т. д. Но это должно помочь вам решить проблему jaxb с минимальным кодом.
EDIT 3 - пример конфигурации на стороне сервера Как я уже говорил, на стороне сервера настроена пружина.Вот пример конфигурации, которая работает для подключения к провайдеру:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<jaxrs:server id="TestApi">
<jaxrs:serviceBeans>
<ref bean="testApi" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean id="xstreamJsonProvider" class="webtests.rest.XstreamJsonProvider" />
</jaxrs:providers>
</jaxrs:server>
<bean id="testApi" class="webtests.rest.TestApi">
</bean>
</beans>
Я также отметил, что в последней используемой мной версии cxf есть разница в типах носителей, поэтому примервыше, для чтения / записи тела сообщения xstream требуется быстрая модификация, где isWritable / isReadable изменяется на:
return MediaType.APPLICATION_JSON_TYPE.getType ().equals ( mediaType.getType () )
&& MediaType.APPLICATION_JSON_TYPE.getSubtype ().equals ( mediaType.getSubtype () )
&& type.equals ( Demo.class );
EDIT 4 - конфигурация без пружины Используя выбранный контейнер сервлета, настройте
org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
по крайней мере с 2 параметрами инициализации:
jaxrs.serviceClasses
jaxrs.providers
, где serviceClasses - это список разделенных пробелами реализаций службы, которые вы хотите связать, таких как TestApi, упомянутый выше, ипоставщики - это список поставщиков тела сообщения, разделенных пробелами, например, упомянутый выше XstreamJsonProvider.В tomcat вы можете добавить следующее в web.xml:
<servlet>
<servlet-name>cxfservlet</servlet-name>
<servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
<init-param>
<param-name>jaxrs.serviceClasses</param-name>
<param-value>webtests.rest.TestApi</param-value>
</init-param>
<init-param>
<param-name>jaxrs.providers</param-name>
<param-value>webtests.rest.XstreamJsonProvider</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Это довольно быстрый способ запустить его без пружины.Если вы не используете контейнер сервлета, вам потребуется настроить JAXRSServerFactoryBean.setProviders с экземпляром XstreamJsonProvider и установить реализацию службы с помощью метода JAXRSServerFactoryBean.setResourceProvider.Проверьте метод CXFNonSpringJaxrsServlet.init, чтобы увидеть, как они это делают при установке в контейнере сервлета.
Это должно помочь вам в любом случае.