zss
2024-07-26 cf7b98dabcaa7f429248dc576149559737227fd5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
package com.yuanchu.mom.backup;
 
import com.yuanchu.mom.dto.PerformanceShiftAddDto;
import com.yuanchu.mom.mapper.EnumMapper;
import com.yuanchu.mom.pojo.Enums;
import com.yuanchu.mom.pojo.PerformanceShift;
import com.yuanchu.mom.pojo.User;
import com.yuanchu.mom.service.EnumService;
import com.yuanchu.mom.service.PerformanceShiftService;
import com.yuanchu.mom.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
import javax.annotation.Resource;
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.Date;
import java.util.Dictionary;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
 
@Component
@EnableScheduling
@Slf4j
public class MysqlDataBackup {
    /**
     * 数据库版本是否为 8.0 + (false=否  true=是), mysql8+ 需要参数  --column-statistics=0  , mysql8- 不需要
     */
    Boolean isDbVersion8 = false;
 
    /**
     * 备份命令
     * USERNAME   账号
     * PASSWORD   密码
     * SERVERPATH 服务器IP/域名
     * DBNAME     数据库名称
     * FILEPATH   备份文件存放地址+名称
     * 说明
     * cmdCompression : 需压缩 (本地或服务器需安装 mysqldump 命令(安装mysql自带患独立安装) +  gzip 命令(独立安装))
     * cmd :            不压缩 (本地或服务器需安装 mysqldump 命令(安装mysql自带患独立安装)
     * --column-statistics=0     mysql8 添加该参数, 非mysql8 不添加, 否则将出错
     */
    String cmdMysql8 = "mysqldump --column-statistics=0  -u{USERNAME} -p{PASSWORD} -h{SERVERPATH} -P3306 --databases {DBNAME}"; //  > {FILEPATH}.sql
    String cmd = "mysqldump -u{USERNAME} -p{PASSWORD} -h{SERVERPATH} -P3306 --databases {DBNAME}";      //  > {FILEPATH}.sql
 
    /**
     * 备份 sql 存放目录(相对路径, 注意可能需要在 MvcConfig 配置访问权限)
     */
    @Value("${backup.path}")
    private String filePath;
 
    @Value("${spring.datasource.url}")
    private String dbUrl;
 
    @Value("${spring.datasource.username}")
    private String dbUserName;
 
    @Value("${spring.datasource.password}")
    private String dbPassWord;
 
    @Value("${backup.destiny}")
    private Integer destiny;
 
    @Value("${backup.mysqldump}")
    private String mysqldump;
 
    @Resource
    private PerformanceShiftService performanceShiftService;
 
    @Resource
    private EnumService enumService;
 
    @Resource
    private UserService userService;
 
    /**
     * 每天晚上23点05秒执行 【  0 0 4 1/1 * ? 】
     * 测试 20 秒一次【  0/20 * * * * ? 】@Scheduled(cron = "5 * 23 * * ?")
     */
    //@Scheduled(cron = "0/20 * * * * ?")
    private void configureTasks() {
        log.info("【备份数据库】--START");
        String dbUrl2 = dbUrl.replace("jdbc:mysql://", "");
 
        // 获取数据库名称
        String dbName = dbUrl2.substring(dbUrl2.lastIndexOf("/") + 1, dbUrl2.indexOf("?"));
        // 获取数据库地址
        String serverPath = dbUrl2.substring(0, dbUrl2.lastIndexOf(":"));
        // 数据库账号
        String username = dbUserName;
        // 数据库密码
        String password = dbPassWord;
 
        // 备份文件目录+名称  备份文件存放目录+名称(名称 = 数据库名+时间字符串.sql)
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String format = simpleDateFormat.format(new Date());
        String timeStr = format
                .replaceAll("-", "_")
                .replaceAll(" ", "_")
                .replaceAll(":", "");
        timeStr = timeStr.substring(0, 15);
        String pathFileName = filePath + "/" + dbName + "_" + timeStr + ".sql";
        String newCmd = "";
        if (isDbVersion8) {
            newCmd = cmdMysql8;
        } else {
            newCmd = cmd;
        }
        // 执行命令
        newCmd = newCmd.replace("{USERNAME}", username)
                .replace("{PASSWORD}", password)
                .replace("{SERVERPATH}", serverPath)
                .replace("{DBNAME}", dbName)
                .replace("{FILEPATH}", pathFileName);
        PrintWriter printWriter = null;
        BufferedReader bufferedReader = null;
        try {
            // 创建存放sql的文件
            existsFile(new File(pathFileName));
            printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(pathFileName), "utf8"));
            Process process = null;
            String property = System.getProperty("os.name");
            System.out.println(property);
            if (property.indexOf("Linux") != -1) {
                // linux
                process = Runtime.getRuntime().exec(new String[]{"bash", "-c", newCmd});
            } else {
                // 本地win
                String mysqldumpPath = "cmd /c " + mysqldump + "/" + newCmd;
                System.out.println(mysqldumpPath);
                process = Runtime.getRuntime().exec(mysqldumpPath);
            }
            InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream(), "utf8");
            bufferedReader = new BufferedReader(inputStreamReader);
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                printWriter.println(line);
            }
            // 此次会执行过长时间,直到备份完成
            printWriter.flush();
            printWriter.close();
            //0 表示线程正常终止。
            if (process.waitFor() == 0) {
                // 线程正常执行
                log.info("【备份数据库】SUCCESS,SQL文件:{}", pathFileName);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("【备份数据库】FAILURE");
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
                if (printWriter != null) {
                    printWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        log.info("【备份数据库】--END");
    }
 
 
    /**
     * 每天晚上23点0分10秒执行 【  0 0 4 1/1 * ? 】
     * 测试 20 秒一次【  0/20 * * * * ? 】
     */
//    @Scheduled(cron = "6 0 23 * * ?")
    private void TimerDeleteFile(){
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("d");
        Integer currentDay = Integer.valueOf(sdf.format(date));
        File file = new File(filePath);
        File[] files = file.listFiles();
        if (files != null) {
            for(File f : files){
                if(f.isFile()){//若是文件,直接打印
                    String[] splitFile = f.getName().split("_");
                    Integer fileDay = Integer.valueOf(splitFile[splitFile.length - 2]);
                    Integer i = currentDay - fileDay;
                    if (i.equals(destiny)){
                        f.delete();
                        log.info("备份sql文件过多进行删除!");
                    }
                }
            }
        }
    }
 
 
    /**
     * 定时任务,每个月1号的00:00:00给下一个月排班
     * 给每个人都进行排班(默认早班)
     */
    @Scheduled(cron = "0 0 0 1 * ?")
    //@Scheduled(cron = "0/20 * * * * ?")
    private void timerCreateSchedule(){
        System.out.println("开始给每个人进行排班,默认早班======start");
        // TODO 给每个人都进行排班(默认早班)
        PerformanceShiftAddDto performanceShiftAddDto = new PerformanceShiftAddDto();
        //班次--早(查询字典)
        List<Enums> shiftType = enumService.selectEnumByCategory("班次类型");
        List<String> collect = shiftType.stream().filter(enums -> enums.getLabel().equals("早")).map(enums -> enums.getValue()).collect(Collectors.toList());
        performanceShiftAddDto.setShift(collect.get(0));
        //人员--所有人
        String userIds = userService.getDeviceManager().stream().map(user -> user.getId().toString()).distinct().collect(Collectors.joining(","));
        performanceShiftAddDto.setUserId(userIds);
        //周次--当月所有
        // 获取当前日期
        LocalDate today = LocalDate.now().plusMonths(1);
        // 获取本月的第一天和最后一天
        LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
        // 获取周字段信息(根据区域设置)
        WeekFields weekFields = WeekFields.of(Locale.getDefault());
        // 获取本月第一天的周一
        LocalDate startOfWeek = firstDayOfMonth.with(TemporalAdjusters.previousOrSame(weekFields.getFirstDayOfWeek()));
        // 遍历本月所有天数,找出每周的第一天和最后一天
        LocalDate endOfWeek;
        while (startOfWeek.isBefore(firstDayOfMonth.plusMonths(1))) {
            endOfWeek = startOfWeek.plusDays(6);
            LocalDateTime startDateTime = LocalDateTime.of(startOfWeek, LocalTime.MIDNIGHT);
            LocalDateTime endDateTime = LocalDateTime.of(endOfWeek, LocalTime.MIDNIGHT);
            System.out.println("Week starts on " + startDateTime + " and ends on " + endDateTime);
            performanceShiftAddDto.setStartWeek(startDateTime);
            performanceShiftAddDto.setEndWeek(endDateTime);
            performanceShiftService.performanceShiftAdd(performanceShiftAddDto);
            startOfWeek = startOfWeek.plusWeeks(1);
        }
 
        System.out.println("排班结束======end");
    }
 
    /**
     * 判断文件是否存在,不存在创建
     */
    private static void existsFile(File file) {
        // 判断文件路径是否存在,不存在新建
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}