1. 跨域 32
1.1 图解
1.2 演示可以跨域的标签 30
- 跨域是指从一个域名的网页去请求另一个域名的资源。比如从百度(https://baidu.com)页面去请求京东(https://www.jd.com)的资源。
- 通过超链接或者form表单提交或者window.location.href的方式进行跨域是不存在问题的(**大家可以编写程序测试一下**)。
代码在E:\java学习\Ajax\course\course10\web 30
index.html
<!--演示跨域问题 32-->
<!--a 应用的index页面-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>a 应用的index页面</title>
</head>
<body>
<!--通过超链接的方式可以跨域嘛 可以 -->
<a href="http://localhost:8081/b/index.html">访问b的index页面(跨域访问)</a>
<!--form表单可以跨域嘛 可以-->
<form action="http://localhost:8081/b/user/reg" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="注册">
</form>
<!--通过js代码中的window.location.href/document.location.href可以跨域吗?可以-->
<button onclick="window.location.href='http://localhost:8081/b/index.html'">b的index页面(跨域访问)1</button>
<button onclick="document.location.href='http://localhost:8081/b/index.html'">b的index页面(跨域访问)2</button>
<!--使用script标签可以加载js文件,这个可以跨域吗?可以-->
<script type="text/javascript" src="http://localhost:8081/b/my.js"></script>
<br>
<!--加载其他站点的图片,可以跨域吗-->
<img src="http://localhost:8081/b/guidao.jpg"/>
</body>
</html>
在course-10_1中
E:\java学习\Ajax\course\course10_1\web
index.html
<!--演示跨域问题 32-->
<!--b 应用的index页面-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>b 应用的index页面</title>
</head>
<body>
<h1>b 应用的index页面</h1>
</body>
</html>
com.bjpowernode.b.web.servlet
UserRegServlet
package com.bjpowernode.b.web.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
//研究form表单的跨域问题 32
@WebServlet("/user/reg")
public class UserRegServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//响应到前端
response.getWriter().print(username +":"+password);
}
}
my.js
//研究跨域问题 32
alert("b应用当中的my.js文件被加载并执行了")
2. ajax跨域问题 33
但在一个域名的网页中的一段js代码发送ajax请求去访问另一个域名中的资源,由于同源策略的存在导致无法跨域访问,那么ajax就存在这种跨域问题。
- 同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性,同源就是协议、域名和端口都相同。
- 同源策略有什么用?如果你刚刚在网银输入账号密码,查看了自己还有1万块钱,紧接着访问一些不规矩的网站,这个网站可以访问刚刚的网银站点,并且获取账号密码,那后果可想而知。所以,从安全的角度来讲,同源策略是有利于保护网站信息的。
- 有一些情况下,我们是需要使用ajax进行跨域访问的。比如某公司的A页面(a.bjpowernode.com)有可能需要获取B页面(b.bjpowernode.com)。
3. 同源还是不同源 33
3.1 区分同源和不同源的三要素 33
- 协议
- 域名
- 端口
- 协议一致,域名一致,端口号一致,三个要素都一致,才是同源,其它一律都是不同源
4. AJAX跨域解决方案 34
4.1 方案1:设置响应头 34
- 核心原理:跨域访问的资源允许你跨域访问。
实现:
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080"); // 允许某个
response.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有
代码在E:\java学习\Ajax\course\course10\web 34-35
ajax1.html
<!--测试ajax跨域访问 33-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试ajax跨域访问</title>
</head>
<body>
<!--发送ajax跨域请求-->
<script type="text/javascript">
/* window.onload = function (){
document.getElementById("btn").onclick = function (){
}
}*/
/*
* 默认情况下:发送ajax跨域请求的时候会出现以下错误:
* Access to XMLHttpRequest at 'http://localhost:8081/b/hello' from origin 'http://localhost:8080' has been blocked by CORS policy:
* No 'Access-Control-Allow-Origin' header is present on the requested resource.
* 出现这个错误的根本原因是:跨域的时候,不允许共享同一个XMLHttpRequest对象。因为共享同一个XMLHttpRequest对象是不安全的。
* 重点提示:CORS策略阻止(这个ajax跨域请求被:同源策略阻止。)
* 什么是同源策略?????
* 同源策略是浏览器的一种安全策略。
* 什么是同源?什么是不同源?
* 协议一致、域名一致、端口号一致。才是同源。
* 只要上面的任一元素不一致,就是不同源。
* 同源:XMLHttpRequest对象可以共享。
* 不同源:XMLHttpRequest对象不可以共享。
*/
//使用ES6新特性:箭头函数
window.onload = () =>{
document.getElementById("btn").onclick = () =>{
// 发送ajax的跨域请求
// 1. 创建核心对象
// let是一个关键字,可以定义变量。
// ES6的新特性:let和const关键字都可以定义变量。
// 注意:在JS中声明变量,可以使用:var let const。他们之间有什么区别?自己研究。
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () =>{
if (xhr.readyState==4){
if (xhr.status>=200 && xhr.status<300){
document.getElementById("mydiv").innerHTML = xhr.responseText
}
}
}
xhr.open("GET","http://localhost:8081/b/hello",true)
xhr.send()
}
}
</script>
<button id="btn">发送ajax跨域请求</button>
<div id="mydiv"></div>
</body>
</html>
在course-10_1中
com.bjpowernode.b.web.servlet
HelloServlet
package com.bjpowernode.b.web.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
//测试ajax跨域访问 33
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置响应头允许ajax跨域访问 34
//response.setHeader("Access-Control-Allow-Origin","http://localhost:8080");
response.setHeader("Access-Control-Allow-Origin","*");//*号代表任何网站都可访问
//响应
response.getWriter().print("hello,ajax!!!");
}
}
4.2 方案2:jsonp 35
4.2.1 jsonp演示跨域 35
- jsonp:json with padding(带填充的json)
- jsonp不是一个真正的ajax请求。只不过可以完成ajax的局部刷新效果。可以说jsonp是一种类ajax请求的机制。
- jsonp不是ajax请求,但是可以完成局部刷新的效果,并且可以解决跨域问题。
- 注意:jsonp解决跨域的时候,只支持GET请求。不支持post请求。
代码在E:\java学习\Ajax\course\course10\web 35
ajax2.html
<!--jsonp实现跨域 35-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsonp实现跨域</title>
</head>
<body>
<script type="text/javascript">
/**
* 这是我自定义的函数
*/
function sayHello(data){
//alert("hello world!")
alert("hello," + data.name)
}
function sum(){
alert("求和。。。")
}
</script>
<!--超链接也可以跨域呀?为什么不用呢?因为超链接点击之后会跳转页面,无法做到页面局部刷新效果。-->
<!--script标签是可以跨域的。src属性可以是xxx.js文件,那这个路径可以是一个servlet路径吗?可以-->
<script type="text/javascript" src="http://localhost:8081/b/jsonp?fun=sum"></script>
</body>
</html>
在course-10_1中
com.bjpowernode.b.web.servlet
JSONServlet1
package com.bjpowernode.b.web.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
//演示jsonp的跨域请求 35
@WebServlet("/jsonp")
public class JSONServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//在后台输出
System.out.println("jsonp方式完成跨域访问");
//向前端响应一段js代码
PrintWriter out = response.getWriter();
//out.print("alert(123)");// 这是响应一段js代码,只不过这个alert函数是JS内置的函数,可以直接用。
// 注意:不要误以为是后端java代码调用了sayHello()函数,实际上后端只负责响应一个字符串回去。
// 真正的调用者,还是浏览器,浏览器接收到这个字符串之后,会自动将这个字符串当做一段js代码解释执行。
//out.print("sayHello()"); // 这也是响应一段JS代码。只不过这个sayHello函数是程序员自定义的。
//响应一段js代码,然后传一个json数据给前端
//out.print("sayHello({\"name\" : \"jackson\"})");
//动态获取函数名
String fun = request.getParameter("fun");
//out.print(fun+"({\"name\" : \"jackson\"})");
out.print(fun+"()");
}
}
4.2.2 jsonp解决跨域问题,达到ajax局部刷新的效果 36
代码在E:\java学习\Ajax\course\course10\web 36
ajax3.html
<!--jsonp解决跨域问题,达到ajax局部刷新的效果 36-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsonp跨域</title>
</head>
<body>
<!--<script type="text/javascript" src="http://localhost:8081/b/jsonp?fun=sayHello"></script>-->
<script type="text/javascript">
//自定义函数
function sayHello(data){//data是一个json:{"username":"lucy"}
document.getElementById("mydiv").innerHTML = data.username
}
window.onload = ()=>{
document.getElementById("btn").onclick = ()=>{
//加载script元素
//创建script元素对象
const htmlScriptElement = document.createElement("script");
//设置script的type属性
htmlScriptElement.type = "text/javascript"
//设置script的src属性
htmlScriptElement.src = "http://localhost:8081/b/jsonp2?fun=sayHello"
//将script对象添加到body标签中(这一步就是加载script)
//解释getElementsByTagName根据"body"标签得到的是一个数组,但是我们只有一个body标签,所以
//得到的数组就一个元素,然后我们将我们创建出来的script对象也就是htmlScriptElement
//作为孩子添加进body标签
document.getElementsByTagName("body")[0].appendChild(htmlScriptElement)
}
}
</script>
<button id="btn">jsonp解决跨域问题,达到ajax局部刷新的效果 </button>
<div id="mydiv"></div>
</body>
</html>
在course-10_1中
com.bjpowernode.b.web.servlet
JSONServlet2
package com.bjpowernode.b.web.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
//jsonp解决跨域问题,达到ajax局部刷新的效果 36
@WebServlet("/jsonp2")
public class JOSNServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取函数名
String fun = request.getParameter("fun");
//响应一段js代码
response.getWriter().print(fun+"({\"username\":\"lucy\"})");
}
}
标签:http,跨域,jakarta,ajax,理解,import,servlet,请求
From: https://blog.51cto.com/u_15784725/6378108