diff --git a/distributed-demos/distribuited-lock-demos/pom.xml b/distributed-demos/distribuited-lock-demos/pom.xml
index 4ebba5f057e55d20f340730149437fcd7fbc8dee..6a262a8479a6f9b514eb050fdf43d937ea989cf9 100644
--- a/distributed-demos/distribuited-lock-demos/pom.xml
+++ b/distributed-demos/distribuited-lock-demos/pom.xml
@@ -13,6 +13,7 @@
pom
redis-lock-demo
+ redisson-sample
diff --git a/distributed-demos/distribuited-lock-demos/redisson-sample/pom.xml b/distributed-demos/distribuited-lock-demos/redisson-sample/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..12b30a3e3ec4b2aced4759ab880ff018c9163915
--- /dev/null
+++ b/distributed-demos/distribuited-lock-demos/redisson-sample/pom.xml
@@ -0,0 +1,35 @@
+
+
+
+ distribuited-lock-demos
+ com.gsean.demos
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ redisson-sample
+
+
+ 8
+ 8
+
+
+
+
+ org.redisson
+ redisson
+ 3.15.6
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ com.alibaba
+ fastjson
+
+
+
+
\ No newline at end of file
diff --git a/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/RedissonSampleApp.java b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/RedissonSampleApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..052d662221eee4e849eb4618f92e2a33877531ec
--- /dev/null
+++ b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/RedissonSampleApp.java
@@ -0,0 +1,19 @@
+package com.gsean.redisson;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/15 16:50
+ * @modificed by
+ **/
+@SpringBootApplication
+public class RedissonSampleApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(RedissonSampleApp.class,args);
+ }
+
+}
diff --git a/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/config/RedisConfig.java b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/config/RedisConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..8631a1502d596d0b132b73e1b98fadf1a4a53707
--- /dev/null
+++ b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/config/RedisConfig.java
@@ -0,0 +1,45 @@
+package com.gsean.redisson.config;
+
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.redisson.config.SingleServerConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/15 17:46
+ * @modificed by
+ **/
+@Configuration
+public class RedisConfig {
+
+ @Autowired
+ private Environment env;
+
+ /**
+ * 自定义注入配置操作Redisson的客户端实例
+ * @return
+ */
+ @Bean
+ public RedissonClient config(){
+ //创建配置实例
+ Config config=new Config();
+ //可以设置传输模式为EPOLL,也可以设置为NIO等等
+ //config.setTransportMode(TransportMode.NIO);
+ //设置服务节点部署模式:集群模式;单一节点模式;主从模式;哨兵模式等等
+ //config.useClusterServers().addNodeAddress(env.getProperty("redisson.host.config"),env.getProperty("redisson.host.config"));
+ config
+ .useSingleServer()
+ .setAddress(env.getProperty("redisson.host.config"))
+ .setPassword(env.getProperty("spring.redis.password"))
+ .setKeepAlive(true);
+ //创建并返回操作Redisson的客户端实例
+ return Redisson.create(config);
+ }
+
+}
diff --git a/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/service/UserService.java b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/service/UserService.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc3b4b7393cc7d105b31a48056a4ff53bda7d315
--- /dev/null
+++ b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/service/UserService.java
@@ -0,0 +1,15 @@
+package com.gsean.redisson.service;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/15 18:33
+ * @modificed by
+ **/
+public interface UserService {
+
+
+
+ Long addUserAndGet();
+
+}
diff --git a/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/utils/LockUtil.java b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/utils/LockUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..af5e5f40bbef985d3ff0fd7ff39a1fbc4e733bf6
--- /dev/null
+++ b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/java/com/gsean/redisson/utils/LockUtil.java
@@ -0,0 +1,69 @@
+package com.gsean.redisson.utils;
+
+import java.util.concurrent.TimeUnit;
+import javax.xml.ws.RequestWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author linxin.xiong
+ * @description 分布式锁工具类
+ * @date created in 2021/6/21 11:22
+ * @modificed by
+ */
+@Slf4j
+@Component
+public class LockUtil {
+
+ private static RedissonClient redissonClient;
+
+ @Autowired
+ public void setRedissonClient(RedissonClient redissonClient) {
+ LockUtil.redissonClient = redissonClient;
+ }
+
+
+ /**
+ * 获取分布式redis锁并执行runnable.
+ * 多个线程获取锁失败时会等待指定时间,仍未获取到锁则跳过执行.
+ *
+ * @param lockName lockName
+ * @param runnable operations after locked
+ * @param waitTime the maximum time to acquire the lock
+ * @param leaseTime lock expiration time
+ */
+ public static void tryLockAndExecute(String lockName, Runnable runnable, long waitTime, long leaseTime) {
+ RLock lock = redissonClient.getLock(lockName);
+ boolean locked = false;
+ try {
+ locked = lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
+ } catch (InterruptedException ex) {
+ log.error("LockUtil#tryLockAndExecute() interrupted... lockName={}", lockName, ex);
+ Thread.currentThread().interrupt();
+ }
+ if (locked) {
+ // 不捕获异常,由调用层控制吞并异常或事务回滚
+ try {
+ runnable.run();
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * 获取分布式redis锁并执行runnable.
+ * 多个线程获取锁失败时没有等待时间,直接跳过,适用于只需获取一次锁的场景,如定时任务.
+ *
+ * @param lockName lockName
+ * @param runnable operations after locked
+ */
+ public static void tryLockWithoutWaiting(String lockName, Runnable runnable) {
+ tryLockAndExecute(lockName,runnable,0,60);
+ }
+
+}
diff --git a/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/resources/application.yml b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..aeb46817860585fbf1a8e0ccb3e76ab54a41da5e
--- /dev/null
+++ b/distributed-demos/distribuited-lock-demos/redisson-sample/src/main/resources/application.yml
@@ -0,0 +1,9 @@
+redisson:
+ host:
+ config: redis://127.0.0.1:6379
+
+spring:
+ redis:
+ password: 123456
+
+
diff --git a/distributed-demos/distribuited-lock-demos/redisson-sample/src/test/java/com/gsean/redisson/RedissonSampleAppTest.java b/distributed-demos/distribuited-lock-demos/redisson-sample/src/test/java/com/gsean/redisson/RedissonSampleAppTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..614e828fcea6e790f95342a1f542e4136df1b45b
--- /dev/null
+++ b/distributed-demos/distribuited-lock-demos/redisson-sample/src/test/java/com/gsean/redisson/RedissonSampleAppTest.java
@@ -0,0 +1,43 @@
+package com.gsean.redisson;
+
+import static org.junit.Assert.*;
+
+import com.alibaba.fastjson.JSON;
+import io.lettuce.core.RedisClient;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/15 17:55
+ * @modificed by
+ **/
+@SpringBootTest
+@RunWith(SpringJUnit4ClassRunner.class)
+public class RedissonSampleAppTest {
+
+
+ @Autowired
+ private RedissonClient redissonClient;
+
+
+ /**
+ *
+ * 获取配置
+ * @author: Jincheng.Guo11
+ * @date: 2021/11/15 18:09
+ * @return: void
+ * @throws: java.lang.Exception
+ * @modificed by:
+ */
+ @Test
+ public void testA(){
+ System.out.println(JSON.toJSONString(redissonClient.getConfig()));
+ }
+
+}
\ No newline at end of file
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/pom.xml b/mq-demos/rocketmq-demos/rocketmq-sample/pom.xml
index db7e13d065cbf709a17a2f26e367c6039ad3f974..e1816955ffc538242196c3f23a064534fe579002 100644
--- a/mq-demos/rocketmq-demos/rocketmq-sample/pom.xml
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/pom.xml
@@ -27,6 +27,7 @@
org.springframework.boot
spring-boot-starter-web
+
\ No newline at end of file
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/MessageQueueChannels.java b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/MessageQueueChannels.java
index f9ec1a6817e0f37333f2e167fd413de3cdacc339..da8e065e1320e4a7012101b75a907185c922af83 100644
--- a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/MessageQueueChannels.java
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/MessageQueueChannels.java
@@ -12,25 +12,25 @@ import org.springframework.messaging.SubscribableChannel;
*/
public interface MessageQueueChannels {
- String WECHAT_CODE_PRE_LOAD_OUTPUT = "gsean-test-output";
- String WECHAT_CODE_PRE_LOAD_INPUT = "gsean-test-input";
+ String USER_PAYLOD_OUTPUT = "user-payload-output";
+ String USER_PAYLOD_INPUT = "user-payload-input";
/**
- * 二维码预加载事件发送通道.
+ * 用户负载事件发送通道.
*
* @return MessageChannel
*/
- @Output(WECHAT_CODE_PRE_LOAD_OUTPUT)
- MessageChannel wechatCodePreLoadOutput();
+ @Output(USER_PAYLOD_OUTPUT)
+ MessageChannel userPaylodOutput();
/**
- * 二维码预加载事件接收通道.
+ * 用户负载事件接收通道.
*
* @return SubscribableChannel
*/
- @Input(WECHAT_CODE_PRE_LOAD_INPUT)
- SubscribableChannel wechatCodePreLoadInput();
+ @Input(USER_PAYLOD_INPUT)
+ SubscribableChannel userPayloadInput();
}
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/QueueConsumer.java b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/QueueConsumer.java
index e44dabfa3f57d34c7a27f546f768d35b98165c1a..b00d373bf550e89407553e707160e1906be5b287 100644
--- a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/QueueConsumer.java
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/QueueConsumer.java
@@ -1,32 +1,43 @@
-//package com.gsean.rocket.config;
-//
-//import lombok.RequiredArgsConstructor;
-//import lombok.extern.slf4j.Slf4j;
-//import org.springframework.cloud.stream.annotation.EnableBinding;
-//import org.springframework.cloud.stream.annotation.StreamListener;
-//import org.springframework.stereotype.Service;
-//
-///**
-// * 消息队列消费.
-// *
-// * @author linxin.xiong
-// */
-//@Slf4j
-//@Service
-//@EnableBinding({MessageQueueChannels.class})
-//@RequiredArgsConstructor
-//public class QueueConsumer {
-//
-//
-// /**
-// * 处理二维码预加载消息.
-// *
-// * @param message 二维码预加载
-// */
-// @StreamListener(MessageQueueChannels.WECHAT_CODE_PRE_LOAD_INPUT)
-// public void wechatCodeUrlPreLoadMessageHandler(String message) {
-// System.out.println(message);
-// }
-//
-//
-//}
+package com.gsean.rocket.config;
+
+import com.alibaba.fastjson.JSON;
+import com.gsean.rocket.dto.UserPayload;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.stream.annotation.StreamListener;
+import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.stereotype.Component;
+
+/**
+ * 消息队列消费.
+ *
+ * @author linxin.xiong
+ */
+@Slf4j
+@Component
+public class QueueConsumer {
+
+
+ /**
+ * 用户负载消费消息.
+ *
+ * @param message 二维码预加载
+ */
+ @StreamListener(MessageQueueChannels.USER_PAYLOD_INPUT)
+ public void userPayloadMessageHandler(@Payload UserPayload message) {
+ log.info("用户负载消费:{}", JSON.toJSONString(message));
+// if(message.getId().equals(1L)){
+// log.error("消费失败");
+// throw new RuntimeException("消费失败");
+// }
+ log.info("消费成功");
+ }
+
+
+
+
+
+
+
+}
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/QueueProducer.java b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/QueueProducer.java
index d0b5b21e120cc95f604269b83453bd278d93f22e..511eb66d852a12d8a5405c88ff8586502674305b 100644
--- a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/QueueProducer.java
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/QueueProducer.java
@@ -1,7 +1,9 @@
package com.gsean.rocket.config;
+import com.gsean.rocket.dto.UserPayload;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.common.message.MessageConst;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
@@ -15,22 +17,31 @@ import org.springframework.stereotype.Service;
@Slf4j
@Service
public class QueueProducer {
+ @Autowired
+ private MessageQueueChannels messageQueueChannels;
- @Resource(name = MessageQueueChannels.WECHAT_CODE_PRE_LOAD_OUTPUT)
- private MessageChannel wechatCodePreLoadOutput;
-
-// @Resource(name = com.geely.app.config.rocketmq.MessageQueueChannels.FABULOUS_CREATE_OUTPUT)
-// private MessageChannel fabulousCreateOutput;
+ public void sendUserPayload(UserPayload payload) {
+ boolean send = messageQueueChannels.userPaylodOutput()
+ .send(MessageBuilder.withPayload(payload).build());
+ log.info("发送用户负载状态:{}",send);
+ }
- public void sendWechatCodePreLoadMessage(Object msg) {
- try {
- boolean send = wechatCodePreLoadOutput.send(MessageBuilder.withPayload(msg).build());
- if (!send) {
- log.error("预生成分享二维码消息发送失败...");
- }
- } catch (Exception ex) {
- log.error("预生成分享二维码消息发送异常...", ex);
- }
+ /**
+ * 发送延迟消息
+ *
+ * @param payload
+ * @author: Jincheng.Guo11
+ * @date: 2021/11/19 17:00
+ * @return: void
+ * @throws: java.lang.Exception
+ * @modificed by:
+ */
+ public void sendDelayUserPayload(UserPayload payload) {
+ boolean send = messageQueueChannels.userPaylodOutput()
+ .send(MessageBuilder.withPayload(payload)
+ .setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, "3")
+ .build());
+ log.info("发送延时用户负载状态:{}",send);
}
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/TransactionListenerImpl.java b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/TransactionListenerImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..87594f2c1cf0bc69e58e6937e85ba8e29e61e47b
--- /dev/null
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/config/TransactionListenerImpl.java
@@ -0,0 +1,36 @@
+package com.gsean.rocket.config;
+
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
+import org.springframework.messaging.Message;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/19 11:43
+ * @modificed by
+ **/
+@Slf4j
+@RocketMQTransactionListener(txProducerGroup = "test")
+public class TransactionListenerImpl implements RocketMQLocalTransactionListener {
+
+ @Override
+ public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
+ // 从消息 Header 中解析到 args 参数,并使用 JSON 反序列化
+ String args = JSON.parseObject(message.getHeaders().get("args", String.class),
+ String.class);
+ // ... local transaction process, return rollback, commit or unknown
+ log.info("[executeLocalTransaction][执行本地事务,消息:{} args:{}]", message, args);
+ return RocketMQLocalTransactionState.UNKNOWN;
+ }
+
+ @Override
+ public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
+ // ... check transaction status and return rollback, commit or unknown
+ log.info("[checkLocalTransaction][回查消息:{}]", message);
+ return RocketMQLocalTransactionState.COMMIT;
+ }
+}
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/dto/UserPayload.java b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/dto/UserPayload.java
new file mode 100644
index 0000000000000000000000000000000000000000..a49524d8150a4fdd474667a02da5e6e8cc687331
--- /dev/null
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/java/com/gsean/rocket/dto/UserPayload.java
@@ -0,0 +1,21 @@
+package com.gsean.rocket.dto;
+
+import java.time.LocalDate;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/16 14:24
+ * @modificed by
+ **/
+@Data
+@Accessors(chain = true)
+public class UserPayload {
+
+ private Long id;
+ private String name;
+ private LocalDate birth;
+
+}
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application-v1.yml b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application-v1.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b2f6c980a56f7487afc1ae84b048a21b0d4d4520
--- /dev/null
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application-v1.yml
@@ -0,0 +1,33 @@
+# RocketMQ配置 简单消息配置
+spring:
+ cloud:
+ # Spring Cloud Stream 配置项,对应 BindingServiceProperties 类
+ stream:
+ # Spring Cloud Stream RocketMQ 配置项
+ rocketmq:
+ # RocketMQ Binder 配置项,对应 RocketMQBinderConfigurationProperties 类
+ binder:
+ # RocketMQ Namesrv 地址
+# name-server: 10.113.75.163:9876;10.113.75.164:9876;
+# name-server: 127.0.0.1:9876
+ name-server: 10.113.72.232:9876
+ bindings:
+ user-paylod-input:
+ consumer:
+ enabled: true #默认是true,开发可以false
+# broadcasting: true #是否开启广播消费,默认集群消费
+# delay-level-when-next-consume: -1
+
+ # Binding 配置项,对应 BindingProperties Map
+ bindings:
+ #定义name为gsean-test-output的binding
+ user-payload-output:
+ destination: USERPAYLOAD-TOPIC
+ content-type: application/json
+ #定义name为gsean-test-input的binding
+ user-payload-input:
+ destination: USERPAYLOAD-TOPIC
+ group: user-payload-group-01
+ content-type: application/json
+
+
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application-v2.yml b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application-v2.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3f5072d548a6f82c427555b3f824f1b7bc91be65
--- /dev/null
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application-v2.yml
@@ -0,0 +1,31 @@
+# RocketMQ配置 事务消息配置
+spring:
+ cloud:
+ # Spring Cloud Stream 配置项,对应 BindingServiceProperties 类
+ stream:
+ # Spring Cloud Stream RocketMQ 配置项
+ rocketmq:
+ # RocketMQ Binder 配置项,对应 RocketMQBinderConfigurationProperties 类
+ binder:
+ # RocketMQ Namesrv 地址
+ name-server: 10.113.75.163:9876;10.113.75.164:9876;
+ bindings:
+ user-payload-output:
+ producer:
+ group: test
+ sync: true
+ transactional: true
+
+ # Binding 配置项,对应 BindingProperties Map
+ bindings:
+ #定义name为gsean-test-output的binding
+ user-payload-output:
+ destination: TRANSACTION-TOPIC
+ content-type: application/json
+ #定义name为gsean-test-input的binding
+ user-payload-input:
+ destination: TRANSACTION-TOPIC
+ group: user-payload-group-02
+ content-type: application/json
+
+
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application.yml b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application.yml
index 45b8c222b447a33164c1a423f990d6d4971df8b9..8b22b1756ac35995bcf7662f29c2988b42b4c0db 100644
--- a/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application.yml
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/main/resources/application.yml
@@ -1,49 +1,6 @@
+server:
+ port: ${random.int[10000,19999]}
-# 短信验证码请求域名(网关地址)
-code:
- url: http://gateway.cloud-dev.geega.com
-
-# 助力分享二维码前端页面地址
-fabulous:
- share:
- page: "package/pages/questions"
-
-item:
- id: "116800100090001"
-
-store:
- id: "2"
-
-# 小程序appId和appsecret
-wechat:
- # appId: wx12927de7e3a4dbf2
- # appsecret: 35555a9e98c806654df1176b9b30d3ce
- appId: wxce8456066fec3a6a
- appsecret: a7cb5f3890e4f4eb3e856aaad3f61823
-
-# RocketMQ配置
spring:
- cloud:
- # Spring Cloud Stream 配置项,对应 BindingServiceProperties 类
- stream:
- # Spring Cloud Stream RocketMQ 配置项
- rocketmq:
- # RocketMQ Binder 配置项,对应 RocketMQBinderConfigurationProperties 类
- binder:
- # RocketMQ Namesrv 地址
- name-server: 10.113.75.163:9876;10.113.75.164:9876;
- # Binding 配置项,对应 BindingProperties Map
- bindings:
- #定义name为gsean-test-output的binding
- gsean-test-output:
- destination: TEST-TOPIC
- content-type: application/json
- #定义name为gsean-test-input的binding
- gsean-test-input:
- destination: TEST-TOPIC
- group: test-group
- content-type: application/json
-
-
-server:
- port: 8082
+ profiles:
+ active: v1
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/test/java/com/gsean/rocket/MyTest.java b/mq-demos/rocketmq-demos/rocketmq-sample/src/test/java/com/gsean/rocket/MyTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4fa9908d54b4e998ab1cac2edec2c44b047fa7f2
--- /dev/null
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/test/java/com/gsean/rocket/MyTest.java
@@ -0,0 +1,25 @@
+package com.gsean.rocket;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.test.annotation.Repeat;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/16 14:52
+ * @modificed by
+ **/
+public class MyTest {
+
+
+
+
+
+ @Test
+ @Repeat(3)
+ public void test1(){
+ System.out.println("hello");
+ }
+
+}
diff --git a/mq-demos/rocketmq-demos/rocketmq-sample/src/test/java/com/gsean/rocket/RocketMqAppTest.java b/mq-demos/rocketmq-demos/rocketmq-sample/src/test/java/com/gsean/rocket/RocketMqAppTest.java
index 6be2ee099b1ce474783a5a1a0e1fdffe61dee735..79e441859fa434b07a19763c991943b33d66f4e3 100644
--- a/mq-demos/rocketmq-demos/rocketmq-sample/src/test/java/com/gsean/rocket/RocketMqAppTest.java
+++ b/mq-demos/rocketmq-demos/rocketmq-sample/src/test/java/com/gsean/rocket/RocketMqAppTest.java
@@ -1,10 +1,14 @@
package com.gsean.rocket;
import com.gsean.rocket.config.QueueProducer;
+import com.gsean.rocket.dto.UserPayload;
+import java.time.LocalDate;
+import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
/**
@@ -15,14 +19,37 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
**/
@SpringBootTest
@ExtendWith(SpringExtension.class)
+@ActiveProfiles("v1")
class RocketMqAppTest {
@Autowired
private QueueProducer queueProducer;
+
+
@Test
- public void testA(){
- queueProducer.sendWechatCodePreLoadMessage("hello gsean");
+ public void testSendUserPayload(){
+// Stream.iterate(0,x->x+1).limit(3).forEachOrdered(item->{
+ UserPayload userPayload = new UserPayload().setId(1L).setName("gsean"+1).setBirth(LocalDate.now());
+ queueProducer.sendUserPayload(userPayload);
+// });
+ }
+ /**
+ *
+ * 延时消息测试
+ * @author: Jincheng.Guo11
+ * @date: 2021/11/19 17:01
+ * @return: void
+ * @throws: java.lang.Exception
+ * @modificed by:
+ */
+ @Test
+ public void testDelayMsg(){
+ UserPayload userPayload = new UserPayload().setId(1L).setName("delay").setBirth(LocalDate.now());
+ queueProducer.sendDelayUserPayload(userPayload);
}
+
+
+
}
\ No newline at end of file
diff --git a/redis-demos/redis-sampleV2/src/main/java/com/gsean/redis/config/RedisConfig.java b/redis-demos/redis-sampleV2/src/main/java/com/gsean/redis/config/RedisConfig.java
index 0ec00221a49bcf368fb016a72dcaf7b6c1dac184..8e1b379c43c76a092c7be2b90cd9c101439b21b5 100644
--- a/redis-demos/redis-sampleV2/src/main/java/com/gsean/redis/config/RedisConfig.java
+++ b/redis-demos/redis-sampleV2/src/main/java/com/gsean/redis/config/RedisConfig.java
@@ -13,6 +13,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
@@ -29,6 +30,8 @@ public class RedisConfig {
@Autowired
private LettuceConnectionFactory connectionFactory;
+
+
@Bean
public RedisTemplate redisTemplate() {
RedisTemplate redisTemplate = new RedisTemplate<>();
diff --git a/swagger-demo/swagger-sample/src/main/java/com/gsean/swagger/SwaggerSampleApplication.java b/swagger-demo/swagger-sample/src/main/java/com/gsean/swagger/SwaggerSampleApplication.java
index 49891e9e9710e936fe2b6c64f7836ef44f792cb1..9a95ce7e84a468a92544c2339e6c02b06cb1ae47 100644
--- a/swagger-demo/swagger-sample/src/main/java/com/gsean/swagger/SwaggerSampleApplication.java
+++ b/swagger-demo/swagger-sample/src/main/java/com/gsean/swagger/SwaggerSampleApplication.java
@@ -19,7 +19,5 @@ import springfox.documentation.swagger2.configuration.Swagger2DocumentationConfi
public class SwaggerSampleApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(SwaggerSampleApplication.class, args);
- Swagger2DocumentationConfiguration bean = run.getBean(Swagger2DocumentationConfiguration.class);
- System.out.println(bean==null);
}
}
diff --git a/swagger-demo/swagger-ui-demo/pom.xml b/swagger-demo/swagger-ui-demo/pom.xml
index 6d998ee34ff6fb566f5ee01c68e44f5dec3fbfce..e9ce1047dd7de6e00c32e1444bbf47a054525a3e 100644
--- a/swagger-demo/swagger-ui-demo/pom.xml
+++ b/swagger-demo/swagger-ui-demo/pom.xml
@@ -64,5 +64,14 @@
swagger-bootstrap-ui
1.9.1
+
+ org.apache.commons
+ commons-lang3
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ runtime
+
\ No newline at end of file
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/EnumModelPropertyBuilderPlugin.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/EnumModelPropertyBuilderPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b3a5517849bdef8af5fa4520aeab5ee709fd738
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/EnumModelPropertyBuilderPlugin.java
@@ -0,0 +1,84 @@
+package com.gsean.swaggerui.config;
+
+import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
+import com.google.common.base.Optional;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ReflectionUtils;
+import springfox.documentation.builders.ModelPropertyBuilder;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
+import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/22 10:10
+ * @modificed by
+ **/
+@Component
+public class EnumModelPropertyBuilderPlugin implements ModelPropertyBuilderPlugin
+{
+
+ @Override
+ public void apply(ModelPropertyContext context) {
+ Optional optional = context.getBeanPropertyDefinition();
+ if (!optional.isPresent()) {
+ return;
+ }
+
+ final Class> fieldType = optional.get().getField().getRawType();
+
+ addDescForEnum(context, fieldType);
+ }
+
+ @Override
+ public boolean supports(DocumentationType documentationType) {
+ return true;
+ }
+
+ private void addDescForEnum(ModelPropertyContext context, Class> fieldType) {
+ if (Enum.class.isAssignableFrom(fieldType)) {
+ SwaggerDisplayEnum annotation = AnnotationUtils
+ .findAnnotation(fieldType, SwaggerDisplayEnum.class);
+ if (annotation != null) {
+ String index = annotation.index();
+ String name = annotation.name();
+
+ Object[] enumConstants = fieldType.getEnumConstants();
+
+ List displayValues =
+ Arrays.stream(enumConstants)
+ .filter(Objects::nonNull)
+ .map(item -> {
+ Class> currentClass = item.getClass();
+
+ Field indexField = ReflectionUtils.findField(currentClass, index);
+ ReflectionUtils.makeAccessible(indexField);
+ Object value = ReflectionUtils.getField(indexField, item);
+
+ Field descField = ReflectionUtils.findField(currentClass, name);
+ ReflectionUtils.makeAccessible(descField);
+ Object desc = ReflectionUtils.getField(descField, item);
+ return value + ":" + desc;
+
+ }).collect(Collectors.toList());
+
+
+ ModelPropertyBuilder builder = context.getBuilder();
+ Field descField = ReflectionUtils.findField(builder.getClass(), "description");
+ ReflectionUtils.makeAccessible(descField);
+ String joinText = ReflectionUtils.getField(descField, builder)
+ + " (" + String.join("; ", displayValues) + ")";
+
+ builder.description(joinText).type(context.getResolver().resolve(Integer.class));
+ }
+ }
+
+ }
+}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/EnumParameterBuilderPlugin.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/EnumParameterBuilderPlugin.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0bf5aa9ae653635c53e1ab3c971d80113727648
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/EnumParameterBuilderPlugin.java
@@ -0,0 +1,123 @@
+package com.gsean.swaggerui.config;
+
+import com.fasterxml.classmate.ResolvedType;
+import com.google.common.base.Joiner;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ReflectionUtils;
+import springfox.documentation.builders.OperationBuilder;
+import springfox.documentation.builders.ParameterBuilder;
+import springfox.documentation.service.AllowableListValues;
+import springfox.documentation.service.Parameter;
+import springfox.documentation.service.ResolvedMethodParameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.OperationBuilderPlugin;
+import springfox.documentation.spi.service.ParameterBuilderPlugin;
+import springfox.documentation.spi.service.contexts.OperationContext;
+import springfox.documentation.spi.service.contexts.ParameterContext;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/22 10:13
+ * @modificed by
+ **/
+@Component
+public class EnumParameterBuilderPlugin implements ParameterBuilderPlugin, OperationBuilderPlugin {
+ private static final Joiner joiner = Joiner.on(",");
+
+ @Override
+ public void apply(OperationContext context) {
+ Map> map = new HashMap<>();
+ List parameters = context.getParameters();
+ parameters.forEach(parameter -> {
+ ResolvedType parameterType = parameter.getParameterType();
+ Class> clazz = parameterType.getErasedType();
+ if (Enum.class.isAssignableFrom(clazz)) {
+ SwaggerDisplayEnum annotation = AnnotationUtils.findAnnotation(clazz, SwaggerDisplayEnum.class);
+ if (annotation != null) {
+ String index = annotation.index();
+ String name = annotation.name();
+ Object[] enumConstants = clazz.getEnumConstants();
+
+ List displayValues = Arrays.stream(enumConstants).filter(Objects::nonNull).map(item -> {
+ Class> currentClass = item.getClass();
+
+ Field indexField = ReflectionUtils.findField(currentClass, index);
+ ReflectionUtils.makeAccessible(indexField);
+ Object value = ReflectionUtils.getField(indexField, item);
+
+ Field descField = ReflectionUtils.findField(currentClass, name);
+ ReflectionUtils.makeAccessible(descField);
+ Object desc = ReflectionUtils.getField(descField, item);
+ return value + ":" + desc;
+
+ }).collect(Collectors.toList());
+
+ map.put(parameter.defaultName().or(""), displayValues);
+
+ OperationBuilder operationBuilder = context.operationBuilder();
+ Field parametersField = ReflectionUtils.findField(operationBuilder.getClass(), "parameters");
+ ReflectionUtils.makeAccessible(parametersField);
+ List list = (List) ReflectionUtils.getField(parametersField, operationBuilder);
+
+ map.forEach((k, v) -> {
+ for (Parameter currentParameter : list) {
+ if (StringUtils.equals(currentParameter.getName(), k)) {
+ Field description = ReflectionUtils.findField(currentParameter.getClass(), "description");
+ ReflectionUtils.makeAccessible(description);
+ Object field = ReflectionUtils.getField(description, currentParameter);
+ ReflectionUtils.setField(description, currentParameter, field + " , " + joiner.join(v));
+ break;
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+
+ @Override
+ public void apply(ParameterContext context) {
+ Class> type = context.resolvedMethodParameter().getParameterType().getErasedType();
+ if (Enum.class.isAssignableFrom(type)) {
+ SwaggerDisplayEnum annotation = AnnotationUtils.findAnnotation(type, SwaggerDisplayEnum.class);
+ if (annotation != null) {
+
+ String index = annotation.index();
+ String name = annotation.name();
+ Object[] enumConstants = type.getEnumConstants();
+ List displayValues = Arrays.stream(enumConstants).filter(Objects::nonNull).map(item -> {
+ Class> currentClass = item.getClass();
+
+ Field indexField = ReflectionUtils.findField(currentClass, index);
+ ReflectionUtils.makeAccessible(indexField);
+ Object value = ReflectionUtils.getField(indexField, item);
+
+ Field descField = ReflectionUtils.findField(currentClass, name);
+ ReflectionUtils.makeAccessible(descField);
+ Object desc = ReflectionUtils.getField(descField, item);
+ return value.toString();
+
+ }).collect(Collectors.toList());
+
+ ParameterBuilder parameterBuilder = context.parameterBuilder();
+ AllowableListValues values = new AllowableListValues(displayValues, "LIST");
+ parameterBuilder.allowableValues(values);
+ }
+ }
+ }
+
+ @Override
+ public boolean supports(DocumentationType documentationType) {
+ return true;
+ }
+}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/MvcConfiguration.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/MvcConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..03e5b75335a428e74c46e0f0b98928f1c484610e
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/MvcConfiguration.java
@@ -0,0 +1,161 @@
+package com.gsean.swaggerui.config;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+import com.gsean.swaggerui.plugin.EnumMvcConverterFactory;
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+import org.apache.commons.lang3.time.DateUtils;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.format.FormatterRegistry;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @author shenjianeng
+ * @date 2020/4/19
+ */
+@Configuration
+public class MvcConfiguration implements WebMvcConfigurer {
+ private final String YYYY_MM_DD = "yyyy-MM-dd";
+
+ private final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+ private final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+ private final String HH_MM_SS = "HH:mm:ss";
+
+ @Bean
+ public EnumMvcConverterFactory enumMvcConverterFactory() {
+ return new EnumMvcConverterFactory();
+ }
+
+ @Override
+ public void addFormatters(FormatterRegistry registry) {
+ // org.springframework.core.convert.support.GenericConversionService.ConvertersForPair.add
+ // this.converters.addFirst(converter);
+ // 所以我们自定义的会放在前面
+ registry.addConverterFactory(enumMvcConverterFactory());
+ registry.addConverter(localDateTimeConverter());
+ registry.addConverter(localDateConverter());
+ registry.addConverter(localTimeConverter());
+ }
+
+ /**
+ * Json序列化和反序列化转换器,用于转换Post请求体中的json以及将我们的对象序列化为返回响应的json
+ */
+ @Bean
+ public ObjectMapper customDateObjectMapper(){
+
+
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
+ objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+
+ //LocalDateTime系列序列化和反序列化模块,继承自jsr310,这里修改了日期格式
+ JavaTimeModule javaTimeModule = new JavaTimeModule();
+ javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS)));
+ javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(YYYY_MM_DD)));
+ javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(HH_MM_SS)));
+ javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS)));
+ javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(YYYY_MM_DD)));
+ javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(HH_MM_SS)));
+
+ //Date序列化和反序列化
+ javaTimeModule.addSerializer(Date.class, new JsonSerializer() {
+ @Override
+ public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+ SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
+ String formattedDate = formatter.format(date);
+ jsonGenerator.writeString(formattedDate);
+ }
+ });
+ javaTimeModule.addDeserializer(Date.class, new JsonDeserializer() {
+ @Override
+ public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+ SimpleDateFormat format = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
+ String date = jsonParser.getText();
+ try {
+ return format.parse(date);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
+ objectMapper.registerModule(javaTimeModule);
+ return objectMapper;
+ }
+
+
+ /**
+ * LocalDate转换器,用于转换RequestParam和PathVariable参数
+ */
+ private Converter localDateConverter() {
+ return new Converter() {
+ @Override
+ public LocalDate convert(String source) {
+ if(!ObjectUtils.isEmpty(source)){
+ return LocalDate.parse(source, DateTimeFormatter.ofPattern(YYYY_MM_DD));
+ }
+ return null ;
+
+ }
+ };
+ }
+
+ /**
+ * LocalDateTime转换器,用于转换RequestParam和PathVariable参数
+ */
+ private Converter localDateTimeConverter() {
+ return new Converter() {
+ @Override
+ public LocalDateTime convert(String source) {
+ if(!ObjectUtils.isEmpty(source)) {
+ return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
+ }
+ return null ;
+ }
+ };
+ }
+
+ /**
+ * LocalTime转换器,用于转换RequestParam和PathVariable参数
+ */
+ private Converter localTimeConverter() {
+ return new Converter() {
+ @Override
+ public LocalTime convert(String source) {
+ if(!ObjectUtils.isEmpty(source)) {
+ return LocalTime.parse(source, DateTimeFormatter.ofPattern(HH_MM_SS));
+ }
+ return null;
+ }
+ };
+ }
+}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/SwaggerDisplayEnum.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/SwaggerDisplayEnum.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c1c6214aa9baab4315148ea877fc5171a579e2c
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/config/SwaggerDisplayEnum.java
@@ -0,0 +1,21 @@
+package com.gsean.swaggerui.config;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/22 10:09
+ * @modificed by
+ **/
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SwaggerDisplayEnum {
+
+ String index() default "index";
+ String name() default "name";
+
+}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/controller/HelloController.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/controller/HelloController.java
index e2b40080750d5fd73322f3df1d696c20a9cc8df5..249728e75d376dd76ce7bae6c8eaaec35c8f5a46 100644
--- a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/controller/HelloController.java
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/controller/HelloController.java
@@ -1,10 +1,17 @@
package com.gsean.swaggerui.controller;
+import com.gsean.swaggerui.enums.Status;
import com.gsean.swaggerui.module.User;
+import com.gsean.swaggerui.params.StatusParam;
+import com.gsean.swaggerui.params.UserDTO;
+import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
@@ -16,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
* Version: 1.0
*/
@RestController
+@Api(value = "hello接口管理")
public class HelloController {
@GetMapping("/hello")
@@ -25,7 +33,25 @@ public class HelloController {
@PostMapping("/hello2")
@ApiOperation(value = "二接口")
- public User hello2(@RequestBody User user){
- return user;
+ public User hello2(@RequestBody UserDTO user){
+ User resUser = new User().setId(user.getId()).setName(user.getName()).setStatus(user.getStatus())
+ .setBirthDate(user.getBirthDate()).setCreatedTime(user.getCreatedTime());
+ return resUser;
+ }
+
+
+ @GetMapping("/hello3")
+ @ApiOperation(value = "枚举请求体")
+ public User hello3(@RequestParam Status status){
+ User gsaen = new User().setId(1).setName("gsaen").setStatus(status).setBirthDate(LocalDate.now()).setCreatedTime(
+ LocalDateTime.now());
+ return gsaen;
+ }
+
+ @GetMapping("/hello4")
+ @ApiOperation(value = "枚举请求体v2")
+ public User hello4(StatusParam statusParam,@RequestParam Status status){
+ User gsaen = new User().setId(statusParam.getId()).setName("gsaen").setStatus(status).setBirthDate(LocalDate.now());
+ return gsaen;
}
}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/enums/Status.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/enums/Status.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb855fbc5522cb0910b3c2229adf5f2e4192be0c
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/enums/Status.java
@@ -0,0 +1,48 @@
+package com.gsean.swaggerui.enums;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.gsean.swaggerui.config.SwaggerDisplayEnum;
+import com.gsean.swaggerui.plugin.EnumConvertMethod;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import lombok.Getter;
+import org.springframework.lang.Nullable;
+
+@Getter
+@SwaggerDisplayEnum(index = "id", name = "des")
+@JsonFormat(shape = JsonFormat.Shape.OBJECT)
+public enum Status {
+
+ ACTIVE(1,"可用"),
+ UNACTIVE(2, "不可用");
+
+// @JsonValue
+ private Integer id;
+ private String des;
+
+ Status(Integer id,String des) {
+ this.id=id;
+ this.des = des;
+ }
+
+
+ private static final Map mappings;
+
+ static {
+ Map temp = new HashMap<>();
+ for (Status courseType : values()) {
+ temp.put(courseType.id, courseType);
+ }
+ mappings = Collections.unmodifiableMap(temp);
+ }
+
+ @EnumConvertMethod
+ @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
+ @Nullable
+ public static Status resolve(int index) {
+ return mappings.get(index);
+ }
+}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/module/User.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/module/User.java
index 6ec8f519517becbfa1c9c5145e04e084debe5e80..422a6c6b7d73d6272dffec07ed1b2e3016ba765d 100644
--- a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/module/User.java
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/module/User.java
@@ -1,7 +1,19 @@
package com.gsean.swaggerui.module;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.gsean.swaggerui.enums.Status;
+import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
import lombok.Data;
+import lombok.experimental.Accessors;
/**
* ProjectName:gsean-springboot-demos
@@ -12,9 +24,21 @@ import lombok.Data;
* Version: 1.0
*/
@Data
-
+@ApiModel(value = "用户")
+@Accessors(chain = true)
public class User {
@ApiModelProperty(name = "name",value = "名称")
private String name;
+ @ApiModelProperty(value = "id")
private Integer id;
+ @ApiModelProperty(value = "状态")
+ private Status status;
+ @ApiModelProperty(value = "生日")
+// @JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8")
+ private LocalDate birthDate;
+ @ApiModelProperty(value = "创建日期")
+// @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+ private LocalDateTime createdTime;
+
+
}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/params/StatusParam.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/params/StatusParam.java
new file mode 100644
index 0000000000000000000000000000000000000000..94652ce5574e5cbeaf827ae20d1baf91e0b37e62
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/params/StatusParam.java
@@ -0,0 +1,21 @@
+package com.gsean.swaggerui.params;
+
+import com.gsean.swaggerui.enums.Status;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/22 11:13
+ * @modificed by
+ **/
+@ApiModel("状态请求体")
+@Getter
+public class StatusParam {
+ @ApiModelProperty(value = "id",example = "1",required = true)
+ private Integer id;
+
+
+}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/params/UserDTO.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/params/UserDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..650298e35429d91d9435c5edf8cbe24ee22c129d
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/params/UserDTO.java
@@ -0,0 +1,44 @@
+package com.gsean.swaggerui.params;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.gsean.swaggerui.enums.Status;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import lombok.Data;
+import lombok.Getter;
+import lombok.experimental.Accessors;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/22 13:25
+ * @modificed by
+ **/
+@Data
+@ApiModel(value = "用户")
+@Accessors(chain = true)
+public class UserDTO {
+ @ApiModelProperty(name = "name",value = "名称")
+ private String name;
+ @ApiModelProperty(value = "id")
+ private Integer id;
+ @ApiModelProperty(value = "状态")
+ private Status status;
+ @ApiModelProperty(value = "生日",example = "2021-12-11")
+// @JsonDeserialize(using = LocalDateDeserializer.class)
+// @JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8")
+ private LocalDate birthDate;
+ @ApiModelProperty(value = "创建日期")
+// @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+// @JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8")
+ private LocalDateTime createdTime;
+
+}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/plugin/EnumConvertMethod.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/plugin/EnumConvertMethod.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d385d5dc17a5f4b732e7ba444852ac863603e0b
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/plugin/EnumConvertMethod.java
@@ -0,0 +1,20 @@
+package com.gsean.swaggerui.plugin;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 在自定义枚举类的工厂方法上标记该注解,用于Spring MVC 转换器转换枚举
+ * {@link com.github.shen.mvc.plugin.EnumMvcConverterFactory}
+ *
+ * @author shenjianeng
+ * @date 2020/4/19
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface EnumConvertMethod {
+}
diff --git a/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/plugin/EnumMvcConverterFactory.java b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/plugin/EnumMvcConverterFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5ceb6dc2090af3a7c1c6e72fada5358925de76f
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/main/java/com/gsean/swaggerui/plugin/EnumMvcConverterFactory.java
@@ -0,0 +1,79 @@
+package com.gsean.swaggerui.plugin;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.reflect.MethodUtils;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.core.convert.converter.ConverterFactory;
+import org.springframework.lang.Nullable;
+import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * springMVC 枚举类的转换器
+ * 如果枚举类中有工厂方法(静态方法)被标记为{@link EnumConvertMethod },则调用该方法转为枚举对象
+ *
+ * @author shenjianeng
+ * @date 2020/4/19
+ */
+@SuppressWarnings("all")
+public class EnumMvcConverterFactory implements ConverterFactory> {
+
+ private final ConcurrentMap>, EnumMvcConverterHolder> holderMapper = new ConcurrentHashMap<>();
+
+
+ @Override
+ public > Converter getConverter(Class targetType) {
+ EnumMvcConverterHolder holder = holderMapper.computeIfAbsent(targetType, EnumMvcConverterHolder::createHolder);
+ return (Converter) holder.converter;
+ }
+
+
+ @AllArgsConstructor
+ static class EnumMvcConverterHolder {
+ @Nullable
+ final EnumMvcConverter> converter;
+
+ static EnumMvcConverterHolder createHolder(Class> targetType) {
+ List methodList = MethodUtils.getMethodsListWithAnnotation(targetType, EnumConvertMethod.class, false, true);
+ if (CollectionUtils.isEmpty(methodList)) {
+ return new EnumMvcConverterHolder(null);
+ }
+ Assert.isTrue(methodList.size() == 1, "@EnumConvertMethod 只能标记在一个工厂方法(静态方法)上");
+ Method method = methodList.get(0);
+ Assert.isTrue(Modifier.isStatic(method.getModifiers()), "@EnumConvertMethod 只能标记在工厂方法(静态方法)上");
+ return new EnumMvcConverterHolder(new EnumMvcConverter<>(method));
+ }
+
+ }
+
+ static class EnumMvcConverter> implements Converter {
+
+ private final Method method;
+
+ public EnumMvcConverter(Method method) {
+ this.method = method;
+ this.method.setAccessible(true);
+ }
+
+ @Override
+ public T convert(String source) {
+ if (source.isEmpty()) {
+ // reset the enum value to null.
+ return null;
+ }
+ try {
+ return (T) method.invoke(null, Integer.valueOf(source));
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ }
+
+
+}
diff --git a/swagger-demo/swagger-ui-demo/src/main/resources/application.yml b/swagger-demo/swagger-ui-demo/src/main/resources/application.yml
index be69f30d13f1f9298fb89d5ec46821c8499d9746..338b4ba6d827f1ebf6f1018d02eab8c927b6d4fc 100644
--- a/swagger-demo/swagger-ui-demo/src/main/resources/application.yml
+++ b/swagger-demo/swagger-ui-demo/src/main/resources/application.yml
@@ -1,2 +1,8 @@
server:
- port: 20201
\ No newline at end of file
+ port: 20201
+
+#spring:
+# jackson:
+# # 格式化返回时间 yyyy-MM-dd HH:mm:ss
+# date-format: yyyy-MM-dd HH:mm:ss
+# time-zone: GMT+8
\ No newline at end of file
diff --git a/swagger-demo/swagger-ui-demo/src/test/java/com/gsean/swaggerui/SwaggerUIApplicationTest.java b/swagger-demo/swagger-ui-demo/src/test/java/com/gsean/swaggerui/SwaggerUIApplicationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e32f1c7aa204161103ffa39f592e78505d1c7d43
--- /dev/null
+++ b/swagger-demo/swagger-ui-demo/src/test/java/com/gsean/swaggerui/SwaggerUIApplicationTest.java
@@ -0,0 +1,45 @@
+package com.gsean.swaggerui;
+
+import static org.junit.Assert.*;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.gsean.swaggerui.controller.HelloController;
+import com.gsean.swaggerui.enums.Status;
+import com.gsean.swaggerui.params.UserDTO;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @authoer Jincheng.Guo11
+ * @description
+ * @date:created in 2021/11/22 14:51
+ * @modificed by
+ **/
+@SpringBootTest
+@RunWith(SpringRunner.class)
+public class SwaggerUIApplicationTest {
+ @Autowired
+ private ObjectMapper objectMapper;
+
+
+
+
+ @Test
+ public void testA() throws Exception{
+ UserDTO gsean = new UserDTO().setId(1).setName("gsean").setStatus(Status.ACTIVE)
+ .setBirthDate(LocalDate.now()).setCreatedTime(
+ LocalDateTime.now());
+ //序列化测试
+ String jsonStr = objectMapper.writeValueAsString(gsean);
+ System.out.println(jsonStr);
+ UserDTO userDTO = objectMapper.readValue(jsonStr, UserDTO.class);
+ System.out.println(userDTO.getBirthDate());
+
+ }
+
+}
\ No newline at end of file