springBoot 2.x过滤器--监听器--拦截器

springboot 2.x过滤器

1.什么是 springboot 2.x过滤器

  • 类似于检票员,检验游客的门票

2.springboot里的过滤器

ApplicationContextHeaderFilter
OrderedCharacterEncodingFilter
OrderedFormContentFilter
OrderedRequestContextFilter

3.过滤器的优先级

  • 低位值意味着更⾼的优先级 Higher values are interpreted as lower priority

4.自定义Filter,避免和默认的Filter优先级一样,不然会冲突

  • 注册Filter配置俩种方式
    • bean FilterRegistrationBean
    • Servlet 3.0 webFilter

5.使用新版servlet 3.0的注解开发自定义Filter

  • 在启动类里添加注解@ServletComponentScan ,进行扫描
  • 新建一个Filter类,implements Filter,并实现对应的接口
  • @WebFilter 标记一个类为filter,被spring扫描
  • urlPatterns:拦截规则,支持正则, urlPatterns为过滤的路径,filterName为过滤器的名称
  • 控制chain.doFilter的方法调用,来实现是否放行
  • 不放行,web应用resp.sendRedirect("/index.html")或者返回json字符串

使用范围:权限控制、⽤户登录状态控制

5.1 启动类里添加注解@ServletComponentScan

@SpringBootApplication     //标记此类为springboot 应用
@ServletComponentScan
public class MavenDemoApplication {
    
    
	public static void main(String[] args) {
    
    
		SpringApplication.run(MavenDemoApplication.class, args);
	}
}

5.2新建一个filter 包,包里创建一个Filter类

在这里插入图片描述

5.3类里实现Filter接口,并且类被标注为 @WebFilter, urlPatterns为过滤的路径(过滤/api/v1/pri/ 下所有的路径),filterName为过滤器的名称(登录过滤器)

在这里插入图片描述

5.4 在实现接口的类里重写3个方法

public void init(FilterConfig filterConfig) throws ServletException {}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {}

public void destroy() {}

上述三个方法均在类加载时使用,初始化–过滤–销毁,过滤的过程发生在第二个过滤的时候
过滤过程中的代码:

@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("过滤开始");
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse rep = (HttpServletResponse) servletResponse;

        String token =req.getHeader("token");   //从headers中得到token
        if (StringUtils.isEmpty(token)){
    
               // 如果header里面没有token时,从请求的参数里面拿token
            token = req.getParameter("token");
        }
        if (!StringUtils.isEmpty(token)){
    
                //如果还为空,直接返回json字符串或跳转index页面
            // 判断token是否合法
            User user = UserServiceImpl.sessionMap.get(token);  //在登录时在sessionMap里存了token,通过token取出user,若为空则未登录,若不为空则显示正确
            if(user !=null){
    
    
                filterChain.doFilter(servletRequest,servletResponse);
            }else{
    
    
                JsonData jsonData = JsonData.buildError("登录失败,token无效",-2);
                String jsonStr = objectMapper.writeValueAsString(jsonData);         //json转字符
                renderJson(rep,jsonStr);
            }
        }else {
    
    
            JsonData jsonData = JsonData.buildError("登录失败,token无效",-3);
            String jsonStr = objectMapper.writeValueAsString(jsonData);    
            renderJson(rep,jsonStr);
        }
    }
    private void renderJson(HttpServletResponse response,String json){
    
    
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        try(PrintWriter writer=response.getWriter()){
    
    
            writer.print(json);
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }

在这里插入图片描述

springboot监听器

监听器:

应⽤启动监听器,会话监听器,请求监听器

作用:

  • ServletContextListener 应⽤启动监听
  • HttpSessionLisener 会话监听
  • ServletRequestListener 请求监听

常⽤的监听器

ServletContextListener、HttpSessionListener、ServletRequestListener)

代码:

@WebListener
public class CustomSessionListener implements HttpSessionListener {
    
    
    @Override
    public void sessionCreated(HttpSessionEvent se) {
    
    
        System.out.println("会话监听已开启");
        //HttpSessionListener.super.sessionCreated(se);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
    
    
        System.out.println("会话监听已销毁");
        //HttpSessionListener.super.sessionDestroyed(se);
    }
}

SpringBoot2.X拦截器

1. 拦截器:

和过滤器⽤途基本类似

2.SpringBoot2.X拦截器使用步骤:

  • 2.1 创建一个类(列如:CustomWebConfigurer类)实现WebMvcConfigurer接口 拦截器配置类
  • 2.2 在类上加注解@COnfiguration
  • 2.3 在类里override 重写addInterceptors这个方法,在方法里可添加自定义的多个拦截器
  • 2.4 自定义拦截器
    • preHandle:调⽤Controller某个⽅法之前
    • postHandle:Controller之后调⽤,视图渲染之前,如果控制器Controller出现了
      异常,则不会执⾏此⽅法
    • afterCompletion:不管有没有异常,这个afterCompletion都会被调⽤,⽤于资
      源清理

拦截器的配置类 代码:

/**
 * 拦截器配置类
 */
@Configuration
public class CustomWebConfigurer implements WebMvcConfigurer {
    
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        registry.addInterceptor(getLoginInterceptor()).addPathPatterns("/api/v1/pri/**");
        //可添加多个拦截器
        registry.addInterceptor(new TwoLoginIntercepter()).addPathPatterns("/api/v1/pri/**");

        WebMvcConfigurer.super.addInterceptors(registry);
    }
    @Bean
    public LoginIntercepter getLoginInterceptor(){
    
    
        return new LoginIntercepter();
    }
}

拦截器实现类代码:

public class LoginIntercepter implements HandlerInterceptor {
    
    
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        System.out.println("LoginIntercepter preHandle...");

        String token =request.getHeader("token");   //从headers中得到token
        if (StringUtils.isEmpty(token)){
    
    
            token = request.getParameter("token");
        }
        if (!StringUtils.isEmpty(token)){
    
    
            // 判断token是否合法
            User user = UserServiceImpl.sessionMap.get(token);
            if(user !=null){
    
    
                return true;
            }else{
    
    
                JsonData jsonData = JsonData.buildError("登录失败,token无效",-2);
                String jsonStr = objectMapper.writeValueAsString(jsonData);
                renderJson(response,jsonStr);
                return false;
            }
        }else {
    
    
            JsonData jsonData =JsonData.buildError("未登录",-3);
            String jsonStr = objectMapper.writeValueAsString(jsonData);
            renderJson(response,jsonStr);
            return false;
        }
        //return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    private void renderJson(HttpServletResponse response,String json){
    
    
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        try(PrintWriter writer=response.getWriter()){
    
    
            writer.print(json);
        }catch (Exception e){
    
    
            e.printStackTrace();
        }

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
    
        System.out.println("LoginIntercepter postHandle...");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
    
        System.out.println("LoginIntercepter afterCompletion...");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

拦截器不生效的常见问题:

  • 是否有加@Configuration
  • 拦截路径是否有问题 ** 和 *
  • 拦截器最后路径⼀定要 /** 如果是⽬录的话则是 /*/

和Filter过滤器的区别

  • Filter和Interceptor⼆者都是AOP编程思想的体现,功能基本都可以实现
  • 拦截器功能更强⼤些,Filter能做的事情它都能做
  • Filter在只在Servlet前后起作⽤,⽽Interceptor够深⼊到⽅法前后、异常抛出前后等
  • filter依赖于Servlet容器即web应⽤中,⽽Interceptor不依赖于Servlet容器所以可以运⾏在
    多种环境。
  • 在接⼝调⽤的⽣命周期⾥,Interceptor可以被多次调⽤,⽽Filter只能在容器初始化时调⽤⼀
    次。
  • Filter和Interceptor的执⾏顺序 过滤前->拦截前->action执⾏->拦截后->过滤后

如何配置不拦截某些路径?

registry.addInterceptor(new
LoginIntercepter()).addPathPatterns("/api/v1/pri/**")

//配置不拦截某些路径,⽐如静态资源
.excludePathPatterns("//*.html","//*.js");

猜你喜欢

转载自blog.csdn.net/m0_49969111/article/details/118726066
今日推荐