Tomcat 8(和 9)强制行为,空字符串被错误地设置为空字符串
Tomcat 8 (and 9) coerce behaviour, null strings are incorrectly set as empty strings
我刚迁移到 Tomcat 8。我以前使用系统 属性 org.apache.el.parser.COERCE_TO_ZERO=false
所以空字符串、数字、布尔值等被视为 null
.
在Tomcat 8, EL 3.0 中,它应该是默认的,但实际上它在 JSF 端将 null
字符串转换为空字符串 ""
。
它应该是 bug 并且它应该被更正但是我无法让它在 TomEE 快照中工作(Tomcat 8.0.27.0,MyFaces 2.2.8 ).
这是 EL 3.0 规范中的错误。自 EL 3.0 以来,由于 JSP spec issue 184, null
will be coerced back to empty string before the model value setter is invoked. Basically, the javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL
doesn't have any affect anymore. See also JSF issue 3071 and EL spec issue 18.
的过度修复
基本上,要解决这个问题,您需要提供自定义 EL 解析器,或者 replace/upgrade EL 实现(或者只是整个服务器,因为它实际上是开箱即用的提供 EL 的服务器)到带有错误修正的版本。您链接的 Tomcat issue 57309 与这个特定的 EL 3.0 问题无关,即从 null 到空字符串的不必要强制转换,它仅与 Tomcat 对自定义 EL 解析器的无知有关。
您可以通过两种方式解决这个问题:
提供如下所示的自定义 EL 解析器。确保您使用 Tomcat 8.0.16 或更新版本,如您找到的 Tomcat 问题报告中所述。
public class EmptyToNullStringELResolver extends ELResolver {
@Override
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return String.class;
}
@Override
public Object convertToType(ELContext context, Object value, Class<?> targetType) {
if (value == null && targetType == String.class) {
context.setPropertyResolved(true);
}
return value;
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
return null;
}
@Override
public Class<?> getType(ELContext context, Object base, Object property) {
return null;
}
@Override
public Object getValue(ELContext context, Object base, Object property) {
return null;
}
@Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
return true;
}
@Override
public void setValue(ELContext context, Object base, Object property, Object value) {
// NOOP.
}
}
为了达到运行,请在faces-config.xml
中进行如下注册:
<application>
<el-resolver>com.example.EmptyToNullStringELResolver</el-resolver>
</application>
或者,切换到 Oracle EL。他们已经在 version 3.0.1 b05 which has been available since 7 July 2014 (just pick the newest 中修复了它,即今天的 3.0.1-b10)。
只需将 javax.el.jar
文件放入 /WEB-INF/lib
并将以下上下文参数添加到 web.xml
以指示 MyFaces 使用 Oracle EL 实现:
<context-param>
<param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
如果您使用的是 Mojarra,请使用参数名称 com.sun.faces.expressionFactory
。
由于我自己也一时感到困惑,所以我写了一篇博客来解决问题:The empty String madness。
###另见:
- javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL does not work anymore since Java EE 7 / EL 3.0
我刚迁移到 Tomcat 8。我以前使用系统 属性 org.apache.el.parser.COERCE_TO_ZERO=false
所以空字符串、数字、布尔值等被视为 null
.
在Tomcat 8, EL 3.0 中,它应该是默认的,但实际上它在 JSF 端将 null
字符串转换为空字符串 ""
。
它应该是 bug 并且它应该被更正但是我无法让它在 TomEE 快照中工作(Tomcat 8.0.27.0,MyFaces 2.2.8 ).
这是 EL 3.0 规范中的错误。自 EL 3.0 以来,由于 JSP spec issue 184, null
will be coerced back to empty string before the model value setter is invoked. Basically, the javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL
doesn't have any affect anymore. See also JSF issue 3071 and EL spec issue 18.
基本上,要解决这个问题,您需要提供自定义 EL 解析器,或者 replace/upgrade EL 实现(或者只是整个服务器,因为它实际上是开箱即用的提供 EL 的服务器)到带有错误修正的版本。您链接的 Tomcat issue 57309 与这个特定的 EL 3.0 问题无关,即从 null 到空字符串的不必要强制转换,它仅与 Tomcat 对自定义 EL 解析器的无知有关。
您可以通过两种方式解决这个问题:
提供如下所示的自定义 EL 解析器。确保您使用 Tomcat 8.0.16 或更新版本,如您找到的 Tomcat 问题报告中所述。
public class EmptyToNullStringELResolver extends ELResolver { @Override public Class<?> getCommonPropertyType(ELContext context, Object base) { return String.class; } @Override public Object convertToType(ELContext context, Object value, Class<?> targetType) { if (value == null && targetType == String.class) { context.setPropertyResolved(true); } return value; } @Override public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) { return null; } @Override public Class<?> getType(ELContext context, Object base, Object property) { return null; } @Override public Object getValue(ELContext context, Object base, Object property) { return null; } @Override public boolean isReadOnly(ELContext context, Object base, Object property) { return true; } @Override public void setValue(ELContext context, Object base, Object property, Object value) { // NOOP. } }
为了达到运行,请在
faces-config.xml
中进行如下注册:<application> <el-resolver>com.example.EmptyToNullStringELResolver</el-resolver> </application>
或者,切换到 Oracle EL。他们已经在 version 3.0.1 b05 which has been available since 7 July 2014 (just pick the newest 中修复了它,即今天的 3.0.1-b10)。
只需将
javax.el.jar
文件放入/WEB-INF/lib
并将以下上下文参数添加到web.xml
以指示 MyFaces 使用 Oracle EL 实现:<context-param> <param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name> <param-value>com.sun.el.ExpressionFactoryImpl</param-value> </context-param>
如果您使用的是 Mojarra,请使用参数名称
com.sun.faces.expressionFactory
。
由于我自己也一时感到困惑,所以我写了一篇博客来解决问题:The empty String madness。
###另见:
- javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL does not work anymore since Java EE 7 / EL 3.0