SpringBoot2.0(过滤器,监听器,拦截器)

简介: SpringBoot2.0(过滤器,监听器,拦截器)

一,过滤器

1.1,自定义Filter

使用Servlet3.0的注解进行配置

启动类里面增加 @ServletComponentScan ,进行扫描

新建一个Filter类,implements Filter ,并实现对应接口

@WebFilter 标记一个类为Filter,被spring进行扫描

urlPatterns:拦截规则,支持正则

控制chain.doFilter的方法的调用,来实现是否通过放行,

不放行的话,web应用resp.sendRedirect(“/index.html”)

场景:权限控制,用户登录(非前端后端分离场景)等

1.2,启动类代码

package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan  // 扫描select的注解
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class,args);
    }
}

1.2,创建filter类和LoginFilter包


1.2.1,编写loginFilter类 过滤器代码

package com.demo.filter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
@WebFilter(urlPatterns = {"/*"})
@Order(Ordered.HIGHEST_PRECEDENCE)    // 设置过滤器的排序,int类型
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化过滤器");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("doFilter");
//        servletResponse.setCharacterEncoding("UTF-8");
        // 设置响应的字符编码为UTF-8
        servletResponse.setCharacterEncoding("UTF-8");
        // 设置响应的内容类型为text/plain;charset=UTF-8
        servletResponse.setContentType("text/plain;charset=UTF-8");
        // 登录过滤器 有两种情况,需要放行
        // 1,登录请求要放行
        // 2. 不是登录请求,但是有登录token
        String uri = ((HttpServletRequest)servletRequest).getRequestURI();
        System.out.println(uri);
        if (uri.startsWith("/login/")){  // 判断是否以 /login/ 开头
            // 放行
            filterChain.doFilter(servletRequest,servletResponse);
        }else {
            // 从请求中获取token
            String token = ((HttpServletRequest)servletRequest).getParameter("token");
            if (token != null && !"".equals(token)){
                // 其实还需要进行解码,现在是只要有token就放行
                filterChain.doFilter(servletRequest,servletResponse);
            }else {
                PrintWriter pw = servletResponse.getWriter();
                pw.flush();
                pw.write("请先登录");
                pw.close();
            }
        }
    }
    @Override
    public void destroy() {
        System.out.println("销毁过滤器");
    }
}

1.2.2,创建二个Controller类

看看是不是以login开头的放行

第一个controller类为LoginController

package com.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/login")
public class LoginController {
    @RequestMapping("/doLogin")
    public Object doLogin(){
        return "登录接口";
    }
}

第二个controller类为HelloController

看看不是以login会不会过滤

package com.demo.controller;
import com.demo.bean.Person;
import com.demo.config.BootProperties;
import com.demo.config.SysProperties;
import com.demo.util.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.xml.crypto.Data;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.UUID;
@RestController
public class HelloController {
    @Autowired
    private BootProperties bootProperties;
    @RequestMapping("/test6")
    public Object test6(){
        return sysProperties.getParam1()+sysProperties.getParam2();
    }
}
// 整个之前的代码试试


证明过滤了,试试登录后

二,监听器

2.1,自定义监听器

  1. 自定义Listenter(常用监听器
    servletContextListenter,
    httpSessionListenter,
    HTTPSessionAttributeListenter,
    servletRequestListenter)

2.2,创建listenter包和MyListenter类

2.2.1,编写MyListenter类 监听器代码

package com.demo.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("请求被销毁");
    }
    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        System.out.println("请求被初始化创建");
    }
}

三,拦截器

3.1,创建自定义拦截器配置类

@Configuration

继承WebMvcConfigurationAdapter(SpringBoot2.X之前旧版本)

SpringBoot2.X新版本配置拦截器 implements WebMvcConfigurer

3.2,创建配置包config和配置类MyWebMvcConfigurer

package com.demo.config;
import com.demo.interceptor.Logininterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration  // 添加了Configuration的类,我们称之为配置类
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new Logininterceptor()).addPathPatterns("/login/**");
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}

3.3,创建拦截器包interceptor和Logininterceptor类

Logininterceptor类代码

package com.demo.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Logininterceptor implements HandlerInterceptor {
    // 调用Controller某个方法之前,判断是否要不要处理
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return false; // false是拦截, true是不拦截
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }
}

四,按顺序进行拦截,先注册,先被拦截

拦截器不生效的常见问题

  1. 是否有加@Configuration
  2. 拦截器是否有路径问题 ** 和 *
  3. 拦截器最后路径一定要 " /** " ,如果是目录的话则是 /*/

Filter

是基于函数回调 doFilter(),而lnterceptor则是基于AOP思想

Filter在只在Servlet前后起作用,而lnterceptor够深入到方法前后,异常抛出前后等


依赖于Servlet容器即web应用中,而lnterceptor不依赖于Servlet容器所以可以运行在多种环境。


在接口调用的声明周期里,lnterceptor可以被多次调用,而Filter只能在容器中初始化调用一次。


Filter和lnterceptor的执行顺序

过滤前 --> 拦截前 --> action(handler) --> 执行 --> 拦截后 --> 过滤后


相关文章
|
1月前
|
Java Spring 容器
【二十二】springboot整合拦截器实战并对比过滤器
【二十二】springboot整合拦截器实战并对比过滤器
33 0
|
2月前
|
安全 Java Spring
SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)
SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)
47 0
|
4月前
|
Java 数据库
SpringBoot中如何在过滤器中取get的参数值
SpringBoot中如何在过滤器中取get的参数值
70 0
|
3月前
|
Java 容器
SpringBoot3 事件和监听器
SpringBoot3 事件和监听器
|
1月前
|
存储 前端开发 NoSQL
【二十一】springboot整合过滤器实战
【二十一】springboot整合过滤器实战
15 0
|
7月前
|
JSON 安全 Java
Spring Boot中的安全过滤器及使用方法
Spring Boot中的安全过滤器及使用方法
|
3月前
|
NoSQL Java Redis
SpringBoot-自定义监听器
本文讲解如何在Spring Boot创建自定义监听器
38 0
SpringBoot-自定义监听器
|
4月前
|
前端开发 JavaScript Java
Spring Boot中Spring MVC的基本配置讲解与实战(包括静态资源配置,拦截器配置,文件上传配置及实战 附源码)
Spring Boot中Spring MVC的基本配置讲解与实战(包括静态资源配置,拦截器配置,文件上传配置及实战 附源码)
53 1
|
4月前
|
存储 Java
SpringBoot中过滤器如何设置执行顺序
SpringBoot中过滤器如何设置执行顺序
119 0
|
4月前
|
Java
SpringBoot中如何在过滤器中取post的参数值
SpringBoot中如何在过滤器中取post的参数值
79 0