拦截器
- 拦截器(interceptor)是springmvc中的一个组件,是运行在DispatcherServlet之后,运行在Controller之前的
- 拦截器可以决定对某些符合条件的进行拦截或者放行,所以,通常用于对一些具有相同运行条件的功能进行约束
Spring 中的拦截器用于拦截控制器方法的执行1
拦截器需要实现HandlerInterceptor
拦截器必须在SpringMVC的配置文件中配置:
<!-- 图片解析器--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean> <bean class="com.atguigu.interceptor.FirstInterceptor"></bean> <ref bean="firstInterceptor"></ref> <!-- 以上两种配置方式都是对DispatcherServlet所处理的所有的请求进行拦截 --> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/testRequestEntity"/> <ref bean="firstInterceptor"></ref> </mvc:interceptor> <!--
以上配置方式可以通过ref或bean标签设置拦截器,通过mvc:mapping设置需要拦截的请求,通过
mvc:exclude-mapping设置需要排除的请求,即不需要拦截的请求
-->
拦截器的三个抽象方法
- preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,中断处理流程,即不调用控制器方法,不执行后序的内容
- postHandle:控制器方法执行之后执行postHandle()
- afterCompletion:处理完视图和模型数据,渲染视图完毕之后执行afterCompletion()
多个拦截器的执行顺序
①若每个拦截器的preHandle()都返回true
此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:
preHandle()会按照配置的顺序执行,而postHandle()和afterCompletion()会按照配置的反序执行
②若某个拦截器的preHandle()返回了false
preHandle()返回false和它之前的拦截器的preHandle() 都会执行,postHandle()都不执行,返回false 的拦截器之前的拦截器的afterCompletion()会执行
演示实例—登录检查
public class LoginInterceptor implements HandlerInterceptor{ /* * 在处理器执行之前调用(non-Javadoc) * 1. 获取session * 2. 读取session中的uid的值 * 如果为null,表示没有登录,那么直接重定向到登录界面,同时返回false,不需要执行后面的流程了 * 如果不为null,表示已经登录了,那么直接返回true,继续执行后面的拦截器或者处理器 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session=request.getSession(); //获取session Object uid=session.getAttribute("uid"); //读取session中的对象 //如果uid存在,那么即可登录完成 if (uid!=null) { return true; //返回true,登录成功就需要执行后续的流程 } response.sendRedirect(request.getContextPath()+"/user/login.do"); //重定向到登录界面 return false; //返回false,后面的流程也不用执行了,直接中断 } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
拦截器和过滤器的区别(主要的区别)
- 拦截器是springmvc中,仅仅当使用springmvc才可以使用拦截器,过滤器是Java EE体系中的,无论使用哪种框架都可以使用过滤器
- 拦截器在DispatcherServlet之后,在处理器之前执行,过滤器在DispatcherServlet之前执行
- 过滤器会在所有的servlet之前执行(所有的请求都会执行),而拦截器会在springmvc中DispatcherServlet之后执行,所以过滤器在项目中可以过滤任何请求(只要是配置了对应的路径),而拦截器只会在DispatcherServlet处理的请求的基础之上进行拦截
总结
- 当多种请求都需要做相同或者极为相似的任务时,可以使用拦截器
- 开发好拦截器,那么需要在springmvc的配置文件中配置
- 在mvc:interceptors可以有如果若干个mvc:interceptor,即是配置若干个拦截器,配置的多个拦截器将会形成拦截器链,如果配置多个拦截器对同一个路径都会拦截,那么会按照配置的节点顺序执行。
异常处理的组件
如果报错就会直接跳转至该异常处理的组件
SpringMVC的各个组件及其执行流程
SpringMVC的常用组件
- DispatcherServlet:前端控制器,不需要工程师开发,由框架提供 作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求
- HandlerMapping:处理器映射器,不需要工程师开发,由框架提供 作用:根据请求的url、method等信息查找Handler,即控制器方法
- Handler:处理器,需要工程师开发 作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理
- HandlerAdapter:处理器适配器,不需要工程师开发,由框架提供 作用:通过HandlerAdapter对处理器(控制器方法)进行执行
- ViewResolver:视图解析器,不需要工程师开发,由框架提供 作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、 RedirectView
- View:视图 作用:将模型数据通过页面展示给用户
SpringMVC执行流程
- 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获。
- DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI),判断请求URI对应的映射:
2.1. 不存在
再判断是否配置了mvc:default-servlet-handler
如果没配置,则控制台报映射查找不到,客户端展示404错误
如果有配置,则访问目标资源(一般为静态资源,如:JS,CSS,HTML),找不到客户端也会展示404错误
2.2. 存在则执行以下流程
根据该URI,调用HandlerMappingrequestmapping进行匹配 获得该Handler配置的所有相关的对象(包括Handler对象以及 Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。
DispatcherServlet 根据获得的Handler(控制器方法),选择一个合适的HandlerAdapter。
如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法【正向】
提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。
此时将开始执行拦截器的postHandle(...)方法【逆向】。
根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行 HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model 和View,来渲染视图。
渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。
将渲染结果返回给客户端。