Merge remote-tracking branch 'origin/station' into station

This commit is contained in:
qiaoqinzheng 2023-06-21 13:50:58 +08:00
commit f081b1fac1
25 changed files with 1463 additions and 9 deletions

View File

@ -259,5 +259,4 @@
<version>3.3</version> <version>3.3</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,204 @@
package org.jeecg.common.email;
import com.google.common.collect.Lists;
import com.sun.mail.imap.IMAPStore;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.email.emuns.MailContentType;
import org.jeecg.modules.base.entity.SysEmail;
import org.jetbrains.annotations.NotNull;
import javax.mail.*;
import javax.mail.internet.MimeUtility;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* 邮件服务管理器
*/
@Slf4j
public class EmailServiceManager {
private SysEmail email;
/** 邮件接收数量 */
private Integer receiveNum;
/** smtp协议的存储对象 */
private IMAPStore store = null;
/** 邮件附件临时存储路径 */
private String temporaryStoragePath;
/** 收件箱 */
private Folder folder = null;
@NotNull
public static EmailServiceManager getInstance(){
return new EmailServiceManager();
}
/**
* 初始化邮件服务管理器
* @param email 邮件属性
*/
public void init(SysEmail email){
this.email = email;
}
/**
* 初始化邮件服务管理器
* @param email 邮件属性
*/
public void init(SysEmail email,Integer receiveNum,String temporaryStoragePath){
this.email = email;
this.receiveNum = receiveNum;
this.temporaryStoragePath = temporaryStoragePath;
}
/**
* 测试邮件服务连通性
*/
public boolean testConnectEmailServer(){
Socket socket = new Socket();
boolean flag = false;
try {
socket.connect(new InetSocketAddress(email.getEmailServerAddress(),email.getPort()),5000);
log.info("{}邮件服务连接测试成功",email.getEmailServerAddress());
flag = true;
} catch (IOException e) {
log.error("{}邮件服务连接测试失败,请检查邮件服务属性配置是否正确或邮件服务未开启,原因{}",email.getEmailServerAddress(),e.getMessage());
}finally {
try {
if(null != socket){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return flag;
}
/**
* 接收邮件
*/
public Message[] receiveMail() throws MessagingException {
//配置邮件服务属性
Properties props = new Properties();
props.put("mail.store.protocol","imap");
props.put("mail.imap.host",email.getEmailServerAddress());
props.put("mail.imap.port",email.getPort());
//获取邮件回话
final Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(email.getUsername(), email.getPassword());
}
});
Map<String, String> iam = new HashMap<>();
iam.put("name", "myname");
iam.put("version", "1.0.0");
iam.put("vendor", "myclient");
iam.put("support-email", "testmail@test.com");
//获取smtp协议的存储对象
store = (IMAPStore) session.getStore();
//连接
store.connect();
store.id(iam);
//获取收件箱
folder = store.getFolder("INBOX");
folder.open(Folder.READ_WRITE);
//获取邮件数量
final int messageCount = folder.getMessageCount();
if(messageCount > 0){
Integer start = 1;
Integer end = this.receiveNum>messageCount?messageCount:this.receiveNum;
final Message[] messages = folder.getMessages(start,end);
return messages;
}
return null;
}
/**
* 获取邮件内容
* @param part
* @return
* @throws MessagingException
* @throws IOException
*/
public void getMailContent(@NotNull Part part, StringBuilder content) throws MessagingException, IOException {
Multipart multipart = (Multipart) part.getContent();
for(int i=0;i<multipart.getCount();i++) {
final Part bodyPart = multipart.getBodyPart(i);
if(bodyPart.isMimeType(MailContentType.PLAIN.getContentType())){
content.append(bodyPart.getContent().toString());
}else if(bodyPart.isMimeType(MailContentType.RELATED.getContentType()) || bodyPart.isMimeType(MailContentType.ALTERNATIVE.getContentType())){
getMailContent(bodyPart,content);
}
}
}
/**
* 保存邮件附件
* @param part
* @throws MessagingException
* @throws IOException
*/
public List<String> saveAttachment(@NotNull Part part) throws MessagingException, IOException {
List<String> filePathList = Lists.newArrayList();
Multipart multipart = (Multipart) part.getContent();
for(int i=0;i<multipart.getCount();i++){
final BodyPart bodyPart = multipart.getBodyPart(i);
if(Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try{
final String fileName = MimeUtility.decodeText(bodyPart.getFileName());
bis = new BufferedInputStream(bodyPart.getInputStream());
File file = new File(this.temporaryStoragePath+File.separator+fileName);
bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] buf = new byte[4096];
int len;
while(-1 != (len = bis.read(buf,0,buf.length))){
bos.write(buf,0,buf.length);
}
filePathList.add(file.getAbsolutePath());
}finally {
if(null != bis){
bis.close();
}
if(null != bos){
bos.flush();
bos.close();
}
}
}
}
return filePathList;
}
/**
* 删除邮件
* @param message
* @throws MessagingException
*/
public void removeMail(@NotNull Message message) throws MessagingException {
message.setFlag(Flags.Flag.DELETED,true);
}
/**
* 关闭邮件服务连接资源
*/
public void close(){
try {
if(null != folder){
folder.close();
}
if(null != store){
store.close();
}
} catch (MessagingException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,43 @@
package org.jeecg.common.email.emuns;
/**
* 邮件类型
* @author 86187
*/
public enum MailContentType {
/**
* 该类型表示带附件的邮件在邮件正文中包含了其他类型文件的附件
* 例如 PDF 文件Word 文档图像音频和视频等
*/
MIXED("multipart/mixed"),
/**
* 该类型表示多部分邮件其中包含了邮件正文的不同版本通常情况下这种邮件类型包含两个部分
* 一个是纯文本格式的正文另一个则是 HTML 格式的正文
* 邮件客户端将根据用户设置或者默认值来选择相应的正文版本进行展示
*/
ALTERNATIVE("multipart/alternative"),
/**
* 该类型也是多部分邮件它一般用于邮件中嵌入的图片音频视频等附件的展示在该类型邮件中图片等资源作为与 HTML 文档相关联的部分进行传输
* 并且采用相对 URL 指向这些资源以确保在不同设备上展示正文时不会出现问题
*/
RELATED("multipart/related"),
/**
* 该类型表示 HTML 格式的邮件在邮件中可以包含各种样式和格式信息例如字体颜色图像链接等
*/
HTML("text/html"),
/**
* 该类型表示纯文本邮件在邮件中只包含纯文本不包含格式化信息
*/
PLAIN("text/plain");
private final String contentType;
MailContentType(String contentType) {
this.contentType = contentType;
}
public String getContentType(){
return this.contentType;
}
}

View File

@ -0,0 +1,26 @@
package org.jeecg.common.email.emuns;
/**
* 邮件类型
*/
public enum SysMailType {
/**
* 接收邮件
*/
RECEIVE_EMAIL(1),
/**
* 发送邮件
*/
SEND_EMAIL(2);
private Integer emailType;
SysMailType(int emailType) {
this.emailType = emailType;
}
public Integer getEmailType(){
return this.emailType;
}
}

View File

@ -259,4 +259,5 @@ public class FTPUtil {
} }
} }
} }
} }

View File

@ -46,7 +46,7 @@ public class SysEmailLog implements Serializable {
@TableField(value = "receive_time") @TableField(value = "receive_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime receiveTime; private Date receiveTime;
/** /**
* 创建时间 * 创建时间

View File

@ -0,0 +1,363 @@
package org.jeecg.modules.base.struct;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 能谱结构体字段信息
*/
@Data
public class EnergySpectrumStruct implements Serializable {
/************************* Infomations ******************/
/**
* 消息类型
*/
private String msg_type;
/**
* 消息id
*/
private String msg_id;
/**
* 数据类型
*/
private String data_type;
/************************* Header Black ******************/
/**
* designator
*/
private String designator;
/**
* site code
*/
private String site_code;
/**
* detector code
*/
private String detector_code;
/**
* system type: P for particulate; B for gas with 3-D β - γ coincidence detection; and
*/
private String system_type;
/**
* sample geometry
*/
private String sample_geometry;
/**
* spectrum qualifier: preliminary ( PREL )or full ( FULL)
*/
private String spectrum_quantity;
/**
* sample reference identification
*/
private String sample_ref_id;
/**
* measurement identification
*/
private String measurement_id;
/**
* detector background measurement identification
*/
private String detector_bk_measurement_id;
/**
* gas background measurement identification (memory effect)
*/
private String gas_bk_measurement_id;
/**
* transmit date (yyyy / mm / dd)
*/
private String transmit_date;
/**
* transmit time (hh : mm : ss . s)
*/
private String transmit_time;
/************************* Comment ******************/
private String comment;
/************************* Acquisition Block ******************/
/**
* acquisition start date (yyyy / mm / dd)
*/
private String acquisition_start_date;
/**
* acquisition start time (hh : mm : ss . s)
*/
private String acquisition_start_time;
/**
* acquisition real time (s)
*/
private Double acquisition_real_time;
/**
* acquisition live time (s)
*/
private Double acquisition_live_time;
/************************* Collection Block ******************/
/**
* collection start date (yyyy / mm / dd)
*/
private String collection_start_date;
/**
* collection start time (hh : mm : ss . s)
*/
private String collection_start_time;
/**
* collection stop date (yyyy / mm / dd)
*/
private String collection_stop_date;
/**
* collection stop time (hh : mm : ss . s)
*/
private String collection_stop_time;
/**
* total air volume sampled (standard cubic meters [scm])
*/
private Double air_volume;
/************************* Processing Block ******************/
/**
* sample volume of Xe (cm 3 )
*/
private Double sample_volume_of_Xe;
/**
* uncertainty (cm 3 )
*/
private Double uncertainty_1;
/**
* Xe collection yield (Xe gas in sample/total Xe gas sampled)
*/
private Double Xe_collection_yield;
/**
* uncertainty (Xe gas in sample/total Xe gas sampled)
*/
private Double uncertainty_2;
/**
* archive bottle identification
*/
private String archive_bottle_id;
/************************* Calibration Block ******************/
/**
* date of last calibration (yyyy / mm / dd)
*/
private String date_calibration;
/**
* time of last calibration (hh : mm : ss)
*/
private String time_calibration;
/************************* g_Energy Block ******************/
/**
* γ -energy (keV)
*/
private List<Double> g_energy;
/**
* centroid channel
*/
private List<Double> g_centroid_channel;
/**
* uncertainty (channels)
*/
private List<Double> g_uncertainty;
private Integer g_record_count;
/************************* b_Energy Block ******************/
/**
* electron energy (keV)
*/
private List<Double> b_electron_energy;
/**
* decay mode descriptor: B for β-particle, C for conversion electron (CE)
*/
private List<String> b_decay_mode;
/**
* maximum channel of β-particle distribution or centroid channel of CE (channels)
*/
private List<Double> b_channel;
/**
* uncertainty (channels)
*/
private List<Double> b_uncertainty;
private Integer b_record_count;
/************************* g_Resolution Block ******************/
/**
* γ -energy (keV)
*/
private List<Double> g_r_energy;
/**
* FWHM (keV)
*/
private List<Double> g_r_FWHM;
/**
* uncertainty (keV)
*/
private List<Double> g_r_uncertainty;
private Integer g_r_record_count;
/************************* b_Resolution Block ******************/
/**
* electron energy (keV)
*/
private List<Double> b_r_electron_energy;
/**
* FWHM (keV)
*/
private List<Double> b_r_FWHM;
/**
* uncertainty (keV)
*/
private List<Double> b_r_uncertainty;
private Integer b_r_record_count;
/************************* g_Efficiency Block ******************/
/**
* γ -energy (keV)
*/
private List<Double> g_e_energy;
/**
* efficiency (counts in peak/photon emitted)
*/
private List<Double> g_e_efficiency;
/**
* uncertainty (counts in peak/photon emitted)
*/
private List<Double> g_e_uncertainty;
private Integer g_e_record_count;
/************************* ROI_Limits Block ******************/
/**
* ROI number
*/
private List<String> ROI_number;
/**
* 2-D ROI β-range start, x 1 (keV)
*/
private List<Double> POI_B_x1;
/**
* 2-D ROI β-range stop, x 2 (keV)
*/
private List<Double> POI_B_x2;
/**
* 2-D ROI γ-range start, y 1 (keV)
*/
private List<Double> POI_G_y1;
/**
* 2-D ROI γ-range stop, y 2 (keV)
*/
private List<Double> POI_G_y2;
private Integer roi_record_count;
/************************* b-gEfficiency Block ******************/
/**
* nuclide name
*/
private List<String> bg_nuclide_name;
/**
* ROI number
*/
private List<String> bg_ROI_number;
/**
* β-γ coincidence efficiency (counts in ROI/β-γ pair emitted)
*/
private List<Double> bg_efficiency;
/**
* uncertainty (counts in ROI/β-γ pair emitted)
*/
private List<Double> bg_uncertainty;
private Integer bg_record_count;
/************************* Ratios Block ******************/
/**
* ratio identifier
*/
private List<String> ratio_id;
/**
* ROI number for the higher γ -energy ROI
*/
private List<String> ROI_num_highter_G_energy_ROI;
/**
* ROI number for the lower γ -energy ROI
*/
private List<String> ROI_num_lower_G_energy_ROI;
/**
* Q_DECLARE_METATYPE(RMSSOHData::HeaderBlock)count ratio(counts in higher γ -energy ROI/counts in lower γ -energy ROI)
*/
private List<Double> count_ratio;
/**
* count ratio uncertainty (percent)
*/
private List<Double> count_ratio_uncertainty;
private Integer ratio_record_count;
/************************* g_Spectrum Block ******************/
/**
* number of γ channels
*/
private Long num_g_channel;
/**
* γ-energy span (keV)
*/
private Long g_energy_span;
/**
* begin of channels
*/
private Long g_begin_channel;
/**
* count at channel
*/
private List<Long> g_counts;
/************************* b_Spectrum Block ******************/
/**
* number of β -channels
*/
private Long num_b_channel;
/**
* β -energy span (keV)
*/
private Long b_energy_span;
/**
* begin of channels
*/
private Long b_begin_channel;
/**
* counts at channels
*/
private List<Long> b_counts;
/************************* Histogram Block ******************/
/**
* β-channels
*/
private Long b_channels;
/**
* γ-channels
*/
private Long g_channels;
/**
* β-energy span
*/
private Long b_h_energy_span;
/**
* γ-energy span
*/
private Long g_h_energy_span;
/**
* counts at channels
*/
private List<Long> h_counts;
}

View File

@ -0,0 +1,30 @@
<?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>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-module-auto-process</artifactId>
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base-core</artifactId>
</dependency>
<!-- 引入jeecg-boot-starter-cloud依赖 -->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-starter-cloud</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,251 @@
package org.jeecg.modules;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.EmailConstant;
import org.jeecg.common.email.EmailServiceManager;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.email.EmailParsingActuator;
import org.jeecg.modules.emuns.SysMailEnableType;
import org.jeecg.modules.email.EmailProperties;
import org.jeecg.modules.properties.SpectrumPathProperties;
import org.jeecg.modules.properties.TaskProperties;
import org.jeecg.modules.service.ISysMailService;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 自动处理程序管理器
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class AutoProcessManager{
private final ISysMailService mailService;
private final TaskProperties taskProperties;
private final RedisUtil redisUtil;
private final SpectrumPathProperties spectrumPathProperties;
/**
* 邮件Map数据锁
*/
private final Object lock = new Object();
/**
* 以邮件Id为key邮件信息为value
*/
private Map<String,EmailProperties> emailMap = new HashMap<>();
/**
* 以邮件id为key以邮件执行线程为value
*/
private Map<String,Thread> emailExecThreadMap = new HashMap<>();
/**
* 启动自动处理
*/
public void start() {
//邮件数据监测线程
final MailDataMonitor mailDataMonitor = new MailDataMonitor();
mailDataMonitor.setName("mail-data-monitor");
mailDataMonitor.start();
//邮件服务监测线程
final MailServerMonitor monitorThread = new MailServerMonitor();
monitorThread.setName("mail-server-monitor");
monitorThread.start();
//邮件执行线程管理
final MailExecManager autoProcessThread = new MailExecManager();
autoProcessThread.setName("mail-exec-thread-manage");
autoProcessThread.start();
}
/**
* 自动处理线程
*/
private class MailExecManager extends Thread{
@Override
public void run() {
for(;;){
long start = System.currentTimeMillis();
if(!CollectionUtils.isEmpty(emailMap)){
Iterator<EmailProperties> iterator = emailMap.values().iterator();
while(iterator.hasNext()){
EmailProperties next = iterator.next();
if(next.isDelFlag()){
if(emailExecThreadMap.containsKey(next.getId())){
Thread thread = emailExecThreadMap.get(next.getId());
thread.interrupt();
emailExecThreadMap.remove(next.getId());
}
iterator.remove();
}
if(next.isNewEmailFlag()){
EmailParsingActuator emailParsingActuator = new EmailParsingActuator();
emailParsingActuator.init(taskProperties,next);
emailParsingActuator.setName(next.getUsername()+"-email-monitor");
emailParsingActuator.start();
//把邮件监测执行线程加入管理队列
emailExecThreadMap.put(next.getId(),emailParsingActuator);
//新邮件监测监测线程已启动则修改新邮件标记为false
next.setNewEmailFlag(false);
}
}
}
long end = System.currentTimeMillis();
long sleepTime = taskProperties.getMonitoringMailDataCycle() - (end-start);
//如果sleepTime > 0 需要睡眠到指定时间否则继续下次获取邮件
if(sleepTime > 0){
try {
//如果本次
TimeUnit.MILLISECONDS.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 邮箱通信监测线程具体功能如下
* 监测邮件服务通讯是否正常把各邮箱通信状态写入redis
*/
private class MailServerMonitor extends Thread{
@Override
public void run() {
for(;;){
long start = System.currentTimeMillis();
try{
if(!CollectionUtils.isEmpty(emailMap)){
emailMap.values().forEach(email->{
if(!email.isDelFlag()){
final EmailServiceManager emailServiceManager = EmailServiceManager.getInstance();
emailServiceManager.init(email);
boolean testFlag = emailServiceManager.testConnectEmailServer();
redisUtil.hset(EmailConstant.EMAIL_STATUS_PREFIX,email.getId(),testFlag);
if(testFlag && !emailExecThreadMap.containsKey(email.getId())){
email.setNewEmailFlag(true);
}
if(!testFlag){
//如果邮件服务通信测试失败则添加删除标记
email.setDelFlag(true);
}
}
});
}
//捕获异常不处理保障线程异常不退出
}catch (Exception e){
e.printStackTrace();
}
long end = System.currentTimeMillis();
long sleepTime = taskProperties.getMonitoringMailCommStatusCycle() - (end-start);
//如果sleepTime > 0 需要睡眠到指定时间否则继续下次监测
if(sleepTime > 0){
try {
TimeUnit.MILLISECONDS.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 邮箱数据监测线程具体功能如下
* 1.监测邮件数据表是否有变化
* 1.1有新邮件记录并且已启用则启动新线程执行
* 1.2有邮件记录被删除并且此邮箱信息已有线程执行则停止执行
*/
private class MailDataMonitor extends Thread{
@Override
public void run() {
for (;;){
long start = System.currentTimeMillis();
try{
final List<EmailProperties> receiveMails = mailService.findReceiveMails();
if(!CollectionUtils.isEmpty(receiveMails)){
//如果库里已有数据原来已开启使用并且监测Map中已存在现在关闭使用则添加删除标记
//如果本次查询数据监测Map中不存在并且已开启使用的则加入监测Map
for(EmailProperties email : receiveMails){
final boolean flag = emailMap.containsKey(email.getId());
if(flag && email.getEnabled().equals(SysMailEnableType.NOT_ENABLE.getMailEnableType())){
EmailProperties sourceEmail = emailMap.get(email.getId());
sourceEmail.setDelFlag(true);
}
if(!flag && email.getEnabled().equals(SysMailEnableType.ENABLE.getMailEnableType())){
email.setNewEmailFlag(true);
putSysEmailMap(email);
log.info("{}邮箱加入监测队列",email.getEmailServerAddress());
}
}
//如果监测Map中存在的邮箱数据在本次查询数据中不存在说明库里已删除则添加删除标记
emailMap.forEach((emailId,sourceEmail)->{
final long result = receiveMails.stream().filter(email -> emailId.equals(email.getId())).count();
if (result <= 0){
sourceEmail.setDelFlag(true);
}
});
}
//捕获异常不处理保障线程异常不退出
}catch (Exception e){
e.printStackTrace();
}
long end = System.currentTimeMillis();
long sleepTime = taskProperties.getMonitoringMailDataCycle() - (end-start);
//如果sleepTime > 0 需要睡眠到指定时间否则继续下次监测
if(sleepTime > 0){
try {
TimeUnit.MILLISECONDS.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 新增邮箱数据
* @param email
*/
private void putSysEmailMap(EmailProperties email){
synchronized (this.lock){
emailMap.put(email.getId(),email);
}
}
/**
* 删除邮箱数据
* @param emailId
*/
private void removeSysEmailMap(String emailId){
synchronized (this.lock){
if (emailMap.containsKey(emailId)){
emailMap.remove(emailId);
}
}
}
/**
* 删除邮箱数据
* @param sysEmailIds
*/
private void removeSysEmailMap(List<String> sysEmailIds){
synchronized (this.lock){
for(String sysEmailId : sysEmailIds){
if (emailMap.containsKey(sysEmailId)){
emailMap.remove(sysEmailId);
}
}
}
}
}

View File

@ -0,0 +1,26 @@
package org.jeecg.modules.config.mybatis;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 自定义实体字段填充
* @author 86187
*/
@Component
public class CustomMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject,"createTime", LocalDateTime.class,LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
}
}

View File

@ -0,0 +1,18 @@
package org.jeecg.modules.email;
import lombok.Data;
import org.jeecg.modules.base.entity.SysEmailLog;
import java.util.List;
/**
* 邮件日志属性
*/
@Data
public class EmailLogProperties extends SysEmailLog {
/**
* 邮件附件本地存储路径
*/
private List<String> filePathList;
}

View File

@ -0,0 +1,107 @@
package org.jeecg.modules.email;
import org.jeecg.common.email.EmailServiceManager;
import org.jeecg.common.email.emuns.MailContentType;
import org.jeecg.modules.properties.TaskProperties;
import org.jetbrains.annotations.NotNull;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.MimeUtility;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 邮件解析执行器
*/
public class EmailParsingActuator extends Thread{
private TaskProperties taskProperties;
private EmailProperties emailProperties;
private ThreadPoolExecutor poolExecutor;
public void init(TaskProperties taskProperties,
EmailProperties emailProperties){
this.taskProperties = taskProperties;
this.emailProperties = emailProperties;
//初始化线程池
ThreadFactory threadFactory = new CustomizableThreadFactory("mail-parsing-");
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(taskProperties.getReceiveNum(),taskProperties.getReceiveNum()*2,5, TimeUnit.SECONDS, new LinkedBlockingQueue<>(),threadFactory);
}
@Override
public void run() {
for(;;){
long start = System.currentTimeMillis();
final EmailServiceManager emailServiceManager = EmailServiceManager.getInstance();
emailServiceManager.init(emailProperties,taskProperties.getReceiveNum(),taskProperties.getTemporaryStoragePath());
try {
final Message[] messages = emailServiceManager.receiveMail();
for(Message message : messages){
final EmailLogProperties emailLogProperties = this.parseingMail(emailServiceManager,message);
//如果邮件没有附件获取附件都不是PHD文件也不是IMS2.0协议的文件需把邮件删除
// emailServiceManager.removeMail(message);
}
}catch (MessagingException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally {
//关闭资源
emailServiceManager.close();
}
break;
// long end = System.currentTimeMillis();
// long sleepTime = taskProperties.getMailThreadExecCycle() - (end-start);
// //如果sleepTime > 0 需要睡眠到指定时间否则继续下次获取邮件
// if(sleepTime > 0){
// try {
// //如果本次
// TimeUnit.MILLISECONDS.sleep(sleepTime);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
}
}
/**
* 解析邮件
* @param message
*/
public EmailLogProperties parseingMail(@NotNull EmailServiceManager emailServiceManager,@NotNull Message message) throws MessagingException, IOException {
//如果是带有附件的邮件
if(message.getContentType().startsWith(MailContentType.MIXED.getContentType())){
//封装邮件日志信息
EmailLogProperties mailLog = new EmailLogProperties();
mailLog.setEmailId(emailProperties.getId());
mailLog.setSubject(MimeUtility.decodeText(message.getSubject()));
final StringBuilder content = new StringBuilder();
emailServiceManager.getMailContent(message,content);
mailLog.setContext(content.toString());
mailLog.setReceiveTime(message.getSentDate());
final List<String> filePathList = emailServiceManager.saveAttachment(message);
mailLog.setFilePathList(filePathList);
return mailLog;
}else{
//如果此邮件不带有附件则删除
emailServiceManager.removeMail(message);
}
return null;
}
//SaunaβSpalaxγ
private boolean checkMail(String filePath){
File file = new File(filePath);
if(file.isFile()){
}
return true;
}
}

View File

@ -0,0 +1,27 @@
package org.jeecg.modules.email;
import lombok.Data;
import org.jeecg.modules.base.entity.SysEmail;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.Serializable;
/**
* 邮件属性
* @author 86187
*/
@Data
public class EmailProperties extends SysEmail {
/**
* 是否是新邮件
*/
private boolean newEmailFlag;
/**
* 该邮件处理线程是否需要删除
*/
private boolean delFlag;
}

View File

@ -0,0 +1,26 @@
package org.jeecg.modules.emuns;
/**
* 邮件类型
*/
public enum SysMailEnableType {
/**
* 未启用邮件
*/
NOT_ENABLE(0),
/**
* 启用邮件
*/
ENABLE(1);
private Integer mailEnableType;
SysMailEnableType(int mailEnableType) {
this.mailEnableType = mailEnableType;
}
public Integer getMailEnableType(){
return this.mailEnableType;
}
}

View File

@ -0,0 +1,10 @@
package org.jeecg.modules.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.base.entity.SysEmail;
/**
* 邮件数据表Mapper
*/
public interface SysMailMapper extends BaseMapper<SysEmail> {
}

View File

@ -0,0 +1,28 @@
package org.jeecg.modules.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.Map;
/**
* 能谱文件存储路径属性
* @author 86187
*/
@Data
@Component
@ConfigurationProperties(prefix = "file-system")
public class SpectrumPathProperties implements Serializable {
/**
* 能谱文件存储根路径
*/
private String rootPath;
/**
* 能谱文件存储路径以能谱系统类型/能谱类型为key以存储路径为value
*/
private Map<String,String> filePathMap;
}

View File

@ -0,0 +1,42 @@
package org.jeecg.modules.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.Serializable;
/**
* 邮件任务运行参数
* @author 86187
*/
@Data
@Component
@ConfigurationProperties(prefix = "task")
public class TaskProperties implements Serializable {
/**
* 单次获取邮件数量
*/
private Integer receiveNum;
/**
* 监测数据库邮箱数据变化周期
*/
private Long monitoringMailDataCycle;
/**
* 监测邮箱通信状态周期
*/
private Long monitoringMailCommStatusCycle;
/**
* 获取邮箱邮件线程执行周期
*/
private Long mailThreadExecCycle;
/**
* 邮件附件临时存储路径
*/
private String temporaryStoragePath;
}

View File

@ -0,0 +1,18 @@
package org.jeecg.modules.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.base.entity.SysEmail;
import org.jeecg.modules.email.EmailProperties;
import java.util.List;
/**
* 邮箱数据服务
*/
public interface ISysMailService extends IService<SysEmail> {
/**
* 查询接收邮箱数据
* @return
*/
List<EmailProperties> findReceiveMails();
}

View File

@ -0,0 +1,47 @@
package org.jeecg.modules.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import org.jeecg.common.email.emuns.SysMailType;
import org.jeecg.modules.base.entity.SysEmail;
import org.jeecg.modules.email.EmailProperties;
import org.jeecg.modules.emuns.SysMailEnableType;
import org.jeecg.modules.mapper.SysMailMapper;
import org.jeecg.modules.service.ISysMailService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.List;
/**
* 邮箱数据服务实现
*/
@Service
@DS("master")
public class SysMailServiceImpl extends ServiceImpl<SysMailMapper, SysEmail> implements ISysMailService {
/**
* 查询接收邮箱数据
* @return
*/
@Override
public List<EmailProperties> findReceiveMails() {
LambdaQueryWrapper<SysEmail> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysEmail::getEmilType, SysMailType.RECEIVE_EMAIL.getEmailType());
queryWrapper.eq(SysEmail::getEnabled, SysMailEnableType.ENABLE.getMailEnableType());
List<SysEmail> sysEmail = this.list(queryWrapper);
if(!CollectionUtils.isEmpty(sysEmail)){
List<EmailProperties> emailPropertiesList = Lists.newArrayList();
for (SysEmail email : sysEmail){
EmailProperties mailProperties = new EmailProperties();
BeanUtils.copyProperties(email,mailProperties);
emailPropertiesList.add(mailProperties);
}
return emailPropertiesList;
}
return Collections.emptyList();
}
}

View File

@ -0,0 +1,42 @@
<?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>jeecg-server-cloud</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-auto-process-start</artifactId>
<dependencies>
<!-- 引入jeecg-boot-starter-cloud依赖 -->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-starter-cloud</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base-core</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-module-auto-process</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,54 @@
package org.jeecg;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.AutoProcessManager;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @author 86187
*/
@Slf4j
@SpringBootApplication
@EnableFeignClients(basePackages = {"org.jeecg"})
@EnableScheduling
@RequiredArgsConstructor
public class JeecgAutoProcessApplication extends SpringBootServletInitializer implements CommandLineRunner {
private final AutoProcessManager autoProcessManager;
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(JeecgAutoProcessApplication.class);
}
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext application = SpringApplication.run(JeecgAutoProcessApplication.class, args);
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String path = oConvertUtils.getString(env.getProperty("server.servlet.context-path"));
log.info("\n----------------------------------------------------------\n\t" +
"Application Jeecg-Boot is running! Access URLs:\n\t" +
"Local: \t\thttp://localhost:" + port + path + "/doc.html\n" +
"External: \thttp://" + ip + ":" + port + path + "/doc.html\n" +
"Swagger文档: \thttp://" + ip + ":" + port + path + "/doc.html\n" +
"----------------------------------------------------------");
}
@Override
public void run(String... args) throws Exception {
autoProcessManager.start();
}
}

View File

@ -0,0 +1,19 @@
server:
port: 7004
spring:
application:
name: jeecg-auto-process
cloud:
nacos:
config:
server-addr: @config.server-addr@
group: @config.group@
namespace: @config.namespace@
discovery:
server-addr: ${spring.cloud.nacos.config.server-addr}
config:
import:
- optional:nacos:jeecg.yaml
- optional:nacos:jeecg-auto-process-@profile.name@.yaml

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 -->
<property name="LOG_HOME" value="../logs" />
<!--<property name="COLOR_PATTERN" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta( %replace(%caller{1}){'\t|Caller.{1}0|\r\n', ''})- %gray(%msg%xEx%n)" />-->
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/jeecg-system-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
</encoder>
</appender>
<!-- 生成 error html格式日志开始 -->
<appender name="HTML" class="ch.qos.logback.core.FileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!--设置日志级别,过滤掉info日志,只输入error日志-->
<level>ERROR</level>
</filter>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.html.HTMLLayout">
<pattern>%p%d%msg%M%F{32}%L</pattern>
</layout>
</encoder>
<file>${LOG_HOME}/error-log.html</file>
</appender>
<!-- 生成 error html格式日志结束 -->
<!-- 每天生成一个html格式的日志开始 -->
<appender name="FILE_HTML" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/jeecg-system-%d{yyyy-MM-dd}.%i.html</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
<MaxFileSize>10MB</MaxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.html.HTMLLayout">
<pattern>%p%d%msg%M%F{32}%L</pattern>
</layout>
</encoder>
</appender>
<!-- 每天生成一个html格式的日志结束 -->
<!--myibatis log configure -->
<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" />
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
<appender-ref ref="HTML" />
<appender-ref ref="FILE_HTML" />
</root>
</configuration>

View File

@ -25,6 +25,7 @@
<module>jeecg-web-statistics-start</module> <module>jeecg-web-statistics-start</module>
<module>jeecg-log-manage-start</module> <module>jeecg-log-manage-start</module>
<module>jeecg-abnormal-alarm-start</module> <module>jeecg-abnormal-alarm-start</module>
<module>jeecg-auto-process-start</module>
</modules> </modules>
</project> </project>

View File

@ -82,6 +82,7 @@
<module>jeecg-module-station-operation</module> <module>jeecg-module-station-operation</module>
<module>jeecg-module-web-statistics</module> <module>jeecg-module-web-statistics</module>
<module>jeecg-module-abnormal-alarm</module> <module>jeecg-module-abnormal-alarm</module>
<module>jeecg-module-auto-process</module>
</modules> </modules>
<repositories> <repositories>
@ -187,12 +188,6 @@
<artifactId>jeecg-module-web-statistics</artifactId> <artifactId>jeecg-module-web-statistics</artifactId>
<version>${jeecgboot.version}</version> <version>${jeecgboot.version}</version>
</dependency> </dependency>
<!-- jeecg-module-abnormal-alarm模块 -->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-module-abnormal-alarm</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
<!-- jeecg tools --> <!-- jeecg tools -->
<dependency> <dependency>
<groupId>org.jeecgframework.boot</groupId> <groupId>org.jeecgframework.boot</groupId>