Day 22 - Spring Boot & Interceptor

Interceptor 拦截器

在许多的Java Web 框架都有实现Interceptor 的方法,例如Struct2 是Interceptor就是Spring MVC 就是HandlerInterceptor,而Interceptor 介於DispatcherServlet 与Controller 之间,可以在请求到达Controller 前或回应回传出Controller 时进行拦截,拦截成功一样可以实作一些自定义的业务逻辑或对回应资料进行修改。

实作

建立一个IndexInterceptor

建立Interceptor 的常见方法一样有两种,一种是实作org.springframework.web.servlet.HandlerInterceptor 介面,另一种则是继承org.springframework.web.servlet.handler.HandlerInterceptorAdapter 类别,不管是哪种方法都要覆写三个方法。

  1. preHandle(...) : 该方法是在请求进入Controller 之前执行,用来进行一些初始化或预处理,也可以判断是否继续执行下去。
    该方法返回值为Boolean 值,返回false 表示请求结束,後续Interceptor 和Controller 均不会执行,而返回true 表示请求继续,会继续调用下一个Interceptor 或是Controller。

  2. postHandle(...) : 该方法是Controller 之後执行的方法,会在DispatcherServlet 进行视图渲染以前被调用,所以可以在这个方法中队Controller 处理之後的ModelAndView 物件进行操作。

  3. afterCompletion(...) : 该方法是在整个请求结束之後,在DispatcherServlet 对视图渲染完成後执行,主要进行资源清理。

package com.example.iThomeIronMan.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.example.iThomeIronMan.controller.LoginRegisterController;
import com.example.iThomeIronMan.model.Member;

@Component
public class IndexInterceptor implements HandlerInterceptor {

	private static final Logger logger = LoggerFactory.getLogger(LoginRegisterController.class);
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// TODO Auto-generated method stub

		String uri = new String(request.getRequestURI());
				
		HttpSession session = request.getSession();
		Member member = (Member) session.getAttribute("MemberSession");

		// 已登入
		if(member != null) {
			logger.info(member.getName() + " 访问 " + uri);
			return true;
		}
		// 未登入
		else {
			return false;
		}
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
	}

}

设定拦截器及其拦截路径

最後设定拦截器使用InterceptorRegistry 的三个方法。

  1. addInterceptor() : 注册拦截器。
  2. addPathPatterns() : 新增拦截路径。
  3. excludePathPatterns() : 新增不拦截路径。
package com.example.iThomeIronMan.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.example.iThomeIronMan.interceptor.IndexInterceptor;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

	@Autowired
	private IndexInterceptor indexInterceptor;
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// TODO Auto-generated method stub
		
		registry.addInterceptor(indexInterceptor)
						.addPathPatterns("/information/**", "/updatePassword/**")
						.excludePathPatterns("/login/**", "/register/**", "/css/**", "/images/**", "/js/**");
	}

}

Filter vs. Interceptor

https://ithelp.ithome.com.tw/upload/images/20211006/20140728RrzXyCCKFw.png
我们可以根据上面的介绍画出上面这个流程图,Filter 的作用区间在请求到达Servlet 之前,Interceptor 在Dsipatcher Servlet 接收请求之後在交由Controller 之前;Filter 面对的是请求而Interceptor 面对的是Controller,两者的主要应用场景与功能几乎类似,例如登入认证、Session 检查和处理等等,而主要的差异就是越早的过滤或拦截对系统性能的消耗越少,在应用上就要由开发人员根据实际业务情况综合考虑了。

参考网站

HandlerInterceptors vs. Filters in Spring MVC
Spring Boot之Filter和Interceptor的对比分析


<<:  [Day 24] Facial Landmark: MTCNN

>>:  口罩脸孔资料集的上传

每日挑战,从Javascript面试题目了解一些你可能忽略的概念 - Day17

tags: ItIron2021 Javascript 前言 前两天这样搞下来,相信你们对this已...

NoSQL的格式(一)

再来检核DynamoDB的资料, 比较与SQL的不同 回到DynamoDB Portal, 点选第一...

Day 2 - API 文件导览、 Postman 测试取得 Nonce

在进行串接前,首先需要有定义串接的规格,例如:串接的协定 (HTTP、或走 FTP 档案交换等等)、...

如何提高CDN缓存命中率?

CDN缓存命中率低的可能原因如下: HTTP Header设置不当导致无法缓存,请检查源站Cache...

Day 06 CSS <复合选择器>

CSS的选择器分为基础选择器以及复合选择器 本日将将继续说明复合选择器 复合选择器可以更准确更高效的...