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

发布于:2024-06-16 ⋅ 阅读:(22) ⋅ 点赞:(0)

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

前提提要,由于过滤器和拦截器的相关函数是没有返回值的,所以我们像前端返回数据时需要使用到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表明拦截