system: [SYSTEM]

user: 3. 生成工具的设计 3.1. 工具的目标 这个代码生成工具的目的是生成基于现有成熟的开源框架的REST风格Web API实现。在《Code Generation in Action》一书中，作者Jack Herrington总结代码生成工具的十条准则 [ 6 ] ，在本代码生成工具设计时也尽量遵循下面的准则： 图1. 请求资源存在时响应 图2. 请求资源不存在时响应 1) 重视手工编码。代码生成工具解决的只是避免在重复代码的编写上面浪费过多的时间，在涉及业务细节的代码仍然需要手动进行编写。 2) 先进行手工编码。在生成代码前，可以手工编写目标系统基本的架构。这样可以对所生成的代码有所了解。便于在代码生成以后进行相应的修改。 3) 考虑生成工具使用的语言。根据需求，代码生成工具的目标系统的源码是Java，利用Java的反射机制等技术，可以直接从框架当中获得相应信息，提高因为框架版本变化时生成工具的伸缩性，所以代码生成工具同样使用Java进行实现。 4) 整合到IDE当中。代码生成工具并不能做到一次就可以生成满足需求的系统，代码生成以后仍然需要由开发人员进行适当的修改。以插件形式将代码生成工具与IDE的结合，可以直接将生成代码以IDE工程的形式导入其中，与现有的开发流程结合。 5) 在生成代码当中以注释形式增加警告信息以及修改建议信息。在代码当中增加警告信息可以避免用户破坏代码，同时，对于代码生成工具无法完成的代码，增加引导性的注释，引导开发人员完成这部分代码的编写。 6) 包含文档。代码生成的文档有两种，一种是Javadoc文档，一种是生成的REST API文档。前者通过在源码当中添加满足一定规范的注释，使用工具自动生成。后者则采用模板的形式生成。 7) 不断地维护。新技术和框架的不断出现也促使代码生成工具需要不断去迎合这些新技术的要求。 3.2. 技术选择 Spring Boot是一个用于Spring快速开发的框架，通过少量的配置，利用Spring Boot开发的程序即可使用Spring Framework当中核心的依赖注入，AOP等技术。相比起传统的Spring应用程序开发，Spring Boot摒弃了繁杂的XML和Maven依赖配置，提供一种快速开发Spring程序的途径，在一定程度上解决了一直被开发者诟病的复杂臃肿的配置引起复杂度增加的问题，近年来开始为人们所接受并开始应用至新开发的项目当中。 Spring HATEOAS是Spring的子项目。Spring HATEOAS提供一组快速实现HATEOAS的工具，与Spring MVC共同实现快速开发成熟度高的REST Web Services或者Web API。 JPA (Java Persistence API)是Sun提出在Java SE和Java EE下使用的Java持久化更规范 [ 7 ] ，作为JSR-220实现的一部分，可以脱离EJB 3.0而使用。JPA本身不提供数据持久化的实现，仅仅用于描述Java类到关系型数据库记录之间的映射的规则，数据持久化的实现由第三方开源的ORM框架实现，比如Hibernate。 Hibernate是一个成熟的开源ORM框架，能够从配置文件，或者类当中JPA注解定义的映射配置实现自动的对象与关系型数据库记录之间的相互映射。Hibernate将数据库常见的增删查改封装成一组API，通过这组API即可以完成数据库的相应操作。另外，Hibernate还提供了语法与SQL类似的HQL，在持久化过程中，Hibernate会自动将HQL翻译成SQL语句执行查询。Hibernate框架把数据操作的细节进行了屏蔽，提供的透明的持久化过程，使得程序员在开发的过程不需要过于关心数据库的操作细节 [ 8 ] ，简化程序的开发。 3.3. 软件架构 图3为系统的体系架构，软件的主要逻辑与界面分离，可以通过Swing，Web调用，也可以作为插件的形式引入到开发环境当中。 在该架构当中，数据信息分析模块、代码生成模块和编译打包模块三个模块组成了生成工具。生成 图3. 系统的体系架构 工具没有面向特定的用户界面，核心逻辑与界面逻辑相分离，降低了各自之间的耦合程度，从而降低系统整体的维护成本。该生成工具还可以作为第三方jar文件引入到其他的项目当中，便于未来需求发生变化时快速的重构。 3.4. 模块功能划分 1) 数据信息分析模块：接收用户的输入的信息，这些信息主要是用于描述实体类以及实体类之间的关联关系，数据信息分析模块会根据这些输入信息生成与之相对应的Java类信息。 2) 代码生成模块：该模块接收Java类的元信息，根据这些类信息生成相应的代码和配置系文件，整合成Maven项目。 3) 编译打包模块：将产生的Maven项目编译，打包成可以用于发布的war包。 这三个模块共同完成从用户需求的输入到生成项目的流程，图4描述了整个系统工作时的工作流程。 3.5. 生成工具数据的分析与抽象 该生成工具同时涉及到数据实体、实体之间关联关系信息、元信息等等，数据实体、实体关系是用于接收来自用户输入的数据。这些数据经过数据信息分析模块后会产生相应的类信息，这些类信息会被代码生成模块用于生成Java代码和相应的配置文件。无论是数据信息的数据，还是类信息数据，都采用面向对象的方式封装成各种各样的类。根据需求，把上述的数据抽象成两种类，第一种是用于描述数据信息的类： 数据实体(Entity)、实体之间的关系(EntityRelationship)、实体字段(EntityField)，三者关系如图5所示。 另外一种则是描述代码元信息的类： 类信息(ClassInfo)、字段信息(FieldInfo)、修饰符信息(ModifierInfo)、类型信息(TypeInfo)、注解信息(AnnotationInfo)、注解参数信息(AnnotationParameter)、方法信息(MethodInfo)，图4用于表示这7个类之间的关系。 图6展示了本系统从Java语法要素抽象得到类的类图。ClassInfo表示一个Java的类信息，在Java语言当中，所有的字段、方法等都不能脱离类的存在而存在，抽象得到的类模型必然要以类为中心，这一点在图中则体现为ClassInfo类位于图的中心位置，表示方法和字段的MethodInfo类和FieldInfo类在ClassInfo中以字段的形式存在，表示这个类中定义的方法和字段。图中的AnnotationInfo表示注解信息。注解是Java在JDK1.5版本开始引入的一种在在代码当中的特殊标记。注解信息可以运用在类，字段和方法级别上，所以MethodInfo、FieldInfo和ClassInfo类当中都含有一个AnnotationInfo类型的集合类，用于储存这个方法、字段和类级别上的注解信息。Java是一种强类型的面向对象编程语言，类型和访问 图4. 系统工作流程 图5. 数据信息类的类图 图6. 元信息类的类图 控制机制是Java当中十分重要的内容。图6中TypeInfo类和ModifierInfo类分别用于表示类型和访问控制的访问修饰符，这两项信息在Java当中是极其重要的信息。其中，类、方法和字段都涉及到访问修饰符的信息，所以在这三者当中都含有一个ModifierInfo对象实例。方法、字段和注解都涉及类型信息，这三者对象当中都含有一个TypeInfo对象实例。 这些用于存放类信息的类可以根据Java语法规则的层次关系组织成树状的结构。树的根节点是表示类信息的ClassInfo对象，这个类下面的字段，方法都是这个根节点的子节点。字段和方法结点下面有这个字段的类型、修饰符信息等，这些信息对应的对象均以被修饰对象结点的子结点的形式存在。图7为一个带有JPA注解的Java类对应的类信息结构。 通过构建这样的一个树状的结构，可以层次化地将一个类的字段，方法，注解等信息进行完整描述。按树状的类信息组织，在代码生成阶段，把整个类的代码生成工作拆分成很多的注解代码生成，字段声明语句生成等等大量的工作，避免了整个系统的复杂度集中在少数的逻辑代码当中引起的系统复杂度的增加。