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

7

我刚刚迁移到了Tomcat 8。以前我使用系统属性org.apache.el.parser.COERCE_TO_ZERO=false,这样空字符串、数字、布尔值等会被视为null

在Tomcat 8中,EL 3.0应该是默认的,但实际上它将null字符串转换为空字符串""在JSF方面。

这应该是一个错误,应该得到纠正,但我无法在TomEE快照(Tomcat 8.0.27.0,MyFaces 2.2.8)中使其工作。


1
相关吗?https://dev59.com/rXzaa4cB1Zd3GeqPS633#31020728 - BalusC
是的,确实,谢谢! - cocorossello
1个回答

11

这是 EL 3.0 规范中的一个错误。自从 EL 3.0 开始,由于过度热衷于修复 JSP spec issue 184,在模型值设置器被调用之前,null 将被强制转换为空字符串。基本上,javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL 不再起作用了。另请参见 JSF issue 3071EL spec issue 18

基本上,要解决这个问题,您需要提供自定义EL解析器,或者替换/升级EL实现(或者只是整个服务器,因为它实际上是提供EL的)。您链接的Tomcat issue 57309与此特定的EL 3.0问题无关,即从null强制转换为空字符串,它只与Tomcat对自定义EL解析器的无知有关。
您可以通过两种方式解决此问题:
  1. Provide a custom EL resolver like below. Make sure that you use Tomcat 8.0.16 or newer, as specified in the Tomcat issue report you found.

     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.
         }
    
     }
    

    In order to get it to run, register as below in faces-config.xml:

     <application>
         <el-resolver>com.example.EmptyToNullStringELResolver</el-resolver>
     </application>
    

  2. Or, switch to Oracle EL. They already fixed it in version 3.0.1 b05 which has been available since 7 July 2014 (just pick the newest one which is 3.0.1-b10 as of today).

    Just drop javax.el.jar file in /WEB-INF/lib and add the below context param to web.xml in order to instruct MyFaces to use the Oracle EL implementation instead:

     <context-param>     
         <param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
         <param-value>com.sun.el.ExpressionFactoryImpl</param-value>   
     </context-param>
    

    In case you're using Mojarra, use param name com.sun.faces.expressionFactory.

由于我自己有些疑惑,因此写了一篇博客来澄清:空字符串的疯狂之谜

###另请参阅:


只有第一种解决方案适用于我。我正在使用joinfaces:https://github.com/joinfaces/joinfaces - CelinHC
1
我最近尝试通过将Tomcat 8.5升级到9.0.7(Weld 3,Mojarra 2.3和Jersey 2.26)来从EE7升级到EE8。突然间,这个空/空字符串开始影响我的视图参数。我试图理解这篇帖子中的建议,但失败了。我希望BalusC能够阐明我可能会遇到的问题,因为我本以为这些问题早就消失了。 - matsa
从Tomcat 8.5升级到9.0.12,上面的解决方案#2不再适用于我。然而,返回https://stackoverflow.com/users/157882/balusc EmptyToNullStringConverter发布在这里http://balusc.omnifaces.org/2015/10/the-empty-string-madness.html会导致在表单提交时将空字符串设置为null。 - Ted Spradley
由于我的依赖于PrimeFaces,我无法简单地添加自定义EL解析器:org.primefaces.application.exceptionhandler.PrimeExceptionHandlerELResolver。 - matsa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接