栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaEE 中的 Filter

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaEE 中的 Filter

目录
  • 前言
  • 一、过滤器(Filter)
    • (1) 概念
    • (2) 过滤器的一般作用
    • (3) 在代码中使用
    • (4) Filter 的优先级
    • (5) Filter 的生命周期方法
    • (6) @WebFilter 的 dispatchTypes 属性
    • (7) 其他点赞高的创作者的文章
  • 二、SpringBoot 项目中配置 SpringMVC
  • 三、拦截器(Interceptor)
    • (1) 简介
      • ① 过滤器(Filter)
      • ② 拦截器(Interceptor)
    • (2) 使用拦截器
      • ① 使用
      • ② 三个默认方法的解析:
  • 四、Shiro

前言

① 当提到【登陆】二字的时候,我总能在脑子里面想起三个词:【过滤器】、【拦截器】、【Shiro】
② 在我脑中它们三个都有拦截请求的功能,但具体是干啥的我无法说出来。根据费曼学习法,如果我无法说出来,就代表我不会。
③ 接下来学习一下过滤器、拦截器和 Shiro,并记录一下。

一、过滤器(Filter) (1) 概念

① 官方文档:A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.
过滤器是一个对象,它对资源(servlet 或静态资源)的请求或对来自资源的响应执行筛选(过滤)任务,或对两者都执行筛选(过滤)任务。

② 其他同学的博客:当访问服务器的资源时,过滤器可以把请求拦截下来,去执行一些特殊的功能。过滤器页可以把响应拦截下来,控制某些东西是否可以返回给客户端。

③ 提炼一下:Filter 用来拦截、过滤、筛选客户端的请求和服务器的响应。

(2) 过滤器的一般作用
  • Authentication Filters 身份验证(登陆)
  • Logging and Auditing Filters 日志和审核
  • Image conversion Filters 图片转换
  • Data compression Filters 数据压缩
  • Encryption Filters 加密过滤
  • Filters that trigger resource access events 触发资源访问事件的过滤器
(3) 在代码中使用

在 SpringBoot 项目中使用 Filter 的时候,在 Filter 类上要加上 @Component 注解,否则没有效果。【迷糊点】

下面通过 @WebFilter 的方式使用 Filter,暂时不知道 xml 配置文件的方式在 SpringBoot 项目中如何使用。

@WebFilter("
    @Override
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println("① chain.doFilter 前的代码是对【请求】执行过滤功能");

        filterChain.doFilter(request, response);

        System.out.println("② chain.doFilter 后的代码是对【响应】执行过滤功能");
    }

}
@RestController
@RequestMapping("/apples")
public class AppleController {

    @GetMapping("/apple1")
    @ResponseBody
    public String apple1() {
        System.out.println("AppleController - apple1");
        return "AppleController - apple1";
    }

}

执行结果:
① chain.doFilter 前的代码是对【请求】执行过滤功能
AppleController - apple1
② chain.doFilter 后的代码是对【响应】执行过滤功能

Filter 是一个接口,Filter 中有三个方法:init()、doFilter()、destroy()
其中,init() 和 destroy() 是默认(default)方法,无需实现(implements)Filter 的类必须实现这两个方法。doFilter 不是默认方法,实现(implements)Filter 接口的类必须实现 doFilter 方法。

init() 方法被调用:called by the web container to indicate to a filter that it is being placed into service.
Filter 的 init 方法由 Web 容器调用,用于指示某个 Filter 被应用于到了服务之中。
Filter 的 init 方法在启动 SpringBoot 项目(运行 main 方法)的过程中被调用。

doFilter() 方法被调用:called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.

destroy() 方法被调用:called by the web container to indicate to a filter that it is being taken out of service.
destroy() 方法由 Web 容器调用,用于指示某个 Filter 已经从服务中停止了。

下面的代码是我第一次学习 Filter 的时候写的,现在来重读一下。
该代码作用:通过拦截器进行登录验证。
① chain.doFilter 之前的代码是对【请求】进行过滤,chain.doFilter 之后的代码是对【响应】进行过滤
② 在下面的代码中,先把 ServletRequest 类型的 req 和 ServletResponse 类型的 resp 转换为 HttpServletRequest 的类型的 request 和 HttpServletResponse 类型的 response。便于对客户端的请求进行筛选和对响应进行处理。
③ HttpServletRequest 的类型的 request 的 getRequestURI 方法可以获取到客户端请求的部分路径(不包含协议、域名、端口号)的字符串,可通过客户端路径进行筛选,判断哪些路径需要进行登录,哪些路径需要直接通过(不用登录)。
④ 调用 chain.doFilter 方法后,才可进入下一链条调用。

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
  // 需要通过 HttpServletRequest 类型的 request 拿到 Session
  HttpServletRequest request = ((HttpServletRequest) req);
  // 需要通过HttpServletResponse类型的response重定向
  HttpServletResponse response = (HttpServletResponse) resp;
  String uri = request.getRequestURI();

  if (uri.contains("/asset/")) { // 资源文件优先放开
    chain.doFilter(req, resp);
  } else if (uri.contains("/admin") || uri.contains("/remove") || uri.contains("save")) { // 需要进行过滤的
    Object user = request.getSession().getAttribute("user");
    if (user != null) { // 登录成功过
      chain.doFilter(req, resp);
    } else { // 没有登录成功过
      response.sendRedirect(request.getContextPath() + "/page/login.jsp");
    }
  } else { // (login.jsp、captcha)
    System.out.println(uri);
    chain.doFilter(req, resp);
  }
}
(4) Filter 的优先级

当有多个 Filter 的时候,哪个 Filter 先执行?
① 通过注解方式使用 Filter:按照 Filter 的字母顺序,小的哪个 Filter 先执行。
如:CharsetFilter 和 LoginFilter,CharSetFilter 的(C)比 LoginFilter 的(L)小,所以 CharSetFilter 先执行。
② 通过 xml 配置文件使用 Filter:先配置哪个 Filter 就先执行哪个 Filter。

下面是测试代码:

@Component
@WebFilter("
@Configuration
//@EnableWebMvc // 完全自定义 SpringMVC 的配置
public class SpringMVCConfig implements WebMvcConfigurer {

    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

    }
}
  • 若想完全自定义 SpringMVC 的配置,可使用 @EnableWebMvc 注解

三、拦截器(Interceptor)

在 SpringMVC 框架中,拦截器是 Java 面试中的常客。

(1) 简介

拦截器(Interceptor)的功能与过滤器(Filter)类似,但有本质的区别。

① 过滤器(Filter)
  • 是 Servlet 规范的一部分
  • 能过滤任意请求,如 html、js、jsp
  • 请求抵达 Servlet 之前,响应抵达客户端之前都可过滤
  • 常用于:编码设置、登录校验等
② 拦截器(Interceptor)
  • 是 SpringMVC 的一部分
  • 只能拦截 DispatcherServlet 能拦截到的内容,一般用来拦截 controller
  • 常用于:抽取 controller 的公共代码

除了 jsp,DispatcherServlet 都可以拦截。

(2) 使用拦截器 ① 使用
  • 创建一个拦截器类(QYInterceptor)实现 HandlerInterceptor 接口
  • 创建一个 SpringMVC 配置类(QYWebMvcConfig),实现 WebMvcConfigurer 接口。实现该接口的 addInterceptor 方法
public class QYInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        System.out.println("QYInterceptor - preHandle - " + request.getRequestURL());
        // 必须返回 true 才会进入下一个步
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler, // 通过 handler 可得知是哪个控制器的哪个方法
                           ModelAndView modelAndView) throws Exception {
        System.out.println("QYInterceptor - postHandle - " + handler);
    }

    
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) throws Exception {
        // 下面这种代码执行完之后 afterCompletion 方法被调用                        
        // response.sendRedirect("");
        // request.getRequestDispatcher("").forward(request, response);
        // response.getWriter().write("");
        System.out.println("QYInterceptor - afterCompletion");
    }

}
@Configuration
//@EnableWebMvc // 完全自定义 SpringMVC 的配置
public class QYMVCConfig implements WebMvcConfigurer {

    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        String[] pathPatterns = new String[]{"/sysUsers/login", "/asset*.html"};
        registry.addInterceptor(new QYInterceptor())
                .addPathPatterns("/**") // 拦截全部路径
                .excludePathPatterns(pathPatterns);
    }
}

执行结果:

  • HandlerInterceptor 接口中方法的都是默认方法(在接口中有该方法的默认实现)
  • HandlerInterceptor 接口中有 3 个默认方法,分别是:preHandle、postHandle、afterCompletion
② 三个默认方法的解析:
  • preHandle:在 controller 的处理方法之前调用(该方法返回值为 true 才执行 controller 里面的内容)
    – 通常在 preHandle 中进行初始化、请求预处理(可实现登录验证)
    – preHandle 返回 true 才会执行后面的调用。若返回 false,不会调用 controller 处理方法、postHandle 和 afterCompletion
    – 当有多个拦截器时,preHandle 按照正序执行

  • postHandle:在 controller 的处理方法之后,DispatcherServlet 进行视图渲染之前调用
    – 可在 postHandle 中进行请求后续加工处理操作
    – 当有多个拦截器时,postHandle 按照逆序执行

  • afterCompletion:在 DispatcherServlet 进行视图渲染之后调用
    – 一般在这里进行资源回收操作
    – 当有多个拦截器时,afterCompletion按照逆序执行


四、Shiro

…

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1008847.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号