自定义Filter

本文详细介绍了如何使用Servlet3.0的注解进行配置,包括@ServletComponentScan的使用,以及如何创建和实现Filter接口。通过示例代码展示了@WebFilter注解的应用,设置拦截规则,实现自定义登录拦截器。

这里我我介绍的是针对使用Servlet3.0的注解进行配置:
          1.启动类里面增加 @ServletComponentScan,进行扫描
          2.新建一个Filter类,implements Filter,并实现对应的接口
           3. @WebFilter 标记一个类为filter,被spring进行扫描 
                urlPatterns:拦截规则,支持正则

直接上代码:

package com.study.studyBoot.Filter;

import com.study.studyBoot.controller.FileController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.thymeleaf.util.StringUtils;

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

/**
 * @Description: 自定义拦截器
 * @author: panboyang
 * @date :2019-06-30 13:05:01
 * @params :urlPatterns 拦截规则,支持正则
 */
@WebFilter(urlPatterns = "/test/*", filterName = "loginFilter")
public class LoginFilter implements Filter {
    private static final Logger LOG = LoggerFactory.getLogger(LoginFilter.class);

    /**
     * @Description: 容器被加载的时候调用
     * @author: panboyang
     * @date :2019-06-30 13:08:05
     * @params: No such property: code for class: Script1
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        LOG.info("容器正在初始化");
    }

    /**
     * @Description: 拦截的时候调用
     * @author: panboyang
     * @date :2019-06-30 13:08:05
     * @params: No such property: code for class: Script1
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       LOG.info("正在拦截");
        HttpServletRequest request= (HttpServletRequest) servletRequest;
        HttpServletResponse response= (HttpServletResponse) servletResponse;
        //得到前端传进来的登录信息,登录账号密码
       String username=  request.getParameter("userName");
        String pwd= request.getParameter("pwd");
         //查询数据库进行匹配
        String sqlUserName="数据库用户名";
        String sqlPwd="数据库密码";
        if(StringUtils.isEmpty(username)&&StringUtils.isEmpty(pwd)){
            LOG.info("账号密码不能为空");
        }else {
            if(username.equals(sqlUserName)&&pwd.equals(sqlPwd)){
//放行
                filterChain.doFilter(servletRequest,servletResponse);
            }else {
                response.sendRedirect("error.html");
                return;
            }
        }


    }

    /**
     * @Description: 摧毁的时候调用
     * @author: panboyang
     * @date :
     * @params: No such property: code for class: Script1
     */
    @Override
    public void destroy() {
          LOG.info("容器正在摧毁");
    }
}

启动类增加注解:

查看启动日志:

 

<think>我们已经在之前的讨论中了解了Log4j2过滤器的基本配置。现在用户明确要求实现自定义Filter,因此需要基于引用内容提供实现方法。 根据引用[1],自定义过滤器需要实现org.apache.logging.log4j.core.Filter接口。核心方法是filter(LogEvent event)方法,该方法返回一个Result枚举(ACCEPT, DENY, NEUTRAL)。 实现步骤: 1. 创建自定义Filter类,实现Filter接口(或继承AbstractFilter)。 2. 实现filter(LogEvent event)方法,编写自定义逻辑。 3. 使用@Plugin注解标记该类,以便Log4j2识别。 4. 在配置文件中使用自定义Filter(需要指定包名或通过插件机制加载)。 另外,参考引用[2]和[3]中关于自定义Appender的插件注册方式,自定义Filter同样需要插件注册。有两种方式: a) 在配置文件的<Configuration>标签中添加packages属性,指定自定义Filter所在的包。 b) 通过生成Log4j2Plugins.dat文件(在META-INF/org/apache/logging/log4j/core/config/plugins目录下)自动注册。 下面详细说明: 步骤1:创建自定义Filter类 建议继承AbstractFilter,它已经实现了部分方法。 示例:创建一个根据日志消息内容是否包含特定关键词的过滤器。 ```java package com.example.log4j2.filters; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.AbstractFilter; import org.apache.logging.log4j.core.config.Node; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginFactory; import org.apache.logging.log4j.message.Message; @Plugin(name = "KeywordFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE) public class KeywordFilter extends AbstractFilter { private final String keyword; private KeywordFilter(String keyword, Result onMatch, Result onMismatch) { super(onMatch, onMismatch); this.keyword = keyword; } @Override public Result filter(LogEvent event) { // 获取日志消息 Message msg = event.getMessage(); if (msg == null) { return onMismatch; // 没有消息,按不匹配处理 } String formattedMessage = msg.getFormattedMessage(); if (formattedMessage.contains(keyword)) { return onMatch; // 匹配关键词 } return onMismatch; } // 工厂方法,用于从配置中创建实例 @PluginFactory public static KeywordFilter createFilter( @PluginAttribute("keyword") String keyword, @PluginAttribute("onMatch") Result onMatch, @PluginAttribute("onMismatch") Result onMismatch) { // 处理默认值 if (onMatch == null) { onMatch = Result.NEUTRAL; } if (onMismatch == null) { onMismatch = Result.DENY; } return new KeywordFilter(keyword, onMatch, onMismatch); } } ``` 步骤2:在配置文件中使用自定义Filter 方式一:通过packages属性指定包名 ```xml <Configuration status="WARN" packages="com.example.log4j2.filters"> <Appenders> <Console name="Console"> <KeywordFilter keyword="SECRET" onMatch="DENY" onMismatch="NEUTRAL"/> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="DEBUG"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration> ``` 方式二:通过插件机制(生成Log4j2Plugins.dat) 如果你使用Maven,可以添加log4j-core依赖,并确保在resources目录下创建META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat文件。但是,通常我们使用注解处理器自动生成该文件。 对于Maven项目,添加以下依赖和构建配置: ```xml <dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.17.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <annotationProcessorPaths> <path> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.17.1</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build> ``` 编译项目后,注解处理器会自动生成Log4j2Plugins.dat文件,这样在配置文件中就可以直接使用自定义Filter,无需指定packages。 步骤3:测试 使用日志记录,观察是否按预期过滤。 注意事项: 1. 自定义Filter的@Plugin注解中,name属性是配置时使用的元素名,category固定为Node.CATEGORY,elementType固定为Filter.ELEMENT_TYPE。 2. 工厂方法(@PluginFactory)的参数与配置中的属性对应,使用@PluginAttribute注解。 3. 在配置中,自定义Filter的使用方式与内置Filter相同。 如果遇到问题,可以启用Log4j2的内部调试(在JVM参数中添加-Dlog4j2.debug=true)来查看加载情况。 引用[4]和[5]提到了通过ThreadContext(MDC)传递上下文信息(如traceId),这也可以用于自定义过滤器中,例如根据traceId过滤日志。在自定义过滤器的filter方法中,可以通过event.getContextData()获取ThreadContext中的数据,然后进行判断。 示例:根据traceId过滤 ```java @Override public Result filter(LogEvent event) { String traceId = event.getContextData().getValue("traceId"); if ("12345".equals(traceId)) { return onMatch; } return onMismatch; } ``` 这样,我们就可以在自定义过滤器中利用线程上下文数据。 总结:自定义Filter的实现包括编写Filter类、使用注解声明插件、提供工厂方法,然后在配置中引用。注意注册方式(packages或插件文件)。</think>### Log4j2 自定义 Filter 实现方法 在 Log4j2 中添加自定义 Filter 需要实现特定接口并进行插件注册,以下是完整实现步骤: #### 1. 创建自定义 Filter 类 继承 `AbstractFilter` 并实现核心过滤逻辑: ```java import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.Filter.Result; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginFactory; import org.apache.logging.log4j.core.filter.AbstractFilter; @Plugin( name = "CustomFilter", // XML 配置中使用的名称 category = "Core", elementType = Filter.ELEMENT_TYPE ) public class CustomFilter extends AbstractFilter { private final String keyword; private CustomFilter(String keyword, Result onMatch, Result onMismatch) { super(onMatch, onMismatch); this.keyword = keyword; } @Override public Result filter(LogEvent event) { // 核心过滤逻辑 if (event.getMessage() != null && event.getMessage().getFormattedMessage().contains(keyword)) { return onMatch; // 匹配时返回 ACCEPT/DENY } return onMismatch; // 不匹配时返回 NEUTRAL/DENY } @PluginFactory public static CustomFilter createFilter( @PluginAttribute("keyword") String keyword, @PluginAttribute("onMatch") Result onMatch, @PluginAttribute("onMismatch") Result onMismatch ) { // 设置默认值 if (onMatch == null) onMatch = Result.ACCEPT; if (onMismatch == null) onMismatch = Result.NEUTRAL; return new CustomFilter(keyword, onMatch, onMismatch); } } ``` #### 2. 插件注册(两种方式) **方式一:通过 packages 声明(推荐)** ```xml <Configuration status="WARN" packages="com.yourpackage.filters"> <Appenders> <Console name="Console"> <CustomFilter keyword="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> </Console> </Appenders> </Configuration> ``` **方式二:通过插件元数据(需构建工具)** 1. 确保项目包含 `log4j-core` 依赖 2. Maven/Gradle 构建时会自动生成 `META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat` #### 3. XML 配置使用 ```xml <Configuration> <Appenders> <Console name="Console"> <!-- 过滤包含"SECRET"的日志 --> <CustomFilter keyword="SECRET" onMatch="DENY" onMismatch="NEUTRAL"/> <PatternLayout pattern="%d{HH:mm:ss.SSS} %msg%n"/> </Console> </Appenders> <Loggers> <Root level="DEBUG"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration> ``` #### 4. 高级功能实现 **结合线程上下文过滤**(参考引用[4][5]): ```java @Override public Result filter(LogEvent event) { String userId = event.getContextData().getValue("USER_ID"); return "ADMIN".equals(userId) ? onMatch : onMismatch; } ``` **动态修改过滤规则**: ```java // 在运行时更新过滤条件 CustomFilter filter = (CustomFilter)logger.getAppenders().get("Console").getFilter(); filter.setKeyword("NEW_KEYWORD"); ``` #### 关键注解说明 | 注解 | 作用 | |-----------------|----------------------------------------------------------------------| | `@Plugin` | 声明 Log4j2 插件,`name` 对应 XML 元素名 | | `@PluginFactory`| 标记工厂方法,用于从配置创建实例 | | `@PluginAttribute` | 绑定 XML 属性到方法参数 | #### 调试技巧 ```java // 启用详细日志 System.setProperty("log4j2.debug", "true"); // 查看过滤器决策 StatusLogger.getLogger().info("Filter result: " + filterResult); ``` > **注意事项**: > 1. 确保 `onMatch`/`onMismatch` 使用 `Result` 枚举值(ACCEPT/DENY/NEUTRAL) > 2. 多过滤器组合时注意执行顺序 > 3. 线程安全:避免在 `filter()` 方法中修改共享状态[^1][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习没有捷径,如果有那便是持之以恒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值