log4j2 自定义layout 出错 error RollingFile contains an invalid element or attribute FLayout
使用的是log4j2 -2.8.1版本。
自定义了一个FLayout如下package com.common;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Date;
import java.util.List;import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
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.PluginConfiguration;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.AbstractStringLayout;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.apache.logging.log4j.core.pattern.PatternParser;@Plugin(name = "FLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class FLayout extends AbstractStringLayout {
    private static final String KEY = "Converter";
    private final PatternSerializer fPatternSerializer;    private FLayout(final Configuration config,final Charset charset,final String pattern,final String headerPattern,
            final String footerPattern) {
super(config,charset,new PatternSerializer(getPatternFormatter(config,headerPattern)),
new PatternSerializer(getPatternFormatter(config,footerPattern)));
this.fPatternSerializer=new PatternSerializer(getPatternFormatter(config,pattern));
}    @PluginFactory
    public static FLayout createLayout( @PluginConfiguration final Configuration config,
     @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset,
            @PluginAttribute("pattern")String pattern,
     @PluginAttribute("header") String headerPattern,
            @PluginAttribute("footer") String footerPattern) {
     if(pattern==null){
     pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} : %m%n";
     }
     if(headerPattern==null){
     headerPattern="%m%n";
     }
     if(footerPattern==null){
     footerPattern="%m%n";
     }
    
        return new FLayout(config,charset,pattern,headerPattern,footerPattern);
    }

@Override
    public String toSerializable(final LogEvent event) {
return this.fPatternSerializer.toSerializable(event);
    }

public static PatternFormatter[] getPatternFormatter(final Configuration config,final String pattern){
final PatternParser parser = createPatternParser(config);
        final List<PatternFormatter> list = parser.parse(pattern);
        final PatternFormatter[] formatters = list.toArray(new PatternFormatter[0]);
return formatters;
}
    public static PatternParser createPatternParser(final Configuration config) {
        if (config == null) {
            return new PatternParser(config, KEY, LogEventPatternConverter.class);
        }
        PatternParser parser = config.getComponent(KEY);
        if (parser == null) {
            parser = new PatternParser(config, KEY, LogEventPatternConverter.class);
            config.addComponent(KEY, parser);
            parser = config.getComponent(KEY);
        }
        return parser;
    }        @Override
    public byte[] toByteArray(LogEvent loge) {
        if ((loge == null)) {
            return null;
        }
        String formatLoge =toSerializable(loge);
        return formatLoge.getBytes();
    } }package com.common;import java.util.Arrays;import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer;
import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer2;
import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.apache.logging.log4j.util.PropertiesUtil;public class PatternSerializer implements Serializer, Serializer2 { public final PatternFormatter[] formatters;
public PatternSerializer(final PatternFormatter[] formatters) {
        super();
        this.formatters = formatters;    }
    protected static final int DEFAULT_STRING_BUILDER_SIZE = 1024;    protected static final int MAX_STRING_BUILDER_SIZE = Math.max(DEFAULT_STRING_BUILDER_SIZE,
            size("log4j.layoutStringBuilder.maxSize", 2 * 1024));
    private static final ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<>();    /**
     * Returns a {@code StringBuilder} that this Layout implementation can use to write the formatted log event to.
     *
     * @return a {@code StringBuilder}
     */
    protected static StringBuilder getStringBuilder() {
        StringBuilder result = threadLocal.get();
        if (result == null) {
            result = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
            threadLocal.set(result);
        }
        trimToMaxSize(result);
        result.setLength(0);
        return result;
    }
    @Override
    public String toSerializable( LogEvent event) {
        final StringBuilder sb = getStringBuilder();
        try {
            return toSerializable(event, sb).toString();
        } finally {
            trimToMaxSize(sb);
        }
    }
    private static int size(final String property, final int defaultValue) {
        return PropertiesUtil.getProperties().getIntegerProperty(property, defaultValue);
    }
    protected static void trimToMaxSize(final StringBuilder stringBuilder) {
        if (stringBuilder.length() > MAX_STRING_BUILDER_SIZE) {
            stringBuilder.setLength(MAX_STRING_BUILDER_SIZE);
            stringBuilder.trimToSize();
        }
    }
    @Override
    public StringBuilder toSerializable(final LogEvent event, final StringBuilder buffer) {
        final int len = formatters.length;
        for (int i = 0; i < len; i++) {
            formatters[i].format(event, buffer);
        }
            String str = buffer.toString();
            buffer.setLength(0);
            buffer.append(str);        return buffer;
    }
    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append(super.toString());
        builder.append("[formatters=");
        builder.append(Arrays.toString(formatters));
        builder.append("]");
        return builder.toString();
    }
}使用路径来加载配置文件,配置文件如下
<?xml version="1.0" encoding="Shift_JIS"?> <Configuration packages="com.common">
    <Properties>
        <Property name="log_path">C:/workspace/logs/</Property>
      <!-- 部署到server上更换为具体的log路径-->
    </Properties>

<Appenders>
<RollingFile name="RollingFile"  fileName="${log_path}/f.log" append="true"
filePattern="${log_path}/f.log.%d{yyyyMMdd}">
<FLayout charset="Shift_JIS" pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} : %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy  interval="1"/>
      <SizeBasedTriggeringPolicy size="1000 MB" /> 
</Policies>
</RollingFile>
</Appenders> <loggers>
   <Logger name="TestLogger" level="DEBUG" additivity="false">  
          <AppenderRef ref="RollingFile" />  
       </Logger>
         <root level="INFO">
         </root>
    </loggers></Configuration>
自己在eclipse上测试运行能输出想要格式的log,打成包部署到server上,出此error RollingFile contains an invalid element or attribute FLayout 的错。请各路大神指教是什么地方出了问题。