ApiBoot Resource Load
ApiBoot Resource Load
是一款资源与业务完全分离的基础框架,可以整合微服务(Feign、OpenFeign)
进行负载均衡读取固定类型、固定所属业务的资源信息,遵循一定的资源存储规则
完成自动化
资源读取、添加、更新、删除、缓存等。
使用场景
- 业务图片存储
- 业务音频、视频文件存储
- 业务文件
- 其他资源文件…
引入 ApiBoot Resource Load
在pom.xml
配置文件内添加如下依赖:
- <!--ApiBoot Resource Load-->
- <dependency>
- <groupId>org.minbox.framework</groupId>
- <artifactId>api-boot-starter-resource-load</artifactId>
- </dependency>
ApiBoot
所提供的依赖都不需要添加版本号,但是需要添加版本依赖,具体查看ApiBoot版本依赖
了解ApiBootResourceStoreDelegate
ApiBootResourceStoreDelegate
是一个资源数据读取的委托驱动接口,在使用ApiBoot Resource Load
时,需要实现该接口完成资源的读取方法loadResourceUrl()
,该方法的参数如下所示:
- 第一个参数
sourceFieldValue
,是查询资源的业务编号,具体的配置详见下面的示例。 - 第二个参数
resourceType
,是查询资源的类型,相同的业务编号下很有可能存在多种类型,比如:用户编号对应用户头像、用户封面等。
ApiBootResourceStoreDelegate示例:
- // 示例
- @Service
- public class ResourceLoadService implements ApiBootResourceStoreDelegate {
- /**
- * logger instance
- */
- static Logger logger = LoggerFactory.getLogger(ResourceLoadService.class);
- @Override
- public List<String> loadResourceUrl(String sourceFieldValue, String resourceType) throws ApiBootException {
- logger.info("查询资源的业务逻辑字段值:{}", sourceFieldValue);
- logger.info("资源类型:{}", resourceType);
- return Arrays.asList(new String[]{"http://test.oss.com/111.png"});
- }
- }
loadResourceUrl
方法需要返回根据resourceFieldValue
、resourceType
字段查询到的资源列表。
内置注解
@ResourceLoad
标注方法需要进行ApiBoot Resource Load
自动化读取资源信息,该注解必须添加,且只能添加在方法上。
@ResourceFields
@ResourceField
注解的集合
@ResourceField
配置@ResourceLoad
标注的方法具体有哪些字段需要进行资源的自动映射,参数解释如下所示:
name
:查询资源后设置到类内Field
的名称source
:查询资源所需的业务逻辑编号类内Field
的名称type
:资源类型,自行定义isArray
:接收查询后资源的Field
类型是否为array
,true:arrayisList
:接收查询后资源的Field
类型是否为list
,true:list
单对象资源加载
资源加载一般都是实体类的方式进行返回的,下面我们先来创建一个实体类方便示例测试,如下所示:
- /**
- * 示例对象
- */
- @Data
- class SampleUserInfo {
- public SampleUserInfo(String userId, int age) {
- this.userId = userId;
- this.age = age;
- }
- private String userId;
- private String headImage;
- private String shortImage;
- private int age;
- }
返回值为单对象资源加载示例:
- /**
- * 返回值为单个对象的示例
- *
- * @return
- */
- @ResourceLoad
- @ResourceFields({
- @ResourceField(name = "headImage", source = "userId", type = "HEAD_IMAGE"),
- @ResourceField(name = "shortImage", source = "userId", type = "SHORT_IMAGE")
- })
- public SampleUserInfo singleObjectSample() {
- return new SampleUserInfo("yuqiyu", 24);
- }
在上面,我们配置读取两种类型的资源,分别是:
HEAD_IMAGE
、SHORT_IMAGE
,而且配置的业务资源编号都是userId
字段,这两个字段也就是会传递给ApiBootResourceStoreDelegate#loadResourceUrl
方法作为参数。其中
HEAD_IMAGE
读取到的资源路径设置到SampleUserInfo
类内的headImage
,SHORT_IMAGE
读取到的资源路径设置到SampleUserInfo
类内的shortImage
字段。
注意:如果你的方法返回对象只有一个资源对象需要映射,可以单独配置使用
@ResourceField
注解。
List集合资源加载
- /**
- * 返回值为list集合的示例
- *
- * @return
- */
- @ResourceLoad
- @ResourceFields({
- @ResourceField(name = "headImage", source = "userId", type = "HEAD_IMAGE"),
- @ResourceField(name = "shortImage", source = "userId", type = "SHORT_IMAGE")
- })
- public List<SampleUserInfo> listSample() {
- List<SampleUserInfo> users = new ArrayList();
- users.add(new SampleUserInfo("yuqiyu", 24));
- users.add(new SampleUserInfo("hengboy", 24));
- return users;
- }
在上面,会为返回值list
内的每一个SampleUserInfo
对象进行设置查询的资源信息。
Map集合资源加载
- /**
- * 返回值为map集合的示例
- *
- * @return
- */
- @ResourceLoad
- @ResourceFields({
- @ResourceField(name = "headImage", source = "userId", type = "HEAD_IMAGE"),
- @ResourceField(name = "shortImage", source = "userId", type = "SHORT_IMAGE")
- })
- public Map<String, SampleUserInfo> mapSample() {
- Map<String, SampleUserInfo> users = new HashMap<>(2);
- users.put("yuqiyu", new SampleUserInfo("yuqiyu", 24));
- users.put("hengboy", new SampleUserInfo("hengboy", 24));
- return users;
- }
Map
类型作为返回值时,其中注意map -> value
必须是对象类型。
内存方式缓存资源
ApiBoot Resource Load
提供了内存缓存的支持,相同类型、相同业务逻辑的资源数据只会从数据库内读取一次,除非执行资源的删除、更新,否则只能等到下次重启项目时进行更新。
Redis方式缓存资源
ApiBoot Resource Load
支持使用redis
进行自动缓存资源数据,尽可能减轻数据库的读取压力。
添加redis集成
使用spring-boot-starter-data-redis
依赖来完成集成redis
,在pom.xml
添加依赖如下所示:
- <!--Spring Boot Redis Starter-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
添加依赖后需要进行相应的配置,在application.yml
配置文件内,如下所示:
- spring:
- redis:
- password: 123456
在上面仅仅配置了连接密码,spring-boot-starter-data-redis
配置文件提供了大多数的默认配置,可自行修改。
ApiBoot Resource Load
自动通过RedisTemplate
来完成资源缓存,无需额外配置
表达式使用
@ResourceField
注解的name
、source
属性都支持表达式使用,如下示例:
- @ResourceLoad(event = ResourceStoreEvent.INSERT)
@ResourceFields({
@ResourceField(name = "#p2", source = "#p1.userId", type = ResourceConstant.SHORT_IMAGE),
@ResourceField(name = "#p3", source = "#p0", type = ResourceConstant.HEAD_IMAGE)
})
public void insertResource(String userId, UserInfo userInfo, List<String> shortImage, String headImage) {
//…
}
在上面代码中,#p
是正则表达式所匹配的规则,#p0
为第一个参数,#p1
则为第二个参数,以此类推。
如果参数是对象类型,可以通过#p1.userId
来指定source
对应业务编号的字段。
#p1.userId
则对应参数userInfo
对象内的userId
字段。
自动添加资源
配置资源的自动添加,是通过方法的参数值来进行实现,如下所示:
- @ResourceLoad(event = ResourceStoreEvent.INSERT)
@ResourceFields({
@ResourceField(name = "#p1", source = "#p0.userId", type = ResourceConstant.SHORT_IMAGE),
@ResourceField(name = "#p2", source = "#p0.userId", type = ResourceConstant.HEAD_IMAGE)
})
public void insertUser(UserInfo userInfo, List<String> shortImage, String headImage) {
//..
}
在上面添加资源示例中,要注意,@ResourceLoad
的event
属性需要修改为ResourceStoreEvent.INSERT
。
- @ResourceField(name = "#p2", source = "#p1.userId", type = ResourceConstant.SHORT_IMAGE)
name
:配置使用第二个参数作为SHORT_IMAGE
类型的资源列表。source
:注意#p
索引是从0
开始,所以这里#p1
是第二个参数,#p0.userId
配置使用第一个参数的userId
作为业务逻辑编号字段。type
:常量,自定义
解释:
当调用配置以上注解的方法时,会自动调用
ApiBootResourceStoreDelegate#addResource
方法完成资源的添加,在调用之前,需要从#p0.userId
标注的参数对象中拿到userId
的值作为资源编号,然后拿到#p1
标注的参数值作为资源列表,最终拿到type
的值一并传递给ApiBootResourceStoreDelegate#addResource
方法,做自行保存处理。
- @ResourceField(name = "#p2", source = "#p0.userId", type = ResourceConstant.HEAD_IMAGE)
解释:
调用方法之前,需要拿到
#p0.userId
第一个参数作为业务逻辑编号,然后拿到#p2
第三个参数作为资源列表,最后拿到type
的值一并传递给ApiBootResourceStoreDelegate#addResource
方法。
注意:insertResource
方法配置了两个@ResourceField
所以在执行时,会调用两次ApiBootResourceStoreDelegate#addResource
方法。
自动更新资源
配置资源的自动更新,同样是通过方法的参数值来进行实现,如下所示:
- @ResourceLoad(event = ResourceStoreEvent.UPDATE)
@ResourceFields({
@ResourceField(name = "#p1", source = "#p0", type = ResourceConstant.SHORT_IMAGE)
})
public void updateUserImage(String userId, List<String> shortImage) {
//…
}
在上面示例中,配置@ResourceField
注解则会完成,类型为SHORT_IMAGE
且业务逻辑编号为第一个参数值的资源更新,而更新的资源列表则是第二个参数,也就是List集合。
具体解释与自动添加资源一致。
自动删除资源
配置资源的自动删除,同样是通过方法的参数值来进行实现,如下所示:
- @ResourceLoad(event = ResourceStoreEvent.DELETE)
@ResourceFields({
@ResourceField(name = "shortImage", source = "#p0", type = ResourceConstant.SHORT_IMAGE),
@ResourceField(name = "headImage", source = "#p0", type = ResourceConstant.HEAD_IMAGE)
})
public void deleteUser(String userId) {
//删除用户逻辑
}
在上面代码中,删除用户时,会自动删除userId
业务编号下的SHORT_IMAGE
、HEAD_IMAGE
等资源列表。
资源字段是List或者Array?
如果查询资源时,返回值对象接收资源的字段为List或者Array,可以通过@ResourceField
字段的属性来配置,如下所示:
- // isList
- @ResourceField(name = "shortImage", source = "userId", type = ResourceConstant.SHORT_IMAGE, isList = true)
- // isArray
- @ResourceField(name = "shortImage", source = "userId", type = ResourceConstant.SHORT_IMAGE, isArray = true)