使用jquery的getjson()遇到的跨域訪問問題(二)——使用攔截器進行數據封裝

上一篇我們提到了使用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,再把攔截器的類加進去就行了。

發佈了110 篇原創文章 · 獲贊 19 · 訪問量 46萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章