什么是网站跨域问题
当浏览器请求访问页面时,页面中请求的ajax地址如果和页面请求的地址域名、端口、协议不同的话,浏览器会采用安全策略,请求能够正常的到达服务器端,但是无法获取响应结果。
跨域问题的遇到场景
实际开发中前后端分离
网站跨域问题的解决方案
1. 响应头设置允许跨域访问,response.setHeader("Access-Control-Allow-Origin","*");*表示允许所有的ip
2. 使用jsonp解决网站跨域访问。缺点:只支持get请求,本质模拟了script脚本提交
3. 使用HttpClient实现转发。缺点:需要发送两次请求
4. 使用Nginx搭建API网关,保持域名和端口一致。配置location位置
5. 使用微服务中的Zuul网关
方案一(通过设置响应头)
==============A项目(http://127.0.0.1:8080)================
$(document).ready(function() {
$.ajax({
type : "POST",
async : false,
url : "http://127.0.0.1:8081/getBInfo",
dataType : "json",
success : function(data) {
alert(data["retCode"]);
},
error : function() {
alert('fail');
}
});
});
===============B项目(http://127.0.0.1:8081)================
@RequestMapping("/getBInfo")
public Map<String, Object> getBInfo(HttpServletResponse response) {
System.out.println(">>>>>>B项目getBInfo>>>>>>");
// 告诉客户端(浏览器 )允许跨域访问 *表示所有域名都是可以 在公司中正常的代码应该放入在过滤器中
response.setHeader("Access-Control-Allow-Origin", "*");
Map<String, Object> result = new HashMap<String, Object>();
result.put("retCode", "200");
result.put("retMsg", "登陆成功");
return result;
}
方案二(使用jsonp)
===============A项目(http://127.0.0.1:8080)================
$(document).ready(function() {
$.ajax({
type : "POST",
async : false,
url : "http://127.0.0.1:8081/getBInfo",
dataType : "jsonp",
jsonp:"jsonpCallback",
jsonpCallback:"callback",
success : function(data) {
alert(data["retCode"]);
},
error : function() {
alert('fail');
}
});
});
===============B项目(http://127.0.0.1:8081)================
@RequestMapping("/getBInfo")
public void getBInfo(HttpServletResponse response, String jsonpCallback)
throws IOException {
JSONObject result = new JSONObject();
result.put("retCode", "200");
result.put("retMsg", "登陆成功");
PrintWriter writer = response.getWriter();
writer.println(jsonpCallback + "(" + result.toJSONString() + ")");
writer.close();
// 127.0.0.1:8081?jsonpCallback=256163154
// B项目返回结果集 256163154(jsonObject)
}
方案三(通过HttpClient)
===============A项目(http://127.0.0.1:8080)================
$(document).ready(function() {
$.ajax({
type : "POST",
async : false,
url : "http://127.0.0.1:8080/forWardB",
dataType : "json",
success : function(data) {
alert(data["retCode"]);
},
error : function() {
alert('fail');
}
});
});
// 使用HttpClient进行方法B接口,该接口的ip地址为127.0.0.1:8080
@RequestMapping("/forWardB")
@ResponseBody
public JSONObject forWardB() {
// 中间采用rpc httpClient技术调用接口。服务器与服务器之间不存在跨域问题
JSONObject result = HttpClientUtils.httpGet("http://127.0.0.1:8081/getBInfo");
return result;
}
===============B项目(http://127.0.0.1:8081)================
@RequestMapping("/getBInfo")
@ResponseBody
public Map<String, Object> getBInfo(HttpServletResponse response) {
System.out.println(">>>>>>B项目getBInfo>>>>>>");
Map<String, Object> result = new HashMap<String, Object>();
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地址
* @param jsonParam 参数
* @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 地址
* @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;
}
}
方案四(使用Nginx搭建网关)
==================本地计算的host文件=====================
127.0.0.01 api.mayikt.com
=============Nginx的配置文件conf===============
server{
listen 80;
server_name localhost;
location /mayikt-a/{
proxy_pass http://192.168.18.190:8080/;# 8080后不加/,项目路径中必须有mayikt-a,所以不要省略
index index.html index.htm;
}
location /mayikt-b/{
proxy_pass http://192.168.18.190:8081/;
index index.html index.htm;
}
}
===============A项目(http://192.168.18.190:8080)================
$(document).ready(function() {
$.ajax({
type : "POST",
async : false,
url : "http://api.mayikt.com/mayikt-b/getInfo",
dataType : "json",
success : function(data) {
alert(data["retCode"]);
},
error : function() {
alert('fail');
}
});
});
===============B项目(http://192.168.18.190:8081)================
@RequestMapping("/getBInfo")
@ResponseBody
public Map<String, Object> getBInfo(HttpServletResponse response) {
System.out.println(">>>>>>B项目getBInfo>>>>>>");
Map<String, Object> result = new HashMap<String, Object>();
result.put("retCode", "200");
result.put("retMsg", "登陆成功");
return result;
}