feat:仓库初始化问题修复

This commit is contained in:
wangyu 2021-12-08 10:54:09 +08:00
parent 6fc717a186
commit e5ae9766df
8 changed files with 142 additions and 50 deletions

View File

@ -4,6 +4,7 @@ import com.flyfish.framework.constant.Frameworks;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.util.CastUtils;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.util.Collections; import java.util.Collections;
@ -143,6 +144,14 @@ public class Result<T> {
return (Result<R>) this; return (Result<R>) this;
} }
public <R> Mono<Result<R>> flatMap(Function<T, Mono<R>> function) {
return Mono.defer(() -> function.apply(data))
.map(mapped -> {
this.data = CastUtils.cast(mapped);
return (Result<R>) this;
});
}
public Result<T> orElse(Result<T> other) { public Result<T> orElse(Result<T> other) {
if (null == this.data) { if (null == this.data) {
return other; return other;

View File

@ -1,5 +1,7 @@
package com.flyfish.framework.domain.base; package com.flyfish.framework.domain.base;
import reactor.core.publisher.Mono;
/** /**
* 基础的视图模型 * 基础的视图模型
* *
@ -7,15 +9,27 @@ package com.flyfish.framework.domain.base;
*/ */
public interface Vo<T> { public interface Vo<T> {
void setId(String id);
String getId(); String getId();
void setId(String id);
/** /**
* 赋值从po转换的逻辑 * 赋值从po转换的逻辑
* *
* @param po 数据库实体 * @param po 数据库实体
* @return 结果 * @return 结果
*/ */
Vo<T> from(T po); default Vo<T> from(T po) {
return this;
}
/**
* 异步的进行查询处理
*
* @param po 实体
* @return 结果
*/
default Mono<Vo<T>> retrieve(T po) {
return Mono.just(from(po));
}
} }

View File

@ -4,15 +4,11 @@ package com.flyfish.framework.dict.service;
import com.flyfish.framework.dict.domain.Dictionary; import com.flyfish.framework.dict.domain.Dictionary;
import com.flyfish.framework.dict.repository.DictionaryRepository; import com.flyfish.framework.dict.repository.DictionaryRepository;
import com.flyfish.framework.service.impl.BaseReactiveServiceImpl; import com.flyfish.framework.service.impl.BaseReactiveServiceImpl;
import com.flyfish.framework.utils.RedisOperations; import com.flyfish.framework.utils.ReactiveRedisOperations;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Optional;
/** /**
* 字典表服务 * 字典表服务
@ -25,9 +21,7 @@ public class DictionaryService extends BaseReactiveServiceImpl<Dictionary> {
private final String DICT_KEY = "dict-"; private final String DICT_KEY = "dict-";
@Resource @Resource
private MongoOperations mongoOperations; private ReactiveRedisOperations reactiveRedisOperations;
@Resource
private RedisOperations redisOperations;
/** /**
* 通过code查询 * 通过code查询
@ -35,29 +29,14 @@ public class DictionaryService extends BaseReactiveServiceImpl<Dictionary> {
* @return 结果 * @return 结果
*/ */
public Mono<Dictionary> getByCode(String code) { public Mono<Dictionary> getByCode(String code) {
String cacheKey = DICT_KEY + code;
return reactiveRedisOperations.hasKey(cacheKey)
.flatMap(hasKey -> {
if (hasKey) {
return reactiveRedisOperations.get(cacheKey).map(obj -> (Dictionary) obj);
}
DictionaryRepository repository = this.getRepository(); DictionaryRepository repository = this.getRepository();
return repository.findByCode(code); return repository.findByCode(code);
} });
/**
* 通过code同步查询
*
* @param code 编码
* @return 结果
*/
public Optional<Dictionary> 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();
}
}
} }
} }

View File

@ -12,7 +12,8 @@ import lombok.Getter;
@AllArgsConstructor @AllArgsConstructor
public enum RestBeanCandidate implements NamedEnum { 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; private final String name;
} }

View File

@ -1,7 +1,9 @@
package com.flyfish.framework.beans.repository; 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.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition; 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.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; 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.MongoRepositoryConfigurationExtension;
import org.springframework.data.mongodb.repository.config.ReactiveMongoRepositoryConfigurationExtension;
import org.springframework.data.repository.config.*; import org.springframework.data.repository.config.*;
/** /**
* 自定义的仓库注册器 * 自定义的仓库注册器
*
* @author wangyu * @author wangyu
*/ */
public class CustomRepositoryRegistrar { public class CustomRepositoryRegistrar {
@ -25,35 +30,59 @@ public class CustomRepositoryRegistrar {
private final RepositoryConfigurationExtension extension = new MongoRepositoryConfigurationExtension(); private final RepositoryConfigurationExtension extension = new MongoRepositoryConfigurationExtension();
private final RepositoryConfigurationSource configurationSource; private final RepositoryConfigurationSource configurationSource;
private final CustomRepositoryBuilder builder; 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, public CustomRepositoryRegistrar(AnnotationMetadata metadata, ResourceLoader resourceLoader, Environment environment,
BeanDefinitionRegistry registry, BeanNameGenerator generator) { BeanDefinitionRegistry registry, BeanNameGenerator generator) {
// repo生成的构建器 // repo生成的构建器
this.configurationSource = new AnnotationRepositoryConfigurationSource(metadata, this.configurationSource = new AnnotationRepositoryConfigurationSource(metadata,
EnableMongoRepositories.class, resourceLoader, environment, registry, generator); EnableMongoRepositories.class, resourceLoader, environment, registry, generator);
// 异步的repo生成的构建器
this.reactiveConfigurationSource = new AnnotationRepositoryConfigurationSource(metadata,
EnableReactiveMongoRepositories.class, resourceLoader, environment, registry, generator);
// 构建器 // 构建器
this.builder = new CustomRepositoryBuilder(registry, extension, this.builder = new CustomRepositoryBuilder(registry, extension,
configurationSource, resourceLoader, environment); configurationSource, resourceLoader, environment);
// 异步的构造器
this.reactiveBuilder = new CustomRepositoryBuilder(registry, reactiveExtension, reactiveConfigurationSource,
resourceLoader, environment);
} }
/** /**
* 根据class直接注册bean * 根据class直接注册bean
*
* @param clazz 编译后的class * @param clazz 编译后的class
*/ */
public void register(Class<?> clazz) { 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并注册到容器中
BeanDefinition origin = BeanDefinitionBuilder.genericBeanDefinition(clazz).getRawBeanDefinition(); BeanDefinition origin = BeanDefinitionBuilder.genericBeanDefinition(clazz).getRawBeanDefinition();
//设置当前bean定义对象是单例的 //设置当前bean定义对象是单例的
origin.setScope("singleton"); origin.setScope("singleton");
// 构造配置
RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration = RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration =
new DefaultRepositoryConfiguration<>(configurationSource, origin, extension); new DefaultRepositoryConfiguration<>(configurationSource, origin, extension);
BeanDefinitionBuilder definitionBuilder = builder.build(configuration); BeanDefinitionBuilder definitionBuilder = builder.build(configuration);
extension.postProcess(definitionBuilder, configurationSource); extension.postProcess(definitionBuilder, configurationSource);
extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource); extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource);
AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition(); AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition();
beanDefinition.setPrimary(configuration.isPrimary()); beanDefinition.setPrimary(configuration.isPrimary());
String beanName = StringUtils.uncapitalize(clazz.getSimpleName()); String beanName = StringUtils.uncapitalize(clazz.getSimpleName());
@ -61,6 +90,7 @@ public class CustomRepositoryRegistrar {
builder.getRegistry().registerBeanDefinition(beanName, beanDefinition); builder.getRegistry().registerBeanDefinition(beanName, beanDefinition);
} }
public RepositoryConfigurationExtension getExtension() { public RepositoryConfigurationExtension getExtension() {
return extension; return extension;
} }

View File

@ -9,6 +9,8 @@ import com.flyfish.framework.compiler.DynamicJavaCompiler;
import com.flyfish.framework.compiler.support.JavaSource; import com.flyfish.framework.compiler.support.JavaSource;
import com.flyfish.framework.compiler.template.TemplateCompiler; import com.flyfish.framework.compiler.template.TemplateCompiler;
import com.flyfish.framework.domain.base.Vo; 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.Assert;
import com.flyfish.framework.utils.StringFormats; import com.flyfish.framework.utils.StringFormats;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -103,7 +105,7 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
// 分别生成实现类从repo到controller // 分别生成实现类从repo到controller
templates.forEach((type, template) -> { templates.forEach((type, template) -> {
// 当且仅当存在vo时才编译view-controller // 当且仅当存在vo时才编译view-controller
if (type == RestBeanCandidate.VIEW_CONTROLLER && !hasVo) { if (testNotSupport(clazz, type, hasVo)) {
return; return;
} }
source.setSuperClass(superClasses.getOrDefault(type, noOp).apply(restBean).getCanonicalName()); source.setSuperClass(superClasses.getOrDefault(type, noOp).apply(restBean).getCanonicalName());
@ -128,6 +130,8 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
.forEach(clazz -> registerBean(clazz, registry)); .forEach(clazz -> registerBean(clazz, registry));
loadedClasses.getOrDefault(VIEW_CONTROLLER, Collections.emptyList()) loadedClasses.getOrDefault(VIEW_CONTROLLER, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry)); .forEach(clazz -> registerBean(clazz, registry));
loadedClasses.getOrDefault(REACTIVE_VIEW_CONTROLLER, Collections.emptyList())
.forEach(clazz -> registerBean(clazz, registry));
log.info("结束注册rest bean..."); log.info("结束注册rest bean...");
} }
@ -191,4 +195,23 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
public void setEnvironment(Environment environment) { public void setEnvironment(Environment environment) {
this.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;
}
}
} }

View File

@ -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<Result<List<Vo<#{beanClassName}>>>> 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);
}
}

View File

@ -8,28 +8,26 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import com.flyfish.framework.bean.Result; import com.flyfish.framework.bean.Result;
import com.flyfish.framework.configuration.annotations.PagedQuery; import com.flyfish.framework.configuration.annotations.PagedQuery;
import com.flyfish.framework.domain.base.Vo; import com.flyfish.framework.domain.base.Vo;
import com.flyfish.framework.service.BaseReactiveService; import com.flyfish.framework.service.BaseService;
import reactor.core.publisher.Mono;
@RestController @RestController
@RequestMapping("#{uri}") @RequestMapping("#{uri}")
public class #{className} { public class #{className} {
@Autowired @Autowired
protected BaseReactiveService<#{beanClassName}> service; protected BaseService<#{beanClassName}> service;
@GetMapping("views") @GetMapping("views")
public Mono<Result<List<Vo<#{beanClassName}>>>> getVoList(@PagedQuery #{queryBeanClassName}#{queryBeanSuffix} qo) { public Result<List<Vo<#{beanClassName}>>> getVoList(@PagedQuery #{queryBeanClassName}#{queryBeanSuffix} qo) {
if (null != qo.getPageable()) { if (null != qo.getPageable()) {
return service.getPageList(qo).map(page -> page.map(item -> new #{listViewClassName}().from(item))) return Result.accept(service.getPageList(qo).map(item -> new #{listViewClassName}().from(item)));
.map(Result::accept);
} }
return service.getList(qo).map(item -> new #{listViewClassName}().from(item)) return Result.accept(service.getList(qo).stream()
.collectList() .map(item -> new #{listViewClassName}().from(item)).collect(Collectors.toList()));
.map(Result::accept);
} }
} }