博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【学习笔记】springboot的过滤器与拦截器的使用 springboot的事件驱动模型
阅读量:3905 次
发布时间:2019-05-23

本文共 4372 字,大约阅读时间需要 14 分钟。

文章目录


过滤器

在实际的开发过程中,可能会遇到这样一类需求:统计在线用户、敏感词过滤或者基于URL进行访问控制。这些需求有一个共同点——在每个接口被请求时都需要进行该类操作。换而言之,如果编写了对应以上需求的代码,在每一个接口的某处都需要对这些代码进行调用。不使用一些技巧的话,这个开发过程会变得异常烦琐。

Filter(过滤器)这一概念来源于“Servlet规范”,具体的功能实现由Servlet容器(即Spring Boot内容的Tomcat)提供。过滤器的主要职责在于对资源的请求与响应的过滤,对从客户端向服务端发送的请求进行过滤,也可以对服务端返回的响应进行处理。Filter与Servlet是有区别的。Filter虽然可以对请求与响应做出处理,但其本身并不可以产生响应。

使用过滤器实现访问控制

(1)创建一个需要实施访问控制的控制器。

一个简单的例子:
在路径src/main/java/com/example/myb-log/controller下创建SecretController.java:

@RequestMapping("/secret")@RestControllerpublic class SecretController {
@GetMapping public String secret() {
return "secret"; }}

(2)创建用于身份认证的控制器。如果通过了认证,控制器将在Cookie中写入作为身份凭证的内容。

在controller路径下创建SessionController.java:

@RestController@RequestMapping("/session")public class SessionController {
@PostMapping public String login(@RequestBody SessionQuery sessionQuery, HttpServletResponse response) {
if (authenticate(sessionQuery)) {
certificate(response); return "success"; } //登陆失败返回错误 return "failed"; } private boolean authenticate(SessionQuery sessionQuery) {
//简单的验证逻辑,仅作演示 return Objects.equals(sessionQuery.getUsername(), "admin") && Objects.equals(sessionQuery.getPassword(), "password"); } private void certificate(HttpServletResponse response) {
//将登陆凭证以cookie的形式返回给客户端 Cookie credential = new Cookie("sessionId", "test-token"); response.addCookie(credential); }}

(3)创建用于检查凭证的过滤器。过滤器通过检查请求中附带的Cookie内容,以确认用户的身份。

创建SessionFilter.java:

@Slf4j@WebFilter(urlPatterns = "/secret/*")public class SessionFilter implements Filter {
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//读取Cookie Cookie[] cookies = Optional.ofNullable(((HttpServletRequest) servletRequest).getCookies()) .orElse(new Cookie[0]); boolean unauthorized = true; for (Cookie cookie : cookies) {
if ("sessionId".equals(cookie.getName()) && "test-token".equals(cookie.getValue())) {
unauthorized = false; } } if (unauthorized) {
log.error("UNAUTHORIZED"); unauthorizedResp(servletResponse); }else {
filterChain.doFilter(servletRequest, servletResponse); } } private void unauthorizedResp(ServletResponse response) throws IOException {
HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); httpResponse.setHeader("Content-type", "text/html;charset=UTF-8"); httpResponse.setCharacterEncoding("UTF-8"); httpResponse.getWriter().write("UNAUTHORIZED"); }}

(4)启用过滤器。需要在主类中使用@ServletComponentScan注解,以启用被注解@WebFilter修饰的过滤器。

(5)分别在请求登录接口前后访问“受保护”的路径,以确认访问控制是否生效。

拦截器

Interceptor(拦截器)这一功能由Spring提供。Interceptor与Filter类似,操作粒度更小,但整体功能不如Filter强大。Interceptor支持自定义预处理(preHandle)可以在此过程中决定是否禁止程序继续进行,自定义后续处理(postHandle)。 使用拦截器的前提是需要实现HandlerInterceptor接口。该接口包含三种主要方法: ·

 preHandle():在执行实际的处理程序之前调用,但尚未生成视图。 · 
 postHandle():处理程序执行后调用。 · 
 afterC ompletion():在请求已经响应并且视图生成完毕之后调用。
使用步骤:
首先创建一个继承HandlerInterceptorAdapter的拦截器类,使用日志打印请求中的参数。在路径src/main/java/com/example/myblog/interceptor下创建LogRequestInterceptor.java:
然后将拦截器配置到Spring上下文。在路径src/main/java/com/example/myblog/config下创建InterceptorConfig.java:

@Configuration@RequiredArgsConstructorpublic class InterceptorConfig implements WebMvcConfigurer {
private final LogRequestInterceptor logRequestInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(logRequestInterceptor).addPathPatterns("/**"); }}

事件驱动模型

默认情况下,事件的发布与监听是同步执行的。当要用到异步事件时,需要进行额外的配置。具体方式在于创建ApplicationEventMulticaster的JavaBean。在路径src/main/java/com/example/myblog/config下创建AsynchronousEventsConfig.java:

@Configurationpublic class AsynchronousEventsConfig {
@Bean(name = "applicationEventMulticaster") public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster(); eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor()); return eventMulticaster; }}

转载地址:http://oxten.baihongyu.com/

你可能感兴趣的文章
linux kernel中epoll的设计和实现
查看>>
linux:网络栈内存不足引发进程挂起问题
查看>>
linux:用systemtap来修改下linux内核变量的值
查看>>
linux:systemtap观察page_cache的使用情况
查看>>
linux:dropwatch 网络协议栈丢包检查利器
查看>>
Linux IO协议栈框图
查看>>
linux 内核编程之proc虚拟文件系统
查看>>
Linux学习】epoll详解
查看>>
Linux open系统调用流程
查看>>
Linux 2.6.35 新增特性 RPS RFS [复制链接]
查看>>
使用gdb调试linux内核
查看>>
使用systemtap调试linux内核
查看>>
SystemTap Beginner
查看>>
深入分析 Linux 内核链表
查看>>
qperf测量网络带宽和延迟
查看>>
linux kernel笔记——中断
查看>>
linux 内核tcp接收数据的实现
查看>>
gcc 生成 .a静态库和 .so动态库
查看>>
三张图看遍Linux 性能监控、测试、优化工具
查看>>
100个常用的linux命令
查看>>