Compare commits

..

No commits in common. "master" and "add_notification_sql" have entirely different histories.

112 changed files with 645 additions and 5140 deletions

View File

@ -1,3 +0,0 @@
/docker-data
/logs
.idea

5
.gitignore vendored
View File

@ -90,8 +90,3 @@ target/
.env
/docker-data/
/logs/
*/src/main/resources/application.yml
*/src/main/resources/mail.properties

View File

@ -1,13 +1,13 @@
![](/api/attachments/366811?raw=true)
![](/api/attachments/365506?raw=true)
### 主要组成部分:
1. **管理后台(在建)** :提供对分布式的任务集中监控、管理等功能
2. **各类执行器** :消息中心的业务逻辑实现,目前只实现「系统通知」和「邮件通知」功能,后续可以考虑短信通知、微信通知等实现
3. **GNS-Writer**:给 `业务层` 调用的 API 网关,负责从业务逻辑层接受信息
1. **xxl-job 调度管理中心** :提供对分布式的任务集中监控、管理等功能
2. **xxl-job 执行器** :消息中心的业务逻辑实现,目前只实现「系统通知」功能,后续可以考虑 `email-executor`、`text-message-executor` 等实现
3. **GNS-Writer**:给 `Forge业务层` 调用的 API 网关,负责从业务逻辑层接受信息
4. **middleware**:独立运行的中间件服务, 包括消息中间件、缓存中间件、DB
5. **GNS-Reader**:给 `业务层` 调用的 API 网关,负责提供业务数据
5. **GNS-Reader**:给 `Forge业务层` 调用的 API 网关,负责提供业务数据
### 一些约定:
@ -22,27 +22,4 @@
3. 在本地分支修改任务并推送到自己名下的仓库
4. 在 [仓库首页](https://forgeplus.trustie.net/projects/Gitlink/gitlink-notification-system) 触发 pull request 并等待审核处理
### 使用 Docker 运行
1. git pull 拉取本仓库并保存到本地
2. 下载并安装 [Docker Engine](https://docs.docker.com/engine/install/)
3. 配置好 Java 环境以及 Maven 环境 (Java 8 版本以上、Maven 3 版本以上)
4. 复制配置文件,在仓库跟目录执行:
```
cp middleware/.env.example middleware/.env
cp reader/src/main/resources/application.yml.example reader/src/main/resources/application.yml
cp writer/src/main/resources/application.yml.example writer/src/main/resources/application.yml
cp executor/src/main/resources/application.yml.example executor/src/main/resources/application.yml
cp reader/src/main/resources/mail.properties.example reader/src/main/resources/mail.properties
cp writer/src/main/resources/mail.properties.example writer/src/main/resources/mail.properties
cp executor/src/main/resources/mail.properties.example executor/src/main/resources/mail.properties
```
5. 修改 `{repo}/middleware/.env` 文件里 `SQL_SCRIPT_PATH``DOCKER_DATA_PATH` 绝对路径到本地磁盘
6. 进入到仓库根目录下的 `{repo}/middleware` 目录并执行 `start_docker_compose.sh` 脚本
7. 浏览器访问
1. 数据推送相关接口http://localhost:58082/doc.html
2. 数据读取相关接口http://localhost:58080/doc.html
8. 停止 Docker 时环境时请执行 `{repo}/middleware/end_docker_compose.sh` 脚本

View File

@ -1,80 +0,0 @@
<?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>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.9.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.38</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.38</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,59 +0,0 @@
package cn.org.gitlink.notification.common.config;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableKafka
public class KafkaConsumerConfig {
@Value("${spring.kafka.consumer.bootstrap_servers:#{null}}")
private String servers;
@Value("${spring.kafka.consumer.auto_offset_reset:#{null}}")
private String autoOffsetReset;
@Value("${spring.kafka.consumer.max_poll_records:#{null}")
private String maxPollRecords;
@Value("${spring.kafka.consumer.topic:#{null}}")
private String topic;
@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> consumerListenerFactory() {
// 如果当前配置信息内没有kafka consumer则不创建监听工厂
if (null == servers) return null;
ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
factory.setConsumerFactory(consumerConfigs());
factory.setRecordFilterStrategy(record -> record.topic().toLowerCase().equals(this.topic));
return factory;
}
@Bean
public ConsumerFactory<String, Object> consumerConfigs() {
Map<String, Object> props = new HashMap<>();
// 如果当前配置信息内没有kafka consumer此处解决没有设置配置信息而引起的空指针异常
if (null != servers) {
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, maxPollRecords);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, autoOffsetReset);
props.put(ConsumerConfig.ALLOW_AUTO_CREATE_TOPICS_CONFIG, false);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
}
return new DefaultKafkaConsumerFactory<>(props);
}
}

View File

@ -1,49 +0,0 @@
package cn.org.gitlink.notification.common.config;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class KafkaProducerConfig {
@Value("${spring.kafka.producer.bootstrap_servers:#{null}}")
private String bootstrapServers;
@Value("${spring.kafka.producer.retries:#{null}}")
private Integer retries;
@Value("${spring.kafka.producer.batch_size:#{null}}")
private Integer batchSize;
@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(producerConfigs(), true);
}
@Bean
ProducerFactory<String, String> producerConfigs() {
Map<String, Object> props = new HashMap<>();
// 如果当前配置信息内没有kafka producer相关配置则不做参数设置此处解决没有设置配置信息而引起的空指针异常
if (null != bootstrapServers) {
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ProducerConfig.RETRIES_CONFIG, retries);
props.put(ProducerConfig.ACKS_CONFIG, "all");
props.put(ProducerConfig.BATCH_SIZE_CONFIG, batchSize);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
}
return new DefaultKafkaProducerFactory<>(props);
}
}

View File

@ -1,44 +0,0 @@
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;
}
}

View File

@ -1,44 +0,0 @@
package cn.org.gitlink.notification.common.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 消息系统常量
*
* @author: wanjia
* @time: 2021/9/9
*/
public class NotificationSystemConstant {
//平台编码
public static final String PLATFORM_CODE_GITLINK = "gitlink"; //gitlink平台
public static final String PLATFORM_CODE_HEHUI = "hehui"; //hehui平台
public static final String PLATFORM_CODE_OSREDM = "osredm"; //红山开源平台
public static final Map<String, String> PLATFORM_CODE_MAP = new HashMap<String, String>() {
{
put("gitlink", PLATFORM_CODE_GITLINK);
put("hehui", PLATFORM_CODE_HEHUI);
put("osredm", PLATFORM_CODE_OSREDM);
}
};
//邮件任务处理状态
public static final Integer EMAIL_JOB_NOT_DISPATCHED = -1; //处理成功
public static final Integer EMAIL_JOB_DISPATCHED_SUCCESS = 1; //处理成功
public static final Integer EMAIL_JOB_DISPATCHED_FAIL = 2; //处理失败
//邮件发送记录状态
public static final Integer EMAIL_UNSENT_RECORD = -1; //处理成功
public static final Integer EMAIL_SENT_SUCCESS = 1; //处理成功
public static final Integer EMAIL_SENT_FAIL = 2; //处理失败
//未读消息类型
public static final Integer NOTIFICATION_TYPE_ALL = -1; //全部未读消息
public static final Integer NOTIFICATION_TYPE_SYS = 1; //系统消息
public static final Integer NOTIFICATION_TYPE_ATME = 2; //@我的消息
//是否已读状态
public static final Integer STATUS_OPTION_ALL = -1; //所有信息类型包括未读已读
public static final Integer STATUS_OPTION_UNREAD = 1; //未读信息
public static final Integer STATUS_OPTION_READ = 2; //已读信息
}

View File

@ -1,12 +0,0 @@
package cn.org.gitlink.notification.common.exceptions;
/**
* 网关拦截非白名单用户异常类
* @author zengwei
* @date 2021/09/07
* */
public class ForbiddenException extends Exception{
public ForbiddenException(String message) {
super(message);
}
}

View File

@ -1,67 +0,0 @@
package cn.org.gitlink.notification.common.interceptor;
import cn.org.gitlink.notification.common.exceptions.ForbiddenException;
import cn.org.gitlink.notification.common.response.DataPacketUtil;
import cn.org.gitlink.notification.common.response.ResponseData;
import cn.org.gitlink.notification.common.utils.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* web请求异常全局处理类在使用的模块内继承此类然后加上ControllerAdvice注解example:
*
* @author zengwei
* @ControllerAdvice public class ReaderExceptionInterceptor extends ExceptionInterceptor {}
* @date 2021/09/07
*/
public class ExceptionInterceptor {
private static final Logger logger = LoggerFactory.getLogger(ExceptionInterceptor.class);
private static String logTemplate = "request page url{}, error:{}";
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler({ForbiddenException.class})
public ResponseData handle(HttpServletRequest request, ForbiddenException e) {
logger.warn("非法求请, ip:{}", CommonUtils.getIPAddress(request));
return DataPacketUtil.jsonFailResult(e.getMessage());
}
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler({Exception.class})
public ResponseData handle(HttpServletRequest request, Exception e) {
logger.error(logTemplate, request.getRequestURI(), e);
return DataPacketUtil.jsonFailResult(e.getMessage());
}
/**
* valid 异常处理
*
* @param e
* @return
*/
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseData handlerValidException(MethodArgumentNotValidException e){
Map<String, Object> errorMessageMap = new HashMap<>();
// 获取所有错误信息
List<FieldError> errList = e.getBindingResult().getFieldErrors();
for (FieldError error : errList) {
errorMessageMap.put(error.getField(), error.getDefaultMessage());
}
logger.error("data errors:{}", errorMessageMap);
return DataPacketUtil.jsonFailResult(errorMessageMap);
}
}

View File

@ -1,42 +0,0 @@
package cn.org.gitlink.notification.common.interceptor;
import cn.org.gitlink.notification.common.exceptions.ForbiddenException;
import cn.org.gitlink.notification.common.utils.CommonUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* GitLink统一拦截类example:
* @Configuration
* public class ReaderWebConfig implements WebMvcConfigurer {
* @Autowired
* private GitLinkInterceptor gitLinkInterceptor;
* @Override
* public void addInterceptors(InterceptorRegistry registry) {
* registry.addInterceptor(gitLinkInterceptor).addPathPatterns("/**");
* }
* }
*
* @author zengwei
* @date 2021/09/07
* */
@Component
public class GitLinkInterceptor implements HandlerInterceptor {
@Value(value = "${white-list:''}")
private String whiteList;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
if (null == httpServletRequest || whiteList.contains("*")) {
return true;
}
if (!whiteList.contains(CommonUtils.getIPAddress(httpServletRequest))) {
throw new ForbiddenException("没有权限访问,请向管理员申请访问权限!");
}
return true;
}
}

View File

@ -1,52 +0,0 @@
package cn.org.gitlink.notification.common.response;
import java.util.HashMap;
public class DataPacketUtil
{
public static final String RESULT_KEY_SUCCESS = "请求成功";
public static final String RESULT_KEY_FAIL = "请求失败";
public static final Integer SUCCESS_CODE = 1;
public static final Integer FAIL_CODE = 0;
public static final String NOT_FOUND_MESSAGE = "资源不存在";
public static final String FORBIDDEN_MESSAGE = "您无权限进行此操作!";
public static ResponseData jsonResult(String msg, Integer code, Object data)
{
return new ResponseData(msg, code, data);
}
public static ResponseData jsonSuccessResult() {
return jsonResult(RESULT_KEY_SUCCESS, SUCCESS_CODE, new HashMap<>());
}
public static ResponseData jsonSuccessResult(Object data) {
return jsonResult(RESULT_KEY_SUCCESS, SUCCESS_CODE, data);
}
public static ResponseData jsonSuccessResult(String msg) {
return jsonResult(msg, SUCCESS_CODE, new HashMap<>());
}
public static ResponseData jsonSuccessResult(String msg, Object data) {
return jsonResult(msg, SUCCESS_CODE, data);
}
public static ResponseData jsonFailResult() {
return jsonResult( RESULT_KEY_FAIL, FAIL_CODE, new HashMap<>());
}
public static ResponseData jsonFailResult(String msg) {
return jsonResult( msg, FAIL_CODE, new HashMap<>());
}
public static ResponseData jsonFailResult(Object data) {
return jsonResult( RESULT_KEY_FAIL, FAIL_CODE, data);
}
public static ResponseData jsonFailResult(String msg, Object data) {
return jsonResult( msg, FAIL_CODE, data);
}
}

View File

@ -1,34 +0,0 @@
package cn.org.gitlink.notification.common.response;
import java.io.Serializable;
public class PageData<T> implements Serializable {
private long total;
private java.util.List<T> rows;
public PageData(long total, java.util.List<T> rows) {
this.total = total;
this.rows = rows;
}
public long getTotal() {
return this.total;
}
public void setTotal(long total) {
this.total = total;
}
public java.util.List<T> getRows() {
return this.rows;
}
public void setRows(java.util.List<T> rows) {
this.rows = rows;
}
public PageData() {
}
}

View File

@ -1,65 +0,0 @@
package cn.org.gitlink.notification.common.response;
import org.apache.kafka.common.protocol.types.Field;
import java.io.Serializable;
public class ResponseData<T> implements Serializable {
/**
* 响应状态
*/
protected Integer code;
/**
* 响应消息
*/
protected String message;
/**
* 响应数据
*/
private T data;
public void setMessage(String message) {
this.message = message;
}
public void setCode(Integer code) { this.code = code; }
public String toString() {
return "ResponseData(message=" + getMessage() + ", data=" + getData() + ")";
}
public String getMessage() {
return this.message;
}
public Integer getCode() { return this.code; }
public ResponseData(T data) {
this.data = data;
}
public ResponseData(String message) {
this.message = message;
}
public ResponseData(String message, Integer code, T data) {
this.message = message;
this.code = code;
this.data = data;
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public ResponseData() {
}
}

View File

@ -1,52 +0,0 @@
package cn.org.gitlink.notification.common.utils;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
/**
* 公共工具类
* @author zengwei
* @date 2021/09/07
* */
public class CommonUtils {
/**
* 根据request获取ip
* @author zengwei
* @data 2021/07/09
* */
public static String getIPAddress(HttpServletRequest request) {
String Xip = request.getHeader("X-Real-IP");
String XFor = request.getHeader("X-Forwarded-For");
if (StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) {
//多次反向代理后会有多个ip值第一个ip才是真实ip
int index = XFor.indexOf(",");
if (index != -1) {
return XFor.substring(0,index);
} else {
return XFor;
}
}
XFor = Xip;
if (StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) {
return XFor;
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
XFor = request.getRemoteAddr();
}
return XFor;
}
}

View File

@ -1,35 +0,0 @@
package cn.org.gitlink.notification.common.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
@PropertySource(value = "mail.properties")
@Service(value = "GitlinkMailUtils")
public class EmailUtils {
@Value("${spring.mail.username}")
private String emailFrom;
@Autowired
private JavaMailSender mailSender;
public void sendMail(String subject, String recipient, String content) throws MessagingException {
MimeMessage mail = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mail, true);
helper.setTo(recipient);
helper.setFrom(emailFrom);
helper.setSubject(subject);
helper.setText(content, true);
mailSender.send(mail);
}
}

View File

@ -1,157 +0,0 @@
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.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
* 操作kafka的工具类
*
* @author zengwei
* @date 2021-09-07
*/
@Component(value = "GitlinkKafkaUtil")
public class KafkaUtil {
private Logger logger = LogManager.getLogger(KafkaUtil.class);
@Value("${spring.kafka.producer.bootstrap_servers:#{null}}")
private String kafkaServer;
@Value("${spring.kafka.producer.partitions:#{null}}")
private Integer partitions;
@Value("${spring.kafka.producer.replication_factor:#{null}}")
private Short replicationFactor;
@Value("${spring.kafka.producer.topics:''}")
private String topicString;
private AdminClient adminClient;
@Autowired
private KafkaTemplate kafkaTemplate;
/**
* 初始化AdminClient
* '@PostConstruct该注解被用来修饰一个非静态的void方法
* @PostConstruct修饰的方法会在服务器加载Servlet的时候运行并且只会被服务器执行一次
* PostConstruct在构造函数之后执行init方法之前执行ls
*/
@PostConstruct
private void initAdminClient() {
Map<String, Object> props = new HashMap<>(1);
// 如果当前配置信息内没有kafka producer相关配置则不对adminClient做初始化
if (kafkaServer == null) {
return;
}
props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaServer);
adminClient = KafkaAdminClient.create(props);
// 初始化topics
if (null !=partitions && null != replicationFactor) {
List<String> topics = Arrays.asList(topicString.split(","));
if (!topics.isEmpty()) {
List<NewTopic> newTopics = new LinkedList<>();
topics.forEach(topic -> {
newTopics.add(new NewTopic(topic, partitions, replicationFactor));
});
this.createTopic(newTopics);
}
}
}
public void createTopic(Collection<NewTopic> newTopics) {
adminClient.createTopics(newTopics);
}
public void deleteTopic(Collection<String> topics) {
adminClient.deleteTopics(topics);
}
/**
* 获取 Topic 的信息
*
* @param topics
* @return
*/
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) {
logger.error(e);
}
return info.get();
}
/**
* 获取所有 Topic
*
* @return
*/
public List<String> getAllTopic() {
try {
return adminClient.listTopics().listings().get().stream().map(TopicListing::name).collect(Collectors.toList());
} catch (InterruptedException | ExecutionException e) {
logger.error(e);
}
return Lists.newArrayList();
}
/**
* Kafka 发送消息
*
* @param topic
* @param message
*/
public void sendMessage(String topic, String message) {
ListenableFuture<SendResult<String, String>> future = kafkaTemplate.send(topic, message);
future.addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
@Override
public void onFailure(Throwable throwable) {
logger.error(throwable);
}
@Override
public void onSuccess(SendResult<String, String> stringStringSendResult) {
logger.debug(stringStringSendResult.getRecordMetadata());
}
});
}
/**
* kafka 发送信息
*
* @param topic
* @param message
* @param callback
*/
public void sendMessage(String topic, String message, ListenableFutureCallback callback) {
ListenableFuture<SendResult<String, String>> future = kafkaTemplate.send(topic, message);
future.addCallback(callback);
}
}

View File

@ -1,276 +0,0 @@
package cn.org.gitlink.notification.common.utils;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ConvertingCursor;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
/**
* Redis工具类
*
* @author zengwei
* @date 2021/09/03
*/
@Component(value = "GitlinkRedisUtil")
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// =============================common============================
public boolean scanAndDel(String keyPreffix) {
try {
ScanOptions options = ScanOptions.scanOptions().match(keyPreffix).count(100).build();
Cursor<String> cursor = (Cursor<String>) redisTemplate.executeWithStickyConnection(
redisConnection -> new ConvertingCursor<>(redisConnection.scan(options),
redisTemplate.getKeySerializer()::deserialize));
cursor.forEachRemaining(key -> {
redisTemplate.delete(key);
});
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}//end of try
}//end of method
/**
* 指定缓存失效时间
*
* @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);
}
}

View File

@ -1,43 +0,0 @@
package cn.org.gitlink.notification.common.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* spring context 工具类主要用来获取context里面的bean
* @author zengwei
* @Date 2021-09-09
* */
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}

View File

@ -1,54 +0,0 @@
package cn.org.gitlink.notification.common.utils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadUtil {
private Logger logger = LogManager.getLogger(ThreadUtil.class);
private static final Integer MAX_THREAD_COUNT = 5;
private static final Long KEEP_ALIVE_TIME_IN_MINUTES = 3L;
private static final int UNLIMITED_QUEUE = Integer.MAX_VALUE;
private static ThreadUtil instance = null;
private static ThreadPoolExecutor executorService = null;
private ThreadUtil() {
executorService = new ThreadPoolExecutor(MAX_THREAD_COUNT, MAX_THREAD_COUNT, KEEP_ALIVE_TIME_IN_MINUTES,
TimeUnit.MINUTES, new LinkedBlockingDeque<>(UNLIMITED_QUEUE));
executorService.allowCoreThreadTimeOut(true);
}
public static ThreadUtil getInstance() {
if (instance == null) {
instance = new ThreadUtil();
}
return instance;
}
public void runTask(Runnable runnable) {
try {
executorService.execute(runnable);
} catch (Exception e) {
logger.error(e);
}
}//end of method
public int getPoolSize() {
return executorService.getPoolSize();
}//end of method
public void shutdown() {
try {
if (!executorService.isShutdown()) {
executorService.shutdown();
}
} catch (Exception e) {
logger.error(e);
}//end of try-catch
}//end of method
}

View File

@ -1,43 +0,0 @@
package cn.org.gitlink.notification.common.utils;
import cn.org.gitlink.notification.common.constant.NotificationSystemConstant;
import cn.org.gitlink.notification.common.response.DataPacketUtil;
import cn.org.gitlink.notification.common.response.ResponseData;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @description: Validator工具类
* @author: wanjia
* @time: 2021/9/9
*/
public class ValidatorUtils {
public static Map<String, String> buildValidationErrorMessageMap(BindingResult bindingResult) {
Map<String, String> errorMessageMap = new HashMap<>();
List<FieldError> errList = bindingResult.getFieldErrors();
for (FieldError error : errList) {
errorMessageMap.put(error.getField(), error.getDefaultMessage());
}
return errorMessageMap;
}
/**
* 验证 platform合法性
*
* @param platform
* @return
*/
public static ResponseData validatePlatformCode(String platform) {
//验证 {platform} 参数合法性以判断请求来源
if (!NotificationSystemConstant.PLATFORM_CODE_MAP.containsKey(platform)) {
return DataPacketUtil.jsonFailResult("{platform} 参数非法");
}
return null;
}
}

View File

@ -1,31 +0,0 @@
DROP TABLE IF EXISTS `gitlink_email_jobs`;
CREATE TABLE `gitlink_email_jobs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`sender` int(11) NOT NULL COMMENT '发送者id',
`emails` text NOT NULL COMMENT '收件人全部邮件地址',
`subject` varchar(500) DEFAULT NULL COMMENT '邮件主题',
`content` text NOT NULL COMMENT '邮件内容',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`dispatched_at` datetime DEFAULT NULL COMMENT '处理时间',
`dispatched_status` int(11) DEFAULT '-1' COMMENT '发送状态:-1 未处理,1 处理成功,2 处理失败',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
DROP TABLE IF EXISTS `gitlink_email_send_records`;
CREATE TABLE `gitlink_email_send_records` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(500) NOT NULL DEFAULT '' COMMENT '收件人邮件地址',
`job_id` int(11) NOT NULL COMMENT '邮件详情id',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`sent_at` datetime DEFAULT NULL COMMENT '发送时间',
`status` int(11) DEFAULT '-1' COMMENT '发送状态:-1 未发送,1 发送成功,2 发送失败',
PRIMARY KEY (`id`),
KEY `index_on_email_and_status` (`email`,`status`),
KEY `index_on_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
-- 2023-01-05 更新字符集编码
ALTER TABLE gitlink_email_jobs CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE gitlink_email_send_records CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

View File

@ -1,41 +0,0 @@
USE gitlink_notification;
DROP TABLE IF EXISTS `gns_platform_info`;
CREATE TABLE `gns_platform_info` (
`id` INT NOT NULL AUTO_INCREMENT,
`platform_code` VARCHAR(200) NOT NULL DEFAULT '' COMMENT '平台编码',
`platform_name` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '平台名称',
`created_at` DATETIME NOT NULL DEFAULT NOW() COMMENT '创建时间',
`updated_at` DATETIME DEFAULT NULL COMMENT '更新时间',
`is_delete` TINYINT(1) NOT NULL DEFAULT '-1' COMMENT '是否删除: -1未删除1已删除',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb3;
INSERT INTO gns_platform_info(platform_code,platform_name,created_at,is_delete) VALUES('gitlink','Gitlink平台',NOW(),-1);
DROP TABLE IF EXISTS `gitlink_sys_notification`;
CREATE TABLE `gitlink_sys_notification` (
`id` INT NOT NULL AUTO_INCREMENT,
`sender` INT(11) NOT NULL COMMENT '发送者id',
`receiver` INT(11) NOT NULL COMMENT '接受者id',
`content` TEXT NOT NULL COMMENT '消息内容:富文本',
`notification_url` VARCHAR(2000) DEFAULT NULL COMMENT '消息跳转链接',
`created_at` DATETIME NOT NULL DEFAULT NOW() COMMENT '创建时间',
`status` TINYINT(4) NOT NULL DEFAULT 1 COMMENT '已读状态: 1未读2已读',
`is_delete` TINYINT(1) NOT NULL DEFAULT '-1' COMMENT '是否删除: -1未删除1已删除',
PRIMARY KEY (`id`),
KEY `index_on_receiver_and_status` (`receiver`,`status`),
KEY `index_on_status` (`status`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb3;
-- 2021-09-07 区分系统消息类型
ALTER TABLE gitlink_sys_notification ADD COLUMN (`type` TINYINT(4) NOT NULL DEFAULT 1 COMMENT '消息类型: 1系统消息2@我');
-- 2021-09-09 新增 source 字段区分消息来源、新增 extra 字段保存额外信息
ALTER TABLE gitlink_sys_notification ADD source varchar(250) NULL COMMENT '消息来源';
ALTER TABLE gitlink_sys_notification ADD extra TEXT NULL COMMENT '额外信息(备用字段)';
-- 2023-01-05 更新字符集编码
ALTER TABLE gitlink_sys_notification CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

View File

@ -1,30 +0,0 @@
USE gitlink_notification;
-- 2021-09-10 新增测试平台
INSERT INTO gns_platform_info(platform_code,platform_name,created_at,is_delete) VALUES('hehui','hehui平台',NOW(),-1);
DROP TABLE IF EXISTS `hehui_sys_notification`;
CREATE TABLE `hehui_sys_notification` (
`id` INT NOT NULL AUTO_INCREMENT,
`sender` INT(11) NOT NULL COMMENT '发送者id',
`receiver` INT(11) NOT NULL COMMENT '接受者id',
`content` TEXT NOT NULL COMMENT '消息内容:富文本',
`notification_url` VARCHAR(2000) DEFAULT NULL COMMENT '消息跳转链接',
`created_at` DATETIME NOT NULL DEFAULT NOW() COMMENT '创建时间',
`status` TINYINT(4) NOT NULL DEFAULT 1 COMMENT '已读状态: 1未读2已读',
`is_delete` TINYINT(1) NOT NULL DEFAULT '-1' COMMENT '是否删除: -1未删除1已删除',
PRIMARY KEY (`id`),
KEY `index_on_receiver_and_status` (`receiver`,`status`),
KEY `index_on_status` (`status`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb3;
-- 2021-09-10 区分系统消息类型
ALTER TABLE hehui_sys_notification ADD COLUMN (`type` TINYINT(4) NOT NULL DEFAULT 1 COMMENT '消息类型: 1系统消息2@我');
-- 2021-09-10 新增 source 字段区分消息来源、新增 extra 字段保存额外信息
ALTER TABLE hehui_sys_notification ADD source varchar(250) NULL COMMENT '消息来源';
ALTER TABLE hehui_sys_notification ADD extra TEXT NULL COMMENT '额外信息(备用字段)';
-- 2023-01-05 更新字符集编码
ALTER TABLE hehui_sys_notification CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

22
db/notification.sql Normal file
View File

@ -0,0 +1,22 @@
CREATE TABLE `platform_info` (
`id` int NOT NULL AUTO_INCREMENT,
`platform_code` varchar(50) NOT NULL DEFAULT '' COMMENT '平台编码',
`platform_name` varchar(50) NOT NULL DEFAULT '' COMMENT '平台名称',
`created_at` datetime DEFAULT NULL COMMENT '创建时间',
`updated_at` datetime DEFAULT NULL COMMENT '更新时间',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标志',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
CREATE TABLE `gitlink_sys_notification` (
`id` int NOT NULL AUTO_INCREMENT,
`sender` int NOT NULL COMMENT '发送者id',
`receiver` int NOT NULL COMMENT '接受者id',
`content` text NOT NULL COMMENT '消息内容',
`notification_url` varchar(255) DEFAULT NULL COMMENT '消息跳转url',
`created_at` datetime DEFAULT NULL COMMENT '创建时间',
`status` tinyint(4) NOT NULL COMMENT '消息状态1-未读2-已读3-未删除4-已删除',
PRIMARY KEY (`id`),
KEY `index_on_receiver_and_status` (`receiver`,`status`),
KEY `index_on_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

View File

@ -1,30 +0,0 @@
USE gitlink_notification;
-- 2022-02-14 新增红山平台
INSERT INTO gns_platform_info(platform_code,platform_name,created_at,is_delete) VALUES('osredm','红山平台',NOW(),-1);
DROP TABLE IF EXISTS `osredm_sys_notification`;
CREATE TABLE `osredm_sys_notification` (
`id` INT NOT NULL AUTO_INCREMENT,
`sender` INT(11) NOT NULL COMMENT '发送者id',
`receiver` INT(11) NOT NULL COMMENT '接受者id',
`content` TEXT NOT NULL COMMENT '消息内容:富文本',
`notification_url` VARCHAR(2000) DEFAULT NULL COMMENT '消息跳转链接',
`created_at` DATETIME NOT NULL DEFAULT NOW() COMMENT '创建时间',
`status` TINYINT(4) NOT NULL DEFAULT 1 COMMENT '已读状态: 1未读2已读',
`is_delete` TINYINT(1) NOT NULL DEFAULT '-1' COMMENT '是否删除: -1未删除1已删除',
PRIMARY KEY (`id`),
KEY `index_on_receiver_and_status` (`receiver`,`status`),
KEY `index_on_status` (`status`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb3;
-- 2021-09-10 区分系统消息类型
ALTER TABLE osredm_sys_notification ADD COLUMN (`type` TINYINT(4) NOT NULL DEFAULT 1 COMMENT '消息类型: 1系统消息2@我');
-- 2021-09-10 新增 source 字段区分消息来源、新增 extra 字段保存额外信息
ALTER TABLE osredm_sys_notification ADD source varchar(250) NULL COMMENT '消息来源';
ALTER TABLE osredm_sys_notification ADD extra TEXT NULL COMMENT '额外信息(备用字段)';
-- 2023-01-05 更新字符集编码
ALTER TABLE osredm_sys_notification CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

121
db/xxl-job-structure.sql Normal file
View File

@ -0,0 +1,121 @@
#
# XXL-JOB v2.3.0
# Copyright (c) 2015-present, xuxueli.
CREATE database if NOT EXISTS `gitlink_notification` default character set utf8mb4 collate utf8mb4_unicode_ci;
use `gitlink_notification`;
SET NAMES utf8mb4;
CREATE TABLE `xxl_job_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_desc` varchar(255) NOT NULL,
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`author` varchar(64) DEFAULT NULL COMMENT '作者',
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
`schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
`schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
`misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID多个逗号分隔',
`trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态0-停止1-运行',
`trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
`trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
`trigger_msg` text COMMENT '调度-日志',
`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
`handle_msg` text COMMENT '执行-日志',
`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态0-默认、1-无需告警、2-告警成功、3-告警失败',
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
`running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
`suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
`fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_registry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(12) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型0=自动注册、1=手动录入',
`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`role` tinyint(4) NOT NULL COMMENT '角色0-普通用户、1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限执行器ID列表多个逗号分割',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');
commit;

View File

@ -21,17 +21,11 @@
<version>${springboot.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.xuxueli/xxl-job-core -->
<dependency>
<groupId>cn.org.gitlink.notification</groupId>
<artifactId>gns-common</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>cn.org.gitlink.notification</groupId>
<artifactId>gns-model</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
@ -41,13 +35,6 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>

View File

@ -2,12 +2,8 @@ package cn.org.gitlink.notification.executor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@ComponentScan("cn.org.gitlink.notification.*")
@SpringBootApplication
@EnableTransactionManagement
public class ExecutorApplication {
public static void main(String[] args) {
SpringApplication.run(ExecutorApplication.class, args);}

View File

@ -0,0 +1,54 @@
package cn.org.gitlink.notification.executor.core.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class XXLJobConfig {
private Logger logger = LoggerFactory.getLogger(XXLJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.appname}")
private String appname;
@Value("${xxl.job.executor.address}")
private String address;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
}

View File

@ -1,111 +0,0 @@
package cn.org.gitlink.notification.executor.service.email;
import cn.org.gitlink.notification.common.constant.NotificationSystemConstant;
import cn.org.gitlink.notification.common.utils.EmailUtils;
import cn.org.gitlink.notification.model.dao.entity.EmailJob;
import cn.org.gitlink.notification.model.dao.entity.EmailSendRecord;
import cn.org.gitlink.notification.model.service.notification.EmailJobsService;
import cn.org.gitlink.notification.model.service.notification.EmailSendRecordsService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.mail.MessagingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Component
public class EmailService {
private Logger logger = LogManager.getLogger(EmailService.class);
@Autowired
private EmailJobsService emailJobsService;
@Autowired
private EmailSendRecordsService emailSendRecordsService;
@Autowired
private EmailUtils emailUtils;
/**
* 处理邮件发送任务根据emails添加到邮件发送记录表中
*
* @param platform 平台编码
* @param dispatchNumber 待处理发送任务列表数量
* @return: void
* @Author: wanjia
* @Date: 2021/9/15
*/
@Transactional
public void DispatchEmailJobs(String platform, Integer dispatchNumber) {
//获取指定数量待处理列表
List<EmailJob> emailJobList = new ArrayList<>();
try {
emailJobList = emailJobsService.getEmailJobsByDispatchedStatus(platform, NotificationSystemConstant.EMAIL_JOB_NOT_DISPATCHED, dispatchNumber);
} catch (Exception e) {
logger.error("获取未处理邮件任务列表失败:\n" + e);
}
//将EmailJob分配到email_send_records中
Boolean flag = null;
for (EmailJob emailJob : emailJobList) {
try {
flag = emailSendRecordsService.createEmailSendRecords(platform, emailJob.getEmails(), emailJob.getId());
} catch (Exception e) {
logger.error("处理EmailJob失败email_job_id: " + emailJob.getId() + "\n" + e);
}
//EmailJob分配成功更新状态
try {
emailJobsService.markEmailJobAs(platform, emailJob.getId(), new Date(), flag ? NotificationSystemConstant.EMAIL_JOB_DISPATCHED_SUCCESS : NotificationSystemConstant.EMAIL_JOB_DISPATCHED_FAIL);
} catch (Exception e) {
logger.error("更新EmailJob状态失败email_job_id: " + emailJob.getId() + "\n" + e);
}
}
}
/**
* 发送邮件
*
* @param platform 平台编码
* @param sentNumber 一次发送数量
* @return: void
* @Author: wanjia
* @Date: 2021/9/15
*/
@Transactional
public void sendEmail(String platform, Integer sentNumber) {
//获取待发送列表
List<EmailSendRecord> emailSendRecordList = new ArrayList<>();
try {
emailSendRecordList = emailSendRecordsService.getRecordsByStatus(platform, NotificationSystemConstant.EMAIL_UNSENT_RECORD, sentNumber);
} catch (Exception e) {
logger.error("获取未发送邮件列表失败:\n" + e);
}
//发送邮件
Boolean flag = null;
for (EmailSendRecord unSentEmailSendRecord : emailSendRecordList) {
flag = false;
try {
emailUtils.sendMail(unSentEmailSendRecord.getSubject(), unSentEmailSendRecord.getEmail(), unSentEmailSendRecord.getContent());
flag = true;
unSentEmailSendRecord.setSentAt(new Date());
unSentEmailSendRecord.setStatus(flag ? NotificationSystemConstant.EMAIL_SENT_SUCCESS : NotificationSystemConstant.EMAIL_SENT_FAIL);
} catch (Exception e) {
unSentEmailSendRecord.setStatus(NotificationSystemConstant.EMAIL_SENT_FAIL);
logger.error("发送邮件失败email: " + unSentEmailSendRecord.getEmail() + "\n" + e);
}
}
//更新emailSendRecord状态
try {
emailSendRecordsService.markEmailSendRecordsAs(platform, emailSendRecordList);
} catch (Exception e) {
logger.error(e);
}
}
}

View File

@ -1,52 +0,0 @@
package cn.org.gitlink.notification.executor.service.jobhandler;
import cn.org.gitlink.notification.common.utils.KafkaUtil;
import cn.org.gitlink.notification.model.dao.entity.vo.NewEmailJobVo;
import cn.org.gitlink.notification.model.service.notification.EmailJobsService;
import com.alibaba.fastjson.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.KafkaHandler;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
@Configuration
@KafkaListener(topics = "${spring.kafka.consumer.topic_email}", groupId = "${spring.kafka.consumer.group_id_email}")
public class EmailJobsListener {
private Logger logger = LogManager.getLogger(EmailJobsListener.class);
@Autowired
private EmailJobsService emailJobsService;
@Value("${spring.kafka.producer.topic_new_email_remind}")
private String gitlinkNewEmailRemindTopic;
@Autowired
@Qualifier(value = "GitlinkKafkaUtil")
private KafkaUtil kafkaUtil;
@KafkaHandler
public void messageHandler(String message) {
try {
NewEmailJobVo newEmailJobVo = JSONObject.parseObject(message, NewEmailJobVo.class);
Boolean flag = emailJobsService.createEmailJob(newEmailJobVo);
//if the message is inserted successfully, send a new email-job message to kafka
if (flag){
kafkaUtil.sendMessage(gitlinkNewEmailRemindTopic, JSONObject.toJSONString(newEmailJobVo));
}
} catch (Exception e) {
logger.error(e);
}
}
@KafkaHandler(isDefault = true)
public void defaultHandler(Object object) {
logger.error("Unknow object received. ->" + object);
}//end of method
}

View File

@ -1,39 +0,0 @@
package cn.org.gitlink.notification.executor.service.jobhandler;
import cn.org.gitlink.notification.executor.service.email.EmailService;
import cn.org.gitlink.notification.model.dao.entity.vo.NewEmailJobVo;
import com.alibaba.fastjson.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.KafkaHandler;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
@Configuration
@KafkaListener(topics = "${spring.kafka.consumer.topic_new_email_remind}", groupId = "${spring.kafka.consumer.group_id_email}")
public class EmailSentListener {
private Logger logger = LogManager.getLogger(EmailSentListener.class);
@Autowired
private EmailService emailService;
@KafkaHandler
public void messageHandler(String message) {
NewEmailJobVo newEmailJobVo = JSONObject.parseObject(message, NewEmailJobVo.class);
//处理邮件任务
emailService.DispatchEmailJobs(newEmailJobVo.getPlatform(), 1);
//发送邮件
emailService.sendEmail(newEmailJobVo.getPlatform(), 100);
}
@KafkaHandler(isDefault = true)
public void defaultHandler(Object object) {
logger.error("Unknow object received. ->" + object);
}//end of method
}

View File

@ -1,38 +0,0 @@
package cn.org.gitlink.notification.executor.service.jobhandler;
import cn.org.gitlink.notification.model.dao.entity.vo.NewSysNotificationVo;
import cn.org.gitlink.notification.model.service.notification.SysNotificationService;
import com.alibaba.fastjson.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.KafkaHandler;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
@Configuration
@KafkaListener(topics = "${spring.kafka.consumer.topic}", groupId = "${spring.kafka.consumer.group_id}")
public class NotificationListener {
private Logger logger = LogManager.getLogger(NotificationListener.class);
@Autowired
private SysNotificationService sysNotificationService;
@KafkaHandler
public void messageHandler(String message) {
try {
NewSysNotificationVo newSysNotificationVo = JSONObject.parseObject(message, NewSysNotificationVo.class);
sysNotificationService.sendNotification(newSysNotificationVo);
} catch (Exception e) {
logger.error(e);
}
}
@KafkaHandler(isDefault = true)
public void defaultHandler(Object object) {
logger.error("Unknow object received. ->" + object);
}//end of method
}

View File

@ -0,0 +1,250 @@
package cn.org.gitlink.notification.executor.service.jobhandler;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
/**
* XxlJob开发示例Bean模式
*
* 开发步骤
* 1任务开发在Spring Bean实例中开发Job方法
* 2注解配置为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")"注解value值对应的是调度中心新建任务的JobHandler属性的值
* 3执行日志需要通过 "XxlJobHelper.log" 打印执行日志
* 4任务结果默认任务结果为 "成功" 状态不需要主动设置如有诉求比如设置任务结果为失败可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果
*
*/
@Component
public class SampleXXLJob {
private static Logger logger = LoggerFactory.getLogger(SampleXXLJob.class);
/**
* 1简单任务示例Bean模式
*/
@XxlJob("demoJobHandler")
public void demoJobHandler() throws Exception {
XxlJobHelper.log("XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) {
XxlJobHelper.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2);
}
// default success
}
/**
* 2分片广播任务
*/
@XxlJob("shardingJobHandler")
public void shardingJobHandler() throws Exception {
// 分片参数
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
XxlJobHelper.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardIndex, shardTotal);
// 业务逻辑
for (int i = 0; i < shardTotal; i++) {
if (i == shardIndex) {
XxlJobHelper.log("第 {} 片, 命中分片开始处理", i);
} else {
XxlJobHelper.log("第 {} 片, 忽略", i);
}
}
}
/**
* 3命令行任务
*/
@XxlJob("commandJobHandler")
public void commandJobHandler() throws Exception {
String command = XxlJobHelper.getJobParam();
int exitValue = -1;
BufferedReader bufferedReader = null;
try {
// command process
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command(command);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
//Process process = Runtime.getRuntime().exec(command);
BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream());
bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream));
// command log
String line;
while ((line = bufferedReader.readLine()) != null) {
XxlJobHelper.log(line);
}
// command exit
process.waitFor();
exitValue = process.exitValue();
} catch (Exception e) {
XxlJobHelper.log(e);
} finally {
if (bufferedReader != null) {
bufferedReader.close();
}
}
if (exitValue == 0) {
// default success
} else {
XxlJobHelper.handleFail("command exit value("+exitValue+") is failed");
}
}
/**
* 4跨平台Http任务
* 参数示例
* "url: http://www.baidu.com\n" +
* "method: get\n" +
* "data: content\n";
*/
@XxlJob("httpJobHandler")
public void httpJobHandler() throws Exception {
// param parse
String param = XxlJobHelper.getJobParam();
if (param==null || param.trim().length()==0) {
XxlJobHelper.log("param["+ param +"] invalid.");
XxlJobHelper.handleFail();
return;
}
String[] httpParams = param.split("\n");
String url = null;
String method = null;
String data = null;
for (String httpParam: httpParams) {
if (httpParam.startsWith("url:")) {
url = httpParam.substring(httpParam.indexOf("url:") + 4).trim();
}
if (httpParam.startsWith("method:")) {
method = httpParam.substring(httpParam.indexOf("method:") + 7).trim().toUpperCase();
}
if (httpParam.startsWith("data:")) {
data = httpParam.substring(httpParam.indexOf("data:") + 5).trim();
}
}
// param valid
if (url==null || url.trim().length()==0) {
XxlJobHelper.log("url["+ url +"] invalid.");
XxlJobHelper.handleFail();
return;
}
if (method==null || !Arrays.asList("GET", "POST").contains(method)) {
XxlJobHelper.log("method["+ method +"] invalid.");
XxlJobHelper.handleFail();
return;
}
boolean isPostMethod = method.equals("POST");
// request
HttpURLConnection connection = null;
BufferedReader bufferedReader = null;
try {
// connection
URL realUrl = new URL(url);
connection = (HttpURLConnection) realUrl.openConnection();
// connection setting
connection.setRequestMethod(method);
connection.setDoOutput(isPostMethod);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setReadTimeout(5 * 1000);
connection.setConnectTimeout(3 * 1000);
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
connection.setRequestProperty("Accept-Charset", "application/json;charset=UTF-8");
// do connection
connection.connect();
// data
if (isPostMethod && data!=null && data.trim().length()>0) {
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
dataOutputStream.write(data.getBytes("UTF-8"));
dataOutputStream.flush();
dataOutputStream.close();
}
// valid StatusCode
int statusCode = connection.getResponseCode();
if (statusCode != 200) {
throw new RuntimeException("Http Request StatusCode(" + statusCode + ") Invalid.");
}
// result
bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
StringBuilder result = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
result.append(line);
}
String responseMsg = result.toString();
XxlJobHelper.log(responseMsg);
return;
} catch (Exception e) {
XxlJobHelper.log(e);
XxlJobHelper.handleFail();
return;
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (connection != null) {
connection.disconnect();
}
} catch (Exception e2) {
XxlJobHelper.log(e2);
}
}
}
/**
* 5生命周期任务示例任务初始化与销毁时支持自定义相关逻辑
*/
@XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy")
public void demoJobHandler2() throws Exception {
XxlJobHelper.log("XXL-JOB, Hello World.");
}
public void init(){
logger.info("init");
}
public void destroy(){
logger.info("destory");
}
}

View File

@ -0,0 +1,17 @@
server.port=8083
logging.config=classpath:logback.xml
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### xxl-job, access token
xxl.job.accessToken=
### xxl-job executor appname
xxl.job.executor.appname=xxl-job-executor-trustie-sample
### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
xxl.job.executor.address=
### xxl-job executor server-info
xxl.job.executor.ip=
xxl.job.executor.port=82
### xxl-job executor log-path
xxl.job.executor.logpath=./log/xxl-job/jobhandler
### xxl-job executor log-retention-days
xxl.job.executor.logretentiondays=30

View File

@ -1,59 +0,0 @@
server:
port: 8083
logging:
config: classpath:logback.xml
spring:
kafka:
producer:
bootstrap_servers: kafka1:9092,kafka2:9092
retries: 5
batch_size: 16384
replication_factor: 1
partitions: 3
topic_new_email_remind: topic-gitlink-new-email-remind
# 需要初始化的topic, 添加新的topic后要在这里加上, 用逗号隔开
topics: ${spring.kafka.producer.topic_new_email_remind}
consumer:
bootstrap_servers: kafka1:9092,kafka2:9092
group_id: group-gitlink-notification
group_id_email: group-gitlink-email
group_id_new_email_remind: group-gitlink-new-email-remind
auto_offset_reset: earliest
max_poll_records: 100
enable-auto-commit: true
auto-commit-interval: 1S
topic: topic-gitlink-notification
topic_email: topic-gitlink-email
topic_new_email_remind: topic-gitlink-new-email-remind
listener:
concurrency: 1
ack-mode: record
redis:
database: 0
host: redis
port: 6379
password:
pool:
max-active: 200
max-wait: -1
max-idle: 10
min-idle: 0
timeout: 1000
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://mysql:3306/gitlink_notification?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&allowMultiQueries=true&useSSL=false
username: gitlink
password: giTlinK0^827
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
serialization:
indent_output: true
fail_on_empty_beans: false
white-list: '*'

View File

@ -2,7 +2,7 @@
<configuration debug="false" scan="true" scanPeriod="1 seconds">
<contextName>logback</contextName>
<property name="log.path" value="./logs/executor.log"/>
<property name="log.path" value="./logs/xxl-job-executor-sample-springboot.log"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>

View File

@ -1,12 +0,0 @@
spring.mail.host=smtp.exmail.qq.com
spring.mail.default-encoding=utf-8
spring.mail.port=465
spring.mail.username=gitlink@barats.cn
spring.mail.password=
spring.mail.properties[mail.smtp.auth]=true
spring.mail.properties[mail.smtp.connectiontimeout]=10000
spring.mail.properties[mail.smtp.timeout]=10000
spring.mail.properties[mail.smtp.writetimeout]=10000
spring.mail.properties[mail.smtp.starttls.enable]=true
spring.mail.properties[mail.smtp.socketFactory.port]=465
spring.mail.properties[mail.smtp.socketFactory.class]=javax.net.ssl.SSLSocketFactory

View File

@ -5,29 +5,25 @@
MYSQL_VERSION=5.7.35
REDIS_VERSION=6.2.5
KAFKA_VERSION=latest
GITLINK_NOTIFICATION_SYS_VERSION=1.0.0
XXL_JOB_ADMIN_VERSION=2.3.0
#============================================ Container config ============================================
MYSQL_CONTAINER_NAME=gitlink_mysql
REDIS_CONTAINER_NAME=gitlink_redis
ZOOKEEPER_CONTAINER_NAME=gitlink_zookeeper
KAFKA_CONTAINER_01_NAME=gitlink_kafka_01
KAFKA_CONTAINER_02_NAME=gitlink_kafka_02
GNS_EXECUTOR_CONTAINER_NAME=gns_executor
GNS_READER_CONTAINER_NAME=gns_reader
GNS_WRITER_CONTAINER_NAME=gns_writer
XXL_JOB_ADMIN_CONTAINER_NAME=gitlink_xxl_job_admin
ZOOKEEPER_CONTAINER_NAME=gitlink_zookeepr
KAFKA_CONTAINER_NAME=gitlink_kafka
KAFKA_MANAGER_CONTAINER_NAME=gitlink_kafka_manager
#============================================ Ports config ============================================
MYSQL_LOCAL_PORT=33306
REDIS_LOCAL_PORT=6379
ZOOKEEPER_LOCAL_PORT=22181
KAFKA_01_LOCAL_PORT=29092
KAFKA_02_LOCAL_PORT=39092
GNS_EXECUTOR_LOCAL_PORT=8083
GNS_WRITER_LOCAL_PORT=58082
GNS_READER_LOCAL_PORT=58080
MYSQL_LOCAL_PORT=33306 # TODO: MysQL 本地端口
REDIS_LOCAL_PORT=6379 # TODO: Redis 本地端口
ZOOKEEPER_LOCAL_PORT=2181 # TODO: Zookeeper 本地端口
KAFKA_LOCAL_PORT=9092 # TODO: Kafka 本地端口
KAFKA_MANAGER_LOCAL_PORT=9003 # TODO: Kafka 管理本地端口
XXL_JOB_ADMIN_LOCAL_PORT=9999 #TODO: xxl-job-admin 本地端口
#============================================ Path config ============================================
# TODO: 需要预执行的 sql 脚本目录
@ -40,4 +36,12 @@ DOCKER_DATA_PATH=/Users/barat/Documents/Institutue/repos/gitlink-notification-sy
MYSQL_ROOT_PASSWORD=gitLiNk_827
MYSQL_USER=gitlink
MYSQL_PASSWORD=giTlinK0^827
MYSQL_DATABASE=gitlink_notification
MYSQL_DATABASE=gitlink_notification
#============================================ Kafaka config ============================================
KAFKA_LOG_RETENTION_HOURS=120
KAFKA_MESSAGE_MAX_BYTES=10000000
KAFKA_REPLICA_FETCH_MAX_BYTES=10000000
KAFKA_GROUP_MAX_SESSION_TIMEOUT_MS=60000
KAFKA_NUM_PARTITIONS=3
KAFKA_DELETE_RETENTION_MS=1000

View File

@ -1 +0,0 @@
docker-compose -f services.yml down && docker volume prune -f && mvn -f ../pom.xml clean

View File

@ -1 +0,0 @@
docker-compose -f services.yml down && docker volume prune -f && mvn -f ../pom.xml clean

View File

@ -1,13 +0,0 @@
# Dockerfile for gns-writer.jar
#FROM maven:3.8.2-openjdk-11-slim AS build
#COPY . /data
#WORKDIR /data
#RUN mvn clean package -DskipTests
FROM openjdk:11.0.12-jre-slim
COPY executor/target/gns-executor-1.0.0.jar /data/gns-executor-app.jar
WORKDIR /data
EXPOSE 8083
ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS gns-executor-app.jar"]

View File

@ -1,13 +0,0 @@
# Dockerfile for gns-writer.jar
#FROM maven:3.8.2-openjdk-11-slim AS build
#COPY . /data
#WORKDIR /data
#RUN mvn clean package -DskipTests
FROM openjdk:11.0.12-jre-slim
COPY reader/target/gns-reader-1.0.0.jar /data/gns-reader-app.jar
WORKDIR /data
EXPOSE 8081
ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS gns-reader-app.jar"]

View File

@ -1,181 +1,104 @@
version: '3'
services:
mysql:
image: mysql:${MYSQL_VERSION}
container_name: ${MYSQL_CONTAINER_NAME}
hostname: mysql
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- TZ=Asia/Shanghai
volumes:
- ${DOCKER_DATA_PATH}/mysql:/var/lib/mysql
- ${SQL_SCRIPT_PATH}/gns-notification.sql:/docker-entrypoint-initdb.d/0001.sql
- ${SQL_SCRIPT_PATH}/hehui-gns-notification.sql:/docker-entrypoint-initdb.d/0002.sql
- ${SQL_SCRIPT_PATH}/gns-email.sql:/docker-entrypoint-initdb.d/0003.sql
- ${SQL_SCRIPT_PATH}/osredm-gns-notification.sql:/docker-entrypoint-initdb.d/0004.sql
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
ports:
- ${MYSQL_LOCAL_PORT}:3306
networks:
- gitlink_network
restart: always
redis:
image: redis:${REDIS_VERSION}
container_name: ${REDIS_CONTAINER_NAME}
hostname: redis
volumes:
- ${DOCKER_DATA_PATH}/redis/data:/data
- ${DOCKER_DATA_PATH}/redis/logs:/logs
environment:
- TZ=Asia/Shanghai
ports:
- ${REDIS_LOCAL_PORT}:6379
networks:
- gitlink_network
restart: always
# See Also: https://hub.docker.com/r/confluentinc/cp-zookeeper
zookeeper:
image: confluentinc/cp-zookeeper:latest
container_name: ${ZOOKEEPER_CONTAINER_NAME}
hostname: zookeeper
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
ports:
- ${ZOOKEEPER_LOCAL_PORT}:2181
# volumes:
# - ${DOCKER_DATA_PATH}/zookeeper:/var/lib/zookeeper
networks:
- gitlink_network
restart: always
# See Also: https://hub.docker.com/r/confluentinc/cp-kafka
kafka1:
image: confluentinc/cp-kafka:latest
container_name: ${KAFKA_CONTAINER_01_NAME}
hostname: kafka1
depends_on:
- zookeeper
ports:
- ${KAFKA_01_LOCAL_PORT}:29092
# volumes:
# - ${DOCKER_DATA_PATH}/kafka/${KAFKA_CONTAINER_01_NAME}/lib:/var/lib/kafka
# - ${DOCKER_DATA_PATH}/kafka/${KAFKA_CONTAINER_01_NAME}/logs:/var/logs/kafka
# - ${DOCKER_DATA_PATH}/kafka/${KAFKA_CONTAINER_01_NAME}/conf:/etc/kafka
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9092,PLAINTEXT_HOST://localhost:${KAFKA_01_LOCAL_PORT}
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
networks:
- gitlink_network
restart: always
# See Also: https://hub.docker.com/r/confluentinc/cp-kafka
kafka2:
image: confluentinc/cp-kafka:latest
container_name: ${KAFKA_CONTAINER_02_NAME}
hostname: kafka2
depends_on:
- zookeeper
ports:
- ${KAFKA_02_LOCAL_PORT}:39092
# volumes:
# - ${DOCKER_DATA_PATH}/kafka/${KAFKA_CONTAINER_02_NAME}/lib:/var/lib/kafka
# - ${DOCKER_DATA_PATH}/kafka/${KAFKA_CONTAINER_02_NAME}/logs:/var/logs/kafka
# - ${DOCKER_DATA_PATH}/kafka/${KAFKA_CONTAINER_02_NAME}/conf:/etc/kafka
environment:
KAFKA_BROKER_ID: 2
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka2:9092,PLAINTEXT_HOST://localhost:${KAFKA_02_LOCAL_PORT}
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
networks:
- gitlink_network
restart: always
gitlink-reader:
container_name: ${GNS_READER_CONTAINER_NAME}
hostname: gitlink_reader
image: gitlink/gns-reader:${GITLINK_NOTIFICATION_SYS_VERSION}
build:
context: ../
dockerfile: middleware/reader.Dockerfile
networks:
- gitlink_network
environment:
- TZ=Asia/Shanghai
volumes:
- ${DOCKER_DATA_PATH}/gitlink/:/data/logs/
depends_on:
- kafka1
- kafka2
- redis
- mysql
ports:
- ${GNS_READER_LOCAL_PORT}:8081
restart: always
gitlink-writer:
container_name: ${GNS_WRITER_CONTAINER_NAME}
hostname: gitlink_writer
image: gitlink/gns-writer:${GITLINK_NOTIFICATION_SYS_VERSION}
build:
context: ../
dockerfile: middleware/writer.Dockerfile
networks:
- gitlink_network
environment:
- TZ=Asia/Shanghai
volumes:
- ${DOCKER_DATA_PATH}/gitlink/:/data/logs/
depends_on:
- kafka1
- kafka2
- redis
- mysql
ports:
- ${GNS_WRITER_LOCAL_PORT}:8082
restart: always
gitlink-executor:
container_name: ${GNS_EXECUTOR_CONTAINER_NAME}
hostname: gitlink_executor
image: gitlink/gns-executor:${GITLINK_NOTIFICATION_SYS_VERSION}
build:
context: ../
dockerfile: middleware/executor.Dockerfile
networks:
- gitlink_network
volumes:
- ${DOCKER_DATA_PATH}/gitlink/:/data/logs/
environment:
- TZ=Asia/Shanghai
depends_on:
- kafka1
- kafka2
- redis
- mysql
ports:
- ${GNS_EXECUTOR_LOCAL_PORT}:8083
restart: always
networks:
gitlink_network:
driver: bridge
name: gitlink_network
driver_opts:
com.docker.network.enable_ipv6: "true"
version: '3'
services:
mysql:
image: mysql:${MYSQL_VERSION}
container_name: ${MYSQL_CONTAINER_NAME}
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
volumes:
- ${DOCKER_DATA_PATH}/mysql:/var/lib/mysql
- ${SQL_SCRIPT_PATH}/xxl-job-structure.sql:/docker-entrypoint-initdb.d/0000.sql
ports:
- ${MYSQL_LOCAL_PORT}:3306
networks:
- gitlink_network
redis:
image: redis:${REDIS_VERSION}
container_name: ${REDIS_CONTAINER_NAME}
volumes:
- ${DOCKER_DATA_PATH}/redis/data:/data
- ${DOCKER_DATA_PATH}/redis/logs:/logs
ports:
- ${REDIS_LOCAL_PORT}:6379
networks:
- gitlink_network
xxl-job-admin:
image: xuxueli/xxl-job-admin:${XXL_JOB_ADMIN_VERSION}
container_name: ${XXL_JOB_ADMIN_CONTAINER_NAME}
environment:
- JAVA_OPTS=-Xmx512m
- PARAMS=--spring.datasource.url=jdbc:mysql://${MYSQL_CONTAINER_NAME}:3306/gitlink_notification?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai --spring.datasource.username=${MYSQL_USER} --spring.datasource.password=${MYSQL_PASSWORD}
volumes:
- ${DOCKER_DATA_PATH}/xxl-job-admin:/data/applogs
ports:
- ${XXL_JOB_ADMIN_LOCAL_PORT}:8080
depends_on:
- mysql
networks:
- gitlink_network
zookeeper:
image: wurstmeister/zookeeper
container_name: ${ZOOKEEPER_CONTAINER_NAME}
ports:
- ${ZOOKEEPER_LOCAL_PORT}:2181
networks:
- gitlink_network
kafka:
image: wurstmeister/kafka
container_name: ${KAFKA_CONTAINER_NAME}
volumes:
- /etc/localtime:/etc/localtime
ports:
- ${KAFKA_LOCAL_PORT}:9092
networks:
- gitlink_network
environment:
KAFKA_ADVERTISED_HOST_NAME: ${KAFKA_CONTAINER_NAME}
KAFKA_ZOOKEEPER_CONNECT: ${ZOOKEEPER_CONTAINER_NAME}:2181
KAFKA_ADVERTISED_PORT: 9092
KAFKA_LOG_RETENTION_HOURS: ${KAFKA_LOG_RETENTION_HOURS}
KAFKA_MESSAGE_MAX_BYTES: ${KAFKA_MESSAGE_MAX_BYTES}
KAFKA_REPLICA_FETCH_MAX_BYTES: ${KAFKA_REPLICA_FETCH_MAX_BYTES}
KAFKA_GROUP_MAX_SESSION_TIMEOUT_MS: ${KAFKA_GROUP_MAX_SESSION_TIMEOUT_MS}
KAFKA_NUM_PARTITIONS: ${KAFKA_NUM_PARTITIONS}
KAFKA_DELETE_RETENTION_MS: ${KAFKA_DELETE_RETENTION_MS}
kafka-manager:
image: sheepkiller/kafka-manager
container_name: ${KAFKA_MANAGER_CONTAINER_NAME}
networks:
- gitlink_network
environment:
ZK_HOSTS: ${ZOOKEEPER_CONTAINER_NAME}
ports:
- ${KAFKA_MANAGER_LOCAL_PORT}:9000
networks:
gitlink_network:
driver: bridge
name: gitlink_network
driver_opts:
com.docker.network.enable_ipv6: "true"

View File

@ -1 +0,0 @@
mvn -f ../pom.xml clean package -DskipTests && docker-compose -f services.yml up --build --force-recreate

View File

@ -1 +0,0 @@
mvn -f ../pom.xml clean package -DskipTests && docker-compose -f services.yml up --build --force-recreate

View File

@ -1,13 +0,0 @@
# Dockerfile for gns-writer.jar
#FROM maven:3.8.2-openjdk-11-slim AS build
#COPY . /data
#WORKDIR /data
#RUN mvn clean package -DskipTests
FROM openjdk:11.0.12-jre-slim
COPY writer/target/gns-writer-1.0.0.jar /data/gns-writer-app.jar
WORKDIR /data
EXPOSE 8082
ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS gns-writer-app.jar"]

View File

@ -26,59 +26,5 @@
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>cn.org.gitlink.notification</groupId>
<artifactId>gns-common</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
<!-- mybatis-plus begin -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.0</version>
</dependency>
<!-- mybatis-plus end -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.3.4.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package cn.org.gitlink.notification.model;
public class Demo {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

View File

@ -1,14 +0,0 @@
package cn.org.gitlink.notification.model;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement
public class ModelApplication {
public static void main(String[] args) {
SpringApplication.run(ModelApplication.class, args);
}
}

View File

@ -1,35 +0,0 @@
package cn.org.gitlink.notification.model.config;
import cn.org.gitlink.notification.model.handler.MetaHandler;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement
@Configuration
@MapperScan("cn.org.gitlink.notification.model.dao")
public class MyBatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
/**
* 自动填充功能
* @return
*/
@Bean
public GlobalConfig globalConfig() {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setMetaObjectHandler(new MetaHandler());
return globalConfig;
}
}

View File

@ -1,96 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Date;
public class EmailJob {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer sender;
private String emails;
private String subject;
private String content;
@JsonProperty("created_at")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createdAt;
@JsonProperty("dispatched_at")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date dispatchedAt;
private Integer dispatchedStatus;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getSender() {
return sender;
}
public void setSender(Integer sender) {
this.sender = sender;
}
public String getEmails() {
return emails;
}
public void setEmails(String emails) {
this.emails = emails == null ? null : emails.trim();
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject == null ? null : subject.trim();
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content == null ? null : content.trim();
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getDispatchedAt() {
return dispatchedAt;
}
public void setDispatchedAt(Date dispatchedAt) {
this.dispatchedAt = dispatchedAt;
}
public Integer getDispatchedStatus() {
return dispatchedStatus;
}
public void setDispatchedStatus(Integer dispatchedStatus) {
this.dispatchedStatus = dispatchedStatus;
}
}

View File

@ -1,98 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Date;
public class EmailSendRecord {
@TableId(type = IdType.AUTO)
private Integer id;
private String email;
private Integer jobId;
@JsonProperty("created_at")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createdAt;
@JsonProperty("sent_at")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date sentAt;
private Integer status;
@TableField(exist = false)
private String content;
@TableField(exist = false)
private String subject;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email == null ? null : email.trim();
}
public Integer getJobId() {
return jobId;
}
public void setJobId(Integer jobId) {
this.jobId = jobId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getSentAt() {
return sentAt;
}
public void setSentAt(Date sentAt) {
this.sentAt = sentAt;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
}

View File

@ -1,69 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.util.Date;
public class PlatformInfo {
@TableId(type = IdType.AUTO)
private Integer id;
private String platformCode;
private String platformName;
private Date createdAt;
private Date updatedAt;
private Boolean isDelete;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getPlatformCode() {
return platformCode;
}
public void setPlatformCode(String platformCode) {
this.platformCode = platformCode == null ? null : platformCode.trim();
}
public String getPlatformName() {
return platformName;
}
public void setPlatformName(String platformName) {
this.platformName = platformName == null ? null : platformName.trim();
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Boolean getIsDelete() {
return isDelete;
}
public void setIsDelete(Boolean isDelete) {
this.isDelete = isDelete;
}
}

View File

@ -1,126 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Date;
public class SysNotification {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer sender;
private Integer receiver;
private String content;
@JsonProperty("notification_url")
private String notificationUrl;
@JsonProperty("created_at")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createdAt;
private Integer status;
private Integer type;
@JsonIgnore
private Integer isDelete;
private String source;
private String extra;
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getSender() {
return sender;
}
public void setSender(Integer sender) {
this.sender = sender;
}
public Integer getReceiver() {
return receiver;
}
public void setReceiver(Integer receiver) {
this.receiver = receiver;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content == null ? null : content.trim();
}
public String getNotificationUrl() {
return notificationUrl;
}
public void setNotificationUrl(String notificationUrl) {
this.notificationUrl = notificationUrl == null ? null : notificationUrl.trim();
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Integer getIsDelete() {
return isDelete;
}
public void setIsDelete(Integer isDelete) {
this.isDelete = isDelete;
}
}

View File

@ -1,48 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity.vo;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
public class DeleteNotificationsVo {
@ApiModelProperty(value = "消息ids,'-1' 全部消息", required = true)
@NotBlank
@Pattern(regexp = "^(\\-|\\+?)\\d+(,\\d+)*$", message = "消息id串非法")
private String notificationIds;
@ApiModelProperty(value = "消息接收者", required = true)
@NotNull(message = "消息接收者不能为空")
private Integer receiver;
@ApiModelProperty(value = "消息类型 -1全部 1-系统消息 2-@我", required = true)
@Range(min = -1, max = 2)
@NotNull(message = "消息类型不能为空")
private Integer type;
public String getNotificationIds() {
return notificationIds;
}
public void setNotificationIds(String notificationIds) {
this.notificationIds = notificationIds;
}
public Integer getReceiver() {
return receiver;
}
public void setReceiver(Integer receiver) {
this.receiver = receiver;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
}

View File

@ -1,63 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity.vo;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
public class NewEmailJobParamsVo {
@ApiModelProperty(value = "邮件发送者", required = true)
@NotNull(message = "邮件发送者不能为空")
@Range(min = Integer.MIN_VALUE, max = Integer.MAX_VALUE)
private Integer sender;
@ApiModelProperty(value = "邮件地址eg: w@163.com,j@163.com", required = true)
@Pattern(regexp = "^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*(,\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*)*$", message = "邮件地址串非法")
@NotBlank(message = "邮件地址不能为空")
private String emails;
@ApiModelProperty(value = "邮件主题", required = true)
@NotBlank(message = "邮件主题不能为空")
@Size(max = 255, message = "邮件主题长度在0~255")
private String subject;
@ApiModelProperty(value = "邮件内容", required = true)
@NotBlank(message = "邮件内容不能为空")
private String content;
public Integer getSender() {
return sender;
}
public void setSender(Integer sender) {
this.sender = sender;
}
public String getEmails() {
return emails;
}
public void setEmails(String emails) {
this.emails = emails;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@ -1,74 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity.vo;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
public class NewEmailJobVo {
//平台编码
private String platform;
@ApiModelProperty(value = "邮件发送者", required = true)
@NotNull(message = "邮件发送者不能为空")
@Range(min = Integer.MIN_VALUE, max = Integer.MAX_VALUE)
private Integer sender;
@ApiModelProperty(value = "邮件地址eg: w@163.com,j@163.com", required = true)
@Pattern(regexp = "^(\\-|\\+?)\\d+(,\\d+)*$", message = "邮件地址串非法")
@NotBlank(message = "邮件地址不能为空")
private String emails;
@ApiModelProperty(value = "邮件主题", required = true)
@NotBlank(message = "邮件主题不能为空")
@Size(max = 255, message = "邮件主题长度在0~255")
private String subject;
@ApiModelProperty(value = "邮件内容", required = true)
@NotBlank(message = "邮件内容不能为空")
private String content;
public String getPlatform() {
return platform;
}
public void setPlatform(String platform) {
this.platform = platform;
}
public Integer getSender() {
return sender;
}
public void setSender(Integer sender) {
this.sender = sender;
}
public String getEmails() {
return emails;
}
public void setEmails(String emails) {
this.emails = emails;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@ -1,102 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity.vo;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
/**
* @description:
* @author: wanjia
* @time: 2021/9/10
*/
public class NewSysNotificationParamsVo {
@ApiModelProperty(value = "消息发送者", required = true)
@NotNull(message = "消息发送者不能为空")
@Range(min = Integer.MIN_VALUE, max = Integer.MAX_VALUE)
private Integer sender;
@ApiModelProperty(value = "消息接收者", required = true)
@Pattern(regexp = "^(\\-|\\+?)\\d+(,\\d+)*$", message = "接收者id串非法")
@NotBlank(message = "消息接收者不能为空")
private String receivers;
@ApiModelProperty(value = "消息内容", required = true)
@NotBlank(message = "消息内容不能为空")
private String content;
@ApiModelProperty(value = "消息跳转链接")
@Size(max = 2000, message = "消息跳转链接长度在0~2000")
private String notification_url;
@ApiModelProperty(value = "消息类型 1-系统消息 2-@我", required = true)
@Range(min = 1, max = 2)
@NotNull(message = "消息类型不能为空")
private Integer type;
@ApiModelProperty(value = "消息来源")
private String source;
@ApiModelProperty(value = "额外信息")
private String extra;
public Integer getSender() {
return sender;
}
public void setSender(Integer sender) {
this.sender = sender;
}
public String getReceivers() {
return receivers;
}
public void setReceivers(String receivers) {
this.receivers = receivers;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getNotification_url() {
return notification_url;
}
public void setNotification_url(String notification_url) {
this.notification_url = notification_url;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
}

View File

@ -1,107 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity.vo;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
public class NewSysNotificationVo {
//平台编码
private String platform;
@ApiModelProperty(value = "消息发送者", required = true)
@NotNull(message = "消息发送者不能为空")
@Range(min = Integer.MIN_VALUE, max = Integer.MAX_VALUE)
private Integer sender;
@ApiModelProperty(value = "消息接收者", required = true)
@Pattern(regexp = "^(\\-|\\+?)\\d+(,\\d+)*$", message = "接收者id串非法")
@NotBlank(message = "消息接收者不能为空")
private String receivers;
@ApiModelProperty(value = "消息内容", required = true)
@NotBlank(message = "消息内容不能为空")
private String content;
@ApiModelProperty(value = "消息跳转链接")
@Size(max = 2000, message = "消息跳转链接长度在0~2000")
private String notification_url;
@ApiModelProperty(value = "消息类型 1-系统消息 2-@我", required = true)
@Range(min = 1, max = 2)
@NotNull(message = "消息类型不能为空")
private Integer type;
@ApiModelProperty(value = "消息来源")
private String source;
@ApiModelProperty(value = "额外信息")
private String extra;
public String getPlatform() {
return platform;
}
public void setPlatform(String platform) {
this.platform = platform;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
public Integer getSender() {
return sender;
}
public void setSender(Integer sender) {
this.sender = sender;
}
public String getReceivers() {
return receivers;
}
public void setReceivers(String receivers) {
this.receivers = receivers;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getNotification_url() {
return notification_url;
}
public void setNotification_url(String notification_url) {
this.notification_url = notification_url;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
}

View File

@ -1,48 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
public class ReceiverNotificationCountVo implements Serializable {
private Integer receiver;
@JsonProperty("unread_notification")
private Integer unreadNotification;
private Integer type;
public ReceiverNotificationCountVo() {
}
public ReceiverNotificationCountVo(Integer receiver, Integer unreadNotification, Integer type) {
this.receiver = receiver;
this.unreadNotification = unreadNotification;
this.type = type;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Integer getReceiver() {
return receiver;
}
public void setReceiver(Integer receiver) {
this.receiver = receiver;
}
public Integer getUnreadNotification() {
return unreadNotification;
}
public void setUnreadNotification(Integer unreadNotification) {
this.unreadNotification = unreadNotification;
}
}

View File

@ -1,120 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity.vo;
import cn.org.gitlink.notification.model.dao.entity.SysNotification;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
public class ReceiverNotificationListVo {
private Integer receiver;
private Integer type;
@JsonProperty("unread_total")
private Integer totalUnreadNotifiationCount;
@JsonProperty("unread_notification")
private Integer unreadNotificationCount;
@JsonProperty("unread_atme")
private Integer unreadAtMeCount;
@JsonProperty("records")
private List<SysNotification> records;
@JsonProperty("records_count")
private long recordsCount;
@JsonProperty("page_num")
private long pageNum;
@JsonProperty("total_page_count")
private long totalPageCount;
@JsonProperty("page_size")
private long pageSize;
public ReceiverNotificationListVo() {
}
public Integer getReceiver() {
return receiver;
}
public void setReceiver(Integer receiver) {
this.receiver = receiver;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Integer getTotalUnreadNotifiationCount() {
return totalUnreadNotifiationCount;
}
public void setTotalUnreadNotifiationCount(Integer totalUnreadNotifiationCount) {
this.totalUnreadNotifiationCount = totalUnreadNotifiationCount;
}
public Integer getUnreadNotificationCount() {
return unreadNotificationCount;
}
public void setUnreadNotificationCount(Integer unreadNotificationCount) {
this.unreadNotificationCount = unreadNotificationCount;
}
public Integer getUnreadAtMeCount() {
return unreadAtMeCount;
}
public void setUnreadAtMeCount(Integer unreadAtMeCount) {
this.unreadAtMeCount = unreadAtMeCount;
}
public List<SysNotification> getRecords() {
return records;
}
public void setRecords(List<SysNotification> records) {
this.records = records;
}
public long getRecordsCount() {
return recordsCount;
}
public void setRecordsCount(long recordsCount) {
this.recordsCount = recordsCount;
}
public long getPageNum() {
return pageNum;
}
public void setPageNum(long pageNum) {
this.pageNum = pageNum;
}
public long getTotalPageCount() {
return totalPageCount;
}
public void setTotalPageCount(long totalPageCount) {
this.totalPageCount = totalPageCount;
}
public long getPageSize() {
return pageSize;
}
public void setPageSize(long pageSize) {
this.pageSize = pageSize;
}
}

View File

@ -1,66 +0,0 @@
package cn.org.gitlink.notification.model.dao.entity.vo;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
/**
* @description:
* @author: wanjia
* @time: 2021/9/10
*/
public class UpdateNotificationStatusParamsVo {
@ApiModelProperty(value = "消息ids,'-1' 全部消息", required = true)
@NotBlank
@Pattern(regexp = "^(\\-|\\+?)\\d+(,\\d+)*$", message = "消息id串非法")
private String notificationIds;
@ApiModelProperty(value = "已读状态: 1未读2已读", required = true)
@NotNull
@Range(min = 1, max = 2)
private Integer status;
@ApiModelProperty(value = "消息接收者", required = true)
@NotNull(message = "消息接收者不能为空")
private Integer receiver;
@ApiModelProperty(value = "消息类型 -1全部 1-系统消息 2-@我", required = true)
@Range(min = -1, max = 2)
@NotNull(message = "消息类型不能为空")
private Integer type;
public String getNotificationIds() {
return notificationIds;
}
public void setNotificationIds(String notificationIds) {
this.notificationIds = notificationIds;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getReceiver() {
return receiver;
}
public void setReceiver(Integer receiver) {
this.receiver = receiver;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
}

View File

@ -1,23 +0,0 @@
package cn.org.gitlink.notification.model.dao.mapper;
import cn.org.gitlink.notification.model.dao.entity.EmailJob;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface EmailJobsMapper extends BaseMapper<EmailJob> {
int deleteByPrimaryKey(@Param("platform") String platform, Integer id);
int insert(@Param("platform") String platform, @Param("record") EmailJob record);
int insertSelective(@Param("platform") String platform, @Param("record") EmailJob record);
EmailJob selectByPrimaryKey(@Param("platform") String platform, Integer id);
int updateByPrimaryKeySelective(@Param("platform") String platform, @Param("record") EmailJob record);
int updateByPrimaryKey(@Param("platform") String platform, @Param("record") EmailJob record);
List<EmailJob> getEmailJobsByDispatchedStatus(@Param("platform") String platform, @Param("dispatchedStatus") Integer dispatchedStatus, @Param("size") Integer size);
}

View File

@ -1,29 +0,0 @@
package cn.org.gitlink.notification.model.dao.mapper;
import cn.org.gitlink.notification.model.dao.entity.EmailSendRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface EmailSendRecordsMapper extends BaseMapper<EmailSendRecord> {
int deleteByPrimaryKey(@Param("platform") String platform, Integer id);
int insert(@Param("platform") String platform, @Param("record") EmailSendRecord record);
int insertSelective(@Param("platform") String platform, @Param("record") EmailSendRecord record);
EmailSendRecord selectByPrimaryKey(@Param("platform") String platform, Integer id);
int updateByPrimaryKeySelective(@Param("platform") String platform, @Param("record") EmailSendRecord record);
int updateByPrimaryKey(@Param("platform") String platform, @Param("record") EmailSendRecord record);
//批量插入邮件发送任务记录
int insertEmailSendRecordBatch(@Param("platform") String platform,@Param("list") List<EmailSendRecord> emailSendRecordList);
List<EmailSendRecord> getRecordsByStatus(@Param("platform") String platform, @Param("status") Integer status, @Param("size") Integer sentNumber);
//批量更新邮件发送任务记录
int updateEmailSendRecordsBatch(@Param("platform") String platform, @Param("list") List<EmailSendRecord> emailSendRecordList);
}

View File

@ -1,10 +0,0 @@
package cn.org.gitlink.notification.model.dao.mapper;
import org.apache.ibatis.annotations.Param;
public interface OperateTableMapper {
int existTable(@Param("tableName")String tableName);
int dropTable(@Param("tableName")String tableName);
int createNewTable(@Param("tableName")String tableName);
// int insert(@Param("tableName")String tableName,@Param("trackpoint")Trackpoint trackpoint);
}

View File

@ -1,18 +0,0 @@
package cn.org.gitlink.notification.model.dao.mapper;
import cn.org.gitlink.notification.model.dao.entity.PlatformInfo;
public interface PlatformInfoMapper {
int deleteByPrimaryKey(Integer id);
int insert(PlatformInfo record);
int insertSelective(PlatformInfo record);
PlatformInfo selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(PlatformInfo record);
int updateByPrimaryKey(PlatformInfo record);
}

View File

@ -1,58 +0,0 @@
package cn.org.gitlink.notification.model.dao.mapper;
import cn.org.gitlink.notification.model.dao.entity.SysNotification;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface SysNotificationMapper extends BaseMapper<SysNotification> {
int deleteByPrimaryKey(@Param("platform") String platform, Integer id);
int insert(@Param("platform") String platform, @Param("record") SysNotification record);
int insertSelective(@Param("platform") String platform, @Param("record") SysNotification record);
SysNotification selectByPrimaryKey(@Param("platform") String platform, Integer id);
int updateByPrimaryKeySelective(@Param("platform") String platform, SysNotification record);
int updateByPrimaryKey(@Param("platform") String platform, @Param("record") SysNotification record);
int updateStatusByNotificationId(@Param("platform") String platform,
@Param("receiver") Integer receiver,
@Param("notificationIds") String notificationIds,
@Param("status") Integer status,
@Param("type") Integer type);
int getNewSysNotificationNumber(@Param("platform") String platform,
@Param("receiver") Integer receiver,
@Param("type") Integer type,
@Param("status") Integer status);
List<SysNotification> getUnreadSysNotificationsList(@Param("platform") String platform,
@Param("receiver") Integer receiver,
@Param("status") Integer status,
@Param("notificationNumber") Integer notificationNumber,
@Param("type") Integer type);
List<SysNotification> getSysNotificationPageList(Page page, String orderBy,
@Param("type") int type,
@Param("sources") String sources,
@Param("platform") String platform,
@Param("receiver") Integer receiver,
@Param("status") Integer status);
int getSysNotificationNumberByType(@Param("platform") String platform,
@Param("receiver") Integer receiver,
@Param("type") Integer type);
int deleteNotificationByIds(@Param("platform") String platform,
@Param("receiver") Integer receiver,
@Param("notificationIds") String notificationIds,
@Param("type") Integer type);
//批量插入系统消息数据
int insertSysNotificationsBatch(@Param("platform") String platform, @Param("list") List<SysNotification> sysNotificationList);
}

View File

@ -1,28 +0,0 @@
package cn.org.gitlink.notification.model.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MetaHandler implements MetaObjectHandler {
/**
* 更新数据执行
* @param metaObject
*/
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updatedAt", new Date(), metaObject);
}
/**
* 新增数据执行
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createdAt", new Date(), metaObject);
this.setFieldValByName("updatedAt", new Date(), metaObject);
}
}

View File

@ -1,47 +0,0 @@
package cn.org.gitlink.notification.model.service.notification;
import cn.org.gitlink.notification.model.dao.entity.EmailJob;
import cn.org.gitlink.notification.model.dao.entity.vo.NewEmailJobVo;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.Date;
import java.util.List;
public interface EmailJobsService extends IService<EmailJob> {
/**
* 添加发送邮件任务
*
* @param newEmailJobVo
* @return: boolean
* @Author: wanjia
* @Date: 2021/9/13
*/
boolean createEmailJob(NewEmailJobVo newEmailJobVo) throws Exception;
/**
* 获取所有未处理邮件任务列表
*
* @param platform 平台编码
* @param dispatchedStatus 发送状态-1 未处理,1 处理成功,2 处理失败
* @param size 列表大小
* @return: List<EmailJob>
* @Author: wanjia
* @Date: 2021/9/13
*/
List<EmailJob> getEmailJobsByDispatchedStatus(String platform,Integer dispatchedStatus, Integer size) throws Exception;
/**
* 更新邮件任务状态
*
* @param platform 平台编码
* @param emailJobId 邮件任务id
* @param dispatchedAt 处理时间
* @param dispatchedStatus 处理状态 -1 未处理,1 处理成功,2 处理失败
* @return: int
* @Author: wanjia
* @Date: 2021/9/13
*/
int markEmailJobAs(String platform, Integer emailJobId, Date dispatchedAt, Integer dispatchedStatus) throws Exception;
}

View File

@ -1,44 +0,0 @@
package cn.org.gitlink.notification.model.service.notification;
import cn.org.gitlink.notification.model.dao.entity.EmailSendRecord;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
public interface EmailSendRecordsService extends IService<EmailSendRecord> {
/**
* 新增邮件任务到邮件发送记录表中
*
* @param platform 平台编码
* @param emails 邮件地址eg: w@163.com,j@163.com
* @param jobId 邮件任务id
* @return: boolean
* @Author: wanjia
* @Date: 2021/9/13
*/
boolean createEmailSendRecords(String platform, String emails, Integer jobId) throws Exception;
/**
* 获取发送记录列表
*
* @param platform 平台编码
* @param status 邮件发送记录状态 -1未发送 1发送成功 2发送失败
* @param size 列表数量
* @return: List<EmailSendRecord>
* @Author: wanjia
* @Date: 2021/9/15
*/
List<EmailSendRecord> getRecordsByStatus(String platform, Integer status, Integer size) throws Exception;
/**
* 变更邮件发送记录状态
*
* @param platform 平台编码
* @param emailSendRecordList 待更新列表
* @return: int
* @Author: wanjia
* @Date: 2021/9/13
*/
int markEmailSendRecordsAs(String platform, List<EmailSendRecord> emailSendRecordList) throws Exception;
}

View File

@ -1,28 +0,0 @@
package cn.org.gitlink.notification.model.service.notification;
import cn.org.gitlink.notification.model.dao.mapper.OperateTableMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Component
public class OperateTableService {
@Resource
private OperateTableMapper operateTableMapper;
Logger logger = LoggerFactory.getLogger(this.getClass());
@Transactional
public Boolean createTableByPlatform(String platformCode){
if(operateTableMapper.existTable(platformCode + "_sys_notification") > 0){
logger.info("该平台已存在:" + platformCode);
return false;
}
operateTableMapper.dropTable(platformCode);
operateTableMapper.createNewTable(platformCode);
return true;
}
}

View File

@ -1,62 +0,0 @@
package cn.org.gitlink.notification.model.service.notification;
import cn.org.gitlink.notification.model.dao.entity.SysNotification;
import cn.org.gitlink.notification.model.dao.entity.vo.NewSysNotificationVo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
public interface SysNotificationService extends IService<SysNotification> {
//给用户发送消息
boolean sendNotification(NewSysNotificationVo sysNotification) throws Exception;
/**
* 设置系统消息状态为
*
* @param platform 平台编号
* @param notificationIds 消息编号列表中英文逗号隔开eg221,2323,4,111,23123
* @param status 1 未读 2已读
* @param type 类型 -1 全部 1 系统消息2 @我
* @return
*/
int markNotificationAs(String platform, Integer receiver, String notificationIds, Integer status, Integer type) throws Exception;
/**
* 获取消息总数
*
* @param platform 平台编号
* @param receiver 信息接收者
* @param type 类型-1 返回全部1 系统消息2 @我消息
* @param status 状态 -1 全部1 未读 2 已读
* @return
*/
int getNotificationCount(String platform, Integer receiver, Integer type, Integer status) throws Exception;
/**
* 获取消息列表
*
* @param platform 平台编号
* @param receiver 消息接收者
* @param status 状态 -1 全部1 未读 2 已读
* @param type 类型 -1 全部 1 系统消息2 @我
* @param sources
* @param page 页码
* @param size 页大小
* @return
*/
Page<SysNotification> getNotification(String platform, Integer receiver, Integer status, Integer type, String sources, Integer page, Integer size) throws Exception;
/**
* @Description: 批量删除系统消息
*
* @Param platform 平台编码
* @Param notificationIds 消息编号列表中英文逗号隔开eg221,2323,4,111,23123
* @Param type -1 全部 1 系统消息 2 @我
* @return: int
* @Author: wanjia
* @Date: 2021/9/13
*/
int deleteNotifications(String platform, Integer receiver, String notificationIds, Integer type) throws Exception;
}

View File

@ -1,38 +0,0 @@
package cn.org.gitlink.notification.model.service.notification.impl;
import cn.org.gitlink.notification.model.dao.entity.EmailJob;
import cn.org.gitlink.notification.model.dao.entity.vo.NewEmailJobVo;
import cn.org.gitlink.notification.model.dao.mapper.EmailJobsMapper;
import cn.org.gitlink.notification.model.service.notification.EmailJobsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
@Service(value = "EmailJobsServiceImpl")
public class EmailJobsServiceImpl extends ServiceImpl<EmailJobsMapper, EmailJob> implements EmailJobsService {
@Override
public boolean createEmailJob(NewEmailJobVo newEmailJobVo) {
String platform = newEmailJobVo.getPlatform();
EmailJob emailJob = new EmailJob();
BeanUtils.copyProperties(newEmailJobVo, emailJob);
return baseMapper.insertSelective(platform, emailJob) > 0;
}
@Override
public List<EmailJob> getEmailJobsByDispatchedStatus(String platform,Integer dispatchedStatus, Integer size) {
return baseMapper.getEmailJobsByDispatchedStatus(platform,dispatchedStatus, size);
}
@Override
public int markEmailJobAs(String platform, Integer emailJobId, Date dispatchedAt, Integer dispatchedStatus) {
EmailJob emailJob = new EmailJob();
emailJob.setId(emailJobId);
emailJob.setDispatchedAt(dispatchedAt);
emailJob.setDispatchedStatus(dispatchedStatus);
return baseMapper.updateByPrimaryKeySelective(platform, emailJob);
}
}

View File

@ -1,41 +0,0 @@
package cn.org.gitlink.notification.model.service.notification.impl;
import cn.org.gitlink.notification.model.dao.entity.EmailSendRecord;
import cn.org.gitlink.notification.model.dao.mapper.EmailSendRecordsMapper;
import cn.org.gitlink.notification.model.service.notification.EmailSendRecordsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Service(value = "EmailSendRecordsServiceImpl")
public class EmailSendRecordsServiceImpl extends ServiceImpl<EmailSendRecordsMapper, EmailSendRecord> implements EmailSendRecordsService {
@Override
@Transactional
public boolean createEmailSendRecords(String platform, String emails, Integer jobId) {
List<String> list = Arrays.asList(emails.split(","));
List<EmailSendRecord> emailSendRecordList = new ArrayList<EmailSendRecord>();
for (String email : list){
EmailSendRecord emailSendRecord = new EmailSendRecord();
emailSendRecord.setJobId(jobId);
emailSendRecord.setEmail(email);
emailSendRecordList.add(emailSendRecord);
}
int i = baseMapper.insertEmailSendRecordBatch(platform, emailSendRecordList);
return i > 0;
}
@Override
public int markEmailSendRecordsAs(String platform, List<EmailSendRecord> emailSendRecordList){
return baseMapper.updateEmailSendRecordsBatch(platform, emailSendRecordList);
}
@Override
public List<EmailSendRecord> getRecordsByStatus(String platform, Integer status, Integer sentNumber){
return baseMapper.getRecordsByStatus(platform, status, sentNumber);
}
}

View File

@ -1,117 +0,0 @@
package cn.org.gitlink.notification.model.service.notification.impl;
import cn.org.gitlink.notification.common.utils.RedisUtil;
import cn.org.gitlink.notification.model.dao.entity.SysNotification;
import cn.org.gitlink.notification.model.dao.entity.vo.NewSysNotificationVo;
import cn.org.gitlink.notification.model.dao.mapper.SysNotificationMapper;
import cn.org.gitlink.notification.model.service.notification.SysNotificationService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Service(value = "SysNotificationServiceImpl")
public class SysNotificationServiceImpl extends ServiceImpl<SysNotificationMapper, SysNotification> implements SysNotificationService {
private static final String CACHE_KEY_PREFIX = "GNSCPre";
@Autowired
@Qualifier(value = "GitlinkRedisUtil")
private RedisUtil redisUtil;
@Override
@Transactional
public boolean sendNotification(NewSysNotificationVo newSysNotificationVo) {
List<SysNotification> sysNotificationList = new ArrayList<>();
List<String> list = Arrays.asList(newSysNotificationVo.getReceivers().split(","));
for (String receiver : list) {
SysNotification sysNotification = new SysNotification();
sysNotification.setSender(newSysNotificationVo.getSender());
sysNotification.setContent(newSysNotificationVo.getContent());
sysNotification.setNotificationUrl(newSysNotificationVo.getNotification_url());
sysNotification.setType(newSysNotificationVo.getType());
sysNotification.setSource(newSysNotificationVo.getSource());
sysNotification.setExtra(newSysNotificationVo.getExtra());
sysNotification.setReceiver(Integer.parseInt(receiver));
sysNotificationList.add(sysNotification);
}
baseMapper.insertSysNotificationsBatch(newSysNotificationVo.getPlatform(), sysNotificationList);
for (String receiver : list){
this.delUserCache(newSysNotificationVo.getPlatform(), Integer.parseInt(receiver));
}
return true;
}
@Override
public int markNotificationAs(String platform, Integer receiver, String notificationIds, Integer status, Integer type) {
int count = baseMapper.updateStatusByNotificationId(platform, receiver, notificationIds, status, type);
if (count > 0) {
this.delUserCache(platform, receiver);
}
return count;
}
@Override
public int getNotificationCount(String platform, Integer receiver, Integer type, Integer status) {
String cacheKey = cacheKeyForCount(platform, receiver, type, status);
Object foundResult = this.redisUtil.get(cacheKey);
if (foundResult != null) {
return (Integer) foundResult;
}
int count = baseMapper.getNewSysNotificationNumber(platform, receiver, type, status);
this.redisUtil.set(cacheKey, count);
return count;
}
@Override
public Page<SysNotification> getNotification(String platform, Integer receiver, Integer status, Integer type, String sources, Integer page, Integer size) {
String cacheKey = cacheKeyForPage(platform, receiver, type, sources, status, page, size);
Object foundResult = this.redisUtil.get(cacheKey);
if (foundResult != null) {
return (Page<SysNotification>) foundResult;
}
Page<SysNotification> pageItem = new Page<SysNotification>(page, size);
List<SysNotification> sysNotificationList = baseMapper.getSysNotificationPageList(
pageItem, "", type, sources, platform, receiver, status
);
pageItem.setRecords(sysNotificationList);
this.redisUtil.set(cacheKey, pageItem);
return pageItem;
}
@Override
public int deleteNotifications(String platform, Integer receiver, String notificationIds, Integer type) {
int count = baseMapper.deleteNotificationByIds(platform, receiver, notificationIds, type);
if (count > 0) {
this.delUserCache(platform, receiver);
}
return count;
}
//////////////////////////////// 私有方法 ////////////////////////////////
private void delUserCache(String platform, Integer receiver) {
redisUtil.scanAndDel(cachePrefixForPlatform(platform, receiver) + "*");
}//end of method
private static String cacheKeyForCount(String platform, Integer receiver, Integer type, Integer status) {
return String.format("%s#T%s#S%s#Count", cachePrefixForPlatform(platform, receiver), type, status);
}
private static String cacheKeyForPage(String platform, Integer receiver, Integer type, String sources, Integer status, Integer page, Integer size) {
return String.format("%s#T%s#%s#S%s#P%s_S%s", cachePrefixForPlatform(platform, receiver), type, sources, status, page, size);
}
private static String cachePrefixForPlatform(String platform, Integer receiver) {
return String.format("%s#%s#R%s", CACHE_KEY_PREFIX, platform.trim().toUpperCase(), receiver);
}
}

View File

@ -1,7 +0,0 @@
spring:
datasource:
# 配置数据源类型
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:33306/gitlink_notification?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&allowMultiQueries=true
username: gitlink
password: giTlinK0^827

View File

@ -1,135 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.org.gitlink.notification.model.dao.mapper.EmailJobsMapper" >
<resultMap id="BaseResultMap" type="cn.org.gitlink.notification.model.dao.entity.EmailJob" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="sender" property="sender" jdbcType="INTEGER" />
<result column="emails" property="emails" jdbcType="VARCHAR" />
<result column="subject" property="subject" jdbcType="VARCHAR" />
<result column="content" property="content" jdbcType="VARCHAR" />
<result column="created_at" property="createdAt" jdbcType="TIMESTAMP" />
<result column="dispatched_at" property="dispatchedAt" jdbcType="TIMESTAMP" />
<result column="dispatched_status" property="dispatchedStatus" jdbcType="INTEGER" />
</resultMap>
<sql id="Base_Column_List" >
id, sender, emails, subject, content, created_at, dispatched_at, dispatched_status
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from ${platform}_email_jobs
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from ${platform}_email_jobs
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="cn.org.gitlink.notification.model.dao.entity.EmailJob" >
insert into ${platform}_email_jobs (id, sender, emails,
subject, content, created_at,
dispatched_at, dispatched_status)
values (#{record.id,jdbcType=INTEGER}, #{record.sender,jdbcType=INTEGER}, #{record.emails,jdbcType=VARCHAR},
#{record.subject,jdbcType=VARCHAR}, #{record.content,jdbcType=VARCHAR}, #{record.createdAt,jdbcType=TIMESTAMP},
#{record.dispatchedAt,jdbcType=TIMESTAMP}, #{record.dispatchedStatus,jdbcType=INTEGER})
</insert>
<insert id="insertSelective" parameterType="cn.org.gitlink.notification.model.dao.entity.EmailJob" >
insert into ${platform}_email_jobs
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="record.id != null" >
id,
</if>
<if test="record.sender != null" >
sender,
</if>
<if test="record.emails != null" >
emails,
</if>
<if test="record.subject != null" >
subject,
</if>
<if test="record.content != null" >
content,
</if>
<if test="record.createdAt != null" >
created_at,
</if>
<if test="record.dispatchedAt != null" >
dispatched_at,
</if>
<if test="record.dispatchedStatus != null" >
dispatched_status,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="record.id != null" >
#{record.id,jdbcType=INTEGER},
</if>
<if test="record.sender != null" >
#{record.sender,jdbcType=INTEGER},
</if>
<if test="record.emails != null" >
#{record.emails,jdbcType=VARCHAR},
</if>
<if test="record.subject != null" >
#{record.subject,jdbcType=VARCHAR},
</if>
<if test="record.content != null" >
#{record.content,jdbcType=VARCHAR},
</if>
<if test="record.createdAt != null" >
#{record.createdAt,jdbcType=TIMESTAMP},
</if>
<if test="record.dispatchedAt != null" >
#{record.dispatchedAt,jdbcType=TIMESTAMP},
</if>
<if test="record.dispatchedStatus != null" >
#{record.dispatchedStatus,jdbcType=INTEGER},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="cn.org.gitlink.notification.model.dao.entity.EmailJob" >
update ${platform}_email_jobs
<set >
<if test="record.sender != null" >
sender = #{record.sender,jdbcType=INTEGER},
</if>
<if test="record.emails != null" >
emails = #{record.emails,jdbcType=VARCHAR},
</if>
<if test="record.subject != null" >
subject = #{record.subject,jdbcType=VARCHAR},
</if>
<if test="record.content != null" >
content = #{record.content,jdbcType=VARCHAR},
</if>
<if test="record.createdAt != null" >
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
</if>
<if test="record.dispatchedAt != null" >
dispatched_at = #{record.dispatchedAt,jdbcType=TIMESTAMP},
</if>
<if test="record.dispatchedStatus != null" >
dispatched_status = #{record.dispatchedStatus,jdbcType=INTEGER},
</if>
</set>
where id = #{record.id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="cn.org.gitlink.notification.model.dao.entity.EmailJob" >
update ${platform}_email_jobs
set sender = #{record.sender,jdbcType=INTEGER},
emails = #{record.emails,jdbcType=VARCHAR},
subject = #{record.subject,jdbcType=VARCHAR},
content = #{record.content,jdbcType=VARCHAR},
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
dispatched_at = #{record.dispatchedAt,jdbcType=TIMESTAMP},
dispatched_status = #{record.dispatchedStatus,jdbcType=INTEGER}
where id = #{record.id,jdbcType=INTEGER}
</update>
<select id="getEmailJobsByDispatchedStatus" resultMap="BaseResultMap">
select * from ${platform}_email_jobs
where dispatched_status = #{dispatchedStatus} order by id desc
<if test="size != null">
limit #{size}
</if>
</select>
</mapper>

View File

@ -1,152 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.org.gitlink.notification.model.dao.mapper.EmailSendRecordsMapper" >
<resultMap id="BaseResultMap" type="cn.org.gitlink.notification.model.dao.entity.EmailSendRecord" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="email" property="email" jdbcType="VARCHAR" />
<result column="job_id" property="jobId" jdbcType="INTEGER" />
<result column="created_at" property="createdAt" jdbcType="TIMESTAMP" />
<result column="sent_at" property="sentAt" jdbcType="TIMESTAMP" />
<result column="status" property="status" jdbcType="INTEGER" />
</resultMap>
<sql id="Base_Column_List" >
id, email, job_id, created_at, sent_at, status
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from ${platform}_email_send_records
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from ${platform}_email_send_records
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="cn.org.gitlink.notification.model.dao.entity.EmailSendRecord" >
insert into ${platform}_email_send_records (id, email, job_id,
created_at, sent_at, status
)
values (#{record.id,jdbcType=INTEGER}, #{record.email,jdbcType=VARCHAR}, #{record.jobId,jdbcType=INTEGER},
#{record.createdAt,jdbcType=TIMESTAMP}, #{record.sentAt,jdbcType=TIMESTAMP}, #{record.status,jdbcType=INTEGER}
)
</insert>
<insert id="insertSelective" parameterType="cn.org.gitlink.notification.model.dao.entity.EmailSendRecord" >
insert into ${platform}_email_send_records
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="record.id != null" >
id,
</if>
<if test="record.email != null" >
email,
</if>
<if test="record.jobId != null" >
job_id,
</if>
<if test="record.createdAt != null" >
created_at,
</if>
<if test="record.sentAt != null" >
sent_at,
</if>
<if test="record.status != null" >
status,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="record.id != null" >
#{record.id,jdbcType=INTEGER},
</if>
<if test="record.email != null" >
#{record.email,jdbcType=VARCHAR},
</if>
<if test="record.jobId != null" >
#{record.jobId,jdbcType=INTEGER},
</if>
<if test="record.createdAt != null" >
#{record.createdAt,jdbcType=TIMESTAMP},
</if>
<if test="record.sentAt != null" >
#{record.sentAt,jdbcType=TIMESTAMP},
</if>
<if test="record.status != null" >
#{record.status,jdbcType=INTEGER},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="cn.org.gitlink.notification.model.dao.entity.EmailSendRecord" >
update ${platform}_email_send_records
<set >
<if test="record.email != null" >
email = #{record.email,jdbcType=VARCHAR},
</if>
<if test="record.jobId != null" >
job_id = #{record.jobId,jdbcType=INTEGER},
</if>
<if test="record.createdAt != null" >
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
</if>
<if test="record.sentAt != null" >
sent_at = #{record.sentAt,jdbcType=TIMESTAMP},
</if>
<if test="record.status != null" >
status = #{record.status,jdbcType=INTEGER},
</if>
</set>
where id = #{record.id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="cn.org.gitlink.notification.model.dao.entity.EmailSendRecord" >
update ${platform}_email_send_records
set email = #{record.email,jdbcType=VARCHAR},
job_id = #{record.jobId,jdbcType=INTEGER},
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
sent_at = #{record.sentAt,jdbcType=TIMESTAMP},
status = #{record.status,jdbcType=INTEGER}
where id = #{record.id,jdbcType=INTEGER}
</update>
<insert id ="insertEmailSendRecordBatch" parameterType="java.util.List" >
<selectKey resultType ="java.lang.Integer" keyProperty= "id"
order= "AFTER">
SELECT LAST_INSERT_ID()
</selectKey >
insert into ${platform}_email_send_records
(id, email, job_id)
values
<foreach collection ="list" item="record" index= "index" separator =",">
(
#{record.id,jdbcType=INTEGER}, #{record.email,jdbcType=VARCHAR}, #{record.jobId,jdbcType=INTEGER}
)
</foreach >
</insert >
<select id="getRecordsByStatus" resultMap="BaseResultMap">
select a.id, a.email, a.job_id, a.created_at, a.sent_at, a.status, b.subject, b.content
from ${platform}_email_send_records a
left join ${platform}_email_jobs b on a.job_id = b.id
where status = #{status} order by id desc
<if test="size != null">
limit #{size}
</if>
</select>
<update id="updateEmailSendRecordsBatch" parameterType="list">
update ${platform}_email_send_records
<trim prefix="set" suffixOverrides=",">
<trim prefix="sent_at =case" suffix="end,">
<foreach collection="list" item="item" index="index">
<if test="item.sentAt!=null">
when id=#{item.id} then #{item.sentAt}
</if>
</foreach>
</trim>
<trim prefix=" status =case" suffix="end,">
<foreach collection="list" item="item" index="index">
<if test="item.status!=null">
when id=#{item.id} then #{item.status}
</if>
</foreach>
</trim>
</trim>
where id in
<foreach collection="list" item="item" separator="," open="(" close=")">
#{item.id}
</foreach>
</update>
</mapper>

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.org.gitlink.notification.model.dao.mapper.OperateTableMapper" >
<select id="existTable" parameterType="String" resultType="Integer">
select count(*)
from information_schema.TABLES
where LCASE(table_name)= #{tableName}
</select>
<update id="dropTable">
DROP TABLE IF EXISTS ${tableName}_sys_notification
</update>
<update id="createNewTable" parameterType="String">
CREATE TABLE ${tableName}_sys_notification (
`id` INT NOT NULL AUTO_INCREMENT,
`sender` INT(11) NOT NULL COMMENT '发送者id',
`receiver` INT(11) NOT NULL COMMENT '接受者id',
`content` TEXT NOT NULL COMMENT '消息内容:富文本',
`notification_url` VARCHAR(2000) DEFAULT NULL COMMENT '消息跳转链接',
`created_at` DATETIME NOT NULL DEFAULT NOW() COMMENT '创建时间',
`status` TINYINT(4) NOT NULL DEFAULT 1 COMMENT '已读状态: 1未读2已读',
`is_delete` TINYINT(1) NOT NULL DEFAULT '-1' COMMENT '是否删除: -1未删除1已删除',
PRIMARY KEY (`id`),
KEY `index_on_receiver_and_status` (`receiver`,`status`),
KEY `index_on_status` (`status`))
</update>
</mapper>

View File

@ -1,106 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.org.gitlink.notification.model.dao.mapper.PlatformInfoMapper" >
<resultMap id="BaseResultMap" type="cn.org.gitlink.notification.model.dao.entity.PlatformInfo" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="platform_code" property="platformCode" jdbcType="VARCHAR" />
<result column="platform_name" property="platformName" jdbcType="VARCHAR" />
<result column="created_at" property="createdAt" jdbcType="TIMESTAMP" />
<result column="updated_at" property="updatedAt" jdbcType="TIMESTAMP" />
<result column="is_delete" property="isDelete" jdbcType="BIT" />
</resultMap>
<sql id="Base_Column_List" >
id, platform_code, platform_name, created_at, updated_at, is_delete
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from gns_platform_info
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from gns_platform_info
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="cn.org.gitlink.notification.model.dao.entity.PlatformInfo" >
insert into gns_platform_info (id, platform_code, platform_name,
created_at, updated_at, is_delete
)
values (#{id,jdbcType=INTEGER}, #{platformCode,jdbcType=VARCHAR}, #{platformName,jdbcType=VARCHAR},
#{createdAt,jdbcType=TIMESTAMP}, #{updatedAt,jdbcType=TIMESTAMP}, #{isDelete,jdbcType=BIT}
)
</insert>
<insert id="insertSelective" parameterType="cn.org.gitlink.notification.model.dao.entity.PlatformInfo" >
insert into gns_platform_info
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="platformCode != null" >
platform_code,
</if>
<if test="platformName != null" >
platform_name,
</if>
<if test="createdAt != null" >
created_at,
</if>
<if test="updatedAt != null" >
updated_at,
</if>
<if test="isDelete != null" >
is_delete,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="platformCode != null" >
#{platformCode,jdbcType=VARCHAR},
</if>
<if test="platformName != null" >
#{platformName,jdbcType=VARCHAR},
</if>
<if test="createdAt != null" >
#{createdAt,jdbcType=TIMESTAMP},
</if>
<if test="updatedAt != null" >
#{updatedAt,jdbcType=TIMESTAMP},
</if>
<if test="isDelete != null" >
#{isDelete,jdbcType=BIT},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="cn.org.gitlink.notification.model.dao.entity.PlatformInfo" >
update gns_platform_info
<set >
<if test="platformCode != null" >
platform_code = #{platformCode,jdbcType=VARCHAR},
</if>
<if test="platformName != null" >
platform_name = #{platformName,jdbcType=VARCHAR},
</if>
<if test="createdAt != null" >
created_at = #{createdAt,jdbcType=TIMESTAMP},
</if>
<if test="updatedAt != null" >
updated_at = #{updatedAt,jdbcType=TIMESTAMP},
</if>
<if test="isDelete != null" >
is_delete = #{isDelete,jdbcType=BIT},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="cn.org.gitlink.notification.model.dao.entity.PlatformInfo" >
update gns_platform_info
set platform_code = #{platformCode,jdbcType=VARCHAR},
platform_name = #{platformName,jdbcType=VARCHAR},
created_at = #{createdAt,jdbcType=TIMESTAMP},
updated_at = #{updatedAt,jdbcType=TIMESTAMP},
is_delete = #{isDelete,jdbcType=BIT}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>

View File

@ -1,238 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.org.gitlink.notification.model.dao.mapper.SysNotificationMapper">
<resultMap id="BaseResultMap" type="cn.org.gitlink.notification.model.dao.entity.SysNotification">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="sender" property="sender" jdbcType="INTEGER"/>
<result column="receiver" property="receiver" jdbcType="INTEGER"/>
<result column="content" property="content" jdbcType="VARCHAR"/>
<result column="notification_url" property="notificationUrl" jdbcType="VARCHAR"/>
<result column="created_at" property="createdAt" jdbcType="TIMESTAMP"/>
<result column="status" property="status" jdbcType="TINYINT"/>
<result column="type" property="type" jdbcType="TINYINT"/>
<result column="is_delete" property="isDelete" jdbcType="BIT"/>
<result column="source" property="source" jdbcType="VARCHAR"/>
<result column="extra" property="extra" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
id, sender, receiver, content, notification_url, created_at, status, type, is_delete, source, extra
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">
select
<include refid="Base_Column_List"/>
from ${platform}_sys_notification
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from ${platform}_sys_notification
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="cn.org.gitlink.notification.model.dao.entity.SysNotification">
insert into ${platform}_sys_notification (id, sender, receiver,
content, notification_url,
status, type, source, extra)
values (#{record.id,jdbcType=INTEGER}, #{record.sender,jdbcType=INTEGER}, #{record.receiver,jdbcType=INTEGER},
#{record.content,jdbcType=VARCHAR}, #{record.notificationUrl,jdbcType=VARCHAR},
#{record.status,jdbcType=TINYINT}, #{record.type,jdbcType=TINYINT})
#{record.source,jdbcType=VARCHAR}, #{record.extra,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" parameterType="cn.org.gitlink.notification.model.dao.entity.SysNotification">
insert into ${platform}_sys_notification
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="record.id != null">
id,
</if>
<if test="record.sender != null">
sender,
</if>
<if test="record.receiver != null">
receiver,
</if>
<if test="record.content != null">
content,
</if>
<if test="record.notificationUrl != null">
notification_url,
</if>
<if test="record.createdAt != null">
created_at,
</if>
<if test="record.status != null">
status,
</if>
<if test="record.type != null">
type,
</if>
<if test="record.isDelete != null">
is_delete,
</if>
<if test="record.source != null">
source,
</if>
<if test="record.extra != null">
extra,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="record.id != null">
#{record.id,jdbcType=INTEGER},
</if>
<if test="record.sender != null">
#{record.sender,jdbcType=INTEGER},
</if>
<if test="record.receiver != null">
#{record.receiver,jdbcType=INTEGER},
</if>
<if test="record.content != null">
#{record.content,jdbcType=VARCHAR},
</if>
<if test="record.notificationUrl != null">
#{record.notificationUrl,jdbcType=VARCHAR},
</if>
<if test="record.createdAt != null">
#{record.createdAt,jdbcType=TIMESTAMP},
</if>
<if test="record.status != null">
#{record.status,jdbcType=TINYINT},
</if>
<if test="record.type != null">
#{record.type,jdbcType=TINYINT},
</if>
<if test="record.isDelete != null">
#{record.isDelete,jdbcType=BIT},
</if>
<if test="record.source != null">
#{record.source,jdbcType=VARCHAR},
</if>
<if test="record.extra != null">
#{record.extra,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective"
parameterType="cn.org.gitlink.notification.model.dao.entity.SysNotification">
update ${platform}_sys_notification
<set>
<if test="record.sender != null">
sender = #{record.sender,jdbcType=INTEGER},
</if>
<if test="record.receiver != null">
receiver = #{record.receiver,jdbcType=INTEGER},
</if>
<if test="record.content != null">
content = #{record.content,jdbcType=VARCHAR},
</if>
<if test="record.notificationUrl != null">
notification_url = #{record.notificationUrl,jdbcType=VARCHAR},
</if>
<if test="record.createdAt != null">
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
</if>
<if test="record.status != null">
status = #{record.status,jdbcType=TINYINT},
</if>
<if test="record.type != null">
status = #{record.type,jdbcType=TINYINT},
</if>
<if test="record.isDelete != null">
is_delete = #{record.isDelete,jdbcType=BIT},
</if>
<if test="record.source != null">
source = #{record.source,jdbcType=VARCHAR},
</if>
<if test="record.extra != null">
extra = #{record.extra,jdbcType=VARCHAR},
</if>
</set>
where id = #{record.id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="cn.org.gitlink.notification.model.dao.entity.SysNotification">
update ${platform}_sys_notification
set sender = #{sender,jdbcType=INTEGER},
receiver = #{receiver,jdbcType=INTEGER},
content = #{content,jdbcType=VARCHAR},
notification_url = #{notificationUrl,jdbcType=VARCHAR},
created_at = #{createdAt,jdbcType=TIMESTAMP},
status = #{status,jdbcType=TINYINT},
type = #{type,jdbcType=TINYINT},
is_delete = #{isDelete,jdbcType=BIT},
source = #{source,jdbcType=VARCHAR}
extra = #{extra,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateStatusByNotificationId">
update ${platform}_sys_notification set status = #{status} where receiver=#{receiver}
<if test="type != -1">
and `type` = #{type}
</if>
<if test="notificationIds != '-1'">
and id in (${notificationIds})
</if>
</update>
<select id="getNewSysNotificationNumber" resultType="java.lang.Integer">
select count(`receiver`)
from ${platform}_sys_notification
where receiver = #{receiver}
<if test="type != -1">
and type = #{type}
</if>
<if test="status != -1">
and status = #{status}
</if>
AND is_delete = -1
</select>
<select id="getSysNotificationNumberByType" resultType="java.lang.Integer">
select count(*)
from ${platform}_sys_notification
where receiver = #{receiver} and status = 1 and `type` = #{type} AND is_delete = -1
</select>
<select id="getUnreadSysNotificationsList" resultMap="BaseResultMap">
select * FROM ${platform}_sys_notification
where receiver = #{receiver} AND status = #{status} AND `type` = #{type} AND is_delete = -1
ORDER BY id DESC limit #{notificationNumber}
</select>
<select id="getSysNotificationPageList" parameterType="cn.org.gitlink.notification.model.dao.entity.SysNotification"
resultMap="BaseResultMap">
select * FROM ${platform}_sys_notification
where receiver = #{receiver} AND is_delete = -1
<if test="type != -1">
and type = #{type}
</if>
<if test="status != -1">
and status = #{status}
</if>
<if test="sources != null and sources != ''">
and source in
<foreach collection="sources.split(',')" item="sources" open="(" separator="," close=")">
#{sources}
</foreach>
</if>
ORDER BY id DESC
</select>
<update id="deleteNotificationByIds">
update ${platform}_sys_notification set is_delete = 1 where receiver=#{receiver}
<if test="type != -1">
and `type` = #{type}
</if>
<if test="notificationIds != '-1'">
and id in (${notificationIds})
</if>
</update>
<insert id ="insertSysNotificationsBatch" parameterType="java.util.List" >
<selectKey resultType ="java.lang.Integer" keyProperty= "id"
order= "AFTER">
SELECT LAST_INSERT_ID()
</selectKey >
insert into ${platform}_sys_notification
(id, sender, receiver, content, notification_url, type, source, extra)
values
<foreach collection ="list" item="record" index= "index" separator =",">
(
#{record.id,jdbcType=INTEGER}, #{record.sender,jdbcType=INTEGER}, #{record.receiver,jdbcType=INTEGER},
#{record.content,jdbcType=VARCHAR}, #{record.notificationUrl,jdbcType=VARCHAR}, #{record.type,jdbcType=TINYINT},
#{record.source,jdbcType=VARCHAR}, #{record.extra,jdbcType=VARCHAR}
)
</foreach >
</insert >
</mapper>

View File

@ -1,13 +0,0 @@
package cn.org.gitlink.notification.model;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement
public class ModelApplicationTest {
public static void main(String[] args) {
SpringApplication.run(ModelApplicationTest.class, args);
}
}

View File

@ -1,31 +0,0 @@
package cn.org.gitlink.notification.model.service.notification;
import cn.org.gitlink.notification.model.dao.entity.vo.NewSysNotificationVo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.util.Assert;
@RunWith(MockitoJUnitRunner.class)
public class CachedServiceTest {
@Mock
SysNotificationService notificationService;
@Test(expected = NullPointerException.class)
public void testSendNotification() {
NewSysNotificationVo notificationVo = new NewSysNotificationVo();
notificationVo.setSender(1);
notificationVo.setContent("wowowowowo");
notificationVo.setReceivers("1111,2222,3333,4444,5555");
notificationVo.setExtra("extra_info");
notificationVo.setSource("delete_issue");
notificationVo.setType(1);
try {
Assert.isTrue(notificationService.sendNotification(notificationVo), "done");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -1,69 +0,0 @@
package cn.org.gitlink.notification.model.service.notification;
import cn.org.gitlink.notification.model.dao.entity.EmailJob;
import cn.org.gitlink.notification.model.dao.entity.vo.NewEmailJobVo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import java.util.Date;
import java.util.List;
@RunWith(MockitoJUnitRunner.class)
public class EmailServiceTest {
@Mock
EmailJobsService emailJobsService;
@Mock
EmailSendRecordsService emailSendRecordsService;
Logger logger = LoggerFactory.getLogger(this.getClass());
@Test
public void testEmailService(){
NewEmailJobVo emailJobVo = new NewEmailJobVo();
emailJobVo.setPlatform("gitlink");
emailJobVo.setSender(1);
emailJobVo.setEmails("w@163.com,j@163.com");
emailJobVo.setSubject("subjectTest");
emailJobVo.setContent("contentTest");
//添加发送邮件任务
try {
Assert.isTrue(emailJobsService.createEmailJob(emailJobVo), "done");
} catch (Exception e) {
e.printStackTrace();
}
//获取待处理邮件任务列表
try {
List<EmailJob> emailJobs = emailJobsService.getEmailJobsByDispatchedStatus("gitlink",-1,10);
Assert.notEmpty(emailJobs, "success");
} catch (Exception e) {
e.printStackTrace();
}
//获取待处理邮件任务列表并处理邮件任务在records表中插入发送记录数据
try {
List<EmailJob> emailJobs = emailJobsService.getEmailJobsByDispatchedStatus("gitlink", -1, 10);
for (EmailJob emailJob : emailJobs){
emailSendRecordsService.createEmailSendRecords("gitlink", emailJob.getEmails(), emailJob.getId());
}
//发送邮件成功后更新邮件发送记录
// int count = emailSendRecordsService.markEmailSendRecordsAs("gitlink", 1, new Date(), 1);
// Assert.isTrue(count > 0, "update email_send_record status success");
} catch (Exception e){
e.printStackTrace();
}
try {
int count = emailJobsService.markEmailJobAs("gitlink", 1, new Date(), 1);
Assert.isTrue(count > 0, "update status success");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -1,49 +0,0 @@
package cn.org.gitlink.notification.model.service.notification;
import cn.org.gitlink.notification.model.ModelApplicationTest;
import cn.org.gitlink.notification.model.dao.entity.SysNotification;
import cn.org.gitlink.notification.model.dao.entity.vo.NewSysNotificationVo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ModelApplicationTest.class)
public class ServiceTests {
@Autowired
SysNotificationService sysNotificationService;
@Autowired
OperateTableService operateTableService;
Logger logger = LoggerFactory.getLogger(this.getClass());
@Test
public void testSysNotificationService() throws Exception {
int i = sysNotificationService.getNotificationCount("gitlink", 234,1,1);
Page<SysNotification> sysNotificationPage = sysNotificationService.getNotification("gitlink", 100,1,1, "IssueChanged", 1,20);
NewSysNotificationVo newSysNotificationVo = new NewSysNotificationVo();
newSysNotificationVo.setSender(1);
newSysNotificationVo.setReceivers("7,8");
newSysNotificationVo.setContent("baladiwei 在 gitlink-notification-system 修改ReadMe 文件的标题");
newSysNotificationVo.setNotification_url("www.baidu.com");
newSysNotificationVo.setPlatform("gitlink");
boolean j = sysNotificationService.sendNotification(newSysNotificationVo);
logger.info("insertResult:" + j);
int k = sysNotificationService.markNotificationAs("gitlink", 100, "1,2",2,1);
logger.info("updateStatus:" + k);
}
@Test
public void test2() {
operateTableService.createTableByPlatform("trustie");
}
}

View File

@ -1,7 +0,0 @@
spring:
datasource:
# 配置数据源类型
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:33306/gitlink_notification?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&allowMultiQueries=true
username: gitlink
password: giTlinK0^827

31
pom.xml
View File

@ -14,14 +14,11 @@
<module>writer</module>
<module>reader</module>
<module>executor</module>
<module>common</module>
</modules>
<properties>
<main-version>1.0.0</main-version>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- 打包时跳过test测试 -->
<skipTests>true</skipTests>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -51,34 +48,6 @@
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>${springboot.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -20,16 +20,6 @@
<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>
<dependency>
<groupId>cn.org.gitlink.notification</groupId>
<artifactId>gns-model</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
@ -37,13 +27,6 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
@ -51,4 +34,5 @@
</plugins>
</build>
</project>

View File

@ -2,12 +2,8 @@ package cn.org.gitlink.notification.reader;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@ComponentScan("cn.org.gitlink.notification.*")
@SpringBootApplication
@EnableTransactionManagement
public class ReaderApiApplication {
public static void main(String[] args) {
SpringApplication.run(ReaderApiApplication.class, args);

View File

@ -1,7 +0,0 @@
package cn.org.gitlink.notification.reader.config;
import cn.org.gitlink.notification.common.interceptor.ExceptionInterceptor;
import org.springframework.web.bind.annotation.ControllerAdvice;
@ControllerAdvice
public class ReaderExceptionInterceptor extends ExceptionInterceptor {}

View File

@ -1,17 +0,0 @@
package cn.org.gitlink.notification.reader.config;
import cn.org.gitlink.notification.common.interceptor.GitLinkInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class ReaderWebConfig implements WebMvcConfigurer {
@Autowired
private GitLinkInterceptor gitLinkInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(gitLinkInterceptor).addPathPatterns("/**");
}
}

View File

@ -16,13 +16,14 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
@EnableKnife4j
@Import({BeanValidatorPluginsConfiguration.class})
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("cn.org.gitlink.notification.reader")).paths(PathSelectors.any()).build();
.apis(RequestHandlerSelectors.basePackage("com.gitlink.notification")).paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {

View File

@ -0,0 +1,12 @@
package cn.org.gitlink.notification.reader.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class IndexController {
@GetMapping(value = "")
public String index() {
return "reader index!";
}
}

View File

@ -1,198 +0,0 @@
package cn.org.gitlink.notification.reader.controller;
import cn.org.gitlink.notification.common.constant.NotificationSystemConstant;
import cn.org.gitlink.notification.common.response.DataPacketUtil;
import cn.org.gitlink.notification.common.response.ResponseData;
import cn.org.gitlink.notification.common.utils.RedisUtil;
import cn.org.gitlink.notification.common.utils.ValidatorUtils;
import cn.org.gitlink.notification.model.dao.entity.vo.ReceiverNotificationCountVo;
import cn.org.gitlink.notification.model.dao.entity.vo.ReceiverNotificationListVo;
import cn.org.gitlink.notification.model.service.notification.SysNotificationService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(value = "/gns/notification")
public class NotificationController {
@Autowired
private RedisUtil redisUtil;
@Autowired
@Qualifier(value = "SysNotificationServiceImpl")
private SysNotificationService notificationService;
private Logger logger = LogManager.getLogger(NotificationController.class);
/**
* 获取系统消息列表
*
* @param platform 平台
* @param receiver 消息接收者
* @param status 信息状态值未-1时获取全部信息值为1时只获取未读消息值为2时获取已读消息
* @param type 消息类型1 系统消息2 @我消息
* @return
*/
@ApiOperation("获取系统消息列表")
@GetMapping(value = "/{platform}/list")
public ResponseData list(@ApiParam(value = "平台编码", required = true)
@PathVariable(name = "platform", required = true) String platform,
@ApiParam(value = "消息接收者", required = true)
@RequestParam(name = "receiver", required = true) Integer receiver,
@ApiParam(value = "信息状态:值未-1时获取全部信息值为1时只获取未读消息值为2时获取已读消息", required = false, defaultValue = "1")
@RequestParam(name = "status", required = false, defaultValue = "1") Integer status,
@ApiParam(value = "消息类型:值为-1时获取全部信息值为1时获取系统消息值为2时获取@我消息", defaultValue = "-1")
@RequestParam(name = "type", required = false, defaultValue = "-1") Integer type,
@ApiParam(value = "消息来源")
@RequestParam(name = "sources", required = false) String sources,
@ApiParam(value = "页码:值为-1时默认值不开启分页", required = false, defaultValue = "-1")
@RequestParam(name = "page", required = false, defaultValue = "-1") Integer page,
@ApiParam(value = "页大小页码", required = false, defaultValue = "20")
@RequestParam(name = "size", required = false, defaultValue = "20") Integer size) {
//参数合法性验证
ResponseData jsonFailResult = ValidatorUtils.validatePlatformCode(platform);
if (jsonFailResult != null) return jsonFailResult;
jsonFailResult = validateReceiver(receiver);
if (jsonFailResult != null) return jsonFailResult;
jsonFailResult = validateNotificationType(type);
if (jsonFailResult != null) return jsonFailResult;
jsonFailResult = validateStatusParams(status);
if (jsonFailResult != null) return jsonFailResult;
ReceiverNotificationListVo notificationListVo = new ReceiverNotificationListVo();
notificationListVo.setReceiver(receiver);
notificationListVo.setType(type);
try {
//获取全部未读消息总数
notificationListVo.setTotalUnreadNotifiationCount(notificationService.getNotificationCount(platform, receiver, NotificationSystemConstant.NOTIFICATION_TYPE_ALL, NotificationSystemConstant.STATUS_OPTION_UNREAD));
//获取未读系统消息总数
notificationListVo.setUnreadNotificationCount(notificationService.getNotificationCount(platform, receiver, NotificationSystemConstant.NOTIFICATION_TYPE_SYS, NotificationSystemConstant.STATUS_OPTION_UNREAD));
//获取未读@我消息总数
notificationListVo.setUnreadAtMeCount(notificationService.getNotificationCount(platform, receiver, NotificationSystemConstant.NOTIFICATION_TYPE_ATME, NotificationSystemConstant.STATUS_OPTION_UNREAD));
if (page == -1) {
page = 1;
}
//分页的数据
Page foundPage = notificationService.getNotification(platform, receiver, status, type, sources, page, size);
if (foundPage != null) {
notificationListVo.setPageNum(foundPage.getCurrent());
notificationListVo.setPageSize(foundPage.getSize());
notificationListVo.setRecordsCount(foundPage.getTotal());
notificationListVo.setTotalPageCount(foundPage.getPages());
notificationListVo.setRecords(foundPage.getRecords());
}
return DataPacketUtil.jsonSuccessResult(notificationListVo);
} catch (Exception e) {
logger.error(e);
return DataPacketUtil.jsonFailResult(e.getMessage());
}//end of try-catch
}//end of method
/**
* 获取消息数量
*
* @param platform 平台编号
* @param receiver 消息接收者
* @param type -1 全部消息 | 1 系统消息 | 2 @我
* @return
*/
@ApiOperation("获取消息数量")
@GetMapping(value = "/{platform}/count")
public ResponseData count(@ApiParam(value = "平台编码", required = true)
@PathVariable(name = "platform", required = true) String platform,
@ApiParam(value = "消息接收者", required = true)
@RequestParam(name = "receiver", required = true) Integer receiver,
@ApiParam(value = "消息类型:值为-1时获取全部信息值为1时获取系统消息值为2时获取@我消息", defaultValue = "-1")
@RequestParam(name = "type", required = false, defaultValue = "-1") Integer type) {
ResponseData jsonFailResult = ValidatorUtils.validatePlatformCode(platform);
if (jsonFailResult != null) return jsonFailResult;
jsonFailResult = validateReceiver(receiver);
if (jsonFailResult != null) return jsonFailResult;
jsonFailResult = validateNotificationType(type);
if (jsonFailResult != null) return jsonFailResult;
try {
ReceiverNotificationCountVo countVo = new ReceiverNotificationCountVo();
countVo.setReceiver(receiver);
countVo.setType(type);
countVo.setUnreadNotification(notificationService.getNotificationCount(platform, receiver, type, NotificationSystemConstant.STATUS_OPTION_UNREAD));
return DataPacketUtil.jsonSuccessResult(countVo);
} catch (Exception e) {
logger.error(e);
return DataPacketUtil.jsonFailResult(e.getMessage());
}
}//end of method
//////////////////////////////// 私有方法 ////////////////////////////////
/**
* 验证 platform receiver 的合法性
*
* @param receiver
* @return
*/
private ResponseData validateReceiver(Integer receiver) {
//验证 {receiver} 参数合法性
if (receiver <= 0 || receiver >= Integer.MAX_VALUE) {
logger.debug("\t 输入参数 {receiver} 的值 {" + receiver + "} 超出约定范围");
return DataPacketUtil.jsonFailResult("{receiver} 参数非法");
}
return null;
}//end of method
/**
* 验证消息类型合法性
*
* @param type
* @return
*/
private ResponseData validateNotificationType(Integer type) {
if (type == NotificationSystemConstant.NOTIFICATION_TYPE_ALL || type == NotificationSystemConstant.NOTIFICATION_TYPE_SYS || type == NotificationSystemConstant.NOTIFICATION_TYPE_ATME) {
return null;
} else {
logger.debug("\t 输入参数 {type} 的值 {" + type + "} 超出约定范围");
return DataPacketUtil.jsonFailResult("{type} 参数非法");
}//end of if
}//end of method
/**
* stauts 参数合法性验证
*
* @param status
* @return
*/
private ResponseData validateStatusParams(Integer status) {
if (status == NotificationSystemConstant.STATUS_OPTION_ALL || status == NotificationSystemConstant.STATUS_OPTION_READ || status == NotificationSystemConstant.STATUS_OPTION_UNREAD) {
return null;
} else {
logger.debug("\t输入参数 {status} 的值 {" + status + "}超出约定范围");
return DataPacketUtil.jsonFailResult("{status} 参数非法");
}
}//end of method
}//end of class

View File

@ -0,0 +1,2 @@
server:
port: 8080

View File

@ -1,34 +0,0 @@
server:
port: 8081
logging:
config: classpath:logback.xml
spring:
redis:
database: 0
host: redis
port: 6379
password:
pool:
max-active: 200
max-wait: -1
max-idle: 10
min-idle: 0
timeout: 1000
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://mysql:3306/gitlink_notification?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&allowMultiQueries=true&useSSL=false
username: gitlink
password: giTlinK0^827
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
serialization:
indent_output: true
fail_on_empty_beans: false
white-list: '*'

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
<contextName>logback</contextName>
<property name="log.path" value="./logs/reader.log"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}.%d{yyyy-MM-dd}.log</fileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder>
<pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
</pattern>
</encoder>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 给 MyBatis 使用 -->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- 自己的包所有日志都应该时刻关注 -->
<logger name="cn.org.gitlink" level="DEBUG"/>
<root level="error">
<appender-ref ref="console"/>
<appender-ref ref="file"/>
</root>
</configuration>

View File

@ -1,10 +0,0 @@
spring.mail.host=smtp.exmail.qq.com
spring.mail.default-encoding=utf-8
spring.mail.port=465
spring.mail.username=gitlink@barats.cn
spring.mail.password=
spring.mail.properties[mail.smtp.auth]=true
spring.mail.properties[mail.smtp.connectiontimeout]=10000
spring.mail.properties[mail.smtp.timeout]=10000
spring.mail.properties[mail.smtp.writetimeout]=10000
spring.mail.properties[mail.smtp.starttls.enable]=true

Some files were not shown because too many files have changed in this diff Show More