解决跨域问题 方案一:添加HTTP请求头 方案二:JSONP 方案三:HttpClient 方案四:Nginx

跨域:就是浏览器的安全机制,要求该工程请求的域名需要一致,如果说请求域名不一致的情况下,浏览器没有办法直接返回结果;

解决问题的方案:

  JSONP方式;

  Nginx方式;

  HttpClient方式;

  添加HTTP请求头方式;

  后台response添加header,response.setHeader("Access-Control-Allow-Origin", "*"); 支持所有网站  

  项目搭建结构如下:创建两个独立的项目 

    解决跨域问题
方案一:添加HTTP请求头
方案二:JSONP
方案三:HttpClient
方案四:Nginx 解决跨域问题
方案一:添加HTTP请求头
方案二:JSONP
方案三:HttpClient
方案四:Nginx

   后端代码:

package com.wn;

import com.alibaba.fastjson.JSON;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    //方法一:使用请求头解决跨域问题
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        System.out.println("数据:"+username);

        //响应
        resp.getWriter().write("success");

        //添加请求头方式解决跨域
        resp.setHeader("Access-Control-Allow-Origin","*");

    }
}

  前端代码:

<%--
  Created by IntelliJ IDEA.
  User: wn
  Date: 2020/2/6
  Time: 10:04
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>跨域</title>
    <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
    <script>
        //使用请求头解决跨域问题
        $(function () {
            $("#button").click(function () {
                var username=$("#username").val();
               $.ajax({
                   url:"http://www.aproject.com:8080/aServlet",
                   data:{"username":username},
                   type:"POST",
                   success:function (result) {
                       alert(result)
                   },
                   error:function () {
                       alert("error!!!")
                   }
               })
            })
        })</script>
</head>
<body>
  <input type="text" name="username" id="username"/><button id="button" type="button">提交</button>
</body>
</html>

方案二:JSONP

  前端代码:

<%--
  Created by IntelliJ IDEA.
  User: wn
  Date: 2020/2/6
  Time: 10:04
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>跨域</title>
    <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
    <script>
       //使用JSONP方式解决跨域问题
        $(function () {
            $("#button").click(function () {
                var username=$("#username").val();
                $.ajax({
                    url:"http://www.aproject.com:8080/aServlet?username="+username,
                    type:"GET",
                    jsonp:"jsonp",  //回调函数
                    dataType:"JSONP",
                    success:function (result) {
                        alert(result)
                    },
                    error:function () {
                        alert("error!!!")
                    }
                })
            })
        })</script>
</head>
<body>
  <input type="text" name="username" id="username"/><button id="button" type="button">提交</button>
</body>
</html>

  后端代码:

package com.wn;

import com.alibaba.fastjson.JSON;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    //resp.setContentType("text/html;charset=utf-8");
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
//方法二:使用JSONP解决跨域问题 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); System.out.println("数据:"+username); //使用JSONP解决跨域问题 String jsonp = req.getParameter("jsonp"); //需要将返回的数据转换为JSON格式 String success = JSON.toJSONString("success"); resp.getWriter().write(jsonp+"("+success+")"); } }

  jquery中jsonp的实现原理

      在同源策略下,在某个服务器下的页面时无法获取到该服务器以外的数据的,即一般的ajax是不能进行跨域请求的。但是img,iframe,script等标签是个例外,这些标签可以通过src属性请求到其他服务器上的数据。利用script标签的开放策略,我们可以实现跨域请求数据,当然这需要服务器端的配合。jquery中ajax的核心是通过XmlHttpRequest获取非本业内容,而jsonp的核心则是动态添加,script标签来调用服务器提供的js脚本。

      当我们正常地请求一个JSON数据的时候,服务端返回的是一串JSON类型的数据,而我们使用JSONP模式来请求数据的时候服务器返回的是一段可执行的JavaScript代码。因为JSONP跨域的原理就是用的动态加载,所以我们只能把参数通过URL的方式传递,所以JSONP的type类型只能是GET请求方式!

      使用JSONP模式来请求数据的整个流程:客户端发送一个请求,规定一个可执行的函数名(这里就是jquery做了封装的处理,自动帮我们生成回调函数并把数据取出来供success属性方法来调用,而不是传递一个回调句柄),服务器端接受定义的函数名称,然后把数据通过实参的形式发送出去。

      (在query源码中,JSONP的实现方式是动态添加script标签来调用服务器提供的JS脚本。jquery会在Window对象中加载一个全局的函数,当script代码插入时函数执行,执行完毕后就script标签会被移除。同时jquery还对非跨域的请求进行了优化,如果这个是在同一个域名下那么它就会像正常地ajax请求一样工作。)

  JSONP的优缺点

      JSONP的优点:它不像是XMLHttpRequest对象实现的ajax请求那样受到同源策略的限制,它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持,并且在请求完毕后可以通过调用callback的方式回传结果;

      JSONP的缺点:它只支持GET请求而不支持POST等其他类型的HTTP请求,它只支持跨域HTTP请求这种情况下,不能解决不同域的两个页面之间如何进行JavaScript调用的问题;

方案三:HttpClient

  前端代码:

<%--
  Created by IntelliJ IDEA.
  User: wn
  Date: 2020/2/6
  Time: 10:04
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>跨域</title>
    <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
    <script>
        //使用HttpClient方式解决跨域问题
        $(function () {
            $("#button").click(function () {
                var username=$("#username").val();
                $.ajax({
                    url:"httpServlet?username="+username,
                    type:"GET",
                    success:function (result) {
                        alert(result)
                    },
                    error:function () {
                        alert("error!!!")
                    }
                })
            })
        })

    </script>
</head>
<body>
  <input type="text" name="username" id="username"/><button id="button" type="button">提交</button>
</body>
</html>

  HttpClient类:

package com.wn;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import sun.net.www.http.HttpClient;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/httpServlet")
public class HttpCient extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建连接
        CloseableHttpClient client = HttpClients.createDefault();
        //请求
        HttpGet httpGet=new HttpGet("http://www.aproject.com:8080/aServlet?username="+req.getParameter("username"));
        //发送请求
        CloseableHttpResponse response = client.execute(httpGet);
        //获取返回结果  将A工程中的success提示语句返回给httpClient
        String s = EntityUtils.toString(response.getEntity());
        //响应   HttpClient将返回的结果响应给页面
        resp.getWriter().write(s);
    }
}

  后端代码:

package com.wn;

import com.alibaba.fastjson.JSON;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    //resp.setContentType("text/html;charset=utf-8");
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    //方法三:使用HttpClient解决跨域问题
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        System.out.println("数据:"+username);

        //响应
        resp.getWriter().write("success");
    }
}

  实现原理

      实现原理很简单,若想在B项目中通过ajax访问A项目获取结果,固然有ajax跨域问题,但是B项目中访问B项目获取结果,不存在跨域问题,这种方式实际上是在B项目中ajax请求范文B项目中的HttpClient,在通过HttpClient转发请求获取A项目中的数据结果。但这种方式产生了两次请求,效率低,但内部请求,比较安全。

方案四:Nginx

  B项目不能直接请求A项目内容,可以通过Nginx,根据同域名,但项目名不同进行区分

  当我们访问www.bproject.com通过www.nginx.com/B访问,并通过nginx转达到www.bproject.com

  当我们访问www.aproject.com通过www.nginx.com/A访问,并通过nginx转达到www.aproject.com

server {
        listen       80;
        server_name  www.nginx.com;
        location /A {
            proxy_pass  http://www.aproject.com:8080;
            index  index.html index.htm;
        }
        location /B {
            proxy_pass  http://www.bproject.com:8081;
            index  index.html index.htm;
        }
}