过滤器(Filter)

概念:Filter过滤器,是JavaWeb三大组件(Servlet、Filter、Listener)之一

过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能

过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等

过滤器与拦截器_拦截器

Filter快速入门

1.定义Filter:定义一个类,实现Filter接口,并重写其所有方法过滤器与拦截器_执行流程_02

2.配置Filter:Filter类上加@WebFilte 注解,配置拦截资源路径。引导类上@ServletComponentScan开启Servlet组件支持。

”/*“代表所有资源路径

过滤器与拦截器_拦截器_03

过滤器与拦截器_ide_04

@WebFilter(urlPatterns = "/*")
public class DemoFilter implements Filter{
    @Override//初始化方法,只调用一次
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override//拦截到请求之后调用,调用多次
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override//销毁方法,只调用一次
    public void destroy() {
        Filter.super.destroy();
    }

详解(执行流程、拦截路径、过滤器链)过滤器与拦截器_ide_05

在请求以后,过滤器拦截请求,执行拦截前的操作,执行完以后,放行,在访问完资源以后,响应之前还会再次回到Filter,此时可以执行放行后的逻辑

Filter拦截路径

Filter可以根据需求,配置不同的拦截资源路径。过滤器与拦截器_ide_06

过滤器链

一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链

顺序:注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序过滤器与拦截器_执行流程_07

登录校验Filter

步骤

获取请求url

判断请求url中是否包含login,如果包含,说明是登录操作,放行

获取请求头中的令牌

判断令牌是否存在,如果不存在,返回错误

解析令牌,解析失败,返回错误

放行

过滤器与拦截器_执行流程_08

@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        //1.获取请求的url
        String url = req.getRequestURL().toString();
        log.info("请求的url:{}",url);

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

        //判断令牌是否存在
        if(!StringUtils.hasLength(jwt)){
            log.info("请求token为空");
            Result error = Result.error("NOT_LOGIN");
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return;

        }

        //解析token 如果解析失败,返回错误结果
        try{
            JwtUtils.parseJWT(jwt);
        }catch (Exception e){
            e.printStackTrace();
            log.info("解析令牌失败");
            Result error = Result.error("NOT_LOGIN");
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return;
        }

        //放行
        log.info("令牌合法,放行");
        filterChain.doFilter(servletRequest,servletResponse);

    }

拦截器Interceptor

概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。

作用:拦截请求,在指定的方法调用前后,根据业务需要执行预定的代码

入门

定义拦截器,实现HandlerInterceptor接口,并重写其所有方法

注册拦截器

过滤器与拦截器_执行流程_09

@Component
public class LoginCheckInterceptor implements HandlerInterceptor{
    @Override//目标资源方法运行前运行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return 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...");
    }
}
@Configuration//配置类
public class WebConfig implements WebMvcConfigurer{
    @Resource
    private LoginCheckInterceptor loginCheckInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
    }
}

详解(拦截路径、执行流程)

拦截路径

过滤器与拦截器_执行流程_10

过滤器与拦截器_ide_11

执行流程

过滤器与拦截器_执行流程_12

Filter与Interceptor的区别

接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口。

拦截范围不同:过滤器Filter会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源。

登录校验

public class LoginCheckInterceptor implements HandlerInterceptor{
    @Override//目标资源方法运行前运行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {

        //1.获取请求的url
        String url = req.getRequestURL().toString();
        log.info("请求的url:{}",url);

        //判断url中是否包含login
        if(url.contains("login")){
            log.info("登录操作,放行");
            return true;
        }
        //获取请求头中的令牌
        String jwt = req.getHeader("token");

        //判断令牌是否存在
        if(!StringUtils.hasLength(jwt)){
            log.info("请求token为空");
            Result error = Result.error("NOT_LOGIN");
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return false;

        }

        //解析token 如果解析失败,返回错误结果
        try{
            JwtUtils.parseJWT(jwt);
        }catch (Exception e){
            e.printStackTrace();
            log.info("解析令牌失败");
            Result error = Result.error("NOT_LOGIN");
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return false;
        }

        //放行
        log.info("令牌合法,放行");
        return true;
    }

全局异常处理器

/**
 * 全局异常处理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)//捕获所有异常
    public Result ex(Exception ex){
        ex.printStackTrace();
        return Result.error("对不起,操作失败");
    }
}

@RestControllerAdvice = @ControllerAdvice + @ResponseBody