为什么我对 Web 服务的 jquery AJAX 调用不返回任何数据?为什么当我调用我的 Web 服务时没有任何反应?为什么我的 Web 服务客户端不能使用不同服务器/域上的 Web 服务?
我花了相当多的时间研究如何让我的 jquery UI 应用程序使用另一个域上的 Web 服务。我终于想通了,并在这里为将来遇到此挑战的任何人记录详细信息。请注意,我对托管在 JBOSS v4 容器中的一组 Documentum DFS POJO Web 服务使用 jquery $.ajax 调用。较新版本的 Tomcat/JBOSS 使这更容易。
这是等式的 jquery 方面:
<script type="text/javascript">
var tjson;
var webServiceURL = 'http://hostname/services/pDFS/atlContractService';
var soapMessage;
$(document).ready(function() {
jQuery.support.cors = true;
});
function onSaveTitleData() {
soapMessage = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.prodagio.com"><soapenv:Header/><soapenv:Body><ser:saveProjectData><prjInfo>' + tjson + '</prjInfo></ser:saveProjectData></soapenv:Body></soapenv:Envelope>';
CallService();
}
function CallService()
{
$.ajax({
url: webServiceURL,
type: "POST",
dataType: "xml",
data: soapMessage,
processData: false,
contentType: "text/xml; charset=\"utf-8\"",
success: OnSuccess,
error: OnError
});
return false;
}
function OnSuccess(data, status)
{
alert(data.d);
}
function OnError(request, status, error)
{
alert(request + status + error);
}
function prepareTitleSavePackage(obj, rowIndx) {
var rObjectId = obj.dataModel.data[rowIndx].r_object_id;
var parentId = obj.dataModel.data[rowIndx].parentId;
var contractChronId = obj.dataModel.data[rowIndx].contractChronId;
var picture = obj.dataModel.data[rowIndx].picture;
var project = obj.dataModel.data[rowIndx].project;
var bu = obj.dataModel.data[rowIndx].bu;
var aka = obj.dataModel.data[rowIndx].aka;
var status = obj.dataModel.data[rowIndx].document_status;
if ( !rObjectId || rObjectId.length < 16 ) {
rObjectId = "new";
}
tjson = "{rObjectId : '" + rObjectId + "', picture : '" + picture + "', project: '"
+ project + "', bu : '" + bu + "', aka: '" + aka + "', status : '"
+ status + "', parentId : '"
+ parentId + "', contractChronId : '" + contractChronId + "'}";
//alert(tjson);
}
function addTitleRow() {
var parentId = jQuery("#contractObjId").val();
var contractChronId = parentId;
jQuery("#grid_array").pqGrid( "addRow",
{rowData : { 'parentId' : parentId, 'contractChronId' : contractChronId } }
);
//jQuery("#currentTitleIndex").val(titleRowIndex);
}
</script>
实际调用的 Web 服务只是一个小问题。更重要的是,为了在调用该服务时避免网络安全错误(当它托管在不同的域中时),您必须实现一个过滤器。当然,这需要修改应用程序的 web.xml 并实现过滤器类。
这是我添加到 web.xml 中的行:
<filter>
<filter-name>pCorsFilter</filter-name>
<filter-class>com.p.dfs.util.CrossOriginRequestSharingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>pCorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这是实际的 Java 类实现:
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.Filter;
import com.documentum.fc.common.DfLogger;
public class CrossOriginRequestSharingFilter implements Filter
{
public void destroy() {
}
public static String VALID_METHODS = "DELETE, HEAD, GET, OPTIONS, POST, PUT";
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpServletResponse httpResp = (HttpServletResponse) resp;
try {
// No Origin header present means this is not a cross-domain request
String origin = httpReq.getHeader("Origin");
DfLogger.debug(this.getClass(),"doFilter(): origin " + origin, null, null);
if (origin == null) {
DfLogger.debug(this.getClass(),"doFilter(): origin == null ", null, null);
// Return standard response if OPTIONS request w/o Origin header
if ("OPTIONS".equalsIgnoreCase(httpReq.getMethod())) {
httpResp.setHeader("Allow", VALID_METHODS);
httpResp.setStatus(200);
return;
}
} else {
DfLogger.debug(this.getClass(),"doFilter(): origin != null ", null, null);
// This is a cross-domain request, add headers allowing access
String validOrigins = ReadProperties.getInstance().getString("VALID_ORIGINS");
DfLogger.debug(this.getClass(),"doFilter(): validOrigins " + validOrigins, null, null);
if ( validOrigins.indexOf(origin) > -1 ) {
httpResp.setHeader("Access-Control-Allow-Origin", origin);
httpResp.setHeader("Access-Control-Allow-Methods", VALID_METHODS);
DfLogger.debug(this.getClass(),"doFilter(): header set", null, null);
String headers = httpReq.getHeader("Access-Control-Request-Headers");
if (headers != null)
httpResp.setHeader("Access-Control-Allow-Headers", headers);
// Allow caching cross-domain permission
httpResp.setHeader("Access-Control-Max-Age", "3600");
}
}
DfLogger.debug(this.getClass(),"doFilter(): if origin complete", null, null);
// Pass request down the chain, except for OPTIONS
if (!"OPTIONS".equalsIgnoreCase(httpReq.getMethod())) {
DfLogger.debug(this.getClass(),"doFilter(): chain.doFilter", null, null);
chain.doFilter(req, resp);
}
} catch ( Exception eee ) {
DfLogger.error(this.getClass(),"doFilter(): error " + eee.getMessage(), null, null);
}
}
public void init(FilterConfig config) throws ServletException {
DfLogger.error(this.getClass(),"doFilter(): CrossOriginRequestSharingFilter initialized", null, null);
}
}
所有这些放在一起都有效。