• 过滤器和拦截器的基本知识


    过滤器和拦截器的基本知识

    前提提要,由于过滤器和拦截器的相关函数是没有返回值的,所以我们像前端返回数据时需要使用到HttpServletResponse中的相关函数,且需要配合阿里巴巴的插件fastjson将返回信息转为json格式,或者使用gson转为json

    • fastjson使用示例
    HttpServletResponse response = (HttpServletResponse) servletResponse;
    Result result = Result.error("NOT_LOGIN");
    String notLogin = JSONObject.toJSONString(result);
    response.getWriter().write(notLogin);
    
    • gson使用实例:
    private GSon gson;
    @Test
    public void testJSON()
    {
    	String json = gson.toJson(Result.success());
    	System.out.println(json);
    }
    

    一、过滤器

    过滤器是javaWeb的三大组件之一,所以我们在使用过滤器是需要在启动类添加注解@ServletComponentScan, 表明该springboot工程支持Servlet组件扫描

    package com.example;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    
    import javax.servlet.annotation.WebFilter;
    // 表明支持Servlet组件扫描
    @ServletComponentScan
    @SpringBootApplication
    public class TiliasWebManagementApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(TiliasWebManagementApplication.class, args);
        }
    
    }
    

    使用过滤器我们一般需要实现三个函数,分别是

    • init —>这个函数提供了默认实现,可以不实现
    • doFilter -->核心函数
    • destory -->同样提供了默认实现,可以不实现

    在这里插入图片描述

    1、执行流程

    在这里插入图片描述

     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 
     {
         // filterChain.doFilter之前的操作为放行前的操作,像身份验证这些需要判断的一般都是filterChain.doFilter执行前完成的
         
         //放行,即如果前面的过滤条件满足,则将请求发送给对应的执行函数进行后续操作
        filterChain.doFilter(servletRequest, servletResponse);
         
         // filterChain.doFilter之后的操作为放行后的操作
     }
    

    下面是一个登录验证的操作

        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
    
            // 获取URL
            String url = request.getRequestURI().toString();
            if (url.contains("login")) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
    
            // 获取token
            String jwt = request.getHeader("token");
            log.info("token = {}", jwt);
            // 如果token为空,但会未登录信号
            if (!StringUtils.hasLength(jwt)) {
                Result result = Result.error("NOT_LOGIN");
                String notLogin = JSONObject.toJSONString(result);
                response.getWriter().write(notLogin);
                return;
            }
            try {
                JwtUtils.parseJWT(jwt);
            } catch (Exception e) {
                e.printStackTrace();
                log.info("jwt令牌无效");
                Result result = Result.error("NOT_LOGIN");
                String notLogin = JSONObject.toJSONString(result);
                response.getWriter().write(notLogin);
                return;
            }
            //放行
            filterChain.doFilter(servletRequest, servletResponse);
        }
    

    二、拦截器

    拦截器的使用一般还需要配合一个配置类的使用,所以拦截器实现相较于过滤器略显复杂,但也相差无几

    在这里插入图片描述

    拦截器的使用一般需要添加一个配置类,该配置类需要实现WebMvcConfigurer中的addInterceptors方法

    package com.example.config;
    
    import com.example.interceptor.LoginCheckInterceptor;
    import lombok.extern.slf4j.Slf4j;
    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;
    
    /**
     * 拦截器配置类
     */
    // Configuration 设置该类为一个配置类
    @Slf4j
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Autowired
        private LoginCheckInterceptor loginCheckInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // 注册一个拦截器,拦截除了/login之外的所有请求
            registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
        }
    
    }
    

    拦截器同样有三个重要函数,实现效果跟Filter类似

    • preHandle -->放行前的操作
    • postHandle -->放行后的操作
    • afterCompletion–>最后执行的操作

    其中,拦截器更精细化的控制前端的请求

    在这里插入图片描述

    • 使用示例
    package com.example.interceptor;
    
    import com.alibaba.fastjson.JSONObject;
    import com.example.pojo.Result;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.util.StringUtils;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 拦截器处理逻辑
     */
    @Component
    public class LoginCheckInterceptor implements HandlerInterceptor {
        @Override
        // 目标资源方法前执行,true为方行,false为拦截
        // 与doFilter的fileChain前执行的方法类似
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 获取token
            String token = request.getHeader("token");
            // 如果token为空,返回未登录信号
            if(!StringUtils.hasLength(token)){
                Result error = Result.error("NOT_LOGIN");
                String notLogin = JSONObject.toJSONString(error);
                response.getWriter().write(notLogin);
                return false;
            }
            // 放行
            return true;
        }
    
        @Override
        // 目标资源方法后执行后执行
        // 与doFilter的fileChain后执行的方法类似
        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");
        }
    }
    

    需要注意的是,拦截器的放行和拦截是使用true和false来指定的,true表明放行,false表明拦截

  • 相关阅读:
    前端技术选型与探索
    GBase 8c V3.0.0数据类型——网络地址函数和操作符(macaddr函数)
    游戏滚动列表的优化(降低drawcall从154降低到14,图片大小,界面逻辑)
    CSS实现鼠标移至图片上显示遮罩层及文字效果
    面试中关于 SpringCloud 都需要了解哪些基础?
    kafka中partition数量与消费者对应关系以及Java实践(Spring 版本)
    Flutter 自定义 TextInputFormatter 文本输入过滤器 Flutter 实现输入4位自动添加空格
    高性能异步编排框架Gobrs-Async简单使用
    本周大新闻|苹果首款MR重在验证市场需求,Pico 4更多参数曝光
    spark
  • 原文地址:https://blog.csdn.net/weixin_73186358/article/details/139710389