如何使用拦截器配置Jsonp和CXF

时间:2013-06-07 13:53:00

标签: rest jsonp cxf jax-rs interceptor

我正在开发一个restful WS,我想让用户选择以XML或Json的形式从我的WS中取回数据,并且如果他们想要Jsonp,也可以选择一个回调函数。这是我迄今为止所拥有的,而拦截器的部分基于CXF - JAX-RS : Data Bindings

我的休息服务:

@GET
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ "application/x-javascript", MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getServers(@Context ServletContext context,
        @Context Request request,
        @QueryParam("format") String format,
        @QueryParam("callback") String callback) {

some code where server object is created....

    if(format.equals("json"){

        if(callback!= null){
            response = Response.status(Status.OK).type("application/x-javascript")
                        .entity(server).build();
        }else{
            response = Response.status(Status.OK).type("application/json")
                        .entity(server).build();
        }

    } else {
    response = Response.status(Status.OK).type("application/xml")
                        .entity(server).build();
    }
    return response;
}

我的服务器对象:

@XmlRootElement (name="Server")
public class Server implements Serializable {

    private String name=null;
    private String hardware = null;

    public Server(){

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getHardware() {
        return hardware;
    }

    public void setHardware(String hardware) {
        this.hardware = hardware;
    }

}

WEB-INF中的my beans.xml:

<?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:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />

  <context:property-placeholder/>
  <context:annotation-config/>
  <bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer"/>
  <bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"/>

   <jaxrs:server id="services" address="/">
    <jaxrs:serviceBeans>
      <bean class="com.ba.serversws_cxf.resources.MyResource" />
    </jaxrs:serviceBeans>

    <jaxrs:inInterceptors>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpInInterceptor">
        <property name="callbackParam" value="callback"/>
       </bean>
    </jaxrs:inInterceptors>
    <jaxrs:outInterceptors>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPreStreamInterceptor">
            <property name="mediaType" value="application/x+javascript"/>
       </bean>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPostStreamInterceptor"/>
    </jaxrs:outInterceptors>

    <jaxrs:providers>
        <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
    </jaxrs:providers>
    </jaxrs:server>

</beans>

设置查询参数“callback”时出现的错误是:

org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor writeResponseErrorMessage
WARNING: No message body writer has been found for response class Server.

它适用于其他两种情况。

我已经寻找解决方案,但仍然没有。

有什么想法吗?

由于

1 个答案:

答案 0 :(得分:0)

以下是@Overrides wrtieTo() org.apache.cxf.jaxrs.provider.json.JSONProvider;方法的<jaxrs:extensionMappings>

首先,在我的beans.xml文件中,我使用了jsonp并且我声明了<jaxrs:server id="services" address="/"> <jaxrs:extensionMappings> <entry key="xml" value="application/xml" /> <entry key="json" value="application/json" /> <entry key="jsonp" value="application/javascript"/> </jaxrs:extensionMappings> </jaxrs:server> 扩展名。

这是代码

writeTo()

以下是我@Override <{1}}方法的代码import java.io.IOException; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import org.apache.cxf.jaxrs.provider.json.JSONProvider; import org.apache.cxf.jaxrs.utils.HttpUtils; @SuppressWarnings("rawtypes") @Produces("application/javascript") public class JsonpProvider extends JSONProvider { @SuppressWarnings("unchecked") @Override public void writeTo(Object obj, Class cls, Type genericType, Annotation[] anns, MediaType m, MultivaluedMap headers, OutputStream os) throws IOException { String requestURI = getContext().getHttpServletRequest() .getRequestURI(); if (requestURI.contains(".jsonp")) { String prefix = getContext().getHttpServletRequest().getParameter( "_jsonp"); if (prefix != null && !prefix.isEmpty()) { os.write(prefix.getBytes(HttpUtils.getSetEncoding(m, headers, "UTF-8"))); } else { os.write("callback".getBytes(HttpUtils.getSetEncoding(m, headers, "UTF-8"))); } os.write('('); super.writeTo(obj, cls, genericType, anns, m, headers, os); os.write(')'); } else { super.writeTo(obj, cls, genericType, anns, m, headers, os); } } }

.jsonp

所以我在上面的代码中正在做的是检查是否已经为URL提供了_jsonp扩展名。如果是,那么我知道我必须使用回调函数返回jsopn。最后一件事是设置回调函数的名称。如果用户已将_jsonp查询参数设置为URL,则此参数的值将是回调函数的名称。如果callback pquery参数为null,那么我放置一个defult名称beans.xml

当你在json文件中作为<jaxrs:providers> <bean class="org.apache.cxf.jaxrs.ext.search.SearchContextProvider"/> <bean class="com.ba.serversws_cxf.utils.JsonpProvider"> <property name="ignoreNamespaces" value="true" /> <property name="dropRootElement" value="false" /> <property name="supportUnwrapped" value="true" /> </bean> </jaxrs:providers> 提供程序时,你将JsonpProvider放在上面:

{{1}}

希望能帮助@bhuvan!