├── .gitignore ├── README.md ├── dis-commons ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── itxiaoer │ └── dis │ └── commons │ ├── Dis.java │ ├── DisResponse.java │ ├── annotation │ ├── Dis.java │ └── DisInclude.java │ ├── constnat │ └── ErrorCode.java │ ├── exception │ └── DisException.java │ └── logger │ └── DisLogger.java ├── dis-core ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── itxiaoer │ │ └── dis │ │ └── core │ │ ├── DisAutoConfiguration.java │ │ ├── aspect │ │ └── DisAspect.java │ │ ├── config │ │ └── DisProperties.java │ │ ├── util │ │ └── ReflectUtils.java │ │ └── validate │ │ └── DisValidate.java │ └── resources │ └── META-INF │ ├── spring-configuration-metadata.json │ └── spring.factories ├── dis-sample ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── itxiaoer │ │ │ └── sample │ │ │ ├── DisSampleApplication.java │ │ │ └── web │ │ │ ├── ExceptionAdvice.java │ │ │ ├── MyResponse.java │ │ │ ├── ParamsDto.java │ │ │ └── SampleController.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── itxiaoer │ └── sample │ ├── DisSampleApplicationTests.java │ └── DisStoreTests.java ├── dis-store ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── itxiaoer │ │ └── dis │ │ └── store │ │ ├── DisStore.java │ │ ├── DisStoreAutoConfiguration.java │ │ ├── DisStoreProperties.java │ │ ├── DisTemplate.java │ │ ├── config │ │ └── RedisConfig.java │ │ ├── constant │ │ └── DisStoreConstants.java │ │ ├── id │ │ ├── ID.java │ │ └── Md5ID.java │ │ └── redis │ │ ├── DisRedisAutoConfiguration.java │ │ └── RedisStore.java │ └── resources │ └── META-INF │ ├── scripts │ └── setnx.lua │ ├── spring-configuration-metadata.json │ └── spring.factories └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dis(Distributed Idempotence Structure) 2 | 3 | ## 项目介绍 4 | 基于Spring Boot + Redis幂等性框架 5 | 6 | 底层验证基于Lua脚本实现 7 | 8 | ## 执行流程 9 | 在编写中 10 | 11 | ## 如何使用 12 | 13 | ### 引入jar包 14 | 15 | ```xml 16 | 17 | com.itxiaoer.dis 18 | dis-core 19 | 1.0.0 20 | 21 | ``` 22 | 23 | ### 定义返回值类型(必须) 24 | 25 | - 因需要判断业务系统执行是否成功,通过DisResponse的方法isSuccess来判断。 26 | 27 | ```java 28 | package com.itxiaoer.dis.sample.web; 29 | 30 | import com.itxiaoer.dis.commons.Responsive; 31 | import lombok.Data; 32 | 33 | import java.util.Objects; 34 | 35 | /** 36 | * @author : liuyk 37 | */ 38 | @Data 39 | public class MyResponse implements Responsive{ 40 | 41 | private boolean success; 42 | 43 | @Override 44 | public boolean isSuccess() { 45 | return success; 46 | } 47 | 48 | } 49 | 50 | ``` 51 | 完整例子见dis-sample 52 | 53 | ### 编写请求 54 | 55 | - 简单参数 56 | ```java 57 | package com.itxiaoer.dis.sample.web; 58 | 59 | import com.itxiaoer.dis.commons.annotation.Dis; 60 | import com.itxiaoer.dis.commons.annotation.DisInclude; 61 | import org.springframework.web.bind.annotation.GetMapping; 62 | import org.springframework.web.bind.annotation.RestController; 63 | 64 | import java.util.Map; 65 | 66 | /** 67 | * @author : liuyk 68 | */ 69 | @RestController 70 | public class SampleController { 71 | 72 | @Dis(expireTime = 1000) 73 | @GetMapping("/sample") 74 | public MyResponse create1(@DisInclude String name, @DisInclude String id, @DisInclude Map params) { 75 | System.out.println("hello " + name); 76 | return MyResponse.success("hello !" + name); 77 | } 78 | } 79 | 80 | ``` 81 | - 自定义对象 82 | ```java 83 | package com.itxiaoer.dis.sample.web; 84 | 85 | import com.itxiaoer.dis.commons.Dis; 86 | import lombok.Data; 87 | 88 | /** 89 | * @author : liuyk 90 | */ 91 | @Data 92 | public class ParamsDto implements Dis { 93 | private String id; 94 | private String name; 95 | 96 | @Override 97 | public String dis() { 98 | return id + name; 99 | } 100 | } 101 | 102 | ``` 103 | 104 | ```java 105 | 106 | package com.itxiaoer.dis.sample.web; 107 | 108 | import com.itxiaoer.dis.commons.annotation.Dis; 109 | import com.itxiaoer.dis.commons.annotation.DisInclude; 110 | import org.springframework.web.bind.annotation.GetMapping; 111 | import org.springframework.web.bind.annotation.RestController; 112 | 113 | import java.util.Map; 114 | 115 | /** 116 | * @author : liuyk 117 | */ 118 | @RestController 119 | public class SampleController { 120 | 121 | @Dis(expireTime = 1000) 122 | @GetMapping("/sample1") 123 | public MyResponse create2(@DisInclude ParamsDto paramsDto, @DisInclude String age) { 124 | System.out.println("hello " + paramsDto.getName()); 125 | return MyResponse.success("hello !" + paramsDto.getName()); 126 | } 127 | } 128 | 129 | ``` 130 | 131 | ### 配置 application.yml 132 | 133 | ```yaml 134 | spring: 135 | redis: 136 | host: 127.0.0.1 137 | dis: 138 | store: 139 | type: redis 140 | active: true 141 | appId: dis-sample 142 | ``` 143 | 144 | ### 全局异常处理 145 | 有重复请求目前采用抛出异常方式,所以需要业务自己处理 146 | 147 | ```java 148 | package com.itxiaoer.dis.sample.web; 149 | 150 | import com.itxiaoer.dis.commons.exception.DisException; 151 | import lombok.extern.slf4j.Slf4j; 152 | import org.springframework.web.bind.annotation.ControllerAdvice; 153 | import org.springframework.web.bind.annotation.ExceptionHandler; 154 | import org.springframework.web.bind.annotation.ResponseBody; 155 | 156 | /** 157 | * @author : liuyk 158 | */ 159 | @Slf4j 160 | @ControllerAdvice 161 | public class ExceptionAdvice { 162 | 163 | 164 | @ResponseBody 165 | @ExceptionHandler({DisException.class}) 166 | public MyResponse handleDisException(DisException e) { 167 | return MyResponse.fail(e.getMessage()); 168 | } 169 | } 170 | 171 | ``` 172 | 173 | ## 参数说明 174 | 175 | - 启动参数 176 | 177 | |名称|值|说明| 178 | |----|----|---| 179 | |spring.dis.active|true|false|是否启用dis| 180 | |spring.dis.appId|应用唯一名称|在微服务架构下,防止请求参数相同| 181 | |spring.dis.store.type|使用存储的类型|redis,目前只支持redis| 182 | 183 | - 业务参数 184 | 185 | |名称|值|说明| 186 | |----|----|---| 187 | |expireTime|执行业务方法的有效时间|再请求参数一致情况下,该方法多长时间不可重复| 188 | 189 | ## 注解说明 190 | 191 | - @Dis 192 | 标注该方法是否要求幂等 193 | - @DisInclude 194 | 标注该参数为幂等内容的一部份 195 | 196 | ## 接口 197 | - Dis 198 | 实现Dis接口,并重写dis方法,该方法提供该操作唯一性的内容特性 199 | 200 | ## License 201 | The project is licensed under the Apache 2 license 202 | 203 | -------------------------------------------------------------------------------- /dis-commons/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dis 5 | com.itxiaoer.dis 6 | 1.0.6-SNAPSHOT 7 | 8 | 4.0.0 9 | 10 | dis-commons 11 | 12 | 13 | 14 | com.itxiaoer.commons 15 | commons-core 16 | 17 | 18 | -------------------------------------------------------------------------------- /dis-commons/src/main/java/com/itxiaoer/dis/commons/Dis.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.commons; 2 | 3 | /** 4 | * dis content 5 | * 6 | * @author : liuyk 7 | */ 8 | public interface Dis { 9 | /** 10 | * 获取唯一内容标识 11 | * 12 | * @return 唯一内容标识 13 | */ 14 | String dis(); 15 | } 16 | -------------------------------------------------------------------------------- /dis-commons/src/main/java/com/itxiaoer/dis/commons/DisResponse.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.commons; 2 | 3 | import com.itxiaoer.commons.core.page.Responsive; 4 | 5 | /** 6 | * dis response 7 | * 8 | * see com.itxiaoer.commons.page.Responsive 9 | * @author : liuyk 10 | */ 11 | @Deprecated 12 | @SuppressWarnings("unused") 13 | public interface DisResponse extends Responsive { 14 | } 15 | -------------------------------------------------------------------------------- /dis-commons/src/main/java/com/itxiaoer/dis/commons/annotation/Dis.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.commons.annotation; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * @author : liuyk 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.METHOD) 14 | public @interface Dis { 15 | /** 16 | * How long does it take to submit 17 | */ 18 | long expireTime(); 19 | } 20 | -------------------------------------------------------------------------------- /dis-commons/src/main/java/com/itxiaoer/dis/commons/annotation/DisInclude.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.commons.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : liuyk 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 13 | public @interface DisInclude { 14 | } 15 | -------------------------------------------------------------------------------- /dis-commons/src/main/java/com/itxiaoer/dis/commons/constnat/ErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.commons.constnat; 2 | 3 | /** 4 | * error code 5 | * 6 | * @author : liuyk 7 | */ 8 | @SuppressWarnings("unused") 9 | public final class ErrorCode { 10 | private ErrorCode() { 11 | } 12 | 13 | /** 14 | * store timeout error 15 | */ 16 | public static final String CODE_OF_TIME_OUT = "4001"; 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /dis-commons/src/main/java/com/itxiaoer/dis/commons/exception/DisException.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.commons.exception; 2 | 3 | /** 4 | * @author : liuyk 5 | */ 6 | @SuppressWarnings("unused") 7 | public class DisException extends RuntimeException { 8 | 9 | 10 | public DisException(String message) { 11 | super(message); 12 | } 13 | 14 | public DisException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | 18 | public DisException(Throwable cause) { 19 | super(cause); 20 | } 21 | 22 | protected DisException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 23 | super(message, cause, enableSuppression, writableStackTrace); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dis-commons/src/main/java/com/itxiaoer/dis/commons/logger/DisLogger.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.commons.logger; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | /** 11 | * @author : liuyk 12 | */ 13 | @Component 14 | @SuppressWarnings("unused") 15 | public class DisLogger { 16 | private static final Map, Logger> LOGGER_MAP = new ConcurrentHashMap<>(); 17 | 18 | 19 | private Logger get(Class clazz) { 20 | Logger logger = LOGGER_MAP.get(clazz); 21 | if (logger == null) { 22 | logger = LoggerFactory.getLogger(clazz); 23 | LOGGER_MAP.put(clazz, LoggerFactory.getLogger(clazz)); 24 | } 25 | return logger; 26 | } 27 | 28 | public void debug(Class clazz, String message, Object... args) { 29 | Logger logger = this.get(clazz); 30 | if (logger.isDebugEnabled()) { 31 | logger.debug(message, args); 32 | } 33 | } 34 | 35 | public void info(Class clazz, String message, Object... args) { 36 | this.get(clazz).info(message, args); 37 | } 38 | 39 | public void error(Class clazz, String message, Throwable e, Object... args) { 40 | this.get(clazz).error(message, e, args); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /dis-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dis 5 | com.itxiaoer.dis 6 | 1.0.6-SNAPSHOT 7 | 8 | 4.0.0 9 | dis-core 10 | 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-aop 15 | 16 | 17 | 18 | 19 | com.itxiaoer.dis 20 | dis-commons 21 | 22 | 23 | com.itxiaoer.dis 24 | dis-store 25 | 26 | 27 | 28 | org.jooq 29 | joor-java-8 30 | 0.9.7 31 | 32 | 33 | 34 | org.apache.commons 35 | commons-lang3 36 | 37 | 38 | 39 | org.projectlombok 40 | lombok 41 | true 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /dis-core/src/main/java/com/itxiaoer/dis/core/DisAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.core; 2 | 3 | import com.itxiaoer.dis.core.config.DisProperties; 4 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 5 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | /** 10 | * @author : liuyk 11 | */ 12 | @Configuration 13 | @ComponentScan("com.itxiaoer.dis") 14 | @EnableConfigurationProperties(DisProperties.class) 15 | @ConditionalOnProperty(value = "spring.dis.active", havingValue = "true") 16 | public class DisAutoConfiguration { 17 | } 18 | -------------------------------------------------------------------------------- /dis-core/src/main/java/com/itxiaoer/dis/core/aspect/DisAspect.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.core.aspect; 2 | 3 | import com.itxiaoer.commons.core.page.Responsive; 4 | import com.itxiaoer.dis.commons.annotation.Dis; 5 | import com.itxiaoer.dis.commons.exception.DisException; 6 | import com.itxiaoer.dis.commons.logger.DisLogger; 7 | import com.itxiaoer.dis.core.config.DisProperties; 8 | import com.itxiaoer.dis.core.util.ReflectUtils; 9 | import com.itxiaoer.dis.store.DisTemplate; 10 | import com.itxiaoer.dis.store.id.Md5ID; 11 | import org.aspectj.lang.ProceedingJoinPoint; 12 | import org.aspectj.lang.annotation.Around; 13 | import org.aspectj.lang.annotation.Aspect; 14 | import org.aspectj.lang.annotation.Pointcut; 15 | import org.aspectj.lang.reflect.MethodSignature; 16 | import org.springframework.stereotype.Component; 17 | import org.springframework.util.StringUtils; 18 | 19 | import javax.annotation.Resource; 20 | 21 | /** 22 | * @author : liuyk 23 | */ 24 | @Aspect 25 | @Component 26 | public class DisAspect { 27 | 28 | @Resource 29 | private DisProperties disProperties; 30 | 31 | @Resource 32 | private DisTemplate disTemplate; 33 | 34 | 35 | @Resource 36 | private DisLogger disLogger; 37 | 38 | @Pointcut("@annotation(com.itxiaoer.dis.commons.annotation.Dis)") 39 | private void dis() { 40 | } 41 | 42 | @Around("dis()") 43 | public Object around(ProceedingJoinPoint joinPoint) { 44 | MethodSignature signature = (MethodSignature) joinPoint.getSignature(); 45 | Dis dis = signature.getMethod().getAnnotation(Dis.class); 46 | String content = ReflectUtils.find(joinPoint); 47 | String id = new Md5ID(disProperties.getAppId(), content).id(); 48 | disLogger.debug(DisAspect.class, " dis begin [id = {} , content = {} ] ", id, content); 49 | // 区分是存在,还是出现异常 50 | Boolean success = this.disTemplate.setNx(id, content, dis.expireTime()); 51 | disLogger.debug(DisAspect.class, " dis store [id = {} , content = {},success = {} ] ", id, content, success); 52 | // not delete id 53 | if (!success) { 54 | // false 55 | // id exists? not delete 56 | String value = this.disTemplate.get(id); 57 | if (!StringUtils.isEmpty(value)) { 58 | throw new DisException("the same request is already being processed"); 59 | } 60 | // false store error 61 | this.disTemplate.delete(id); 62 | throw new DisException("store is not working "); 63 | } 64 | try { 65 | 66 | Object proceed; 67 | try { 68 | proceed = joinPoint.proceed(); 69 | } catch (Throwable throwable) { 70 | disLogger.error(DisAspect.class, throwable.getMessage(), throwable); 71 | throw new DisException(throwable); 72 | } 73 | 74 | if (!(proceed instanceof Responsive)) { 75 | throw new DisException(signature.getClass().getName() + "#" + signature.getMethod().getName() + " return response must be implements Responsive. "); 76 | } 77 | // 此处服务器断电如何处理?单位时间请求无法处理? TODO 78 | Responsive response = (Responsive) proceed; 79 | // success 80 | if (response.isSuccess()) { 81 | // 判断结果, 82 | return proceed; 83 | } 84 | this.disTemplate.delete(id); 85 | // fail 86 | return proceed; 87 | } catch (Exception e) { 88 | this.disTemplate.delete(id); 89 | throw e; 90 | } 91 | 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /dis-core/src/main/java/com/itxiaoer/dis/core/config/DisProperties.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.core.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * dis properties 8 | * 9 | * @author : liuyk 10 | */ 11 | @Data 12 | @ConfigurationProperties(prefix = "spring.dis") 13 | public class DisProperties { 14 | /** 15 | * active 16 | */ 17 | private boolean active; 18 | /** 19 | * appId 20 | */ 21 | private String appId; 22 | } 23 | -------------------------------------------------------------------------------- /dis-core/src/main/java/com/itxiaoer/dis/core/util/ReflectUtils.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.core.util; 2 | 3 | import com.itxiaoer.dis.commons.Dis; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.aspectj.lang.JoinPoint; 6 | import org.aspectj.lang.reflect.MethodSignature; 7 | 8 | import java.lang.annotation.Annotation; 9 | import java.lang.reflect.InvocationTargetException; 10 | import java.util.Collection; 11 | import java.util.Map; 12 | import java.util.Objects; 13 | 14 | /** 15 | * @author : liuyk 16 | */ 17 | @Slf4j 18 | @SuppressWarnings("all") 19 | public final class ReflectUtils { 20 | 21 | public static String find(JoinPoint joinPoint) { 22 | MethodSignature signature = (MethodSignature) joinPoint.getSignature(); 23 | String methodName = signature.getMethod().getName(); 24 | Class[] parameterTypes = signature.getMethod().getParameterTypes(); 25 | Object[] args = joinPoint.getArgs(); 26 | StringBuilder sb = new StringBuilder(); 27 | try { 28 | Annotation[][] annotations = joinPoint.getTarget().getClass().getMethod(methodName, parameterTypes).getParameterAnnotations(); 29 | for (int i = 0; i < annotations.length; i++) { 30 | Annotation[] annotation = annotations[i]; 31 | for (Annotation annotation1 : annotation) { 32 | sb.append(parse(args[i])); 33 | } 34 | } 35 | return sb.toString(); 36 | } catch (NoSuchMethodException e) { 37 | e.printStackTrace(); 38 | return ""; 39 | } 40 | } 41 | 42 | 43 | public static String parse(Object obj) { 44 | if (Objects.isNull(obj)) { 45 | return ""; 46 | } 47 | 48 | // implements Dis 49 | if (obj instanceof Dis) { 50 | Dis dis = (Dis) obj; 51 | return dis.dis(); 52 | } 53 | 54 | // is collection 55 | if (obj instanceof Collection) { 56 | Collection collection = (Collection) obj; 57 | return collection.isEmpty() ? "" : collection.toString(); 58 | } 59 | 60 | // is map 61 | if (obj instanceof Map) { 62 | Map map = (Map) obj; 63 | return map.isEmpty() ? "" : map.toString(); 64 | } 65 | return obj.toString(); 66 | } 67 | 68 | 69 | public static boolean invoke(String clazzName, String method, Object object) { 70 | try { 71 | return invoke(Class.forName(clazzName), method, object); 72 | } catch (ClassNotFoundException e) { 73 | e.printStackTrace(); 74 | return false; 75 | } 76 | } 77 | 78 | 79 | public static boolean invoke(Class clazz, String method, Object object) { 80 | try { 81 | return (Boolean) clazz.getMethod(method).invoke(object); 82 | } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { 83 | log.error(e.getMessage(), e); 84 | return false; 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /dis-core/src/main/java/com/itxiaoer/dis/core/validate/DisValidate.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.core.validate; 2 | 3 | import com.itxiaoer.dis.core.config.DisProperties; 4 | import org.springframework.boot.CommandLineRunner; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.util.Assert; 7 | 8 | import javax.annotation.Resource; 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * @author : liuyk 13 | */ 14 | @Component 15 | @SuppressWarnings("all") 16 | public class DisValidate implements CommandLineRunner { 17 | 18 | @Resource 19 | private DisProperties disProperties; 20 | 21 | @Override 22 | public void run(String... args) throws Exception { 23 | this.validate(); 24 | } 25 | 26 | 27 | public void validate() { 28 | 29 | Assert.hasText(disProperties.getAppId(), "appId argument must have text; it must not be null, empty, or blank"); 30 | } 31 | 32 | 33 | public void validate(String response, String state) { 34 | try { 35 | Class clazz = Class.forName(response); 36 | // method 37 | Method method = clazz.getMethod(state); 38 | } catch (Exception e) { 39 | throw new IllegalArgumentException("class " + response + " not found. or method " + state + " not found. "); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /dis-core/src/main/resources/META-INF/spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "hints": [ 3 | { 4 | "name": "spring.dis.active", 5 | "values": [ 6 | { 7 | "value": true 8 | }, 9 | { 10 | "value": false 11 | } 12 | ] 13 | }, 14 | { 15 | "name": "spring.dis.appId" 16 | } 17 | ], 18 | "groups": [ 19 | { 20 | "sourceType": "com.itxiaoer.dis.core.config.DisProperties", 21 | "name": "DisProperties", 22 | "type": "com.itxiaoer.dis.core.config.DisProperties" 23 | } 24 | ], 25 | "properties": [ 26 | { 27 | "sourceType": "com.itxiaoer.dis.core.config.DisProperties", 28 | "name": "spring.dis.active", 29 | "type": "java.lang.Boolean" 30 | }, 31 | { 32 | "sourceType": "com.itxiaoer.dis.core.config.DisProperties", 33 | "name": "spring.dis.appId", 34 | "type": "java.lang.String" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /dis-core/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | com.itxiaoer.dis.core.DisAutoConfiguration -------------------------------------------------------------------------------- /dis-sample/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /dis-sample/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | dis-sample 6 | jar 7 | 8 | dis-sample 9 | Demo project for Spring Boot 10 | 11 | 12 | dis 13 | com.itxiaoer.dis 14 | 1.0.6-SNAPSHOT 15 | 16 | 17 | 18 | UTF-8 19 | UTF-8 20 | 1.8 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | org.hibernate.validator 30 | hibernate-validator 31 | 32 | 33 | 34 | 35 | 36 | com.itxiaoer.dis 37 | dis-core 38 | 39 | 40 | 41 | com.itxiaoer.commons 42 | commons-core 43 | 44 | 45 | 46 | org.projectlombok 47 | lombok 48 | true 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-test 53 | test 54 | 55 | 56 | 57 | 58 | 59 | 60 | org.springframework.boot 61 | spring-boot-maven-plugin 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /dis-sample/src/main/java/com/itxiaoer/sample/DisSampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.sample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author : liuyk 8 | */ 9 | @SpringBootApplication 10 | public class DisSampleApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(DisSampleApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /dis-sample/src/main/java/com/itxiaoer/sample/web/ExceptionAdvice.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.sample.web; 2 | 3 | import com.itxiaoer.dis.commons.exception.DisException; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.web.bind.annotation.ControllerAdvice; 6 | import org.springframework.web.bind.annotation.ExceptionHandler; 7 | import org.springframework.web.bind.annotation.ResponseBody; 8 | 9 | /** 10 | * @author : liuyk 11 | */ 12 | @Slf4j 13 | @ControllerAdvice 14 | public class ExceptionAdvice { 15 | 16 | 17 | @ResponseBody 18 | @ExceptionHandler({DisException.class}) 19 | public MyResponse handleDisException(DisException e) { 20 | return MyResponse.fail(e.getMessage()); 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /dis-sample/src/main/java/com/itxiaoer/sample/web/MyResponse.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.sample.web; 2 | 3 | import com.itxiaoer.commons.core.page.Responsive; 4 | import lombok.Data; 5 | 6 | import java.util.Objects; 7 | 8 | /** 9 | * @author : liuyk 10 | */ 11 | @Data 12 | @SuppressWarnings("all") 13 | public class MyResponse implements Responsive { 14 | 15 | /** 16 | * code 17 | */ 18 | private String code; 19 | /** 20 | * message 21 | */ 22 | private String msg; 23 | 24 | 25 | private T data; 26 | 27 | private boolean success; 28 | 29 | @Override 30 | public boolean isSuccess() { 31 | return success; 32 | } 33 | 34 | /** 35 | * private 36 | */ 37 | private MyResponse() { 38 | } 39 | 40 | /** 41 | * private 42 | */ 43 | private MyResponse(T data) { 44 | this.success = true; 45 | this.data = data; 46 | } 47 | 48 | 49 | private MyResponse(boolean success, String msg) { 50 | this(success, msg, "0"); 51 | } 52 | 53 | private MyResponse(boolean success, String msg, String code) { 54 | this.msg = msg; 55 | this.success = success; 56 | this.code = code; 57 | } 58 | 59 | 60 | public static MyResponse success() { 61 | return new MyResponse<>(null); 62 | } 63 | 64 | public static MyResponse success(E data) { 65 | return new MyResponse<>(data); 66 | } 67 | 68 | 69 | public static MyResponse fail(String msg) { 70 | return new MyResponse<>(false, msg); 71 | } 72 | 73 | 74 | public static MyResponse fail(String msg, String code) { 75 | return new MyResponse<>(false, msg); 76 | } 77 | 78 | public static MyResponse build(Boolean success) { 79 | if (Objects.equals(success, Boolean.TRUE)) { 80 | return new MyResponse<>(Boolean.TRUE); 81 | } 82 | return new MyResponse<>(false, ""); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /dis-sample/src/main/java/com/itxiaoer/sample/web/ParamsDto.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.sample.web; 2 | 3 | import com.itxiaoer.dis.commons.Dis; 4 | import lombok.Data; 5 | 6 | /** 7 | * @author : liuyk 8 | */ 9 | @Data 10 | public class ParamsDto implements Dis { 11 | private String id; 12 | private String name; 13 | 14 | @Override 15 | public String dis() { 16 | return id + name; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dis-sample/src/main/java/com/itxiaoer/sample/web/SampleController.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.sample.web; 2 | 3 | import com.itxiaoer.dis.commons.annotation.Dis; 4 | import com.itxiaoer.dis.commons.annotation.DisInclude; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * @author : liuyk 12 | */ 13 | @RestController 14 | public class SampleController { 15 | 16 | @Dis(expireTime = 1000) 17 | @GetMapping("/sample") 18 | public MyResponse create1(@DisInclude String name, @DisInclude String id, @DisInclude Map params) { 19 | System.out.println("hello " + name); 20 | return MyResponse.success("hello !" + name); 21 | } 22 | 23 | 24 | @Dis(expireTime = 1000) 25 | @GetMapping("/sample1") 26 | public MyResponse create2(@DisInclude ParamsDto paramsDto, @DisInclude String age) { 27 | System.out.println("hello " + paramsDto.getName()); 28 | return MyResponse.success("hello !" + paramsDto.getName()); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /dis-sample/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | redis: 3 | host: 127.0.0.1 4 | dis: 5 | store: 6 | # type: redis 7 | active: true 8 | appId: dis-sample 9 | logging: 10 | level: 11 | org.springframework: info 12 | -------------------------------------------------------------------------------- /dis-sample/src/test/java/com/itxiaoer/sample/DisSampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.sample; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DisSampleApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /dis-sample/src/test/java/com/itxiaoer/sample/DisStoreTests.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.sample; 2 | 3 | import com.itxiaoer.dis.store.DisStore; 4 | import org.junit.Test; 5 | 6 | import javax.annotation.Resource; 7 | 8 | public class DisStoreTests extends DisSampleApplicationTests { 9 | @Resource 10 | private DisStore disStore; 11 | 12 | @Test 13 | public void set() { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dis-store/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dis 5 | com.itxiaoer.dis 6 | 1.0.6-SNAPSHOT 7 | 8 | 4.0.0 9 | 10 | dis-store 11 | 12 | 13 | 14 | org.springframework 15 | spring-context 16 | 17 | 18 | 19 | com.itxiaoer.commons 20 | commons-redis 21 | 22 | 23 | 24 | com.itxiaoer.dis 25 | dis-commons 26 | 27 | 28 | 29 | org.projectlombok 30 | lombok 31 | true 32 | 33 | 34 | -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/DisStore.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store; 2 | 3 | /** 4 | * dis store 5 | * 6 | * @author : liuyk 7 | */ 8 | public interface DisStore { 9 | /** 10 | * set key and value 11 | * 12 | * @param key key 13 | * @param value value 14 | * @param expireTime expireTime unit: seconds 15 | * @return true or false 16 | */ 17 | Boolean setNx(String key, String value, long expireTime); 18 | 19 | /** 20 | * delete key 21 | * 22 | * @param key key 23 | * @return true or false 24 | */ 25 | Boolean delete(String key); 26 | 27 | /** 28 | * get key 29 | * 30 | * @param key key 31 | * @return value 32 | */ 33 | String get(String key); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/DisStoreAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store; 2 | 3 | import com.itxiaoer.dis.store.redis.DisRedisAutoConfiguration; 4 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 5 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.Import; 9 | 10 | /** 11 | * @author : liuyk 12 | */ 13 | @ComponentScan 14 | @Configuration 15 | @Import(DisRedisAutoConfiguration.class) 16 | @EnableConfigurationProperties(DisStoreProperties.class) 17 | @ConditionalOnProperty(value = "spring.dis.active", havingValue = "true") 18 | public class DisStoreAutoConfiguration { 19 | } -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/DisStoreProperties.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store; 2 | 3 | import lombok.Data; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | /** 8 | * dis store config 9 | * 10 | * @author : liuyk 11 | */ 12 | @Data 13 | @ConfigurationProperties(prefix = "spring.dis.store") 14 | public class DisStoreProperties { 15 | @Value("${spring.dis.store.type:redis}") 16 | private String type; 17 | } 18 | -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/DisTemplate.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import javax.annotation.Resource; 6 | 7 | /** 8 | * @author : liuyk 9 | */ 10 | 11 | @Component 12 | @SuppressWarnings("unused") 13 | public class DisTemplate { 14 | 15 | @Resource 16 | private DisStore disStore; 17 | 18 | public Boolean setNx(String id, String content, long expireTime) { 19 | return this.disStore.setNx(id, content, expireTime); 20 | } 21 | 22 | 23 | public Boolean delete(String key) { 24 | return this.disStore.delete(key); 25 | } 26 | 27 | public String get(String key) { 28 | return this.disStore.get(key); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.data.redis.connection.RedisConnectionFactory; 7 | import org.springframework.data.redis.core.RedisTemplate; 8 | import org.springframework.data.redis.serializer.StringRedisSerializer; 9 | 10 | @Configuration 11 | public class RedisConfig { 12 | 13 | 14 | @Bean 15 | public RedisTemplate disRedisTemplate(@Autowired RedisConnectionFactory redisConnectionFactory) { 16 | RedisTemplate disRedisTemplate = new RedisTemplate<>(); 17 | disRedisTemplate.setConnectionFactory(redisConnectionFactory); 18 | disRedisTemplate.setDefaultSerializer(new StringRedisSerializer()); 19 | disRedisTemplate.setValueSerializer(new StringRedisSerializer()); 20 | disRedisTemplate.setKeySerializer(new StringRedisSerializer()); 21 | disRedisTemplate.afterPropertiesSet(); 22 | return disRedisTemplate; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/constant/DisStoreConstants.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store.constant; 2 | 3 | /** 4 | * @author : liuyk 5 | */ 6 | public final class DisStoreConstants { 7 | private DisStoreConstants() { 8 | } 9 | 10 | /*** 11 | * 12 | * redis store type 13 | * 14 | */ 15 | public static final String STORE_TYPE_REDIS = "redis"; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/id/ID.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store.id; 2 | 3 | /** 4 | * @author : liuyk 5 | */ 6 | public interface ID { 7 | /** 8 | * 生成id 9 | * 10 | * @return id 11 | */ 12 | String id(); 13 | } 14 | -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/id/Md5ID.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store.id; 2 | 3 | import com.itxiaoer.dis.commons.exception.DisException; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.springframework.util.DigestUtils; 8 | import org.springframework.util.StringUtils; 9 | 10 | import java.nio.charset.Charset; 11 | 12 | /** 13 | * @author : liuyk 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class Md5ID implements ID { 19 | 20 | private String appKey; 21 | 22 | private String content; 23 | 24 | @Override 25 | public String id() { 26 | if (StringUtils.isEmpty(appKey)) { 27 | throw new DisException("this appKey argument must have length; it must not be null or empty"); 28 | } 29 | 30 | if (StringUtils.isEmpty(content)) { 31 | throw new DisException("this content argument must have length; it must not be null or empty"); 32 | } 33 | 34 | return DigestUtils.md5DigestAsHex((appKey + content).getBytes(Charset.defaultCharset())); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/redis/DisRedisAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store.redis; 2 | 3 | import com.itxiaoer.dis.store.DisStore; 4 | import com.itxiaoer.dis.store.constant.DisStoreConstants; 5 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.core.io.ClassPathResource; 9 | import org.springframework.data.redis.core.script.RedisScript; 10 | import org.springframework.scripting.ScriptSource; 11 | import org.springframework.scripting.support.ResourceScriptSource; 12 | 13 | import java.io.IOException; 14 | 15 | /** 16 | * dis redis auto configuration 17 | * 18 | * @author : liuyk 19 | */ 20 | @Configuration 21 | @ConditionalOnProperty(name = "spring.dis.store.type", havingValue = DisStoreConstants.STORE_TYPE_REDIS, matchIfMissing = true) 22 | public class DisRedisAutoConfiguration { 23 | 24 | @Bean 25 | public DisStore disRemoteStore() { 26 | return new RedisStore(); 27 | } 28 | 29 | @Bean 30 | public RedisScript nxScript() throws IOException { 31 | ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource("META-INF/scripts/setnx.lua")); 32 | return RedisScript.of(scriptSource.getScriptAsString(), Boolean.class); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dis-store/src/main/java/com/itxiaoer/dis/store/redis/RedisStore.java: -------------------------------------------------------------------------------- 1 | package com.itxiaoer.dis.store.redis; 2 | 3 | import com.itxiaoer.dis.store.DisStore; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.data.redis.core.RedisTemplate; 6 | import org.springframework.data.redis.core.ValueOperations; 7 | import org.springframework.data.redis.core.script.DefaultRedisScript; 8 | import org.springframework.data.redis.core.script.RedisScript; 9 | import org.springframework.data.redis.serializer.StringRedisSerializer; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.ArrayList; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | 16 | /** 17 | * @author : liuyk 18 | */ 19 | public class RedisStore implements DisStore { 20 | 21 | @Resource 22 | private ValueOperations valueOperations; 23 | 24 | @Resource(name = "disRedisTemplate") 25 | private RedisTemplate disRedisTemplate; 26 | 27 | @Autowired 28 | private RedisScript nxScript; 29 | 30 | @Override 31 | public Boolean setNx(String key, String value, long expireTime) { 32 | Object execute = disRedisTemplate.execute(nxScript,Arrays.asList(key),value,String.valueOf(expireTime)); 33 | return (Boolean) execute; 34 | } 35 | 36 | @Override 37 | public Boolean delete(String key) { 38 | return this.disRedisTemplate.delete(key); 39 | } 40 | 41 | @Override 42 | public String get(String key) { 43 | return this.disRedisTemplate.opsForValue().get(key); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /dis-store/src/main/resources/META-INF/scripts/setnx.lua: -------------------------------------------------------------------------------- 1 | local current = redis.call('GET', KEYS[1]) 2 | if current then 3 | return false 4 | else 5 | redis.call('SET', KEYS[1], ARGV[1]) 6 | redis.call('EXPIRE', KEYS[1], ARGV[2]) 7 | return true 8 | end -------------------------------------------------------------------------------- /dis-store/src/main/resources/META-INF/spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "hints": [ 3 | { 4 | "name": "spring.dis.store.type", 5 | "values": [ 6 | { 7 | "value": "redis" 8 | }, 9 | { 10 | "value": "local" 11 | } 12 | ] 13 | } 14 | ], 15 | "groups": [ 16 | { 17 | "sourceType": "com.itxiaoer.dis.store.DisStoreProperties", 18 | "name": "DisStoreProperties", 19 | "type": "com.itxiaoer.dis.store.DisStoreProperties" 20 | } 21 | ], 22 | "properties": [ 23 | { 24 | "sourceType": "com.itxiaoer.dis.store.DisStoreProperties", 25 | "name": "spring.dis.store.type", 26 | "type": "java.lang.String" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /dis-store/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | com.itxiaoer.dis.store.DisStoreAutoConfiguration 3 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.itxiaoer.dis 6 | dis 7 | 1.0.6-SNAPSHOT 8 | pom 9 | 10 | dis 11 | Demo project for Spring Boot 12 | 13 | 14 | 15 | dis-commons 16 | dis-core 17 | dis-store 18 | dis-sample 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 2.1.9 25 | 1.0.6-SNAPSHOT 26 | 1.8 27 | 28 | 29 | 30 | 31 | oss 32 | https://oss.sonatype.org/content/groups/public/ 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-dependencies 41 | 2.0.4.RELEASE 42 | pom 43 | import 44 | 45 | 46 | 47 | com.itxiaoer.commons 48 | commons-redis 49 | ${itxiaoer.commons.version} 50 | 51 | 52 | 53 | com.itxiaoer.commons 54 | commons-core 55 | ${itxiaoer.commons.version} 56 | 57 | 58 | 59 | 60 | com.itxiaoer.dis 61 | dis-commons 62 | ${itxiaoer.dis.version} 63 | 64 | 65 | 66 | com.itxiaoer.dis 67 | dis-core 68 | ${itxiaoer.dis.version} 69 | 70 | 71 | 72 | com.itxiaoer.dis 73 | dis-store 74 | ${itxiaoer.dis.version} 75 | 76 | 77 | 78 | org.apache.commons 79 | commons-lang3 80 | 3.8 81 | 82 | 83 | 84 | 85 | 86 | 87 | org.springframework.boot 88 | spring-boot-autoconfigure 89 | 90 | 91 | 92 | http://blog.itxiaoer.com 93 | 94 | 95 | 96 | The Apache Software License, Version 2.0 97 | http://www.apache.org/licenses/LICENSE-2.0.txt 98 | 99 | 100 | 101 | 102 | 103 | 104 | liuyukuai 105 | 271007729@qq.com 106 | 107 | 108 | 109 | 110 | scm:git:https://github.com/liuyukuai/dis.git 111 | 112 | 113 | scm:git:https://github.com/liuyukuai/dis.git 114 | 115 | https://github.com/liuyukuai/dis 116 | HEAD 117 | 118 | 119 | 120 | 121 | oss 122 | https://oss.sonatype.org/content/repositories/snapshots/ 123 | 124 | 125 | oss 126 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 127 | 128 | 129 | 130 | 131 | 132 | 133 | org.sonatype.plugins 134 | nexus-staging-maven-plugin 135 | 1.6.7 136 | true 137 | 138 | oss 139 | https://oss.sonatype.org/ 140 | true 141 | 142 | 143 | 144 | 145 | org.apache.maven.plugins 146 | maven-source-plugin 147 | 2.2.1 148 | 149 | 150 | attach-sources 151 | 152 | jar-no-fork 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | org.apache.maven.plugins 161 | maven-javadoc-plugin 162 | 3.2.0 163 | 164 | 165 | attach-javadocs 166 | 167 | jar 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | org.apache.maven.plugins 176 | maven-gpg-plugin 177 | 1.5 178 | 179 | 180 | sign-artifacts 181 | verify 182 | 183 | sign 184 | 185 | 186 | 187 | 188 | 189 | 190 | org.apache.maven.plugins 191 | maven-release-plugin 192 | 2.5.3 193 | 194 | 195 | v@{project.version} 196 | true 197 | deploy 198 | 199 | 200 | 201 | 202 | org.apache.maven.plugins 203 | maven-compiler-plugin 204 | 3.8.0 205 | 206 | 1.8 207 | 1.8 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | --------------------------------------------------------------------------------