当我使用js的ajax代码去访问另外一台机器上部署的项目的接口时,会出现交叉资源访问错误,其实就是我们通常所说的跨域访问问题。
解决方法是:在web.xml里面拦截url访问请求,然后由servlet来处理请求,将传递过来的url进行处理后变成真实的url,由java来处理这个url后返回真实的结果。
废话不多说,下面是详细的实现方法。
第一步:
web.xml
<!-- 跨域访问运营接口 -->
<servlet>
<description></description>
<display-name>PtlRequestServlet</display-name>
<servlet-name>PtlRequestServlet</servlet-name>
<servlet-class>com.skyform.portal.PtlRequestServlet</servlet-class>
<init-param>
<description>base url of portal api request</description>
<param-name>portal.url</param-name>
<param-value>http://172.31.100.18:8082/portal</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>PtlRequestServlet</servlet-name>
<url-pattern>/portal</url-pattern>
</servlet-mapping>
第二部:
在公共方法里common.js里写出ajax请求方法和url拦截方法
function getPortalBaseUrl() {
var pathName=window.location.pathname;
PTL_API="/"+pathName.split("/")[1]+"/portal?command=";
return PTL_API;
};
上面的getPortalBaseUrl()方法是我调用的地址的前缀部分
下面是ajax普通的get和post请求方法
function queryDataGet(url, callback) {
$.ajax({
type : 'GET',
'url' : url,
dataType : 'json',
contentType : "application/json; charset=utf-8",
"success" : function(data) {
callback(data);
},
error : function(error) {
console.log(error);
}
});
};
//监控中列表项选用“POST”方法获取数据
function queryDataPost(url,requestParam,callback) {
$.ajax({
type: 'POST',
'url': url,
dataType : 'json',
data:requestParam,
contentType : "application/json; charset=utf-8",
"success" : function(data){
callback(data);
},
error : function(error) {
console.log(error);
}
});
};
下面是带头信息的ajax的get和post方法
function queryTokenGet(url, token, resourcePool, callback) {
$.ajax({
type : 'GET',
'url' : url,
async: false,
beforeSend :function(xhr){
xhr.setRequestHeader('token',token);
xhr.setRequestHeader('resourcePool',resourcePool);
},
dataType : 'json',
contentType : "application/json; charset=utf-8",
"success" : function(data) {
callback(data);
},
error : function(error) {
console.log(error);
}
});
};
//选用“POST”方法获取数据
function queryTokenPost(url,token,resourcePool,requestParam,callback) {
$.ajax({
type: 'POST',
'url': url,
async: false,
beforeSend :function(xhr){
xhr.setRequestHeader('token',token);
xhr.setRequestHeader('resourcePool',resourcePool);
},
dataType : 'json',
data:requestParam,
contentType : "application/json; charset=utf-8",
"success" : function(data){
callback(data);
},
error : function(error) {
console.log(error);
}
});
};
上面只写了方法,下面是调用的具体代码
var cmd = "/rest/aggregation/getListVirtualMachines";
var prams = {
id : virtualmachineid
};
queryDataPost(getPrUrl() + cmd, JSON.stringify(prams), function(result) {
//将返回的result数据信息进行展示
});
第二步:com.skyform.portal.PtlRequestServlet接到请求后处理请求
package com.company.portal;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class PtlRequestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private String ptlUrl;
public PtlRequestServlet() {
}
public void init(ServletConfig config) throws ServletException {
ptlUrl = config.getInitParameter("portal.url");
if (ptlUrl == null)
ptlUrl = "http://localhost:8082/portal";
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("PtlRequestServlet.java--------GET");
String result = PtlRedirector.getResponseGet(request, ptlUrl);
response.setCharacterEncoding("UTF-8");
PrintWriter writer = response.getWriter();
writer.write(result);
writer.close();
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// request.setCharacterEncoding("UTF-8");
System.out.println("PtlRequestServlet.java--------POST");
String result = PtlRedirector.getResponsePost(request, ptlUrl);
response.setCharacterEncoding("UTF-8");
PrintWriter writer = response.getWriter();
writer.write(result);
writer.close();
}
}
上面的代码是判断web.xml里面的portal.url有没有赋值,如果为空就将prlUrl赋值为"http://localhost:8082/portal"
当代码走到
String result = PtlRedirector.getResponsePost(request, ptlUrl);
的时候,会将ptlUrl发送给PtlRedirector类进行处理
第三步:
是PtlRedirector类的处理过程
package com.company.portal;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
public class PtlRedirector {
public static String getResponseGet(HttpServletRequest request,
String baseUrl) {
String param = concatParams(request);
String url = baseUrl + param;
String token = request.getHeader("token");
String resourcePool = request.getHeader("resourcePool");
String response = readResponseFromURL(url,token,resourcePool);
return response;
}
public static String getResponsePost(HttpServletRequest request,
String baseUrl) {
String param = concatParams(request);
String url = baseUrl + param;
String json = readJSONString(request);
String token,resourcePool;
token = request.getHeader("token");
resourcePool = request.getHeader("resourcePool");
String response;
if(token != null && resourcePool != null){
response = sendPostHeader(url,token,resourcePool,json);
}else{
response = sendPost(url, json);
}
return response;
}
private static String sendPostHeader(String url, String token,
String resourcePool, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("token", token);
conn.setRequestProperty("resourcePool", resourcePool);
// 设置通用的请求属性
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "utf-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
public static String readJSONString(HttpServletRequest request) {
StringBuffer json = new StringBuffer();
String line = null;
try {
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null) {
json.append(line);
}
} catch (Exception e) {
System.out.println(e.toString());
return json.toString();
}
return json.toString();
}
@SuppressWarnings("rawtypes")
private static String concatParams(HttpServletRequest request) {
StringBuilder sb = new StringBuilder();
Enumeration en = request.getParameterNames();
while (en.hasMoreElements()) {
String name = (String) en.nextElement();
String value = request.getParameter(name).trim();
if (value.length() == 0)
continue;
sb.append(value);
}
return sb.toString();
}
private static String readResponseFromURL(String url,String token,String resourcePool) {
URL getUrl;
HttpURLConnection connection = null;
BufferedReader reader = null;
StringBuilder result = new StringBuilder();
try {
getUrl = new URL(url);
connection = (HttpURLConnection) getUrl.openConnection();
connection.setRequestProperty("token", token);
connection.setRequestProperty("resourcePool", resourcePool);
connection.connect();
if (connection.getResponseCode() == 200) {
reader = new BufferedReader(new InputStreamReader(
connection.getInputStream(), "utf-8"));// set charset to
String lines;
while ((lines = reader.readLine()) != null) {
result.append(lines);
}
} else {
reader = new BufferedReader(new InputStreamReader(
connection.getErrorStream(), "utf-8"));// set charset to
String lines;
while ((lines = reader.readLine()) != null) {
result.append(lines);
}
}
} catch (Exception e) {
} finally {
try {
if (reader != null) {
reader.close();
}
if (connection != null) {
connection.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return result.toString();
}
private static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "utf-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
}
上面的代码分别给出了带头信息的Post请求和不带头信息的Post请求的处理方法,同时给出不同请求方式Get和Post的带头信息的和不带头信息的处理方法,会将js里面请求的url变成所需要的url从而达到跨域访问的效果。