暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

为什么阿里不建议在返回对象中使用枚举

JAVA前线 2020-05-11
483

公众号IT徐胖子原创本文,请勿转载


1 文章概述

在阿里巴巴开发手册中有这样一条强制规定值得大家关注:【强制】二方库里可以定义枚举类型,参数可以使用枚举类型,但是接口返回值不允许使用枚举类型或者包含枚举类型的POJO对象。

我们在日常开发中服务生产者会提供二方包给消费者引用,在返回对象中属性不能包含枚举类型,这是一个强制要求。我们通过一个实例分析:为什么阿里巴巴开发手册中会有这样一条强制要求。


2 生产者实例

服务生产者提供1.0版本二方包:

    public class StudentDTO implements Serializable {
    private Long id;
    private String name;
    private HobbyEnum hobbyEum;
    }


    public enum HobbyEnum {
    FOOTBALL(1),
    BASKETBALL(2)
    }

    服务生产者发布RPC服务:

      public class StudentServiceImpl implements StudentService {
      public StudentDTO queryStudentById(Long id) {
      StudentDTO student = new StudentDTO();
      student.setId(100L);
      student.setName("微信公众号「IT徐胖子」");
      student.setHobbyEnum(HobbyEnum.FOOTBALL);
      return student;
      }
      }


      3 消费者实例

      服务消费者引入生产者1.0版本二方包:

        <dependency>
        <groupId>com.test.xpz</groupId>
        <artifactId>xpz-student-api</artifactId>
        <version>1.0</version>
        </dependency>

        服务消费者以如下代码调用可以得到正确结果,到目前为止都没有问题:

          public class StudentTest {
          @Resource
          private StudentService studentService;

          public void getStudent() {
          StudentDTO student = studentService.queryStudent(100L);
          System.out.println(student);
          }
          }


          4 发现问题

          服务生产者枚举类新增信息并且升级二方包至2.0版本:

            public enum HobbyEnum {
            FOOTBALL(1),
            BASKETBALL(2),
            SWIMMING(3)
            }

            服务生产者修改提供服务代码实现

              public class StudentServiceImpl implements StudentService {
              public StudentDTO queryStudentById(Long id) {
              StudentDTO student = new StudentDTO();
              student.setId(100L);
              student.setName("微信公众号「IT徐胖子」");
              student.setHobbyEnum(HobbyEnum.SWIMMING);
              return student;
              }
              }

              服务消费者不做任何改动保持引用1.0版本二方包。现在生产者返回结果包含SWIMMING信息,但是1.0版本二方包根本没有这个值,所以会引起序列化异常。这是一个非常严重的问题,消费者在没有做任何改动的情况下依然出现异常。

                hessian.io.HessianFieldException: 
                Caused by: java.lang.IllegalArgumentException: No enum constant com.xpz.student.HobbyEnum.SWIMMING


                5 解决方案

                StudentDTO属性全部改为基本类型或者基本类型包装类就可以避免这类严重错误,消费者可以使用HobbyEnum枚举类去翻译hobby这个数值的含义。这个问题非常容易被忽略值得大家关注。

                  public class StudentDTO implements Serializable {
                  private Long id;
                  private String name;
                  private int hobby;
                  }



                  长按二维码关注更多精彩文章

                  文章转载自JAVA前线,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论