Java过滤器与监听器间区别与联系

 

过滤器

过滤器可以对 Web 服务资源进行过滤,过滤静态资源如静态 HTML、CSS、JS、IMG 等,过滤动态资源如 JSP、Servlet 等,从而实现一些特殊的需求,比如 URL 访问权限设置,过滤敏感词汇,压缩响应信息。

自定义过滤器

定义一个过滤器实现 Filter 接口,重写三个方法

init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。注意:这个方法必须执行成功,否则过滤器会不起作用。

doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。

destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次

@Slf4j
public class WebMvcFilter implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
      String encoding = filterConfig.getInitParameter("encoding");
      log.info("-1-----encoding: {} ----->", encoding);
  }
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
      log.info("0-----doFilter----->");
      filterChain.doFilter(servletRequest, servletResponse);
  }
  @Override
  public void destroy() {
      log.info("5-----destroy----->");
  }
}

定义一个配置类注册过滤器并定义规则。

@Configuration
public class WebFilterConfiguration {
  @Bean
  public FilterRegistrationBean getWebMvcFilter(){
      FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
      WebMvcFilter webMvcFilter = new WebMvcFilter();
      filterFilterRegistrationBean.setFilter(webMvcFilter);
      filterFilterRegistrationBean.addUrlPatterns("/api/*");
      filterFilterRegistrationBean.setName("WebMvcFilter");
      filterFilterRegistrationBean.addInitParameter("encoding", "GBK");
      filterFilterRegistrationBean.setOrder(1);
      return filterFilterRegistrationBean;
  }
}

拦截器和过滤器的区别

  • 过滤器依赖 Servlet 容器,拦截器不依赖 Servlet 容器。
  • 过滤器基于容器的函数回调,拦截器基于 Java 的反射机制。
  • 过滤器几乎可以过滤所有的请求,包括静态和动态资源。拦截器只能拦截 Controller 层定义的路由请求,不处理静态资源。
  • 过滤器只能在容器初始化的时候调用一次,拦截器可以多次调用。
  • 拦截器可以访问 Controller 层中的方法和上下文,可以获取 IOC 容器中的各种 Bean 并根据需求进行处理。过滤器不支持访问且不能获取。

 

监听器

  • 监听器可以监听 Web 中特定的事件。
  • 监听器监听的是拥有作用域的对象,如 ServletContext、HttpSession 等。这些作用域对象分别都有相同的方法,如 setAttribute、getAttribute、removeAttribute,只要调用这几个方法就会进入到监听器对应的方法中处理相应的逻辑。
  • 初始化上下文(Spring 容器的初始化,文件的解析)、会话的监听(在线人数),监听干预用户信息(用户资源倾斜)。

监听ServletContext 的 application 对象

@Component
public class ServletContextListener implements ApplicationListener<ContextRefreshedEvent> {
  @Override
  public void onApplicationEvent(ContextRefreshedEvent event) {
      if (event.getApplicationContext().getParent() == null) {
          ApplicationContext applicationContext = event.getApplicationContext();
          UserService userService = applicationContext.getBean(UserService.class);
          User user = userService.getUser();
          ServletContext application = applicationContext.getBean(ServletContext.class);
          application.setAttribute("user", user);
      }
  }
}

测试

@RestController
@Slf4j
public class UserController {
  @GetMapping("/api/getUser")
  public User getUser(HttpServletRequest request) {
      ServletContext servletContext = request.getServletContext();
      User user = (User) servletContext.getAttribute("user");
      log.info("user: {}", user);
      return user;
  }
}

监听 HttpSession的 session 对象

定义一个监听器实现 HttpSessionListener 接口,重写两个方法,获取 session 会话对象,并将数据放到 HttpSession 的作用域对象 session 中。

@Component
@Slf4j
public class LoginSessionListener implements HttpSessionListener {
  public static Integer count = 0;
  @Override
  public void sessionCreated(HttpSessionEvent se) {
      log.info("新用户上线...");
      count++;
      se.getSession().getServletContext().setAttribute("personCount", count);
  }
  @Override
  public void sessionDestroyed(HttpSessionEvent se) {
      log.info("用户下线了...");
      count--;
      se.getSession().getServletContext().setAttribute("personCount", count);
  }
}

测试

@RestController
@Slf4j
public class LoginController {
  @GetMapping("/getOnlineUser")
  public String getOnlineUser(HttpServletRequest request) {
      Integer personCount = (Integer) request.getServletContext().getAttribute("personCount");
      log.info("登录的人数是: {}", (personCount == null ? 0 : personCount));
      return "登录的人数是:" + (personCount == null ? 0 : personCount);
  }
  @GetMapping("logined")
  public String logined(HttpSession session) {
      session.setAttribute("user", new User(1L, "PlanMak1r", "123456"));
      log.info("登录成功...");
      return "success";
  }
  @GetMapping("logout")
  public String logout(HttpSession session) {
      session.invalidate();
      log.info("退出成功...");
      return "success";
  }
}

关于Java过滤器与监听器间区别与联系的文章就介绍至此,更多相关Java过滤器与监听器内容请搜索编程宝库以前的文章,希望以后支持编程宝库

 前言为什么需要异步执行?场景:电商系统中获取一个完整的商品信息可能分为以下几步:①获取商品基本信息②获取商品图片信息③获取商品促销活动信息④获取商品各种类的基本信息 等 ...