log4j增加过滤器

日志log4j一般配置

<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
    <!-- 设置日志输出的样式 -->
    <layout class="org.apache.log4j.PatternLayout">
        <!-- 设置日志输出的格式 -->
        <param name="ConversionPattern" value="**** [%p] [%d{yyyy/MM/dd HH:mm:ss:SSS}] ******************************%n[Thread] %t%n[Class] %C%n[Method] %M%n[Message] %m%n%n" />
    </layout>
</appender>

可以增加过滤器

<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
    <!-- 设置日志输出的样式 -->
    <layout class="org.apache.log4j.PatternLayout">
        <!-- 设置日志输出的格式 -->
        <param name="ConversionPattern" value="**** [%p] [%d{yyyy/MM/dd HH:mm:ss:SSS}] ******************************%n[Thread] %t%n[Class] %C%n[Method] %M%n[Message] %m%n%n" />
    </layout>
    <filter class="org.apache.log4j.varia.StringMatchFilter">
        <param name="StringToMatch" value="adminPass" />
        <param name="AcceptOnMatch" value="false" />
    </filter>
</appender>

log4j的StringMatchFilter只能判断是否包含某个字符串,源码中用的是indexOf

public int decide(LoggingEvent event) {
    String msg = event.getRenderedMessage();
    if(msg == null ||  stringToMatch == null)
      return Filter.NEUTRAL;
    
    if( msg.indexOf(stringToMatch) == -1 ) {
      return Filter.NEUTRAL;
    } else { // we've got a match
      if(acceptOnMatch) {
return Filter.ACCEPT;
      } else {
return Filter.DENY;
      }
    }
  }

filter可以自定义,可以实现更复杂的过滤,比如写个正则判断是否包含身份证

package com.daimeng.interceptor;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.log4j.helpers.OptionConverter;
/**
 * 
* @功能描述: log4j的过滤器
* @用法:在log4j的appender里面添加filter
* 参考 org.apache.log4j.varia.StringMatchFilter
* <filter class="org.apache.log4j.varia.StringMatchFilter">
        <param name="StringToMatch" value="adminPass" />
        <param name="AcceptOnMatch" value="false" />
    </filter> 
    
* @名称: MyIdNoStringMatchFilter.java 
* @路径 com.dms.interceptor 
* @作者 daimeng.fun
* @E-Mail 
* @创建时间 2020年8月25日 下午3:11:45 
* @version V1.0
 */
public class MyIdNoStringMatchFilter {
/**
 * @deprecated Options are now handled using the JavaBeans paradigm. This
 *             constant is not longer needed and will be removed in the
 *             <em>near</em> term.
 */
public static final String STRING_TO_MATCH_OPTION = "StringToMatch";
/**
 * @deprecated Options are now handled using the JavaBeans paradigm. This
 *             constant is not longer needed and will be removed in the
 *             <em>near</em> term.
 */
public static final String ACCEPT_ON_MATCH_OPTION = "AcceptOnMatch";
boolean acceptOnMatch = true;
String stringToMatch;
/**
 * @deprecated We now use JavaBeans introspection to configure components.
 *             Options strings are no longer needed.
 */
public String[] getOptionStrings() {
return new String[] { STRING_TO_MATCH_OPTION, ACCEPT_ON_MATCH_OPTION };
}
/**
 * @deprecated Use the setter method for the option directly instead of the
 *             generic <code>setOption</code> method.
 */
public void setOption(String key, String value) {
if (key.equalsIgnoreCase(STRING_TO_MATCH_OPTION)) {
stringToMatch = value;
} else if (key.equalsIgnoreCase(ACCEPT_ON_MATCH_OPTION)) {
acceptOnMatch = OptionConverter.toBoolean(value, acceptOnMatch);
}
}
public void setStringToMatch(String s) {
stringToMatch = s;
}
public String getStringToMatch() {
return stringToMatch;
}
public void setAcceptOnMatch(boolean acceptOnMatch) {
this.acceptOnMatch = acceptOnMatch;
}
public boolean getAcceptOnMatch() {
return acceptOnMatch;
}
/**
 * Returns {@link Filter#NEUTRAL} is there is no string match.
 */
    public int decide(LoggingEvent event) {
        String msg = event.getRenderedMessage();
        if (msg == null || stringToMatch == null)
            return Filter.NEUTRAL;
        if (!checkId(msg)) {
            return Filter.NEUTRAL;
        } else { // we've got a match
            if (acceptOnMatch) {
                return Filter.ACCEPT;
            } else {
                return Filter.DENY;
            }
        }
    }
public static boolean checkId(String idmsg) {
//假设18位身份证号码:41000119910101123X  410001 19910101 123X
        //^开头
        //[1-9] 第一位1-9中的一个      4
        //\\d{5} 五位数字           10001(前六位省市县地区)
        //(18|19|20)                19(现阶段可能取值范围18xx-20xx年)
        //\\d{2}                    91(年份)
        //((0[1-9])|(10|11|12))     01(月份)
        //(([0-2][1-9])|10|20|30|31)01(日期)
        //\\d{3} 三位数字            123(第十七位奇数代表男,偶数代表女)
        //[0-9Xx] 0123456789Xx其中的一个 X(第十八位为校验值)
        //$结尾
 
        //假设15位身份证号码:410001910101123  410001 910101 123
        //^开头
        //[1-9] 第一位1-9中的一个      4
        //\\d{5} 五位数字           10001(前六位省市县地区)
        //\\d{2}                    91(年份)
        //((0[1-9])|(10|11|12))     01(月份)
        //(([0-2][1-9])|10|20|30|31)01(日期)
        //\\d{3} 三位数字            123(第十五位奇数代表男,偶数代表女),15位身份证不含X
        //$结尾
String regularExpression = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|" +
                "(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";
boolean matches = idmsg.matches(regularExpression);
 
        //判断第18位校验值
        if (matches) {
 
            if (idmsg.length() == 18) {
                try {
                    char[] charArray = idmsg.toCharArray();
                    //前十七位加权因子
                    int[] idCardWi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
                    //这是除以11后,可能产生的11位余数对应的验证码
                    String[] idCardY = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
                    int sum = 0;
                    for (int i = 0; i < idCardWi.length; i++) {
                        int current = Integer.parseInt(String.valueOf(charArray[i]));
                        int count = current * idCardWi[i];
                        sum += count;
                    }
                    char idCardLast = charArray[17];
                    int idCardMod = sum % 11;
                    if (idCardY[idCardMod].toUpperCase().equals(String.valueOf(idCardLast).toUpperCase())) {
                        return true;
                    } else {
                        return false;
                    }
 
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
            }
 
        }
        return matches;
    }
    public static ArrayList<String> getParamFromXml(String context){
        Pattern p = Pattern.compile("\\>(.*?)\\<\\/");
        Matcher m = p.matcher(context);
        ArrayList<String> result=new ArrayList<String>();
        while(m.find()){
            String r = m.group(1);
            if(r != null && r.indexOf(">") > -1) {
                r = r.split(">")[r.split(">").length-1];
            }
            System.out.println(r);
            result.add(r);
        }
        return result;
    }

}


log4j就可以这么配置

<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
    <!-- 设置日志输出的样式 -->
    <layout class="org.apache.log4j.PatternLayout">
        <!-- 设置日志输出的格式 -->
        <param name="ConversionPattern" value="**** [%p] [%d{yyyy/MM/dd HH:mm:ss:SSS}] ******************************%n[Thread] %t%n[Class] %C%n[Method] %M%n[Message] %m%n%n" />
    </layout>
    <filter class="org.apache.log4j.varia.StringMatchFilter">
        <param name="StringToMatch" value="adminPass" />
        <param name="AcceptOnMatch" value="false" />
    </filter>
    <filter class="com.daimeng.interceptor.MyIdNoStringMatchFilter">
        <param name="StringToMatch" value="adminPass" />
        <param name="AcceptOnMatch" value="false" />
    </filter>
</appender>


{context}