Tomcat 8(和 9)强制行为,空字符串被错误地设置为空字符串

Posted

技术标签:

【中文标题】Tomcat 8(和 9)强制行为,空字符串被错误地设置为空字符串【英文标题】:Tomcat 8 (and 9) coerce behaviour, null strings are incorrectly set as empty strings 【发布时间】:2016-01-24 20:53:07 【问题描述】:

我刚刚迁移到 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)。

【问题讨论】:

相关? ***.com/a/31020728 是的,确实,谢谢! 【参考方案1】:

这是 EL 3.0 规范中的一个错误。从 EL 3.0 开始,由于过度修复了 JSP spec issue 184,null 将在调用模型值设置器之前被强制返回为空字符串。基本上,javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL 不再有任何影响。另见JSF issue 3071 和EL spec issue 18。

基本上,要解决此问题,您需要提供自定义 EL 解析器,或者将 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 中修复了它,它自 2014 年 7 月 7 日起可用(只需选择 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

【讨论】:

只有第一个解决方案对我有用。我正在使用连接面:github.com/joinfaces/joinfaces 我最近尝试通过将 Tomcat 8.5 迁移到 9.0.7(Weld 3、Mojarra 2.3 和 Jersey 2.26)从 EE7 升级到 EE8。突然,这个空/空字符串开始使用我的视图参数进行混乱。我试图理解这篇文章中的建议,但失败了。我希望 BalusC 能够阐明我可能正在经历的事情,而我原本以为现在这一切都已经过去了。 从 Tomcat 8.5 升级到 9.0.12,上面使用 sun jar 的解决方案 #2 不再适用于我。但是,返回此处发布的***.com/users/157882/balusc EmptyToNullStringConverter balusc.omnifaces.org/2015/10/the-empty-string-madness.html 会导致表单提交时将空字符串设置为 null。 由于我对 PrimeFaces 的依赖,我无法简单地添加自定义 EL 解析器:org.primefaces.application.exceptionhandler.PrimeExceptionHandlerELResolver

以上是关于Tomcat 8(和 9)强制行为,空字符串被错误地设置为空字符串的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat 8 - LDAP:NameNotFoundException 错误代码 32,剩余名称为空字符串

为啥当 hjust 和 vjust 是字符串时 geom_text() 会抛出强制错误?

使用 Safari 错误在 websockets 和 Tomcat 上强制使用 SSL

Tomcat 8 (jvisualvm) 下的奇怪内存行为

protobuf转换的数组传进scoket中类型转换错误

如何强制 IIS7 返回 Tomcat 错误响应