内容简介:就像维基百科建议的那样,KISS是一个缩写保持简单,愚蠢作为美国海军在1960年提出的设计原则.KISS原则指出,如果保持简单而不是复杂化,大多数系统都能发挥最佳作用; 因此,简单性应该是设计中的关键目标,并且应该避免不必要的复杂性。
就像维基百科建议的那样,KISS是一个缩写
保持简单,愚蠢
作为美国海军在1960年提出的设计原则.KISS原则指出,如果保持简单而不是复杂化,大多数系统都能发挥最佳作用; 因此,简单性应该是设计中的关键目标,并且应该避免不必要的复杂性。
根据我的经验,我研究了许多类型的技术,有机会检查源代码,一般来说,从客户端(可以是SPA或本机应用程序)和服务器端开发应用程序。 。依靠这样的经历,我想开发一个简单的架构,包括尊重基本的格局在CRUD上下文。我将说明这个架构的基础,作为我所有项目的起点。
在设计中我记住了KISS概念,从这个角度来看,我将提供5层,称为层,具有特定的职责任务:
- 前端
- API
- 商业逻辑
- 集成层
- DAO
我使用多层架构模型。列表中的层顺序与信息流严格关联,从前端一直到达DAO!
本文引用的项目可通过以下链接下载: https://github.com/paspao/springboot-kiss-architecture
git clone https://github.com/paspao/springboot-kiss-architecture
该项目使用maven(即父类和子类)进行管理; 即使在Angular中开发的前端被包含在maven构建阶段中以创建单个工件(下面的FRONTEND段中提供了更多详细信息)。
为了深入了解每一层,我更喜欢使用BottomUp方法,所以让我们从数据开始。
DAO
数据访问对象。我在谈论CRUD应用程序,即要收集和处理的数据。这个模块代表了最深刻的一点。该层执行数据,它描述实体和访问逻辑。注意:插入,修改,删除和显示数据的简单数据访问逻辑,不与任何其他层绑定; 它是最深层的,并且它与它的任何兄弟都没有依赖关系,它不处理应用程序的特定方面,例如授权,事务或其他:也只是访问数据。在Springboot上下文中,我正在执行实体和存储库范例。
@Configuration @ComponentScan(<font>"org.ska.dao"</font><font>) @EntityScan(basePackages = {</font><font>"org.ska.dao.entity"</font><font>}) @EnableJpaRepositories(basePackages = {</font><font>"org.ska.dao.repository"</font><font>}) @EnableAutoConfiguration @EnableTransactionManagement <b>public</b> <b>class</b> KissDaoConfiguration { } </font>
所以我定义了组件,实体和存储库的位置。此外,我启用了事务,因此使用DAO模块的任何人都不必担心配置DAO模块的方面。
集成
简单的CRUD数据管理是不够的:我们可能需要与不依赖于我们数据的其他系统(例如JAX-WS或JAX-RS服务)或具有不同协议的特定打印系统等进行互操作。此组件包括所有这些交互/集成都没有对应用程序上下文的特定绑定,以保证您具有非常高的可重用性(如DAO模块,此层也是叶类型)。
@Configuration @ComponentScan(basePackages = {<font>"org.ska.integration.beans"</font><font>}) <b>public</b> <b>class</b> KissIntegrationConfiguration { @Bean <b>public</b> GeoApiContext geocoder(){ GeoApiContext context = <b>new</b> GeoApiContext.Builder() .apiKey(</font><font>"Your apikey"</font><font>) .build(); <b>return</b> context; } } </font>
这里我展示了模块配置的中心点:只有一个对服务定义的引用和第三方服务的实例(GeoApiContext)。
业务逻辑
稍后识别要处理的数据时,每个应用程序必须处理定义到DAO层中的实体之间的交互逻辑。您必须将用户需求与应用程序逻辑相结合,将它们分解,然后向上层公开简单且可读的签名。因此,这一层允许开发人员进行一些处理,而无需详细说明数据库的结构或下面的集成。
我们在这里发现DTO的定义和用法有助于掩盖存储在数据库系统或各种集成bean中的数据:为什么?
有一些原因:首先,它是一种隐藏敏感数据的信息形式(例如密码,时间戳或数据一致性所需的其他信息,但对最终用户没有)。如果需要详细说明返回的数据(如从多个源组合的数据),DTO有助于以合适的方式构建这些数据。
另一个方面是数据的序列化:在某些上下文中,您必须转换数据库中存在的信息,以使其可用于人类。因此,开发人员必须“污染” 实体使用序列化逻辑,其目的应该只是表示数据,例如:数据库系统上的DATE字段可能是一个数字,但我们以可打印的方式表示它,所以我们可能会使用格式化注释; 这是一个解决方案!但在这种情况下,我们将序列化的各个方面链接到一个实体,从长远来看,这个解决方案将导致无法使用的代码。哈罗德·阿贝尔森说:
必须编写程序供人们阅读,并且只有程序才能执行。
DTO允许面对列出的问题,创建类似“缓冲区”的东西,因此更松散耦合和更多可重用性。
总而言之,BUSINESS LOGIC与DAO层和INTEGRATION层进行通信,创建协同作用并在它们之间进行交互。此外,它将逻辑和数据转换带入DTO,可供其他层使用。警告:业务逻辑层使用定义的DTO,同样适用于返回的数据。它们绝不是其他层中定义的对象,因此要确保我们上面所说的内容并且能够处理返回的数据。
该层的另一个特征是事务管理:由于它实现了业务逻辑,因此能够确定对数据的操作是否成功,因此定义了操作的“ 事务性 ”。
以下是业务逻辑层的@Configuration:
@Configuration @ComponentScan(basePackages = {<font>"org.ska.business"</font><font>}) @Import({KissDaoConfiguration.<b>class</b>, KissIntegrationConfiguration.<b>class</b>}) <b>public</b> <b>class</b> KissBusinessConfiguration { @Bean <b>public</b> Mapper dozerMapper(){ Mapper dozerBeanMapper = DozerBeanMapperBuilder.buildDefault(); <b>return</b> dozerBeanMapper; } } </font>
它是唯一一个直接链接到DAO和INTEGRATION层的模块,因此必须导入配置才能使用它们。此外,为了加快实体和DTO之间的映射,使用为此而生成的框架是一种很好的做法,避免了长期和不可读的setter和getter代码块; 在我的例子中,我使用了一个名为Dozer的映射框架。
API
在这层中,呈现逻辑,它代表了我们应用程序的入口点,至少从服务器的角度来看。JAX-RS或JAX-WS等服务的定义主要是以XML,JSON或其他方式呈现数据。它仅与BUSINESS LOGIC层进行对话:服务只调用Business层提供的一个或多个服务,它永远不会直接使用INTEGRATION或DAO层,也不会使用其中定义的对象,以避免紧密耦合和意大利面条代码。
它涉及身份验证和授权的管理:这里可以确定谁可以执行操作:在下面的层中要复杂得多,或者确定哪些角色尚不可知的信息。
API总是需要一些文档:缺乏REST世界之一是缺少这些服务的通用描述符。保证这方面的技术是Swagger(现在是OpenAPI):它允许记录API,但是生成的文档也可以重用来生成客户端部分,因此不仅仅是描述性的部分。例如,在我的情况下,带有REST服务的通信层完全由服务的Swagger描述生成:在FRONTEND模块中,有一个remote-services文件夹,其中包含工具: https://editor.swagger.io .
在api层的配置类中,我导入业务层并设置Swagger文档的生成。
@Configuration @Import(KissBusinessConfiguration.<b>class</b>) @EnableSwagger2 <b>public</b> <b>class</b> KissApiConfiguration { @Autowired <b>private</b> Environment env; @Bean <b>public</b> Docket api() { <b>return</b> <b>new</b> Docket(DocumentationType.SWAGGER_2) .select() <font><i>//.apis(RequestHandlerSelectors.any())</i></font><font> .apis(RequestHandlerSelectors.basePackage(</font><font>"org.ska.api.web"</font><font>)) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); } <b>private</b> ApiInfo apiInfo() { <b>return</b> <b>new</b> ApiInfo( </font><font>"Contact management REST API"</font><font>, </font><font>"API"</font><font>, env.getProperty(</font><font>"info.version"</font><font>), <b>null</b>, <b>new</b> Contact(</font><font>"Pasquale Paola"</font><font>, </font><font>"https://www.linkedin.com/in/pasqualepaola/"</font><font>, </font><font>"pasquale.paola@gmail.com"</font><font>), <b>null</b>, <b>null</b>, Collections.emptyList()); } } </font>
前端
它代表单页应用程序:这种类型的应用程序必须与应用程序完全分离,并且Rest技术的使用已经保证了这一方面,但有必要注意与远程服务的通信是如何实现的。我经常陷入非常糟糕的组织和管理用于调用远程服务的各种HTTP客户端,我的意思是在整个应用程序中找到的引用。
为了解决这个问题并使SPA与代表与远程服务通信的所有内容严格分开,如前所述,我使用Swagger技术生成一个允许与Rest API通信的存根。所以开发人员将使用Swagger生成的东西,主要是因为它提供了大量现成的代码,具有不同的使用选项,而你不再需要重写它。此外,逻辑将在其他地方实现,因为远程通信部分(Stub)将不断重新生成,并且开发人员不会梦想在可能被覆盖的源中实现自己的逻辑(我希望)。
为了确保用Angular编写的应用程序可以包含在Maven项目的构建周期中,我确保通过添加pom.xml文件即使FRONTEND也成为Maven模块。这个模块不会产生任何工件,所以包装将是pom类型,但是这样我就可以将它插入到maven构建中并与其兄弟姐妹创建依赖关系。为了能够在Maven上下文中集成Angular构建,我使用了一个名为frontend-maven-plugin的插件:它允许安装Node和Npm实例
<execution> <id>install node and npm</id> <goals> <goal>install-node-and-npm</goal> </goals> <phase>generate-resources</phase> </execution> <execution> <id>npm install</id> <goals> <goal>npm</goal> </goals> <configuration> <arguments>install</arguments> </configuration> </execution>
以及随后调用Angular CLI来管理依赖关系并构建。
<execution> <id>npm build</id> <goals> <goal>npm</goal> </goals> <phase>generate-resources</phase> <configuration> <arguments>run build</arguments> </configuration> </execution>
当调用Npm构建任务时,控件将从Angular CLI中获取,如package.json中所述:
... <font>"build"</font><font>: </font><font>"ng build --prod --progress --build-optimizer --delete-output-path --base-href /kiss/ui/ --output-path dist/resources/static/ui"</font><font> ... </font>
输出路径设置为dist / resources / static / ui,路径dist / resources也配置为前端模块的资源。结合下面的层API配置,它允许在Springboot应用程序中注入Angular构建的结果。在输出路径(package.json 中的build命令)中有一个特殊目录 ... / static / ...,其中一个是Springboot允许定义静态内容的目录。
<resources> <resource> <directory>../frontend/dist/resources</directory> </resource> <resource> <directory>src/main/resources</directory> <filtering><b>true</b></filtering> </resource> </resources> ...
Build
mvn clean install
Run
java -jar api/target/api-0.0.1-SNAPSHOT.jar
http://localhost:8080/kiss/
点击标题见原文!以上所述就是小编给大家介绍的《Kiss架构:Springboot + Angular - Pasquale Paola》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 『互联网架构』软件架构-分布式架构(14)
- 『互联网架构』软件架构-电商系统架构(上)(69)
- 『互联网架构』软件架构-电商系统架构(中)(70)
- 『互联网架构』软件架构-电商系统架构(下)(71)
- 『互联网架构』软件架构-电商系统架构发展历程(68)
- 阿里P8架构师谈:淘宝技术架构从1.0到4.0的架构变迁!附架构资料
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。