使用jquery的getjson()遇到的跨域访问问题(二)——使用拦截器进行数据封装

时间:2022-08-28 20:06:18

上一篇我们提到了使用jsonp来解决getjson的跨域访问问题,服务器需要对数据进行一次封装,实际上jersey已经实现了这个功能,具体用法也很简单,加上@JSONP标识就行。
对上一篇的服务器代码进行修改:

    @GET
@JSONP(queryParam = "jsoncallback")
@Path("/test")
@Produces("application/json;charset=utf8")
public String go(){
return info;
}

其中queryparam给出了封装时使用的函数名,在客户端提交数据请求时,url地址就是****?jsoncallback=?

OK,这样就搞定了,当然了,如果需要更进一步的操作,比如说对输出的内容进行深度加工,那么可以参考jersey的实现,源代码在这里:JsonWithPaddingInterceptor.java

比如说同样的功能,自己来实现。看上边的源码,是用拦截器实现的,把源码修改下:

@javax.ws.rs.ext.Provider
public class JsonWithPaddingInterceptor implements WriterInterceptor {

private static final Map<String, Set<String>> JAVASCRIPT_TYPES;

static {
JAVASCRIPT_TYPES = new HashMap<>(2);

JAVASCRIPT_TYPES.put("application", Arrays.asList("x-javascript", "ecmascript", "javascript")
.stream().collect(Collectors.toSet()));
JAVASCRIPT_TYPES.put("text", Arrays.asList("javascript", "x-javascript", "ecmascript", "jscript")
.stream().collect(Collectors.toSet()));
}

@Inject
private Provider<ContainerRequest> containerRequestProvider;

/***实现具体操作的函数****/
@Override
public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
String callbackname = getCallbackName();

if (callbackname!=null) {
context.setMediaType(MediaType.APPLICATION_JSON_TYPE);
context.getOutputStream().write(callbackname.getBytes(MessageUtils.getCharset(context.getMediaType())));
context.getOutputStream().write('(');
}
//这里可以添加自己感兴趣的东西
context.proceed();

if (callbackname!=null) {
context.getOutputStream().write(')');
}
}


/**
* Returns a JavaScript callback name to wrap the JSON entity into. The callback name is determined from the url
* @return a JavaScript callback name.
*/

private String getCallbackName() {
final ContainerRequest containerRequest = containerRequestProvider.get();
final UriInfo uriInfo = containerRequest.getUriInfo();
final MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters();
if(queryParameters.get("jsoncallback")!=null)
return queryParameters.getFirst("jsoncallback");
return null;
}

}

对源码改动不大,删除了点儿东西,功能也仅仅是进行了数据封装。
拦截器的代码完成,下一步需要在web.xml里注册。

<servlet>
……
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider, ***.JsonWithPaddingInterceptor</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<init-param>jersey.config.server.provider.classnames里已经有了一个provider,再把拦截器的类加进去就行了。