拦截器是SpringMVC中的一个核心应用组件,主要用于处理多个Controller的共性问题.当我们的请求由DispatcherServlet派发到具体Controller之前首先要执行拦截器中一些相关方法,在这些方法中可以对请求进行相应预处理(例如权限检测,参数验证),这些方法可以决定对这个请求进行拦截还是放行。
1. 服务器与请求
1.1. 常见的WEB服务器
- Toncat服务器:我最常用的服务器,开放源代码的,运行servlet和JSP Web应用软件基于Java,比绝大多数的商业用的软件服务器要好。
- Apache服务器:使用广泛,开源代码,支持多个平台,相对其他服务器占的内存较大,是重量级产品。
- Microsoft IIS服务器:微软的,包括Web服务器,FTP服务器,NNTP服务器和SMTP服务器。需要购买。
- Nginx服务器:俄罗斯的一个站点开发的,相比于Apache服务器,Nginx占用内存小且较稳定。
1.2. 发送请求
前端向服务器发送请求有2种,(1)通过浏览器发送请求,(2)进入到系统后,通过js发送请求。
1.3. 通过浏览器发送URL请求
(1)用户在浏览器上输入网址,包含协议和域名.
(2)浏览器获得IP地址,浏览器先找自身缓存是否有记录,没有的话再找操作系统缓存,再没有就请求本地DNS服务器帮忙,本地DNS再找不到再一层层往上,最终浏览器获得对应的IP地址。
(3)浏览器发送请求,浏览器根据HTTP协议,给对应IP地址的主机发送请求报文,默认端口为80,报文包括请求内容,浏览器信息,本地缓存,cookie等信息。
(4)web服务器接收请求,寻找文件,Tomcat服务器接收到请求,找对应的html文件
(5)返回数据,web服务器向浏览器反馈html文件,浏览器进行渲染,页面加载。
1.4. js文件发送请求
在项目中,使用ajax向服务器发送请求,例如xxx.do。
2. 实现拦截器
拦截器需要实现 HandleInterceptor接口,或者继承HandlerInterceptorAdaptor抽象类;
HandlerInterceptor接口的三个方法:
- preHandle()
- postHandle()
- afterCompletion()
inceptor的作用是,每次在前端向后台发送一个请求时do,后台都会先经过inceptor中的preHandle这个函数,判断这个请求是否满足要求(是否已经登录,是否是管理员),如果满足要求就返回true,系统会自动把这个do请求提交给controller对应的函数进行处理,controller中的函数调用完之后,再次进入Inception中的postHandle()和afterCompletion()方法中。否则preHandle返回false,不会提交这个请求,不会执行Controller中的函数,也不会执行之后的Inception中的postHandle()和afterCompletion()方法。
服务器一启动,就会创建拦截器对象;拦截器是单例的,整个过程,拦截器只有一个实例对象。
项目中需要实现一个登录系统,当用户没有登录时,不能访问系统的主页和其他页面,但是可以访问系统的登录界面,所以需要在mvc.xml中设置一下,不拦截登录的请求。
2.1. Controller
下面是用户登录的Controller实现,当前端访问login.jsp时,这时登录的请求不会被拦截器拦截,会执行login()方法,验证前端用户输入的用户名和密码是否正确,如果正确的话,将userName放入到session中,并返回给前端index,那么界面将会跳转到index.jsp,如果用户名或密码错误,那么返回给前端login,前端界面还是login.jsp。
1 |
|
2.2. Interceptor
在interceptor中会拦截URL请求,如果session中的用户名为空会重定向到login.jsp。但在在做项目时遇见一个问题,拦截器只能拦截js中的ajax发来的URL请求,不能拦截浏览器发送的URL请求。也就是说如果用户在浏览器中输入index.jsp,不会经过拦截器,如果是js中的ajax发送的请求,会经过拦截器。如果用户没有登录直接在浏览器中输入index.jsp,这时页面依然可以进入到index.jsp,这说明拦截器没有起作用。为了应对这一情况,有三种解决方案:
(1)把判断用户是否登录的代码写到了jsp中,在jsp中写java代码需要加上<%%>,在这里判断session中的用户名,如果为空的话,直接重定向到login.jsp,这样用户在未登录的情况下,在浏览器上输入index.jsp,页面不会跳转到index.jsp中,还是在login.jsp中。
(2)把所有的jsp文件放在WEB-INF文件里,这样用户是直接不能访问WEB-INF文件下的jsp文件的。spring mvc的理念也是通过controller里的@RequestMapping来请求相关jsp页面,而非用户直接访问jsp页面。也就是说,jsp页面的访问需要通过controller来进行一次请求,因为会拦截对controller的请求,所以也就相当于拦截了jsp页面。如果要做登陆拦截,只需要把登陆页面不拦截,其余页面拦截进行是否登陆的验证即可。
(3)jsp如果不放在WEB-INF文件下,spring mvc是无法拦截的,这种情况下需要用最原始的servlet的Filter接口。
1 | <% |
1 | public class LoginInterceptor implements HandlerInterceptor { |
2.3. mvc配置文件
在mvc.xml配置文件中,需要对拦截器进行配置,因为login请求不需要拦截,所以把这个请求排除,这样当前端访问login.jsp页面时,就会显示出登录的界面。
1 | <mvc:interceptors> |
页面加载的顺序:
前端输入一个网址,相当于发出一个url,比如querywda.jsp。首先拦截器拦截这个url,判断是否合法,如果合法,会交给controller处理,处理完之后才会显示querywda的界面,调用相应的querywda.js。如果不合法,就应该在inception就把这个请求拦截下来,重定向到login,这样querywda的界面也不会加载出来