1

我在尝试让跨域 ajax 请求工作时遇到了麻烦,尽管我在 Stack Overflow 上找到了许多解决方案,但我无法让它工作。

$.ajax({
        url : 'http://SERVER:PORT/CONTEXT/RESOURCE.html?someParameter=1234',
        dataType : 'json',
        success: function(xhr) {
            alert('ok '+JSON.stringify(xhr));
        },
                error : function(xhr) {
                        alert('error '+JSON.stringify(xhr));
                }
    });

仅使用数据类型“json”进行标准 $.ajax 调用,服务器会以空白响应和 statusText“错误”进行响应,如下所示:

 error {"readyState":0,"responseText":"","status":0,"statusText":"error"}

因此,我尝试按照其他线程中的建议将数据类型简单地更改为“jsonp”,但这次它仍然进入错误状态,并出现以下响应:

error {"readyState":4,"status":200,"statusText":"success"}

和“parsererror”的错误消息但没有数据。

是什么赋予了?

我是否需要在服务器端做一些特别的事情,因为它是 Weblogic 中的 Spring MVC?

编辑:jQuery 版本 1.9.1 Spring-3 MVC

EDIT2:哦,是的,我也尝试过 $.getJSON,但是这个命令似乎什么也没做——当我运行将 $.ajax 替换为 $.getJSON 的代码时,什么也没有发生。没有响应,我没有看到控制台中发生任何错误,也没有看到转到 URL 的网络请求。我也确实在第二次尝试中更改了语法,我将其称为 $.getJSON(url, callback); 但这并没有改变任何东西

EDIT3:我还应该提到,当我使用“json”数据类型运行原始代码并查看 Firebug 的响应选项卡时,它是空的。但是当我使用“jsonp”运行第二个代码时,我确实在“响应”选项卡中看到了 JSON 文本。所以很奇怪为什么它仍然会抛出错误。

4

1 回答 1

1

好的,经过更多研究,我终于找到了原因——是的,我确实需要在服务器端做一些事情来支持 jsonp。我最终编写了一个 servlet 过滤器,它将返回的 json 字符串包装在适当的回调中。

每天学些新东西!

public class JsonPCallbackFilter extends OncePerRequestFilter {

    Logger logger = Logger.getLogger(JsonPCallbackFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        //logger.debug("Filter: "+request.getRequestURI());

        @SuppressWarnings("unchecked")
        Map<String, String[]> parms = request.getParameterMap();

        if(parms.containsKey("callback")) {
            logger.debug("Wrapping response with JSONP callback '" + parms.get("callback")[0] + "'");

            OutputStream out = response.getOutputStream();

            ByteResponseWrapper wrapper = new ByteResponseWrapper(response);

            chain.doFilter(request, wrapper);

            StringBuffer sb = new StringBuffer();
            sb.append(parms.get("callback")[0] + "(");
            sb.append(new String(wrapper.getBytes()));
            sb.append(new String(");"));

            out.write(sb.toString().getBytes());

            wrapper.setContentType("text/javascript;charset=UTF-8");
            response.setContentLength(sb.length());

            out.close();
        } else {
            chain.doFilter(request, response);
        }
    }
}

static class ByteOutputStream extends ServletOutputStream {
    private ByteArrayOutputStream bos = new ByteArrayOutputStream();

    @Override
    public void write(int b) throws IOException {
       bos.write(b);            
    }

    public byte[] getBytes() {
       return bos.toByteArray();
    }
}

static class ByteResponseWrapper extends HttpServletResponseWrapper {
   private PrintWriter writer;
   private ByteOutputStream output;

   public byte[] getBytes() {
      writer.flush();
      return output.getBytes();
   }

   public ByteResponseWrapper(HttpServletResponse response) {
      super(response);
      output = new ByteOutputStream();
      writer = new PrintWriter(output);
   }

@Override
public PrintWriter getWriter() {
    return writer;
}

@Override
public ServletOutputStream getOutputStream() throws IOException {
    return output;
   }
}

    <filter>
      <filter-name>jsonpFilter</filter-name>
      <filter-class>com.blahblah.JsonPCallbackFilter</filter-class>
    </filter>

    <filter-mapping>
      <filter-name>jsonpFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
于 2013-08-17T03:59:26.723 回答