Ajax+跨域
引入
前面,我们学习了Servlet,学会了如何搭建一个简单的JavaWeb项目。
现在梳理一下上节课的内容,我们学会了简单的服务器搭建,学会了使用Servlet的创建和使用,知道了Servlet的生命周期,这些在Servlet接口中已经定义好了这些方法,包括,初始化 构造方法,init
,服务service
,销毁destory
。
构造方法在第一次请求该Servlet服务时,调用创建且调用一次。
一次http请求发送到后端找到Servlet程序,是按照一个特定顺序调用方法的
init 方法在构造方法执行完成后立即执行,用来初始化Servlet,有一个ServletConfig参数,封装servlet配置信息,只执行一次
service 方法每次请求都会执行,提供服务,该方法有两个参数ServletRequest和ServletResponse,ServletRequest保存了客户端向服务器发送的请求,而ServletResponse用来设置如何对客户端进行响应
destory方法,在服务器关闭时执行,可以在服务器关闭时加入自己要实现的操作
而在service方法中会根据method.equals(“请求方式”)匹配请求方式,根据不同的请求方式,调用不同的方法例如:doGet ( ) 和doPost ( ) 我们在Servletde实现类中重写这些方法,以实现该Servlet的业务,例如:注册,登录。
过滤器:在后面我们发现了光使用Servlet实现类书写逻辑的话,会出现严重的代码重写,例如:再每个Servlet业务中都要书写这串代码servletRequest.setCharacterEncoding(“utf-8”);,以修改响应的字符格式,这些东西我们可以书写再过滤器中,只写一次,以达到多次使用的效果,避免了代码赘余,而过滤器的作用还有权限访问控制,过滤敏感词汇
上节课,我们写了一个简单的Web项目,通过判断数据库中是否拥有注册用户名来向用户提示是否可以注册该用户名,但是,提示的信息要刷新浏览器,用户只有返回注册界面才可以继续操作。
1. Ajax
上述情况,我们要避免刷新,并且向服务器提交数据判断是否拥有该用户名的操作应该不能影响用户下面的操作才行 (异步) ,而Ajax可以做到。前后端同步请求,后端相应的内容,会把整个页面内容覆盖掉,打断了客户端的其他操作。
在这里提出一个异步的概念,讲异步之前,先将同步,同步就是,一定要等任务执行完了,得到结果,才执行下一个任务;而异步则是,任务执行不影响下面的任务,相当于多线程。
1.1 Ajax简介
Ajax就是实现异步的一种技术
Asynchronous JavaScript and XML,Ajax后端向前端响应数据时,是将数据封装到一个XML文件中的,前端接受后解析XML,这已经是过去式了,现在使用轻量级的json
XMLHttpRequest对象向后端发送请求,接受相应的内容。这个过程中出现了跨域问题,以后讲解,我们只需复制CorsFilter到过滤器包即可
- Ajax 全称为:“Asynchronous JavaScript and XML”(异步JavaScript 和 XML),使用 Ajax,我们可以无刷新状态更新页面,并且实现异步提交,提升了
用户体验。- Ajax其实质是利用浏览器提供的一个特殊的对象(XMLHttpRequest)异步地向服务器发送请求。
- 服务器返回部分数据,浏览器让你去利用这些数据对页面做部分的更新,整个过程,页面无刷新,不打断用户的操作。
1.2 创建 XMLHttpRequest 对象
前端如何发送异步请求呢?
使用JS提供的一个XMLHttpRequset对象,代理网页向后端发送一个请求(异步的),服务器相应的内容,也是由此对象接收的,最终在js中将接受的数据更新到网页中某个标签上,不影响网页的其他操作,网页不会出现刷新。
上面说了Ajax利用XMLHttpRequest异步的向服务器发送请求,我们重点学习一下。
- XMLHttpRequest对象:发送请求到服务器并获得返回结果
- 所有现代浏览器 都内建了 XMLHttpRequest 对象,通过一行简单的JavaScript 代码,我们就可以创建 XMLHttpRequest 对象。
- new XMLHttpRequest()
- JavaScript对象XMLHttpRequest是整个Ajax技术的核心,它提供了异步
发送请求的能力
常用方法
方法名 | 说 明 |
---|---|
open(method,URL,async) | 建立与服务器的连接method参数指定请求的HTTP方法,典型的值是GET或POST,URL参数指定请求的地址,async参数指定是否使用异步请求,其值为true或false |
send(content) | 发送请求content参数指定请求的参数 |
setRequestHeader(header,value) | 设置请求的头信息 |
常用属性
- onreadystatechange:事件,指定回调函数
- readystate: XMLHttpRequest的状态信息
- responseText:获得响应的文本内容
就绪状态码 | 说 明 |
---|---|
0 | XMLHttpRequest对象没有完成初始化 |
1 | XMLHttpRequest对象开始发送请求 |
2 | XMLHttpRequest对象的请求发送完成 |
3 | XMLHttpRequest对象开始读取响应,还没有结束 |
4 | XMLHttpRequest对象读取响应结束 |
● Get方式提交:
xmlhttp.open("GET","testServlet?name="+userName,true);
xmlhttp.send();
以下是代码实例,以下代码如果不解决跨域问题,则无法显示服务器返回的信息,因为出现了跨域,下面来着重讲一下跨域的相关概念。
function checkAccount(username){
var httpObj = new XMLHttpRequest();
// true表示异步
httpObj.open("GET","http://localhost:8080/webback/reg?username="+username,true);
httpObj.send(null);//发送请求
//接受请求
httpObj.onreadystatechange = function(){
if(httpObj.readyState==4){
/* alert(httpObj.responseText);
/*这里没有弹出后端的响应数据 */
document.getElementById("mesId").innerHTML = httpObj.responseText;
}
}
}
2. 跨域
2.1 什么是跨域 ?
跨域是指从一个域名的网页去请求另一个域名的资源。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。跨域严格一点的定义是:只要协议,域名,端口,由任何一个不同,就是跨域。
2.2 为什么浏览器要限制跨域访问呢
如果一个网页可以随意的访问另一个网站的资源,那么就回出现安全问题。
2.3 为什么要跨域
有的大型网站由很多不同的子域,这些网站需要互相交流数据。
2.4 解决跨域问题
这里使用后端解决
跨域资源共享(CORS)
W3C 的 Web 工作组推荐了一种新的机制,即跨域资源共享(Cross-origin Resource Sharing),简称CORS。其实这个机制就是实现了跨站访问控制,使得安全地进行跨站数据传输成为可能。
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许ajax进行跨域的访问。
只需要在后台中加上响应头来允许域请求!在被请求的Response header中加入设置,就可以实现跨域访问了!
创建过滤器实现后端设置允许跨域访问:
参考代码:配置web.xml,以过滤器的配置格式进行配置
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CorsFilter implements Filter {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
//允许携带Cookie时不能设置为* 否则前端报错
httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("origin"));//允许所有请求跨域
httpResponse.setHeader("Access-Control-Allow-Methods", "*");//允许跨域的请求方法GET, POST, HEAD 等
httpResponse.setHeader("Access-Control-Allow-Headers", "*");//允许跨域的请求头
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");//是否携带cookie
filterChain.doFilter(servletRequest, servletResponse);
}
}
3. Axios框架
Axios是Ajax框架,详情了解Axios官网
就是这个框架里封装了XMLHttpRequest可以向发送异步请求且简化了Ajax中繁杂的代码。
● 下载axios文件https://unpkg.com/axios/dist/axios.min.js
● 导入项目
//get请求
axios.get('/user?ID=12345').then(function (response) {
console.log(response);
})
//post请求
axios.post('/user', “name1=value1&name2=value2”).then(function (response) {
console.log(response);
})
//响应结果格式
axios.get('/user/12345').then(function(response) {
console.log(response.data);//后端返回数据,默认为json格式
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.config);
});
使用Axios框架后的js代码:
function checkAccount(username){
axios.get("http://localhost:8080/webback/reg?username="+username).then(function(resp){
console.log(resp);//这行代码可以查看resp中的属性,可以注释,不影响业务
document.getElementById("mesId").innerHTML = resp.data;
});
}
4. JSON
JSON(JavaScript Object Notation JavaScript对象表现形式)是一种轻量级的数据交换格式
上面我们后端向前端响应数据仅仅响应了一个字符串,而Java作为面向对象的语言,我们肯定不会仅仅只返回字符串,有时候还会返回对象,但在这时,前端JavaScript虽然也是面向对象的语言,Java与JavaScript两个编程语言无法相互识别(就如同懂英语的人和懂中文的人无法交流,除非两人都懂英文与中文,否则,两者无法用不同的语言进行交流,而JSON则是Java生成一个JSON格式的字符串,发送到前端,前端再解析成JavaScript对象),JSON用于不同语言之间的数据交换。
早期数据交换使用的是XML文件,将数据写在标签中但是过于复杂,现在用JSON
JSON(JavaScript Object Notation) 是一种轻量级的数据交
换格式
- 数据在键值对中
- 数据由逗号分隔
- 大括号保存对象
- 方括号保存数组
语法:
JSON 键值对是用来保存 JS 对象的一种方式,和 JS 对象的写法也大同小异,键/值对
组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值:
{“firstName”: “John”}
{“name”:”value”,”sex”:”男”}
//导入json jar包之后,两行代码便可发送数据,前端只需根据数据.属性名访问即可
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(要发送的对象);
要发送的对象必须书写get()方法
5. 总结
这节课因为网页向后端传输数据导致页面刷新的原因我们引入了异步的概念,异步就是不同步,通过异步请求不影响用户接下来的操作实现网页的局部刷新,而Ajax是用来向后端发送异步请求的一门技术,而Ajax利用了浏览器提供的一个特殊对象XMLHttpRequest异步的向后端发送请求,而后续呢,我们又讲了Axios(Ajax框架),将Ajax代码封装了起来,实现了代码的简化,且Axios内部仍是和Ajax相同的原理。
在前端向后端发送请求时,若是表单提交给后端,数据则是以Json格式传输给字符串(Json就是一种字符格式),而Json格式的表单数据传输给后端时,后端无法识别,现在我们的解决方式是,转化为Java可以识别的字符串(键值对),这时,前端的任务便完成了。
接下来将后端,后端接收到请求之后,执行Servlet构造方法,初始化方法,服务方法,调用响应请求方式的方法,获取用户数据,处理用户数据,返回用户数据,这个时候又涉及到问题:
- 跨域:我们通过加入一个过滤器设置响应头中的数据,可以理解为暗号,只要响应头中的数据设置之后,前端便会识别这个数据是可靠的,从而接收数据,响应到前端。
- Java对象与JavaScript语法不一致,导致相互之间的数据无法识别,这里我们通过将对象转化为Json,解决了前端不识别后端格式的问题