一. 过滤器
**作用:**拦截web服务器向后端发送的数据,使请求地址在到达servlet之前进入到指定的过滤器中,可以对数据进行一些统一的处理,比如设置编码,权限控制等
**使用:**创建一个类实现Filter接口,并实现里面的doFilter()方法,过滤器要做的作用主要写在doFilter方法中
java
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
filterChain.doFilter(servletRequest, servletResponse);
}
}
这是一个设置编码的过滤器,被配置的会被该过滤器拦截的servlet程序,都会在到达后端前被统一设置为utf-8编码
注意:
- 上述案例最后一句代码必须要写,否则程序不会继续向下执行,发出的请求将不会到达后端程序,最后一句表示将信息继续传递给下一个过滤器,如果所有过滤器都被执行,就会传递到后端
- 过滤器中除了有抽象方法doFilter,还有两个默认方法init()和destroy()不是必须要实现的,在需要的时候实现即可,不实现默认调父类的,父类的是空的
- 但是仅仅只是实现了Filter这个接口并不能使用过滤器,因为过滤器和servlet程序一样需要进行配置,我们需要对他设置哪些servlet程序会被该过滤器拦截,和servlet程序一样,有两种配置方法
1. web.xml文件中配置过滤器
html
<!--
注册过滤器,告诉服务器有这么一个过滤器
-->
<filter>
<filter-name>coding</filter-name>
<filter-class>com.ffyc.dormServer.filter.EncodingFilter</filter-class>
</filter>
<!--
配置过滤器,指定哪些servlet程序会被该过滤器拦截
/* 表示所有servlet程序都会被拦截
/login 表示地址为/login的servlet程序会被拦截
-->
<filter-mapping>
<filter-name>coding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2. 注解配置过滤器
java
@WebFilter(urlPatterns = "/*")
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
filterChain.doFilter(servletRequest, servletResponse);
}
}
在类的上面加上@WebFilter注解,服务器会自动的检查该注解里面的信息,就知道该过滤器会拦截哪些servlet程序,urlPatterns表示要拦截的地址,里面还可以有很多属性,比如name表示为该过滤器起一个名字,loadonStartup默认为-1表示在第一次访问时创建servlet对象,如果将其改为0或1表示在服务器启动时就创建该servle对象
二. 同步请求与异步请求
1. 同步请求
**同步:**同时只能做一件事
**同步请求:**当前端向后端发送请求时,此时客户端的一切操作会停止,后端返回来的响应会覆盖当前网页中的内容,一次只能做一件事,与服务器交互时,客户端就不能继续进行操作了,很影响客户体验
1.1 实现同步请求
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js"></script>
<script>
function checkAccount(account){
location.href="http://127.0.0.1:8088/webServer/check?account="+account;
</script>
</head>
<body>
账号:<input type="text" name="account" onblur="checkAccount(this.value)"/><span id="msg"></span><br/>
密码:<input type="password">
</body>
</html>
当我们将输入好账号时,本来应该输入密码,但由于输入完账号,就要像后端发出请求,来验证我这个账号是否已经存在,存在就不能注册,不存在才能注册,但由于是同步请求,输入结束后,该页面就被后端的响应覆盖,导致用户无法继续操作,体验感很差
2. 异步请求
**异步:**同时能做多件事
**异步请求:**当客户端与服务器交互时,不会影响客户端页面的操作,后端发来的响应不会覆盖整个页面
可以同时完成多件事,比如客户端的操作和向后端发送的请求处理
2.1 实现异步请求
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js"></script>
<script>
function checkAccount(account){
// 1.创建请求对象
var httpobj = new XMLHttpRequest();
httpobj.open("get","http://127.0.0.1:8088/webServer/check?account="+account); //封装请求
httpobj.send(null); //发送请求 */
// 2.执行回调函数,接收响应的结果
httpobj.onreadystatechange = function(){
document.getElementById("msg").innerHTML = httpobj.responseText;
}
}
</script>
</head>
<body>
账号:<input type="text" name="account" onblur="checkAccount(this.value)"/><span id="msg"></span><br/>
密码:<input type="password">
</body>
</html>
可以看到当我们填写完账号时,向后端发出检查的请求,后端做出响应后,客户端仍然可以进行操作,且页面内容不会被覆盖
2.2 axios框架实现异步请求
虽然上述方法成功实现了异步请求,但是写法相对麻烦,但却是最本质的,为了便于程序员书写,我们可以用axios框架实现异步请求,axios是一个http的网络请求库
2.2.1 基本的HTML文件中配置axios框架
- 首先去官网找文档,下载axios.js文件
将上述地址复制到浏览器中,右键点击另存为下载到一个能找到的地方,然后打开HBuilder X
将其拖到你创建的普通项目的js文件夹中,然后导入到html文件中,就和之前导入vue普通项目一样
然后按照下面的代码就可以使用框架实现异步请求
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js"></script>
<script>
function checkAccount(account){
axios.get("http://127.0.0.1:8088/webServer/check?account="+account)
.then(function(response){
document.getElementById("msg").innerHTML = response.data;
console.log(response);
})
}
}
</script>
</head>
<body>
账号:<input type="text" name="account" onblur="checkAccount(this.value)"/><span id="msg"></span><br/>
密码:<input type="password">
</body>
</html>
2.2.2 vue-cli项目中配置axios框架
-
打开HBuilder X创建一个vue-cli项目并完成配置,打开终端输入以下指令
npm install axios
-
在main.js中完成以下配置
2.1 导入axios
import axios from 'axios';
2.2 设置访问后台服务器的地址
html
axios.defaults.baseURL="http://127.0.0.1:9999/api/";
<!--
127.0.0.1:9999这是IP和端口,是服务器的IP和端口,需要自己改
/api是访问后台哪个serlet程序的地址,这些在web.xml文件或注解中都配置过
也需要自己改
-->
注意:
127.0.0.1:9999这是IP和端口,是服务器的IP和端口,需要自己改
/api是访问后台哪个serlet程序的地址,这些在web.xml文件或注解中都配置过也需要自己改
2.3 将axios挂载到vue全局对象中,使用this可以直接访问
html
Vue.prototype.$http=axios;
这句话的意思是,将axios挂载到全局唯一的vue对象中,并给axios起了一个别名叫http,可以通过this.$http来访问该axios对象
这样就配置完成了,接下来使用get或post方法即可发送对应的请求,then方法中的回调函数会在请求成功或失败时触发,通过回调函数的形参可以获取响应内容,或错误信息
基本语法:
html
this.$http.get(地址?Key=value&key2=val1).then(function(response){ }
this.$http.post("login",{key:"value",key2:"val2"}).then(function(response){ }
post请求的写法
get请求也是类似的
三. 跨域问题
前后端在进行异步交互时会出现跨域问题
1. 跨域问题
不同服务器间进行访问,浏览器不允许js接收来自其他服务器响应的数据,只要协议,域名,端口其中一个不同,都属于跨域访问
2.为什么要跨域访问
1.因为一个公司会有很多业务,这些业务部署在不同的服务器中,当某个业务需要与其他业务进行交互时,就会遇到两个不同的服务器之间需要进行访问.
2.现在的项目大部分都是前后端分离的,而往往前端项目部署在一个服务器中,后端项目部署在一个服务器中,这样就能减轻服务器的压力,但是访问时就需要跨域访问了
所以我们必须要允许跨域访问的存在
3.浏览器为什么阻止跨域访问
为了安全,不能让其他服务器中的内容肆意的响应到自己的服务器中
4.如何解决跨域问题
后端:在响应时告诉浏览器允许接收来自某些指定服务响应的内容,加一个过滤器即可
前端:处理方式很多,而且跨域问题本就是前端需要考虑的问题
四. 后端响应标准格式json数据
当我们前端向后端发送一个请求,后端经过处理向前端返回一个响应,但前后端所用的语言不同,换句话说,前端无法正确识别后端返回来的信息,也就无法将其正确的输出到网页中,所以为了统一,作出了一种规定,后端向前端响应的是标准格式的json数据
**json(javaScript Object Notation):**javaScript对象表示法,用于交换解析文本信息的,比以前的web.xml文件更轻量级
有了json我们后端的java程序只要发送一种固定的json数据格式,这样前端就能成功识别并显示
json格式:"{键:值},{键:值}"这样的字符串
当然在后端并不需要我们自己去将结果拼接成一个这样的字符串,而是通过第三方的jar包来实现好的,我们只需要导入相应的依赖到maven中即可
json依赖:
html
<!--json-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.2</version>
</dependency>
我们后端在处理时往往会创建一个Result类该类专门用于返回响应结果,结果包含状态码,响应内容,以及相应的对象数据
java
/*
登录处理的servlet程序
*/
@WebServlet(urlPatterns = "/login",name = "login",loadOnStartup = 1)
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求
String account = req.getParameter("account");
String password = req.getParameter("password");
PrintWriter pw = resp.getWriter();
Result<Admin> result = null;
//对请求进行处理
try {
Admin admin = new LoginDao().login(account, password);
if(admin!=null){
result = new Result<>(200,"登录成功",admin);
}else{
result = new Result<>(201,"账号或密码错误",null);
}
} catch (Exception e) {
result = new Result<>(500,"系统忙,请稍后再试!",null);
}
pw.write(new ObjectMapper().writeValueAsString(result));
}
}
可以看到这是一个登陆的后端响应程序,我们将与数据库交互的结果放在一个对象中,并将该对象存在一个Result对象中,这样就能返回一个标准的json格式的响应