
区分同源和不同源的三要素
协议一致,域名一致,端口号一致,三个要素都一致,才是同源,其它一律都是不同源
| URL1 | URL2 | 是否同源 | 描述 |
|---|---|---|---|
| http://localhost:8080/a/index.html | http://localhost:8080/a/first | 同源 | 协议 域名 端口一致 |
| http://localhost:8080/a/index.html | http://localhost:8080/b/first | 同源 | 协议 域名 端口一致 |
| http://www.myweb.com:8080/a.js | https://www.myweb.com:8080/b.js | 不同源 | 协议不同 |
| http://www.myweb.com:8080/a.js | http://www.myweb.com:8081/b.js | 不同源 | 端口不同 |
| http://www.myweb.com/a.js | http://www.myweb2.com/b.js | 不同源 | 域名不同 |
| http://www.myweb.com/a.js | http://crm.myweb.com/b.js | 不同源 | 子域名不同 |
说明:
//设置响应头,允许Ajax跨域请求
response.setHeader("Access-Control-Allow-Origin","http://localhost:8080");
模拟实现核心代码:
// 使用ES6新特性:箭头函数
window.onload = () => {
document.getElementById("btn").onclick = () => {
let xmlHttpRequest = new XMLHttpRequest();
// 2. 注册回调函数
xmlHttpRequest.onreadystatechange = () => {
if (xmlHttpRequest.readyState == 4) {
if (xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) {
document.getElementById("mydiv").innerHTML = xmlHttpRequest.responseText
}
}
}
// 3. 开启通道
xmlHttpRequest.open("GET", "http://localhost:8081/b/hello", true)
// 4. 发送请求
xmlHttpRequest.send()
}
}
同源
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置响应头,允许Ajax跨域请求
response.setHeader("Access-Control-Allow-Origin","http://localhost:8080");
// response.getWriter().print("hello,ajax");
response.getWriter().print("{\"username\":\"zhangsan\"}");
}
}
jsonp简介:
代码实现:
<script type="text/javascript">
function sayHello(data){
alert("hello"+data.name)
}
</script>
<!--使用jsonp实现跨域请求:src:向 b web应用的jsonp程序发送请求-->
<script type="text/javascript" src="http://localhost:8081/b/jsonp1?fun=sayHello">
/*从bWEB服务器会返回一个js代码*/
</script>
String fun = request.getParameter("fun");
response.getWriter().print(fun+"({\"name\":\"json\"})");
使用jQuery封装的jsonp,在发送请求时,URL会被默认添加上callback=jQuery36003529724253140707_1660986216632&_=1660986216637,【创建一个callback函数】这就导致在后端响应数据时,需要把json格式的数据响应给callback函数,之后函数会再去调用ajax请求中的success属性。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery的jsonp封装解决Ajax的跨域问题title>
head>
<body>
<script type="text/javascript" src="/a/js/jquery-3.6.0.min.js">script>
<script type="text/javascript">
$(function () {
$("#btn").click(function () {
//默认发送地址
//http://localhost:8081/b/jsonp3?callback=jQuery36003529724253140707_1660986216632&_=1660986216637
//jQuery会默认生成一个callback函数,然后执行success中的内容
$.ajax({
type: "GET",//jsonp仅仅支持get
url: "http://localhost:8081/b/jsonp3",
dataType: "jsonp",//指定数据类型是jsonp形式
//另外自己也可以指定函数名和函数,不适用默认的callback
/*jsonp: "fun",
jsonpCallback:"sayHello",*/
success: function (data) {
$("#mydiv").html("欢迎,"+data.username)
}
})
})
})
script>
<button id="btn">jQuery库封装的jsonpbutton>
<div id="mydiv">div>
body>
html>
@WebServlet("/jsonp3")
public class JSONP3Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String callback = request.getParameter("callback");
response.getWriter().print(callback+"({\"username\":\"zhangsan\"})");
}
}
理解代理机制:

代码实现:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>实现代理解决跨域问题title>
head>
<body>
<script type="text/javascript">
window.onload = () =>{
document.getElementById("btn").onclick = () =>{
//创建XMLHttpRequest对象
var xmlHttpRequest = new XMLHttpRequest();
//注册回调函数
xmlHttpRequest.onreadystatechange = () =>{
if (xmlHttpRequest.readyState == 4) {
if (xmlHttpRequest.status == 200) {
document.getElementById("mydiv").innerHTML = xmlHttpRequest.responseText
}else {
alert(xmlHttpRequest.status)
}
}
}
//打开通道
xmlHttpRequest.open("GET","/a/proxy",true)
//发送数据
xmlHttpRequest.send()
}
}
script>
<button id="btn">使用代理方式解决跨域问题button>
<div id="mydiv">div>
body>
html>
@WebServlet("/proxy")
public class ProxyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//通过httpclient组件,发送HTTP Get请求,访问TargetServlet
// 目标地址
String url = "http://localhost:8081/b/target";
HttpGet httpGet = new HttpGet(url);
// 设置类型 "application/x-www-form-urlencoded" "application/json"
httpGet.setHeader("Content-Type", "application/x-www-form-urlencoded");
// System.out.println("调用URL: " + httpGet.getURI());
//httpClient实例化
CloseableHttpClient httpClient = HttpClients.createDefault();
// 执行请求并获取返回
HttpResponse resp = httpClient.execute(httpGet);
HttpEntity entity = resp.getEntity();
// System.out.println("返回状态码:" + resp.getStatusLine());
// 显示结果
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
String line = null;
StringBuffer responseSB = new StringBuffer();
while ((line = reader.readLine()) != null) {
responseSB.append(line);
}
System.out.println("服务器响应的数据:" + responseSB);
reader.close();
httpClient.close();
response.getWriter().print(responseSB);
}
}
@WebServlet("/target")
public class TargetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//相当于跨域的那个服务器,响应一个json格式的字符串
response.getWriter().print("{\"username\":\"zhangsan\"}");
}
}