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 解析器的无知有关。

您可以通过两种方式解决这个问题:

  1. 提供如下所示的自定义 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>
    

  2. 或者,切换到 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