添加公共组件 #10
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>gitlink-notification-system</artifactId>
|
||||
<groupId>cn.org.gitlink.notification</groupId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<artifactId>gns-common</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<name>[GNS] - Common</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>api</description>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<dependencies>
|
||||
<!--集成redis-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<version>2.3.4.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.3</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.11.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.11.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 集成kafka -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.kafka</groupId>
|
||||
<artifactId>spring-kafka</artifactId>
|
||||
<version>2.7.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package cn.org.gitlink.notification.common.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.*;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* redis配置类
|
||||
* @Date: 2021/09/03
|
||||
* @Author: zengwei
|
||||
* @Description:
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("all")
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
|
||||
template.setConnectionFactory(factory);
|
||||
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
|
||||
ObjectMapper om = new ObjectMapper();
|
||||
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
|
||||
jackson2JsonRedisSerializer.setObjectMapper(om);
|
||||
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||
// key采用String的序列化方式
|
||||
template.setKeySerializer(stringRedisSerializer);
|
||||
// hash的key也采用String的序列化方式
|
||||
template.setHashKeySerializer(stringRedisSerializer);
|
||||
// value序列化方式采用jackson
|
||||
template.setValueSerializer(jackson2JsonRedisSerializer);
|
||||
// hash的value序列化方式采用jackson
|
||||
template.setHashValueSerializer(jackson2JsonRedisSerializer);
|
||||
template.afterPropertiesSet();
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
package cn.org.gitlink.notification.common.utils;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.kafka.clients.admin.*;
|
||||
import org.apache.kafka.common.TopicPartitionInfo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.kafka.core.KafkaTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 操作kafka的工具类
|
||||
*
|
||||
* @author 154594742@qq.com
|
||||
* @date 2021/3/2 14:52
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class KafkaUtil {
|
||||
|
||||
@Value("${spring.kafka.bootstrap-servers:#{null}}")
|
||||
private String springKafkaBootstrapServers;
|
||||
|
||||
private AdminClient adminClient;
|
||||
|
||||
@Autowired
|
||||
private KafkaTemplate kafkaTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* 初始化AdminClient
|
||||
* '@PostConstruct该注解被用来修饰一个非静态的void()方法。
|
||||
* 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。
|
||||
* PostConstruct在构造函数之后执行,init()方法之前执行。
|
||||
*/
|
||||
@PostConstruct
|
||||
private void initAdminClient() {
|
||||
Map<String, Object> props = new HashMap<>(1);
|
||||
if (springKafkaBootstrapServers == null) {
|
||||
return;
|
||||
}
|
||||
props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, springKafkaBootstrapServers);
|
||||
adminClient = KafkaAdminClient.create(props);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增topic,支持批量
|
||||
*/
|
||||
public void createTopic(Collection<NewTopic> newTopics) {
|
||||
adminClient.createTopics(newTopics);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除topic,支持批量
|
||||
*/
|
||||
public void deleteTopic(Collection<String> topics) {
|
||||
adminClient.deleteTopics(topics);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定topic的信息
|
||||
*/
|
||||
public String getTopicInfo(Collection<String> topics) {
|
||||
AtomicReference<String> info = new AtomicReference<String>("");
|
||||
try {
|
||||
adminClient.describeTopics(topics).all().get().forEach((topic, description) -> {
|
||||
for (TopicPartitionInfo partition : description.partitions()) {
|
||||
info.set(info + partition.toString() + "\n");
|
||||
}
|
||||
});
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return info.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部topic
|
||||
*/
|
||||
public List<String> getAllTopic() {
|
||||
try {
|
||||
return adminClient.listTopics().listings().get().stream().map(TopicListing::name).collect(Collectors.toList());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 往topic中发送消息
|
||||
*/
|
||||
public void sendMessage(String topic, String message) {
|
||||
kafkaTemplate.send(topic, message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
package cn.org.gitlink.notification.common.utils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
/**
|
||||
* Redis工具类
|
||||
* @author zengwei
|
||||
* @date 2021/09/03
|
||||
*/
|
||||
@Component
|
||||
public class RedisUtil {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
// =============================common============================
|
||||
/**
|
||||
* 指定缓存失效时间
|
||||
* @param key 键
|
||||
* @param time 时间(秒)
|
||||
* @return
|
||||
*/
|
||||
public boolean expire(String key, long time) {
|
||||
try {
|
||||
if (time > 0) {
|
||||
redisTemplate.expire(key, time, TimeUnit.SECONDS);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key 获取过期时间
|
||||
* @param key 键 不能为null
|
||||
* @return 时间(秒) 返回0代表为永久有效
|
||||
*/
|
||||
public long getExpire(String key) {
|
||||
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断key是否存在
|
||||
* @param key 键
|
||||
* @return true 存在 false不存在
|
||||
*/
|
||||
public boolean hasKey(String key) {
|
||||
try {
|
||||
return redisTemplate.hasKey(key);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
* @param key 可以传一个值 或多个
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void del(String... key) {
|
||||
if (key != null && key.length > 0) {
|
||||
if (key.length == 1) {
|
||||
redisTemplate.delete(key[0]);
|
||||
} else {
|
||||
redisTemplate.delete(CollectionUtils.arrayToList(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================String=============================
|
||||
/**
|
||||
* 普通缓存获取
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
public Object get(String key) {
|
||||
return key == null ? null : redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通缓存放入
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @return true成功 false失败
|
||||
*/
|
||||
public boolean set(String key, Object value) {
|
||||
try {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通缓存放入并设置时间
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
|
||||
* @return true成功 false 失败
|
||||
*/
|
||||
public boolean set(String key, Object value, long time) {
|
||||
try {
|
||||
if (time > 0) {
|
||||
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
|
||||
} else {
|
||||
set(key, value);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ================================Map=================================
|
||||
/**
|
||||
* HashGet
|
||||
* @param key 键 不能为null
|
||||
* @param item 项 不能为null
|
||||
* @return 值
|
||||
*/
|
||||
public Object hget(String key, String item) {
|
||||
return redisTemplate.opsForHash().get(key, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取hashKey对应的所有键值
|
||||
* @param key 键
|
||||
* @return 对应的多个键值
|
||||
*/
|
||||
public Map<Object, Object> hmget(String key) {
|
||||
return redisTemplate.opsForHash().entries(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* HashSet
|
||||
* @param key 键
|
||||
* @param map 对应多个键值
|
||||
* @return true 成功 false 失败
|
||||
*/
|
||||
public boolean hmset(String key, Map<String, Object> map) {
|
||||
try {
|
||||
redisTemplate.opsForHash().putAll(key, map);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HashSet 并设置时间
|
||||
* @param key 键
|
||||
* @param map 对应多个键值
|
||||
* @param time 时间(秒)
|
||||
* @return true成功 false失败
|
||||
*/
|
||||
public boolean hmset(String key, Map<String, Object> map, long time) {
|
||||
try {
|
||||
redisTemplate.opsForHash().putAll(key, map);
|
||||
if (time > 0) {
|
||||
expire(key, time);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向一张hash表中放入数据,如果不存在将创建
|
||||
* @param key 键
|
||||
* @param item 项
|
||||
* @param value 值
|
||||
* @return true 成功 false失败
|
||||
*/
|
||||
public boolean hset(String key, String item, Object value) {
|
||||
try {
|
||||
redisTemplate.opsForHash().put(key, item, value);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向一张hash表中放入数据,如果不存在将创建
|
||||
* @param key 键
|
||||
* @param item 项
|
||||
* @param value 值
|
||||
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
|
||||
* @return true 成功 false失败
|
||||
*/
|
||||
public boolean hset(String key, String item, Object value, long time) {
|
||||
try {
|
||||
redisTemplate.opsForHash().put(key, item, value);
|
||||
if (time > 0) {
|
||||
expire(key, time);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除hash表中的值
|
||||
* @param key 键 不能为null
|
||||
* @param item 项 可以使多个 不能为null
|
||||
*/
|
||||
public void hdel(String key, Object... item) {
|
||||
redisTemplate.opsForHash().delete(key, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断hash表中是否有该项的值
|
||||
* @param key 键 不能为null
|
||||
* @param item 项 不能为null
|
||||
* @return true 存在 false不存在
|
||||
*/
|
||||
public boolean hHasKey(String key, String item) {
|
||||
return redisTemplate.opsForHash().hasKey(key, item);
|
||||
}
|
||||
}
|
||||
1
pom.xml
1
pom.xml
|
|
@ -14,6 +14,7 @@
|
|||
<module>writer</module>
|
||||
<module>reader</module>
|
||||
<module>executor</module>
|
||||
<module>common</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.org.gitlink.notification</groupId>
|
||||
<artifactId>gns-common</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
@ -34,5 +39,4 @@
|
|||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
|
|
@ -2,7 +2,9 @@ package cn.org.gitlink.notification.reader;
|
|||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@ComponentScan("cn.org.gitlink.notification.*")
|
||||
@SpringBootApplication
|
||||
public class ReaderApiApplication {
|
||||
public static void main(String[] args) {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
package cn.org.gitlink.notification.reader.controller;
|
||||
|
||||
import cn.org.gitlink.notification.common.utils.RedisUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class IndexController {
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
@GetMapping(value = "")
|
||||
public String index() {
|
||||
return "reader index!";
|
||||
redisUtil.set("hello", "Hello reader!");
|
||||
return redisUtil.get("hello").toString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,24 @@
|
|||
server:
|
||||
port: 8080
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
database: 0
|
||||
# Redis服务器地址
|
||||
host: 127.0.0.1
|
||||
# Redis服务器连接端口
|
||||
port: 6379
|
||||
# Redis服务器连接密码(默认为空)
|
||||
password:
|
||||
pool:
|
||||
# 连接池最大连接数(使用负值表示没有限制)
|
||||
max-active: 200
|
||||
# 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-wait: -1
|
||||
# 连接池中的最大空闲连接
|
||||
max-idle: 10
|
||||
# 连接池中的最小空闲连接
|
||||
min-idle: 0
|
||||
# 连接超时时间(毫秒)
|
||||
timeout: 1000
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@
|
|||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.org.gitlink.notification</groupId>
|
||||
<artifactId>gns-common</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package cn.org.gitlink.notification;
|
|||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@ComponentScan("cn.org.gitlink.notification.*")
|
||||
@SpringBootApplication
|
||||
public class WriterApiApplication {
|
||||
public static void main(String[] args) {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,35 @@
|
|||
server:
|
||||
port: 8082
|
||||
port: 8082
|
||||
|
||||
spring:
|
||||
#kafka配置
|
||||
kafka:
|
||||
#这里改为你的kafka服务器ip和端口号
|
||||
bootstrap-servers: 172.16.15.29:9092
|
||||
#=============== producer =======================
|
||||
producer:
|
||||
#如果该值大于零时,表示启用重试失败的发送次数
|
||||
retries: 0
|
||||
#每当多个记录被发送到同一分区时,生产者将尝试将记录一起批量处理为更少的请求,默认值为16384(单位字节)
|
||||
batch-size: 16384
|
||||
#生产者可用于缓冲等待发送到服务器的记录的内存总字节数,默认值为3355443
|
||||
buffer-memory: 33554432
|
||||
#key的Serializer类,实现类实现了接口org.apache.kafka.common.serialization.Serializer
|
||||
key-serializer: org.apache.kafka.common.serialization.StringSerializer
|
||||
#value的Serializer类,实现类实现了接口org.apache.kafka.common.serialization.Serializer
|
||||
value-serializer: org.apache.kafka.common.serialization.StringSerializer
|
||||
#=============== consumer =======================
|
||||
consumer:
|
||||
#用于标识此使用者所属的使用者组的唯一字符串
|
||||
group-id: test-consumer-group
|
||||
#当Kafka中没有初始偏移量或者服务器上不再存在当前偏移量时该怎么办,默认值为latest,表示自动将偏移重置为最新的偏移量
|
||||
#可选的值为latest, earliest, none
|
||||
auto-offset-reset: earliest
|
||||
#消费者的偏移量将在后台定期提交,默认值为true
|
||||
enable-auto-commit: true
|
||||
#如果'enable-auto-commit'为true,则消费者偏移自动提交给Kafka的频率(以毫秒为单位),默认值为5000。
|
||||
auto-commit-interval: 100
|
||||
#密钥的反序列化器类,实现类实现了接口org.apache.kafka.common.serialization.Deserializer
|
||||
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
|
||||
#值的反序列化器类,实现类实现了接口org.apache.kafka.common.serialization.Deserializer
|
||||
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
|
||||
Loading…
Reference in New Issue