返回

Struts 升级 '_typeConverter' 异常详解与解决

java

Struts升级中的 “_typeConverter” 异常

在Struts应用升级后,可能会遇到java.lang.IllegalArgumentException: unknown reserved key '_typeConverter' 异常,尤其是在从较低版本升级到较高版本时。此错误通常在登录或者其他涉及到Ognl表达式处理的过程中出现。问题的核心在于Struts2新版本中,OGNL库的配置或用法有所改变。旧版本的代码可能存在一些在新版本中不被允许的用法,导致框架无法正确解析。

原因分析

这个异常表示,当Struts2框架尝试通过OGNL设置属性时,遇到了一个它不识别的保留 “_typeConverter”。在Struts2中,OGNL常用于在运行时动态访问和修改对象属性,以及在表单和Action之间传输数据。 _typeConverter 用于处理类型转换逻辑, 但新版本的Struts 框架对保留关键字的定义有所改变,使得直接通过OGNL设置 '_typeConverter' 会引发这个错误。这个错误通常发生在 Struts 结果处理或者值栈操作期间,当 Struts尝试将 typeConverter 应用到特定的结果配置时。

解决方案

主要有以下几种方式解决这个错误:

1. 移除不必要的属性注入:

检查Struts的配置文件(例如:struts.xml)和自定义的拦截器或者结果类,看是否有手动设置typeConverter的情况。可能某个Result 配置、或是其他的对象创建流程,直接或间接试图将名为 _typeConverter 的参数传给 OGNL 。这种情况下,删除相关配置或者修改逻辑是解决问题的关键。Struts框架内部有默认的机制处理类型转换,不应手动进行干预, 除非是非常特殊的情景。

示例:

<result name="success" type="redirectAction">
   <param name="actionName">home</param>
   <!-- 错误配置示例 - 移除  _typeConverter 相关配置  -->
  <!--<param name="_typeConverter">someTypeConverter</param>-->
</result>
  • 操作步骤:
    1. 定位 struts.xml, 或其他的拦截器配置文件等地方。
    2. 搜索 _typeConverter
    3. 删除该参数配置。
    4. 重启服务器并测试。

2. 修改OGNL上下文:

有时,问题的根源可能在于更底层的地方,如自定义的 TypeConverter 实现。新版的OGNL版本在对typeConverter上下文的管理上有所调整。如果确实需要用到自定义类型转换器,不要尝试直接通过OGNLContext操作_typeConverter 。应确保遵循Struts官方的TypeConverter注册机制。使用 @TypeConversion 注解或通过在配置文件中注册 xwork-conversion.xml,使得框架能正确的处理转换逻辑, 而不是直接设置 OGNL 的上下文。

示例:
a. 使用注解注册:

import org.apache.struts2.util.StrutsTypeConverter;

import java.util.Map;

@TypeConversion(converter=MyTypeConverter.class)
public class MyAction extends ActionSupport{
  //...
    private String myCustomType;

   // getter 和 setter
}
// 实际的TypeConverter 类,  避免手动设置 _typeConverter
import com.opensymphony.xwork2.conversion.TypeConversionException;
import org.apache.struts2.util.StrutsTypeConverter;
import java.util.Map;

public class MyTypeConverter extends StrutsTypeConverter{

    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {

        if (values == null || values.length == 0){
             return null;
        }

         // 执行自定义的转换逻辑
        String val = values[0];
        try {
           return process(val)
        }catch(Exception e)
        {
            throw new TypeConversionException("error conversion: " + e.getMessage());
        }
    }


    @Override
    public String convertToString(Map context, Object o) {

         if(o ==null){
          return "";
         }
        // 执行从对象到字符串的转换逻辑
        return o.toString();
    }

  public String process(String str)
    {
       // 自定义的转换过程
      return str + "_processed";

   }
}

b. 在xwork-conversion.xml配置:

<!DOCTYPE converters PUBLIC "-//OpenSymphony Group//XWork Converter 1.1//EN" "http://www.opensymphony.com/xwork/xwork-conversion-1.1.dtd">

<converters>
     <converter name="myCustomType" class="MyTypeConverter"/>
</converters>
  • 操作步骤:
    1. 实现自定义的类型转换类,确保不要直接操作 Ognl 上下文的 _typeConverter
    2. 通过 Struts2 提供的机制(注解,xml配置) 注册你的转换器。
    3. 清理编译环境,并重新部署应用。
    4. 测试应用。

3. 版本回退(临时方案):

如果升级造成的配置或代码改动量太大,短期内难以找出具体问题所在,可以考虑暂时降回Struts版本至旧版本 (Struts 2.3.10)。这样做可以保证应用的正常运转。不过此方案治标不治本。当确认问题源头,需要立刻完成最终的升级工作。

  • 操作步骤:
    1. 删除当前项目中所有的Struts库 (jar 文件)。
    2. 加入旧版本 (2.3.10) 的Struts 库文件。
    3. 测试应用确保运行正常。

其他建议:

  • 升级Struts等类库之前,应该充分测试, 包括单元测试以及集成测试,特别是涉及到 OGNL 或类型转换的部分。
  • 仔细阅读新版本Struts的文档,了解配置和使用上的差异。
  • 升级步骤,建议遵循 小版本递进升级的策略,并伴随大量的回归测试,避免一次性升级过大,造成问题难以定位和解决。
  • 可以关注Struts社区,通常一些常见的问题都会在社区有讨论记录,通过查询或发帖提问也能获取帮助。

以上措施可能能够解决或绕开 java.lang.IllegalArgumentException: unknown reserved key '_typeConverter' 错误,提升应用稳定性,并为升级打好基础。遇到类似问题,应该根据实际代码,配置文件进行排查, 灵活运用不同解决方案。