海哥 发表于 2025-2-17 01:22:17

Springboot焦点:过滤器

☆ 什么是过滤器

   过滤器(Filter)是在Web应用程序中用来拦截和处理哀求/响应的组件。它们按照肯定的次序链式地处理每个传入的HTTP哀求,并可以在哀求被处理前或响应被发送回客户端后执行某些逻辑。
常用于做权限查抄认证,记载日志操纵、拦截过滤哀求、敏感数据处理,同一编码处理等。
☆ 过滤器的生命周期



[*]初始化
此方法只运行一次,当Web应用程序启动时,Servlet容器会为每个界说的过滤器创建一个实例,并调用其init()方法。通常用来读取配置文件和初始化资源,执行一些必要的初始化操纵。

[*]init(FilterConfig filterConfig):
参数:filterConfig 提供了访问过滤器配置信息的方式,比如初始化参数。
注意事项:在这个阶段,不应该进行耗时的操纵,由于这会影响应用的启动速度。

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    // 执行初始化逻辑,如读取配置参数等
}


[*] 哀求处理
一旦过滤器被初始化,它就会进入活动状态,每当有新的哀求到来时,容器会调用过滤器的doFilter()方法。这是过滤器的焦点部门,可以在其中添加自界说过滤逻辑来查抄、修改哀求或响应。

[*]doFilter(ServletRequest request, ServletResponse response, FilterChain chain):
参数:
request:当前的HTTP哀求对象。
response:即将发送给客户端的HTTP响应对象。
chain:表现过滤器链的对象,用于将哀求传递给下一个过滤器或最终的目标资源。
注意事项:在这个方法内部,你可以选择是否继承调用chain.doFilter()来让哀求继承沿过滤器链进步,或者直接结束哀求并返反响应。

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    // 在这里添加过滤逻辑
    try {
      // 可选:预处理请求
      
      // 继续调用下一个过滤器或目标资源
      chain.doFilter(request, response);
      
      // 可选:后处理响应
    } catch (Exception e) {
      // 异常处理逻辑
    }
}


[*] 烧毁
过滤器烧毁之前会调用destroy()方法,通知过滤器释放其所占用的全部资源。此方法只运行一次,通常用作关闭数据库连接、注销监听器等。

[*]destroy():
没有参数。
注意事项:应该确保全部已分配的资源都被正确释放,以克制内存走漏或其他问题。

@Override
public void destroy() {
    // 执行清理逻辑,如关闭资源等
}
☆ 使用场景


[*]身份验证与授权:确保只有经过认证和授权的用户才气访问某些特定的资源
[*]日志记载:记载全部哀求信息,包罗但不限于访问时间、来源IP地址、哀求方法、URI等,有助于体系管理和安全监控。
[*]同一编码格式:确保全部传入和传出的数据都使用同一的字符编码格式,克制不同字符集兼容、乱码问题。
[*]XSS防护:防止跨站脚本攻击,确保输入输出的安全性。
[*]CSRF防护:防止跨站哀求伪造攻击,确保表单提交的真实性和完整性。
[*]性能监控:收集有关哀求处理时间和吞吐量的数据,资助优化体系性能。
……
☆ 如何使用
在Springboot中,实现过滤器的方式有多种,如何使用取决于本身的习惯偏好,以下是几种常见实现方式:


[*]直接实现Filter接口
最根本的实现方式,自界说类实现Filter接口。
import javax.servlet.*;
import java.io.IOException;
@Slf4j
@Component
@Order(1)
public class MyCustomFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
         // 初始化逻辑
      log.info("filter1 init……");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
      log.info("=================:{}", "在这里添加过滤逻辑");      
      // 继续调用下一个过滤器或目标资源
      chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
      // 清理逻辑
      log.info("filter1 destroy……");
    }
}
注册过滤器:
可以通过配置类手动注册这个过滤器,或者使用@Component注解让Spring主动检测到它,过滤器的次序可以通过注解@Order指定。


[*]扩展OncePerRequestFilter
如果渴望确保过滤器只针对每个哀求执行一次(即使存在多层转发或其他内部哀求),通过扩展OncePerRequestFilter类,可以克制重复执行过滤逻辑。
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CustomOncePerRequestFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
      // 自定义逻辑
      super.doFilterInternal(request, response, filterChain);
    }
}


[*]同样可以通过配置类或@Component注解来注册。
基于注解@WebFilter 和 @ServletComponentScan
起首必要在主应用程序类或启动类上添加启用@ServletComponentScan注解,用以扫描并注册带有@WebFilter注解的组件。
示例代码:编写过滤器实现Filter

import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
@WebFilter(urlPatterns = "user/*", filterName = "filter1", initParams = @WebInitParam(name = "paramName", value = "paramValue"))
@Slf4j
public class UserFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
      // 初始化逻辑
      log.info("filter1 init……");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
      // 过滤逻辑
      HttpServletRequest request1 = (HttpServletRequest) servletRequest;
      String token = request1.getHeader("token");
      log.info("token值:{}", token);

      if (token != null) {
            //该方法执行后直接运行至下一个过滤器
            chain.doFilter(request, response);
      } else {
            log.info("错误处理:{}", "非法用户");
      }
    }
    @Override
    public void destroy() {
      // 清理逻辑
      log.info("filter1 destroy……");
    }
}
启用扫描:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan //过滤器扫描
public class MyApplication {
    public static void main(String[] args) {
      SpringApplication.run(MyApplication.class, args);
    }
}


[*]通过配置类注册过滤器
通过编写配置类并在其中界说@Bean来注册过滤器。这种方法提供了更大的灵活性,可以在这里指定URL模式、初始化参数以及过滤器的次序等。
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<MyCustomFilter> loggingFilter(){
      FilterRegistrationBean<MyCustomFilter> registrationBean = new FilterRegistrationBean<>();
      registrationBean.setFilter(new MyCustomFilter());
      registrationBean.addUrlPatterns("/api/*"); // 指定过滤器适用的URL模式
      registrationBean.setOrder(1); // 设置过滤器的优先级
      return registrationBean;
    }
}
☆ 参考:文章 FC464782123

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Springboot焦点:过滤器