在当前域名请求网站中,默认不允许通过ajax请求发送其他域名。默认情况下浏览器会有安全机制,可以访问,但是获取不到返回结果。
$.ajax({
type : "GET",
async : false,
url : "http://b.lun.com:8081/ajaxB",
dataType : "jsonp",
jsonp : "jsonpCallback",//服务端用于接收callback调用的function名的参数
success : function(data) {
alert(data["errorCode"]);
},
error : function() {
alert('fail');
}
});
原理:动态添加一个标签,而
script
标签的src
属性是没有跨域的限制的。这样说来,这种跨域方式其实与ajax XmlHttpRequest
协议无关了。
可以说jsonp
的方式原理上和是一致的,因为他的原理实际上就是 使用
js
的script
标签 进行传参,那么必然是get
方式的了,和浏览器中敲入一个url
一样。
//使用jsonp 解决跨域问题
@RequestMapping("/getBInfo")
public void getBInfo(HttpServletResponse response, String jsonpCallback)
throws IOException {
JSONObject result = new JSONObject();
result.put("retCode", "200");
result.put("retMsg", "登陆成功");
//获得response的输出流
PrintWriter writer = response.getWriter();
//拼接jsonpCallback
writer.println(jsonpCallback + "(" + result.toJSONString() + ")");
//关闭输出流
writer.close();
}
// 该接口提供给A项目进行ajax调用
@RequestMapping("/getBInfo")
public Map getBInfo(HttpServletResponse response) {
// 告诉客户端(浏览器 )允许跨域访问 *表示所有域名都是可以 在公司中正常的代码应该放入在过滤器中
response.setHeader("Access-Control-Allow-Origin", "*");
Map result = new HashMap();
result.put("retCode", "200");
result.put("retMsg", "登陆成功");
return result;
}
一般情况下,会在过滤器下设置响应头。
首先先建立一个HttpClient工具包(网上百度了一波)
public class HttpClientUtils {
private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); // 日志记录
private static RequestConfig requestConfig = null;
static {
// 设置请求和传输超时时间
requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
}
/**
* post请求传输json参数
*
* @param url
* url地址
* @param json
* 参数
* @return
*/
public static JSONObject httpPost(String url, JSONObject jsonParam) {
// post请求返回结果
CloseableHttpClient httpClient = HttpClients.createDefault();
JSONObject jsonResult = null;
HttpPost httpPost = new HttpPost(url);
// 设置请求和传输超时时间
httpPost.setConfig(requestConfig);
try {
if (null != jsonParam) {
// 解决中文乱码问题
StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
}
CloseableHttpResponse result = httpClient.execute(httpPost);
// 请求发送成功,并得到响应
if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String str = "";
try {
// 读取服务器返回过来的json字符串数据
str = EntityUtils.toString(result.getEntity(), "utf-8");
// 把json字符串转换成json对象
jsonResult = JSONObject.parseObject(str);
} catch (Exception e) {
logger.error("post请求提交失败:" + url, e);
}
}
} catch (IOException e) {
logger.error("post请求提交失败:" + url, e);
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* post请求传输String参数 例如:name=Jack&sex=1&type=2
* Content-type:application/x-www-form-urlencoded
*
* @param url
* url地址
* @param strParam
* 参数
* @return
*/
public static JSONObject httpPost(String url, String strParam) {
// post请求返回结果
CloseableHttpClient httpClient = HttpClients.createDefault();
JSONObject jsonResult = null;
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
try {
if (null != strParam) {
// 解决中文乱码问题
StringEntity entity = new StringEntity(strParam, "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/x-www-form-urlencoded");
httpPost.setEntity(entity);
}
CloseableHttpResponse result = httpClient.execute(httpPost);
// 请求发送成功,并得到响应
if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String str = "";
try {
// 读取服务器返回过来的json字符串数据
str = EntityUtils.toString(result.getEntity(), "utf-8");
// 把json字符串转换成json对象
jsonResult = JSONObject.parseObject(str);
} catch (Exception e) {
logger.error("post请求提交失败:" + url, e);
}
}
} catch (IOException e) {
logger.error("post请求提交失败:" + url, e);
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* 发送get请求
*
* @param url
* 路径
* @return
*/
public static JSONObject httpGet(String url) {
// get请求返回结果
JSONObject jsonResult = null;
CloseableHttpClient client = HttpClients.createDefault();
// 发送get请求
HttpGet request = new HttpGet(url);
request.setConfig(requestConfig);
try {
CloseableHttpResponse response = client.execute(request);
// 请求发送成功,并得到响应
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 读取服务器返回过来的json字符串数据
HttpEntity entity = response.getEntity();
String strResult = EntityUtils.toString(entity, "utf-8");
// 把json字符串转换成json对象
jsonResult = JSONObject.parseObject(strResult);
} else {
logger.error("get请求提交失败:" + url);
}
} catch (IOException e) {
logger.error("get请求提交失败:" + url, e);
} finally {
request.releaseConnection();
}
return jsonResult;
}
}
通过HttpClient内部转发
// 使用HttpClient进行方法B接口
@RequestMapping("/forWardB")
@ResponseBody
public JSONObject forWardB() {
JSONObject result = HttpClientUtils.httpGet("http://b.lun.com:8081/getBInfo");
return result;
}
原理:保证域名和端口号都是相同的,根据项目不同名称使用Nginx进行转发到真实服务器地址。
这种方案可以彻底解决网站跨域问题。
nginx配置文件
server {
listen 80;
server_name www.lun.com;
###A项目
location /a {
proxy_pass http://a.lun.com:8080/;
index index.html index.htm;
}
###B项目
location /b {
proxy_pass http://b.lun.com:8081/;
index index.html index.htm;
}
}