同步/异步请求
表单(前端)向后端发送请求,属于同步请求
同步: 发一个请求, 给一个回应, 会用回应的内容覆盖掉浏览器中内容,这样会打断前端其他的正常操作,在现在的前端中,显得不太友好。
异步: 不同步 前端正常输入时,可以同时与后端进行交互,后端响应的数据不会影响前端正常操作.
可以使用一个js中提供的对象,向后端发送请求, 服务器响应的内容会被js对象接收。然后在js中,用接收到的内容局部的更新网页,这样整个过程页面不会出现刷新,覆盖操作,不会打断页面的正常操作。现在的前后端交互技术,基本都是基于Ajax的异步交互技术
现在的前后端交互技术,基本都是基于Ajax的异步交互技术
Ajax 阿贾克斯 异步交互技术
Ajax 全称为:“Asynchronous JavaScript and XML”(异步 JavaScript 和 XML),使用 Ajax,可以无刷新状态更新页面,并且实现异步提交,提升了用户体验。
Ajax其实质是利用浏览器提供的一个特殊的对象(XMLHttpRequest)异步地向服务器发送请求,服务器返回部分数据,浏览器让你去利用这些数据对页面做部分的更新,整个过程,页面无刷新,不打断用户的操作。
创建XMLHttpRequest对象
XMLHttpRequest对象:发送请求到服务器并获得返回结果
浏览器都建了XMLHttpRequest 对象,通过一行简单的JavaScript 代码,我们就可以创建 XMLHttpRequest 对象。 new XMLHttpRequest();
JavaScript对象XMLHttpRequest是整个Ajax技术的核心,它提供了异步发送请求的能力
常用方法:
常用属性
onreadystatechange:事件,指定回调函数
readystate: XMLHttpRequest的状态信息
responseText:获得响应的文本内容
Get方式提交:
xmlhttp.open("GET" , "testServlet?name= "+userName,true);
xmlhttp.send();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
function checkAccount(account){
var httpobj=new XMLHttpRequest();
httpobj.open("get","http://127.0.0.1:8080/webBack/reg?account="+account,true);
httpobj.send();
httpobj.onreadystatechange=function(){
//接收后端的响应数据
document.getElementById("aid").innerHTML=httpobj.responseText;//存在一个问题,浏览器默认不让前端8848接收来自其他服务器的响应数据
}
}
</script>
</head>
<body>
<form action="http://127.0.0.1:8080/webBack/reg" method="post">
账号:<input type="text" name="account" value="" onblur="checkAccount(this.value)"/>
<span id="aid"></span><br />
密码:<input type="text" name="password" value=""/><br/>
</form>
</body>
</html>
package servlet;
public class RegServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String account=req.getParameter("account");
resp.setHeader("Content-Type","text/html;charset=utf-8");//设置啊应义
if(account.equals("admin")){
resp.getWriter().print("账号已经被注册");
}else{
resp.getWriter().print("账号可以注册");
}
}
}
但是存在一个问题,浏览器默认不让前端8848接收来自其他服务器的响应数据。
跨域
但是前后端交互中出现一个跨域问题:属于前端问题
跨域是指从一个域名的网页去请求另一个域名的资源。只要协议、域名,端口有任何一个的不同,就被当作是跨域
在前端服务页面中(8848) 接收后端服务器响应的数据(8080),使用ajax技术前端后交互,为了安全性,前端默认会进行阻止,不让前端服务接收其他后端的数据。
跨域问题解决:
前端解决
后端解决:跨域资源共享(Cross-origin Resource Sharing),简称CORS
这个机制就是实现了跨站访问控制,使得安全地进行跨站数据传输成为可能。服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许ajax进行跨域的访问。只需要在后台中加上响应头来允许域请求!在被请求的Response header中加入设置,就可以实现跨域访问了!在响应头中设置说明,告知浏览器,此次的响应是可靠的。
创建过滤器实现后端设置允许跨域访问:
package filter;
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);
}
}
<!--配置允许跨域响应-->
<filter>
<filter-name>corsFilter</filter-name>
<filter-class>filter.CorsFilter</filter-class>
</filter>
<!--配置进入到过滤器的映射地址-->
<filter-mapping>
<filter-name>corsFilter</filter-name>
<url-pattern>/*</url-pattern><!--配置哪些地址可以进入到当前的过滤器中-->
</filter-mapping>
axios框架
下载axios文件https://unpkg.com/axios/dist/axios.min.js
将axios.min.js放在js目录底下
用axios,后端也要处理跨域问题
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script>
function checkAccount(account){
axios.get("http://127.0.0.1:8080/webBack/reg?account="+account).then(function(resp){//then就相当于回调,请求成功之后就响应,resp是后端响应的数据
document.getElementById("aid").innerHTML=resp.data;//get请求。
})
/* axios.post("http://127.0.0.1:8080/webBack/reg","account="+account+"&age=20").then(function(resp){
document.getElementById("aid").innerHTML=resp.data;
//post请求数据是在请求体中,数据和地址是分开的。resp.data是后端响应的数据
}) */
}
</script>
</head>
<body>
<form action="http://127.0.0.1:8080/webBack/reg" method="post">
账号:<input type="text" name="account" value="" onblur="checkAccount(this.value)"/>
<span id="aid"></span><br />
密码:<input type="text" name="age" value=""/><br/>
</form>
</body>
</html>
JSON
后端如何向前端响应更多的数据,可以把数据封装在一个个对象中,然后把对象直接响应给前端
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式
数据在键值对中
数据由逗号分隔
大括号保存对象
方括号保存数组
语法:
JSON 键值对是用来保存 JS 对象的一种方式,和 JS 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 " " 包裹,使用冒号 : 分隔,然后紧接着值:
{"firstName": "John"}
{"name":"value","sex":"男"}
将以下6个jar包导入lib底下:
jackson-annotations-2.13.2.jar
jackson-core-2.13.2.jar
jackson-databind-2.13.2.2.jar
jackson-datatype-jdk8-2.13.2.jar
jackson-datatype-jsr310-2.13.2.jar
jackson-module-parameter-names-2.13.2.jar
public class RegServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost");
resp.setHeader("Content-Type","text/html;charset=utf-8");
String num=req.getParameter("num");
Student student=new Student(num,"张三","男","13677778888");
//resp.getWriter().print(student);//向前端响应的是对象的hashcode值
//涉及到了两种不同语言(java,js)之间进行数据交互 以前java把数据写入到一个xml 文件中,把xml文件传给前端,前端解析此做法非常复杂.
//现在交互中,产生一种轻量级的数据格式(name:"jim",age:20]
// student对象 --->num:109,name:"jim",age:20]
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsString(student);//转为JSON键值对形式的字符串
System.out.println(s);
resp.getWriter().print(s);//响应给前端
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script>
function checkAccount(num){
axios.post("http://127.0.0.1:8080/webBack/reg","num="+num).then(function(resp){
//resp.data->Student对象,前端接收到JSON字符串后,自动会转化为js对象
console.log(resp.data);
console.log(resp.data.num);
console.log(resp.data.name);
console.log(resp.data.gender);
console.log(resp.data.phone);
})
}
</script>
</head>
<body>
<form action="" method="post">
学号:<input type="text" name="num" value="" onblur="checkAccount(this.value)"/><br/>
<span id="aid"></span><br />
</form>
</body>
</html>