RESTful microPos-AW05

作业项目地址

Question:

REST

官方文档

课程对应样例讲解:spring-projects/spring-hateoas-examples

REST目标之一是解决接口不规范的问题;ResponseEntity RESTful架构下返回的标准的数据接口,可以被网页解析,并且传入http状态代码。

annotation类型与get/post等http方法对应

配合open-api:规定程序接口

DTO

martinFowler的解读

Entity To DTO Conversion for a Spring REST API

The DTO Pattern (Data Transfer Object)

不同类型的数据进行综合——为了减少传输时间,把多次请求(不同类型)的数据合并在一起传输,mapper主要用来处理此类转换。

map struct:把服务内的数据结构映射成服务间通讯需要的数据结构。数据可能被重构,不一定与服务内的数据结构保持一致。

spring-petclinic-microservice 虽然有dto文件夹 但是并没有用到map 主要是抽离gateway和biz层的数据交换

pos-api —— 服务间通用api

open-api 官方说明+参数说明

baeldung

前端页面—— 先返回json格式的数据 可以裸奔

把所需的所有api统一建立一个文件夹,注意不是单独服务所以不要用spring-plugin打包,把它作为依赖在其他服务中引用,或者在sprng-plugin配置中选择忽略main函数

1
2
3
4
5
6
7
8
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.2.RELEASE</version>
<configuration>
<skip>true</skip><!--不需要main类打包-->
</configuration>
</plugin>

把pos-api安装到本地,

1
mvn install:install-file -Dfile=../pos-api/target/pos-api-0.0.1-SNAPSHOT.jar -DgroupId=com.micropos -DartifactId=micropos -Dversion=0.0.1

其他模块就可以直接在依赖中引用:

1
2
3
4
5
<dependency>
<groupId>com.micropos</groupId>
<artifactId>pos-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

把products原本有的open-api移除,改用统一的pos-api

修改顶层项目中的pom文件,否则会自动给下层指定默认位置,即上层pom的设置优先于下层的pom设置。

对于曾经有过open-api的products:去掉open-api的plugin换成spring。

原本products中关于open-api的import也要重写,包名与依赖中写的保持一致。

product

先尝试启动product作为一个独立服务,openapi使用的时候遇到如下报错:

required a bean of type that could not be found.

搜索后,在ProductsApplication文件中修改注释为:@SpringBootApplication(scanBasePackages = {"com.micropos.products.*"} )

访问时记得加前缀api,如下:http://localhost:8082/api/products

类似上一次作业,应该在此处添加cache

ehcache

在服务中使用的例子 性能讲解和测试方式

类似之前 在JDRepostry添加 配置了但是不知道是否成功,由于mapper对product进行了转换,所以在指明key/value类型的时候,value类型应当是productDTO,否则mapper会报空指针错:ProductMapper.java:[10,8] Internal error in the mapping processor: java.lang.NullPointerException at jdk.compiler/com.sun.tools.javac.comp.Modules.enterModule(Modules.java:310)

不能像redis一样直接检查数据,需要java程序来管理。先完成其他部分,过程中遇到问题再说。

程序样例1

缓存查看

查询缓存

carts

并不是针对单个用户的购物车状态跳转,而是指同时管理多用户的购物车资源

javax.persistence.* 简单的进行持久化

文档

1
2
3
4
5
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency

@Entity 加了该注释的类在关系型数据库中建表

@GeneratedValue 生成关系数据库中的primarykey

@Accessors

fluent限定只是简单的getter和setter,默认是false,设置为true时,另一个属性chain默认是true,chain为true时决定了返回类型是this而非void

@OneToMany

有嵌套引用的类并且是一组实体的时候,使用该注释

@JoinTable

配合OneToMany使用,在有多对多,一对多的情况下指明

用spring-boot提供的CrudRepository 这是一个提供了数据管理功能的包,样例程序

implements了cartsApi之后可以直接override方法——where is super??

再次出现:[spring boot classnotfound org.springframework.boot.Bootstrapper while staring application](https://stackoverflow.com/questions/65917014/spring-boot-classnotfound-org-springframework-boot-bootstrapper-while-staring-ap)

需要指明spring-cloud的版本,与discovery中保持一致;并且dependencyManagement保留有参数的形式

1
2
3
4
<properties>
<java.version>11</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
</properties>

记得在springboot application的Java文件中用注解扩大bean的扫描范围并且声明向eureka注册

运行时遇到如下问题

image-20220427095447461

重新编译pos-api (没有找到根本的解决办法,偶尔出现)

注册时出现unknown并且端口是默认端口,说明配置文件读取不成功,发现resources放在了和main同级,应该和java文件夹同级

1
2
3
4
5
6
7
8
9
10
11
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method setCartMapper in com.micropos.carts.rest.CartsController required a bean of type 'com.micropos.carts.mapper.CartMapper' that could not be found.


Action:

Consider defining a bean of type 'com.micropos.carts.mapper.CartMapper' in your configuration

遇到cartController有bean无法初始化的问题,是没有定义默认公共构造函数的原因 建议直接在公共构造函数中传入参数cartMapper和cartService

1
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.micropos.carts.model.CartItem

OneToMany注解中添加属性 cascade = casecadeType.ALL

micro 微服务架构

参考的代码 spring-petclinic-microservices配置文件参考;以及microservice-demo

discovery/eureka

eureka server

没有采用远程fetch的形式,直接做了本地配置。

对于eureka的配置,可以参考spring关于eureka的官方文档。其中提供了在start.io建立eureka项目的方式。可以直接使用,对于已经有配置文件的本项目来说,复制粘贴pom中的内容即可(关键是要包含netflix-eureka的依赖)。启动时记得添加@EnableEurekaServer的标注。

yml文件是对于discovery的配置,作为一个独立的服务配置。如果不是默认application.yml的命名方式,需要在mian函数中额外指明。**并且不需要加后缀yml!**(遇到问题记得检查文件是否生效)

如果yml没有配置成功,默认情况下eureka会把自身注册,就会出现如下报错:

com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server

即一个逻辑死循环,因此需要仿照样例将 registerWithEureka,fetchRegistry设置为false。

other server

简单教程

记得在yml文件中添加eureka,服务的application类中启用@EnableDiscoveryClient,并且在pom中添加如下依赖(注意starter不同!)

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

调试中: rest/mvc架构和gateway不共存

如果上层文件夹中pom文件已经有依赖资源,在子层中再次添加依赖需要指明版本。

如果log中出现 Registering application GATEWAY with eureka with status UP,再检查eureka,一般是成功注册了。

配置服务的一般步骤: 依赖+注解+运行检查

如果已有文件中出现冲突,如出现以下报错即是spring-boot-starter-web和spring-cloud-starter-netflix-eureka-client版本冲突,

[spring boot classnotfound org.springframework.boot.Bootstrapper while staring application](https://stackoverflow.com/questions/65917014/spring-boot-classnotfound-org-springframework-boot-bootstrapper-while-staring-ap)

可以在自动生成项目文件的spring官方网站同时选中所需的依赖,然后进行替换。此处是添加了dependencyManagement解决的。

如果需要随机分配,则不在应用中指定server port(待确定?)

Gateway

最后做 其他的可以先做独立应用?——应用本身应该是能够在端口被访问的

配置文件中 关于spring的部分,配置了thymeleaf相关,即网页显示

添加断路器 在转发需求的时候

两部分,一部分保证在eureka登记,另一部分实现转发

转发-简单样例 转发-官方手册

Mono<T> 处理流式数据

可以直接在yml中配置,即可完成转发。但是如果要配置断路器,则必须用代码。

plantuml——AWSuml

画图资源