如何关闭Tomcat8 AccessLogValve日志的双引号自动转义功能
解决Tomcat8 AccessLogValve双引号自动转义问题
针对Tomcat 8.5及以上版本(含部分8.0后期兼容版本)
Tomcat从8.5.0版本开始,AccessLogValve新增了escape属性,可直接关闭双引号的自动转义功能。只需在你的server.xml配置中添加escape="false"参数即可:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="/home1/irteam/apps/tomcat/logs" prefix="accesslog." resolveHosts="false" fileDateFormat="yyMMdd" pattern="%{timestamp}r, "data":%{request_data}r" requestAttributesEnabled="true" encoding="utf-8" escape="false" />
添加后重启Tomcat,日志中的双引号就不会被自动转义了。
针对Tomcat 8.0.x版本(无escape属性)
如果你的Tomcat是8.0.x分支(未包含escape属性的版本),有两种可行方案:
方案1:升级Tomcat版本
直接升级到Tomcat 8.5或更高版本,即可使用上述escape="false"配置解决问题,这是最简便的方式。
方案2:自定义AccessLogValve子类
如果无法升级,可以自定义一个Valve类,重写日志生成逻辑以去除转义:
- 编写自定义Valve代码:
import org.apache.catalina.valves.AccessLogValve; import org.apache.catalina.connector.Request; import java.util.regex.Matcher; import java.util.regex.Pattern; public class UnescapedAccessLogValve extends AccessLogValve { private static final Pattern ESCAPED_QUOTE = Pattern.compile("\\\\\""); @Override protected void addRequestAttributes(StringBuilder buf, Request request) { // 先调用父类方法生成带转义的内容 super.addRequestAttributes(buf, request); // 将转义后的\"替换回原始的" String processed = ESCAPED_QUOTE.matcher(buf.toString()).replaceAll("\""); buf.setLength(0); buf.append(processed); } }
- 编译该类,将生成的
.class文件打包成JAR,放入Tomcat的lib目录下。 - 修改
server.xml中的Valve配置,将className改为自定义类的全限定名:
<Valve className="com.yourpackage.UnescapedAccessLogValve" directory="/home1/irteam/apps/tomcat/logs" prefix="accesslog." resolveHosts="false" fileDateFormat="yyMMdd" pattern="%{timestamp}r, "data":%{request_data}r" requestAttributesEnabled="true" encoding="utf-8" />
为什么业务代码中处理无效?
你之前在Java代码中尝试替换转义符无效,是因为双引号转义是AccessLogValve在生成日志时自动执行的——请求属性本身存储的是未转义的原始数据,但Valve在将其写入日志时会自动添加转义,因此业务代码中修改属性值无法阻止这一过程,必须在Valve层面处理。
内容的提问来源于stack exchange,提问作者user10953698
相关产品推荐
相关产品推荐

