SpringMVC 之 Interceptor 拦截器之登录拦截器,阿里巴巴 java 面试题
前言
统一说明一下,楼主是研究生,一般的 985 毕业,之前在工作了 6 年,做过的大项目数不胜数,
比如再造淘宝项目落地实战,某滴网约车项目,多人在线即时对战网游服务器,和家云服务平台,前后端分离某喵微信商城,亿级流量多级缓存平台,亚马逊电商个性化推荐系统,IOT 流云式平台,阿里巴巴中台实战,年初跳槽后去阿里面试 6 轮之后定级是 P6。
SpringMVC 的拦截器是主要作用是拦截用户请求到后台之间的请求,在进入后台之前可以对其进行权限认证和用户登录的限制。
1.定义拦截器;
========
springmvc 中拦截器中主要有两种方式:第一种是实现 HandleInterceptor 接口,重写里面的方法;第二种是实现 WebRequestInterceptor 接口,同样的重写里面的方法,实现自己自定义的逻辑处理。
1、实现 handleInterceptor 接口;
接口中定义了三个方法:preHandle(requsest,response.handle);postHandle(request,response,handle,modleandview);aftercompletion(request,response,handle,ex);下面说说每个方法的作用和作用空间。
1.preHandle(requsest,response.handle) :在请求处理之前调用这个方法,即请求从前台传递到 controller 之前调用的方法,返回值是 boolean,如果返回的是 true,那么继续进行下面两个方法;如果返回的是 false,请求结束;我的拦截器里面获取了 request 中的 session 数据;来验证用户是否登录;如果 flag 为 true 返回 true;反之返回 false;
2.postHandle(request,response,handle,modleandview):由 preHandle 方法的解释我们知道这个方法包括后面要说到的 afterCompletion 方法都只能是在当前所属的 Interceptor 的 preHandle 方法的返回值为 true 时才能被调用。postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是 Controller 方法调用之后执行,但是它会在 DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对 Controller 处理之后的 ModelAndView 对象进行操作。postHandle 方法被调用的方向跟 preHandle 是相反的,也就是说先声明的 Interceptor 的 postHandle 方法反而会后执行,这和 Struts2 里面的 Interceptor 的执行过程有点类型。Struts2 里面的 Interceptor 的执行过程也是链式的,只是在 Struts2 里面需要手动调用 ActionInvocation 的 invoke 方法来触发对下一个 Interceptor 或者是 Action 的调用,然后每一个 Interceptor 中在 invoke 方法调用之前的内容都是按照声明顺序执行的,而 invoke 方法之后的内容就是反向的。
3.aftercompletion(request,response,handle,ex):该方法也是需要当前对应的 Interceptor 的 preHandle 方法的返回值为 true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。
代码说明?
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class SpringMVCInterceptor implements HandlerInterceptor {
/**
preHandle 方法是进行处理器拦截用的,顾名思义,该方法将在 Controller 处理之前进行调用,SpringMVC 中的 Interceptor 拦截器是链式的,可以同时存在
多个 Interceptor,然后 SpringMVC 会根据声明的前后顺序一个接一个的执行,而且所有的 Interceptor 中的 preHandle 方法都会在
Controller 方法调用之前调用。SpringMVC 的这种 Interceptor 链式结构也是可以进行中断的,这种中断方式是令 preHandle 的返
回值为 false,当 preHandle 的返回值为 false 的时候整个请求就结束了。
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
<span style="white-space:pre"> </span>HttpSession session = request.getSession();
Enumeration<String> e = session.getAttributeNames();
HashMap< String, String> map = new HashMap<String, String>();
while(e.hasMoreElements()){
map.put(e.nextElement(),"");
}
if (map.containsKey("isLogin")) {
if (session.getAttribute("isLogin").equals(true)) {
System.err.println("session 中 username is :"+session.getAttribute("username"));
return true;
}else{
System.err.println("isLogin is false!");
response.sendError(501, "你还没有登录呢!");
return false;
}
}else{
System.err.println("there is not exist isLogin flag!");
response.sendError(502, "这里有点问题,请访问登录页面!");
return false;
}
}/** * 这个方法只会在当前这个 Interceptor 的 preHandle 方法返回值为 true 的时候才会执行。postHandle 是进行处理器拦截用的,它的执行时间是在处理器进行处理之 * 后,也就是在 Controller 的方法调用之后执行,但是它会在 DispatcherServlet 进行视图的渲染之前执行,也就是说在这个方法中你可以对 ModelAndView 进行操 * 作。这个方法的链式结构跟正常访问的方向是相反的,也就是说先声明的 Interceptor 拦截器该方法反而会后调用,这跟 Struts2 里面的拦截器的执行过程有点像, * 只是 Struts2 里面的 intercept 方法中要手动的调用 ActionInvocation 的 invoke 方法,Struts2 中调用 ActionInvocation 的 invoke 方法就是调用下一个 Interceptor * 或者是调用 action,然后要在 Interceptor 之前调用的内容都写在调用 invoke 之前,要在 Interceptor 之后调用的内容都写在调用 invoke 方法之后。 */@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {}/** * 该方法也是需要当前对应的 Interceptor 的 preHandle 方法的返回值为 true 时才会执行。该方法将在整个请求完成之后,也就是 DispatcherServlet 渲染了视图执行, * 这个方法的主要作用是用于清理资源的,当然这个方法也只能在当前这个 Interceptor 的 preHandle 方法的返回值为 true 时才会执行。 */@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)throws Exception {// TODO Auto-generated method stub}}
2.实现 WebRequestInterceptor 接口:(这个方法我没有使用;先码,方便后期学习)
WebRequestInterceptor 中也定义了三个方法,我们也是通过这三个方法来实现拦截的。这三个方法都传递了同一个参数 WebRequest ,那么这个 WebRequest 是什么呢?这个 WebRequest 是 Spring 定义的一个接口,它里面的方法定义都基本跟 HttpServletRequest 一样,在 WebRequestInterceptor 中对 WebRequest 进行的所有操作都将同步到 HttpServletRequest 中,然后在当前请求中一直传递。? ?(1 )preHandle(WebRequest request) 方法。该方法将在请求处理之前进行调用,也就是说会在 Controller 方法调用之前被调用。这个方法跟 HandlerInterceptor 中的 preHandle 是不同的,主要区别在于该方法的返回值是 void ,也就是没有返回值,所以我们一般主要用它来进行资源的准备工作,比如我们在使用 Hibernate 的时候可以在这个方法中准备一个 Hibernate 的 Session 对象,然后利用 WebRequest 的 setAttribute(name, value, scope) 把它放到 WebRequest 的属性中。这里可以说说这个 setAttribute 方法的第三个参数 scope ,该参数是一个 Integer 类型的。在 WebRequest 的父层接口 RequestAttributes 中对它定义了三个常量:? ?SCOPE_REQUEST :它的值是 0 ,代表只有在 request 中可以访问。? ?SCOPE_SESSION :它的值是 1 ,如果环境允许的话它代表的是一个局部的隔离的 session,否则就代表普通的 session,并且在该 session 范围内可以访问。? ?SCOPE_GLOBAL_SESSION :它的值是 2 ,如果环境允许的话,它代表的是一个全局共享的 session,否则就代表普通的 session,并且在该 session 范围内可以访问。? ?(2 )postHandle(WebRequest request, ModelMap model) 方法。该方法将在请求处理之后,也就是在 Controller 方法调用之后被调用,但是会在视图返回被渲染之前被调用,所以可以在这个方法里面通过改变数据模型 ModelMap 来改变数据的展示。该方法有两个参数,WebRequest 对象是用于传递整个请求数据的,比如在 preHandle 中准备的数据都可以通过 WebRequest 来传递和访问;ModelMap 就是 Controller 处理之后返回的 Model 对象,我们可以通过改变它的属性来改变返回的 Model 模型。? ?(3 )afterCompletion(WebRequest request, Exception ex) 方法。该方法会在整个请求处理完成,也就是在视图返回并被渲染之后执行。所以在该方法中可以进行资源的释放操作。而 WebRequest 参数就可以把我们在 preHandle 中准备的资源传递到这里进行释放。Exception 参数表示的是当前请求的异常对象,如果在 Controller 中抛出的异常已经被 Spring 的异常处理器给处理了的话,那么这个异常对象就是是 null 。
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.WebRequest;
《一线大厂 Java 面试真题解析+Java 核心总结学习笔记+最新全套讲解视频+实战项目源码》开源
Java 优秀开源项目:
ali1024.coding.net/public/P7/Java/git
最后
2020 年在匆匆忙忙慌慌乱乱中就这么度过了,我们迎来了新一年,互联网的发展如此之快,技术日新月异,更新迭代成为了这个时代的代名词,坚持下来的技术体系会越来越健壮,JVM 作为如今是跳槽大厂必备的技能,如果你还没掌握,更别提之后更新的新技术了。
更多 JVM 面试整理:
评论