跨域问题解决方案
五种网站跨域解决方案
1. 使用jsonp解决网站跨域 只能支持get 不支持post
2.使用HttpClient内部转发 效率低 发送两次请求
3.使用设置响应头允许跨域
4.基于Nginx搭建企业级API接口网关 保证域名和端口一直 以项目区分反向代理到真实服务器地址
5.使用Zuul搭建微服务API接口网关
使用设置响应头允许跨域:
在B项目中添加:
response.setHeader("Access-Control-Allow-Origin", "*");
package com.toov5.controller; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @SpringBootApplication public class BIndexController { @RequestMapping("/getBInfo") public Map<String, Object> getBInfo(HttpServletResponse response){ //告诉浏览器 允许跨域 这段代码应该放在过滤器里面的 response.setHeader("Access-Control-Allow-Origin", "*"); //*代表所有 可以a.toov5.com专门的 //提供给Ajax嗲用 Map<String,Object> result = new HashMap<String, Object>(); result.put("code", 200); result.put("msg", "登录成功"); return result; } public static void main(String[] args) { SpringApplication.run(BIndexController.class, args); } }
JSONP解决方案:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.0.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $.ajax({ type : "POST", async : false, url : "http://b.toov5.com:8081/getBInfo", dataType : "jsonp", jsonp : "jsonpCallback",//服务端用于接收callback调用的function名的参数 success : function(data) { alert(data["code"]); //获取到code }, error : function() { alert('fail'); } }); }); </script> </head> <body>我是A项目 正在调用B项目 </body> </html>
首先该成JSONP的 形式
dataType : "jsonp", jsonp : "jsonpCallback",//服务端用于接收callback调用的function名的参数
访问: (生成的随机数)
注意 不支持post请求!
HttpClient方案转发:
相当于发送两次请求
隐藏了真实地址 Nginx反向代理类似
同时需要@ResponseBody哦 因为返回json格式
修改前段访问的接口 保持一致:
$(document).ready(function() { $.ajax({ type : "POST", async : false, url : "http://a.toov5.com:8080/forwardB", dataType : "json", success : function(data) { alert(data["code"]); //获取到code }, error : function() { alert('fail'); } }); });
HttpClient:
package com.toov5.controller; import java.io.IOException; import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSONObject; 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; } }
Controller:
package com.toov5.controller; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSONObject; @Controller @SpringBootApplication public class AIndexController { @RequestMapping("/aIndexJsp") public String AIndexJsp() { return "aIndex"; } //使用httpClient进行访问b接口 @RequestMapping("/forwardB") @ResponseBody //这里一定要为 json形式!!! jsp中的ajax访问的路径 public JSONObject forwardB() { JSONObject result = HttpClientUtils.httpGet("http://b.toov5.com:8081/getBInfo"); return result; } public static void main(String[] args) { SpringApplication.run(AIndexController.class, args); } }
B的controller:
package com.toov5.controller; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @SpringBootApplication public class BIndexController { @RequestMapping("/getBInfo") public Map<String, Object> getBInfo(HttpServletResponse response){ //告诉浏览器 允许跨域 这段代码应该放在过滤器里面的 // response.setHeader("Access-Control-Allow-Origin", "*"); //*代表所有 可以a.toov5.com专门的 //提供给Ajax嗲用 Map<String,Object> result = new HashMap<String, Object>(); result.put("code", 200); result.put("msg", "登录成功"); return result; } public static void main(String[] args) { SpringApplication.run(BIndexController.class, args); } }
Nginx 方案:
api.toov5.com/a
api.toov5.com/b
通过Nginx 转发到不同的 项目
Zuul方案:
类似Nginx 修改Zuul的配置yml
不管访问A项目还是B项目 首先保证域名端口号统一
请求先到Nginx 判断域名相同 项目名字不同 转发到某个项目