当浏览器请求访问页面时,页面中请求的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; }
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; }