🎨 引入spring-java-format插件,代码格式管理

This commit is contained in:
b2baccline
2020-06-25 00:19:21 +08:00
parent 2b01fb6f5b
commit 89add5d79a
329 changed files with 6464 additions and 6260 deletions

View File

@@ -13,18 +13,24 @@ import java.util.List;
import java.util.Set;
/**
* @author lingting 2020/6/12 19:35
* @author lingting 2020/6/12 19:35
*/
@Getter
@Setter
@Accessors(chain = true)
public class DingTalkParams {
@JsonProperty("msgtype")
private String type;
private At at;
private ActionCard actionCard;
private Link link;
private Markdown markdown;
private Text text;
@Override
@@ -36,43 +42,64 @@ public class DingTalkParams {
@Data
@Accessors(chain = true)
public static class Text {
private String content;
}
@Data
@Accessors(chain = true)
public static class Markdown {
private String title;
private String text;
}
@Data
@Accessors(chain = true)
public static class Link {
private String text;
private String title;
private String picUrl;
private String messageUrl;
}
@Data
@Accessors(chain = true)
public static class ActionCard {
private String title;
private String text;
private String btnOrientation;
private String singleTitle;
@JsonProperty("singleURL")
private String singleUrl;
@JsonProperty("btns")
private List<DingTalkActionCardMessage.Button> buttons;
}
@Data
@Accessors(chain = true)
public static class At {
@JsonProperty("isAtAll")
private boolean atAll;
private Set<String> atMobiles;
}
}

View File

@@ -8,21 +8,26 @@ import lombok.Setter;
/**
* 钉钉返回信息
*
* @author lingting 2020/6/11 0:23
* @author lingting 2020/6/11 0:23
*/
@Getter
@Setter
public class DingTalkResponse {
public static final String SUCCESS_CODE = "0";
private String errCode;
/**
* 值为ok表示无异常
*/
private String errMsg;
/**
* 钉钉返回信息
*/
private String response;
/**
* 是否发送成功
*/
@@ -42,4 +47,5 @@ public class DingTalkResponse {
public String toString() {
return response;
}
}

View File

@@ -17,32 +17,34 @@ import java.nio.charset.StandardCharsets;
/**
* 订单消息发送
*
* @author lingting 2020/6/10 21:25
* @author lingting 2020/6/10 21:25
*/
@Data
@Accessors(chain = true)
@RequiredArgsConstructor
public class DingTalkSender {
/**
* 请求路径
*/
private final String url;
/**
* 密钥
*/
private String secret;
/**
* 发送消息
* 根据参数值判断使用哪种发送方式
* 发送消息 根据参数值判断使用哪种发送方式
*
* @author lingting 2020-06-11 00:05:51
* @author lingting 2020-06-11 00:05:51
*/
@SneakyThrows
public DingTalkResponse sendMessage(DingTalkMessage message) {
if (StrUtil.isEmpty(secret)) {
return sendNormalMessage(message);
} else {
}
else {
return sendSecretMessage(message);
}
}
@@ -50,16 +52,16 @@ public class DingTalkSender {
/**
* 未使用 加签 安全设置 直接发送
*
* @author lingting 2020-06-11 00:09:23
* @author lingting 2020-06-11 00:09:23
*/
public DingTalkResponse sendNormalMessage(DingTalkMessage message) {
return DingTalkResponse.getInstance(HttpUtil.post(url, message.generate()));
}
/**
* 使用 加签 安全设置 发送
* 使用 加签 安全设置 发送
*
* @author lingting 2020-06-11 00:10:38
* @author lingting 2020-06-11 00:10:38
*/
@SneakyThrows
public DingTalkResponse sendSecretMessage(DingTalkMessage message) {
@@ -69,7 +71,7 @@ public class DingTalkSender {
/**
* 获取签名后的请求路径
*
* @author lingting 2020-06-11 00:13:55
* @author lingting 2020-06-11 00:13:55
*/
@SneakyThrows
public String secret() {
@@ -81,4 +83,5 @@ public class DingTalkSender {
String encode = URLEncoder.encode(Base64.encode(signData), "UTF-8");
return url + "&timestamp=" + timestamp + "&sign=" + encode;
}
}

View File

@@ -4,19 +4,21 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 跳转 ActionCard 类型 消息的按钮排列方式
* 跳转 ActionCard 类型 消息的按钮排列方式
*
* @author lingting 2020/6/10 23:44
* @author lingting 2020/6/10 23:44
*/
@Getter
@AllArgsConstructor
public enum ActionBtnOrientationEnum {
/**
* 按钮排列样式值 说明
* 按钮排列样式值 说明
*/
VERTICAL("0", "按钮竖向排列"),
HORIZONTAL("1", "按钮横向排列"),
;
VERTICAL("0", "按钮竖向排列"), HORIZONTAL("1", "按钮横向排列"),;
private final String val;
private final String text;
}

View File

@@ -6,19 +6,20 @@ import lombok.Getter;
/**
* 钉钉消息类型
*
* @author lingting 2020/6/10 21:29
* @author lingting 2020/6/10 21:29
*/
@Getter
@AllArgsConstructor
public enum MessageTypeEnum {
/**
* 消息值 消息说明
* 消息值 消息说明
*/
TEXT("text", "文本"),
LINK("link", "链接"),
MARKDOWN("markdown", "markdown"),
ACTION_CARD("actionCard", "跳转 actionCard 类型"),
;
TEXT("text", "文本"), LINK("link", "链接"), MARKDOWN("markdown", "markdown"), ACTION_CARD("actionCard",
"跳转 actionCard 类型"),;
private final String val;
private final String desc;
}

View File

@@ -9,13 +9,15 @@ import java.util.Set;
/**
* 钉钉消息基础类
*
* @author lingting 2020/6/10 21:28
* @author lingting 2020/6/10 21:28
*/
public abstract class AbstractDingTalkMessage implements DingTalkMessage {
/**
* at 的人的手机号码
*/
private final Set<String> atPhones = new HashSet<>();
/**
* 是否 at 所有人
*/
@@ -29,7 +31,7 @@ public abstract class AbstractDingTalkMessage implements DingTalkMessage {
/**
* 添加 at 对象的手机号
*
* @author lingting 2020-06-10 21:57:08
* @author lingting 2020-06-10 21:57:08
*/
public AbstractDingTalkMessage addPhone(String phone) {
atPhones.add(phone);
@@ -38,28 +40,24 @@ public abstract class AbstractDingTalkMessage implements DingTalkMessage {
/**
* 获取消息类型
*
* @return 返回消息类型
* @author lingting 2020-06-10 22:12:30
* @author lingting 2020-06-10 22:12:30
*/
public abstract MessageTypeEnum getType();
/**
* 设置非公有属性
*
* @param params 已设置完公有参数的参数类
* @return 已设置完成的参数类
* @author lingting 2020-06-10 22:11:04
* @author lingting 2020-06-10 22:11:04
*/
public abstract DingTalkParams put(DingTalkParams params);
@Override
public String generate() {
DingTalkParams params = put(new DingTalkParams()
.setType(getType().getVal())
.setAt(new DingTalkParams.At().setAtAll(atAll).setAtMobiles(atPhones))
);
DingTalkParams params = put(new DingTalkParams().setType(getType().getVal())
.setAt(new DingTalkParams.At().setAtAll(atAll).setAtMobiles(atPhones)));
return params.toString();
}
}

View File

@@ -15,25 +15,30 @@ import java.util.List;
/**
* 跳转 ActionCard类型
*
* @author lingting 2020/6/10 23:39
* @author lingting 2020/6/10 23:39
*/
@Getter
@Setter
@Accessors(chain = true)
public class DingTalkActionCardMessage extends AbstractDingTalkMessage {
private String title;
/**
* 内容
*/
private MarkdownBuilder text;
/**
* 按钮排列样式 默认横
*/
private ActionBtnOrientationEnum orientation = ActionBtnOrientationEnum.HORIZONTAL;
/**
* 单个按钮的标题
*/
private String singleTitle;
/**
* 点击singleTitle按钮触发的URL
*/
@@ -47,7 +52,7 @@ public class DingTalkActionCardMessage extends AbstractDingTalkMessage {
/**
* 添加按钮
*
* @author lingting 2020-06-10 23:59:45
* @author lingting 2020-06-10 23:59:45
*/
public DingTalkActionCardMessage addButton(String title, String url) {
buttons.add(new Button(title, url));
@@ -61,15 +66,14 @@ public class DingTalkActionCardMessage extends AbstractDingTalkMessage {
@Override
public DingTalkParams put(DingTalkParams params) {
DingTalkParams.ActionCard card = new DingTalkParams.ActionCard()
.setTitle(title)
.setText(text.build())
DingTalkParams.ActionCard card = new DingTalkParams.ActionCard().setTitle(title).setText(text.build())
.setBtnOrientation(orientation.getVal());
// 当 单按钮的 文本和链接都不为空时
// 当 单按钮的 文本和链接都不为空时
if (buttons.size() == 0) {
card.setSingleTitle(singleTitle).setSingleUrl(singleUrl);
} else {
}
else {
card.setButtons(buttons);
}
return params.setActionCard(card);
@@ -78,13 +82,17 @@ public class DingTalkActionCardMessage extends AbstractDingTalkMessage {
@Getter
@AllArgsConstructor
public static class Button {
/**
* 标题
*/
private final String title;
/**
* 跳转路径
*/
private final String actionURL;
}
}

View File

@@ -7,24 +7,28 @@ import lombok.Setter;
import lombok.experimental.Accessors;
/**
* @author lingting 2020/6/10 22:13
* @author lingting 2020/6/10 22:13
*/
@Getter
@Setter
@Accessors(chain = true)
public class DingTalkLinkMessage extends AbstractDingTalkMessage {
/**
* 文本
*/
private String text;
/**
* 标题
*/
private String title;
/**
* 图片url
*/
private String picUrl;
/**
* 消息链接
*/
@@ -37,10 +41,8 @@ public class DingTalkLinkMessage extends AbstractDingTalkMessage {
@Override
public DingTalkParams put(DingTalkParams params) {
return params.setLink(new DingTalkParams.Link()
.setText(text)
.setTitle(title)
.setPicUrl(picUrl)
.setMessageUrl(messageUrl));
return params.setLink(
new DingTalkParams.Link().setText(text).setTitle(title).setPicUrl(picUrl).setMessageUrl(messageUrl));
}
}

View File

@@ -8,16 +8,18 @@ import lombok.Setter;
import lombok.experimental.Accessors;
/**
* @author lingting 2020/6/10 22:13
* @author lingting 2020/6/10 22:13
*/
@Getter
@Setter
@Accessors(chain = true)
public class DingTalkMarkDownMessage extends AbstractDingTalkMessage {
/**
* 标题
*/
private String title;
/**
* 内容
*/
@@ -32,4 +34,5 @@ public class DingTalkMarkDownMessage extends AbstractDingTalkMessage {
public DingTalkParams put(DingTalkParams params) {
return params.setMarkdown(new DingTalkParams.Markdown().setTitle(title).setText(text.build()));
}
}

View File

@@ -1,14 +1,15 @@
package com.hccake.extend.dingtalk.message;
/**
* @author lingting 2020/6/11 21:58
* @author lingting 2020/6/11 21:58
*/
public interface DingTalkMessage {
/**
* 生成钉钉消息发送参数
*
* @return 钉钉文档要求的 jsonString
* @author lingting 2020-06-12 19:56:54
* @author lingting 2020-06-12 19:56:54
*/
String generate();
}

View File

@@ -7,12 +7,13 @@ import lombok.Setter;
import lombok.experimental.Accessors;
/**
* @author lingting 2020/6/10 22:13
* @author lingting 2020/6/10 22:13
*/
@Getter
@Setter
@Accessors(chain = true)
public class DingTalkTextMessage extends AbstractDingTalkMessage {
/**
* 消息内容
*/
@@ -27,4 +28,5 @@ public class DingTalkTextMessage extends AbstractDingTalkMessage {
public DingTalkParams put(DingTalkParams params) {
return params.setText(new DingTalkParams.Text().setContent(content));
}
}

View File

@@ -26,13 +26,17 @@ import java.util.regex.Pattern;
/**
* kafka Stream 流构建方法
*
* @author lingting 2020/6/23 19:31
* @author lingting 2020/6/23 19:31
*/
public class KafkaStreamBuilder {
private static final String BOOTSTRAP_SERVERS_DELIMITER = ",";
@Getter
private Topology topology = new Topology();
private final Properties properties = new Properties();
private final Set<String> bootstrapServers = new HashSet<>();
public KafkaStreamBuilder keySerde(Class<? extends Serde<?>> c) {
@@ -52,9 +56,9 @@ public class KafkaStreamBuilder {
}
/**
* 添加 kafka 路径 host:port
* 添加 kafka 路径 host:port
*
* @author lingting 2020-06-19 16:30:03
* @author lingting 2020-06-19 16:30:03
*/
public KafkaStreamBuilder addBootstrapServers(String uri) {
bootstrapServers.add(uri);
@@ -69,7 +73,7 @@ public class KafkaStreamBuilder {
/**
* 添加配置
*
* @author lingting 2020-06-19 16:30:50
* @author lingting 2020-06-19 16:30:50
*/
public KafkaStreamBuilder put(Object key, Object val) {
properties.put(key, val);
@@ -79,7 +83,7 @@ public class KafkaStreamBuilder {
/**
* 添加配置
*
* @author lingting 2020-06-19 16:30:50
* @author lingting 2020-06-19 16:30:50
*/
public KafkaStreamBuilder putAll(Properties properties) {
this.properties.putAll(properties);
@@ -101,62 +105,76 @@ public class KafkaStreamBuilder {
return this;
}
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name, String... topics) {
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name,
String... topics) {
topology.addSource(offsetReset, name, topics);
return this;
}
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name, Pattern topicPattern) {
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name,
Pattern topicPattern) {
topology.addSource(offsetReset, name, topicPattern);
return this;
}
public synchronized KafkaStreamBuilder addSource(TimestampExtractor timestampExtractor, String name, String... topics) {
public synchronized KafkaStreamBuilder addSource(TimestampExtractor timestampExtractor, String name,
String... topics) {
topology.addSource(timestampExtractor, name, topics);
return this;
}
public synchronized KafkaStreamBuilder addSource(TimestampExtractor timestampExtractor, String name, Pattern topicPattern) {
public synchronized KafkaStreamBuilder addSource(TimestampExtractor timestampExtractor, String name,
Pattern topicPattern) {
topology.addSource(timestampExtractor, name, topicPattern);
return this;
}
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, TimestampExtractor timestampExtractor, String name, String... topics) {
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset,
TimestampExtractor timestampExtractor, String name, String... topics) {
topology.addSource(offsetReset, timestampExtractor, name, topics);
return this;
}
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, TimestampExtractor timestampExtractor, String name, Pattern topicPattern) {
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset,
TimestampExtractor timestampExtractor, String name, Pattern topicPattern) {
topology.addSource(offsetReset, timestampExtractor, name, topicPattern);
return this;
}
public synchronized KafkaStreamBuilder addSource(String name, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, String... topics) {
public synchronized KafkaStreamBuilder addSource(String name, Deserializer<?> keyDeserializer,
Deserializer<?> valueDeserializer, String... topics) {
topology.addSource(name, keyDeserializer, valueDeserializer, topics);
return this;
}
public synchronized KafkaStreamBuilder addSource(String name, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, Pattern topicPattern) {
public synchronized KafkaStreamBuilder addSource(String name, Deserializer<?> keyDeserializer,
Deserializer<?> valueDeserializer, Pattern topicPattern) {
topology.addSource(name, keyDeserializer, valueDeserializer, topicPattern);
return this;
}
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, String... topics) {
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name,
Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, String... topics) {
topology.addSource(offsetReset, name, keyDeserializer, valueDeserializer, topics);
return this;
}
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, Pattern topicPattern) {
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name,
Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, Pattern topicPattern) {
topology.addSource(offsetReset, name, keyDeserializer, valueDeserializer, topicPattern);
return this;
}
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name, TimestampExtractor timestampExtractor, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, String... topics) {
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name,
TimestampExtractor timestampExtractor, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer,
String... topics) {
topology.addSource(offsetReset, name, timestampExtractor, keyDeserializer, valueDeserializer, topics);
return this;
}
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name, TimestampExtractor timestampExtractor, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, Pattern topicPattern) {
public synchronized KafkaStreamBuilder addSource(Topology.AutoOffsetReset offsetReset, String name,
TimestampExtractor timestampExtractor, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer,
Pattern topicPattern) {
topology.addSource(offsetReset, name, timestampExtractor, keyDeserializer, valueDeserializer, topicPattern);
return this;
}
@@ -166,42 +184,51 @@ public class KafkaStreamBuilder {
return this;
}
public synchronized <K, V> KafkaStreamBuilder addSink(String name, String topic, StreamPartitioner<? super K, ? super V> partitioner, String... parentNames) {
public synchronized <K, V> KafkaStreamBuilder addSink(String name, String topic,
StreamPartitioner<? super K, ? super V> partitioner, String... parentNames) {
topology.addSink(name, topic, partitioner, parentNames);
return this;
}
public synchronized <K, V> KafkaStreamBuilder addSink(String name, String topic, Serializer<K> keySerializer, Serializer<V> valueSerializer, String... parentNames) {
public synchronized <K, V> KafkaStreamBuilder addSink(String name, String topic, Serializer<K> keySerializer,
Serializer<V> valueSerializer, String... parentNames) {
topology.addSink(name, topic, keySerializer, valueSerializer, parentNames);
return this;
}
public synchronized <K, V> KafkaStreamBuilder addSink(String name, String topic, Serializer<K> keySerializer, Serializer<V> valueSerializer, StreamPartitioner<? super K, ? super V> partitioner, String... parentNames) {
public synchronized <K, V> KafkaStreamBuilder addSink(String name, String topic, Serializer<K> keySerializer,
Serializer<V> valueSerializer, StreamPartitioner<? super K, ? super V> partitioner, String... parentNames) {
topology.addSink(name, topic, keySerializer, valueSerializer, partitioner, parentNames);
return this;
}
public synchronized <K, V> KafkaStreamBuilder addSink(String name, TopicNameExtractor<K, V> topicExtractor, String... parentNames) {
public synchronized <K, V> KafkaStreamBuilder addSink(String name, TopicNameExtractor<K, V> topicExtractor,
String... parentNames) {
topology.addSink(name, topicExtractor, parentNames);
return this;
}
public synchronized <K, V> KafkaStreamBuilder addSink(String name, TopicNameExtractor<K, V> topicExtractor, StreamPartitioner<? super K, ? super V> partitioner, String... parentNames) {
public synchronized <K, V> KafkaStreamBuilder addSink(String name, TopicNameExtractor<K, V> topicExtractor,
StreamPartitioner<? super K, ? super V> partitioner, String... parentNames) {
topology.addSink(name, topicExtractor, partitioner, parentNames);
return this;
}
public synchronized <K, V> KafkaStreamBuilder addSink(String name, TopicNameExtractor<K, V> topicExtractor, Serializer<K> keySerializer, Serializer<V> valueSerializer, String... parentNames) {
public synchronized <K, V> KafkaStreamBuilder addSink(String name, TopicNameExtractor<K, V> topicExtractor,
Serializer<K> keySerializer, Serializer<V> valueSerializer, String... parentNames) {
topology.addSink(name, topicExtractor, keySerializer, valueSerializer, parentNames);
return this;
}
public synchronized <K, V> KafkaStreamBuilder addSink(String name, TopicNameExtractor<K, V> topicExtractor, Serializer<K> keySerializer, Serializer<V> valueSerializer, StreamPartitioner<? super K, ? super V> partitioner, String... parentNames) {
public synchronized <K, V> KafkaStreamBuilder addSink(String name, TopicNameExtractor<K, V> topicExtractor,
Serializer<K> keySerializer, Serializer<V> valueSerializer,
StreamPartitioner<? super K, ? super V> partitioner, String... parentNames) {
topology.addSink(name, topicExtractor, keySerializer, valueSerializer, partitioner, parentNames);
return this;
}
public synchronized KafkaStreamBuilder addProcessor(String name, ProcessorSupplier<?, ?> supplier, String... parentNames) {
public synchronized KafkaStreamBuilder addProcessor(String name, ProcessorSupplier<?, ?> supplier,
String... parentNames) {
topology.addProcessor(name, supplier, parentNames);
return this;
}
@@ -211,17 +238,24 @@ public class KafkaStreamBuilder {
return this;
}
public synchronized KafkaStreamBuilder addGlobalStore(StoreBuilder<?> storeBuilder, String sourceName, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, String topic, String processorName, ProcessorSupplier<?, ?> stateUpdateSupplier) {
topology.addGlobalStore(storeBuilder, sourceName, keyDeserializer, valueDeserializer, topic, processorName, stateUpdateSupplier);
public synchronized KafkaStreamBuilder addGlobalStore(StoreBuilder<?> storeBuilder, String sourceName,
Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, String topic, String processorName,
ProcessorSupplier<?, ?> stateUpdateSupplier) {
topology.addGlobalStore(storeBuilder, sourceName, keyDeserializer, valueDeserializer, topic, processorName,
stateUpdateSupplier);
return this;
}
public synchronized KafkaStreamBuilder addGlobalStore(StoreBuilder<?> storeBuilder, String sourceName, TimestampExtractor timestampExtractor, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer, String topic, String processorName, ProcessorSupplier<?, ?> stateUpdateSupplier) {
topology.addGlobalStore(storeBuilder, sourceName, timestampExtractor, keyDeserializer, valueDeserializer, topic, processorName, stateUpdateSupplier);
public synchronized KafkaStreamBuilder addGlobalStore(StoreBuilder<?> storeBuilder, String sourceName,
TimestampExtractor timestampExtractor, Deserializer<?> keyDeserializer, Deserializer<?> valueDeserializer,
String topic, String processorName, ProcessorSupplier<?, ?> stateUpdateSupplier) {
topology.addGlobalStore(storeBuilder, sourceName, timestampExtractor, keyDeserializer, valueDeserializer, topic,
processorName, stateUpdateSupplier);
return this;
}
public synchronized KafkaStreamBuilder connectProcessorAndStateStores(String processorName, String... stateStoreNames) {
public synchronized KafkaStreamBuilder connectProcessorAndStateStores(String processorName,
String... stateStoreNames) {
topology.connectProcessorAndStateStores(processorName, stateStoreNames);
return this;
}
@@ -229,7 +263,7 @@ public class KafkaStreamBuilder {
/**
* 自定义的构筑方法, 传入 topology 和属性
*
* @author lingting 2020-06-23 20:24:52
* @author lingting 2020-06-23 20:24:52
*/
public KafkaStreams build(BiFunction<Topology, Properties, KafkaStreams> biFunction) {
return biFunction.apply(topology, getProperties());
@@ -254,8 +288,12 @@ public class KafkaStreamBuilder {
}
public Properties getProperties() {
bootstrapServers.addAll(ListUtil.toList(properties.getProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, StrUtil.EMPTY).split(BOOTSTRAP_SERVERS_DELIMITER)));
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, String.join(BOOTSTRAP_SERVERS_DELIMITER, bootstrapServers));
bootstrapServers
.addAll(ListUtil.toList(properties.getProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, StrUtil.EMPTY)
.split(BOOTSTRAP_SERVERS_DELIMITER)));
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
String.join(BOOTSTRAP_SERVERS_DELIMITER, bootstrapServers));
return properties;
}
}

View File

@@ -7,20 +7,19 @@ import org.apache.kafka.streams.state.KeyValueStore;
/**
* 所有 kafka 流处理执行相关类的顶级父类
*
* @author lingting 2020/6/22 11:02
* @author lingting 2020/6/22 11:02
*/
public abstract class AbstractKafka {
/**
* 获取上下文
*
* @return content
* @author lingting 2020-06-22 11:03:23
* @author lingting 2020-06-22 11:03:23
*/
public abstract ProcessorContext getContext();
/**
* 获取 KeyValueStore
*
* @return java.lang.String
* @author lingting 2020-06-22 09:57:37
*/

View File

@@ -15,10 +15,11 @@ import java.time.Duration;
/**
* kafka 顶级 processor 类
*
* @author lingting 2020/6/16 22:27
* @author lingting 2020/6/16 22:27
*/
@Slf4j
public abstract class AbstractProcessor<K, V> extends AbstractKafka implements Processor<K, V> {
@Getter
private ProcessorContext context;
@@ -29,10 +30,9 @@ public abstract class AbstractProcessor<K, V> extends AbstractKafka implements P
}
/**
* 用于初始化窗口的方法
* 子类如果需要 自己重写
* 用于初始化窗口的方法 子类如果需要 自己重写
*
* @author lingting 2020-06-17 10:44:39
* @author lingting 2020-06-17 10:44:39
*/
public void initSchedule(ProcessorContext context) {
@@ -41,7 +41,7 @@ public abstract class AbstractProcessor<K, V> extends AbstractKafka implements P
/**
* 用于构筑 Punctuator
*
* @author lingting 2020-06-21 13:58:34
* @author lingting 2020-06-21 13:58:34
*/
public void schedule(Duration interval, PunctuationType type, AbstractPunctuator callback) {
context.schedule(interval, type, callback);
@@ -50,7 +50,7 @@ public abstract class AbstractProcessor<K, V> extends AbstractKafka implements P
/**
* 用于构筑 {@link PunctuationType#WALL_CLOCK_TIME} 类型的 Punctuator
*
* @author lingting 2020-06-21 13:58:53
* @author lingting 2020-06-21 13:58:53
*/
public void schedule(Duration interval, AbstractPunctuator callback) {
schedule(interval, PunctuationType.WALL_CLOCK_TIME, callback);
@@ -58,11 +58,10 @@ public abstract class AbstractProcessor<K, V> extends AbstractKafka implements P
/**
* 下发数据
*
* @param key key
* @param value value
* @param key key
* @param value value
* @param childName 目标名称
* @author lingting 2020-06-17 19:44:45
* @author lingting 2020-06-17 19:44:45
*/
public <KEY, VALUE> void forward(KEY key, VALUE value, String childName) {
context.forward(key, value, To.child(childName));
@@ -70,10 +69,9 @@ public abstract class AbstractProcessor<K, V> extends AbstractKafka implements P
/**
* 下发数据
*
* @param key key
* @param key key
* @param value value
* @param to 目标
* @param to 目标
* @author lingting 2020-06-17 19:47:55
*/
public <KEY, VALUE> void forward(KEY key, VALUE value, To to) {
@@ -94,12 +92,14 @@ public abstract class AbstractProcessor<K, V> extends AbstractKafka implements P
try {
startLog(key, value);
process(context, key, value);
} catch (Exception e) {
}
catch (Exception e) {
errLog(e);
String errStr;
try {
errStr = new ObjectMapper().writeValueAsString(value);
} catch (Exception ex) {
}
catch (Exception ex) {
log.error("数据转json出错!msg: {}", ex.getMessage());
errStr = Convert.toStr(value);
}
@@ -109,10 +109,9 @@ public abstract class AbstractProcessor<K, V> extends AbstractKafka implements P
/**
* Process the record with the given key and value.
*
* @param context 上下文
* @param key the key for the record
* @param value the value for the record
* @param key the key for the record
* @param value the value for the record
*/
public abstract void process(ProcessorContext context, K key, V value);
@@ -122,4 +121,5 @@ public abstract class AbstractProcessor<K, V> extends AbstractKafka implements P
@Override
public void close() {
}
}

View File

@@ -10,10 +10,11 @@ import org.apache.kafka.streams.processor.Punctuator;
/**
* kafka 顶级 punctuator 类
*
* @author lingting 2020/6/17 14:02
* @author lingting 2020/6/17 14:02
*/
@Slf4j
public abstract class AbstractPunctuator extends AbstractKafka implements Punctuator {
@Getter
private ProcessorContext context;
@@ -24,7 +25,6 @@ public abstract class AbstractPunctuator extends AbstractKafka implements Punctu
/**
* 是否处理数据, 如果想依据条件执行,需要自己重写当前方法
*
* @return boolean true 表示有参数,可以执行处理
* @author lingting 2020-06-17 14:05:01
*/
@@ -42,7 +42,7 @@ public abstract class AbstractPunctuator extends AbstractKafka implements Punctu
/**
* handle 开始日志
*
* @author lingting 2020-06-21 18:34:15
* @author lingting 2020-06-21 18:34:15
*/
public void startLog() {
log.debug("任务开始执行, 类名 {} ,{}", this.getClass().getSimpleName(), ProcessorContextUtil.toLogString(context));
@@ -50,21 +50,22 @@ public abstract class AbstractPunctuator extends AbstractKafka implements Punctu
/**
* handle 结束日志
*
* @param time 执行时长 单位 毫秒
* @author lingting 2020-06-21 16:39:16
* @param time 执行时长 单位 毫秒
* @author lingting 2020-06-21 16:39:16
*/
public void endLog(long time) {
log.debug("任务执行时长: {}, 类名 {}, {} ", time, this.getClass().getSimpleName(), ProcessorContextUtil.toLogString(context));
log.debug("任务执行时长: {}, 类名 {}, {} ", time, this.getClass().getSimpleName(),
ProcessorContextUtil.toLogString(context));
}
/**
* 异常日志
*
* @author lingting 2020-06-22 19:50:16
* @author lingting 2020-06-22 19:50:16
*/
public void errLog(Throwable e) {
log.error("punctuator 操作数据出错 类名 " + this.getClass().getSimpleName() + ", " + ProcessorContextUtil.toLogString(context), e);
log.error("punctuator 操作数据出错 类名 " + this.getClass().getSimpleName() + ", "
+ ProcessorContextUtil.toLogString(context), e);
}
@Override
@@ -79,16 +80,17 @@ public abstract class AbstractPunctuator extends AbstractKafka implements Punctu
clean();
context.commit();
}
} catch (Exception e) {
}
catch (Exception e) {
errLog(e);
}
}
/**
* 处理聚合的数据
*
* @param timestamp 时间戳
* @author lingting 2020-06-17 14:06:25
*/
public abstract void handle(long timestamp);
}

View File

@@ -14,17 +14,16 @@ import java.util.List;
import java.util.function.BiFunction;
/**
* kafka 扩展类
* 自动注入 指定类型 指定名称的 store
* Value 数据的类型
* Values 存放数据的对象类型
* kafka 扩展类 自动注入 指定类型 指定名称的 store Value 数据的类型 Values 存放数据的对象类型
*
* @author lingting 2020/6/19 10:21
* @author lingting 2020/6/19 10:21
*/
@Slf4j
public abstract class AbstractKeyValueStorePunctuator<K, V, R> extends AbstractPunctuator {
@Getter
private KafkaKeyValueStore<K, V> store;
/**
* 用来处理单个值得函数
*/
@@ -33,10 +32,12 @@ public abstract class AbstractKeyValueStorePunctuator<K, V, R> extends AbstractP
@Override
@Deprecated
public AbstractKeyValueStorePunctuator<K, V, R> init(ProcessorContext context) {
throw new RuntimeException("继承自 com.hccake.extend.kafka.stream.extend.AbstractKeyValueStorePunctuator 的类禁止使用当前方法进行初始化!");
throw new RuntimeException(
"继承自 com.hccake.extend.kafka.stream.extend.AbstractKeyValueStorePunctuator 的类禁止使用当前方法进行初始化!");
}
public AbstractKeyValueStorePunctuator<K, V, R> init(ProcessorContext context, String storeName, BiFunction<K, V, R> signHandle) {
public AbstractKeyValueStorePunctuator<K, V, R> init(ProcessorContext context, String storeName,
BiFunction<K, V, R> signHandle) {
super.init(context);
store = getStore(storeName);
this.signHandle = signHandle;
@@ -46,7 +47,7 @@ public abstract class AbstractKeyValueStorePunctuator<K, V, R> extends AbstractP
/**
* 获取单批量处理数量
*
* @author lingting 2020-06-22 15:37:10
* @author lingting 2020-06-22 15:37:10
*/
public long getHandleSize() {
return 1000;
@@ -71,10 +72,9 @@ public abstract class AbstractKeyValueStorePunctuator<K, V, R> extends AbstractP
/**
* 执行数据处理方法
*
* @param list 数据
* @param list 数据
* @param timestamp 时间戳
* @author lingting 2020-06-22 19:51:56
* @author lingting 2020-06-22 19:51:56
*/
public void runHandle(long timestamp, List<R> list) {
try {
@@ -82,11 +82,14 @@ public abstract class AbstractKeyValueStorePunctuator<K, V, R> extends AbstractP
log.debug("任务执行中,类名 {}, 操作数据量: {}", this.getClass().getSimpleName(), list.size());
handle(timestamp, list);
}
} catch (Exception e) {
}
catch (Exception e) {
errLog(e);
try {
log.error("时间戳: {}, 类名: {}, 异常数据: {}", timestamp, this.getClass().getName(), new ObjectMapper().writeValueAsString(list));
} catch (Exception exception) {
log.error("时间戳: {}, 类名: {}, 异常数据: {}", timestamp, this.getClass().getName(),
new ObjectMapper().writeValueAsString(list));
}
catch (Exception exception) {
log.error("记录异常数据出错! 时间戳: {}, 类名: {}", timestamp, this.getClass().getName());
log.error("数据转换异常! ", exception);
}
@@ -95,9 +98,8 @@ public abstract class AbstractKeyValueStorePunctuator<K, V, R> extends AbstractP
/**
* 批量处理数据
*
* @param timestamp 时间戳
* @param list 当前批数据
* @param list 当前批数据
* @author lingting 2020-06-22 15:35:38
*/
public abstract void handle(long timestamp, List<R> list);
@@ -106,4 +108,5 @@ public abstract class AbstractKeyValueStorePunctuator<K, V, R> extends AbstractP
public void clean() {
}
}

View File

@@ -5,9 +5,10 @@ import lombok.extern.slf4j.Slf4j;
/**
* String String 类型的 store
*
* @author lingting 2020/6/19 10:21
* @author lingting 2020/6/19 10:21
*/
@Slf4j
public abstract class AbstractStringStringStorePunctuator<R> extends AbstractKeyValueStorePunctuator<String, String, R> {
public abstract class AbstractStringStringStorePunctuator<R>
extends AbstractKeyValueStorePunctuator<String, String, R> {
}

View File

@@ -14,10 +14,12 @@ import java.util.function.Supplier;
/**
* 使用 {@link KeyValueStore} 为具体实现的kafka数据缓存方法
*
* @author lingting 2020/6/22 10:24
* @author lingting 2020/6/22 10:24
*/
public class KafkaKeyValueStore<K, V> implements KafkaWindow<V, KeyValueStore<K, V>> {
private KeyValueStore<K, V> store;
private Supplier<K> supplier;
private KafkaKeyValueStore() {
@@ -30,7 +32,7 @@ public class KafkaKeyValueStore<K, V> implements KafkaWindow<V, KeyValueStore<K,
/**
* @param supplier 生成key的方式
* @author lingting 2020-06-22 10:43:34
* @author lingting 2020-06-22 10:43:34
*/
public static <K, V> KafkaKeyValueStore<K, V> init(KeyValueStore<K, V> store, Supplier<K> supplier) {
KafkaKeyValueStore<K, V> keyValueStore = new KafkaKeyValueStore<>();
@@ -63,12 +65,10 @@ public class KafkaKeyValueStore<K, V> implements KafkaWindow<V, KeyValueStore<K,
return list;
}
/**
* 获取插入数据的key
*
* @return 生成的key
* @author lingting 2020-06-22 10:14:15
* @author lingting 2020-06-22 10:14:15
*/
public K getKey() {
return supplier.get();
@@ -98,8 +98,7 @@ public class KafkaKeyValueStore<K, V> implements KafkaWindow<V, KeyValueStore<K,
/**
* 直接插入数据
*
* @param v 值
* @param v 值
* @param kvKeyValueStore 目标
* @author lingting 2020-06-22 10:36:53
*/
@@ -115,4 +114,5 @@ public class KafkaKeyValueStore<K, V> implements KafkaWindow<V, KeyValueStore<K,
public V delete(K key) {
return store.delete(key);
}
}

View File

@@ -4,71 +4,68 @@ import cn.hutool.core.util.StrUtil;
/**
* kafka 数据缓存类的接口
* @author lingting 2020/6/22 10:32
*
* @author lingting 2020/6/22 10:32
*/
public interface KafkaWindow<Value, Values> {
/**
* 数据通过校验才插入
*
* @param values 目标
* @param value 值
* @author lingting 2020-06-19 10:27:30
*/
default void pushValue(Value value, Values values) {
if (check(value)) {
forkPush(value, values);
}
}
/**
* 数据通过校验才插入
* @param values 目标
* @param value 值
* @author lingting 2020-06-19 10:27:30
*/
default void pushValue(Value value, Values values) {
if (check(value)) {
forkPush(value, values);
}
}
/**
* 插入多个数据
*
* @param values 插入目标
* @param iterable 需要插入的多个值
* @author lingting 2020-06-19 11:05:00
*/
default void pushAll(Iterable<Value> iterable, Values values) {
for (Value v : iterable) {
pushValue(v, values);
}
}
/**
* 插入多个数据
* @param values 插入目标
* @param iterable 需要插入的多个值
* @author lingting 2020-06-19 11:05:00
*/
default void pushAll(Iterable<Value> iterable, Values values) {
for (Value v : iterable) {
pushValue(v, values);
}
}
/**
* 直接插入数据
*
* @param value 数据
* @param values 存放所有数据的对象
* @author lingting 2020-06-19 10:25:24
*/
void forkPush(Value value, Values values);
/**
* 直接插入数据
* @param value 数据
* @param values 存放所有数据的对象
* @author lingting 2020-06-19 10:25:24
*/
void forkPush(Value value, Values values);
/**
* 校验 value 是否可以插入
*
* @param value 数据
* @return boolean true 可以插入
* @author lingting 2020-06-19 10:27:17
*/
default boolean check(Value value) {
if (!isInsertNull()) {
// 不能插入空值,进行校验
if (value instanceof String && StrUtil.isEmpty((String) value)) {
// 空值, 结束方法
return false;
}
return value != null;
}
return true;
}
/**
* 校验 value 是否可以插入
* @param value 数据
* @return boolean true 可以插入
* @author lingting 2020-06-19 10:27:17
*/
default boolean check(Value value) {
if (!isInsertNull()) {
// 不能插入空值,进行校验
if (value instanceof String && StrUtil.isEmpty((String) value)) {
// 空值, 结束方法
return false;
}
return value != null;
}
return true;
}
/**
* 是否可以插入空值
* @return true 可以插入空值
* @author lingting 2020-06-19 10:28:52
*/
default boolean isInsertNull() {
return false;
}
/**
* 是否可以插入空值
*
* @return true 可以插入空值
* @author lingting 2020-06-19 10:28:52
*/
default boolean isInsertNull() {
return false;
}
}

View File

@@ -6,7 +6,7 @@ import org.apache.kafka.streams.processor.internals.ProcessorContextImpl;
/**
* kafka 上下文工具类
*
* @author lingting 2020/6/23 18:00
* @author lingting 2020/6/23 18:00
*/
public class ProcessorContextUtil {
@@ -15,9 +15,8 @@ public class ProcessorContextUtil {
if (context instanceof ProcessorContextImpl) {
res += " currentNode.name: " + ((ProcessorContextImpl) context).currentNode().name();
}
res += " topic: " + context.topic() +
" offset: " + context.offset() +
" taskId: " + context.taskId();
res += " topic: " + context.topic() + " offset: " + context.offset() + " taskId: " + context.taskId();
return res;
}
}

View File

@@ -1,8 +1,10 @@
package com.hccake.extend.kafka;
/**
* @author lingting 2020/6/19 16:48
* @author lingting 2020/6/19 16:48
*/
public class KafkaConstants {
public static final String BOOTSTRAP_SERVERS_DELIMITER = ",";
}

View File

@@ -17,16 +17,17 @@ import java.util.function.Function;
import static com.hccake.extend.kafka.KafkaConstants.BOOTSTRAP_SERVERS_DELIMITER;
/**
* 消费者
* 具体的配置请参考 {@link ConsumerConfig}
* 这里只提供一些常用配置
* 消费者 具体的配置请参考 {@link ConsumerConfig} 这里只提供一些常用配置
*
* @author lingting 2020/5/19 20:56
* @author lingting 2020/5/19 20:56
*/
@Slf4j
public class KafkaConsumerBuilder {
private final Properties properties = new Properties();
private final Set<String> bootstrapServers = new HashSet<>();
@Getter
private final Set<String> topics = new HashSet<>();
@@ -47,9 +48,9 @@ public class KafkaConsumerBuilder {
}
/**
* 添加 kafka 路径 host:port
* 添加 kafka 路径 host:port
*
* @author lingting 2020-06-19 16:30:03
* @author lingting 2020-06-19 16:30:03
*/
public KafkaConsumerBuilder addBootstrapServers(String uri) {
bootstrapServers.add(uri);
@@ -64,7 +65,7 @@ public class KafkaConsumerBuilder {
/**
* 添加配置
*
* @author lingting 2020-06-19 16:30:50
* @author lingting 2020-06-19 16:30:50
*/
public KafkaConsumerBuilder put(Object key, Object val) {
properties.put(key, val);
@@ -74,7 +75,7 @@ public class KafkaConsumerBuilder {
/**
* 添加配置
*
* @author lingting 2020-06-19 16:30:50
* @author lingting 2020-06-19 16:30:50
*/
public KafkaConsumerBuilder putAll(Properties properties) {
this.properties.putAll(properties);
@@ -84,7 +85,7 @@ public class KafkaConsumerBuilder {
/**
* 组id
*
* @author lingting 2020-06-19 16:46:32
* @author lingting 2020-06-19 16:46:32
*/
public KafkaConsumerBuilder groupId(String groupId) {
return put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
@@ -120,8 +121,12 @@ public class KafkaConsumerBuilder {
}
public Properties getProperties() {
bootstrapServers.addAll(ListUtil.toList(properties.getProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, StrUtil.EMPTY).split(BOOTSTRAP_SERVERS_DELIMITER)));
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, String.join(BOOTSTRAP_SERVERS_DELIMITER, bootstrapServers));
bootstrapServers
.addAll(ListUtil.toList(properties.getProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, StrUtil.EMPTY)
.split(BOOTSTRAP_SERVERS_DELIMITER)));
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
String.join(BOOTSTRAP_SERVERS_DELIMITER, bootstrapServers));
return properties;
}
}

View File

@@ -10,12 +10,12 @@ import org.apache.kafka.common.header.Header;
import java.util.concurrent.Future;
/**
* 生产者扩展
* 提供了一些更加方便使用 生产者的方法
* 生产者扩展 提供了一些更加方便使用 生产者的方法
*
* @author lingting 2020/6/23 17:11
* @author lingting 2020/6/23 17:11
*/
public class KafkaExtendProducer<K, V> {
@Getter
private final KafkaProducer<K, V> producer;
@@ -23,7 +23,8 @@ public class KafkaExtendProducer<K, V> {
this.producer = producer;
}
public ProducerRecord<K, V> record(String topic, Integer partition, Long timestamp, K key, V value, Iterable<Header> headers) {
public ProducerRecord<K, V> record(String topic, Integer partition, Long timestamp, K key, V value,
Iterable<Header> headers) {
return new ProducerRecord<>(topic, partition, timestamp, key, value, headers);
}
@@ -51,7 +52,8 @@ public class KafkaExtendProducer<K, V> {
return producer.send(record, callback);
}
public Future<RecordMetadata> send(String topic, Integer partition, Long timestamp, K key, V value, Iterable<Header> headers) {
public Future<RecordMetadata> send(String topic, Integer partition, Long timestamp, K key, V value,
Iterable<Header> headers) {
return send(record(topic, partition, timestamp, key, value, headers), null);
}
@@ -78,4 +80,5 @@ public class KafkaExtendProducer<K, V> {
public Future<RecordMetadata> send(String topic, V value, Callback callback) {
return send(record(topic, value), callback);
}
}

View File

@@ -16,15 +16,15 @@ import java.util.function.Function;
import static com.hccake.extend.kafka.KafkaConstants.BOOTSTRAP_SERVERS_DELIMITER;
/**
* 生产者
* 具体的配置请参考 {@link ProducerConfig}
* 这里只提供一些常用配置
* 生产者 具体的配置请参考 {@link ProducerConfig} 这里只提供一些常用配置
*
* @author lingting 2020/5/19 20:56
* @author lingting 2020/5/19 20:56
*/
@Slf4j
public class KafkaProducerBuilder {
private final Properties properties = new Properties();
private final Set<String> bootstrapServers = new HashSet<>();
public KafkaProducerBuilder keySerializer(Class<? extends Serializer<?>> c) {
@@ -44,9 +44,9 @@ public class KafkaProducerBuilder {
}
/**
* 添加 kafka 路径 host:port
* 添加 kafka 路径 host:port
*
* @author lingting 2020-06-19 16:30:03
* @author lingting 2020-06-19 16:30:03
*/
public KafkaProducerBuilder addBootstrapServers(String uri) {
bootstrapServers.add(uri);
@@ -61,7 +61,7 @@ public class KafkaProducerBuilder {
/**
* 添加配置
*
* @author lingting 2020-06-19 16:30:50
* @author lingting 2020-06-19 16:30:50
*/
public KafkaProducerBuilder put(Object key, Object val) {
properties.put(key, val);
@@ -71,7 +71,7 @@ public class KafkaProducerBuilder {
/**
* 添加配置
*
* @author lingting 2020-06-19 16:30:50
* @author lingting 2020-06-19 16:30:50
*/
public KafkaProducerBuilder putAll(Properties properties) {
this.properties.putAll(properties);
@@ -96,8 +96,12 @@ public class KafkaProducerBuilder {
}
public Properties getProperties() {
bootstrapServers.addAll(ListUtil.toList(properties.getProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, StrUtil.EMPTY).split(BOOTSTRAP_SERVERS_DELIMITER)));
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, String.join(BOOTSTRAP_SERVERS_DELIMITER, bootstrapServers));
bootstrapServers
.addAll(ListUtil.toList(properties.getProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, StrUtil.EMPTY)
.split(BOOTSTRAP_SERVERS_DELIMITER)));
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
String.join(BOOTSTRAP_SERVERS_DELIMITER, bootstrapServers));
return properties;
}
}

View File

@@ -5,29 +5,26 @@ import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;
/**
* @author lingting 2020/6/23 17:07
* @author lingting 2020/6/23 17:07
*/
public class KafkaTest {
public static void main(String[] args) {
// KafkaProducer<String, String> producer = new KafkaProducerBuilder()
KafkaConsumer<Object, Object> consumer = new KafkaConsumerBuilder()
.keyDeserializer(StringDeserializer.class)
.valueDeserializer(StringDeserializer.class)
.groupId("group-id")
.addTopic("first")
// .keySerializer(StringSerializer.class)
// .valueSerializer(StringSerializer.class)
.addBootstrapServers("192.168.1.3:50211")
.addBootstrapServers("192.168.1.3:50212")
.build();
// producer.send("first", "测试消息");
// while (true) {
// ConsumerRecords<Object, Object> records = consumer.poll(Duration.ofSeconds(5));
// records.forEach(record -> {
// System.out.println(record.key());
// System.out.println(record.value());
// });
// }
public static void main(String[] args) {
// KafkaProducer<String, String> producer = new KafkaProducerBuilder()
KafkaConsumer<Object, Object> consumer = new KafkaConsumerBuilder().keyDeserializer(StringDeserializer.class)
.valueDeserializer(StringDeserializer.class).groupId("group-id").addTopic("first")
// .keySerializer(StringSerializer.class)
// .valueSerializer(StringSerializer.class)
.addBootstrapServers("192.168.1.3:50211").addBootstrapServers("192.168.1.3:50212").build();
// producer.send("first", "测试消息");
// while (true) {
// ConsumerRecords<Object, Object> records = consumer.poll(Duration.ofSeconds(5));
// records.forEach(record -> {
// System.out.println(record.key());
// System.out.println(record.value());
// });
// }
}
}

View File

@@ -17,19 +17,23 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* 用于mybatis 自定义的 列
*
* @author lingting 2020/5/27 15:53
* @author lingting 2020/5/27 15:53
*/
@Getter
public class Columns<T> {
public static final String COLUMN_FLAG = "@";
/**
* 缓存 全类名 方法名 字段名
* 缓存 全类名 方法名 字段名
*/
private static final Map<String, ConcurrentHashMap<String, String>> COLUMN_CACHE_MAP = new ConcurrentHashMap<>();
/**
* 自定义字段
*/
private final List<Column> list = new ArrayList<>();
/**
* 类的所有字段
*/
@@ -68,8 +72,8 @@ public class Columns<T> {
}
/**
* @param val 自定义的替换sql {@link Columns#COLUMN_FLAG} 表示字段名
* @author lingting 2020-05-27 17:57:35
* @param val 自定义的替换sql {@link Columns#COLUMN_FLAG} 表示字段名
* @author lingting 2020-05-27 17:57:35
*/
public Columns<T> add(SFunction<T, ?> sf, String val) {
String column = getColumn(sf);
@@ -77,10 +81,7 @@ public class Columns<T> {
val = "VALUES(" + column + ")";
}
list.add(new Column()
.setName(column)
.setVal(val.replaceAll(COLUMN_FLAG, column))
);
list.add(new Column().setName(column).setVal(val.replaceAll(COLUMN_FLAG, column)));
back.remove(column);
return this;
}
@@ -88,13 +89,14 @@ public class Columns<T> {
/**
* 获取方法所代表的表的字段名
*
* @author lingting 2020-05-27 17:56:40
* @author lingting 2020-05-27 17:56:40
*/
public String getColumn(SFunction<T, ?> sf) {
SerializedLambda lambda = SerializedLambda.resolve(sf);
if (!COLUMN_CACHE_MAP.containsKey(lambda.getImplClass().getName())) {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(LambdaUtils.getColumnMap(lambda.getImplClass()).size());
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(
LambdaUtils.getColumnMap(lambda.getImplClass()).size());
LambdaUtils.getColumnMap(lambda.getImplClass()).forEach((k, v) -> {
map.put(k, v.getColumn());
});
@@ -115,7 +117,7 @@ public class Columns<T> {
/**
* 忽略设置的字段
*
* @author lingting 2020-05-28 11:06:15
* @author lingting 2020-05-28 11:06:15
*/
public Columns<T> ignore() {
this.ignore = true;
@@ -125,7 +127,7 @@ public class Columns<T> {
/**
* 设置不忽略设置的字段
*
* @author lingting 2020-05-28 11:05:59
* @author lingting 2020-05-28 11:05:59
*/
public Columns<T> set() {
this.ignore = false;
@@ -135,8 +137,11 @@ public class Columns<T> {
@Data
@Accessors(chain = true)
public static class Column {
private String name;
private String val;
}
}
private String name;
private String val;
}
}

View File

@@ -9,17 +9,14 @@ import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 所有的 Mapper接口 都需要继承当前接口
* 如果想自己定义其他的全局方法, 您的全局 BaseMapper 需要继承当前接口
* 所有的 Mapper接口 都需要继承当前接口 如果想自己定义其他的全局方法, 您的全局 BaseMapper 需要继承当前接口
*
* @author lingting 2020/5/27 11:39
* @author lingting 2020/5/27 11:39
*/
public interface ExtendBaseMapper<T> extends com.baomidou.mybatisplus.core.mapper.BaseMapper<T> {
/**
* 批处理 如果重复则忽略
* 实现类 {@link InsertIgnoreByBatch}
*
* 批处理 如果重复则忽略 实现类 {@link InsertIgnoreByBatch}
* @param list 值列表
* @return int
* @author lingting 2020-05-27 11:41:28
@@ -27,10 +24,8 @@ public interface ExtendBaseMapper<T> extends com.baomidou.mybatisplus.core.mappe
int insertIgnoreByBatch(@Param("list") List<T> list);
/**
* 批处理 如果重复则更新
* 实现类 {@link InsertOrUpdateByBatch}
*
* @param list 值列表
* 批处理 如果重复则更新 实现类 {@link InsertOrUpdateByBatch}
* @param list 值列表
* @param ignore 是否忽略全局配置的忽略字段 {@link StaticConfig#UPDATE_IGNORE_FIELDS}
* @return int
* @author lingting 2020-05-27 11:41:28
@@ -39,7 +34,6 @@ public interface ExtendBaseMapper<T> extends com.baomidou.mybatisplus.core.mappe
/**
* 批处理 如果重复则更新 直接调用本方法会 忽略全局配置的忽略字段 {@link StaticConfig#UPDATE_IGNORE_FIELDS}
*
* @param list 值列表
* @return int
* @author lingting 2020-05-27 11:41:28
@@ -49,15 +43,13 @@ public interface ExtendBaseMapper<T> extends com.baomidou.mybatisplus.core.mappe
}
/**
* 自定义 如果重复 需要更新的 field
* 当传入的 columns.ignore 属性为 true时
* 会使用您传入的 字段值 去覆盖 不在 columns.list 中 字段 的值
* 实现类 {@link InsertOrUpdateFieldByBatch}
*
* @param list 值列表
* 自定义 如果重复 需要更新的 field 当传入的 columns.ignore 属性为 true时 会使用您传入的 字段值 去覆盖 不在 columns.list
* 中 字段 的值 实现类 {@link InsertOrUpdateFieldByBatch}
* @param list 值列表
* @param columns 字段
* @return int
* @author lingting 2020-05-27 15:48:20
*/
int insertOrUpdateFieldByBatch(@Param("list") List<T> list, @Param("columns") Columns<T> columns);
}

View File

@@ -11,7 +11,7 @@ import java.util.List;
import java.util.Set;
/**
* @author lingting 2020/5/27 11:43
* @author lingting 2020/5/27 11:43
*/
@Configuration
public class MybatisConfig implements MybatisConfigurer {
@@ -27,4 +27,5 @@ public class MybatisConfig implements MybatisConfigurer {
list.add(new InsertOrUpdateByBatch());
list.add(new InsertOrUpdateFieldByBatch());
}
}

View File

@@ -9,59 +9,56 @@ import org.apache.ibatis.mapping.SqlSource;
/**
* 所有插入自定义方法的父类
*
* @author lingting 2020/5/27 15:14
* @author lingting 2020/5/27 15:14
*/
public abstract class BaseInsertBatch extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlSource sqlSource = languageDriver.createSqlSource(configuration,
String.format(getSql(), tableInfo.getTableName(),
prepareFieldSql(tableInfo),
prepareValuesSqlForMysqlBatch(tableInfo)
),
modelClass);
return this.addInsertMappedStatement(mapperClass, modelClass, getId(), sqlSource, new NoKeyGenerator(), null, null);
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlSource sqlSource = languageDriver.createSqlSource(configuration, String.format(getSql(),
tableInfo.getTableName(), prepareFieldSql(tableInfo), prepareValuesSqlForMysqlBatch(tableInfo)),
modelClass);
return this.addInsertMappedStatement(mapperClass, modelClass, getId(), sqlSource, new NoKeyGenerator(), null,
null);
}
protected String prepareFieldSql(TableInfo tableInfo) {
StringBuilder fieldSql = new StringBuilder();
fieldSql.append(tableInfo.getKeyColumn()).append(",");
tableInfo.getFieldList().forEach(x -> fieldSql.append(x.getColumn()).append(","));
fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
fieldSql.insert(0, "(");
fieldSql.append(")");
return fieldSql.toString();
}
protected String prepareFieldSql(TableInfo tableInfo) {
StringBuilder fieldSql = new StringBuilder();
fieldSql.append(tableInfo.getKeyColumn()).append(",");
tableInfo.getFieldList().forEach(x -> fieldSql.append(x.getColumn()).append(","));
fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
fieldSql.insert(0, "(");
fieldSql.append(")");
return fieldSql.toString();
}
/**
* 获取注册的脚本
*
* @return java.lang.String
* @author lingting 2020-06-09 20:38:54
*/
abstract protected String getSql();
/**
* 获取注册的脚本
* @return java.lang.String
* @author lingting 2020-06-09 20:38:54
*/
abstract protected String getSql();
/**
* 获取脚本id 即 方法名
*
* @return java.lang.String
* @author lingting 2020-06-09 20:39:30
*/
abstract protected String getId();
/**
* 获取脚本id 即 方法名
* @return java.lang.String
* @author lingting 2020-06-09 20:39:30
*/
abstract protected String getId();
protected String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) {
return prepareValuesBuildSqlForMysqlBatch(tableInfo).toString();
}
protected String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) {
return prepareValuesBuildSqlForMysqlBatch(tableInfo).toString();
}
protected StringBuilder prepareValuesBuildSqlForMysqlBatch(TableInfo tableInfo) {
final StringBuilder valueSql = new StringBuilder();
valueSql.append(
"<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
valueSql.delete(valueSql.length() - 1, valueSql.length());
valueSql.append("</foreach>");
return valueSql;
}
protected StringBuilder prepareValuesBuildSqlForMysqlBatch(TableInfo tableInfo) {
final StringBuilder valueSql = new StringBuilder();
valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
valueSql.delete(valueSql.length() - 1, valueSql.length());
valueSql.append("</foreach>");
return valueSql;
}
}

View File

@@ -1,16 +1,18 @@
package com.hccake.extend.mybatis.plus.mysql.methods;
/**
* @author lingting 2020/5/27 11:47
* @author lingting 2020/5/27 11:47
*/
public class InsertIgnoreByBatch extends BaseInsertBatch {
@Override
protected String getSql() {
return "<script>insert ignore into %s %s values %s</script>";
}
@Override
protected String getId() {
return "insertIgnoreByBatch";
}
@Override
protected String getSql() {
return "<script>insert ignore into %s %s values %s</script>";
}
@Override
protected String getId() {
return "insertIgnoreByBatch";
}
}

View File

@@ -4,9 +4,10 @@ import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.hccake.extend.mybatis.plus.config.StaticConfig;
/**
* @author lingting 2020/5/27 11:47
* @author lingting 2020/5/27 11:47
*/
public class InsertOrUpdateByBatch extends BaseInsertBatch {
@Override
protected String getSql() {
return "<script>insert into %s %s values %s</script>";
@@ -29,8 +30,10 @@ public class InsertOrUpdateByBatch extends BaseInsertBatch {
// 默认忽略字段
if (!StaticConfig.UPDATE_IGNORE_FIELDS.contains(field.getProperty())) {
sql.append(field.getColumn()).append("=").append("VALUES(").append(field.getColumn()).append("),");
} else {
ignore.append(",").append(field.getColumn()).append("=").append("VALUES(").append(field.getColumn()).append(")");
}
else {
ignore.append(",").append(field.getColumn()).append("=").append("VALUES(").append(field.getColumn())
.append(")");
}
}
});
@@ -42,4 +45,5 @@ public class InsertOrUpdateByBatch extends BaseInsertBatch {
sql.append("<if test=\"!ignore\">").append(ignore).append("</if>");
return sql.toString();
}
}

View File

@@ -3,39 +3,36 @@ package com.hccake.extend.mybatis.plus.mysql.methods;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
/**
* @author lingting 2020/5/27 11:47
* @author lingting 2020/5/27 11:47
*/
public class InsertOrUpdateFieldByBatch extends BaseInsertBatch {
private static final String SQL = "<script>insert into %s %s values %s</script>";
@Override
protected String getSql() {
return "<script>insert into %s %s values %s</script>";
}
private static final String SQL = "<script>insert into %s %s values %s</script>";
@Override
protected String getId() {
return "insertOrUpdateFieldByBatch";
}
@Override
protected String getSql() {
return "<script>insert into %s %s values %s</script>";
}
@Override
protected String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) {
StringBuilder sql = super.prepareValuesBuildSqlForMysqlBatch(tableInfo);
sql.append(" ON DUPLICATE KEY UPDATE ")
// 如果模式为 不忽略设置的字段
.append("<if test=\"!columns.ignore\">")
.append("<foreach collection=\"columns.list\" item=\"item\" index=\"index\" separator=\",\" >")
.append("${item.name}=${item.val}")
.append("</foreach>")
.append("</if>");
@Override
protected String getId() {
return "insertOrUpdateFieldByBatch";
}
// 如果模式为 忽略设置的字段
sql.append("<if test=\"columns.ignore\">")
.append("<foreach collection=\"columns.back\" item=\"item\" index=\"index\" separator=\",\" >")
.append("${item}=VALUES(${item})")
.append("</foreach>")
.append("</if>");
return sql.toString();
}
@Override
protected String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) {
StringBuilder sql = super.prepareValuesBuildSqlForMysqlBatch(tableInfo);
sql.append(" ON DUPLICATE KEY UPDATE ")
// 如果模式为 不忽略设置的字段
.append("<if test=\"!columns.ignore\">")
.append("<foreach collection=\"columns.list\" item=\"item\" index=\"index\" separator=\",\" >")
.append("${item.name}=${item.val}").append("</foreach>").append("</if>");
// 如果模式为 忽略设置的字段
sql.append("<if test=\"columns.ignore\">")
.append("<foreach collection=\"columns.back\" item=\"item\" index=\"index\" separator=\",\" >")
.append("${item}=VALUES(${item})").append("</foreach>").append("</if>");
return sql.toString();
}
}

View File

@@ -15,14 +15,16 @@ import java.util.ArrayList;
import java.util.List;
/**
* @author lingting 2020/6/9 19:59
* @author lingting 2020/6/9 19:59
*/
@Slf4j
@ComponentScan
@Configuration
@EnableConfigurationProperties({MybatisProperties.class})
@EnableConfigurationProperties({ MybatisProperties.class })
public class MybatisAutoConfiguration {
private final List<MybatisConfigurer> configurers;
private final MybatisProperties properties;
public MybatisAutoConfiguration(List<MybatisConfigurer> configurers, MybatisProperties properties) {
@@ -42,7 +44,8 @@ public class MybatisAutoConfiguration {
for (Class<? extends AbstractMethod> c : properties.getMethods()) {
try {
list.add(c.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
}
catch (InstantiationException | IllegalAccessException e) {
throw new MybatisMethodInstanceException("获取自定义全局方法实例出错 class: " + c.getName(), e);
}
}
@@ -50,4 +53,5 @@ public class MybatisAutoConfiguration {
configurers.forEach(mybatisConfigurer -> mybatisConfigurer.addGlobalMethods(list));
return new SqlInjector(list);
}
}

View File

@@ -7,12 +7,12 @@ import lombok.RequiredArgsConstructor;
import java.util.List;
/**
* @author lingting 2020/5/27 11:46
* @author lingting 2020/5/27 11:46
*/
@RequiredArgsConstructor
public class SqlInjector extends DefaultSqlInjector {
private final List<AbstractMethod> list;
private final List<AbstractMethod> list;
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
@@ -20,4 +20,5 @@ public class SqlInjector extends DefaultSqlInjector {
list.addAll(this.list);
return list;
}
}

View File

@@ -6,15 +6,14 @@ import java.util.List;
import java.util.Set;
/**
* 用于自定义 mybatis 配置
* 自定义配置需 实现本类 并设置为bean
* 用于自定义 mybatis 配置 自定义配置需 实现本类 并设置为bean
*
* @author lingting 2020/5/27 20:56
* @author lingting 2020/5/27 20:56
*/
public interface MybatisConfigurer {
/**
* 添加 生成 更新 sql 时 需要忽略的字段
*
* @param set 字段 set
* @author lingting 2020-05-27 20:58:32
*/
@@ -23,10 +22,10 @@ public interface MybatisConfigurer {
/**
* 添加自定义的 全局方法
*
* @param list 方法list
* @author lingting 2020-05-27 23:47:10
*/
default void addGlobalMethods(List<AbstractMethod> list) {
}
}

View File

@@ -10,11 +10,12 @@ import java.util.List;
import java.util.Set;
/**
* @author lingting 2020-05-28 14:54:30
* @author lingting 2020-05-28 14:54:30
*/
@Data
@ConfigurationProperties(prefix = "ballcat.extend.mybatis-plus")
public class MybatisProperties {
/**
* 全局忽略更新的字段
*/
@@ -24,4 +25,5 @@ public class MybatisProperties {
* 自定义方法
*/
private List<Class<? extends AbstractMethod>> methods = new ArrayList<>();
}

View File

@@ -6,11 +6,13 @@ import java.util.Set;
/**
* 用于配置 需要 动态加载,但是 静态来使用的变量
*
* @author lingting 2020/6/9 20:05
* @author lingting 2020/6/9 20:05
*/
public class StaticConfig {
/**
* 更新时忽略的字段
*/
public static final Set<String> UPDATE_IGNORE_FIELDS = new HashSet<>();
}

View File

@@ -3,11 +3,12 @@ package com.hccake.extend.mybatis.plus.exception;
/**
* mybatis plus 方法 实例化获取异常
*
* @author lingting 2020/5/28 15:06
* @author lingting 2020/5/28 15:06
*/
public class MybatisMethodInstanceException extends RuntimeException {
public MybatisMethodInstanceException(String message, Throwable cause) {
super(message, cause);
}
}