From e5ae9766df06092a12801f0df9bb8a8b124cddef Mon Sep 17 00:00:00 2001 From: wangyu <727842003@qq.com> Date: Wed, 8 Dec 2021 10:54:09 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E4=BB=93=E5=BA=93=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/flyfish/framework/bean/Result.java | 9 ++++ .../com/flyfish/framework/domain/base/Vo.java | 20 +++++++-- .../dict/service/DictionaryService.java | 41 +++++-------------- .../beans/enums/RestBeanCandidate.java | 3 +- .../repository/CustomRepositoryRegistrar.java | 38 +++++++++++++++-- .../config/RestBeanAutoConfigure.java | 27 +++++++++++- .../templates/ReactiveViewController.tpl | 38 +++++++++++++++++ .../resources/templates/ViewController.tpl | 16 ++++---- 8 files changed, 142 insertions(+), 50 deletions(-) create mode 100644 flyfish-web/src/main/resources/templates/ReactiveViewController.tpl diff --git a/flyfish-common/src/main/java/com/flyfish/framework/bean/Result.java b/flyfish-common/src/main/java/com/flyfish/framework/bean/Result.java index 54739b5..927374b 100644 --- a/flyfish-common/src/main/java/com/flyfish/framework/bean/Result.java +++ b/flyfish-common/src/main/java/com/flyfish/framework/bean/Result.java @@ -4,6 +4,7 @@ import com.flyfish.framework.constant.Frameworks; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.data.util.CastUtils; import reactor.core.publisher.Mono; import java.util.Collections; @@ -143,6 +144,14 @@ public class Result { return (Result) this; } + public Mono> flatMap(Function> function) { + return Mono.defer(() -> function.apply(data)) + .map(mapped -> { + this.data = CastUtils.cast(mapped); + return (Result) this; + }); + } + public Result orElse(Result other) { if (null == this.data) { return other; diff --git a/flyfish-data/src/main/java/com/flyfish/framework/domain/base/Vo.java b/flyfish-data/src/main/java/com/flyfish/framework/domain/base/Vo.java index 5da32a7..9121c5d 100644 --- a/flyfish-data/src/main/java/com/flyfish/framework/domain/base/Vo.java +++ b/flyfish-data/src/main/java/com/flyfish/framework/domain/base/Vo.java @@ -1,5 +1,7 @@ package com.flyfish.framework.domain.base; +import reactor.core.publisher.Mono; + /** * 基础的视图模型 * @@ -7,15 +9,27 @@ package com.flyfish.framework.domain.base; */ public interface Vo { - void setId(String id); - String getId(); + void setId(String id); + /** * 赋值,从po转换的逻辑 * * @param po 数据库实体 * @return 结果 */ - Vo from(T po); + default Vo from(T po) { + return this; + } + + /** + * 异步的进行查询处理 + * + * @param po 实体 + * @return 结果 + */ + default Mono> retrieve(T po) { + return Mono.just(from(po)); + } } diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/service/DictionaryService.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/service/DictionaryService.java index 1c7ac2c..614ca5e 100644 --- a/flyfish-dict/src/main/java/com/flyfish/framework/dict/service/DictionaryService.java +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/service/DictionaryService.java @@ -4,15 +4,11 @@ package com.flyfish.framework.dict.service; import com.flyfish.framework.dict.domain.Dictionary; import com.flyfish.framework.dict.repository.DictionaryRepository; import com.flyfish.framework.service.impl.BaseReactiveServiceImpl; -import com.flyfish.framework.utils.RedisOperations; -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.query.Criteria; -import org.springframework.data.mongodb.core.query.Query; +import com.flyfish.framework.utils.ReactiveRedisOperations; import org.springframework.stereotype.Service; import reactor.core.publisher.Mono; import javax.annotation.Resource; -import java.util.Optional; /** * 字典表服务 @@ -25,9 +21,7 @@ public class DictionaryService extends BaseReactiveServiceImpl { private final String DICT_KEY = "dict-"; @Resource - private MongoOperations mongoOperations; - @Resource - private RedisOperations redisOperations; + private ReactiveRedisOperations reactiveRedisOperations; /** * 通过code查询 @@ -35,29 +29,14 @@ public class DictionaryService extends BaseReactiveServiceImpl { * @return 结果 */ public Mono getByCode(String code) { - DictionaryRepository repository = this.getRepository(); - return repository.findByCode(code); - } - - /** - * 通过code同步查询 - * - * @param code 编码 - * @return 结果 - */ - public Optional get(String code) { String cacheKey = DICT_KEY + code; - if (redisOperations.hasKey(cacheKey)) { - return Optional.of(redisOperations.get(cacheKey)).map(obj -> (Dictionary) obj); - } else { - Dictionary dictionary = mongoOperations.findOne(Query.query(Criteria.where("code").is(code)).limit(1), - Dictionary.class); - if (null != dictionary) { - redisOperations.set(cacheKey, dictionary); - return Optional.of(dictionary); - } else { - return Optional.empty(); - } - } + return reactiveRedisOperations.hasKey(cacheKey) + .flatMap(hasKey -> { + if (hasKey) { + return reactiveRedisOperations.get(cacheKey).map(obj -> (Dictionary) obj); + } + DictionaryRepository repository = this.getRepository(); + return repository.findByCode(code); + }); } } diff --git a/flyfish-web/src/main/java/com/flyfish/framework/beans/enums/RestBeanCandidate.java b/flyfish-web/src/main/java/com/flyfish/framework/beans/enums/RestBeanCandidate.java index 0260bb7..ae3a6b7 100644 --- a/flyfish-web/src/main/java/com/flyfish/framework/beans/enums/RestBeanCandidate.java +++ b/flyfish-web/src/main/java/com/flyfish/framework/beans/enums/RestBeanCandidate.java @@ -12,7 +12,8 @@ import lombok.Getter; @AllArgsConstructor public enum RestBeanCandidate implements NamedEnum { - REPOSITORY("Repository"), SERVICE("Service"), CONTROLLER("Controller"), VIEW_CONTROLLER("ViewController"); + REPOSITORY("Repository"), SERVICE("Service"), CONTROLLER("Controller"), + VIEW_CONTROLLER("ViewController"), REACTIVE_VIEW_CONTROLLER("ReactiveViewController"); private final String name; } diff --git a/flyfish-web/src/main/java/com/flyfish/framework/beans/repository/CustomRepositoryRegistrar.java b/flyfish-web/src/main/java/com/flyfish/framework/beans/repository/CustomRepositoryRegistrar.java index f5a23d0..4ca52e0 100644 --- a/flyfish-web/src/main/java/com/flyfish/framework/beans/repository/CustomRepositoryRegistrar.java +++ b/flyfish-web/src/main/java/com/flyfish/framework/beans/repository/CustomRepositoryRegistrar.java @@ -1,7 +1,9 @@ package com.flyfish.framework.beans.repository; +import com.flyfish.framework.repository.DefaultReactiveRepository; +import com.flyfish.framework.repository.DefaultRepository; +import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; @@ -12,11 +14,14 @@ import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; +import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories; import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigurationExtension; +import org.springframework.data.mongodb.repository.config.ReactiveMongoRepositoryConfigurationExtension; import org.springframework.data.repository.config.*; /** * 自定义的仓库注册器 + * * @author wangyu */ public class CustomRepositoryRegistrar { @@ -25,35 +30,59 @@ public class CustomRepositoryRegistrar { private final RepositoryConfigurationExtension extension = new MongoRepositoryConfigurationExtension(); private final RepositoryConfigurationSource configurationSource; private final CustomRepositoryBuilder builder; + // 异步的extension + private final RepositoryConfigurationExtension reactiveExtension = new ReactiveMongoRepositoryConfigurationExtension(); + private final RepositoryConfigurationSource reactiveConfigurationSource; + private final CustomRepositoryBuilder reactiveBuilder; public CustomRepositoryRegistrar(AnnotationMetadata metadata, ResourceLoader resourceLoader, Environment environment, BeanDefinitionRegistry registry, BeanNameGenerator generator) { // repo生成的构建器 this.configurationSource = new AnnotationRepositoryConfigurationSource(metadata, EnableMongoRepositories.class, resourceLoader, environment, registry, generator); + // 异步的repo生成的构建器 + this.reactiveConfigurationSource = new AnnotationRepositoryConfigurationSource(metadata, + EnableReactiveMongoRepositories.class, resourceLoader, environment, registry, generator); // 构建器 this.builder = new CustomRepositoryBuilder(registry, extension, configurationSource, resourceLoader, environment); - + // 异步的构造器 + this.reactiveBuilder = new CustomRepositoryBuilder(registry, reactiveExtension, reactiveConfigurationSource, + resourceLoader, environment); } /** * 根据class直接注册bean + * * @param clazz 编译后的class */ public void register(Class clazz) { + if (ClassUtils.isAssignable(clazz, DefaultRepository.class)) { + register(clazz, configurationSource, extension, builder); + } else if (ClassUtils.isAssignable(clazz, DefaultReactiveRepository.class)) { + register(clazz, reactiveConfigurationSource, reactiveExtension, reactiveBuilder); + } + } + + /** + * 注册仓库内部方法,区分异步和同步 + * + * @param clazz 类型 + * @param configurationSource 配置源 + * @param extension 扩展 + * @param builder 构建器 + */ + private void register(Class clazz, RepositoryConfigurationSource configurationSource, RepositoryConfigurationExtension extension, CustomRepositoryBuilder builder) { //生成BeanDefinition并注册到容器中 BeanDefinition origin = BeanDefinitionBuilder.genericBeanDefinition(clazz).getRawBeanDefinition(); //设置当前bean定义对象是单例的 origin.setScope("singleton"); - // 构造配置 RepositoryConfiguration configuration = new DefaultRepositoryConfiguration<>(configurationSource, origin, extension); BeanDefinitionBuilder definitionBuilder = builder.build(configuration); extension.postProcess(definitionBuilder, configurationSource); extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource); - AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition(); beanDefinition.setPrimary(configuration.isPrimary()); String beanName = StringUtils.uncapitalize(clazz.getSimpleName()); @@ -61,6 +90,7 @@ public class CustomRepositoryRegistrar { builder.getRegistry().registerBeanDefinition(beanName, beanDefinition); } + public RepositoryConfigurationExtension getExtension() { return extension; } diff --git a/flyfish-web/src/main/java/com/flyfish/framework/config/RestBeanAutoConfigure.java b/flyfish-web/src/main/java/com/flyfish/framework/config/RestBeanAutoConfigure.java index f91ca82..a2fee7b 100644 --- a/flyfish-web/src/main/java/com/flyfish/framework/config/RestBeanAutoConfigure.java +++ b/flyfish-web/src/main/java/com/flyfish/framework/config/RestBeanAutoConfigure.java @@ -9,6 +9,8 @@ import com.flyfish.framework.compiler.DynamicJavaCompiler; import com.flyfish.framework.compiler.support.JavaSource; import com.flyfish.framework.compiler.template.TemplateCompiler; import com.flyfish.framework.domain.base.Vo; +import com.flyfish.framework.repository.DefaultReactiveRepository; +import com.flyfish.framework.repository.DefaultRepository; import com.flyfish.framework.utils.Assert; import com.flyfish.framework.utils.StringFormats; import lombok.extern.slf4j.Slf4j; @@ -103,7 +105,7 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res // 分别生成实现类,从repo到controller templates.forEach((type, template) -> { // 当且仅当存在vo时,才编译view-controller - if (type == RestBeanCandidate.VIEW_CONTROLLER && !hasVo) { + if (testNotSupport(clazz, type, hasVo)) { return; } source.setSuperClass(superClasses.getOrDefault(type, noOp).apply(restBean).getCanonicalName()); @@ -128,6 +130,8 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res .forEach(clazz -> registerBean(clazz, registry)); loadedClasses.getOrDefault(VIEW_CONTROLLER, Collections.emptyList()) .forEach(clazz -> registerBean(clazz, registry)); + loadedClasses.getOrDefault(REACTIVE_VIEW_CONTROLLER, Collections.emptyList()) + .forEach(clazz -> registerBean(clazz, registry)); log.info("结束注册rest bean..."); } @@ -137,7 +141,7 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res * @param clazz class,要注册的class * @param registry 注册器,注册bean用 */ - private void registerBean(Class clazz, BeanDefinitionRegistry registry) { + private void registerBean(Class clazz, BeanDefinitionRegistry registry) { //生成BeanDefinition并注册到容器中 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz); BeanDefinition beanDefinition = builder.getRawBeanDefinition(); @@ -191,4 +195,23 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res public void setEnvironment(Environment environment) { this.environment = environment; } + + /** + * 测试是否支持vo + * + * @param clazz 类 + * @param type 注入类型 + * @param hasVo 是否有vo + * @return 结果 + */ + private boolean testNotSupport(Class clazz, RestBeanCandidate type, boolean hasVo) { + switch (type) { + case VIEW_CONTROLLER: + return !hasVo || !DefaultRepository.class.isAssignableFrom(clazz); + case REACTIVE_VIEW_CONTROLLER: + return !hasVo || !DefaultReactiveRepository.class.isAssignableFrom(clazz); + default: + return false; + } + } } diff --git a/flyfish-web/src/main/resources/templates/ReactiveViewController.tpl b/flyfish-web/src/main/resources/templates/ReactiveViewController.tpl new file mode 100644 index 0000000..2305d1f --- /dev/null +++ b/flyfish-web/src/main/resources/templates/ReactiveViewController.tpl @@ -0,0 +1,38 @@ +package #{packageName}; + +import #{beanClass}; +import #{queryBeanClass}; +import #{listViewClass}; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import java.util.List; +import com.flyfish.framework.bean.Result; +import com.flyfish.framework.configuration.annotations.PagedQuery; +import com.flyfish.framework.domain.base.Vo; +import com.flyfish.framework.service.BaseReactiveService; +import reactor.core.publisher.Mono; + +@RestController +@RequestMapping("#{uri}") +public class #{className} { + + @Autowired + protected BaseReactiveService<#{beanClassName}> service; + + @GetMapping("views") + public Mono>>> getVoList(@PagedQuery #{queryBeanClassName}#{queryBeanSuffix} qo) { + if (null != qo.getPageable()) { + return service.getPageList(qo) + .map(Result::accept) + .flatMap(result -> result.flatMap(list -> Flux.fromIterable(list) + .flatMap(item -> #{listViewClassName}().retrieve(item)) + .collectList())); + } + return service.getList(qo).flatMap(item -> new #{listViewClassName}().retrieve(item)) + .collectList() + .map(Result::accept); + } + +} diff --git a/flyfish-web/src/main/resources/templates/ViewController.tpl b/flyfish-web/src/main/resources/templates/ViewController.tpl index 38f5cc4..027dffd 100644 --- a/flyfish-web/src/main/resources/templates/ViewController.tpl +++ b/flyfish-web/src/main/resources/templates/ViewController.tpl @@ -8,28 +8,26 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; +import java.util.stream.Collectors; import com.flyfish.framework.bean.Result; import com.flyfish.framework.configuration.annotations.PagedQuery; import com.flyfish.framework.domain.base.Vo; -import com.flyfish.framework.service.BaseReactiveService; -import reactor.core.publisher.Mono; +import com.flyfish.framework.service.BaseService; @RestController @RequestMapping("#{uri}") public class #{className} { @Autowired - protected BaseReactiveService<#{beanClassName}> service; + protected BaseService<#{beanClassName}> service; @GetMapping("views") - public Mono>>> getVoList(@PagedQuery #{queryBeanClassName}#{queryBeanSuffix} qo) { + public Result>> getVoList(@PagedQuery #{queryBeanClassName}#{queryBeanSuffix} qo) { if (null != qo.getPageable()) { - return service.getPageList(qo).map(page -> page.map(item -> new #{listViewClassName}().from(item))) - .map(Result::accept); + return Result.accept(service.getPageList(qo).map(item -> new #{listViewClassName}().from(item))); } - return service.getList(qo).map(item -> new #{listViewClassName}().from(item)) - .collectList() - .map(Result::accept); + return Result.accept(service.getList(qo).stream() + .map(item -> new #{listViewClassName}().from(item)).collect(Collectors.toList())); } }