- 拦截器的实现原理
- 自定义拦截器的实现步骤
- 拦截器原理
ssss对于拦截器的实现原理,其实是非常简单的,在前几篇文章我们已经分析了,请求映射原理最核心的方法是 doDispatch(request, response),因此我们通过 deBug 方式在doDispatch处打断点学习具体的参数处理是如何工作的,其中的核心方式有获取处理器执行器,映射器,执行目标方法,页面渲染等。 在这其中,其实还穿插着一些拦截器的相关方法执行。
自定义拦截器的实现步骤ssdsadssdas
dsdssss我们可以发现,拦截器是一个接口,一共有三个方法,我们可以重写这三个方法,对其进行自定义拦截。
dssss①、编写HandlerInterceptor接口
@Slf4j @Configuration public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestURI = request.getRequestURI(); log.info("preHandle()拦截的请求路径是()"+requestURI); //登陆检查逻辑 HttpSession session = request.getSession(); Object loginUser = session.getAttribute("loginUser"); if(loginUser!=null){ //放行 return true; } //拦截住(未登录),跳转到登录页 request.setAttribute("msg","请先登陆"); request.getRequestDispatcher("/").forward(request,response); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("postHandle执行{}",modelAndView); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("afterCompletion执行异常{}",ex); } }
dsss【注 1】:
dsdsssspreHandle():是执行目标方法前,执行该方法(通过方法的参数值也可以发现 -->request、response、handle)
dsdsssspostHandle():执行完成目标方法后,页面渲染前,有了返回的ModelAndView后,执行该方法。(参 -->request、response、handle、modelAndView)
dsdssssafterCompletion():页面渲染完后,执行该方法,其实主要是为了显示异常。(参:request、response、handler、ex)
dsss【注 2】:如果没有异常,三个方法按 [注 1] 中所写执行,但如果执行过程中出现异常,则改变执行顺序,具体在原理中讲。
dsdssss
dssss②、 配置拦截器
@Configuration public class AdminWebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") //静态所有请求都被拦截,包括静态资源 .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行的请求 } }
dssss③、拦截器执行顺序
dsdsdsdsddsss
ssss没有异常的执行流程图解:
sssadssdas
ssss代码分析:
sdsss
sds由上图我们可知,③,⑤,⑦是我们拦截器的三个方法。我们根据deBug依次看不同的方法逻辑:
sddss①、根据当前请求,找到HandlerExecutionChain【可以处理当前请求的handler以及handler的所有拦截器】
sddds
sddss②、HandlerAdapter - 为当前Handler 找一个适配器
sddss③、先来 顺序执行 所有拦截器的 preHandle方法,如果其中有失败的,则逆序执行相应的afterCompletion()方法。
sdsdssssss
sdsdssssss
dsdsss【注】:注意逆序执行afterCompletion,有一个小细节,我们用this.interceptorIndex==i++或者–i,说明只有执行完preHandle()方法的拦截器才能逆序执行响应的afterCompletion方法。执行完后,doDispatch()方法就直接return,不会执行目标方法了。
sddss④、所有拦截器都返回True。执行目标方法。
sdsd ddss
sddss⑤、 倒序执行所有拦截器的postHandle方法。
dsdssdds
dsdssdd
sddss⑥、渲染页面。
sddss⑦、页面渲染完成后也会触发所有拦截器的 afterCompletion(通过finally里的方法可以得知这一点)。
sddssdsds
sddsdsdss并且前面的步骤有任何异常都会直接倒序触发所有拦截器的 afterCompletion。
dsdsss【注】:到此doDispatch()方法就结束了,拦截器的三个方法中 afterCompletion 和 preHandle 一定执行。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)