Forráskód Böngészése

Merge remote-tracking branch 'remotes/origin/master' into V_1.0.0_RC

AE86 2 éve
szülő
commit
8f9a5b927e

+ 4 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/config/ConfigChecker.java

@@ -84,6 +84,10 @@ public class ConfigChecker extends AbstractChecker {
             config.setRefreshInterval(time);
         }
 
+        // 刷新邮箱配置(有配置则发邮件)
+        String email = params.get("email");
+        config.setEmail(email);
+
         // 修改基本配置
         this.modifyConfigModel(config, params);
         return config;

+ 0 - 4
dbsyncer-common/pom.xml

@@ -31,10 +31,6 @@
             <groupId>javax.annotation</groupId>
             <artifactId>javax.annotation-api</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-core</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-cache</artifactId>

+ 50 - 0
dbsyncer-common/src/main/java/org/dbsyncer/common/model/NotifyMessage.java

@@ -0,0 +1,50 @@
+package org.dbsyncer.common.model;
+
+/**
+ * 通知消息
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/13 22:14
+ */
+public class NotifyMessage {
+
+    /**
+     * 消息标题
+     */
+    private String title;
+
+    /**
+     * 消息内容
+     */
+    private String content;
+
+    /**
+     * 消息接收人
+     */
+    private String receiver;
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public String getReceiver() {
+        return receiver;
+    }
+
+    public void setReceiver(String receiver) {
+        this.receiver = receiver;
+    }
+}

+ 20 - 0
dbsyncer-common/src/main/java/org/dbsyncer/common/spi/NotifyService.java

@@ -0,0 +1,20 @@
+package org.dbsyncer.common.spi;
+
+import org.dbsyncer.common.model.NotifyMessage;
+
+/**
+ * 通知服务(同步异常、连接器异常、应用异常等消息)
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/13 22:07
+ */
+public interface NotifyService {
+
+    /**
+     * 发送通知消息
+     *
+     * @param notifyMessage
+     */
+    void sendMessage(NotifyMessage notifyMessage);
+}

+ 11 - 0
dbsyncer-parser/src/main/java/org/dbsyncer/parser/model/Config.java

@@ -11,6 +11,9 @@ public class Config extends ConfigModel {
 
     private int refreshInterval = 5;
 
+    // 同步失败发送邮箱,多个以分号分割
+    private String email;
+
     public String getPassword() {
         return password;
     }
@@ -26,4 +29,12 @@ public class Config extends ConfigModel {
     public void setRefreshInterval(int refreshInterval) {
         this.refreshInterval = refreshInterval;
     }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
 }

+ 6 - 0
dbsyncer-plugin/pom.xml

@@ -25,5 +25,11 @@
             <version>${project.parent.version}</version>
         </dependency>
 
+        <!-- Mail -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-mail</artifactId>
+        </dependency>
+
     </dependencies>
 </project>

+ 23 - 0
dbsyncer-plugin/src/main/java/org/dbsyncer/plugin/NotifySupportConfiguration.java

@@ -0,0 +1,23 @@
+package org.dbsyncer.plugin;
+
+import org.dbsyncer.common.spi.NotifyService;
+import org.dbsyncer.plugin.notify.DefaultNotifyService;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/13 22:20
+ */
+@Configuration
+public class NotifySupportConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean
+    public NotifyService notifyService() {
+        return new DefaultNotifyService();
+    }
+
+}

+ 18 - 0
dbsyncer-plugin/src/main/java/org/dbsyncer/plugin/notify/DefaultNotifyService.java

@@ -0,0 +1,18 @@
+package org.dbsyncer.plugin.notify;
+
+import org.dbsyncer.common.model.NotifyMessage;
+import org.dbsyncer.common.spi.NotifyService;
+
+/**
+ * 默认通知服务
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/13 22:57
+ */
+public class DefaultNotifyService implements NotifyService {
+    @Override
+    public void sendMessage(NotifyMessage notifyMessage) {
+
+    }
+}

+ 114 - 0
dbsyncer-plugin/src/main/java/org/dbsyncer/plugin/notify/MailNotifyService.java

@@ -0,0 +1,114 @@
+package org.dbsyncer.plugin.notify;
+
+import org.dbsyncer.common.model.NotifyMessage;
+import org.dbsyncer.common.spi.NotifyService;
+import org.dbsyncer.common.util.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+
+import javax.annotation.PostConstruct;
+import javax.mail.*;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import java.util.Properties;
+
+/**
+ * 邮件通知服务实现
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2022/11/13 22:20
+ */
+@Component
+@ConditionalOnProperty(value = "dbsyncer.plugin.notify.mail.enabled", havingValue = "true")
+@ConfigurationProperties(prefix = "dbsyncer.plugin.notify.mail")
+public class MailNotifyService implements NotifyService {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    /**
+     * 邮箱账户
+     */
+    private String username;
+
+    /**
+     * 授权码
+     */
+    private String password;
+
+    /**
+     * 邮箱会话
+     */
+    private Session session;
+
+    @PostConstruct
+    private void init() {
+        final Properties props = new Properties();
+        props.put("mail.smtp.auth", "true");
+        props.put("mail.smtp.host", "smtp.qq.com");
+        props.put("mail.user", username);
+        props.put("mail.password", password);
+
+        // 构建授权信息,用于进行SMTP进行身份验证
+        session = Session.getInstance(props, new Authenticator() {
+            @Override
+            protected PasswordAuthentication getPasswordAuthentication() {
+                return new PasswordAuthentication(username, password);
+            }
+        });
+    }
+
+    @Override
+    public void sendMessage(NotifyMessage notifyMessage) {
+        try {
+            checkMail(notifyMessage);
+            String to = notifyMessage.getReceiver();
+            String title = notifyMessage.getTitle();
+            String content = notifyMessage.getContent();
+
+            // 创建邮件消息
+            MimeMessage message = new MimeMessage(session);
+            // 设置发件人
+            message.setFrom(new InternetAddress(username));
+
+            // 接收人
+            String[] receiverArray = StringUtil.split(to, ";");
+            int length = receiverArray.length;
+            InternetAddress[] addresses = new InternetAddress[length];
+            for (int i = 0; i < length; i++) {
+                addresses[i] = new InternetAddress(receiverArray[i]);
+            }
+            message.setRecipients(Message.RecipientType.TO, addresses);
+
+            // 设置邮件标题
+            message.setSubject(title);
+
+            // 设置邮件的内容体
+            message.setContent(content, "text/html;charset=UTF-8");
+            // 发送邮件
+            Transport.send(message);
+            logger.info("simple mail send success");
+        } catch (Exception e) {
+            logger.error("simple mail send error!", e);
+        }
+    }
+
+    private void checkMail(NotifyMessage notifyMessage) {
+        Assert.notNull(notifyMessage, "通知请求不能为空");
+        Assert.notNull(notifyMessage.getTitle(), "邮件主题不能为空");
+        Assert.notNull(notifyMessage.getContent(), "邮件内容不能为空");
+        Assert.notNull(notifyMessage.getReceiver(), "邮件收件人不能为空");
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+}

+ 5 - 0
dbsyncer-web/src/main/resources/application.properties

@@ -21,6 +21,11 @@ dbsyncer.parser.flush.buffer.actuator.batch-count=1000
 dbsyncer.parser.flush.buffer.actuator.queue-capacity=50000
 dbsyncer.parser.flush.buffer.actuator.period-millisecond=300
 
+#plugin
+dbsyncer.plugin.notify.mail.enabled=false
+dbsyncer.plugin.notify.mail.username=your mail username
+dbsyncer.plugin.notify.mail.password=your mail authorization code
+
 #storage
 dbsyncer.storage.binlog.recorder.batch-count=1000
 dbsyncer.storage.binlog.recorder.max-processing-seconds=120

+ 6 - 0
dbsyncer-web/src/main/resources/public/system/system.html

@@ -26,6 +26,12 @@
                         <input type="number" class="form-control" max="100" min="1" dbsyncer-valid="require" name="refreshInterval" th:value="${config?.refreshInterval}"/>
                     </div>
                 </div>
+                <div class="form-group">
+                    <label class="col-sm-4 control-label">邮箱配置(多个邮箱分号分割)</label>
+                    <div class="col-sm-8">
+                        <input type="string" class="form-control" max="100" min="1" dbsyncer-valid="false" name="email" th:value="${config?.email}"/>
+                    </div>
+                </div>
                 <div class="form-group">
                     <div class="text-right col-sm-4"></div>
                     <div class="text-right col-sm-8">