什么是网站跨域:
跨域产生原因:在当前域名请求网站中,默认不允许通过ajax请求发送其他域名(属于浏览器安全策略问题,不属于前端问题)。
如果ajax访问的地址与浏览器访问的域名和端口号都不同的情况下,默认浏览器会有安全策略,直接无法获取到请求结果。
注意:跨域问题请求是可以访问的,但只是获取不到结果。
疑问1:微服务通讯(RPC通讯)会产生跨域问题吗?
答案:不会。跨域是浏览器端问题,RPC走的是后端访问,不会产生。
jquery-1.7.2.min.js?t=2020-01-05:4 Failed to load http://b.itmayiedu.com:8081/ajaxB: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.itmayiedu.com:8080' is therefore not allowed access.
(1)使用jsonp解决网站跨域 (不推荐,因为只能支持get请求)
(2)使用HttpClient内部转发(不推荐,会发两次请求效率低)
(3)使用设置响应头允许跨域
(4)基于Nginx搭建企业级API接口网关
(5)使用Zuul搭建微服务API接口网关
后端:
(1)Maven初始化依赖参数
org.springframework.boot
spring-boot-starter-parent
2.0.0.RELEASE
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-tomcat
org.apache.tomcat.embed
tomcat-embed-jasper
org.springframework.boot
spring-boot-starter-log4j
1.3.8.RELEASE
org.springframework.boot
spring-boot-starter-aop
org.apache.httpcomponents
httpclient
com.alibaba
fastjson
1.2.47
(2)application.yml
server:
port: 8080
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
(3)HttpClientUtils工具类
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;
}
}
前端:略
缺点:不支持post请求,代码书写比较复杂
(1)前端代码
(2)后端代码
@RequestMapping(value = "/ajaxB", method = RequestMethod.GET)
public void ajaxB(HttpServletResponse response, String jsonpCallback) throws IOException {
JSONObject root = new JSONObject();
root.put("errorCode", "200");
root.put("errorMsg", "登陆成功");
response.setHeader("Content-type", "text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.print(jsonpCallback + "(" + root.toString() + ")");
writer.close();
}
(1)前端代码
(2)后端代码
A项目进行转发到B项目:
@RequestMapping("/forwardB")
@ResponseBody
public JSONObject forwardB() {
JSONObject result = HttpClientUtils.httpGet("http://b.itmayiedu.com:8081/ajaxB");
System.out.println("result:" + result);
return result;
}
B项目代码:
@RequestMapping("/ajaxB")
public Map ajaxB(HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", "*");
Map result = new HashMap();
result.put("errorCode", "200");
result.put("errorMsg", "登陆成功");
return result;
}
使用Nginx搭建API接口网关
(1) Nginx相关配置:
server {
listen 80;
server_name www.itmayiedu.com;
###A项目
location /a {
proxy_pass http://a.itmayiedu.com:8080/;
index index.html index.htm;
}
###B项目
location /b {
proxy_pass http://b.itmayiedu.com:8081/;
index index.html index.htm;
}
}
(2) 前端代码
(3)后端代码
@RequestMapping("/ajaxB")
public Map ajaxB(HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", "*");
Map result = new HashMap();
result.put("errorCode", "200");
result.put("errorMsg", "登陆成功");
return result;
}