├── .gitignore ├── README.md ├── pom.xml ├── rxjava-apikit ├── pom.xml ├── rxjava-apikit-core │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── org │ │ └── rxjava │ │ └── apikit │ │ ├── annotation │ │ └── Ignore.java │ │ ├── client │ │ ├── ApiType.java │ │ ├── ApiUtils.java │ │ └── ClientAdapter.java │ │ └── core │ │ └── HttpMethodType.java ├── rxjava-apikit-maven-plugin │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── org │ │ └── rxjava │ │ └── apikit │ │ └── plugin │ │ ├── ApikitMojo.java │ │ ├── ApikitsMojo.java │ │ ├── GenerateUtils.java │ │ ├── MavenUtils.java │ │ └── bean │ │ ├── AbstractTask.java │ │ ├── GitTask.java │ │ ├── Group.java │ │ ├── JavaClientTask.java │ │ ├── JavaScriptClientTask.java │ │ └── Task.java └── rxjava-apikit-tool │ ├── ReadMe.md │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── org │ │ └── rxjava │ │ └── apikit │ │ └── tool │ │ ├── ApiGenerateManager.java │ │ ├── analyse │ │ ├── Analyse.java │ │ └── impl │ │ │ ├── ControllerAnalyse.java │ │ │ ├── EnumClassAnalyse.java │ │ │ └── ParamClassAnalyse.java │ │ ├── generator │ │ ├── AbstractGenerator.java │ │ ├── ApiContext.java │ │ ├── ClassNameMapper.java │ │ ├── Context.java │ │ ├── Generator.java │ │ ├── NameMaper.java │ │ ├── PackageNameMapper.java │ │ └── impl │ │ │ ├── AbstractCommonGenerator.java │ │ │ ├── AbstractHttlGenerator.java │ │ │ ├── ApidocApiGenerator.java │ │ │ ├── ApidocGenerator.java │ │ │ ├── DefaultClassNameMapper.java │ │ │ ├── DefaultPackageNameMapper.java │ │ │ ├── GitGenerator.java │ │ │ ├── JavaClientApiGenerator.java │ │ │ ├── JavaScriptApiGenerator.java │ │ │ └── PatternNameMaper.java │ │ ├── info │ │ ├── AnnotationInfo.java │ │ ├── ApiClassInfo.java │ │ ├── ApiInputClassInfo.java │ │ ├── ApiMethodInfo.java │ │ ├── ClassBaseInfo.java │ │ ├── ClassInfo.java │ │ ├── ClassTypeInfo.java │ │ ├── ControllerInfo.java │ │ ├── ControllerMethodInfo.java │ │ ├── EnumConstantInfo.java │ │ ├── EnumParamClassInfo.java │ │ ├── FieldInfo.java │ │ ├── Import.java │ │ ├── InputParamInfo.java │ │ ├── JavaDocInfo.java │ │ ├── PackageInfo.java │ │ ├── ParamClassInfo.java │ │ ├── ParamInfo.java │ │ ├── PropertyInfo.java │ │ ├── TestInfo.java │ │ └── TestSuperInfo.java │ │ ├── type │ │ └── ApiType.java │ │ ├── utils │ │ ├── ClassAnalyseUtils.java │ │ ├── CommentUtils.java │ │ ├── DateTimeUtils.java │ │ ├── HttlUtils.java │ │ ├── JavaFileFormat.java │ │ ├── JdtClassWrapper.java │ │ ├── JsonUtils.java │ │ ├── LocalPathUtils.java │ │ ├── NameUtils.java │ │ └── OrderStatus.java │ │ └── wrapper │ │ ├── ApidocApiWrapper.java │ │ ├── ApidocParamClassWrapper.java │ │ ├── BuilderWrapper.java │ │ ├── JavaApiWrapper.java │ │ ├── JavaEnumParamClassWrapper.java │ │ ├── JavaParamClassWrapper.java │ │ ├── JavaScriptApiWrapper.java │ │ ├── JavaScriptParamClassWrapper.java │ │ ├── JavaScriptWrapper.java │ │ └── JavaWrapper.java │ └── resources │ └── org │ └── rxjava │ └── apikit │ └── tool │ ├── generator │ ├── apidoc │ │ ├── api.httl │ │ ├── index.httl │ │ ├── package.json │ │ ├── paramClass.httl │ │ └── test.httl │ ├── es2015 │ │ ├── Api.d.httl │ │ ├── Api.httl │ │ ├── ParamClass.d.httl │ │ ├── ParamClass.httl │ │ ├── index.d.httl │ │ ├── index.httl │ │ └── package.json │ └── java │ │ ├── .gitignore │ │ ├── ApiClass.httl │ │ ├── EnumParamClass.httl │ │ └── ParamClass.httl │ └── httl.properties ├── rxjava-example ├── README.md ├── rxjava-gateway-example │ ├── pom.xml │ └── src │ │ ├── assembly │ │ ├── bin.xml │ │ └── config │ │ │ └── release │ │ │ ├── Dockerfile │ │ │ ├── bootstrap.yml │ │ │ └── startup.sh │ │ └── main │ │ ├── java │ │ └── org │ │ │ └── rxjava │ │ │ └── gateway │ │ │ └── example │ │ │ ├── CustomDiscoveryClientRouteDefinitionLocator.java │ │ │ ├── CustomGatewayDiscoveryClientAutoConfiguration.java │ │ │ ├── LoginInfoServiceImpl.java │ │ │ ├── RxGatewayExampleApplication.java │ │ │ └── RxGatewayExampleMain.java │ │ └── resources │ │ ├── META-INF │ │ └── spring.factories │ │ └── bootstrap.yml └── rxjava-service-example │ ├── build.sh │ ├── k8s │ └── rxjava-service-example.yaml │ ├── pom.xml │ └── src │ ├── assembly │ ├── bin.xml │ └── config │ │ └── release │ │ ├── Dockerfile │ │ ├── bootstrap.yml │ │ └── startup.sh │ ├── main │ ├── java │ │ └── org │ │ │ └── rxjava │ │ │ └── service │ │ │ └── example │ │ │ ├── RxApiBuildApplication.java │ │ │ ├── RxServiceExampleApplication.java │ │ │ ├── RxServiceExampleMain.java │ │ │ ├── entity │ │ │ └── Example.java │ │ │ ├── form │ │ │ ├── TestForm.java │ │ │ └── TestSuperForm.java │ │ │ ├── model │ │ │ └── TestModel.java │ │ │ ├── person │ │ │ └── TestController.java │ │ │ ├── repository │ │ │ └── ExampleRepository.java │ │ │ └── type │ │ │ └── TestEnumType.java │ └── resources │ │ ├── bootstrap.yml │ │ └── exceptions │ │ └── exception_zh_CN.xml │ └── test │ └── java │ └── org │ └── rxjava │ └── api │ └── example │ └── test │ ├── TestApplication.java │ └── TestContext.java ├── rxjava-gateway └── pom.xml ├── rxjava-service ├── README.md └── pom.xml └── rxjava-spring ├── pom.xml ├── rxjava-spring-boot-core ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── rxjava │ └── common │ └── core │ ├── RxJavaCoreAutoConfiguration.java │ ├── annotation │ ├── Check.java │ ├── EnumValue.java │ └── Login.java │ ├── api │ └── ReactiveHttpClientAdapter.java │ ├── entity │ ├── BaseEntity.java │ ├── Image.java │ ├── KeyValue.java │ ├── LoginInfo.java │ └── Video.java │ ├── exception │ ├── DefaultError.java │ ├── ErrorMessage.java │ ├── ErrorMessageException.java │ ├── FieldError.java │ ├── ForbiddenException.java │ ├── JsonResponseStatusExceptionHandler.java │ └── UnauthorizedException.java │ ├── form │ └── PageForm.java │ ├── mongo │ └── PageAgent.java │ ├── service │ ├── DefaultLoginInfoServiceImpl.java │ └── LoginInfoService.java │ ├── status │ └── Status.java │ ├── tools │ └── RequestTool.java │ └── utils │ ├── ErrorMessageUtils.java │ ├── FileRenameUtils.java │ ├── JavaTimeModuleUtils.java │ ├── JsonUtils.java │ ├── KeyUtils.java │ └── UUIDUtils.java ├── rxjava-spring-boot-starter-service ├── pom.xml └── src │ └── main │ ├── java │ └── org │ │ └── rxjava │ │ └── service │ │ └── starter │ │ ├── RxJavaServiceAutoConfiguration.java │ │ └── boot │ │ ├── LoginInfoArgumentResolver.java │ │ ├── RxJavaWebFluxConfigurer.java │ │ ├── SecurityRequestMappingHandlerAdapter.java │ │ └── ServiceDelegatingWebFluxConfiguration.java │ └── resources │ ├── META-INF │ └── spring.factories │ ├── application.yml │ └── defaultExceptions │ └── exception_zh_CN.xml ├── rxjava-spring-cloud-starter-bus ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── rxjava │ └── common │ └── bus │ ├── BusEmitter.java │ ├── BusEvent.java │ ├── BusEventType.java │ ├── BusReceiver.java │ ├── EnableBus.java │ ├── MessageReceiver.java │ └── RxBusConfiguration.java ├── rxjava-spring-cloud-starter-gateway ├── pom.xml └── src │ └── main │ ├── java │ └── org │ │ └── rxjava │ │ └── gateway │ │ └── starter │ │ ├── RxJavaGatewayAutoConfiguration.java │ │ └── config │ │ ├── AuthenticationToken.java │ │ ├── CustomServerAuthenticationFailureHandler.java │ │ ├── CustomServerAuthenticationSuccessHandler.java │ │ └── RxJavaWebFluxSecurityConfig.java │ └── resources │ └── META-INF │ └── spring.factories └── rxjava-spring-mock-starter ├── pom.xml └── src └── main ├── java └── org │ └── rxjava │ └── mock │ └── starter │ ├── RxJavaMockAutoConfiguration.java │ └── config │ └── MockProperties.java └── resources └── META-INF └── spring.factories /README.md: -------------------------------------------------------------------------------- 1 | #### 如果你觉得还行,请给个star,感谢你的支持🙏 2 | ## QQ交流群:828300414,加群答案:taro-jd 3 | 4 | ### 项目已发布到maven中央仓库,当前最新正式版本号为1.0.8,快照版本1.0.9 5 | 6 | ## rxjava项目说明 7 | 8 | ### 一、模块说明 9 | 10 | - [rxjava-apikit](https://mvnrepository.com/artifact/org.rxjava/rxjava-apikit):Api生成器(包括生成java客户端代码,JavaScript客户端代码) 11 | - [rxjava-example](https://mvnrepository.com/artifact/org.rxjava/rxjava-example):例子工程 12 | - [rxjava-gateway](https://mvnrepository.com/artifact/org.rxjava/rxjava-gateway):网关项目pom 13 | - [rxjava-service](https://mvnrepository.com/artifact/org.rxjava/rxjava-service):微服务项目pom 14 | - [rxjava-spring](https://mvnrepository.com/artifact/org.rxjava/rxjava-spring):对spring的一些整合 15 | - [rxjava](https://mvnrepository.com/artifact/org.rxjava/rxjava):依赖管理pom 16 | 17 | ### 二、Api生成器说明 18 | 19 | - [rxjava-apikit-core](https://mvnrepository.com/artifact/org.rxjava/rxjava-apikit-core):一些默认约定,如适配器 20 | - [rxjava-apikit-maven-plugin](https://mvnrepository.com/artifact/org.rxjava/rxjava-apikit-maven-plugin):maven插件,可直接执行命令生成api 21 | - [rxjava-apikit-tool](https://mvnrepository.com/artifact/org.rxjava/rxjava-apikit-tool):Api生成器实现代码 22 | 23 | - api插件maven生成器命令:进入微服务目录,执行命令 mvn clean rxjava-apikit:apis 24 | 25 | #### ssh方式有时候会出现Auth fail问题,建议暂时使用https方式 26 | 27 | ### 三、例子工程说明 28 | 29 | - rxjava-gateway-example:主要示例了如何创建api网关,以及演示了如何使用token换取loginInfo,并注入到router的微服务请求参数中 30 | - rxjava-service-example:主要示例了如何创建微服务,以及一些基础性的配置,并演示了如何手动创建api到test文件夹,并示例了k8s的一些基本配置 31 | - rxjava-security-example:主要示例了如何使用security创建授权微服务,并演示如何认证和授权 32 | 33 | ### 四、网关项目pom 34 | 35 | - pom暂时行只依赖了spring-cloud-gateway,此pom主要是将一些网关的依赖整合到一起 36 | 37 | ### 五、微服务项目pom 38 | 39 | - pom主要是整合依赖,并且演示了如何配置api生成器maven插件,以及一些包的命名规范 40 | 41 | ### 六、rxjava-spring 42 | 43 | - rxjava-spring-boot-core:主要是一些注解,常用实体类,异常处理,包装了mongo分页,以及一些帮助类 44 | - rxjava-spring-boot-starter-service:整合了spring自动配置,时间格式统一处理,登陆请求拦截,异常统一处理 45 | - rxjava-spring-cloud-starter-bus:做了一些消息总线的基础约定 46 | - rxjava-spring-cloud-starter-gateway:做了一些网关的一些基础配置 47 | -------------------------------------------------------------------------------- /rxjava-apikit/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.rxjava 5 | rxjava 6 | 1.0.9-SNAPSHOT 7 | 8 | 4.0.0 9 | rxjava-apikit 10 | pom 11 | 12 | rxjava-apikit-core 13 | rxjava-apikit-tool 14 | rxjava-apikit-maven-plugin 15 | 16 | 17 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.rxjava 6 | rxjava-apikit 7 | 1.0.9-SNAPSHOT 8 | 9 | rxjava-apikit-core 10 | jar 11 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-core/src/main/java/org/rxjava/apikit/annotation/Ignore.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 忽略生成Api 7 | * 默认为需要登陆 8 | */ 9 | @Target(ElementType.METHOD) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface Ignore { 13 | } 14 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-core/src/main/java/org/rxjava/apikit/client/ApiType.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.client; 2 | 3 | 4 | import java.lang.reflect.ParameterizedType; 5 | import java.lang.reflect.Type; 6 | 7 | /** 8 | * @author happy 9 | */ 10 | public class ApiType implements ParameterizedType { 11 | private final Type[] types; 12 | private final Type raw; 13 | 14 | ApiType(Type raw, Type... types) { 15 | this.raw = raw; 16 | this.types = types; 17 | } 18 | 19 | @Override 20 | public Type[] getActualTypeArguments() { 21 | return this.types; 22 | } 23 | 24 | @Override 25 | public Type getRawType() { 26 | return this.raw; 27 | } 28 | 29 | @Override 30 | public Type getOwnerType() { 31 | return null; 32 | } 33 | } -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-core/src/main/java/org/rxjava/apikit/client/ApiUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.client; 2 | 3 | /** 4 | * @author happy 5 | */ 6 | 7 | import java.io.UnsupportedEncodingException; 8 | import java.lang.reflect.Type; 9 | import java.net.URLEncoder; 10 | import java.util.Iterator; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | 16 | public class ApiUtils { 17 | /** 18 | * 正则表达式名称 19 | */ 20 | private static final Pattern NAMES_PATTERN = Pattern.compile("\\{([^/]+?)}"); 21 | 22 | /** 23 | * 展开Uri组件 24 | */ 25 | public static String expandUriComponent(String url, Map uriVariables) { 26 | if (url == null) { 27 | return null; 28 | } else if (url.indexOf(123) == -1) { 29 | return url; 30 | } else { 31 | Matcher matcher = NAMES_PATTERN.matcher(url); 32 | 33 | StringBuffer sb; 34 | String replacement; 35 | for (sb = new StringBuffer(); matcher.find(); matcher.appendReplacement(sb, replacement)) { 36 | String match = matcher.group(1); 37 | String variableName = getVariableName(match); 38 | Object variableValue = uriVariables.get(variableName); 39 | if (variableValue == null) { 40 | throw new RuntimeException("协议定义错误,需要参数未找到"); 41 | } 42 | 43 | String variableValueString = getVariableValueAsString(variableValue); 44 | 45 | try { 46 | replacement = Matcher.quoteReplacement(URLEncoder.encode(variableValueString, "utf8")); 47 | } catch (UnsupportedEncodingException var10) { 48 | throw new RuntimeException(var10); 49 | } 50 | } 51 | 52 | matcher.appendTail(sb); 53 | return sb.toString(); 54 | } 55 | } 56 | 57 | /** 58 | * 获取变量名 59 | */ 60 | private static String getVariableName(String match) { 61 | int colonIdx = match.indexOf(58); 62 | return colonIdx != -1 ? match.substring(0, colonIdx) : match; 63 | } 64 | 65 | /** 66 | * 获取变量值并转化为字符串 67 | */ 68 | private static String getVariableValueAsString(Object variableValue) { 69 | if (variableValue != null) { 70 | if (variableValue instanceof List) { 71 | List list = (List) variableValue; 72 | StringBuilder sb = new StringBuilder(); 73 | 74 | Object item; 75 | for (Iterator var3 = list.iterator(); var3.hasNext(); sb.append(item)) { 76 | item = var3.next(); 77 | if (sb.length() > 0) { 78 | sb.append(','); 79 | } 80 | } 81 | 82 | return sb.toString(); 83 | } else { 84 | return variableValue.toString(); 85 | } 86 | } else { 87 | return ""; 88 | } 89 | } 90 | 91 | public static ApiType type(Type raw, Type... types) { 92 | return new ApiType(raw, types); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-core/src/main/java/org/rxjava/apikit/client/ClientAdapter.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.client; 2 | 3 | import reactor.core.publisher.Mono; 4 | 5 | import java.lang.reflect.Type; 6 | import java.util.List; 7 | import java.util.Map.Entry; 8 | 9 | /** 10 | * @author happy 11 | * 客户端适配器 12 | */ 13 | public interface ClientAdapter { 14 | /** 15 | * 发起http请求 16 | * 17 | * @param method 请求方法{@link org.rxjava.apikit.core.HttpMethodType} 18 | * @param uri 请求的Uri 19 | * @param form Post请求表单数据 20 | * @param returnType 返回值类型 21 | */ 22 | Mono request(String method, String uri, List> form, Type returnType); 23 | } -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-core/src/main/java/org/rxjava/apikit/core/HttpMethodType.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.core; 2 | 3 | /** 4 | * @author happy 5 | * Http请求方法类型 6 | */ 7 | public enum HttpMethodType { 8 | /** 9 | * 获取 10 | */ 11 | GET, 12 | /** 13 | * 创建 14 | */ 15 | POST, 16 | /** 17 | * 全部更新 18 | */ 19 | PUT, 20 | /** 21 | * 删除 22 | */ 23 | DELETE, 24 | /** 25 | * 部分更新 26 | */ 27 | PATCH; 28 | } 29 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-maven-plugin/src/main/java/org/rxjava/apikit/plugin/ApikitMojo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.plugin; 2 | 3 | import org.apache.maven.plugin.AbstractMojo; 4 | import org.apache.maven.plugins.annotations.Mojo; 5 | import org.apache.maven.plugins.annotations.Parameter; 6 | import org.apache.maven.plugins.annotations.ResolutionScope; 7 | import org.apache.maven.project.MavenProject; 8 | import org.rxjava.apikit.plugin.bean.Group; 9 | import org.rxjava.apikit.plugin.bean.Task; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * @author happy 16 | */ 17 | @Mojo( 18 | name = "api", 19 | requiresDependencyCollection = ResolutionScope.RUNTIME, 20 | requiresDependencyResolution = ResolutionScope.RUNTIME 21 | ) 22 | public class ApikitMojo extends AbstractMojo { 23 | @Parameter 24 | private List tasks; 25 | 26 | @Parameter 27 | private String rootPackage; 28 | 29 | @Parameter 30 | private String apiType; 31 | 32 | @Override 33 | public void execute() { 34 | 35 | Map pluginContext = getPluginContext(); 36 | MavenProject project = (MavenProject) pluginContext.get("project"); 37 | String[] compileSourceRoots = project 38 | .getCompileSourceRoots() 39 | .stream() 40 | .filter(str -> !str.contains("generated-sources/annotations")) 41 | .toArray(String[]::new); 42 | 43 | if (compileSourceRoots.length > 1) { 44 | throw new RuntimeException("Multiple compileSourceRoot is not supported"); 45 | } 46 | //获取到java源码路径 47 | String javaSourcePath = compileSourceRoots[0]; 48 | 49 | getLog().info("开始执行全部任务" + tasks + pluginContext); 50 | 51 | MavenUtils.generate(project, new Group(tasks, rootPackage, apiType), javaSourcePath, compileSourceRoots); 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-maven-plugin/src/main/java/org/rxjava/apikit/plugin/ApikitsMojo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.plugin; 2 | 3 | import org.apache.maven.execution.MavenSession; 4 | import org.apache.maven.plugin.AbstractMojo; 5 | import org.apache.maven.plugins.annotations.Mojo; 6 | import org.apache.maven.plugins.annotations.Parameter; 7 | import org.apache.maven.plugins.annotations.ResolutionScope; 8 | import org.apache.maven.project.MavenProject; 9 | import org.rxjava.apikit.plugin.bean.Group; 10 | 11 | import java.util.List; 12 | 13 | @Mojo( 14 | name = "apis", 15 | requiresDependencyCollection = ResolutionScope.RUNTIME, 16 | requiresDependencyResolution = ResolutionScope.RUNTIME 17 | ) 18 | public class ApikitsMojo extends AbstractMojo { 19 | @Parameter 20 | private List groups; 21 | 22 | @Parameter(defaultValue = "${session}", readonly = true, required = true) 23 | private MavenSession session; 24 | 25 | @Override 26 | public void execute() { 27 | MavenProject project = session.getCurrentProject(); 28 | String[] compileSourceRoots = project 29 | .getCompileSourceRoots() 30 | .stream() 31 | .filter(str -> !str.contains("generated-sources/annotations")) 32 | .toArray(String[]::new); 33 | 34 | if (compileSourceRoots.length > 1) { 35 | throw new RuntimeException("Multiple compileSourceRoot is not supported"); 36 | } 37 | String sourcePath = compileSourceRoots[0]; 38 | try { 39 | getLog().info("开始执行全部任务:" + groups); 40 | for (Group group : groups) { 41 | getLog().info("开始执行第一组:" + group); 42 | MavenUtils.generate(project, group, sourcePath, compileSourceRoots); 43 | getLog().info("结束第一组:" + group); 44 | } 45 | } catch (Exception e) { 46 | throw new RuntimeException(e); 47 | } 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-maven-plugin/src/main/java/org/rxjava/apikit/plugin/MavenUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.plugin; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator; 5 | import org.apache.maven.artifact.DependencyResolutionRequiredException; 6 | import org.apache.maven.project.MavenProject; 7 | import org.codehaus.plexus.classworlds.realm.ClassRealm; 8 | import org.rxjava.apikit.plugin.bean.Group; 9 | 10 | import java.io.IOException; 11 | import java.lang.reflect.Method; 12 | import java.net.MalformedURLException; 13 | import java.net.URL; 14 | import java.net.URLClassLoader; 15 | import java.nio.file.Paths; 16 | import java.util.List; 17 | import java.util.Optional; 18 | import java.util.stream.Stream; 19 | 20 | /** 21 | * @author happy 2019-01-05 15:40 22 | */ 23 | public class MavenUtils { 24 | public static final ObjectMapper MAPPER = new ObjectMapper(); 25 | 26 | static { 27 | MAPPER.enableDefaultTyping(BasicPolymorphicTypeValidator.builder().build(), ObjectMapper.DefaultTyping.NON_FINAL); 28 | } 29 | 30 | public static void generate(MavenProject project, Group group, String sourcePath, String[] srcPaths) { 31 | ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 32 | try { 33 | ClassLoader loader = getUrlClassLoader(project); 34 | @SuppressWarnings("unchecked") 35 | Class generateUtilsClass = (Class) loader 36 | .loadClass(GenerateUtils.class.getName()); 37 | Method generateMethod = generateUtilsClass.getMethod( 38 | "generate", 39 | String.class, 40 | String.class, 41 | String[].class 42 | ); 43 | String groupJson = serialize(group); 44 | /* 45 | * 切换后续操作的classLoad加载器 46 | */ 47 | Thread.currentThread().setContextClassLoader(loader); 48 | generateMethod.invoke(null, groupJson, sourcePath, srcPaths); 49 | } catch (Exception e) { 50 | throw new RuntimeException(e); 51 | } finally { 52 | //还原 53 | Thread.currentThread().setContextClassLoader(contextClassLoader); 54 | } 55 | } 56 | 57 | 58 | public final static String serialize(Object o) { 59 | try { 60 | return MAPPER.writeValueAsString(o); 61 | } catch (IOException e) { 62 | throw new RuntimeException(e.getMessage(), e); 63 | } 64 | } 65 | 66 | 67 | private static URLClassLoader getUrlClassLoader(MavenProject project) throws DependencyResolutionRequiredException { 68 | List compileClasspathElements = project.getCompileClasspathElements(); 69 | List systemClasspathElements = project.getSystemClasspathElements(); 70 | ClassRealm classLoader = (ClassRealm) MavenUtils.class.getClassLoader(); 71 | 72 | Optional apiClassRealm = classLoader.getImportRealms().stream().filter((p) -> "maven.api".equals(p.getId())).findFirst(); 73 | 74 | URL[] urls = Stream.concat( 75 | Stream.concat( 76 | compileClasspathElements.stream().map(MavenUtils::toUrl), 77 | systemClasspathElements.stream().map(MavenUtils::toUrl) 78 | ), 79 | Stream.of(classLoader.getURLs()) 80 | ).toArray(URL[]::new); 81 | 82 | return apiClassRealm 83 | .map(classRealm -> new URLClassLoader(urls, classRealm)) 84 | .orElseGet(() -> new URLClassLoader(urls)); 85 | } 86 | 87 | 88 | private static URL toUrl(String spec) { 89 | try { 90 | return Paths.get(spec).toUri().toURL(); 91 | } catch (MalformedURLException e) { 92 | throw new RuntimeException(e); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-maven-plugin/src/main/java/org/rxjava/apikit/plugin/bean/AbstractTask.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.plugin.bean; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author happy 7 | */ 8 | @Data 9 | abstract class AbstractTask implements Task { 10 | private String outPath; 11 | } 12 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-maven-plugin/src/main/java/org/rxjava/apikit/plugin/bean/GitTask.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.plugin.bean; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author happy 10 | */ 11 | @Getter 12 | @Setter 13 | public class GitTask extends AbstractTask { 14 | private String url; 15 | private String user; 16 | private String password; 17 | private String authorEmail = "apikit@rxjava.org"; 18 | private String authorName = "apikit"; 19 | private Task task; 20 | private String branch = "master"; 21 | private String outPath; 22 | private List deleteUris; 23 | } 24 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-maven-plugin/src/main/java/org/rxjava/apikit/plugin/bean/Group.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.plugin.bean; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author happy 12 | */ 13 | @Getter 14 | @Setter 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class Group { 18 | private List tasks; 19 | private String rootPackage; 20 | private String apiType; 21 | } 22 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-maven-plugin/src/main/java/org/rxjava/apikit/plugin/bean/JavaClientTask.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.plugin.bean; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author happy 8 | */ 9 | @Getter 10 | @Setter 11 | public class JavaClientTask extends AbstractTask { 12 | private String nameMaperSource; 13 | private String nameMaperDist; 14 | private String outRootPackage; 15 | } 16 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-maven-plugin/src/main/java/org/rxjava/apikit/plugin/bean/JavaScriptClientTask.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.plugin.bean; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author happy 8 | */ 9 | @Getter 10 | @Setter 11 | public class JavaScriptClientTask extends AbstractTask { 12 | private String nameMaperSource; 13 | private String nameMaperDist; 14 | private String outRootPackage; 15 | private String serviceId; 16 | } 17 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-maven-plugin/src/main/java/org/rxjava/apikit/plugin/bean/Task.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.plugin.bean; 2 | 3 | /** 4 | * @author happy 5 | */ 6 | public interface Task { 7 | } 8 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/ReadMe.md: -------------------------------------------------------------------------------- 1 | 命名说明: 2 | 3 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | org.rxjava 5 | rxjava-apikit 6 | 1.0.9-SNAPSHOT 7 | 8 | rxjava-apikit-tool 9 | jar 10 | 11 | 12 | org.rxjava 13 | rxjava-apikit-core 14 | ${project.parent.version} 15 | 16 | 17 | org.mongodb 18 | bson 19 | 20 | 21 | org.eclipse.jgit 22 | org.eclipse.jgit 23 | 24 | 25 | org.eclipse.jgit 26 | org.eclipse.jgit.pgm 27 | 28 | 29 | org.slf4j 30 | slf4j-log4j12 31 | 32 | 33 | org.eclipse.jetty 34 | jetty-servlet 35 | 36 | 37 | 38 | 39 | org.eclipse.jdt 40 | org.eclipse.jdt.core 41 | 42 | 43 | javax.validation 44 | validation-api 45 | 46 | 47 | org.springframework 48 | spring-context 49 | 50 | 51 | org.springframework 52 | spring-webflux 53 | 54 | 55 | com.thoughtworks.paranamer 56 | paranamer 57 | 58 | 59 | org.javassist 60 | javassist 61 | 62 | 63 | io.github.lukehutch 64 | fast-classpath-scanner 65 | 66 | 67 | com.github.httl 68 | httl 69 | 70 | 71 | commons-io 72 | commons-io 73 | 74 | 75 | org.slf4j 76 | slf4j-api 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/ApiGenerateManager.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import org.rxjava.apikit.tool.analyse.impl.ControllerAnalyse; 7 | import org.rxjava.apikit.tool.analyse.impl.EnumClassAnalyse; 8 | import org.rxjava.apikit.tool.analyse.impl.ParamClassAnalyse; 9 | import org.rxjava.apikit.tool.generator.Context; 10 | import org.rxjava.apikit.tool.generator.Generator; 11 | import org.rxjava.apikit.tool.utils.LocalPathUtils; 12 | 13 | /** 14 | * @author happy 15 | * Api生成管理器 16 | */ 17 | @Getter 18 | @Setter 19 | @NoArgsConstructor 20 | public class ApiGenerateManager { 21 | /** 22 | * src/main/java的绝对路径 23 | */ 24 | private String javaSourceDir; 25 | /** 26 | * 需要分析的包路径 27 | */ 28 | private String rootPackage; 29 | /** 30 | * 文件编码 31 | */ 32 | private String fileCharset = "utf8"; 33 | /** 34 | * 文件扩展名 35 | */ 36 | private String fileSuffix = ".java"; 37 | /** 38 | * 需要分析的包文件夹路径 39 | */ 40 | private String rootDirPath; 41 | /** 42 | * 上下文 43 | */ 44 | private Context context; 45 | private String[] srcPaths; 46 | 47 | public void generate(Generator generator) throws Exception { 48 | generator.generate(context); 49 | } 50 | 51 | /** 52 | * 开始分析指定文件夹指定包的api及param信息 53 | * 54 | * @param javaSourceDir 源码文件夹路径 55 | * @param rootPackage java包路径 56 | * @return api生成管理器 57 | */ 58 | public static ApiGenerateManager analyse(String javaSourceDir, String rootPackage) { 59 | ApiGenerateManager manager = new ApiGenerateManager(); 60 | manager.javaSourceDir = javaSourceDir; 61 | manager.rootPackage = rootPackage; 62 | //获取java源码的文件夹路径 63 | manager.rootDirPath = LocalPathUtils.packToPath(javaSourceDir, rootPackage).getAbsolutePath(); 64 | manager.context = Context.create(rootPackage, javaSourceDir); 65 | //分析控制器信息并保存到上下文 66 | ControllerAnalyse.create().analyse(manager.context); 67 | //分析参数类型信息并保存到上下文 68 | ParamClassAnalyse.create().analyse(manager.context); 69 | //分析枚举类型信息并保存到上下文 70 | EnumClassAnalyse.create().analyse(manager.context); 71 | return manager; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/analyse/Analyse.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.analyse; 2 | 3 | import org.rxjava.apikit.tool.generator.Context; 4 | 5 | /** 6 | * @author happy 7 | * 分析器 8 | */ 9 | public interface Analyse { 10 | void analyse(Context context); 11 | } 12 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/ApiContext.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator; 2 | 3 | import lombok.Data; 4 | import org.rxjava.apikit.tool.info.ControllerInfo; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author happy 2019/10/26 22:03 11 | * Api上下文 12 | */ 13 | @Data 14 | public class ApiContext { 15 | private List controllerInfos=new ArrayList<>(); 16 | } 17 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/ClassNameMapper.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator; 2 | 3 | import java.util.Set; 4 | 5 | /** 6 | * @author happy 7 | * 类名Mapper接口 8 | */ 9 | public interface ClassNameMapper { 10 | String apply(Set nameSet, String packageName, String name); 11 | } 12 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/Context.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.apache.commons.lang3.ObjectUtils; 6 | import org.rxjava.apikit.tool.info.*; 7 | import org.rxjava.apikit.tool.wrapper.BuilderWrapper; 8 | 9 | import java.util.*; 10 | 11 | /** 12 | * 上下文 13 | * 14 | * @author happy 15 | */ 16 | @Setter 17 | @Getter 18 | public class Context { 19 | 20 | public static Context create(String rootPackage, String javaFilePath) { 21 | Context context = new Context(); 22 | context.rootPackage = rootPackage; 23 | context.javaFilePath = javaFilePath; 24 | return context; 25 | } 26 | 27 | /** 28 | * 包信息 29 | */ 30 | protected PackageInfo apis = new PackageInfo<>(); 31 | /** 32 | * 主包路径 33 | */ 34 | private String rootPackage; 35 | /** 36 | * Java文件路径 37 | */ 38 | private String javaFilePath; 39 | /** 40 | * 消息包装map 41 | */ 42 | private Map> paramClassWrapperMap; 43 | /** 44 | * 消息包装map 45 | */ 46 | private Map> enumParamClassWrapperMap; 47 | /** 48 | * 枚举类 49 | */ 50 | private Set enumInfoSet = new HashSet<>(); 51 | 52 | private TreeMap fullNameParamMap = new TreeMap<>(Comparator.comparing(r -> r)); 53 | 54 | public void addParamClassInfo(ClassInfo key, ParamClassInfo paramClassInfo) { 55 | paramMap.put(key, paramClassInfo); 56 | fullNameParamMap.put(key.getFullName(), paramClassInfo); 57 | } 58 | 59 | public void addEnumParamClassInfo(ClassInfo key, EnumParamClassInfo enumParamClassInfo) { 60 | enumParamMap.put(key, enumParamClassInfo); 61 | } 62 | 63 | private TreeMap paramMap = new TreeMap<>(Comparator.comparing(ClassInfo::getFullName)); 64 | 65 | private TreeMap enumParamMap = new TreeMap<>(Comparator.comparing(ClassInfo::getFullName)); 66 | 67 | public void addApi(ApiClassInfo apiInfo) { 68 | apis.add(apiInfo.getPackageName(), apiInfo); 69 | } 70 | 71 | public Collection getParamClassInfos() { 72 | return paramMap.values(); 73 | } 74 | 75 | public Collection getEnumParamClassInfos() { 76 | return enumParamMap.values(); 77 | } 78 | 79 | public BuilderWrapper getParamWrapper(String fullName) { 80 | return paramClassWrapperMap.get(fullName); 81 | } 82 | 83 | public BuilderWrapper getParamOrEnumWrapper(String fullName) { 84 | BuilderWrapper paramClassInfoBuilderWrapper = paramClassWrapperMap.get(fullName); 85 | if (ObjectUtils.isEmpty(paramClassInfoBuilderWrapper)) { 86 | return enumParamClassWrapperMap.get(fullName); 87 | } 88 | return paramClassInfoBuilderWrapper; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/Generator.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator; 2 | 3 | /** 4 | * @author happy 5 | * 生成器接口 6 | */ 7 | public interface Generator { 8 | /** 9 | * 根据上下文生成 10 | * 11 | * @param context 上下文 12 | */ 13 | void generate(Context context) throws Exception; 14 | 15 | /** 16 | * 获取输出路径 17 | * 18 | * @return 文件输出路径 19 | */ 20 | String getOutPath(); 21 | 22 | /** 23 | * 设置版本号 24 | * 25 | * @param version 版本号 26 | */ 27 | void setVersion(String version); 28 | } 29 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/NameMaper.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator; 2 | 3 | /** 4 | * @author happy 5 | */ 6 | public interface NameMaper { 7 | String apply(String name); 8 | } 9 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/PackageNameMapper.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator; 2 | 3 | /** 4 | * @author happy 5 | * 包名Mapper 6 | */ 7 | public interface PackageNameMapper { 8 | String apply(String sourceRootPackage, String packageName); 9 | } 10 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/impl/AbstractCommonGenerator.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator.impl; 2 | 3 | import org.rxjava.apikit.tool.utils.LocalPathUtils; 4 | import org.rxjava.apikit.tool.wrapper.BuilderWrapper; 5 | 6 | import java.io.File; 7 | 8 | /** 9 | * @author happy 10 | * 抽象类:通用生成器 11 | */ 12 | public abstract class AbstractCommonGenerator extends AbstractHttlGenerator { 13 | /** 14 | * 创建Api文件 15 | */ 16 | File createApiFile(BuilderWrapper wrapper, String suffix) { 17 | String fullDistPackage = wrapper.getFullDistPackage(); 18 | if ("d.ts".equals(suffix) || ("js".equals(suffix))) { 19 | fullDistPackage = ""; 20 | } 21 | return LocalPathUtils.packToPath(outPath, fullDistPackage, wrapper.getDistClassName(), "." + suffix); 22 | } 23 | 24 | /** 25 | * 创建参数类文件 26 | */ 27 | File createParamClassFile(BuilderWrapper wrapper, String suffix) { 28 | return LocalPathUtils.packToPath(outPath, wrapper.getFullDistPackage(wrapper.getDistFolder()), wrapper.getDistClassName(), "." + suffix); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/impl/AbstractHttlGenerator.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator.impl; 2 | 3 | import org.rxjava.apikit.tool.generator.AbstractGenerator; 4 | import org.rxjava.apikit.tool.utils.HttlUtils; 5 | import org.rxjava.apikit.tool.wrapper.BuilderWrapper; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.io.File; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author happy 15 | * 抽象类:Httl模板引擎生成器 16 | */ 17 | abstract class AbstractHttlGenerator extends AbstractGenerator { 18 | private static final Logger log = LoggerFactory.getLogger(AbstractHttlGenerator.class); 19 | 20 | /** 21 | * 执行模块文件生成 22 | */ 23 | void executeModule(BuilderWrapper wrapper, String templPath, File file) throws Exception { 24 | log.info("开始生成文件:{}, templ:{}", file.getAbsolutePath(), templPath); 25 | Map params = new HashMap<>(); 26 | params.put("classInfo", wrapper.getClassInfo()); 27 | params.put("wrapper", wrapper); 28 | HttlUtils.renderFile(file, params, templPath); 29 | log.info("结束生成文件:{}, templ:{}", file.getAbsolutePath(), templPath); 30 | } 31 | 32 | void execute(Map parameters, String templPath, File file) throws Exception { 33 | 34 | log.info("开始生成文件:{}, templ:{}", file.getAbsolutePath(), templPath); 35 | HttlUtils.renderFile(file, parameters, templPath); 36 | log.info("结束生成文件:{}, templ:{}", file.getAbsolutePath(), templPath); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/impl/ApidocGenerator.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator.impl; 2 | 3 | import org.rxjava.apikit.tool.generator.ApiContext; 4 | import org.rxjava.apikit.tool.info.ClassBaseInfo; 5 | import org.rxjava.apikit.tool.utils.HttlUtils; 6 | import org.rxjava.apikit.tool.utils.LocalPathUtils; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.text.ParseException; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.stream.Collectors; 15 | 16 | public class ApidocGenerator { 17 | public void generator(String javaOutApiPath, ApiContext apiContext) { 18 | List nameList = apiContext.getControllerInfos().stream() 19 | .map(ClassBaseInfo::getSimpleName) 20 | .collect(Collectors.toList()); 21 | 22 | Map params = new HashMap<>(); 23 | params.put("nameList", nameList); 24 | File file = LocalPathUtils.packToPath(javaOutApiPath, "test", "api.java"); 25 | try { 26 | HttlUtils.renderFile(file, params, getTemplateFile("test.httl")); 27 | } catch (IOException | ParseException e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | 32 | private String getTemplateFile(String name) { 33 | return "/org/rxjava/apikit/tool/generator/apidoc/" + name; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/impl/DefaultClassNameMapper.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator.impl; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.rxjava.apikit.tool.generator.ClassNameMapper; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * @author happy 10 | * 默认类名Mapper 11 | */ 12 | public class DefaultClassNameMapper implements ClassNameMapper { 13 | @Override 14 | public String apply(Set nameSet, String packageName, String name) { 15 | if (!nameSet.contains(name)) { 16 | return name; 17 | } 18 | String[] packParts = packageName.split("\\."); 19 | 20 | StringBuilder nameSb = new StringBuilder(name); 21 | for (int i = packParts.length - 1; i >= 0; i--) { 22 | String part = packParts[i]; 23 | if (StringUtils.isNotEmpty(part)) { 24 | nameSb.insert(0, Character.toUpperCase(Character.toUpperCase(part.codePointAt(0)))); 25 | nameSb.insert(0, part.substring(1)); 26 | } 27 | String curName = nameSb.toString(); 28 | if (!nameSet.contains(curName)) { 29 | return curName; 30 | } 31 | } 32 | 33 | for (int i = 0; ; i++) { 34 | String curName = name + i; 35 | if (!nameSet.contains(curName)) { 36 | return curName; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/impl/DefaultPackageNameMapper.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator.impl; 2 | 3 | import org.rxjava.apikit.tool.generator.PackageNameMapper; 4 | 5 | /** 6 | * @author happy 7 | * 默认的包名Mapper 8 | */ 9 | public class DefaultPackageNameMapper implements PackageNameMapper { 10 | @Override 11 | public String apply(String sourceRootPackage, String packageName) { 12 | boolean isInPack = packageName.startsWith(sourceRootPackage); 13 | if (isInPack) { 14 | String dist = packageName.substring(sourceRootPackage.length()); 15 | if(dist.startsWith(".")){ 16 | return dist.substring(1); 17 | } 18 | return dist; 19 | }else{ 20 | int index = packageName.lastIndexOf("."); 21 | if(index>-1){ 22 | String dist = packageName.substring(index, packageName.length()); 23 | if(dist.startsWith(".")){ 24 | return dist.substring(1); 25 | } 26 | return dist; 27 | } 28 | } 29 | return "core"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/impl/JavaClientApiGenerator.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator.impl; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.rxjava.apikit.tool.info.ApiClassInfo; 6 | import org.rxjava.apikit.tool.info.EnumParamClassInfo; 7 | import org.rxjava.apikit.tool.info.ParamClassInfo; 8 | import org.rxjava.apikit.tool.wrapper.BuilderWrapper; 9 | import org.rxjava.apikit.tool.wrapper.JavaApiWrapper; 10 | import org.rxjava.apikit.tool.wrapper.JavaEnumParamClassWrapper; 11 | import org.rxjava.apikit.tool.wrapper.JavaParamClassWrapper; 12 | 13 | import java.io.File; 14 | 15 | /** 16 | * @author happy 17 | * Java客户端api生成器 18 | */ 19 | @Setter 20 | @Getter 21 | public class JavaClientApiGenerator extends AbstractCommonGenerator { 22 | 23 | public JavaClientApiGenerator(String rootPackage,String outPath) { 24 | setOutRootPackage(rootPackage); 25 | setOutPath(outPath); 26 | } 27 | 28 | public JavaClientApiGenerator() { 29 | } 30 | 31 | @Override 32 | public void generateBaseFile() { 33 | 34 | } 35 | 36 | /** 37 | * 生成java客户端Api文件 38 | */ 39 | @Override 40 | public void generateApiFile(ApiClassInfo apiInfo) throws Exception { 41 | JavaApiWrapper wrapper = new JavaApiWrapper( 42 | context, apiInfo, outRootPackage, apiNameMaper 43 | ); 44 | File file = createApiFile(wrapper, "java"); 45 | executeModule(wrapper, "/org/rxjava/apikit/tool/generator/java/ApiClass.httl", file); 46 | } 47 | 48 | /** 49 | * 生成参数文件 50 | */ 51 | @Override 52 | public void generateParamFile(BuilderWrapper wrapper) throws Exception { 53 | File file = createParamClassFile(wrapper, "java"); 54 | executeModule( 55 | wrapper, 56 | "/org/rxjava/apikit/tool/generator/java/ParamClass.httl", 57 | file 58 | ); 59 | } 60 | 61 | @Override 62 | public void generateEnumParamFile(BuilderWrapper wrapper) throws Exception { 63 | File file = createParamClassFile(wrapper, "java"); 64 | executeModule( 65 | wrapper, 66 | "/org/rxjava/apikit/tool/generator/java/EnumParamClass.httl", 67 | file 68 | ); 69 | } 70 | 71 | /** 72 | * 创建Java类包装器 73 | * @param paramClassInfo 参数类信息 74 | * @param distPack 发布的包文件夹名 75 | * @param fileName 文件名 76 | */ 77 | @Override 78 | protected JavaParamClassWrapper createParamClassWarpper(ParamClassInfo paramClassInfo, String distPack, String fileName) { 79 | JavaParamClassWrapper javaClassWrapper = new JavaParamClassWrapper(context, paramClassInfo, outRootPackage); 80 | javaClassWrapper.setDistFolder(distPack); 81 | return javaClassWrapper; 82 | } 83 | 84 | /** 85 | * 创建Java枚举类包装器 86 | * @param enumParamClassInfo 参数类信息 87 | * @param distPack 发布的包文件夹名 88 | * @param fileName 文件名 89 | */ 90 | @Override 91 | protected JavaEnumParamClassWrapper createEnumParamClassWarpper(EnumParamClassInfo enumParamClassInfo, String distPack, String fileName) { 92 | JavaEnumParamClassWrapper javaEnumParamClassWrapper = new JavaEnumParamClassWrapper(context, enumParamClassInfo, outRootPackage); 93 | javaEnumParamClassWrapper.setDistFolder(distPack); 94 | return javaEnumParamClassWrapper; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/generator/impl/PatternNameMaper.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.generator.impl; 2 | 3 | import org.rxjava.apikit.tool.generator.NameMaper; 4 | 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | * @author happy 10 | */ 11 | public class PatternNameMaper implements NameMaper { 12 | 13 | /** 14 | * 一个正则表达式解压需要的信息从服务ID获取 15 | * "(?.*)-(?v.*$)" 16 | */ 17 | private Pattern sourcePattern; 18 | /** 19 | * 一个正则表达式关联命名分组定义在服务部分 20 | * "${version}/${name}" 21 | */ 22 | private String distPattern; 23 | 24 | @Override 25 | public String apply(String name) { 26 | Matcher matcher = this.sourcePattern.matcher(name); 27 | String distName = matcher.replaceFirst(this.distPattern); 28 | distName = clean(distName); 29 | return (hasText(distName) ? distName : name); 30 | } 31 | 32 | public PatternNameMaper(String sourcePattern, String distPattern) { 33 | this.sourcePattern = Pattern.compile(sourcePattern); 34 | this.distPattern = distPattern; 35 | } 36 | 37 | private String clean(final String route) { 38 | String routeToClean = route.replaceAll("/{2,}", "/"); 39 | if (routeToClean.startsWith("/")) { 40 | routeToClean = routeToClean.substring(1); 41 | } 42 | if (routeToClean.endsWith("/")) { 43 | routeToClean = routeToClean.substring(0, routeToClean.length() - 1); 44 | } 45 | return routeToClean; 46 | } 47 | 48 | private static boolean hasLength(CharSequence str) { 49 | return str != null && str.length() > 0; 50 | } 51 | 52 | private static boolean hasText(CharSequence str) { 53 | if (!hasLength(str)) { 54 | return false; 55 | } else { 56 | int strLen = str.length(); 57 | 58 | for (int i = 0; i < strLen; ++i) { 59 | if (!Character.isWhitespace(str.charAt(i))) { 60 | return true; 61 | } 62 | } 63 | 64 | return false; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/AnnotationInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author happy 11 | */ 12 | @Getter 13 | @Setter 14 | public class AnnotationInfo { 15 | private ClassTypeInfo typeInfo; 16 | 17 | private List args = new ArrayList<>(); 18 | } 19 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/ApiClassInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import org.rxjava.apikit.core.HttpMethodType; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author happy 12 | * Api类信息 13 | */ 14 | public class ApiClassInfo extends ClassInfo { 15 | /** 16 | * url作为key的map 17 | */ 18 | private Map> methodUrlMap = new HashMap<>(); 19 | /** 20 | * 方法名methodName作为key的map 21 | */ 22 | private Map methodNameMap = new HashMap<>(); 23 | /** 24 | * api方法列表 25 | */ 26 | private List apiMethodList = new ArrayList<>(); 27 | /** 28 | * 添加api方法信息 29 | */ 30 | public void addApiMethod(ApiMethodInfo apiMethodInfo) { 31 | Map map = methodUrlMap.computeIfAbsent(apiMethodInfo.getUrl(), k -> new HashMap<>()); 32 | if (map.put(apiMethodInfo.getType(), apiMethodInfo) != null) { 33 | throw new RuntimeException(apiMethodInfo + "apiMethodInfo严重错误,重复的定义:url" + apiMethodInfo.getUrl() + ",type:" + apiMethodInfo.getType()); 34 | } 35 | if (methodNameMap.put(apiMethodInfo.getMethodName(), apiMethodInfo) != null) { 36 | throw new RuntimeException(apiMethodInfo + "apiMethodInfo严重错误,重复的函数名称" + apiMethodInfo.getMethodName() + ",type:" + apiMethodInfo.getType()); 37 | } 38 | apiMethodInfo.setIndex(apiMethodList.size()); 39 | apiMethodList.add(apiMethodInfo); 40 | } 41 | 42 | public List getApiMethodList() { 43 | return apiMethodList; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/ApiInputClassInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | /** 8 | * @author happy 9 | * Api方法输入类 10 | */ 11 | @Setter 12 | @Getter 13 | public class ApiInputClassInfo extends FieldInfo { 14 | private boolean pathVariable = false; 15 | private boolean formParam = false; 16 | 17 | public ApiInputClassInfo(String name, ClassTypeInfo typeInfo) { 18 | super(name, typeInfo); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/ApiMethodInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Data; 4 | import org.apache.commons.collections4.CollectionUtils; 5 | import org.rxjava.apikit.core.HttpMethodType; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | import java.util.stream.Stream; 11 | 12 | /** 13 | * @author happy 14 | * Api方法信息 15 | */ 16 | @Data 17 | public class ApiMethodInfo { 18 | /** 19 | * 索引号 20 | */ 21 | private int index; 22 | /** 23 | * 方法名 24 | */ 25 | private String methodName; 26 | /** 27 | * 方法请求url 28 | */ 29 | private String url; 30 | /** 31 | * Http请求方法类型,默认为Get 32 | */ 33 | private HttpMethodType[] httpMethodTypes = new HttpMethodType[]{HttpMethodType.GET}; 34 | /** 35 | * 原始类型 36 | */ 37 | private ClassTypeInfo returnClass; 38 | /** 39 | * 返回值的类型 40 | */ 41 | private ClassTypeInfo resultDataType; 42 | /** 43 | * 参数列表 44 | */ 45 | private ArrayList params = new ArrayList<>(); 46 | /** 47 | * 路径参数列表 48 | */ 49 | private ArrayList pathParams = new ArrayList<>(); 50 | /** 51 | * 表单参数列表 52 | */ 53 | private ArrayList formParams = new ArrayList<>(); 54 | /** 55 | * java注释信息 56 | */ 57 | private JavaDocInfo javaDocInfo; 58 | /** 59 | * 是否需要登陆 60 | */ 61 | private boolean login = true; 62 | 63 | public HttpMethodType getType() { 64 | return httpMethodTypes.length > 0 ? httpMethodTypes[0] : null; 65 | } 66 | 67 | public void addParam(ApiInputClassInfo param) { 68 | params.add(param); 69 | if (param.isPathVariable()) { 70 | pathParams.add(param); 71 | } 72 | if (param.isFormParam()) { 73 | formParams.add(param); 74 | } 75 | if (formParams.size() > 1) { 76 | throw new RuntimeException("分析错误!暂时只支持单表单"); 77 | } 78 | } 79 | 80 | protected void findTypes(ClassTypeInfo type, List list) { 81 | list.add(type); 82 | if (CollectionUtils.isNotEmpty(type.getTypeArguments())) { 83 | type.getTypeArguments().forEach(t -> findTypes(t, list)); 84 | } 85 | } 86 | 87 | public List getAllTypes() { 88 | return Stream.of(this) 89 | .flatMap(m -> { 90 | List types = new ArrayList<>(); 91 | types.add(m.getResultDataType()); 92 | m.getParams().forEach(p -> types.add(p.getTypeInfo())); 93 | return types.stream(); 94 | }) 95 | .flatMap(type -> { 96 | List types = new ArrayList<>(); 97 | findTypes(type, types); 98 | return types.stream(); 99 | }) 100 | .filter(typeInfo -> typeInfo.getType().equals(ClassTypeInfo.Type.OTHER)) 101 | .filter(typeInfo -> !typeInfo.isCollection()) 102 | .filter(typeInfo -> !typeInfo.isGeneric()) 103 | .distinct() 104 | .collect(Collectors.toList()); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/ClassBaseInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author happy 2019/10/27 17:56 8 | * 类基本信息 9 | */ 10 | @Getter 11 | @Setter 12 | public class ClassBaseInfo { 13 | /** 14 | * 所在包(org.rxjava.apikit.tool.info) 15 | * 包名为null代表为基本类型:如int,long等 16 | */ 17 | private String packageName; 18 | /** 19 | * 简单类名(ClassBaseInfo) 20 | */ 21 | private String simpleName; 22 | /** 23 | * 全类名(org.rxjava.apikit.tool.info.ClassBaseInfo) 24 | */ 25 | private String name; 26 | } 27 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/ClassInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | 9 | /** 10 | * @author happy 11 | */ 12 | @Setter 13 | @Getter 14 | @EqualsAndHashCode 15 | @NoArgsConstructor 16 | public class ClassInfo { 17 | /** 18 | * Java文档信息 19 | */ 20 | protected JavaDocInfo javaDocInfo; 21 | /** 22 | * 包名 23 | */ 24 | private String packageName; 25 | /** 26 | * 类名 27 | */ 28 | private String className; 29 | 30 | public String getFullName() { 31 | return packageName + "." + className; 32 | } 33 | 34 | public ClassInfo(String packageName, String className) { 35 | this.packageName = packageName; 36 | this.className = className; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/ControllerInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.rxjava.apikit.tool.type.ApiType; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author happy 2019/10/26 22:22 11 | * 控制器信息 12 | */ 13 | @Getter 14 | @Setter 15 | public class ControllerInfo extends ClassBaseInfo{ 16 | /** 17 | * 控制器请求方法列表 18 | */ 19 | private List methodInfos; 20 | /** 21 | * api接口类型 22 | * person:用户 23 | * admin:管理 24 | * inner:内部 25 | */ 26 | private ApiType apiType; 27 | } 28 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/ControllerMethodInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Data; 4 | import org.rxjava.apikit.core.HttpMethodType; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author happy 2019/10/26 22:32 11 | * 控制器方法信息 12 | */ 13 | @Data 14 | public class ControllerMethodInfo { 15 | /** 16 | * 方法名 17 | */ 18 | private String methodName; 19 | /** 20 | * 请求url 21 | */ 22 | private String requestUrl; 23 | /** 24 | * http请求方法数组 25 | */ 26 | private HttpMethodType[] httpMethodTypes; 27 | /** 28 | * 输入参数信息列表 29 | */ 30 | private List inputParamInfos = new ArrayList<>(); 31 | /** 32 | * 输出参数信息 33 | */ 34 | private ParamInfo returnParamInfo; 35 | 36 | public void addInputParams(InputParamInfo inputParamInfo) { 37 | inputParamInfos.add(inputParamInfo); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/EnumConstantInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class EnumConstantInfo { 7 | private String name; 8 | private int ordinal; 9 | } 10 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/EnumParamClassInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.apache.commons.collections4.CollectionUtils; 6 | import org.eclipse.jdt.core.dom.TagElement; 7 | import org.eclipse.jdt.core.dom.TextElement; 8 | import org.eclipse.jdt.core.dom.TypeDeclaration; 9 | 10 | import java.util.*; 11 | 12 | /** 13 | * @author happy 14 | * 方法参数类信息(入参和出参) 15 | */ 16 | @Getter 17 | @Setter 18 | public class EnumParamClassInfo extends ClassInfo { 19 | private List properties = new ArrayList<>(); 20 | private Map propertiesMap = new HashMap<>(); 21 | /** 22 | * 父类类型信息 23 | */ 24 | private ClassTypeInfo superType; 25 | private Class clazz; 26 | protected TypeDeclaration type; 27 | private List typeParameters = new ArrayList<>(); 28 | /** 29 | * 枚举常量信息 30 | */ 31 | private List enumConstantInfos; 32 | 33 | public JavaDocInfo getClassComment() { 34 | return transform(type.getJavadoc()); 35 | } 36 | 37 | protected static JavaDocInfo transform(org.eclipse.jdt.core.dom.Javadoc javadoc) { 38 | if (javadoc == null) { 39 | return null; 40 | } 41 | JavaDocInfo javadocInfo = new JavaDocInfo(); 42 | List tags = javadoc.tags(); 43 | for (Object tag : tags) { 44 | TagElement tagElement = (TagElement) tag; 45 | String tagName = tagElement.getTagName(); 46 | 47 | List fragments = tagElement.fragments(); 48 | ArrayList fragmentsInfo = new ArrayList<>(); 49 | for (Object fragment : fragments) { 50 | if (fragment instanceof TextElement) { 51 | TextElement textElement = (TextElement) fragment; 52 | fragmentsInfo.add(textElement.getText()); 53 | } else { 54 | fragmentsInfo.add(fragment.toString()); 55 | } 56 | } 57 | javadocInfo.add(tagName, fragmentsInfo); 58 | } 59 | return javadocInfo; 60 | } 61 | 62 | public void addTypeParameter(String typeParameter) { 63 | typeParameters.add(typeParameter); 64 | } 65 | 66 | public void add(PropertyInfo attributeInfo) { 67 | properties.add(attributeInfo); 68 | propertiesMap.put(attributeInfo.getFieldName(), attributeInfo); 69 | } 70 | 71 | public void sortPropertys() { 72 | properties.sort(Comparator.comparing(FieldInfo::getFieldName)); 73 | } 74 | 75 | 76 | public boolean hasGenerics() { 77 | return CollectionUtils.isNotEmpty(getTypeParameters()); 78 | } 79 | 80 | public List getTypeParameters() { 81 | return typeParameters; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/FieldInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author happy 11 | * 字段信息 12 | */ 13 | @Setter 14 | @Getter 15 | public class FieldInfo { 16 | /** 17 | * 类型信息 18 | */ 19 | private ClassTypeInfo typeInfo; 20 | /** 21 | * 字段名 22 | */ 23 | private String fieldName; 24 | /** 25 | * 字段注解 26 | */ 27 | private List annotations = new ArrayList<>(); 28 | 29 | public FieldInfo(String fieldName, ClassTypeInfo typeInfo) { 30 | this.fieldName = fieldName; 31 | this.typeInfo = typeInfo; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/Import.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author happy 8 | */ 9 | @Setter 10 | @Getter 11 | public class Import { 12 | /** 13 | * 包名 14 | */ 15 | private String packageName; 16 | /** 17 | * 类名 18 | */ 19 | private String className; 20 | /** 21 | * 是否需要进行包转换 22 | */ 23 | private boolean inside; 24 | /** 25 | * 按需 26 | */ 27 | private boolean onDemand; 28 | 29 | public Import(String packageName, String className, boolean inside, boolean onDemand) { 30 | this.packageName = packageName; 31 | this.className = className; 32 | this.inside = inside; 33 | this.onDemand = onDemand; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/InputParamInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author happy 2019/10/27 00:24 8 | * 输入的参数信息 9 | */ 10 | @Getter 11 | @Setter 12 | public class InputParamInfo extends ParamInfo { 13 | /** 14 | * 是否有@PathVariable注解 15 | */ 16 | private boolean pathVariable; 17 | /** 18 | * 是否有@Valid注解 19 | */ 20 | private boolean valid; 21 | } 22 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/JavaDocInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import com.google.common.collect.ListMultimap; 4 | import com.google.common.collect.Multimaps; 5 | 6 | import java.util.*; 7 | import java.util.stream.Collectors; 8 | 9 | /** 10 | * javadoc 注释信息 11 | * 12 | * @author happy 13 | */ 14 | public class JavaDocInfo { 15 | 16 | /** 17 | * List>> 结构是 tagName -> fragments list 18 | */ 19 | private ListMultimap> tags = Multimaps.newListMultimap( 20 | new LinkedHashMap<>(), ArrayList::new 21 | ); 22 | 23 | /** 24 | * 获取注释第一行 25 | */ 26 | public String getFirstRow(){ 27 | if (tags.isEmpty()) { 28 | return "请设置控制器中文名"; 29 | } 30 | List> tagsList = tags.get(null); 31 | if (tagsList.isEmpty()) { 32 | return "请设置控制器中文名"; 33 | } 34 | List tagValues = tagsList.get(0); 35 | return tagValues.get(0); 36 | } 37 | 38 | public void add(String tagName, List fragmentsInfo) { 39 | tags.put(tagName, fragmentsInfo); 40 | } 41 | 42 | public List> get(String tagName) { 43 | return tags.get(tagName); 44 | } 45 | 46 | public String getToString(String tagName, CharSequence delimiter) { 47 | return getToString(tagName, delimiter, "", ""); 48 | } 49 | 50 | public String getToString(String tagName) { 51 | return getToString(tagName, " ", "", ""); 52 | } 53 | 54 | public String getToString(String tagName, CharSequence delimiter, CharSequence prefix, CharSequence suffix) { 55 | return tags.get(tagName).stream().flatMap(Collection::stream).collect(Collectors.joining(delimiter, prefix, suffix)); 56 | } 57 | 58 | public String getByParamToString(String param, CharSequence delimiter) { 59 | return getByParamToString(param, delimiter, "", ""); 60 | } 61 | 62 | public String getByParamToString(String param, CharSequence delimiter, CharSequence prefix, CharSequence suffix) { 63 | return tags.get("@param").stream() 64 | .filter(r -> !r.isEmpty() && r.get(0).equals(param)) 65 | .flatMap(item -> item.stream().skip(1)) 66 | .collect(Collectors.joining(delimiter, prefix, suffix)); 67 | } 68 | 69 | public ListMultimap> getTags() { 70 | return tags; 71 | } 72 | 73 | public Map.Entry>> getTags(int index) { 74 | int i = 0; 75 | for (Map.Entry>> entry : tags.asMap().entrySet()) { 76 | if (i == index) { 77 | return entry; 78 | } 79 | i++; 80 | } 81 | return null; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/PackageInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import com.google.common.collect.ListMultimap; 4 | import com.google.common.collect.Multimap; 5 | import com.google.common.collect.Multimaps; 6 | 7 | import java.util.Collection; 8 | import java.util.concurrent.ConcurrentSkipListMap; 9 | import java.util.concurrent.CopyOnWriteArrayList; 10 | 11 | /** 12 | * @author happy 13 | */ 14 | public class PackageInfo { 15 | 16 | private Multimap multimap = Multimaps.newListMultimap( 17 | new ConcurrentSkipListMap<>(), CopyOnWriteArrayList::new 18 | ); 19 | 20 | public void add(String packageName, T t) { 21 | multimap.put(packageName, t); 22 | } 23 | 24 | public Collection getValues() { 25 | return multimap.values(); 26 | } 27 | 28 | public static void main(String[] args) { 29 | ListMultimap multimap = Multimaps.newListMultimap(new ConcurrentSkipListMap<>(), CopyOnWriteArrayList::new); 30 | multimap.put("hello", "hi"); 31 | multimap.put("hello", "hia"); 32 | multimap.put("hello", "hi"); 33 | System.out.println(multimap.values()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/ParamClassInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.apache.commons.collections4.CollectionUtils; 6 | import org.eclipse.jdt.core.dom.TagElement; 7 | import org.eclipse.jdt.core.dom.TextElement; 8 | import org.eclipse.jdt.core.dom.TypeDeclaration; 9 | 10 | import java.util.*; 11 | 12 | /** 13 | * @author happy 14 | * 方法参数类信息(入参和出参) 15 | */ 16 | @Getter 17 | @Setter 18 | public class ParamClassInfo extends ClassInfo { 19 | private List properties = new ArrayList<>(); 20 | private Map propertiesMap = new HashMap<>(); 21 | /** 22 | * 父类类型信息 23 | */ 24 | private ClassTypeInfo superType; 25 | private Class clazz; 26 | protected TypeDeclaration type; 27 | private List typeParameters = new ArrayList<>(); 28 | 29 | public JavaDocInfo getClassComment() { 30 | return transform(type.getJavadoc()); 31 | } 32 | 33 | protected static JavaDocInfo transform(org.eclipse.jdt.core.dom.Javadoc javadoc) { 34 | if (javadoc == null) { 35 | return null; 36 | } 37 | JavaDocInfo javadocInfo = new JavaDocInfo(); 38 | List tags = javadoc.tags(); 39 | for (Object tag : tags) { 40 | TagElement tagElement = (TagElement) tag; 41 | String tagName = tagElement.getTagName(); 42 | 43 | List fragments = tagElement.fragments(); 44 | ArrayList fragmentsInfo = new ArrayList<>(); 45 | for (Object fragment : fragments) { 46 | if (fragment instanceof TextElement) { 47 | TextElement textElement = (TextElement) fragment; 48 | fragmentsInfo.add(textElement.getText()); 49 | } else { 50 | fragmentsInfo.add(fragment.toString()); 51 | } 52 | } 53 | javadocInfo.add(tagName, fragmentsInfo); 54 | } 55 | return javadocInfo; 56 | } 57 | 58 | public void addTypeParameter(String typeParameter) { 59 | typeParameters.add(typeParameter); 60 | } 61 | 62 | public void add(PropertyInfo attributeInfo) { 63 | properties.add(attributeInfo); 64 | propertiesMap.put(attributeInfo.getFieldName(), attributeInfo); 65 | } 66 | 67 | public void sortPropertys() { 68 | properties.sort(Comparator.comparing(FieldInfo::getFieldName)); 69 | } 70 | 71 | 72 | public boolean hasGenerics() { 73 | return CollectionUtils.isNotEmpty(getTypeParameters()); 74 | } 75 | 76 | public List getTypeParameters() { 77 | return typeParameters; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/ParamInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author happy 2019/10/27 17:52 12 | */ 13 | @Getter 14 | @Setter 15 | public class ParamInfo extends ClassBaseInfo { 16 | /** 17 | * 是否数组 18 | */ 19 | private boolean array; 20 | /** 21 | * 参数字段名 22 | */ 23 | private String fieldName; 24 | /** 25 | * 子参数信息 26 | * 为null则说明是不再分析的类型 27 | */ 28 | private List childParamInfo; 29 | /** 30 | * 泛型中的实际类型列表 31 | * 非null则说明是泛型 32 | */ 33 | private Map actualTypes; 34 | } 35 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/PropertyInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | /** 8 | * @author happy 9 | * 属性信息 10 | */ 11 | @Setter 12 | @Getter 13 | public class PropertyInfo extends FieldInfo { 14 | 15 | private JavaDocInfo javadocInfo; 16 | 17 | public PropertyInfo(String name, ClassTypeInfo typeInfo) { 18 | super(name, typeInfo); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/TestInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author happy 2019/10/28 00:16 11 | */ 12 | @Getter 13 | @Setter 14 | public class TestInfo { 15 | private String id; 16 | private int num; 17 | private boolean ok; 18 | private List list; 19 | private Map map; 20 | } 21 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/info/TestSuperInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.info; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class TestSuperInfo { 9 | private String testSuperInfoId; 10 | } 11 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/type/ApiType.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.type; 2 | 3 | /** 4 | * @author happy 2019/10/27 02:16 5 | * api接口类型 6 | */ 7 | public enum ApiType { 8 | /** 9 | * 客户 10 | */ 11 | person, 12 | /** 13 | * 管理 14 | */ 15 | admin, 16 | /** 17 | * 内部 18 | */ 19 | inner 20 | } 21 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/utils/CommentUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.utils; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.rxjava.apikit.tool.info.JavaDocInfo; 5 | 6 | import java.util.*; 7 | import java.util.stream.Collectors; 8 | 9 | /** 10 | * @author happy 11 | */ 12 | public class CommentUtils { 13 | /** 14 | * 获取注释不包含tag的内容 15 | */ 16 | public static String getCommentNoTag(JavaDocInfo comment, String start) { 17 | if (comment == null) { 18 | return start; 19 | } 20 | StringBuilder sb = new StringBuilder(); 21 | 22 | for (String tagName : comment.getTags().keySet()) { 23 | if (StringUtils.isEmpty(tagName)) { 24 | sb.append(start); 25 | formatCommentItem(comment, start, sb, tagName); 26 | } 27 | } 28 | if (sb.length() > 0) { 29 | return sb.toString(); 30 | } else { 31 | return start; 32 | } 33 | } 34 | 35 | /** 36 | * 获取注释不带tabName的内容 37 | */ 38 | public static String getBaseComment(JavaDocInfo comment, String start) { 39 | if (comment == null) { 40 | return start; 41 | } 42 | StringBuilder sb = new StringBuilder(); 43 | 44 | List> lists = comment.get(null); 45 | lists.stream().flatMap(Collection::stream).forEach(c -> { 46 | sb.append(start); 47 | sb.append(StringUtils.trimToEmpty(c).replace("\n", "").replace("\r", "")); 48 | sb.append("\n"); 49 | }); 50 | String str = StringUtils.stripEnd(sb.toString(), null); 51 | if (str.length() > 0) { 52 | return str; 53 | } else { 54 | return start; 55 | } 56 | } 57 | 58 | /** 59 | * 格式化注释 60 | */ 61 | private static void formatCommentItem(JavaDocInfo comment, String start, StringBuilder sb, String tagName) { 62 | List> fragments = comment.getTags().get(tagName); 63 | sb.append(fragments.stream().flatMap(Collection::stream).collect(Collectors.joining("\n" + start))); 64 | } 65 | 66 | /** 67 | * 获取注释 68 | */ 69 | public static String getComment(JavaDocInfo comment, String start) { 70 | if (comment == null) { 71 | return start; 72 | } 73 | StringBuilder sb = new StringBuilder(); 74 | for (String tagName : comment.getTags().keySet()) { 75 | sb.append(start); 76 | if (StringUtils.isNotEmpty(tagName)) { 77 | sb.append(tagName); 78 | sb.append(' '); 79 | } 80 | formatCommentItem(comment, start, sb, tagName); 81 | sb.append("\n"); 82 | } 83 | if (sb.length() > 0) { 84 | sb.setLength(sb.length() - 1); 85 | } 86 | return sb.toString(); 87 | } 88 | 89 | /** 90 | * 转化注释为map 91 | */ 92 | public static Map toMap(JavaDocInfo comment) { 93 | if (comment == null) { 94 | return Collections.emptyMap(); 95 | } 96 | Map map = new HashMap<>(); 97 | 98 | for (String tagName : comment.getTags().keySet()) { 99 | StringBuilder sb = new StringBuilder(); 100 | 101 | boolean isParam = "@param".equals(tagName); 102 | 103 | Collection> fragments = comment.getTags().get(tagName); 104 | 105 | if (isParam) { 106 | fragments.forEach(fragment -> { 107 | if (!fragment.isEmpty()) { 108 | String paramName = fragment.get(0); 109 | map.put(paramName, fragments.stream().skip(1).flatMap(Collection::stream).collect(Collectors.joining(" "))); 110 | } 111 | }); 112 | } else { 113 | map.put(tagName, fragments.stream().flatMap(Collection::stream).collect(Collectors.joining(" "))); 114 | } 115 | } 116 | return map; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/utils/DateTimeUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.utils; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | 7 | /** 8 | * 日期帮助类 9 | * 10 | * @author happy 11 | */ 12 | public class DateTimeUtils { 13 | 14 | static final String FORMAT = "yyyy-MM-dd HH:mm:ss"; 15 | 16 | /** 17 | * 格式化日期为字符串 18 | */ 19 | public static String format(Date date) { 20 | SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT); 21 | dateFormat.setLenient(false); 22 | return dateFormat.format(date); 23 | } 24 | 25 | /** 26 | * 解析日期字符串 27 | */ 28 | public static Date parse(String date) throws ParseException { 29 | SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT); 30 | dateFormat.setLenient(false); 31 | return dateFormat.parse(date); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/utils/HttlUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.utils; 2 | 3 | import httl.Engine; 4 | import httl.Template; 5 | import org.apache.commons.io.FileUtils; 6 | import org.apache.commons.io.output.StringBuilderWriter; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.text.ParseException; 13 | import java.util.Map; 14 | import java.util.Properties; 15 | 16 | /** 17 | * Httl模版引擎帮助类 18 | */ 19 | public class HttlUtils { 20 | 21 | private static final Logger log = LoggerFactory.getLogger(HttlUtils.class); 22 | /** 23 | * 文件编码 24 | */ 25 | private static final String FILE_ENCODING = "utf8"; 26 | 27 | private static Engine getEngine() { 28 | return Inner.ENGINE; 29 | } 30 | 31 | 32 | private static class Inner { 33 | private static final Engine ENGINE; 34 | 35 | static { 36 | Properties configProperties = new Properties(); 37 | try { 38 | configProperties.load(HttlUtils.class.getResourceAsStream("/org/rxjava/apikit/tool/httl.properties")); 39 | ENGINE = Engine.getEngine(configProperties); 40 | } catch (IOException e) { 41 | throw new RuntimeException(e); 42 | } 43 | } 44 | } 45 | 46 | /** 47 | * 根据模板生成文件 48 | */ 49 | public static void renderFile(File file, Map params, String templPath) throws IOException, ParseException { 50 | if (!file.getParentFile().exists()) { 51 | synchronized (HttlUtils.class) { 52 | if (!file.getParentFile().exists()) { 53 | if (!file.getParentFile().mkdirs()) { 54 | throw new RuntimeException("创建路径失败!"); 55 | } 56 | } 57 | } 58 | } 59 | 60 | String code = renderToString(params, templPath); 61 | if (file.getName().endsWith(".java")) { 62 | String formatCode = JavaFileFormat.formatCode(code); 63 | writeStringToFile(file, formatCode); 64 | log.info("生成一个文件{}", file.getAbsolutePath()); 65 | } else { 66 | writeStringToFile(file, code); 67 | log.info("生成一个文件{}", file.getAbsolutePath()); 68 | } 69 | } 70 | 71 | private static void writeStringToFile(File file, String data) throws IOException { 72 | data = data.replaceAll("(\r\n|\r|\n|\n\r)", "\r\n"); 73 | FileUtils.writeStringToFile(file, data, HttlUtils.FILE_ENCODING); 74 | } 75 | 76 | private static String renderToString(Map params, String templPath) throws IOException, ParseException { 77 | StringBuilderWriter writer = new StringBuilderWriter(); 78 | Template template = getEngine().getTemplate(templPath); 79 | template.render(params, writer); 80 | log.info("生成一个文件到字符串"); 81 | return writer.toString(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/utils/JavaFileFormat.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.utils; 2 | 3 | import org.eclipse.jdt.core.JavaCore; 4 | import org.eclipse.jdt.core.ToolFactory; 5 | import org.eclipse.jdt.core.formatter.CodeFormatter; 6 | import org.eclipse.jface.text.Document; 7 | import org.eclipse.jface.text.IDocument; 8 | import org.eclipse.text.edits.TextEdit; 9 | 10 | import java.util.Map; 11 | 12 | /** 13 | * Java代码格式化 14 | */ 15 | public class JavaFileFormat { 16 | 17 | public static final CodeFormatter CODE_FORMATTER = createCodeFormatter(); 18 | 19 | private static CodeFormatter createCodeFormatter() { 20 | Map options = JavaCore.getOptions(); 21 | JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); 22 | options.put("org.eclipse.jdt.core.formatter.lineSplit", "120"); 23 | return ToolFactory.createCodeFormatter(options); 24 | } 25 | 26 | public synchronized static String formatCode(String contents) { 27 | IDocument doc = new Document(contents); 28 | TextEdit edit = CODE_FORMATTER.format( 29 | CodeFormatter.K_COMPILATION_UNIT, doc.get(), 0, doc.get() 30 | .length(), 0, null); 31 | if (edit != null) { 32 | try { 33 | edit.apply(doc); 34 | contents = doc.get(); 35 | } catch (Exception e) { 36 | throw new RuntimeException(e); 37 | } 38 | } 39 | return contents; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/utils/JsonUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.utils; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.core.JsonFactory; 5 | import com.fasterxml.jackson.core.JsonParser; 6 | import com.fasterxml.jackson.core.type.TypeReference; 7 | import com.fasterxml.jackson.databind.*; 8 | import com.fasterxml.jackson.datatype.guava.GuavaModule; 9 | 10 | import java.io.IOException; 11 | import java.lang.reflect.Type; 12 | import java.text.SimpleDateFormat; 13 | import java.util.List; 14 | 15 | /** 16 | * @author happy 17 | */ 18 | public class JsonUtils { 19 | public static final ObjectMapper MAPPER = new ObjectMapper(); 20 | 21 | static { 22 | MAPPER.registerModule(new GuavaModule()); 23 | MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 24 | MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); 25 | MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); 26 | SimpleDateFormat dateFormat = new SimpleDateFormat(DateTimeUtils.FORMAT); 27 | dateFormat.setLenient(false); 28 | MAPPER.setDateFormat(dateFormat); 29 | } 30 | 31 | public static ObjectMapper getObjectMapper() { 32 | return MAPPER; 33 | } 34 | 35 | public static final JsonFactory JSON_FACTORY = new JsonFactory(); 36 | 37 | /** 38 | * 不能处理复杂情况,和继承情况 39 | */ 40 | public static String serialize(Object o) { 41 | try { 42 | if (o instanceof List) { 43 | return MAPPER.writeValueAsString(((List) o).toArray()); 44 | } 45 | return MAPPER.writeValueAsString(o); 46 | } catch (IOException e) { 47 | throw new RuntimeException(e.getMessage(), e); 48 | } 49 | } 50 | 51 | /** 52 | * 不能处理复杂情况,和继承情况 53 | */ 54 | public static T deserialize(String json, Class valueType) { 55 | try { 56 | return MAPPER.readValue(json, valueType); 57 | } catch (IOException e) { 58 | throw new RuntimeException(e.getMessage(), e); 59 | } 60 | } 61 | 62 | public static T deserialize(String json, Class parentClass, Class... elementClasses) { 63 | try { 64 | JavaType javaType = MAPPER.getTypeFactory().constructParametricType( 65 | parentClass, elementClasses 66 | ); 67 | return MAPPER.readValue(json, javaType); 68 | } catch (IOException e) { 69 | throw new RuntimeException(e.getMessage(), e); 70 | } 71 | } 72 | 73 | /** 74 | * 不能处理复杂情况,和继承情况 75 | * 对付一般的List;MyClass; 方式足够了 76 | */ 77 | public static T deserialize(String json, TypeReference valueTypeRef) { 78 | try { 79 | return MAPPER.readValue(json, valueTypeRef); 80 | } catch (IOException e) { 81 | throw new RuntimeException(e.getMessage(), e); 82 | } 83 | } 84 | 85 | public static JsonNode deserialize(String json) { 86 | try { 87 | return MAPPER.readTree(json); 88 | } catch (IOException e) { 89 | throw new RuntimeException(e.getMessage(), e); 90 | } 91 | } 92 | 93 | public static ObjectMapper create(boolean isNoDefault) { 94 | return create(isNoDefault, DateTimeUtils.FORMAT); 95 | } 96 | 97 | public static ObjectMapper create(boolean isNoDefault, String dateFormat) { 98 | ObjectMapper mapper = new ObjectMapper(); 99 | mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true); 100 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 101 | mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, true); 102 | if (isNoDefault) { 103 | mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); 104 | } 105 | mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); 106 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat); 107 | simpleDateFormat.setLenient(false); 108 | mapper.setDateFormat(simpleDateFormat); 109 | return mapper; 110 | } 111 | 112 | 113 | } 114 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/utils/LocalPathUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.utils; 2 | 3 | import org.rxjava.apikit.tool.info.Import; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * 路径帮助类 9 | * 10 | * @author happy 11 | */ 12 | public final class LocalPathUtils { 13 | 14 | /** 15 | * 获取指定路径下文件并修改名称+后缀 16 | */ 17 | public static File packToPath(String path, String packname, String name, String suffix) { 18 | File file = packToPath(path, packname); 19 | return new File(file, name + suffix); 20 | } 21 | 22 | /** 23 | * 获取指定路径下文件 24 | */ 25 | public static File packToPath(String path, String packageName) { 26 | return new File(path, packageName.replace(".", File.separator)); 27 | } 28 | 29 | /** 30 | * 获取指定路径下文件并修改名称 31 | */ 32 | public static File packToPath(String path, String packname, String name) { 33 | File file = packToPath(path, packname); 34 | return new File(file, name); 35 | } 36 | 37 | /** 38 | * 路径转为包格式 39 | */ 40 | public static String pathToPack(String path) { 41 | return path.replace(File.separator, "."); 42 | } 43 | 44 | /** 45 | * 字符串首字母大写 46 | */ 47 | public static String toClassName(String str) { 48 | StringBuilder sb = new StringBuilder(); 49 | for (int i = 0; i < str.length(); i++) { 50 | char c = str.charAt(i); 51 | if (0 == i) { 52 | sb.append(Character.toUpperCase(c)); 53 | } else { 54 | sb.append(c); 55 | } 56 | } 57 | return sb.toString(); 58 | } 59 | 60 | /** 61 | * 检查是否在Lang包中的类 62 | */ 63 | public static Import getLangImport(String name) { 64 | try { 65 | Class aClass = Class.forName("java.lang" + "." + name); 66 | return new Import("java.lang", name, false, false); 67 | } catch (ClassNotFoundException e) { 68 | return null; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/utils/NameUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.utils; 2 | 3 | /** 4 | * @author happy 5 | * 命名帮助类 6 | */ 7 | public class NameUtils { 8 | /** 9 | * 首字母小写 10 | */ 11 | public static String toFieldName(String name) { 12 | if (!name.isEmpty()) { 13 | char c = name.charAt(0); 14 | return Character.toLowerCase(c) + name.substring(1); 15 | } 16 | return name; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/utils/OrderStatus.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.utils; 2 | 3 | /** 4 | * 订单状态 5 | */ 6 | public enum OrderStatus { 7 | /** 8 | * 已创建 9 | */ 10 | CREATED, 11 | /** 12 | * 已付款 13 | */ 14 | PAID, 15 | /** 16 | * 已发货 17 | */ 18 | SHIPPED, 19 | /** 20 | * 确认收货 21 | */ 22 | CONFIRMED, 23 | /** 24 | * 取消订单 25 | */ 26 | CANCELLED; 27 | } 28 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/wrapper/BuilderWrapper.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.wrapper; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.apache.commons.collections4.CollectionUtils; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.rxjava.apikit.tool.generator.Context; 8 | import org.rxjava.apikit.tool.info.JavaDocInfo; 9 | import org.rxjava.apikit.tool.info.ClassInfo; 10 | import org.rxjava.apikit.tool.info.ClassTypeInfo; 11 | import org.rxjava.apikit.tool.utils.CommentUtils; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * @author happy 17 | * 生成器包装类 18 | */ 19 | @Setter 20 | @Getter 21 | public class BuilderWrapper { 22 | /** 23 | * 类信息 24 | */ 25 | protected T classInfo; 26 | /** 27 | * 发布的根包 28 | */ 29 | private String distRootPackage; 30 | /** 31 | * 微服务Id 32 | */ 33 | private String serviceId; 34 | /** 35 | * 发布的文件夹 36 | */ 37 | protected String distFolder; 38 | /** 39 | * 上下文 40 | */ 41 | protected Context context; 42 | 43 | BuilderWrapper(Context context, T classInfo, String distRootPackage) { 44 | this.context = context; 45 | this.classInfo = classInfo; 46 | this.distRootPackage = distRootPackage; 47 | } 48 | 49 | public String getDistClassName() { 50 | return classInfo.getClassName(); 51 | } 52 | 53 | public String getFullDistPackage() { 54 | //源码所在的包 55 | String sourcePackage = classInfo.getPackageName(); 56 | //源码所在的根包 57 | String sourceRootPackage = context.getRootPackage(); 58 | 59 | String distFolder = sourcePackage.replace(sourceRootPackage, ""); 60 | 61 | if (distFolder.startsWith(".")) { 62 | distFolder = distFolder.substring(1); 63 | } 64 | //如果源码所在的包根根包不一致,则仅仅获取源码所在的文件夹 65 | String[] floders = distFolder.split("\\."); 66 | if (!sourcePackage.contains(sourceRootPackage) && floders.length > 1) { 67 | distFolder = floders[floders.length - 1]; 68 | } 69 | return getFullDistPackage(distFolder); 70 | } 71 | 72 | public String getDistPackage() { 73 | return getFullDistPackage(getDistFolder()); 74 | } 75 | 76 | public String getFullDistPackage(String distFolder) { 77 | if (StringUtils.isEmpty(distFolder)) { 78 | if (distRootPackage == null) { 79 | return ""; 80 | } 81 | return distRootPackage; 82 | } else { 83 | if (StringUtils.isEmpty(distRootPackage)) { 84 | return distFolder; 85 | } else { 86 | return distRootPackage + "." + distFolder; 87 | } 88 | } 89 | } 90 | 91 | void findTypes(ClassTypeInfo type, List list) { 92 | list.add(type); 93 | if (CollectionUtils.isNotEmpty(type.getTypeArguments())) { 94 | type.getTypeArguments().forEach(t -> findTypes(t, list)); 95 | } 96 | } 97 | 98 | public String getSourceFullName() { 99 | return classInfo.getPackageName() + "." + classInfo.getClassName(); 100 | } 101 | 102 | public String comment(String start) { 103 | JavaDocInfo comment = classInfo.getJavaDocInfo(); 104 | return CommentUtils.getComment(comment, start); 105 | } 106 | 107 | public static String formatBaseComment(JavaDocInfo comment, String start) { 108 | return CommentUtils.getBaseComment(comment, start); 109 | } 110 | 111 | public static String formatComment(JavaDocInfo comment, String start) { 112 | return CommentUtils.getComment(comment, start); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/wrapper/JavaEnumParamClassWrapper.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.wrapper; 2 | 3 | import org.rxjava.apikit.tool.generator.Context; 4 | import org.rxjava.apikit.tool.info.EnumParamClassInfo; 5 | 6 | /** 7 | * @author happy 8 | * Java参数类信息包装器 9 | */ 10 | public class JavaEnumParamClassWrapper extends JavaWrapper { 11 | public JavaEnumParamClassWrapper(Context context, EnumParamClassInfo classInfo, String distRootPackage) { 12 | super(context, classInfo, distRootPackage); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/java/org/rxjava/apikit/tool/wrapper/JavaScriptWrapper.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.apikit.tool.wrapper; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import org.rxjava.apikit.tool.generator.Context; 5 | import org.rxjava.apikit.tool.info.ClassInfo; 6 | import org.rxjava.apikit.tool.info.ClassTypeInfo; 7 | 8 | /** 9 | * @author happy 2019-05-09 23:04 10 | */ 11 | public class JavaScriptWrapper extends BuilderWrapper { 12 | 13 | public JavaScriptWrapper(Context context, T classInfo, String rootPackage) { 14 | super(context, classInfo, rootPackage); 15 | } 16 | 17 | public String toTypeString(ClassTypeInfo typeInfo) { 18 | return toTypeString(typeInfo, false); 19 | } 20 | 21 | public String toTypeString(ClassTypeInfo typeInfo, boolean isArray) { 22 | StringBuilder sb = new StringBuilder(); 23 | ClassTypeInfo.Type type = typeInfo.getType(); 24 | if (typeInfo.isCollection()) { 25 | ClassTypeInfo typeInfoArg = typeInfo.getTypeArguments().get(0); 26 | return toTypeString(typeInfoArg, true); 27 | } else if (type == ClassTypeInfo.Type.OTHER) { 28 | if (typeInfo.isGeneric()) { 29 | sb.append("Object"); 30 | } else { 31 | sb.append(typeInfo.getClassName()); 32 | } 33 | } else { 34 | sb.append(toJavaScriptString(type)); 35 | } 36 | if (typeInfo.isArray() || isArray) { 37 | sb.append("[]"); 38 | } 39 | return sb.toString(); 40 | } 41 | 42 | public String toJavaScriptString(ClassTypeInfo.Type type) { 43 | return TYPE_MAP.get(type); 44 | } 45 | 46 | private static final ImmutableMap TYPE_MAP 47 | = ImmutableMap.builder() 48 | .put(ClassTypeInfo.Type.VOID, "void") 49 | .put(ClassTypeInfo.Type.BOOLEAN, "boolean") 50 | .put(ClassTypeInfo.Type.BYTE, "number") 51 | .put(ClassTypeInfo.Type.SHORT, "number") 52 | .put(ClassTypeInfo.Type.INT, "number") 53 | .put(ClassTypeInfo.Type.LONG, "number") 54 | .put(ClassTypeInfo.Type.FLOAT, "number") 55 | .put(ClassTypeInfo.Type.DOUBLE, "number") 56 | .put(ClassTypeInfo.Type.DATE, "Date") 57 | .put(ClassTypeInfo.Type.STRING, "string") 58 | .build(); 59 | } 60 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/apidoc/api.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ##设置第一个tag为null的字符串为控制器Controller中文名称 5 | 6 | $!{classInfo.javadocInfo.firstRow} 7 | 8 | 请输入控制器名称 9 | 10 | 11 | ##method方法 12 | 13 | $!{method.name} 14 | $!{method.url} 15 | 16 | 17 | ##设置第一个tag为null的字符串为控制器Controller中文名称 18 | 19 | $!{method.comment.firstRow} 20 | 21 | 请输入方法名称 22 | 23 | 24 | 25 | ##循环结束 -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/apidoc/index.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $!{api.key} 5 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/apidoc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rxjava-api", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "dependencies": { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/apidoc/paramClass.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | $!{classInfo.name} 4 | ##参数属性列表 5 | 6 | $!{property.name} 7 | 8 | ##循环结束 -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/apidoc/test.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | ##method方法 4 | 5 | $!{name} 6 | 7 | ##循环结束 -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/es2015/Api.d.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $!{wrapper.imports} 7 | 8 | /** 9 | $!{wrapper.comment(" * ")} 10 | */ 11 | declare class $!{wrapper.getDistClassName()} extends AbstractApi { 12 | 13 | ##异步方法 14 | 15 | /** 16 | $!{wrapper.formatBaseComment(method.comment," * ")} 17 | * 18 | $!{wrapper.requestComment(method," * ")} 19 | */ 20 | $!{method.name}($!{wrapper.params(method,true)}):Promise<$!{wrapper.resultTypeString(method)}>; 21 | 22 | ##循环结束 23 | } 24 | export { $!{wrapper.getDistClassName()} }; 25 | declare const $!{wrapper.fieldName}: $!{wrapper.getDistClassName()}; 26 | export default $!{wrapper.fieldName}; -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/es2015/ParamClass.d.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $!{wrapper.imports} 6 | 7 | /** 8 | $!{wrapper.comment(" * ")} 9 | */ 10 | interface $!{classInfo.name} { 11 | 12 | 13 | 14 | /** 15 | $!{wrapper.formatComment(attr.javadocInfo," * ")} 16 | */ 17 | 18 | $!{attr.name}?:$!{wrapper.toTypeString(attr.typeInfo)}; 19 | 20 | } 21 | 22 | export default $!{classInfo.name}; -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/es2015/ParamClass.httl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apersonw/rxjava/1df845e8d8421cf8efbc9f245a56c0dd69a3cbcb/rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/es2015/ParamClass.httl -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/es2015/index.d.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | import $!{api.key} from '.$!{api.value}'; 6 | 7 | 8 | 9 | export { 10 | 11 | $!{api.key}, 12 | 13 | }; -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/es2015/index.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | "use strict"; 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | 9 | 10 | Object.defineProperty(exports, "$!{api.key}", { 11 | enumerable: true, 12 | get: function get() { 13 | return _$!{api.key}.default; 14 | } 15 | }); 16 | var _$!{api.key} = _interopRequireDefault(require(".$!{api.value}")); 17 | 18 | 19 | 20 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/es2015/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rxjava-api", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "dependencies": { 9 | "rxjava-api-core": "latest" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/java/ApiClass.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | package $!{wrapper.getFullDistPackage()}; 7 | 8 | import reactor.core.publisher.Mono; 9 | 10 | import java.util.*; 11 | import java.util.Map.Entry; 12 | import java.util.concurrent.Future; 13 | 14 | 15 | import org.rxjava.apikit.client.*; 16 | 17 | $!{wrapper.imports} 18 | 19 | public class $!{wrapper.getDistClassName()} { 20 | private ClientAdapter clientAdapter; 21 | 22 | public $!{wrapper.getDistClassName()}() { 23 | } 24 | 25 | public $!{wrapper.getDistClassName()}(ClientAdapter clientAdapter) { 26 | this.clientAdapter = clientAdapter; 27 | } 28 | 29 | 30 | public Mono<$!{wrapper.resultData(method)}> $!{method.methodName}($!{wrapper.params(method)}) { 31 | Map _uriVariables = new HashMap<>(); 32 | 33 | _uriVariables.put("$!{param.getFieldName()}", $!{param.getFieldName()}); 34 | 35 | String _url = ApiUtils.expandUriComponent("$!{method.url}", _uriVariables); 36 | 37 | 38 | 39 | List> _form = $!{param.fieldName}.encode("", new ArrayList<>()); 40 | return clientAdapter.request("$!{method.type.name()}", _url, _form, _$!{method.index}Type); 41 | 42 | return clientAdapter.request("$!{method.type.name()}", _url, null, _$!{method.index}Type); 43 | 44 | } 45 | 46 | 47 | public void setClientAdapter(ClientAdapter clientAdapter) { 48 | this.clientAdapter = clientAdapter; 49 | } 50 | 51 | public ClientAdapter getClientAdapter() { 52 | return clientAdapter; 53 | } 54 | 55 | 56 | $!{wrapper.resultTypeString(method," ")} 57 | 58 | } -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/java/EnumParamClass.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | package $!{wrapper.getFullDistPackage()}; 5 | 6 | public enum $!{wrapper.getDistClassName()} { 7 | 8 | 9 | $!{constant.name}; 10 | 11 | $!{constant.name}, 12 | 13 | 14 | } -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/generator/java/ParamClass.httl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | package $!{wrapper.getFullDistPackage()}; 6 | 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import java.util.*; 10 | import java.util.Map.Entry; 11 | import java.util.AbstractMap.SimpleImmutableEntry; 12 | import org.bson.types.ObjectId; 13 | $!{wrapper.imports} 14 | 15 | @Getter 16 | @Setter 17 | public class $!{wrapper.getDistClassName()}$!{wrapper.typeParameters} $!{wrapper.superInfo} { 18 | 19 | private $!{wrapper.toJavaTypeString(attr.typeInfo, false, true)} $!{attr.fieldName}; 20 | 21 | 22 | public List> encode(String $parent, List> $list) { 23 | $!{wrapper.encodeCode(" ", "$parent")} 24 | } 25 | } -------------------------------------------------------------------------------- /rxjava-apikit/rxjava-apikit-tool/src/main/resources/org/rxjava/apikit/tool/httl.properties: -------------------------------------------------------------------------------- 1 | compiler=httl.spi.compilers.JavassistCompiler 2 | import.packages+=org.rxjava.apikit.tool.info,\ 3 | org.rxjava.apikit.tool.utils,\ 4 | org.rxjava.apikit.tool.wrapper 5 | template.directory= 6 | message.basename=messages 7 | input.encoding=UTF-8 8 | output.encoding=UTF-8 9 | reloadable=true 10 | precompiled=true -------------------------------------------------------------------------------- /rxjava-example/README.md: -------------------------------------------------------------------------------- 1 | ###模块说明 2 | 3 | 本模块下为一系列使用的相关例子工程 -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | org.rxjava 6 | rxjava-gateway 7 | 1.0.8-SNAPSHOT 8 | 9 | rxjava-gateway-example 10 | jar 11 | 12 | example 13 | Example 14 | 15 | 16 | 17 | org.rxjava 18 | rxjava-apikit-tool 19 | ${project.parent.version} 20 | 21 | 22 | com.google.zxing 23 | core 24 | 3.3.3 25 | 26 | 27 | com.google.zxing 28 | javase 29 | 3.3.3 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-test 34 | 35 | 36 | org.junit.vintage 37 | junit-vintage-engine 38 | 39 | 40 | 41 | 42 | 43 | 44 | release 45 | 46 | 47 | 48 | maven-assembly-plugin 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/assembly/bin.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | bin 6 | 7 | dir 8 | 9 | false 10 | 11 | 12 | 13 | ${project.groupId}:* 14 | 15 | base-lib 16 | false 17 | 18 | 19 | 20 | ${project.groupId}:* 21 | 22 | lib 23 | false 24 | 25 | 26 | 27 | 28 | ${basedir}/target/classes 29 | classes 30 | 31 | bootstrap.yml 32 | application.yml 33 | 34 | 35 | 36 | src/assembly/config/release 37 | 38 | bootstrap.yml 39 | application.yml 40 | 41 | true 42 | classes 43 | 44 | 45 | src/assembly/config/release 46 | 47 | Dockerfile 48 | startup.sh 49 | 50 | true 51 | ./ 52 | 53 | 54 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/assembly/config/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.cn-shanghai.aliyuncs.com/taro-mall/java:8_server-jre 2 | 3 | RUN mkdir /rxservice 4 | WORKDIR /rxservice 5 | 6 | COPY base-lib base-lib 7 | COPY lib lib 8 | COPY classes classes 9 | COPY startup.sh startup.sh 10 | 11 | EXPOSE 8080 12 | CMD ["./startup.sh"] -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/assembly/config/release/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: rxjava-${module.type}-${module.name} 4 | cloud: 5 | kubernetes: 6 | config: 7 | sources: 8 | - name: common-configmap 9 | namespace: default 10 | data: 11 | mongodb: 12 | database: rxjava-${module.type}-${module.name} -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/assembly/config/release/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | java $JAVA_OPTIONS -cp ./classes org.rxjava.${module.type}.${module.name}.Rx${module.Type}${module.Name}Main -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/main/java/org/rxjava/gateway/example/CustomGatewayDiscoveryClientAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.gateway.example; 2 | 3 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 4 | import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; 5 | import org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator; 6 | import org.springframework.cloud.gateway.discovery.DiscoveryLocatorProperties; 7 | import org.springframework.context.annotation.Bean; 8 | 9 | public class CustomGatewayDiscoveryClientAutoConfiguration { 10 | @Bean 11 | @ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled") 12 | public DiscoveryClientRouteDefinitionLocator customDiscoveryClientRouteDefinitionLocator( 13 | ReactiveDiscoveryClient discoveryClient, 14 | DiscoveryLocatorProperties properties) { 15 | return new CustomDiscoveryClientRouteDefinitionLocator(discoveryClient, properties); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/main/java/org/rxjava/gateway/example/LoginInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.gateway.example; 2 | 3 | import org.rxjava.common.core.entity.LoginInfo; 4 | import org.rxjava.common.core.service.LoginInfoService; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.web.server.ServerWebExchange; 7 | import reactor.core.publisher.Mono; 8 | 9 | @Service 10 | public class LoginInfoServiceImpl implements LoginInfoService { 11 | @Override 12 | public Mono checkToken(ServerWebExchange serverWebExchange) { 13 | return Mono.just(new LoginInfo()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/main/java/org/rxjava/gateway/example/RxGatewayExampleApplication.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.gateway.example; 2 | 3 | import org.springframework.boot.WebApplicationType; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.cloud.gateway.route.RouteLocator; 7 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import java.util.function.Predicate; 11 | 12 | /** 13 | * @author happy 2019-05-10 18:06 14 | */ 15 | @SpringBootApplication 16 | public class RxGatewayExampleApplication { 17 | public static void main(String[] args) { 18 | new SpringApplicationBuilder(RxGatewayExampleApplication.class).web(WebApplicationType.REACTIVE).run(args); 19 | } 20 | 21 | // @Bean 22 | // public RouteLocator routeLocator(RouteLocatorBuilder builder) { 23 | // return builder.routes() 24 | // .route(p -> p.path("/**") 25 | // .filters(u -> u.rewritePath("/([^/]+)/(?.*)", "/${segment}")) 26 | // .uri("https://www.baidu.com")) 27 | // .build(); 28 | // } 29 | } 30 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/main/java/org/rxjava/gateway/example/RxGatewayExampleMain.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.gateway.example; 2 | 3 | import java.lang.reflect.Method; 4 | import java.net.URL; 5 | import java.net.URLClassLoader; 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | import java.nio.file.Paths; 9 | import java.util.function.Consumer; 10 | 11 | /** 12 | * @author happy 2019-03-17 22:23 13 | */ 14 | public class RxGatewayExampleMain { 15 | public static void main(String... args) { 16 | try { 17 | URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader(); 18 | Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); 19 | addURL.setAccessible(true); 20 | String[] strPaths = new String[]{"base-lib", "lib"}; 21 | for (String strPath : strPaths) { 22 | Path path = Paths.get(strPath); 23 | if (Files.isDirectory(path)) { 24 | Consumer pathConsumer = p -> { 25 | try { 26 | addURL.invoke(cl, p.toUri().toURL()); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | }; 31 | Files.newDirectoryStream(path).forEach(pathConsumer); 32 | } 33 | } 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | } 37 | RxGatewayExampleApplication.main(args); 38 | } 39 | } -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.rxjava.gateway.example.CustomGatewayDiscoveryClientAutoConfiguration -------------------------------------------------------------------------------- /rxjava-example/rxjava-gateway-example/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: rxjava-gateway-example 4 | data: 5 | mongodb: 6 | uri: mongodb://127.0.0.1:27017 7 | database: rxjava-gateway-example 8 | auto-index-creation: false 9 | rabbitmq: 10 | host: 127.0.0.1 11 | port: 5672 12 | username: admin 13 | password: admin 14 | listener: 15 | simple: 16 | concurrency: 10 17 | max-concurrency: 10 18 | prefetch: 1 19 | default-requeue-rejected: true 20 | auto-startup: true 21 | cloud: 22 | kubernetes: 23 | config: 24 | enabled: false 25 | discovery: 26 | enabled: false 27 | bus: 28 | enabled: false 29 | gateway: 30 | discovery: 31 | locator: 32 | lower-case-service-id: true 33 | enabled: true 34 | custom: true 35 | server: 36 | port: 8080 37 | mock: 38 | userId: alkjqwerpoiuasdf 39 | management: 40 | endpoints: 41 | web: 42 | exposure: 43 | include: "*" -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 构建 3 | mvn clean install -Prelease 4 | 5 | # 从pom.xml获取模块名 6 | module_name=`grep 'artifactId' pom.xml | tr -d '/'| sed 's///g' | awk 'NR==2 {print}' | sed 's/ //g'` 7 | 8 | # 请自行修改自己要push的docker仓库 9 | # 推送构建的docker镜像到阿里云服务器 10 | module_tag=registry.cn-shanghai.aliyuncs.com/taro-mall/${module_name}:latest 11 | 12 | docker build ./target/docker-bin/ -t ${module_tag} 13 | 14 | docker push ${module_tag} -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/k8s/rxjava-service-example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: rxjava-service-example 5 | labels: 6 | app: rxjava-service-example 7 | spec: 8 | replicas: 1 9 | template: 10 | metadata: 11 | name: rxjava-service-example 12 | labels: 13 | app: rxjava-service-example 14 | spec: 15 | containers: 16 | - name: rxjava-service-example 17 | image: registry.cn-shanghai.aliyuncs.com/taro-mall/rxjava-service-example:latest 18 | imagePullPolicy: Always 19 | restartPolicy: Always 20 | selector: 21 | matchLabels: 22 | app: rxjava-service-example 23 | --- 24 | apiVersion: v1 25 | kind: Service 26 | metadata: 27 | name: rxjava-service-example 28 | spec: 29 | selector: 30 | app: rxjava-service-example 31 | ports: 32 | - port: 8080 33 | protocol: TCP 34 | targetPort: 8080 35 | type: NodePort -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | org.rxjava 6 | rxjava-service 7 | 1.0.8-SNAPSHOT 8 | 9 | rxjava-service-example 10 | jar 11 | 12 | example 13 | Example 14 | 15 | 16 | 17 | org.rxjava 18 | rxjava-apikit-tool 19 | ${project.parent.version} 20 | 21 | 22 | com.google.zxing 23 | core 24 | 3.3.3 25 | 26 | 27 | com.google.zxing 28 | javase 29 | 3.3.3 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-test 34 | 35 | 36 | org.junit.vintage 37 | junit-vintage-engine 38 | 39 | 40 | 41 | 42 | 43 | 44 | release 45 | 46 | 47 | 48 | maven-assembly-plugin 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/assembly/bin.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | bin 6 | 7 | dir 8 | 9 | false 10 | 11 | 12 | 13 | ${project.groupId}:* 14 | 15 | base-lib 16 | false 17 | 18 | 19 | 20 | ${project.groupId}:* 21 | 22 | lib 23 | false 24 | 25 | 26 | 27 | 28 | ${basedir}/target/classes 29 | classes 30 | 31 | bootstrap.yml 32 | application.yml 33 | 34 | 35 | 36 | src/assembly/config/release 37 | 38 | bootstrap.yml 39 | application.yml 40 | 41 | true 42 | classes 43 | 44 | 45 | src/assembly/config/release 46 | 47 | Dockerfile 48 | startup.sh 49 | 50 | true 51 | ./ 52 | 53 | 54 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/assembly/config/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.cn-shanghai.aliyuncs.com/taro-mall/java:8_server-jre 2 | 3 | RUN mkdir /rxservice 4 | WORKDIR /rxservice 5 | 6 | COPY base-lib base-lib 7 | COPY lib lib 8 | COPY classes classes 9 | COPY startup.sh startup.sh 10 | 11 | EXPOSE 8080 12 | CMD ["./startup.sh"] -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/assembly/config/release/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: rxjava-${module.type}-${module.name} 4 | cloud: 5 | kubernetes: 6 | config: 7 | sources: 8 | - name: common-configmap 9 | namespace: default 10 | data: 11 | mongodb: 12 | database: rxjava-${module.type}-${module.name} -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/assembly/config/release/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | java $JAVA_OPTIONS -cp ./classes org.rxjava.${module.type}.${module.name}.Rx${module.Type}${module.Name}Main -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/RxApiBuildApplication.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example; 2 | 3 | import org.rxjava.apikit.tool.ApiGenerateManager; 4 | import org.rxjava.apikit.tool.generator.impl.ApidocApiGenerator; 5 | import org.rxjava.apikit.tool.generator.impl.JavaClientApiGenerator; 6 | import org.rxjava.apikit.tool.generator.impl.JavaScriptApiGenerator; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.boot.WebApplicationType; 9 | import org.springframework.boot.builder.SpringApplicationBuilder; 10 | 11 | import java.io.File; 12 | 13 | /** 14 | * @author happy 15 | * 手动构建api 16 | */ 17 | public class RxApiBuildApplication implements CommandLineRunner { 18 | /** 19 | * 构建api 20 | */ 21 | public static void main(String[] args) { 22 | new SpringApplicationBuilder(RxApiBuildApplication.class).web(WebApplicationType.NONE).run(args); 23 | } 24 | 25 | @Override 26 | public void run(String... args) throws Exception { 27 | //模块绝对路径 28 | String moduleAbsolutePath = getModuleAbsolutePath("rxjava-service-example"); 29 | //java源码文件夹 30 | String javaSourceDir = new File(moduleAbsolutePath, "src/main/java/").getAbsolutePath(); 31 | //设置Java生成后的文件夹路径 32 | String javaOutPath = new File(moduleAbsolutePath, "src/test/java/").getAbsolutePath(); 33 | //设置Js生成后的文件夹路径 34 | String jsOutPath = new File(moduleAbsolutePath, "src/test/js/").getAbsolutePath(); 35 | //设置Js生成后的文件夹路径 36 | String apidocOutPath = new File(moduleAbsolutePath, "src/test/apidoc/").getAbsolutePath(); 37 | 38 | //分析api和param 39 | ApiGenerateManager manager = ApiGenerateManager.analyse(javaSourceDir, "org.rxjava.service.example"); 40 | { 41 | //配置java客户端生成器 42 | JavaClientApiGenerator javaClientApiGenerator = new JavaClientApiGenerator(); 43 | javaClientApiGenerator.setOutRootPackage("org.rxjava.api.example"); 44 | javaClientApiGenerator.setOutPath(javaOutPath); 45 | 46 | //生成java客户端Api 47 | manager.generate(javaClientApiGenerator); 48 | } 49 | 50 | // { 51 | // //配置js客户端生成器 52 | // JavaScriptApiGenerator javaScriptApiGenerator = new JavaScriptApiGenerator(); 53 | // javaScriptApiGenerator.setOutPath(jsOutPath); 54 | // javaScriptApiGenerator.setServiceId("example"); 55 | // 56 | // //生成java script客户端Api 57 | // manager.generate(javaScriptApiGenerator); 58 | // } 59 | 60 | // { 61 | // //配置apidoc生成器 62 | // ApidocApiGenerator apidocApiGenerator = new ApidocApiGenerator(); 63 | // apidocApiGenerator.setOutPath(apidocOutPath); 64 | // apidocApiGenerator.setServiceId("example"); 65 | // 66 | // //生成apidoc 67 | // manager.generate(apidocApiGenerator); 68 | // } 69 | } 70 | 71 | /** 72 | * 获取指定模块绝对路径 73 | */ 74 | private String getModuleAbsolutePath(String module) { 75 | File root = new File(module); 76 | if (!root.exists()) { 77 | root = new File("rxjava/rxjava-example/", module); 78 | } 79 | if (!root.exists()) { 80 | root = new File("rxjava-example/", module); 81 | } 82 | if (!root.exists()) { 83 | root = new File("."); 84 | } 85 | return root.getAbsolutePath(); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/RxServiceExampleApplication.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example; 2 | 3 | import org.springframework.boot.WebApplicationType; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | 7 | /** 8 | * @author happy 2019-05-10 18:06 9 | */ 10 | @SpringBootApplication 11 | public class RxServiceExampleApplication { 12 | public static void main(String[] args) { 13 | new SpringApplicationBuilder(RxServiceExampleApplication.class).web(WebApplicationType.REACTIVE).run(args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/RxServiceExampleMain.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example; 2 | 3 | import java.lang.reflect.Method; 4 | import java.net.URL; 5 | import java.net.URLClassLoader; 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | import java.nio.file.Paths; 9 | import java.util.function.Consumer; 10 | 11 | /** 12 | * @author happy 2019-03-17 22:23 13 | */ 14 | public class RxServiceExampleMain { 15 | public static void main(String... args) { 16 | try { 17 | URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader(); 18 | Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); 19 | addURL.setAccessible(true); 20 | String[] strPaths = new String[]{"base-lib", "lib"}; 21 | for (String strPath : strPaths) { 22 | Path path = Paths.get(strPath); 23 | if (Files.isDirectory(path)) { 24 | Consumer pathConsumer = p -> { 25 | try { 26 | addURL.invoke(cl, p.toUri().toURL()); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | }; 31 | Files.newDirectoryStream(path).forEach(pathConsumer); 32 | } 33 | } 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | } 37 | RxServiceExampleApplication.main(args); 38 | } 39 | } -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/entity/Example.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example.entity; 2 | 3 | import lombok.Data; 4 | import org.bson.types.ObjectId; 5 | import org.springframework.data.annotation.CreatedDate; 6 | import org.springframework.data.annotation.Id; 7 | import org.springframework.data.mongodb.core.mapping.Document; 8 | 9 | import java.time.LocalDateTime; 10 | 11 | @Data 12 | @Document 13 | public class Example { 14 | @Id 15 | private ObjectId id; 16 | private String name; 17 | @CreatedDate 18 | private LocalDateTime createDate; 19 | } 20 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/form/TestForm.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example.form; 2 | 3 | import lombok.Data; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.bson.types.ObjectId; 7 | import org.rxjava.service.example.type.TestEnumType; 8 | 9 | import javax.validation.constraints.NotEmpty; 10 | import javax.validation.constraints.NotNull; 11 | 12 | /** 13 | * @author happy 2019-01-27 12:16 14 | */ 15 | @Data 16 | public class TestForm extends TestSuperForm { 17 | private ObjectId objectId; 18 | private TestEnumType testEnumType; 19 | private String stringId; 20 | } 21 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/form/TestSuperForm.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example.form; 2 | 3 | import lombok.Data; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.hibernate.validator.constraints.Range; 7 | 8 | import javax.validation.constraints.Min; 9 | 10 | /** 11 | * @author happy 2019-03-27 19:49 12 | */ 13 | @Data 14 | public class TestSuperForm { 15 | @Min(0) 16 | private int page = 0; 17 | @Range(min = 0, max = 20) 18 | private int pageSize = 10; 19 | } 20 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/model/TestModel.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example.model; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class TestModel { 7 | private String id; 8 | private String name; 9 | } 10 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/person/TestController.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example.person; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.rxjava.service.example.entity.Example; 5 | import org.rxjava.service.example.form.TestForm; 6 | import org.rxjava.service.example.model.TestModel; 7 | import org.rxjava.service.example.repository.ExampleRepository; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import reactor.core.publisher.Mono; 14 | 15 | import javax.validation.Valid; 16 | 17 | /** 18 | * @author happy 19 | */ 20 | @RestController 21 | @RequestMapping("mergeTestPath") 22 | @Slf4j 23 | public class TestController { 24 | 25 | @Autowired 26 | private ExampleRepository exampleRepository; 27 | 28 | /** 29 | * 路径变量测试 30 | */ 31 | @GetMapping("path/{id}") 32 | public Mono testPath( 33 | @PathVariable String id, 34 | @Valid TestForm form 35 | ) { 36 | TestModel testModel = new TestModel(); 37 | testModel.setId("haha"); 38 | testModel.setName("我是testModel"); 39 | log.info("TestController id:{}",id); 40 | log.info("TestController objectId:{}",form.getObjectId()); 41 | log.info("TestController testPath:{}",testModel); 42 | Example example = new Example(); 43 | example.setName("我是测试人员"); 44 | return exampleRepository.save(example).thenReturn(testModel); 45 | } 46 | } -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/repository/ExampleRepository.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example.repository; 2 | 3 | import org.bson.types.ObjectId; 4 | import org.rxjava.service.example.entity.Example; 5 | import org.springframework.data.repository.reactive.ReactiveSortingRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface ExampleRepository extends ReactiveSortingRepository { 10 | } 11 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/java/org/rxjava/service/example/type/TestEnumType.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.example.type; 2 | 3 | public enum TestEnumType { 4 | PNG, JPG 5 | } 6 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: rxjava-service-example 4 | data: 5 | mongodb: 6 | uri: mongodb://127.0.0.1:27017 7 | database: rxjava-service-example 8 | auto-index-creation: false 9 | rabbitmq: 10 | host: 127.0.0.1 11 | port: 5672 12 | username: admin 13 | password: admin 14 | listener: 15 | simple: 16 | concurrency: 10 17 | max-concurrency: 10 18 | prefetch: 1 19 | default-requeue-rejected: true 20 | auto-startup: true 21 | cloud: 22 | kubernetes: 23 | config: 24 | enabled: false 25 | discovery: 26 | enabled: false 27 | bus: 28 | enabled: false 29 | server: 30 | port: 8080 31 | mock: 32 | userId: alkjqwerpoiuasdf -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/main/resources/exceptions/exception_zh_CN.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 异常消息 5 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/test/java/org/rxjava/api/example/test/TestApplication.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.api.example.test; 2 | 3 | import org.bson.types.ObjectId; 4 | import org.junit.jupiter.api.Test; 5 | import org.rxjava.api.example.form.TestForm; 6 | import org.rxjava.api.example.model.TestModel; 7 | import org.rxjava.api.example.person.TestApi; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | 11 | @SpringBootTest(classes = {TestContext.class}) 12 | public class TestApplication { 13 | @Autowired 14 | private TestApi testApi; 15 | 16 | @Test 17 | public void testSave() { 18 | TestForm form = new TestForm(); 19 | form.setObjectId(new ObjectId()); 20 | TestModel haha = testApi.testPath("haha", form).block(); 21 | System.out.println(haha); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /rxjava-example/rxjava-service-example/src/test/java/org/rxjava/api/example/test/TestContext.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.api.example.test; 2 | 3 | import org.rxjava.api.example.person.TestApi; 4 | import org.rxjava.apikit.client.ClientAdapter; 5 | import org.rxjava.common.core.api.ReactiveHttpClientAdapter; 6 | import org.rxjava.service.starter.boot.RxJavaWebFluxConfigurer; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Import; 10 | import org.springframework.format.support.DefaultFormattingConversionService; 11 | import org.springframework.web.reactive.function.client.WebClient; 12 | 13 | @Configuration 14 | public class TestContext { 15 | 16 | @Bean 17 | public ClientAdapter clientAdapter() { 18 | return ReactiveHttpClientAdapter.build(new DefaultFormattingConversionService(), WebClient.builder(), "localhost"); 19 | } 20 | 21 | @Bean 22 | public TestApi testApi(ClientAdapter clientAdapter) { 23 | TestApi testApi = new TestApi(); 24 | testApi.setClientAdapter(clientAdapter); 25 | return testApi; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /rxjava-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.rxjava 6 | rxjava 7 | 1.0.9-SNAPSHOT 8 | 9 | rxjava-gateway 10 | pom 11 | 12 | gateway 13 | Gateway 14 | 15 | 16 | 17 | org.rxjava 18 | rxjava-spring-cloud-starter-gateway 19 | ${project.parent.version} 20 | 21 | 22 | -------------------------------------------------------------------------------- /rxjava-service/README.md: -------------------------------------------------------------------------------- 1 | ### 一、模块说明 2 | 3 | rxjava-apikit-maven-plugin 4 | 5 | 主要是整合了api基本的生成配置 6 | 7 | 子项目可进行一下的一些配置 8 | 9 | ```xml 10 | 11 | ${项目api生成后git推送的地址路径} 12 | ${模块名称,纯英文,首字母小写} 13 | ${模块名称,同module.name,首字母大写} 14 | ${模块类型,默认为service,可根据需要进行修改,首字母小写} 15 | ${模块类型,默认为Service,可根据需要进行修改,首字母大写} 16 | 17 | ``` 18 | -------------------------------------------------------------------------------- /rxjava-spring/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.rxjava 5 | rxjava 6 | 1.0.9-SNAPSHOT 7 | 8 | 4.0.0 9 | rxjava-spring 10 | pom 11 | 12 | rxjava-spring-boot-core 13 | rxjava-spring-boot-starter-service 14 | rxjava-spring-cloud-starter-gateway 15 | rxjava-spring-cloud-starter-bus 16 | rxjava-spring-mock-starter 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-webflux 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-data-mongodb-reactive 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-data-redis-reactive 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-actuator 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-validation 38 | 39 | 40 | org.springframework.cloud 41 | spring-cloud-starter-kubernetes-all 42 | 43 | 44 | org.springframework.retry 45 | spring-retry 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | org.junit.vintage 54 | junit-vintage-engine 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.rxjava 6 | rxjava-spring 7 | 1.0.9-SNAPSHOT 8 | 9 | rxjava-spring-boot-core 10 | jar 11 | 12 | 13 | org.rxjava 14 | rxjava-apikit-core 15 | ${project.parent.version} 16 | 17 | 18 | 19 | org.assertj 20 | assertj-core 21 | 22 | 23 | com.belerweb 24 | pinyin4j 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/RxJavaCoreAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core; 2 | 3 | import org.rxjava.common.core.tools.RequestTool; 4 | import org.springframework.boot.autoconfigure.AutoConfigureOrder; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.context.annotation.Primary; 8 | import org.springframework.core.Ordered; 9 | 10 | @Configuration 11 | @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) 12 | public class RxJavaCoreAutoConfiguration { 13 | /** 14 | * 网络请求工具 15 | */ 16 | @Bean 17 | @Primary 18 | public RequestTool requestTool(){ 19 | return new RequestTool(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/annotation/Check.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 认证授权检查 7 | */ 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Check { 12 | boolean value() default true; 13 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/annotation/EnumValue.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.annotation; 2 | 3 | 4 | import org.assertj.core.util.Strings; 5 | 6 | import javax.validation.Constraint; 7 | import javax.validation.ConstraintValidator; 8 | import javax.validation.ConstraintValidatorContext; 9 | import javax.validation.Payload; 10 | import java.lang.annotation.ElementType; 11 | import java.lang.annotation.Retention; 12 | import java.lang.annotation.RetentionPolicy; 13 | import java.lang.annotation.Target; 14 | import java.lang.reflect.InvocationTargetException; 15 | import java.lang.reflect.Method; 16 | import java.lang.reflect.Modifier; 17 | 18 | /** 19 | * 校验枚举值有效性 20 | * @author happy on 2018-05-25. 21 | */ 22 | @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE }) 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Constraint(validatedBy = EnumValue.Validator.class) 25 | public @interface EnumValue { 26 | 27 | String message() default "value is not enum"; 28 | 29 | Class[] groups() default {}; 30 | 31 | Class[] payload() default {}; 32 | 33 | Class> enumClass(); 34 | 35 | String enumMethod() default "isValidName"; 36 | 37 | class Validator implements ConstraintValidator { 38 | 39 | private Class> enumClass; 40 | private String enumMethod; 41 | 42 | @Override 43 | public void initialize(EnumValue enumValue) { 44 | enumMethod = enumValue.enumMethod(); 45 | enumClass = enumValue.enumClass(); 46 | } 47 | 48 | @Override 49 | public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) { 50 | if (value == null) { 51 | return Boolean.TRUE; 52 | } 53 | 54 | if (enumClass == null || enumMethod == null) { 55 | return Boolean.TRUE; 56 | } 57 | 58 | Class valueClass = value.getClass(); 59 | 60 | try { 61 | Method method = enumClass.getMethod(enumMethod, valueClass); 62 | if (!Boolean.TYPE.equals(method.getReturnType()) && !Boolean.class.equals(method.getReturnType())) { 63 | throw new RuntimeException(Strings.formatIfArgs("%s method return is not boolean type in the %s class", enumMethod, enumClass)); 64 | } 65 | 66 | if(!Modifier.isStatic(method.getModifiers())) { 67 | throw new RuntimeException(Strings.formatIfArgs("%s method is not static method in the %s class", enumMethod, enumClass)); 68 | } 69 | 70 | Boolean result = (Boolean)method.invoke(null, value); 71 | return result == null ? false : result; 72 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 73 | throw new RuntimeException(e); 74 | } catch (NoSuchMethodException | SecurityException e) { 75 | throw new RuntimeException(Strings.formatIfArgs("This %s(%s) method does not exist in the %s", enumMethod, valueClass, enumClass), e); 76 | } 77 | } 78 | 79 | } 80 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/annotation/Login.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 是否登陆注解 7 | * 默认为需要登陆 8 | */ 9 | @Target(ElementType.METHOD) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface Login { 13 | boolean value() default true; 14 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/entity/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.data.annotation.CreatedDate; 6 | import org.springframework.data.annotation.LastModifiedDate; 7 | import org.springframework.data.annotation.Version; 8 | import org.springframework.data.mongodb.core.index.Indexed; 9 | import org.springframework.data.mongodb.core.mapping.Document; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | import static org.springframework.data.mongodb.core.index.IndexDirection.DESCENDING; 14 | 15 | /** 16 | * @author happy 2019/10/20 02:10 17 | */ 18 | @Getter 19 | @Setter 20 | @Document 21 | public class BaseEntity { 22 | private String id; 23 | @Version 24 | private long version; 25 | /** 26 | * 创建日期 27 | */ 28 | @CreatedDate 29 | @Indexed(direction = DESCENDING) 30 | private LocalDateTime createDate; 31 | /** 32 | * 更新日期 33 | */ 34 | @LastModifiedDate 35 | private LocalDateTime updateDate; 36 | } 37 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/entity/Image.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.entity; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author happy 2019-07-16 22:36 7 | * 图片 8 | */ 9 | @Data 10 | public class Image { 11 | /** 12 | * 宽:单位像素 13 | */ 14 | private int width; 15 | /** 16 | * 高:单位像素 17 | */ 18 | private int height; 19 | /** 20 | * 存储Key 21 | */ 22 | private String key; 23 | } 24 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/entity/KeyValue.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.entity; 2 | 3 | import lombok.*; 4 | 5 | import java.util.Objects; 6 | 7 | /** 8 | * @author happy 2019-04-22 15:47 9 | * 键值对对象 10 | */ 11 | @Data 12 | public class KeyValue { 13 | private K key; 14 | private V value; 15 | } 16 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/entity/LoginInfo.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | /** 9 | * @author happy 2019-04-14 14:00 10 | * 登陆信息 11 | */ 12 | @Getter 13 | @Setter 14 | public class LoginInfo { 15 | /** 16 | * 用户Id 17 | */ 18 | private String userId; 19 | /** 20 | * 用户登陆信息对应的token 21 | */ 22 | private String token; 23 | /** 24 | * 合作伙伴Id 25 | */ 26 | private String partnerId; 27 | /** 28 | * 过期时间 29 | */ 30 | private LocalDateTime expireDate; 31 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/entity/Video.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.entity; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author happy 2019-07-16 22:36 7 | * 视频 8 | */ 9 | @Data 10 | public class Video { 11 | /** 12 | * 宽:单位像素 13 | */ 14 | private int width; 15 | /** 16 | * 高:单位像素 17 | */ 18 | private int height; 19 | /** 20 | * 存储Key 21 | */ 22 | private String key; 23 | } 24 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/exception/DefaultError.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.exception; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import org.springframework.context.support.DefaultMessageSourceResolvable; 5 | 6 | /** 7 | * @author happy 2019-04-16 23:45 8 | */ 9 | @JsonIgnoreProperties("code") 10 | class DefaultError extends DefaultMessageSourceResolvable { 11 | DefaultError(String code) { 12 | super(code); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/exception/ErrorMessage.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.exception; 2 | 3 | import lombok.Data; 4 | import org.springframework.context.MessageSourceResolvable; 5 | 6 | import java.time.LocalDateTime; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.stream.Stream; 10 | 11 | /** 12 | * @author happy 2019-04-18 01:14 13 | */ 14 | @Data 15 | public class ErrorMessage implements MessageSourceResolvable { 16 | private String[] codes; 17 | private Object[] arguments; 18 | private String defaultMessage; 19 | private LocalDateTime timestamp; 20 | private String path; 21 | private String message; 22 | private List errors; 23 | /** 24 | * 状态字段 25 | */ 26 | private int status; 27 | 28 | public ErrorMessage(String[] codes, Object[] arguments, String defaultMessage) { 29 | this.codes = codes; 30 | this.arguments = arguments; 31 | this.defaultMessage = defaultMessage; 32 | } 33 | 34 | public ErrorMessage(String code, Object... args) { 35 | this(new String[]{code}, args); 36 | } 37 | 38 | public ErrorMessage(String[] codes, Object[] arguments) { 39 | this(codes, arguments, codes[0]); 40 | } 41 | 42 | public ErrorMessage(String code, String... argCode) { 43 | this(code, (Object[]) Stream.of(argCode) 44 | .map(DefaultError::new) 45 | .toArray(DefaultError[]::new)); 46 | } 47 | 48 | public ErrorMessage addFieldObjs(String field, String[] codes, Object... args) { 49 | return add(new FieldError(field, codes, args)); 50 | } 51 | 52 | public ErrorMessage add(FieldError fieldError) { 53 | if (errors == null) { 54 | errors = new ArrayList<>(); 55 | } 56 | errors.add(fieldError); 57 | return this; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/exception/ErrorMessageException.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.exception; 2 | 3 | import org.apache.commons.lang3.ArrayUtils; 4 | import reactor.core.publisher.Mono; 5 | 6 | import java.text.MessageFormat; 7 | import java.util.stream.Stream; 8 | 9 | /** 10 | * @author happy 2019-04-16 23:37 11 | * 错误消息异常(可预知错误均抛出此异常) 12 | */ 13 | public class ErrorMessageException extends RuntimeException { 14 | private ErrorMessage errorMessage; 15 | private ErrorMessageException(String[] codes, Object[] arguments, String defaultMessage, Throwable cause) { 16 | super(MessageFormat.format( 17 | "codes:{0},args:{1}, defaultMessage:{2}", 18 | ArrayUtils.toString(codes), 19 | ArrayUtils.toString(arguments), 20 | defaultMessage 21 | ), cause); 22 | this.errorMessage = new ErrorMessage(codes, arguments, defaultMessage); 23 | } 24 | 25 | /** 26 | * 解析错误码和参数码 27 | * 28 | * @param code 错误码 29 | * @param argsCode 参数码 30 | * @return 解析后的异常 31 | */ 32 | private static ErrorMessageException parseCode(String code, String... argsCode) { 33 | return new ErrorMessageException(code, argsCode); 34 | } 35 | 36 | private ErrorMessageException(String code, String... argsCodes) { 37 | this(new String[]{code}, Stream.of(argsCodes).map(DefaultError::new).toArray(DefaultError[]::new), null, null); 38 | } 39 | 40 | public static Mono mono(String code) { 41 | return Mono.error(parseCode(code)); 42 | } 43 | 44 | public static ErrorMessageException of(String code) { 45 | return new ErrorMessageException(new String[]{code}, null, null, null); 46 | } 47 | 48 | public ErrorMessage getErrorMessage() { 49 | return errorMessage; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/exception/FieldError.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.exception; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import org.springframework.context.MessageSourceResolvable; 5 | import org.springframework.util.Assert; 6 | import reactor.util.annotation.Nullable; 7 | 8 | import java.util.Arrays; 9 | 10 | /** 11 | * @author happy 2019-04-18 01:32 12 | */ 13 | @JsonIgnoreProperties("code") 14 | public class FieldError implements MessageSourceResolvable { 15 | private String[] codes; 16 | private Object[] arguments; 17 | private String defaultMessage; 18 | 19 | 20 | private String field; 21 | private String message; 22 | 23 | public FieldError() { 24 | } 25 | 26 | private FieldError(String[] codes, Object[] arguments, String defaultMessage) { 27 | this.codes = codes; 28 | this.arguments = arguments; 29 | this.defaultMessage = defaultMessage; 30 | } 31 | 32 | /** 33 | * Create a new instance of the ObjectError class. 34 | * 35 | * @param field the name of the affected object 36 | * @param defaultMessage the default message to be used to resolve this message 37 | */ 38 | public FieldError(String field, String defaultMessage) { 39 | this(field, null, null, defaultMessage); 40 | } 41 | 42 | /** 43 | * Create a new instance of the ObjectError class. 44 | * 45 | * @param field the name of the affected object 46 | * @param codes the codes to be used to resolve this message 47 | * @param arguments the array of arguments to be used to resolve this message 48 | * @param defaultMessage the default message to be used to resolve this message 49 | */ 50 | public FieldError( 51 | String field, 52 | @Nullable String[] codes, 53 | @Nullable Object[] arguments, 54 | @Nullable String defaultMessage) { 55 | this(codes, arguments, defaultMessage); 56 | Assert.notNull(field, "Object name must not be null"); 57 | this.field = field; 58 | } 59 | 60 | public FieldError( 61 | String field, 62 | @Nullable String[] codes, 63 | @Nullable Object[] arguments 64 | ) { 65 | this(codes, arguments, null); 66 | Assert.notNull(field, "Object name must not be null"); 67 | this.field = field; 68 | } 69 | 70 | public String getField() { 71 | return field; 72 | } 73 | 74 | 75 | public String getMessage() { 76 | return message; 77 | } 78 | 79 | public void setMessage(String message) { 80 | this.message = message; 81 | } 82 | 83 | 84 | @Override 85 | public String[] getCodes() { 86 | return this.codes; 87 | } 88 | 89 | 90 | public String getCode() { 91 | return this.codes != null && this.codes.length > 0 ? this.codes[this.codes.length - 1] : null; 92 | } 93 | 94 | public void setField(String field) { 95 | this.field = field; 96 | } 97 | 98 | @Override 99 | public Object[] getArguments() { 100 | return this.arguments; 101 | } 102 | 103 | 104 | @Override 105 | public String getDefaultMessage() { 106 | String defaultMessage = this.defaultMessage; 107 | if (defaultMessage == null) { 108 | return getCode(); 109 | } 110 | return defaultMessage; 111 | } 112 | 113 | public void setCodes(String[] codes) { 114 | this.codes = codes; 115 | } 116 | 117 | public void setArguments(Object[] arguments) { 118 | this.arguments = arguments; 119 | } 120 | 121 | public void setDefaultMessage(String defaultMessage) { 122 | this.defaultMessage = defaultMessage; 123 | } 124 | 125 | @Override 126 | public String toString() { 127 | return "FieldError{" + 128 | "codes=" + Arrays.toString(codes) + 129 | ", arguments=" + Arrays.toString(arguments) + 130 | ", defaultMessage='" + defaultMessage + '\'' + 131 | ", field='" + field + '\'' + 132 | ", message='" + message + '\'' + 133 | '}'; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/exception/ForbiddenException.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.exception; 2 | 3 | import org.apache.commons.lang3.ArrayUtils; 4 | import reactor.core.publisher.Mono; 5 | 6 | import java.text.MessageFormat; 7 | import java.util.stream.Stream; 8 | 9 | public class ForbiddenException extends RuntimeException { 10 | private ErrorMessage errorMessage; 11 | 12 | public ForbiddenException(String message) { 13 | super(message); 14 | } 15 | 16 | private ForbiddenException(String[] codes, Object[] arguments, String defaultMessage, Throwable cause) { 17 | super(MessageFormat.format( 18 | "codes:{0},args:{1}, defaultMessage:{2}", 19 | ArrayUtils.toString(codes), 20 | ArrayUtils.toString(arguments), 21 | defaultMessage 22 | ), cause); 23 | this.errorMessage = new ErrorMessage(codes, arguments, defaultMessage); 24 | } 25 | 26 | public static ForbiddenException of(String message) { 27 | return new ForbiddenException(message); 28 | } 29 | 30 | private static ForbiddenException parseCode(String code, String... argsCode) { 31 | return new ForbiddenException(code, argsCode); 32 | } 33 | 34 | private ForbiddenException(String code, String... argsCodes) { 35 | this(new String[]{code}, Stream.of(argsCodes).map(DefaultError::new).toArray(DefaultError[]::new), null, null); 36 | } 37 | 38 | public static Mono mono(String code) { 39 | return Mono.error(parseCode(code)); 40 | } 41 | 42 | public ErrorMessage getErrorMessage() { 43 | return errorMessage; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/exception/UnauthorizedException.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.exception; 2 | 3 | import org.apache.commons.lang3.ArrayUtils; 4 | import reactor.core.publisher.Mono; 5 | 6 | import java.text.MessageFormat; 7 | import java.util.stream.Stream; 8 | 9 | public class UnauthorizedException extends RuntimeException { 10 | private ErrorMessage errorMessage; 11 | 12 | public UnauthorizedException(String message) { 13 | super(message); 14 | } 15 | 16 | private UnauthorizedException(String[] codes, Object[] arguments, String defaultMessage, Throwable cause) { 17 | super(MessageFormat.format( 18 | "codes:{0},args:{1}, defaultMessage:{2}", 19 | ArrayUtils.toString(codes), 20 | ArrayUtils.toString(arguments), 21 | defaultMessage 22 | ), cause); 23 | this.errorMessage = new ErrorMessage(codes, arguments, defaultMessage); 24 | } 25 | 26 | public static UnauthorizedException of(String message) { 27 | return new UnauthorizedException(message); 28 | } 29 | 30 | private static UnauthorizedException parseCode(String code, String... argsCode) { 31 | return new UnauthorizedException(code, argsCode); 32 | } 33 | 34 | private UnauthorizedException(String code, String... argsCodes) { 35 | this(new String[]{code}, Stream.of(argsCodes).map(DefaultError::new).toArray(DefaultError[]::new), null, null); 36 | } 37 | 38 | public static Mono mono(String code) { 39 | return Mono.error(parseCode(code)); 40 | } 41 | 42 | public ErrorMessage getErrorMessage() { 43 | return errorMessage; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/form/PageForm.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.form; 2 | 3 | import lombok.Data; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import javax.validation.constraints.Max; 8 | import javax.validation.constraints.Min; 9 | 10 | /** 11 | * @author happy 2019-04-27 10:53 12 | */ 13 | @Getter 14 | @Setter 15 | public class PageForm { 16 | /** 17 | * 页码 18 | */ 19 | @Min(value = 0, message = "页面最小为0") 20 | private int page = 0; 21 | /** 22 | * 页大小 23 | */ 24 | @Min(value = 1, message = "页大小最小为1") 25 | @Max(value = 100, message = "页大小最大为100") 26 | private int pageSize = 10; 27 | } 28 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/mongo/PageAgent.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.mongo; 2 | 3 | import org.springframework.data.domain.Page; 4 | import org.springframework.data.domain.PageImpl; 5 | import org.springframework.data.domain.PageRequest; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.mongodb.core.ReactiveMongoTemplate; 8 | import org.springframework.data.mongodb.core.query.Query; 9 | import reactor.core.publisher.Mono; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author happy 2019-04-27 11:06 15 | */ 16 | public class PageAgent { 17 | private ReactiveMongoTemplate reactiveMongoTemplate; 18 | private Class clazz; 19 | 20 | public PageAgent(ReactiveMongoTemplate reactiveMongoTemplate, Class clazz) { 21 | this.reactiveMongoTemplate = reactiveMongoTemplate; 22 | this.clazz = clazz; 23 | } 24 | 25 | public Mono> findPage(Query query, Pageable pageable) { 26 | return Mono.subscriberContext() 27 | .flatMap(context -> Mono 28 | .zip( 29 | reactiveMongoTemplate.find(query, clazz).collectList(), 30 | reactiveMongoTemplate.count(query, clazz) 31 | ) 32 | .map(z -> { 33 | List goodsList = z.getT1(); 34 | Long num = z.getT2(); 35 | return new PageImpl<>(goodsList, PageRequest.of(pageable.getPageNumber(), pageable.getPageSize()), num); 36 | }) 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/service/DefaultLoginInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.service; 2 | 3 | import org.rxjava.common.core.entity.LoginInfo; 4 | import org.springframework.web.server.ServerWebExchange; 5 | import reactor.core.publisher.Mono; 6 | 7 | /** 8 | * @author happy 2019-06-29 18:23 9 | * 默认登陆信息服务 10 | */ 11 | public class DefaultLoginInfoServiceImpl implements LoginInfoService { 12 | /** 13 | * Token检查 14 | */ 15 | @Override 16 | public Mono checkToken(ServerWebExchange serverWebExchange) { 17 | return Mono.empty(); 18 | } 19 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/service/LoginInfoService.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.service; 2 | 3 | import org.rxjava.common.core.entity.LoginInfo; 4 | import org.springframework.http.HttpMethod; 5 | import org.springframework.web.server.ServerWebExchange; 6 | import reactor.core.publisher.Mono; 7 | 8 | /** 9 | * @author happy 2019-06-29 21:52 10 | */ 11 | public interface LoginInfoService { 12 | 13 | /** 14 | * token校验 15 | */ 16 | Mono checkToken(ServerWebExchange serverWebExchange); 17 | } 18 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/status/Status.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.status; 2 | 3 | /** 4 | * @author happy 2019-04-27 10:31 5 | */ 6 | public enum Status { 7 | /** 8 | * 正常 9 | */ 10 | NORMAL, 11 | /** 12 | * 下线 13 | */ 14 | OFFLINE, 15 | /** 16 | * 删除 17 | */ 18 | DELETE 19 | } 20 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/tools/RequestTool.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.tools; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import com.fasterxml.jackson.databind.node.JsonNodeFactory; 5 | import org.rxjava.common.core.utils.JsonUtils; 6 | import org.springframework.http.HttpMethod; 7 | import org.springframework.util.LinkedMultiValueMap; 8 | import org.springframework.util.MultiValueMap; 9 | import org.springframework.util.StringUtils; 10 | import org.springframework.web.reactive.function.BodyInserters; 11 | import org.springframework.web.reactive.function.client.WebClient; 12 | import reactor.core.publisher.Mono; 13 | 14 | /** 15 | * @author happy 2019/10/5 11:54 16 | */ 17 | public class RequestTool { 18 | 19 | public Mono get(String requestUrl) { 20 | return get(requestUrl, new LinkedMultiValueMap<>()); 21 | } 22 | 23 | /** 24 | * get请求 25 | * 路径参数 26 | */ 27 | public Mono get(String requestUrl, MultiValueMap params) { 28 | return WebClient.create(requestUrl) 29 | .method(HttpMethod.GET) 30 | .uri(uriBuilder -> { 31 | if (params.isEmpty()) { 32 | return uriBuilder.build(); 33 | } 34 | return uriBuilder.queryParams(params).build(); 35 | }) 36 | .retrieve() 37 | .bodyToMono(String.class) 38 | .map(jsonStr -> { 39 | if (StringUtils.isEmpty(jsonStr) || !(jsonStr.startsWith("[") || jsonStr.startsWith("{"))) { 40 | return JsonNodeFactory.instance.missingNode(); 41 | } 42 | return JsonUtils.deserialize(jsonStr, JsonNode.class); 43 | }); 44 | } 45 | 46 | public Mono post(String requestUrl) { 47 | return post(requestUrl, new LinkedMultiValueMap<>()); 48 | } 49 | 50 | /** 51 | * post请求 52 | * formdata参数 53 | */ 54 | public Mono post(String requestUrl, MultiValueMap params) { 55 | return WebClient.create(requestUrl) 56 | .method(HttpMethod.POST) 57 | .body(BodyInserters.fromFormData(params)) 58 | .retrieve() 59 | .bodyToMono(String.class); 60 | } 61 | 62 | public static void main(String[] args) { 63 | JsonNode block = new RequestTool().get("https://qy-h5-dev.billbear.cn/api/javahotel/cityList").block(); 64 | System.out.println(block); 65 | } 66 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/utils/ErrorMessageUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.utils; 2 | 3 | import org.rxjava.common.core.exception.ErrorMessage; 4 | import org.springframework.context.support.MessageSourceAccessor; 5 | import org.springframework.util.CollectionUtils; 6 | 7 | /** 8 | * @author happy 2019-04-18 01:25 9 | */ 10 | public class ErrorMessageUtils { 11 | public static ErrorMessage handlerI18n(ErrorMessage errorMessage, MessageSourceAccessor messageSourceAccessor) { 12 | if (errorMessage.getMessage() == null) { 13 | errorMessage.setMessage(messageSourceAccessor.getMessage(errorMessage)); 14 | } 15 | 16 | if (!CollectionUtils.isEmpty(errorMessage.getErrors())) { 17 | errorMessage.getErrors().forEach(fieldError -> { 18 | if (fieldError.getMessage() == null) { 19 | fieldError.setMessage(messageSourceAccessor.getMessage(fieldError)); 20 | } 21 | }); 22 | } 23 | return errorMessage; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/utils/FileRenameUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.utils; 2 | 3 | import net.sourceforge.pinyin4j.PinyinHelper; 4 | import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; 5 | import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; 6 | import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; 7 | import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType; 8 | import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; 9 | import org.apache.commons.lang3.ArrayUtils; 10 | import org.apache.commons.lang3.StringUtils; 11 | 12 | import java.io.IOException; 13 | import java.nio.file.Files; 14 | import java.nio.file.Path; 15 | import java.nio.file.Paths; 16 | import java.nio.file.StandardCopyOption; 17 | import java.util.stream.Collectors; 18 | 19 | /** 20 | * @author happy 2019-06-20 14:41 21 | */ 22 | public class FileRenameUtils { 23 | public static final HanyuPinyinOutputFormat FORMAT = new HanyuPinyinOutputFormat(); 24 | 25 | static { 26 | FORMAT.setCaseType(HanyuPinyinCaseType.LOWERCASE); 27 | FORMAT.setToneType(HanyuPinyinToneType.WITHOUT_TONE); 28 | FORMAT.setVCharType(HanyuPinyinVCharType.WITH_V); 29 | } 30 | 31 | public static void main(String[] args) { 32 | 33 | Path source = Paths.get("/Users/happy/DeskTop/img"); 34 | Path dist = Paths.get("/Users/happy/DeskTop/img_py"); 35 | handler(source, dist, "@", "Select"); 36 | } 37 | 38 | private static void handler(Path source, Path dist, String split, String suffix) { 39 | try { 40 | if (Files.isDirectory(source)) { 41 | Files.list(source).forEach(child -> { 42 | Path fileName = child.getFileName(); 43 | String pinyinName = toPinyin(fileName.getFileName().toString()); 44 | if (StringUtils.isNoneEmpty(split, suffix)) { 45 | pinyinName = pinyinName.replace(split, suffix + split); 46 | } 47 | handler(child, dist.resolve(pinyinName)); 48 | }); 49 | } else { 50 | String pinyinName = toPinyin(dist.getFileName().toString()) + suffix; 51 | Files.createDirectories(dist.getParent()); 52 | Files.copy(source, dist.resolveSibling(pinyinName), StandardCopyOption.REPLACE_EXISTING); 53 | } 54 | } catch (IOException ex) { 55 | throw new RuntimeException(ex); 56 | } 57 | } 58 | 59 | private static void handler(Path source, Path dist) { 60 | handler(source, dist, "", ""); 61 | } 62 | 63 | public static String toPinyin(String name) { 64 | return name.chars().mapToObj((int r) -> { 65 | try { 66 | char ch = (char) r; 67 | String[] pinyins = PinyinHelper.toHanyuPinyinStringArray(ch, FORMAT); 68 | if (ArrayUtils.isEmpty(pinyins)) { 69 | return Character.toString(ch); 70 | } else { 71 | String pinyin = pinyins[0]; 72 | return pinyin.substring(0, 1).toUpperCase() + 73 | (pinyin.length() > 1 ? pinyin.substring(1) : ""); 74 | } 75 | } catch (BadHanyuPinyinOutputFormatCombination ex) { 76 | throw new RuntimeException(ex); 77 | } 78 | }).collect(Collectors.joining()); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/utils/JavaTimeModuleUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.utils; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.databind.DeserializationContext; 6 | import com.fasterxml.jackson.databind.JsonDeserializer; 7 | import com.fasterxml.jackson.databind.JsonSerializer; 8 | import com.fasterxml.jackson.databind.SerializerProvider; 9 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 10 | import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; 11 | import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; 12 | import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; 13 | import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; 14 | import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; 15 | import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; 16 | import lombok.Getter; 17 | 18 | import java.io.IOException; 19 | import java.time.*; 20 | import java.time.format.DateTimeFormatter; 21 | 22 | /** 23 | * 日期时间模块帮助类 24 | */ 25 | public class JavaTimeModuleUtils { 26 | @Getter 27 | private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; 28 | @Getter 29 | private static final String DATE_FORMAT = "yyyy-MM-dd"; 30 | @Getter 31 | private static final String TIME_FORMAT = "HH:mm:ss.SSS"; 32 | @Getter 33 | private static JavaTimeModule javaTimeModule = new JavaTimeModule(); 34 | 35 | /** 36 | * 禁止实例化 37 | */ 38 | private JavaTimeModuleUtils() { 39 | } 40 | 41 | /** 42 | * 添加日期时间格式解析支持 43 | */ 44 | public static void addAllFormatter(){ 45 | addTimeFormatter(); 46 | addInstantFormatter(); 47 | addDateTimeFormatter(); 48 | addDateFormatter(); 49 | } 50 | 51 | /** 52 | * 添加日期时间格式支持 53 | */ 54 | private static void addDateTimeFormatter() { 55 | DateTimeFormatter dataTimeFormatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT).withZone(ZoneId.systemDefault()); 56 | javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dataTimeFormatter)); 57 | javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dataTimeFormatter)); 58 | } 59 | 60 | /** 61 | * 添加日期格式支持 62 | */ 63 | private static void addDateFormatter() { 64 | DateTimeFormatter dataFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT).withZone(ZoneId.systemDefault()); 65 | javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dataFormatter)); 66 | javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dataFormatter)); 67 | } 68 | 69 | /** 70 | * 添加时间格式支持 71 | */ 72 | private static void addTimeFormatter() { 73 | DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(TIME_FORMAT).withZone(ZoneId.systemDefault()); 74 | javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter)); 75 | javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter)); 76 | } 77 | 78 | /** 79 | * 添加Instant格式支持 80 | */ 81 | private static void addInstantFormatter(){ 82 | DateTimeFormatter dataTimeFormatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT).withZone(ZoneId.systemDefault()); 83 | javaTimeModule.addDeserializer(Instant.class, new JsonDeserializer() { 84 | @Override 85 | public Instant deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { 86 | return Instant.from(dataTimeFormatter.parse(jsonParser.getText())); 87 | } 88 | }); 89 | javaTimeModule.addSerializer(Instant.class, new JsonSerializer() { 90 | @Override 91 | public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException { 92 | String str = dataTimeFormatter.format(value); 93 | gen.writeString(str); 94 | } 95 | }); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/utils/JsonUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.utils; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | 5 | import java.io.IOException; 6 | import java.util.List; 7 | 8 | /** 9 | * @author happy 2019-04-16 23:26 10 | */ 11 | public class JsonUtils { 12 | public static final ObjectMapper DEFAULT_MAPPER = new ObjectMapper(); 13 | 14 | public static ObjectMapper create() { 15 | return new ObjectMapper(); 16 | } 17 | 18 | /** 19 | * 反序列化Json字符串 20 | */ 21 | public static T deserialize(String json, Class valueType) { 22 | try { 23 | return DEFAULT_MAPPER.readValue(json, valueType); 24 | } catch (IOException e) { 25 | throw new RuntimeException(e.getMessage(), e); 26 | } 27 | } 28 | 29 | public static String serialize(Object o) { 30 | try { 31 | if (o instanceof List) { 32 | return DEFAULT_MAPPER.writeValueAsString(((List) o).toArray()); 33 | } 34 | return DEFAULT_MAPPER.writeValueAsString(o); 35 | } catch (IOException e) { 36 | throw new RuntimeException(e.getMessage(), e); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/utils/KeyUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.utils; 2 | 3 | /** 4 | * @author happy 2019-04-27 00:30 5 | */ 6 | public class KeyUtils { 7 | public static String newCacheId(Class clazz, String key) { 8 | return clazz.getSimpleName() + "-" + key; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-core/src/main/java/org/rxjava/common/core/utils/UUIDUtils.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.core.utils; 2 | 3 | import java.util.Base64; 4 | import java.util.UUID; 5 | 6 | /** 7 | * @author happy 2019-01-12 22:41 8 | * UUID帮助类 9 | */ 10 | public class UUIDUtils { 11 | public static String randomUUIDToBase64() { 12 | UUID uuid = UUID.randomUUID(); 13 | byte[] uuidArr = asByteArray(uuid); 14 | return Base64.getUrlEncoder().withoutPadding().encodeToString(uuidArr); 15 | } 16 | 17 | public static void main(String[] args) { 18 | System.out.println(randomUUIDToBase64()); 19 | System.out.println(randomUUIDToBase64().length()); 20 | } 21 | 22 | public static byte[] asByteArray(UUID uuid) { 23 | long msb = uuid.getMostSignificantBits(); 24 | long lsb = uuid.getLeastSignificantBits(); 25 | byte[] buffer = new byte[16]; 26 | 27 | for (int i = 0; i < 8; i++) { 28 | buffer[i] = (byte) (msb >>> 8 * (7 - i)); 29 | } 30 | for (int i = 8; i < 16; i++) { 31 | buffer[i] = (byte) (lsb >>> 8 * (7 - i)); 32 | } 33 | 34 | return buffer; 35 | } 36 | 37 | public static UUID toUUID(byte[] byteArray) { 38 | 39 | long msb = 0; 40 | long lsb = 0; 41 | for (int i = 0; i < 8; i++) { 42 | msb = (msb << 8) | (byteArray[i] & 0xff); 43 | } 44 | for (int i = 8; i < 16; i++) { 45 | lsb = (lsb << 8) | (byteArray[i] & 0xff); 46 | } 47 | return new UUID(msb, lsb); 48 | } 49 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-starter-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.rxjava 5 | rxjava-spring 6 | 1.0.9-SNAPSHOT 7 | 8 | 4.0.0 9 | rxjava-spring-boot-starter-service 10 | jar 11 | 12 | 13 | org.rxjava 14 | rxjava-spring-boot-core 15 | ${project.parent.version} 16 | 17 | 18 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-starter-service/src/main/java/org/rxjava/service/starter/RxJavaServiceAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.starter; 2 | 3 | import org.rxjava.service.starter.boot.RxJavaWebFluxConfigurer; 4 | import org.rxjava.service.starter.boot.ServiceDelegatingWebFluxConfiguration; 5 | import org.springframework.boot.autoconfigure.AutoConfigureOrder; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.Import; 9 | import org.springframework.core.Ordered; 10 | import org.springframework.data.mongodb.config.EnableMongoAuditing; 11 | 12 | /** 13 | * @author happy 2019-04-09 01:32 14 | * RxJava微服务自动装配 15 | */ 16 | @Configuration 17 | @EnableDiscoveryClient 18 | @EnableMongoAuditing 19 | @Import({ServiceDelegatingWebFluxConfiguration.class, RxJavaWebFluxConfigurer.class}) 20 | @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) 21 | public class RxJavaServiceAutoConfiguration { 22 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-starter-service/src/main/java/org/rxjava/service/starter/boot/LoginInfoArgumentResolver.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.starter.boot; 2 | 3 | import org.rxjava.common.core.entity.LoginInfo; 4 | import org.springframework.core.MethodParameter; 5 | import org.springframework.core.ReactiveAdapterRegistry; 6 | import org.springframework.web.reactive.BindingContext; 7 | import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport; 8 | import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver; 9 | import org.springframework.web.server.ServerWebExchange; 10 | 11 | /** 12 | * @author happy 2019-04-14 17:21 13 | * 登陆信息参数解析 14 | */ 15 | public class LoginInfoArgumentResolver extends HandlerMethodArgumentResolverSupport implements SyncHandlerMethodArgumentResolver { 16 | 17 | static final String LOGIN_REQUEST_ATTRIBUTE = LoginInfoArgumentResolver.class.getName() + "LOGIN_REQUEST_ATTRIBUTE"; 18 | 19 | public LoginInfoArgumentResolver(ReactiveAdapterRegistry adapterRegistry) { 20 | super(adapterRegistry); 21 | } 22 | 23 | @Override 24 | public boolean supportsParameter(MethodParameter parameter) { 25 | return parameter.getParameterType().equals(LoginInfo.class); 26 | } 27 | 28 | @Override 29 | public Object resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) { 30 | return exchange.getAttribute(LoginInfoArgumentResolver.LOGIN_REQUEST_ATTRIBUTE); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-starter-service/src/main/java/org/rxjava/service/starter/boot/RxJavaWebFluxConfigurer.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.starter.boot; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; 6 | import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; 7 | import org.rxjava.common.core.utils.JavaTimeModuleUtils; 8 | import org.rxjava.common.core.utils.JsonUtils; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Primary; 12 | import org.springframework.context.support.ReloadableResourceBundleMessageSource; 13 | import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; 14 | import org.springframework.data.redis.core.ReactiveRedisTemplate; 15 | import org.springframework.data.redis.serializer.RedisSerializationContext; 16 | import org.springframework.http.codec.ServerCodecConfigurer; 17 | import org.springframework.http.codec.json.Jackson2JsonDecoder; 18 | import org.springframework.http.codec.json.Jackson2JsonEncoder; 19 | import org.springframework.web.reactive.config.WebFluxConfigurer; 20 | 21 | import java.text.SimpleDateFormat; 22 | 23 | /** 24 | * @author happy 2019-05-13 01:30 25 | * WebFluxConfigurer 26 | */ 27 | public class RxJavaWebFluxConfigurer implements WebFluxConfigurer { 28 | 29 | @Autowired 30 | private ObjectMapper objectMapper; 31 | 32 | /** 33 | * Redis Bean 34 | */ 35 | @Bean 36 | @Primary 37 | ReactiveRedisTemplate reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) { 38 | return new ReactiveRedisTemplate<>(factory, RedisSerializationContext.string()); 39 | } 40 | 41 | /** 42 | * 使用指定的资源访问指定的名称,异常消息国际化处理 43 | */ 44 | @Bean 45 | public ReloadableResourceBundleMessageSource messageSource() { 46 | ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); 47 | messageSource.setBasenames( 48 | "classpath:exceptions/exception", 49 | "classpath:defaultExceptions/exception" 50 | ); 51 | messageSource.setUseCodeAsDefaultMessage(true); 52 | messageSource.setCacheSeconds(99999999); 53 | return messageSource; 54 | } 55 | 56 | /** 57 | * 配置ObjectMapper 58 | */ 59 | @Bean 60 | @Primary 61 | public ObjectMapper objectMapper() { 62 | ObjectMapper objectMapper = JsonUtils.create(); 63 | //字段值为null则不输出 64 | objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 65 | 66 | //添加json日期时间序列化和反序列化格式支持 67 | JavaTimeModuleUtils.addAllFormatter(); 68 | 69 | //注册模块 70 | objectMapper 71 | .registerModule(new ParameterNamesModule()) 72 | .registerModule(new Jdk8Module()) 73 | .registerModule(JavaTimeModuleUtils.getJavaTimeModule()); 74 | 75 | //配置SimpleDateFormat格式为日期时间格式 76 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat(JavaTimeModuleUtils.getDATE_TIME_FORMAT()); 77 | simpleDateFormat.setLenient(false); 78 | objectMapper.setDateFormat(simpleDateFormat); 79 | 80 | return objectMapper; 81 | } 82 | 83 | /** 84 | * 配置json序列化和反序列化 85 | */ 86 | @Override 87 | public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { 88 | configurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper)); 89 | configurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-starter-service/src/main/java/org/rxjava/service/starter/boot/SecurityRequestMappingHandlerAdapter.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.starter.boot; 2 | 3 | import org.apache.commons.lang3.ObjectUtils; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.rxjava.common.core.annotation.Login; 8 | import org.rxjava.common.core.entity.LoginInfo; 9 | import org.rxjava.common.core.exception.ErrorMessageException; 10 | import org.rxjava.common.core.exception.UnauthorizedException; 11 | import org.rxjava.common.core.utils.JsonUtils; 12 | import org.springframework.http.server.PathContainer; 13 | import org.springframework.http.server.reactive.ServerHttpRequest; 14 | import org.springframework.web.method.HandlerMethod; 15 | import org.springframework.web.reactive.HandlerResult; 16 | import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter; 17 | import org.springframework.web.server.ServerWebExchange; 18 | import reactor.core.publisher.Mono; 19 | 20 | import java.io.UnsupportedEncodingException; 21 | import java.net.URLDecoder; 22 | 23 | import static org.rxjava.service.starter.boot.LoginInfoArgumentResolver.LOGIN_REQUEST_ATTRIBUTE; 24 | 25 | /** 26 | * @author happy 2019-04-16 23:05 27 | * 请求映射适配器 28 | */ 29 | public class SecurityRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter { 30 | private static final Logger log = LogManager.getLogger(); 31 | private static final String LOGIN_INFO = "loginInfo"; 32 | 33 | SecurityRequestMappingHandlerAdapter() { 34 | super(); 35 | } 36 | 37 | @Override 38 | public boolean supports(Object handler) { 39 | return super.supports(handler); 40 | } 41 | 42 | @Override 43 | public Mono handle(ServerWebExchange exchange, Object handler) { 44 | HandlerMethod handlerMethod = (HandlerMethod) handler; 45 | 46 | ServerHttpRequest request = exchange.getRequest(); 47 | PathContainer path = request.getPath().pathWithinApplication(); 48 | String pathValue = path.value(); 49 | 50 | //微服务彼此间接口不注入登陆信息(信息均需要明确传入) 51 | if (pathValue.startsWith("/inner/")) { 52 | return super.handle(exchange, handler); 53 | } 54 | 55 | //检查接口方法是否需要登陆 56 | Login login = handlerMethod.getMethodAnnotation(Login.class); 57 | if (login == null || login.value()) { 58 | 59 | String loginInfoJson = request.getHeaders().getFirst(LOGIN_INFO); 60 | LoginInfo loginInfo = parseLoginJson(loginInfoJson); 61 | 62 | if (loginInfo == null) { 63 | throw UnauthorizedException.of("unauthorized"); 64 | } 65 | //请求参数注入登陆信息对象 66 | exchange.getAttributes().put(LOGIN_REQUEST_ATTRIBUTE, loginInfo); 67 | } 68 | return super.handle(exchange, handler); 69 | } 70 | 71 | /** 72 | * 解析网关注入的登陆信息 73 | */ 74 | private LoginInfo parseLoginJson(String loginInfoJson) { 75 | log.info("parseLoginJson:{}", loginInfoJson); 76 | if (StringUtils.isEmpty(loginInfoJson)) { 77 | return null; 78 | } 79 | try { 80 | loginInfoJson = URLDecoder.decode(loginInfoJson, "utf8"); 81 | } catch (UnsupportedEncodingException e) { 82 | throw new RuntimeException(e); 83 | } 84 | return JsonUtils.deserialize(loginInfoJson, LoginInfo.class); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-starter-service/src/main/java/org/rxjava/service/starter/boot/ServiceDelegatingWebFluxConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.service.starter.boot; 2 | 3 | import org.rxjava.common.core.exception.JsonResponseStatusExceptionHandler; 4 | import org.springframework.beans.factory.ObjectProvider; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.core.Ordered; 7 | import org.springframework.core.annotation.Order; 8 | import org.springframework.http.codec.ServerCodecConfigurer; 9 | import org.springframework.web.reactive.config.DelegatingWebFluxConfiguration; 10 | import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer; 11 | import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter; 12 | import org.springframework.web.reactive.result.view.ViewResolver; 13 | import org.springframework.web.server.WebExceptionHandler; 14 | 15 | import java.util.Collections; 16 | import java.util.List; 17 | 18 | /** 19 | * @author happy 2019-04-16 23:04 20 | * DelegatingWebFluxConfiguration 21 | */ 22 | public class ServiceDelegatingWebFluxConfiguration extends DelegatingWebFluxConfiguration { 23 | 24 | @Override 25 | protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() { 26 | return new SecurityRequestMappingHandlerAdapter(); 27 | } 28 | 29 | /** 30 | * 异常处理器(排在所有异常处理器最前面) 31 | */ 32 | @Bean 33 | @Order(Ordered.HIGHEST_PRECEDENCE) 34 | public WebExceptionHandler jsonResponseStatusExceptionHandler( 35 | ObjectProvider> viewResolversProvider, 36 | ServerCodecConfigurer serverCodecConfigurer 37 | ) { 38 | JsonResponseStatusExceptionHandler handler = new JsonResponseStatusExceptionHandler(); 39 | handler.setMessageWriters(serverCodecConfigurer.getWriters()); 40 | handler.setViewResolvers(viewResolversProvider.getIfAvailable(Collections::emptyList)); 41 | return handler; 42 | } 43 | 44 | /** 45 | * 自定义方法参数配置解析器 46 | */ 47 | @Override 48 | public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) { 49 | configurer.addCustomResolver(new LoginInfoArgumentResolver(webFluxAdapterRegistry())); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-starter-service/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.rxjava.service.starter.RxJavaServiceAutoConfiguration -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-starter-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | level: 3 | root: INFO 4 | org: 5 | springframework: 6 | #控制台打印mongodb操作数据库的日志信息 7 | data.mongodb.core.ReactiveMongoTemplate: DEBUG 8 | context.support: TRACE 9 | web: INFO 10 | boot: 11 | autoconfigure: 12 | logging: DEBUG 13 | #控制台打印httl模板引擎日志信息 14 | httl: INFO 15 | spring: 16 | http: 17 | encoding: 18 | force: true -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-boot-starter-service/src/main/resources/defaultExceptions/exception_zh_CN.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 默认异常异常消息 5 | 结果集空错误 6 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-bus/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.rxjava 5 | rxjava-spring 6 | 1.0.9-SNAPSHOT 7 | 8 | 4.0.0 9 | rxjava-spring-cloud-starter-bus 10 | jar 11 | 12 | 13 | org.springframework.cloud 14 | spring-cloud-starter-bus-amqp 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-bus/src/main/java/org/rxjava/common/bus/BusEvent.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.bus; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * @author happy 2019-06-04 10:26 11 | */ 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class BusEvent { 17 | /** 18 | * 事件唯一Id,保证幂等 19 | */ 20 | private String id; 21 | /** 22 | * 事件类型 23 | */ 24 | private BusEventType type; 25 | /** 26 | * 时间戳 27 | */ 28 | private long timestamp; 29 | /** 30 | * 微服务 31 | */ 32 | private String service; 33 | /** 34 | * 数据 35 | */ 36 | private JsonNode data; 37 | } 38 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-bus/src/main/java/org/rxjava/common/bus/BusEventType.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.bus; 2 | 3 | /** 4 | * @author happy 2019-06-04 10:24 5 | * 总线消息类型 6 | */ 7 | public enum BusEventType { 8 | //应用服务总线消息 9 | /** 10 | * 应用订单取消成功 11 | */ 12 | APP_ORDER_CANCEL_SUCCESS, 13 | /** 14 | * 应用订单待发货 15 | */ 16 | APP_ORDER_WAIT_DELIVER, 17 | /** 18 | * 应用订单发货成功 19 | */ 20 | APP_ORDER_SHIP_SUCCESS, 21 | 22 | //订单服务总线消息类型 23 | /** 24 | * 支付成功 25 | */ 26 | PAY_SUCCESS, 27 | /** 28 | * 订单取消开始 29 | */ 30 | ORDER_CANCEL_START, 31 | 32 | //会员卡服务总线消息类型 33 | 34 | //商品服务总线消息类型 35 | 36 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-bus/src/main/java/org/rxjava/common/bus/BusReceiver.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.bus; 2 | 3 | /** 4 | * @author happy 2019-06-04 10:30 5 | * 接收者 6 | */ 7 | public interface BusReceiver { 8 | void receiveMessage(BusEvent busEvent); 9 | } 10 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-bus/src/main/java/org/rxjava/common/bus/EnableBus.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.bus; 2 | 3 | import org.springframework.context.annotation.Import; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * @author happy 2019-06-04 10:22 9 | * 开启Bus 10 | */ 11 | @Target({ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Documented 14 | @Import({RxBusConfiguration.class}) 15 | public @interface EnableBus { 16 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-bus/src/main/java/org/rxjava/common/bus/MessageReceiver.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.bus; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.fasterxml.jackson.databind.exc.InvalidFormatException; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | import java.io.IOException; 10 | 11 | public class MessageReceiver { 12 | private static final Logger log = LogManager.getLogger(); 13 | 14 | @Autowired 15 | private ObjectMapper objectMapper; 16 | @Autowired 17 | private BusReceiver busReceiver; 18 | 19 | public void receiveMessage(String json) throws IOException { 20 | try { 21 | BusEvent busEvent = objectMapper.readValue(json, BusEvent.class); 22 | busReceiver.receiveMessage(busEvent); 23 | } catch (InvalidFormatException e) { 24 | log.info("忽略非json消息:{},Exception:{e}", json, e); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-bus/src/main/java/org/rxjava/common/bus/RxBusConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.common.bus; 2 | 3 | import org.springframework.amqp.core.Binding; 4 | import org.springframework.amqp.core.BindingBuilder; 5 | import org.springframework.amqp.core.FanoutExchange; 6 | import org.springframework.amqp.core.Queue; 7 | import org.springframework.amqp.rabbit.connection.ConnectionFactory; 8 | import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; 9 | import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter; 10 | import org.springframework.beans.factory.annotation.Qualifier; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 13 | import org.springframework.context.annotation.Bean; 14 | import org.springframework.context.annotation.Configuration; 15 | 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | /** 20 | * @author happy 2019-05-02 14:32 21 | * 消息总线配置 22 | */ 23 | @Configuration 24 | public class RxBusConfiguration { 25 | /** 26 | * fanout交换机名称 27 | */ 28 | static final String FANOUT_EXCHANGE = "rxjava-fanout-exchange"; 29 | /** 30 | * 队列名前缀 31 | */ 32 | private static final String QUEUE_NAME_PREFIX = "rxjava-queue."; 33 | /** 34 | * delay队列名前缀 35 | */ 36 | static final String QUEUE_NAME_DELAY_PREFIX = "rxjava-delay-queue."; 37 | /** 38 | * 应用名 39 | */ 40 | @Value("${spring.application.name}") 41 | String applicationName; 42 | 43 | /** 44 | * fanout交换机 45 | */ 46 | @Bean 47 | @Qualifier("fanoutExchange") 48 | public FanoutExchange fanoutExchange() { 49 | return new FanoutExchange(FANOUT_EXCHANGE); 50 | } 51 | 52 | /** 53 | * 队列 54 | */ 55 | @Bean 56 | @ConditionalOnBean(BusReceiver.class) 57 | @Qualifier("queue") 58 | public Queue queue() { 59 | return new Queue(QUEUE_NAME_PREFIX + applicationName, true); 60 | } 61 | 62 | /** 63 | * delay队列 64 | */ 65 | @Bean 66 | @ConditionalOnBean(BusReceiver.class) 67 | @Qualifier("delayQueue") 68 | public Queue delayQueue() { 69 | Map args = new HashMap<>(); 70 | args.put("x-dead-letter-exchange", FANOUT_EXCHANGE); 71 | args.put("x-dead-letter-router-key", QUEUE_NAME_PREFIX + "#"); 72 | return new Queue(QUEUE_NAME_DELAY_PREFIX + applicationName, true, false, false, args); 73 | } 74 | 75 | /** 76 | * 绑定交换机和队列 77 | */ 78 | @Bean 79 | @ConditionalOnBean(BusReceiver.class) 80 | @Qualifier("fanoutBinding") 81 | public Binding fanoutBinding( 82 | @Qualifier("fanoutExchange") FanoutExchange fanoutExchange, 83 | @Qualifier("queue") Queue queue 84 | ) { 85 | return BindingBuilder.bind(queue).to(fanoutExchange); 86 | } 87 | 88 | /** 89 | * 消息发射bean 90 | */ 91 | @Bean 92 | public BusEmitter busEmitter() { 93 | return new BusEmitter(); 94 | } 95 | 96 | /** 97 | * 消息接收bean 98 | */ 99 | @Bean 100 | @ConditionalOnBean(BusReceiver.class) 101 | @Qualifier("messageReceiver") 102 | public MessageReceiver messageReceiver() { 103 | return new MessageReceiver(); 104 | } 105 | 106 | /** 107 | * 消息监听适配器 108 | */ 109 | @Bean 110 | @ConditionalOnBean(BusReceiver.class) 111 | @Qualifier("messageListenerAdapter") 112 | public MessageListenerAdapter messageListenerAdapter(@Qualifier("messageReceiver") MessageReceiver messageReceiver) { 113 | return new MessageListenerAdapter(messageReceiver, "receiveMessage"); 114 | } 115 | 116 | /** 117 | * 消息监听容器 118 | */ 119 | @Bean 120 | @ConditionalOnBean(BusReceiver.class) 121 | public SimpleMessageListenerContainer busContainer( 122 | ConnectionFactory connectionFactory, 123 | @Qualifier("messageListenerAdapter") MessageListenerAdapter messageListenerAdapter 124 | ) { 125 | SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); 126 | container.setConnectionFactory(connectionFactory); 127 | container.setQueueNames(QUEUE_NAME_PREFIX + applicationName); 128 | container.setMessageListener(messageListenerAdapter); 129 | return container; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.rxjava 5 | rxjava-spring 6 | 1.0.9-SNAPSHOT 7 | 8 | 4.0.0 9 | rxjava-spring-cloud-starter-gateway 10 | jar 11 | 12 | 13 | org.springframework.cloud 14 | spring-cloud-starter-gateway 15 | 16 | 17 | org.rxjava 18 | rxjava-spring-boot-core 19 | ${project.parent.version} 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-security 24 | 25 | 26 | org.rxjava 27 | rxjava-spring-boot-starter-service 28 | ${project.parent.version} 29 | 30 | 31 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-gateway/src/main/java/org/rxjava/gateway/starter/RxJavaGatewayAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.gateway.starter; 2 | 3 | import org.rxjava.gateway.starter.config.RxJavaWebFluxSecurityConfig; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.Import; 6 | 7 | /** 8 | * @author happy 2019-06-28 14:32 9 | */ 10 | @Configuration 11 | @Import({RxJavaWebFluxSecurityConfig.class}) 12 | public class RxJavaGatewayAutoConfiguration { 13 | } 14 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-gateway/src/main/java/org/rxjava/gateway/starter/config/AuthenticationToken.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.gateway.starter.config; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.rxjava.common.core.entity.LoginInfo; 6 | import org.springframework.security.authentication.AbstractAuthenticationToken; 7 | 8 | /** 9 | * @author happy 2019-06-29 03:31 10 | * 授权token 11 | */ 12 | @Getter 13 | @Setter 14 | public class AuthenticationToken extends AbstractAuthenticationToken { 15 | private String token; 16 | private LoginInfo loginInfo; 17 | 18 | public AuthenticationToken(String token) { 19 | super(null); 20 | this.token = token; 21 | } 22 | 23 | public AuthenticationToken(String token, LoginInfo loginInfo) { 24 | super(null); 25 | this.token = token; 26 | this.loginInfo = loginInfo; 27 | setAuthenticated(true); 28 | } 29 | 30 | /** 31 | * 凭证即为token 32 | */ 33 | @Override 34 | public Object getCredentials() { 35 | return token; 36 | } 37 | 38 | /** 39 | * LoginInfo 40 | */ 41 | @Override 42 | public LoginInfo getPrincipal() { 43 | return this.loginInfo; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-gateway/src/main/java/org/rxjava/gateway/starter/config/CustomServerAuthenticationFailureHandler.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.gateway.starter.config; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | import org.springframework.security.web.server.WebFilterExchange; 5 | import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler; 6 | import org.springframework.web.server.ServerWebExchange; 7 | import org.springframework.web.server.WebFilterChain; 8 | import reactor.core.publisher.Mono; 9 | 10 | /** 11 | * @author happy 2019-06-29 16:31 12 | */ 13 | public class CustomServerAuthenticationFailureHandler implements ServerAuthenticationFailureHandler { 14 | 15 | /** 16 | * 鉴权失败,则不注入loginInfo,由微服务判断是否需要loginInfo 17 | */ 18 | @Override 19 | public Mono onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException e) { 20 | ServerWebExchange exchange = webFilterExchange.getExchange(); 21 | WebFilterChain chain = webFilterExchange.getChain(); 22 | return chain.filter(exchange); 23 | } 24 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-gateway/src/main/java/org/rxjava/gateway/starter/config/CustomServerAuthenticationSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.gateway.starter.config; 2 | 3 | import org.apache.commons.lang3.ObjectUtils; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.rxjava.common.core.entity.LoginInfo; 6 | import org.rxjava.common.core.utils.JsonUtils; 7 | import org.springframework.http.server.reactive.ServerHttpRequest; 8 | import org.springframework.security.core.Authentication; 9 | import org.springframework.security.web.server.WebFilterExchange; 10 | import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler; 11 | import org.springframework.web.server.ServerWebExchange; 12 | import org.springframework.web.server.WebFilterChain; 13 | import reactor.core.publisher.Mono; 14 | 15 | import java.io.UnsupportedEncodingException; 16 | import java.net.URLEncoder; 17 | 18 | /** 19 | * @author happy 2019-06-29 16:31 20 | */ 21 | public class CustomServerAuthenticationSuccessHandler implements ServerAuthenticationSuccessHandler { 22 | /** 23 | * 鉴权成功后,将loginInfo注入请求头中 24 | */ 25 | @Override 26 | public Mono onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) { 27 | ServerWebExchange exchange = webFilterExchange.getExchange(); 28 | WebFilterChain chain = webFilterExchange.getChain(); 29 | 30 | ServerHttpRequest request = exchange.getRequest(); 31 | AuthenticationToken authenticationToken = (AuthenticationToken) authentication; 32 | LoginInfo loginInfo = authenticationToken.getLoginInfo(); 33 | 34 | if (ObjectUtils.isEmpty(loginInfo)) { 35 | return chain.filter(exchange); 36 | } 37 | 38 | String loginInfoJson = null; 39 | try { 40 | loginInfoJson = URLEncoder.encode(JsonUtils.serialize(loginInfo), "utf8"); 41 | } catch (UnsupportedEncodingException e) { 42 | e.printStackTrace(); 43 | } 44 | 45 | if (StringUtils.isEmpty(loginInfoJson)) { 46 | return chain.filter(exchange); 47 | } 48 | 49 | ServerHttpRequest host = request 50 | .mutate() 51 | .header("loginInfo", loginInfoJson) 52 | .build(); 53 | ServerWebExchange build = exchange 54 | .mutate() 55 | .request(host) 56 | .build(); 57 | 58 | return chain.filter(build); 59 | } 60 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-cloud-starter-gateway/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.rxjava.gateway.starter.RxJavaGatewayAutoConfiguration -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-mock-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.rxjava 5 | rxjava-spring 6 | 1.0.9-SNAPSHOT 7 | 8 | 4.0.0 9 | rxjava-spring-mock-starter 10 | jar 11 | 12 | 13 | org.rxjava 14 | rxjava-spring-boot-core 15 | ${project.parent.version} 16 | 17 | 18 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-mock-starter/src/main/java/org/rxjava/mock/starter/RxJavaMockAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.mock.starter; 2 | 3 | import org.rxjava.common.core.entity.LoginInfo; 4 | import org.rxjava.common.core.utils.JsonUtils; 5 | import org.rxjava.mock.starter.config.MockProperties; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.core.annotation.Order; 10 | import org.springframework.http.server.reactive.ServerHttpRequest; 11 | import org.springframework.web.server.ServerWebExchange; 12 | import org.springframework.web.server.WebFilter; 13 | import org.springframework.web.server.WebFilterChain; 14 | import reactor.core.publisher.Mono; 15 | 16 | import java.io.UnsupportedEncodingException; 17 | import java.net.URLEncoder; 18 | import java.util.Objects; 19 | 20 | /** 21 | * @author happy 2019-07-03 11:37 22 | * Mock自动配置信息,此过滤器注入用户登陆信息 23 | */ 24 | @Configuration 25 | @EnableConfigurationProperties({MockProperties.class}) 26 | @Order(1) 27 | public class RxJavaMockAutoConfiguration implements WebFilter { 28 | 29 | private static final String LOGIN_INFO = "loginInfo"; 30 | 31 | @Autowired 32 | private MockProperties mockProperties; 33 | 34 | @Override 35 | public Mono filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) { 36 | LoginInfo loginInfo = new LoginInfo(); 37 | loginInfo.setUserId(mockProperties.getUserId()); 38 | 39 | String loginInfoJson = null; 40 | try { 41 | loginInfoJson = URLEncoder.encode(JsonUtils.serialize(loginInfo), "utf8"); 42 | } catch (UnsupportedEncodingException e) { 43 | e.printStackTrace(); 44 | } 45 | 46 | ServerHttpRequest request = serverWebExchange.getRequest(); 47 | ServerHttpRequest host = request 48 | .mutate() 49 | .header(LOGIN_INFO, Objects.requireNonNull(loginInfoJson)) 50 | .build(); 51 | ServerWebExchange build = serverWebExchange 52 | .mutate() 53 | .request(host) 54 | .build(); 55 | 56 | return webFilterChain.filter(build); 57 | } 58 | } -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-mock-starter/src/main/java/org/rxjava/mock/starter/config/MockProperties.java: -------------------------------------------------------------------------------- 1 | package org.rxjava.mock.starter.config; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | @ConfigurationProperties( 8 | prefix = "mock" 9 | ) 10 | @Getter 11 | @Setter 12 | public class MockProperties { 13 | private String userId; 14 | } 15 | -------------------------------------------------------------------------------- /rxjava-spring/rxjava-spring-mock-starter/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.rxjava.mock.starter.RxJavaMockAutoConfiguration --------------------------------------------------------------------------------