统一拦截--过滤器Filter

1.过滤器Filter

1. 概述

  • 概念: Filter过滤器,是JavaWeb三大组件(Servlet、Filter、Listener)之一。
  • 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能
  • 过滤器一般完成一些通用的操作,比如:登录校验统一编码处理敏感字符处理等。

2. Filter的快速入门

  • 1.定义Filter:定义一个类,实现Filter接口,并重写其所有方法。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/*")  //这是JavaWeb中的组件,springboot中没有,还需要在启动类上加上@ServletComponentScan注解
public class demoFilter implements Filter {

    @Override  //初始化、只调用一次 项目启动自动调用
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init初始化方法");
    }

    @Override   
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("拦截到了请求");

        //拦截放行,在路径资源访问之后
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override  //销毁方法,也只调用一次 项目结束自动调用
    public void destroy() {
        System.out.println("destroy初始化方法");
    }
}
  • 2.配置Filter: Filter类上加@WebFilter注解,配置拦截资源的路径。启动类上加@ServletComponentScan开启Servlet组件支持。

3. Filter详解

  • 1.Filter可以根据需求,配置不同的拦截资源路径:
拦截路径 urlPatterns值 含义
拦截具体路径 /login 只有访问/login 路径时,才会被拦截
目录拦截 /emps/* 访问/emps下的所有资源,都会被拦截
拦截所有 /* 访问所有资源,都会被拦截

4. 过滤器链

  • 介绍:一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链
  • 执行流程:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lFPxJ1qN-1687510289356)(18_files/1.jpg)]
  • 执行顺序:注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序。

2.利用Filter过滤器实现登录校验

1. 流程

  • 获取请求url。
  • 判断请求url中是否包含login,如果包含,说明是登录操作,放行。
  • 获取请求头中的令牌(token) 。
  • 判断令牌是否存在,如果不存在,返回错误结果(未登录)。
  • 解析token,如果解析失败,返回错误结果(未登录)。
  • 放行。
    统一拦截--过滤器Filter_第1张图片
  1. 代码实现:(具体细节请看注释)
import com.alibaba.fastjson.JSONObject;
import com.mannor.pojo.Result;
import com.mannor.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        //1. 获取请求url。
        String requestURI = req.getRequestURI();
        log.info("请求的url:{}", requestURI);

        //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
        if (requestURI.contains("login")) {
            log.info("登录操作");
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        //3.获取请求头中的令牌(token)。
        String jwt = req.getHeader("token");

        //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
        if (!StringUtils.hasLength(jwt)) {
            log.info("请求头token为空,返回未登录的信息");
            Result error = Result.error("NOT_LOGIN");//前端需要响应一个json格式的数据
            //手动将对象转换为json格式的数据-------》使用阿里巴巴fastJSON的工具包(需要引入依赖)
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);//使用HttpServletResponse对象返回错误的JSON数据
            return;
        }
        //5.解析token(校验jwt令牌),如果解析失败,返回错误结果(未登录)。如果错误会报错,所以使用try...catch...
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {//程序执行到这里说明程序执行失败--jwt令牌错误
            e.printStackTrace();
            log.info("解析令牌失败,返回未登录的错误信息");
            Result error = Result.error("NOT_LOGIN");//前端需要响应一个json格式的数据
            //手动将对象转换为json格式的数据-------》使用阿里巴巴fastJSON的工具包(需要引入依赖)
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);//使用HttpServletResponse对象返回错误的JSON数据
            return;
        }
        //6.放行。
        log.info("令牌合法,直接放行");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}


你可能感兴趣的:(后端,servlet,java,开发语言)