Spring MVC拦截器
来源:互联网 发布:希拉里女儿 知乎 编辑:程序博客网 时间:2024/05/29 19:16
Spring WebMvc框架中的Interceptor,与Servlet API中的Filter十分类似,用于对Web请求进行预处理/后处理。通常情况下这些预处理/后处理逻辑是通用的,可以被应用于所有或多个Web请求,例如:
- 记录Web请求相关日志,可以用于做一些信息监控、统计、分析
- 检查Web请求访问权限,例如发现用户没有登录后,重定向到登录页面
- 打开/关闭数据库连接——预处理时打开,后处理关闭,可以避免在所有业务方法中都编写类似代码,也不会忘记关闭数据库连接
Spring MVC请求处理流程
上图是Spring MVC框架处理Web请求的基本流程,请求会经过DispatcherServlet
的分发后,会按顺序经过一系列的Interceptor
并执行其中的预处理方法,在请求返回时同样会执行其中的后处理方法。
HandlerInterceptor接口
Spring MVC中拦截器是实现了HandlerInterceptor
接口的Bean:
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()
:预处理回调方法,若方法返回值为true,请求继续(调用下一个拦截器或处理器方法);若方法返回值为false,请求处理流程中断,不会继续调用其他的拦截器或处理器方法,此时需要通过response产生响应;postHandle()
:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时可以通过modelAndView对模型数据进行处理或对视图进行处理afterCompletion()
:整个请求处理完毕回调方法,即在视图渲染完毕时调用
HandlerInterceptor
有三个方法需要实现,但大部分时候可能只需要实现其中的一个方法,HandlerInterceptorAdapter
是一个实现了HandlerInterceptor
的抽象类,它的三个实现方法都为空实现(或者返回true
),继承该抽象类后可以仅仅实现其中的一个方法:
public class Interceptor extends HandlerInterceptorAdapter { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("This is interceptor."); return true; }}
配置Interceptor
定义HandlerInterceptor
后,需要在MVC配置中将它们应用于特定的URL中,下面是一个配置的例子:
@Configuration@EnableWebMvcpublic class WebConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LocaleInterceptor()); registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**"); registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*"); }}
对应的XML配置是:
<mvc:interceptors> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" /> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/admin/**"/> <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/secure/*"/> <bean class="org.example.SecurityInterceptor" /> </mvc:interceptor></mvc:interceptors>
实例:用户登录检查
根据前面几个小节的学习,现在需要实现用户登录检查——如果发现用户没有登录,跳转到登录页面,登录成功后跳转回之前访问的页面。
Interceptor实现检查逻辑
public class LoginInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getSession().getAttribute(Constants.USER_SESSION_ATTR) != null) { return true; } response.sendRedirect("/login?next=".concat(request.getRequestURI())); return false; }}
为了实现跳转登录页面登录成功后能够返回当前页面,在Interceptor
中将当前URL作为/login
的参数next
LoginController
@Controller@RequestMapping("/login")public class LoginController { public static final Logger logger = LoggerFactory.getLogger(LoginController.class); @RequestMapping(method = RequestMethod.GET) public String loginPage(@RequestParam("next") Optional<String> next) { logger.info("next = {}", next); return "login"; } @RequestMapping(method = RequestMethod.POST) public String login(@RequestParam("next") Optional<String> next, HttpSession session) { logger.info("next = {}", next); session.setAttribute(Constants.USER_SESSION_ATTR, "username"); return "redirect:".concat(next.orElse("/")); }}
在登录的POST方法中,除了将Session中放入user对象外,跳转到next
以便回到登录前的页面。
配置Interceptor
需要注意的是,登录页面本身(包括POST请求)不能应用Interceptor来拦截,否则会陷入无限循环中:
@Configurationpublic class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/login"); }}
更多Spring MVC的内容请大家参考Spring MVC实战入门训练。
进一步阅读
Spring MVC实战入门训练
Spring MVC快速入门
Spring MVC DispatcherServlet详解
基于Spring MVC的 Websocket在线聊天室
整合Spring Data JPA与Spring MVC: 分页和排序
整合Spring Data JPA与Spring MVC:使用@Query标注自定义查询语句
基于Spring和Spring MVC实现可跨域访问的REST服务
Spring MVC中使用Thymeleaf模板引擎
要获取本文的参考代码,请访问: https://www.tianmaying.com/tutorial/spring-mvc-interceptor/repo
from: https://www.tianmaying.com/tutorial/spring-mvc-interceptor
- Spring MVC 拦截器
- Spring MVC 拦截器
- Spring MVC 拦截器
- spring MVC拦截器
- Spring MVC拦截器
- spring mvc 拦截器
- spring mvc 拦截器
- spring mvc 拦截器
- Spring mvc 拦截器
- spring mvc 拦截器
- spring mvc 拦截器
- spring mvc 拦截器
- Spring MVC 拦截器
- spring mvc拦截器
- spring mvc拦截器
- spring mvc拦截器
- spring mvc拦截器
- spring mvc 拦截器
- jdk动态代理实现原理
- DOM文档对象模型
- Web开发技术发展历史
- 热修复Tinker简单使用
- node.js上传图片小结
- Spring MVC拦截器
- #和##的区别
- 受限与定向广播
- 两个无序数组分别叫A和B,长度分别是m和n,求中位数,要求时间复杂度O(m+n),空间复杂度O(1) 。
- 问题四:C++中inline是干嘛用的
- CSS的表白:七夕巧克力心
- ss
- win10 SDK 安装错误 :unable to verify the integrity
- day_05