Spring为我们提供了org.springframework.web.servlet.handler.HandlerInterceptorAdapter这个适配器,
继承此类,可以非常方便的实现自己的拦截器。他有三个方法:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception { return true; } 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 { }
分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面)
在preHandle中,可以进行编码、安全控制等处理; 在postHandle中,有机会修改ModelAndView;
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。
如果基于xml配置使用Spring MVC,可以利用SimpleUrlHandlerMapping、
BeanNameUrlHandlerMapping进行Url映射(相当于 struts的path映射)和拦截请求(注入interceptors),
如果基于注解使用Spring MVC,可以使用DefaultAnnotationHandlerMapping注入interceptors。注意无论
基于xml还是基于注 解,HandlerMapping bean都是需要在xml中配置的。
<bean id="timeBasedAccessInterceptor" class="com.spring.handler.TimeBasedAccessInterceptor"> <property name="openingTime" value="9" /> <property name="closingTime" value="12" /> <property name="mappingURL" value=".*/user\.do\?action=reg.*" /> </bean> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <ref bean="timeBasedAccessInterceptor"/> </list> </property> </bean>
这里我们定义了一个mappingURL属性,实现利用正则表达式对url进行匹配,从而更细粒度的进行拦截。当然如果不定义mappingURL,则默认拦截所有对Controller的请求。
UserController:
@Controller @RequestMapping("/user.do") 3. public class UserController{ @Autowired private UserService userService; @RequestMapping(params="action=reg") public ModelAndView reg(Users user) throws Exception { userService.addUser(user); return new ModelAndView("profile","user",user); } // other option ... }
这个Controller相当于Struts的DispatchAction
你也可以配置多个拦截器,每个拦截器进行不同的分工。
拦截器接口:
package org.springframework.web.servlet; public interface HandlerInterceptor { boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; }
preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);
返回值:true表示继续流程(如调用下一个拦截器或处理器);
false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。
//拦截器适配器 //doDispatch方法 //1、处理器拦截器的预处理(正序执行) HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); if (interceptors != null) { for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { //1.1、失败时触发afterCompletion的调用 triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); return; } interceptorIndex = i;//1.2、记录当前预处理成功的索引 } } //2、处理器适配器调用我们的处理器 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //当我们返回null或没有返回逻辑视图名时的默认视图名翻译(详解4.15.5 RequestToViewNameTranslator) if (mv != null && !mv.hasView()) { mv.setViewName(getDefaultViewName(request)); } //3、处理器拦截器的后处理(逆序) if (interceptors != null) { for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); } } //4、视图的渲染 if (mv != null && !mv.wasCleared()) { render(mv, processedRequest, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } //5、触发整个请求处理完毕回调方法afterCompletion triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); // triggerAfterCompletion方法 private void triggerAfterCompletion(HandlerExecutionChain mappedHandler, int interceptorIndex, HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception { // 5、触发整个请求处理完毕回调方法afterCompletion (逆序从1.2中的预处理成功的索引处的拦截器执行) if (mappedHandler != null) { HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); if (interceptors != null) { for (int i = interceptorIndex; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; try { interceptor.afterCompletion(request, response, mappedHandler.getHandler(), ex); } catch (Throwable ex2) { logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); } } } } } //性能监控 package cn.javass.chapter5.web.interceptor; public class StopWatchHandlerInterceptor extends HandlerInterceptorAdapter { private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-StartTime"); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { long beginTime = System.currentTimeMillis();//1、开始时间 startTimeThreadLocal.set(beginTime);//线程绑定变量(该数据只有当前请求的线程可见) return true;//继续流程 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { long endTime = System.currentTimeMillis();//2、结束时间 long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间) long consumeTime = endTime - beginTime;//3、消耗的时间 if(consumeTime > 500) {//此处认为处理时间超过500毫秒的请求为慢请求 //TODO 记录到日志文件 System.out.println( String.format("%s consume %d millis", request.getRequestURI(), consumeTime)); } } } //登录检测 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //1、请求到登录页面 放行 if(request.getServletPath().startsWith(loginUrl)) { return true; } //2、TODO 比如退出、首页等页面无需登录,即此处要放行 允许游客的请求 //3、如果用户已经登录 放行 if(request.getSession().getAttribute("username") != null) { //更好的实现方式的使用cookie return true; } //4、非法请求 即这些请求需要登录后才能访问 //重定向到登录页面 response.sendRedirect(request.getContextPath() + loginUrl); return false; }
相关推荐
在Spring Boot应用中,登录拦截器是一个至关重要的组件,它用于保护特定的Web资源,确保只有经过身份验证的用户才能访问。Spring Boot结合了Spring MVC框架,提供了方便的方式来实现这样的拦截器。本篇文章将深入...
在深入研究Flex-Spring拦截器时,理解Spring AOP的核心概念和AMF的工作原理是至关重要的。通过这样的集成,开发者可以在保持Flex客户端的灵活性和交互性的同时,利用Spring的强大功能来处理复杂的业务逻辑和系统管理...
而Spring拦截器则是实现AOP的一种方式,它类似于Java的Servlet过滤器,可以在方法调用前后执行自定义的操作。 AOP拦截器在Spring中主要通过`HandlerInterceptor`接口或者`@AspectJ`注解来实现。下面我们将详细探讨...
Spring 拦截器是 Spring 框架中一个非常重要的组件,主要用于处理请求和响应,实现业务逻辑之前和之后的预处理和后处理。它为开发者提供了在 MVC 模式下实现统一处理机制的机会,比如权限验证、日志记录、性能监控等...
在本场景中,我们探讨的是如何利用拦截器来实现登录验证功能,确保只有经过身份验证的用户才能访问受保护的资源。 首先,我们需要了解Spring MVC的拦截器工作原理。拦截器链是由多个拦截器组成,每个拦截器都有`...
我们可以通过自定义拦截器来实现特定的功能,比如权限验证、日志记录等。在Struts2的配置文件中,我们可以注册这个拦截器: ```xml ``` 然后在Action类上声明需要使用的拦截器: ```xml ...
本文将详细介绍如何在Spring Boot中实现拦截器以进行权限校验和登录验证,通过一个简单的Demo来阐述整个过程。 首先,我们需要创建一个自定义的拦截器类。这个类通常会继承`HandlerInterceptorAdapter`,这是一个...
拦截器在Spring MVC中扮演着关键的角色,它们可以用来执行一些全局性的任务,如日志记录、权限验证、性能统计等,而不必在每个控制器方法中重复编写这些代码。接下来,我们将深入理解拦截器的工作原理和创建步骤。 ...
本实验报告将探讨如何利用 SpringMVC 的拦截器(Interceptor)来实现用户登录权限验证,确保只有已登录的用户才能访问特定的受保护资源。 首先,我们来看一下实验的基本步骤: 1. 创建 `User` 类:这是表示用户...
通过运行这个项目,你可以学习如何整合Spring MVC、Spring 4以及实现登录和拦截器功能,这对你理解Web应用开发的整个流程非常有帮助。同时,这个项目也适用于快速搭建一个具有基础认证功能的Web应用,是学习和实践...
在这个"ssm+maven用拦截器实现登录小Demo"中,我们将探讨如何利用SSM框架和Maven来构建一个简单的登录系统,并通过拦截器实现权限控制。 首先,Spring MVC中的拦截器(Interceptor)是一种预处理和后处理请求的机制...
总的来说,SpringMVC拦截器是实现登录认证的强大工具,它可以与其他Spring组件无缝集成,提供灵活的控制和扩展性。通过理解其工作原理和配置方式,开发者可以更好地管理和保护Web应用程序的资源。
本项目主要关注的是如何使用过滤器(Filter)和拦截器(Interceptor)来实现登录页面的控制与跳转。以下是对这些知识点的详细说明: 1. **SpringBoot**: SpringBoot是Spring框架的一个子项目,旨在简化Spring应用...
在这个项目中,我们将重点讨论如何利用SSM框架结合Ajax和Maven,以及使用拦截器来实现登录功能。 首先,**Spring**作为核心容器,管理着应用中的bean和依赖注入,提供了AOP(面向切面编程)和事务管理等功能。在...
在Spring Boot中注册拦截器,我们需要在配置类中使用`@EnableAspectJAutoProxy`开启AOP代理,并通过`@Bean`注解声明拦截器实例。然后,使用`@Around`注解定义切点,即拦截所有的JPA操作。 在实际开发中,为了使分库...
本篇文章将详细探讨如何在Spring Boot中添加和使用拦截器来实现登录拦截。 首先,我们需要了解Spring Boot中的拦截器是如何工作的。在Spring MVC框架中,拦截器是基于AOP(面向切面编程)的概念实现的。我们可以...
总结起来,Spring Boot中的拦截器是增强应用程序功能的重要工具,通过实现或扩展拦截器接口,我们可以灵活地控制请求处理流程,实现自定义逻辑,如权限验证、日志记录等。在实际项目中,正确配置和使用拦截器能够...
在Spring Boot应用中,拦截器(Interceptor)是一个重要的组件,主要用于处理HTTP请求和响应,它在控制器(Controller)处理请求之前和之后进行拦截,可以实现如权限验证、日志记录、性能统计等功能。Spring Boot...
首先,创建自定义拦截器类并实现`HandlerInterceptor`接口是实现拦截器功能的第一步。如示例代码所示,我们需要创建一个名为`ErrorInterceptor`的类,并在其中实现`preHandle`和`postHandle`方法。这两个方法都是在...
Spring AOP 拦截器 Advisor 是 Spring 框架中的一个重要概念,它与切面编程密切相关,用于实现细粒度的控制和增强应用程序的行为。在 Spring AOP 中,Advisor 是一个组合了通知(Advice)和切入点(Pointcut)的对象...