SpringMVC拦截器Interceptor
SpringMVC拦截器(Interceptor)实现对每一个请求处理前后进行相关的业务处理,类似与servlet中的Filter。
SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor来实现的。
在SpringMVC中定义一个Interceptor非常简单,主要有4种方式:
1)实现Spring的HandlerInterceptor接口;
2)继承实现了HandlerInterceptor接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter;
3)实现Spring的WebRequestInterceptor接口;
4)继承实现了WebRequestInterceptor的类;
实现了拦截器之后,我们可以通过重写WebMvcConfigurerAdapter的addInterceptors方法来注册自己的拦截器。
我们这里只通过实现HandlerInterceptor接口的方式给出实例。实例中使用拦截器实现两个功能
1)计算每一次请求的处理时间
2)并对特定时间和特定用户(数据在codis中)的请求进行拒绝
1、HandlerInterceptor接口
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
),继承该抽象类后可以仅仅实现其中的一个方法。
2、实现拦截器
package com.xiaoju.dqa.sentinel.monitor.interceptor;
import com.xiaoju.dqa.sentinel.common.client.redis.CodisClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Calendar;
import java.util.Set;
public class AuthInterceptor implements HandlerInterceptor {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private CodisClient codisClient;
/*
* 视图函数执行成功后执行
* */
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
/*
* 在视图函数之后执行
* 本函数的作用:计算处理时间
* */
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
long startTime = (Long) request.getAttribute("startTime");
request.removeAttribute("startTime");
logger.info("处理时间: {}", System.currentTimeMillis() - startTime);
}
/*
* 在视图函数之前执行
* 返回true, 继续执行视图函数
* 返回false, 终止请求流程
* 本函数的作用,:拒绝特定时间sentinel:forbidden:hours; 特定用户的sentinel:forbidden:users请求, 并记录startTime
* */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
boolean going = true;
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
Calendar ca = Calendar.getInstance();
String currentHour = String.valueOf(ca.get(Calendar.HOUR_OF_DAY));
try {
boolean isForbidHour = codisClient.sismember("sentinel:forbidden:hours", currentHour);
if (isForbidHour) {
Set<String> forbiddenUsers = codisClient.smembers("sentinel:forbidden:users");
if (forbiddenUsers != null) {
for (Cookie cookie : request.getCookies()) {
if("username".equals(cookie.getName()) && forbiddenUsers.contains(cookie.getValue())) {
logger.info("[拦截器] 禁止访问. 时间:{}, 用户:{}", currentHour, cookie.getValue());
going = false;
}
}
}
}
} catch (Exception e) {
logger.info("[拦截器] 有问题", e);
}
return going;
}
}
3、注册拦截器
这里预先生成了@bean - authInterceptor是为了让AuthInterceptor类中的codisClient的注入成功,否则即使自动注入了codisClient也无法注入成功。
package com.xiaoju.dqa.sentinel.configuration;
import com.xiaoju.dqa.sentinel.monitor.interceptor.AuthInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebInterceptorConfig extends WebMvcConfigurerAdapter {
@Bean
public AuthInterceptor authInterceptor() {
return new AuthInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则
// excludePathPatterns 用户排除拦截
registry.addInterceptor(authInterceptor()).addPathPatterns("/**").excludePathPatterns("/sentinel/monitor/**");
super.addInterceptors(registry);
}
}
- rman数据备份恢复学习笔记(49天)
- 虚拟专用数据库VPD应用 (48天)
- 关于创建视图的问题(48天)
- 性能调优之redo切换频率(47天)
- 关于oracle中session跟踪的总结(56天)
- oracle中关于小数中0的格式化(55天)
- 关于trigger过滤最大值的问题(54天)
- oracle共享服务器配置汇总(53天)
- 关于drop user的cascade选项解惑(52天)
- ORACLE数据文件名导致的奇怪问题 (51天)
- linux下挂载新硬盘和分区的步骤 (50天)
- 通过shell脚本生成数据统计信息的报表 (笔记65天)
- 物化视图全量刷新的简单测试(63天)
- Golang语言社区--Go操作CSV文件
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- OpenVPN原理及部署使用
- 04 . Jenkins部署Java项目
- java编程思想第四版第七章习题
- 03 . Jenkins构建之代码扫描
- mysql提示Packet for query is too large (1142 > 1024)解决方案
- Kubernetes 1.19.0——deployment(1)
- 02 . Jeknins简介部署及自动化部署PHP代码
- java编程思想第四版第八章习题
- java编程思想第四版第八章总结
- ESP32从网络获取天气OLED显示(附源码)
- 02 . Zabbix配置监控项及聚合图形
- 01 . GitLab简介及环境部署
- 03 . Prometheus监控容器和HTTP探针应用及服务发现
- java编程思想第四版第九章习题
- 03 . Django之腾讯云短信