whyclxw
2024-09-11 b56c0758e2158261d973e90b581d1ed78c5dfc79
告警实时socket和历史分库分表历史查询
10个文件已添加
5个文件已修改
1394 ■■■■ 已修改文件
src/main/java/com/whyc/controller/BatttestdataInfController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/controller/DevalarmDataHisController.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/dto/DalmDto.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/mapper/DevalarmDataMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/pojo/db_alarm/DevalarmData.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/pojo/db_alarm/DevalarmDataYear.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/DevalarmDataService.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/MybatisSqlExecuteService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/SubTablePageInfoService.java 102 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/ActionUtil.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/DateUtil.java 620 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/SubTablePageInfoUtil.java 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/ThreadLocalUtil.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/webSocket/DevalarmSocket.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/DevalarmDataMapper.xml 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/controller/BatttestdataInfController.java
@@ -38,6 +38,7 @@
    public Map<String, Object> getDevTinfByWeek(@RequestParam Integer uid){
        return service.getDevTinfByWeek(uid);
    }
    @ApiOperation(value = "获取设备的充放电记录")
    @GetMapping("getTinfById")
    public Response getTinfById(@RequestParam Integer devId){
src/main/java/com/whyc/controller/DevalarmDataHisController.java
New file
@@ -0,0 +1,33 @@
package com.whyc.controller;
import com.whyc.dto.DalmDto;
import com.whyc.dto.Response;
import com.whyc.service.BatttestdataInfService;
import com.whyc.service.DevalarmDataService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.text.ParseException;
import java.util.Map;
@RestController
@Api(tags = "历史告警管理")
@RequestMapping("tinf")
public class DevalarmDataHisController {
    @Autowired
    private DevalarmDataService dataService;
    @ApiOperation(value = "测试实时告警")
    @PostMapping("getDAlmInf")
    public Response getDAlmInf(@RequestParam int uid, @RequestBody DalmDto dto){
        return dataService.getDAlmInf(uid,dto);
    }
    @ApiOperation(value = "获取历史告警")
    @PostMapping("getDAlmHis")
    public Response getDAlmHis( @RequestBody DalmDto dto) throws ParseException {
        return dataService.getDAlmHis(dto);
    }
}
src/main/java/com/whyc/dto/DalmDto.java
New file
@@ -0,0 +1,19 @@
package com.whyc.dto;
import lombok.Data;
import java.util.Date;
@Data
public class DalmDto {
    private Integer devType;
    private Integer almId;
    private Date startTime;
    private Date endTime;
    private int pageNum;
    private int pageSize;
    private Integer uid;
    private String tableName;
    private Integer limitStart;
    private Integer limitEnd;
}
src/main/java/com/whyc/mapper/DevalarmDataMapper.java
New file
@@ -0,0 +1,12 @@
package com.whyc.mapper;
import com.whyc.dto.DalmDto;
import com.whyc.pojo.db_alarm.DevalarmData;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface DevalarmDataMapper extends CustomMapper<DevalarmData>{
    //获取设备告警信息
    List<DevalarmData> getDAlmInf(@Param("dto") DalmDto dto);
}
src/main/java/com/whyc/pojo/db_alarm/DevalarmData.java
New file
@@ -0,0 +1,71 @@
package com.whyc.pojo.db_alarm;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
 * <p>
 * 设备实时告警记录表
 * </p>
 *
 * @author lxw
 * @since 2024-09-11
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName(schema = "db_alarm",value ="tb_devalarm_data")
@ApiModel(value="DevalarmData对象", description="设备实时告警记录表")
public class DevalarmData implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "自增主键")
    @TableId(value = "num", type = IdType.AUTO)
    private int num;
    @ApiModelProperty(value = "设备ID")
    private Integer devId;
    @ApiModelProperty(value = "告警ID")
    private Integer almId;
    @ApiModelProperty(value = "告警类型【1-上限告警  2-下限告警】")
    private Integer almSignalId;
    @ApiModelProperty(value = "告警开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date almStarttime;
    @ApiModelProperty(value = "告警值")
    private Float almValue;
    @ApiModelProperty(value = "告警是否确认")
    private Integer almIsConfirmed;
    @ApiModelProperty(value = "确认用户ID")
    private Integer confirmedUid;
    @ApiModelProperty(value = "确认时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date confirmedTime;
    @ApiModelProperty(value = "告警结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date almEndtime;
    @ApiModelProperty(value = "告警记录状态[0-实时告警  1-历史告警  2-取消告警]")
    private Integer almClearedType;
}
src/main/java/com/whyc/pojo/db_alarm/DevalarmDataYear.java
New file
@@ -0,0 +1,71 @@
package com.whyc.pojo.db_alarm;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
 * <p>
 * 设备历史告警记录表
 * </p>
 *
 * @author lxw
 * @since 2024-09-11
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_devalarm_data_Year")
@ApiModel(value="DevalarmDataYear对象", description="设备历史告警记录表")
public class DevalarmDataYear implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "自增主键")
    @TableId(value = "num", type = IdType.AUTO)
    private int num;
    @ApiModelProperty(value = "设备ID")
    private Integer devId;
    @ApiModelProperty(value = "告警ID")
    private Integer almId;
    @ApiModelProperty(value = "告警类型【1-上限告警  2-下限告警】")
    private Integer almSignalId;
    @ApiModelProperty(value = "告警开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date almStarttime;
    @ApiModelProperty(value = "告警值")
    private Float almValue;
    @ApiModelProperty(value = "告警是否确认")
    private Integer almIsConfirmed;
    @ApiModelProperty(value = "确认用户ID")
    private Integer confirmedUid;
    @ApiModelProperty(value = "确认时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date confirmedTime;
    @ApiModelProperty(value = "告警结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date almEndtime;
    @ApiModelProperty(value = "告警记录状态[0-实时告警  1-历史告警  2-取消告警]")
    private Integer almClearedType;
}
src/main/java/com/whyc/service/DevalarmDataService.java
New file
@@ -0,0 +1,44 @@
package com.whyc.service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whyc.dto.DalmDto;
import com.whyc.dto.Response;
import com.whyc.mapper.DevalarmDataMapper;
import com.whyc.pojo.db_alarm.DevalarmData;
import com.whyc.pojo.db_alarm.DevalarmDataYear;
import com.whyc.pojo.db_user.UserInf;
import com.whyc.util.ActionUtil;
import com.whyc.util.SubTablePageInfoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.util.List;
@Service
public class DevalarmDataService {
    @Autowired(required = false)
    private DevalarmDataMapper mapper;
    @Autowired(required = false)
    private SubTablePageInfoUtil service;
    //获取设备告警信息
    public Response getDAlmInf(int uid, DalmDto dto) {
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        dto.setUid(uid);
        List<DevalarmData> list=mapper.getDAlmInf(dto);
        PageInfo pageInfo=new PageInfo(list);
        return new Response().setII(1,list!=null,pageInfo,"获取设备告警信息");
    }
    //获取历史告警
    public Response getDAlmHis(DalmDto dto) throws ParseException {
        UserInf uinf= ActionUtil.getUser();
        dto.setUid(uinf.getUid());
        PageInfo pageInfo=service.getPageInfo(dto.getPageNum(),dto.getPageSize(),dto.getStartTime(),dto.getEndTime()
                ,"db_alarm", "tb_devalarm_data", dto);
        return new Response().setII(1,pageInfo!=null,pageInfo,"获取设备告警信息");
    }
}
src/main/java/com/whyc/service/MybatisSqlExecuteService.java
@@ -1,6 +1,7 @@
package com.whyc.service;
import com.whyc.mapper.CallBack;
import com.whyc.util.ActionUtil;
import com.whyc.util.DateUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
@@ -39,7 +40,7 @@
                    Object obj=rs.getObject(i);
                    if(obj instanceof java.util.Date ){
                        //jsonObject.put(property, ActionUtil.sdf.format(obj));
                        jsonObject.put(property,  DateUtil.format_YYYY_MM_DD_HH_MM_SS((java.util.Date) obj));
                        jsonObject.put(property,   ActionUtil.sdf.format((java.util.Date) obj));
                    }else{
                        jsonObject.put(property,obj);
                    }
src/main/java/com/whyc/service/SubTablePageInfoService.java
@@ -1,7 +1,11 @@
package com.whyc.service;
import com.whyc.dto.DalmDto;
import com.whyc.mapper.CallBack;
import com.whyc.pojo.db_alarm.DevalarmData;
import com.whyc.pojo.db_alarm.DevalarmDataYear;
import com.whyc.pojo.db_batt_testdata.BatttestdataId;
import com.whyc.util.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -57,23 +61,28 @@
    }
    /*//查询DevAlm历史告警数量
    public int getCountForDevAlm(DevAlarmHisDto alm) {
        String sql="select  count(distinct num) as number from db_ckpwrdev_alarm." +alm.getRecordYear()
    //查询DevAlm历史告警数量
    public int getCountForDevAlm(DalmDto dto) {
        String sql="select  count(distinct num) as number from db_alarm." +dto.getTableName()
                +" where 1=1 ";
        if(alm.getAlmStartTime()!=null){
            sql+=" and alm_starttime  >='"+ DateUtil.format_YYYY_MM_DD_HH_MM_SS(alm.getAlmStartTime())+"' ";
        if(dto.getStartTime()!=null){
            sql+=" and alm_starttime  >='"+ ThreadLocalUtil.format(dto.getStartTime(),1)+"' ";
        }
        if(alm.getAlmEndTime()!=null){
            sql+=" and alm_endtime  <='"+DateUtil.format_YYYY_MM_DD_HH_MM_SS(alm.getAlmEndTime())+"' ";
        if(dto.getEndTime()!=null){
            sql+=" and alm_endtime  <='"+ThreadLocalUtil.format(dto.getEndTime(),1)+"' ";
        }
        if(alm.getDevType()!=0){
           sql+=" and dev_type="+alm.getDevType();
        if(dto.getDevType()!=0){
           sql+=" and  FLOOR(dev_id/100000000)="+dto.getDevType();
        }
        if(alm.getAlmLevel()!=0){
            sql+=" and alm_level="+alm.getAlmLevel();
        if(dto.getAlmId()!=0){
            sql+=" and alm_id="+dto.getAlmId();
        }
        sql+=" and dev_id in (" +
                "            SELECT distinct dev_id from db_user.tb_battgroup_baojigroup,db_user.tb_battgroup_usr" +
                "            where tb_battgroup_baojigroup.baoji_group_id=tb_battgroup_usr.baoji_group_id" +
                "           and uid="+dto.getUid()+
                ")";
        List list = sqlExecuteService.executeQuery_call(sql, new CallBack() {
            @Override
            public List getResults(ResultSet rs) throws SQLException {
@@ -94,60 +103,51 @@
        return num;
    }
    //查询devalm历史告警
    public List getListDevAlm(DevAlarmHisDto alm){
        String sql="select  * from db_ckpwrdev_alarm." +alm.getRecordYear()
    public List getListDevAlm(DalmDto dto){
        String sql="select  * from db_alarm." +dto.getTableName()
                +" where 1=1 ";
        if(alm.getAlmStartTime()!=null){
            sql+=" and alm_starttime  >='"+ DateUtil.format_YYYY_MM_DD_HH_MM_SS(alm.getAlmStartTime())+"' ";
        if(dto.getStartTime()!=null){
            sql+=" and alm_starttime  >='"+ ThreadLocalUtil.format(dto.getStartTime(),1)+"' ";
        }
        if(alm.getAlmEndTime()!=null){
            sql+=" and alm_endtime  <='"+DateUtil.format_YYYY_MM_DD_HH_MM_SS(alm.getAlmEndTime())+"' ";
        if(dto.getEndTime()!=null){
            sql+=" and alm_endtime  <='"+ThreadLocalUtil.format(dto.getEndTime(),1)+"' ";
        }
        if(alm.getDevType()!=0){
            sql+=" and dev_type="+alm.getDevType();
        if(dto.getDevType()!=0){
            sql+=" and  FLOOR(dev_id/100000000)="+dto.getDevType();
        }
        if(alm.getAlmLevel()!=0){
            sql+=" and alm_level="+alm.getAlmLevel();
        if(dto.getAlmId()!=0){
            sql+=" and alm_id="+dto.getAlmId();
        }
        sql+="  ORDER BY alm_starttime desc limit "+alm.getLimitStart()+","+alm.getLimitEnd()+" ";
        sql+=" and dev_id in (" +
                "            SELECT distinct dev_id from db_user.tb_battgroup_baojigroup,db_user.tb_battgroup_usr" +
                "           where tb_battgroup_baojigroup.baoji_group_id=tb_battgroup_usr.baoji_group_id" +
                "           and uid="+dto.getUid()+
                ")";
        sql+="  ORDER BY alm_starttime asc  limit "+dto.getLimitStart()+","+dto.getLimitEnd()+" ";
        List list = sqlExecuteService.executeQuery_call(sql, new CallBack() {
            @Override
            public List getResults(ResultSet rs) throws SQLException {
                List<CKPowerDevAlarmHistory> list=new ArrayList<>();
                List<DevalarmDataYear> list=new ArrayList<>();
                while (rs.next()){
                    CKPowerDevAlarmHistory ph=new CKPowerDevAlarmHistory();
                    ph.setNum(rs.getLong("num"));
                    ph.setPowerDeviceId(rs.getInt("power_device_id"));
                    ph.setAlmId(rs.getInt("alm_id"));
                    ph.setAlmName(rs.getString("alm_name"));
                    ph.setDevType(rs.getInt("dev_type"));
                    ph.setAlmLevel(rs.getInt("alm_level"));
                    ph.setAlmStartTime(rs.getTimestamp("alm_starttime"));
                    ph.setAlmEndTime(rs.getTimestamp("alm_endtime"));
                    ph.setAlmIsConfirmed(rs.getInt("alm_is_confirmed"));
                    ph.setAlmConfirmedTime(rs.getTimestamp("alm_confirmed_time"));
                    ph.setAlmClearedType(rs.getInt("alm_cleared_type"));
                    list.add(ph);
                    DevalarmDataYear dataYear=new DevalarmDataYear();
                    dataYear.setNum(rs.getInt("num"));
                    dataYear.setDevId(rs.getInt("dev_id"));
                    dataYear.setAlmSignalId(rs.getInt("alm_signal_id"));
                    dataYear.setAlmStarttime(rs.getTimestamp("alm_starttime"));
                    dataYear.setAlmValue(rs.getFloat("alm_value"));
                    dataYear.setAlmIsConfirmed(rs.getInt("alm_is_confirmed"));
                    dataYear.setConfirmedUid(rs.getInt("confirmed_uid"));
                    dataYear.setConfirmedTime(rs.getTimestamp("confirmed_time"));
                    dataYear.setAlmEndtime(rs.getTimestamp("alm_endtime"));
                    dataYear.setAlmClearedType(rs.getInt("alm_cleared_type"));
                    list.add(dataYear);
                }
                return list;
            }
        });
        return list;
    }
    //查询所有的历史时间表
    public List getDevAlmHisList() {
        String sql="SELECT table_name FROM information_schema.tables WHERE table_name LIKE 'tb_ckpowerdev_alarm_history_%'";
        List list = sqlExecuteService.executeQuery_call(sql, new CallBack() {
            @Override
            public List getResults(ResultSet rs) throws SQLException {
                List<String> list=new ArrayList<>();
                while (rs.next()){
                    list.add(rs.getString("table_name"));
                }
                return list;
            }
        });
        return list;
    }*/
}
src/main/java/com/whyc/util/ActionUtil.java
@@ -203,7 +203,7 @@
        UserInf userInf = new UserInf();
        if(obj==null){
            userInf.setUname("未登录的用户账号");
            userInf.setUid(0);
            userInf.setUid(101);
            userInf.setUdownloadRole(0);
        }else{
            userInf=(UserInf) session.getAttribute("user");
src/main/java/com/whyc/util/DateUtil.java
@@ -5,135 +5,289 @@
import java.util.*;
/**
 * 日期处理工具类
 * @Author xuzhongpei
 * @Date 2023-11-16
 * */
 * @Description : 时间工具类
 * @date 2020/10/15
 **/
public class DateUtil {
    /**ThreadLocal副本形式避免多线程中 数据安全问题*/
    private static ThreadLocal<SimpleDateFormat> YYYY_MM_DD_HH_MM_SS = ThreadLocal.withInitial(()->new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
    private static ThreadLocal<SimpleDateFormat> YYYY_MM_DD_HH_MM_SS2 = ThreadLocal.withInitial(()->new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss"));
    private static ThreadLocal<SimpleDateFormat> YYYY_MM_DD_HH_MM_SS_UNION = ThreadLocal.withInitial(()->new SimpleDateFormat("yyyyMMddHHmmss"));
    private static ThreadLocal<SimpleDateFormat> YYYY_MM_DD = ThreadLocal.withInitial(()->new SimpleDateFormat("yyyy-MM-dd"));
    private static ThreadLocal<SimpleDateFormat> YYYY_MM_DD_UNION = ThreadLocal.withInitial(()->new SimpleDateFormat("yyyyMMdd"));
    public static SimpleDateFormat YYYY_MM_DD_HH_MM_SS=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static SimpleDateFormat YYYY_MM_DD_HH_MM_SS_UNION=new SimpleDateFormat("yyyyMMddHHmmss");
    public static SimpleDateFormat YYYY_MM_DD=new SimpleDateFormat("yyyy-MM-dd");
    public static SimpleDateFormat YYYY_MM=new SimpleDateFormat("yyyy-MM");
    public static SimpleDateFormat YYYY_MM_TABLE=new SimpleDateFormat("yyyy_MM");
    public static String format_YYYY_MM_DD_HH_MM_SS(Date date){
        return YYYY_MM_DD_HH_MM_SS.get().format(date);
    public static int compare(String date1Str,String date2Str) throws ParseException {
        Date date1 = YYYY_MM_DD_HH_MM_SS.parse(date1Str);
        Date date2 = YYYY_MM_DD_HH_MM_SS.parse(date2Str);
        if(date1.compareTo(date2)>0){
            return 1;
        }else if(date1.compareTo(date2) == 0){
            return 0;
        }else{
            return -1;
        }
    }
    public static String format_YYYY_MM_DD_HH_MM_SS2(Date date){
        return YYYY_MM_DD_HH_MM_SS2.get().format(date);
    public static Date getMaxTime(String date1Str,String date2Str,String date3Str) {
        try {
            Date date1 = YYYY_MM_DD_HH_MM_SS.parse(date1Str);
            Date date2 = YYYY_MM_DD_HH_MM_SS.parse(date2Str);
            Date date3 = YYYY_MM_DD_HH_MM_SS.parse(date3Str);
            Date maxTime = date1;
            if (maxTime.compareTo(date2) < 0) {
                maxTime = date2;
            }
            if (maxTime.compareTo(date3) < 0) {
                maxTime = date3;
            }
            return maxTime;
        }catch (ParseException e){
            return null;
        }
    }
    public static String format_YYYY_MM_DD_HH_MM_SS_UNION(Date date){
        return YYYY_MM_DD_HH_MM_SS_UNION.get().format(date);
    public static List<List<Date>> getMonthTime(Date startTimeDate,Date endTimeDate) throws ParseException {
        List<List<Date>> timeList = new LinkedList<>();
        Calendar startTimeCalendar = Calendar.getInstance();
        startTimeCalendar.setTime(startTimeDate);
        Calendar endTimeCalendar = Calendar.getInstance();
        endTimeCalendar.setTime(endTimeDate);
        //按月份切分时段
        int startY = startTimeCalendar.get(Calendar.YEAR);
        int startM = startTimeCalendar.get(Calendar.MONTH)+1;
        int endY = endTimeCalendar.get(Calendar.YEAR);
        int endM = endTimeCalendar.get(Calendar.MONTH)+1;
       int Y = endY - startY;
       int len = Y*12+(endM-startM)+1;
        Calendar dateTemp = Calendar.getInstance();
        for (int i = 0; i < len; i++) {
            List<Date> SEList = new LinkedList<>();
            //dateTemp.setTime(YYYY_MM_DD_HH_MM_SS.parse(startY+"-"+startM+"-01 00:00:00"));
            dateTemp.setTime(ThreadLocalUtil.parse(startY+"-"+startM+"-01 00:00:00",1));
            Date recordTime,recordTime1;
            dateTemp.add(Calendar.MONTH,i);
            recordTime = dateTemp.getTime();
            int lastDay = dateTemp.getActualMaximum(Calendar.DAY_OF_MONTH);
            dateTemp.set(Calendar.DAY_OF_MONTH,lastDay);
            dateTemp.set(Calendar.HOUR_OF_DAY,23);
            dateTemp.set(Calendar.MINUTE,59);
            dateTemp.set(Calendar.SECOND,59);
            recordTime1 = dateTemp.getTime();
            if(i==0){
                recordTime = startTimeDate;
            }
            if(i==len-1){
                recordTime1 = endTimeDate;
            }
            SEList.add(recordTime);
            SEList.add(recordTime1);
            timeList.add(SEList);
        }
        return timeList;
    }
    public static String YYYY_MM_DD(Date date){
        return YYYY_MM_DD.get().format(date);
    /**
     * 在分表的情况下使用,按年分表,查询需要切割查询使用
     * <p>
     * 根据传入的起止时间,按照年切割成不同时间段
     *
     * @param startTime 2021-01-01 10:00:00
     * @param endTime   2023-05-01 10:10:10
     * @return 示例[2021, 2022, 2023]
     * 使用方法:
     * 根据返回的第一个数据,如果存在表,则查询筛选条件为>=输入的起始时间;不存在则弃用输入的起始时间
     * 根据返回的最后个数据,如果表存在,则查询筛选条件为<=输入的终止时间;不存在则弃用输入的终止时间
     * 返回的非第一最后数据,查询全表
     */
    public static Map<String,List<Date>> getYearList(Date startTime,Date endTime) throws ParseException {
        Map<String,List<Date>> result = new LinkedHashMap<>();
        Calendar startTimeC = Calendar.getInstance();
        startTimeC.setTime(startTime);
        int startYear = startTimeC.get(Calendar.YEAR);
        Calendar endTimeC = Calendar.getInstance();
        endTimeC.setTime(endTime);
        int endYear = endTimeC.get(Calendar.YEAR);
        int yearSize = endYear - startYear + 1;
        for (int i = startYear; i <= endYear; i++) {
            List<Date> dateList = new LinkedList<>();
            if(yearSize == 1){ //起止时间没有跨年
                dateList.add(startTime);
                dateList.add(endTime);
            }
            else if(i==startYear){ //第一年
                dateList.add(startTime);
                Calendar instance = Calendar.getInstance();
                instance.set(Calendar.YEAR,i);
                instance.set(Calendar.MONTH,instance.getActualMaximum(Calendar.MONTH));
                instance.set(Calendar.DAY_OF_MONTH,instance.getActualMaximum(Calendar.DAY_OF_MONTH));
                instance.set(Calendar.HOUR_OF_DAY,instance.getActualMaximum(Calendar.HOUR_OF_DAY));
                instance.set(Calendar.MINUTE,instance.getActualMaximum(Calendar.MINUTE));
                instance.set(Calendar.SECOND,instance.getActualMaximum(Calendar.SECOND));
                dateList.add(instance.getTime());
            }
            else if(i== endYear){ //尾年
                Calendar instance = Calendar.getInstance();
                instance.set(Calendar.YEAR,i);
                instance.set(Calendar.MONTH,instance.getActualMinimum(Calendar.MONTH));
                instance.set(Calendar.DAY_OF_MONTH,instance.getActualMinimum(Calendar.DAY_OF_MONTH));
                instance.set(Calendar.HOUR_OF_DAY,instance.getActualMinimum(Calendar.HOUR_OF_DAY));
                instance.set(Calendar.MINUTE,instance.getActualMinimum(Calendar.MINUTE));
                instance.set(Calendar.SECOND,instance.getActualMinimum(Calendar.SECOND));
                dateList.add(instance.getTime());
                dateList.add(endTime);
            }else{
                Calendar instance = Calendar.getInstance();
                instance.set(Calendar.YEAR,i);
                instance.set(Calendar.MONTH,instance.getActualMinimum(Calendar.MONTH));
                instance.set(Calendar.DAY_OF_MONTH,instance.getActualMinimum(Calendar.DAY_OF_MONTH));
                instance.set(Calendar.HOUR_OF_DAY,instance.getActualMinimum(Calendar.HOUR_OF_DAY));
                instance.set(Calendar.MINUTE,instance.getActualMinimum(Calendar.MINUTE));
                instance.set(Calendar.SECOND,instance.getActualMinimum(Calendar.SECOND));
                dateList.add(instance.getTime());
                Calendar instance2 = Calendar.getInstance();
                instance2.set(Calendar.YEAR,i);
                instance2.set(Calendar.MONTH,instance2.getActualMaximum(Calendar.MONTH));
                instance2.set(Calendar.DAY_OF_MONTH,instance2.getActualMaximum(Calendar.DAY_OF_MONTH));
                instance2.set(Calendar.HOUR_OF_DAY,instance2.getActualMaximum(Calendar.HOUR_OF_DAY));
                instance2.set(Calendar.MINUTE,instance2.getActualMaximum(Calendar.MINUTE));
                instance2.set(Calendar.SECOND,instance2.getActualMaximum(Calendar.SECOND));
                dateList.add(instance2.getTime());
            }
            result.put(String.valueOf(i),dateList);
        }
        return result;
    }
    public static String format_YYYY_MM_DD_UNION(Date date){
        return YYYY_MM_DD_UNION.get().format(date);
    /**
     *
     * 在分表的情况下使用,按月分表,查询需要切割查询使用
     *
     * 根据传入的起止时间,按照月切割成不同时间段
     * @param startTimeStr 2022-11-01 10:00:00
     * @param endTimeStr 2023-05-01 10:10:10
     * @return  示例[2022_12,2023_1,2023_2,2023_3,2023_4,2023_5] TODO 这个返回对象格式 需要根据业务需要进行调整
     * 使用方法:
     *   根据返回的第一个数据,如果存在表,则查询筛选条件为>=输入的起始时间;不存在则弃用输入的起始时间
     *   根据返回的最后个数据,如果表存在,则查询筛选条件为<=输入的终止时间;不存在则弃用输入的终止时间
     *   返回的非第一最后数据,查询全表
     *
     */
    public static List<String> getMonthList(String startTimeStr,String endTimeStr) throws ParseException {
        Calendar startTimeCalendar = Calendar.getInstance();
        //Date startTime = DateUtil.YYYY_MM_DD_HH_MM_SS.parse(startTimeStr);
        Date startTime = ThreadLocalUtil.parse(startTimeStr,1);
        startTimeCalendar.setTime(startTime);
        Calendar endTimeCalendar = Calendar.getInstance();
        //Date endTime = DateUtil.YYYY_MM_DD_HH_MM_SS.parse(endTimeStr);
        Date endTime = ThreadLocalUtil.parse(endTimeStr,1);
        endTimeCalendar.setTime(endTime);
        /*String[] startTimeSplit = startTimeStr.split("-");
        int startYear = Integer.parseInt(startTimeSplit[0]);
        int startMonth = Integer.parseInt(startTimeSplit[1]);
        String[] endTimeSplit = endTimeStr.split("-");
        int endYear = Integer.parseInt(endTimeSplit[0]);
        int endMonth = Integer.parseInt(endTimeSplit[1]);*/
        List<String> yearMonthList = new LinkedList<>();
        while (!startTimeCalendar.after(endTimeCalendar)){ //起始时间大于终止时间则停止
            yearMonthList.add(startTimeCalendar.get(Calendar.YEAR)+"_"+(startTimeCalendar.get(Calendar.MONTH)+1));
            startTimeCalendar.add(Calendar.MONTH,1);
        }
        return yearMonthList;
    }
    /**
     *  查询使用时,需要处理 默认表查询的问题
     *  示例:
     *  <p>
     * {2020=[Fri Dec 25 14:12:22 CST 2020, Thu Dec 31 23:59:59 CST 2020]}
     * {2021=[Fri Jan 01 00:00:00 CST 2021, Fri Dec 31 23:59:59 CST 2021]}
     * {2022=[Sat Jan 01 00:00:00 CST 2022, Tue Nov 29 09:12:22 CST 2022]}
     * 或
     * {2020=[Fri Dec 25 14:12:22 CST 2020, Thu Dec 31 23:59:59 CST 2020]}
     * {2021=[Fri Jan 01 00:00:00 CST 2021, Fri Dec 31 23:59:59 CST 2021]}
     * {2022=[Sat Jan 01 00:00:00 CST 2022, Thu Dec 29 09:12:22 CST 2022]}
     * {default=[Wed Dec 14 15:27:13 CST 2022, Thu Dec 29 09:12:22 CST 2022]}
     * </p>
     * key为数字,表示年度分表;default为默认表
     * @param startTimeDate 起始时间
     * @param endTimeDate 终止时间
     * @return 需要查询的表及查询时间
     * @throws ParseException
     */
    public static Map<String,List<Date>> getQueryTimeForSubTables(Date startTimeDate,Date endTimeDate) throws ParseException {
        //根据筛选的时间段,查询出符合要求的各分表记录数
        //首先,如果当前时间超过7月,默认表中只有本年度的;如果没超过7月,默认表还存在上一年度的记录
        Calendar instance = Calendar.getInstance();
        if(endTimeDate.compareTo(instance.getTime())>0){ //校验优化最大查询时间
            endTimeDate = instance.getTime();
        }
        int nowYear = instance.get(Calendar.YEAR);
        instance.add(Calendar.MONTH,-6);
        int beforeYear = instance.get(Calendar.YEAR);
        Date beforeYearTime = instance.getTime();
        instance.setTime(endTimeDate);
        int endTimeYear = instance.get(Calendar.YEAR);
    //获取指定年月的天数
    public static int getDaysByYearMonth(int year, int month) {
        Calendar startTime = Calendar.getInstance();
        startTime.setTime(startTimeDate);
        Calendar a = Calendar.getInstance();
        a.set(Calendar.YEAR, year);
        a.set(Calendar.MONTH, month - 1);
        a.set(Calendar.DATE, 1);
        a.roll(Calendar.DATE, -1);
        int maxDate = a.get(Calendar.DATE);
        return maxDate;
        Map<String,List<Date>> yearTimeMap = DateUtil.getYearList(startTimeDate, endTimeDate);;
        if(nowYear == beforeYear){ //默认表只有本年度的(超过了半年,默认表记录全部只有本年度的,同时会生成了当前年度的分表)
            //如果查询时间范围包含当前年度,则需要查询默认表
            if(startTime.get(Calendar.YEAR) >= nowYear && endTimeYear <= nowYear){
                //开始时间设置年度初始时间
                Calendar defaultTableStartTime = Calendar.getInstance();
                defaultTableStartTime.set(Calendar.YEAR,nowYear);
                defaultTableStartTime.set(Calendar.MONTH,defaultTableStartTime.getActualMinimum(Calendar.MONTH));
                defaultTableStartTime.set(Calendar.DAY_OF_MONTH,defaultTableStartTime.getActualMinimum(Calendar.DAY_OF_MONTH));
                defaultTableStartTime.set(Calendar.HOUR_OF_DAY,defaultTableStartTime.getActualMinimum(Calendar.HOUR_OF_DAY));
                defaultTableStartTime.set(Calendar.MINUTE,defaultTableStartTime.getActualMinimum(Calendar.MINUTE));
                defaultTableStartTime.set(Calendar.SECOND,defaultTableStartTime.getActualMinimum(Calendar.SECOND));
                //终止时间设置为当前时间
                List<Date> defaultDateList = new LinkedList<>();
                defaultDateList.add(defaultTableStartTime.getTime());
                defaultDateList.add(endTimeDate);
                yearTimeMap.put("default",defaultDateList);
            }
        }else{ //查询时间范围不在当前年度
            //默认表中存在上一年度的记录.上一年的最早时间为beforeYearTime-上一年的年末
            //判断查询时间范围是否包含默认表中上一年度的时间
            if(instance.getTime().compareTo(beforeYearTime)>0){ //查询时间大于默认表中上一年度时间,说明查询记录也包含在默认表中
                //起始时间
                //终止时间
                List<Date> defaultDateList = new LinkedList<>();
                defaultDateList.add(beforeYearTime);
                defaultDateList.add(endTimeDate);
                yearTimeMap.put("default",defaultDateList);
            }
        }
        return yearTimeMap;
    }
    //获取某年某月的起始和结束时间
    //需要注意的是:月份是从0开始的,比如说如果输入5的话,实际上显示的是4月份的最后一天,千万不要搞错了哦
    public static String getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH,cal.getActualMaximum(Calendar.DATE));
        return  new   SimpleDateFormat( "yyyy-MM-dd ").format(cal.getTime())+"23:59:59";
    }
    public static String getFirstDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH,cal.getMinimum(Calendar.DATE));
        return   new   SimpleDateFormat( "yyyy-MM-dd ").format(cal.getTime())+"00:00:00";
    }
    //获取当前时间的年份
    public static int getNowYear(){
        Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
        ca.setTime(new Date()); //设置时间为当前时间
        int year = ca.get(Calendar.YEAR);
        //System.out.println(month);
        return year;
    }
    //获取当前时间的月份
    public static int getNowMonth(){
        Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
        ca.setTime(new Date()); //设置时间为当前时间
        int month = ca.get(Calendar.MONTH) + 1;
        //System.out.println(month);
        return month;
    }
    //获取当前时间的日期
    public static int getNowDay(){
        Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
        ca.setTime(new Date()); //设置时间为当前时间
        int day = ca.get(Calendar.DAY_OF_MONTH);
        //System.out.println(month);
        return day;
    }
    //当前时间加上x小时
    public static String getDateAdd(int minute){
        Date date = new Date();
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MINUTE, minute);
        return new   SimpleDateFormat( "yyyy-MM-dd HH:mm:ss").format(c.getTime());
    }
    //获取时间的年份
    public static int getDateYear(Date date){
        Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
        ca.setTime(date); //设置时间为当前时间
        int year = ca.get(Calendar.YEAR);
        //System.out.println(month);
        return year;
    }
    //获取时间的月份
    public static int getDateMonth(Date date){
        Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
        ca.setTime(date); //设置时间为当前时间
        int month = ca.get(Calendar.MONTH) + 1;
        //System.out.println(month);
        return month;
    }
    //获取时间的日期
    public static int getDateDay(Date date){
        Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
        ca.setTime(date); //设置时间为当前时间
        int day = ca.get(Calendar.DAY_OF_MONTH);
        //System.out.println(month);
        return day;
    }
    //当前时间加上x小时
    public static Date getDateAdd(Date date,int minute){
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MINUTE, minute);
        return c.getTime();
    }
    /*==========时间切割,按年==========*/
    /**
     * 在分表的情况下使用,按年分表,查询需要切割查询使用 时间倒序
     * <p>
@@ -147,7 +301,7 @@
     * 根据返回的最后个数据,如果表存在,则查询筛选条件为<=输入的终止时间;不存在则弃用输入的终止时间
     * 返回的非第一最后数据,查询全表
     */
    public static Map<String, List<Date>> getYearListDesc(Date startTime, Date endTime) throws ParseException {
    public static Map<String,List<Date>> getYearListDesc(Date startTime,Date endTime) throws ParseException {
        Map<String,List<Date>> result = new LinkedHashMap<>();
        Calendar startTimeC = Calendar.getInstance();
        startTimeC.setTime(startTime);
@@ -212,6 +366,94 @@
    }
    /**
     * 在分表的情况下使用,按月分表,查询需要切割查询使用 时间倒序
     * <p>
     * 根据传入的起止时间,按照年切割成不同时间段
     *
     * @param startTime 2023-01-01 10:00:00
     * @param endTime   2023-05-01 10:10:10
     * @return 示例
     * {
     *  2023_04=[Fri Dec 25 14:12:22 CST 2020, Thu Dec 31 23:59:59 CST 2020]
     *  2023_03=[Fri Jan 01 00:00:00 CST 2021, Fri Dec 31 23:59:59 CST 2021],
     *  2023_02=[Sat Jan 01 00:00:00 CST 2022, Sat Dec 31 23:59:59 CST 2022],
     *  2023_01=[Sun Jan 01 00:00:00 CST 2023, Tue Jan 24 16:45:22 CST 2023],
     *
     * }
     * 使用方法:
     * 根据返回的第一个数据,如果存在表,则查询筛选条件为>=输入的起始时间;不存在则弃用输入的起始时间
     * 根据返回的最后个数据,如果表存在,则查询筛选条件为<=输入的终止时间;不存在则弃用输入的终止时间
     * 返回的非第一最后数据,查询全表
     */
    public static Map<String,List<Date>> getMonthListDesc(Date startTime,Date endTime) throws ParseException {
        Map<String,List<Date>> result = new LinkedHashMap<>();
        Calendar startTimeC = Calendar.getInstance();
        startTimeC.setTime(startTime);
        int startYear = startTimeC.get(Calendar.YEAR);
        int startMonth = startTimeC.get(Calendar.MONTH);
        Calendar endTimeC = Calendar.getInstance();
        endTimeC.setTime(endTime);
        int endYear = endTimeC.get(Calendar.YEAR);
        int endMonth = endTimeC.get(Calendar.MONTH);
        //相差的月份
        int monthCount = endYear*12+endMonth-(startYear*12+startMonth);
        for (int i = monthCount; i >= 0; i--) {
            List<Date> dateList = new LinkedList<>();
            if(monthCount == 0 ){ //起止时间没有跨月
                dateList.add(startTime);
                dateList.add(endTime);
            }
            else if(i==0){ //第一月
                dateList.add(startTime);
                Calendar instance = Calendar.getInstance();
                instance.setTime(startTime);
                instance.set(Calendar.DAY_OF_MONTH,instance.getActualMaximum(Calendar.DAY_OF_MONTH));
                instance.set(Calendar.HOUR_OF_DAY,instance.getActualMaximum(Calendar.HOUR_OF_DAY));
                instance.set(Calendar.MINUTE,instance.getActualMaximum(Calendar.MINUTE));
                instance.set(Calendar.SECOND,instance.getActualMaximum(Calendar.SECOND));
                dateList.add(instance.getTime());
            }
            else if(i== monthCount){ //尾月
                Calendar instance = Calendar.getInstance();
                instance.setTime(endTime);
                instance.set(Calendar.DAY_OF_MONTH,instance.getActualMinimum(Calendar.DAY_OF_MONTH));
                instance.set(Calendar.HOUR_OF_DAY,instance.getActualMinimum(Calendar.HOUR_OF_DAY));
                instance.set(Calendar.MINUTE,instance.getActualMinimum(Calendar.MINUTE));
                instance.set(Calendar.SECOND,instance.getActualMinimum(Calendar.SECOND));
                dateList.add(instance.getTime());
                dateList.add(endTime);
            }else{
                Calendar instance = Calendar.getInstance();
                instance.setTime(startTime);
                instance.add(Calendar.MONTH,i);
                instance.set(Calendar.DAY_OF_MONTH,instance.getActualMinimum(Calendar.DAY_OF_MONTH));
                instance.set(Calendar.HOUR_OF_DAY,instance.getActualMinimum(Calendar.HOUR_OF_DAY));
                instance.set(Calendar.MINUTE,instance.getActualMinimum(Calendar.MINUTE));
                instance.set(Calendar.SECOND,instance.getActualMinimum(Calendar.SECOND));
                dateList.add(instance.getTime());
                Calendar instance2 = Calendar.getInstance();
                instance2.setTime(startTime);
                instance2.add(Calendar.MONTH,i);
                instance2.set(Calendar.DAY_OF_MONTH,instance2.getActualMaximum(Calendar.DAY_OF_MONTH));
                instance2.set(Calendar.HOUR_OF_DAY,instance2.getActualMaximum(Calendar.HOUR_OF_DAY));
                instance2.set(Calendar.MINUTE,instance2.getActualMaximum(Calendar.MINUTE));
                instance2.set(Calendar.SECOND,instance2.getActualMaximum(Calendar.SECOND));
                dateList.add(instance2.getTime());
            }
            //result.put(DateUtil.YYYY_MM_TABLE.format(dateList.get(0)),dateList);
            result.put(ThreadLocalUtil.format(dateList.get(0),2),dateList);
        }
        return result;
    }
    /**
     *  查询使用时,需要处理 默认表查询的问题 倒序
     *  示例:
     *  <p>
@@ -243,6 +485,42 @@
        LinkedHashMap<String,List<Date>> yearTimeMap = (LinkedHashMap<String, List<Date>>) DateUtil.getYearListDesc(startTimeDate, endTimeDate);
        Map<String,List<Date>> yearTimeDescMap = new LinkedHashMap<>();
        boolean existDefaultYear = false;
        /*if(nowYear == beforeYear){ //默认表只有本年度的(超过了半年,默认表记录全部只有本年度的,同时会生成了当前年度的分表)
            //如果查询时间范围包含当前年度,则需要查询默认表
            if(startTime.get(Calendar.YEAR) >= nowYear && endTimeYear <= nowYear){
                //开始时间设置年度初始时间
                Calendar defaultTableStartTime = Calendar.getInstance();
                defaultTableStartTime.set(Calendar.YEAR,nowYear);
                defaultTableStartTime.set(Calendar.MONTH,defaultTableStartTime.getActualMinimum(Calendar.MONTH));
                defaultTableStartTime.set(Calendar.DAY_OF_MONTH,defaultTableStartTime.getActualMinimum(Calendar.DAY_OF_MONTH));
                defaultTableStartTime.set(Calendar.HOUR_OF_DAY,defaultTableStartTime.getActualMinimum(Calendar.HOUR_OF_DAY));
                defaultTableStartTime.set(Calendar.MINUTE,defaultTableStartTime.getActualMinimum(Calendar.MINUTE));
                defaultTableStartTime.set(Calendar.SECOND,defaultTableStartTime.getActualMinimum(Calendar.SECOND));
                //终止时间设置为当前时间
                List<Date> defaultDateList = new LinkedList<>();
                //defaultDateList.add(defaultTableStartTime.getTime());
                defaultDateList.add(startTimeDate);
                defaultDateList.add(endTimeDate);
                yearTimeMap.put("default",defaultDateList);
                existDefaultYear = true;
            }
        }else{ //查询时间范围不在当前年度
            //默认表中存在上一年度的记录.上一年的最早时间为beforeYearTime-上一年的年末
            //判断查询时间范围是否包含默认表中上一年度的时间
            if(instance.getTime().compareTo(beforeYearTime)>0){ //查询时间大于默认表中上一年度时间,说明查询记录也包含在默认表中
                //起始时间
                //终止时间
                List<Date> defaultDateList = new LinkedList<>();
                defaultDateList.add(startTimeDate);
                defaultDateList.add(endTimeDate);
                yearTimeMap.put("default",defaultDateList);
                existDefaultYear = true;
            }
        }*/
        if(startTimeDate.before(now.getTime()) || endTimeDate.after(timeBefore7Month.getTime())){
            List<Date> defaultDateList = new LinkedList<>();
            defaultDateList.add(startTimeDate);
@@ -266,5 +544,121 @@
        return yearTimeDescMap;
    }
    /**
     * 按年划分
     * 优化getQueryTimeForSubTablesDesc,待测试
     * 更新default表是否查询的逻辑,改||为&&
     *
     */
    public static Map<String,List<Date>> getQueryTimeForSubTablesDesc2(Date startTimeDate,Date endTimeDate) throws ParseException {
        //根据筛选的时间段,查询出符合要求的各分表记录数
        //首先,如果当前时间超过7月,默认表中只有本年度的;如果没超过7月,默认表还存在上一年度的记录
        Calendar now = Calendar.getInstance();
        if(endTimeDate.compareTo(now.getTime())>0){ //校验优化最大查询时间
            endTimeDate = now.getTime();
        }
        Calendar timeBefore7Month = Calendar.getInstance();
        timeBefore7Month.add(Calendar.MONTH,-7);
        LinkedHashMap<String,List<Date>> yearTimeMap = (LinkedHashMap<String, List<Date>>) DateUtil.getYearListDesc(startTimeDate, endTimeDate);
        Map<String,List<Date>> yearTimeDescMap = new LinkedHashMap<>();
        boolean existDefaultYear = false;
        //查询的开始时间 小于现在
        //查询的结束时间 大于 七个月前
        if(startTimeDate.before(now.getTime()) && endTimeDate.after(timeBefore7Month.getTime())){
            List<Date> defaultDateList = new LinkedList<>();
            defaultDateList.add(startTimeDate);
            defaultDateList.add(endTimeDate);
            yearTimeMap.put("default",defaultDateList);
            existDefaultYear = true;
        }
        //调整下顺序,将default调整到首位
        if(existDefaultYear){
            List<Date> defaultTimeList = yearTimeMap.get("default");
            yearTimeDescMap.put("default",defaultTimeList);
        }
        Set<String> yearSet = yearTimeMap.keySet();
        for (String year : yearSet) {
            if(!year.equals("default")){
                yearTimeDescMap.put(year,yearTimeMap.get(year));
            }
        }
        return yearTimeDescMap;
    }
    /**
     * 按月划分,时间倒序
     * 在原来按起止时间获取月份划分集合的基础上,加入实际子表逻辑,当前月内的,在default表
     * */
    public static Map<String,List<Date>> getQueryTimeForSubTablesByMonthDesc(Date startTimeDate,Date endTimeDate) throws ParseException {
        //根据筛选的时间段,查询出符合要求的各分表记录数
        //首先,如果当前时间超过7月,默认表中只有本年度的;如果没超过7月,默认表还存在上一年度的记录
        Calendar now = Calendar.getInstance();
        if(endTimeDate.compareTo(now.getTime())>0){ //校验优化最大查询时间
            endTimeDate = now.getTime();
        }
        LinkedHashMap<String,List<Date>> yearTimeMap = (LinkedHashMap<String, List<Date>>) DateUtil.getMonthListDesc(startTimeDate, endTimeDate);
        Map<String,List<Date>> yearTimeDescMap = new LinkedHashMap<>();
        boolean existDefaultYear = false;
        //查询的结束时间 在当月,则有default表
        //同时,抹去月份集合里的当月
        //if(DateUtil.YYYY_MM_TABLE.format(endTimeDate).equals(DateUtil.YYYY_MM_TABLE.format(now.getTime()))){
        if(ThreadLocalUtil.format(endTimeDate,2).equals(ThreadLocalUtil.format(now.getTime(),2))){
            List<Date> defaultDateList = new LinkedList<>();
            defaultDateList.add(startTimeDate);
            defaultDateList.add(endTimeDate);
            yearTimeMap.put("default",defaultDateList);
            existDefaultYear = true;
            //yearTimeMap.remove(DateUtil.YYYY_MM_TABLE.format(endTimeDate));
            yearTimeMap.remove(ThreadLocalUtil.format(endTimeDate,2));
        }
        //调整下顺序,将default调整到首位
        if(existDefaultYear){
            List<Date> defaultTimeList = yearTimeMap.get("default");
            yearTimeDescMap.put("default",defaultTimeList);
        }
        Set<String> yearSet = yearTimeMap.keySet();
        for (String year : yearSet) {
            if(!year.equals("default")){
                yearTimeDescMap.put(year,yearTimeMap.get(year));
            }
        }
        return yearTimeDescMap;
    }
    public static void main(String[] args) throws ParseException {
        //Date d1 = YYYY_MM_DD_HH_MM_SS.parse("2023-01-22 14:12:22");
        //Date d2 = YYYY_MM_DD_HH_MM_SS.parse("2023-08-24 16:45:22");
        //Map<String, List<Date>> monthListDesc = getQueryTimeForSubTablesByMonthDesc(d1, d2);
        //
        //Set<Map.Entry<String, List<Date>>> entries = monthListDesc.entrySet();
        //for (Map.Entry<String, List<Date>> entry : entries) {
        //    System.out.println(entry);
        //}
        //Map<String,String> map = new HashMap<>();
        //map.put("2022_01","");
        //map.put("2022_02","");
        //map.put("2022_10","");
        //map.put("2022_12","");
        //map.put("2021_03","");
        //map.put("2023_01","");
        //map.put("2023_05","");
        //map.put("2021_10","");
        //Set<String> keySet = map.keySet();
        //List<String> keySetDesc = keySet.stream().sorted(Comparator.comparing(String::hashCode).reversed()).collect(Collectors.toList());
        String t1 = "2024-01-25 12:22:29";
        String t2 = "2024-01-25 12:32:24";
        String t3 = "2024-01-25 12:42:26";
        Date maxTime = getMaxTime(t1, t2, t3);
        System.out.println(maxTime.toString());
    }
}
src/main/java/com/whyc/util/SubTablePageInfoUtil.java
New file
@@ -0,0 +1,226 @@
package com.whyc.util;
import com.github.pagehelper.PageInfo;
import com.whyc.dto.DalmDto;
import com.whyc.factory.ThreadPoolExecutorFactory;
import com.whyc.mapper.CommonMapper;
import com.whyc.service.SubTablePageInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
 * 数据量极大的表,按照年份分表,分页查询时获取数据
 */
@Component
public class SubTablePageInfoUtil {
    @Autowired(required = false)
    private CommonMapper commonMapper;
    @Autowired
    private SubTablePageInfoService service;
    /**按年份表分页查询*/
    public PageInfo<Object> getPageInfo(int pageNum,int pageSize,
                                        Date startTime,Date endTime,
                                        String dbName,String tablePrefix,
                                        Object pojo) throws ParseException {
        Map<String, List<Date>> queryTimeForSubTables = DateUtil.getQueryTimeForSubTablesDesc(startTime, endTime);
        //查询分表是否存在,存在则查询结果
        Map<String,Integer> queryCountMap = new LinkedHashMap<>();
        Set<String> tableYearKeySet = queryTimeForSubTables.keySet();
        for (String tableYear : tableYearKeySet) {
            List<Date> queryTime = queryTimeForSubTables.get(tableYear);
            String tableName;
            if(!tableYear.equals("default")){
                //数值
                tableName = tablePrefix+"_"+tableYear;
                String existTableName = commonMapper.existTable(dbName, tableName);
                if(existTableName == null){
                    continue;
                }
            }else{
                tableName = tablePrefix;
            }
            //====== 根据不同类型类型对象对应调整 ======
           if (pojo instanceof DalmDto) {
               DalmDto dto = (DalmDto) pojo;
               dto.setStartTime(queryTime.get(0));
               dto.setEndTime(queryTime.get(1));
               dto.setTableName(tableName);
               int currentCount = service.getCountForDevAlm(dto);
               queryCountMap.put(tableYear, currentCount);
            }
        }
        //分页信息
        //确认总页数,总记录数
        PageInfo<Object> pageInfo = new PageInfo<>();
        int total = 0;
        Set<String> queryKeySet = queryCountMap.keySet();
        for (String queryKey : queryKeySet) {
            int size = queryCountMap.get(queryKey);
            total+=size;
        }
        int pages = (int) Math.ceil(Float.parseFloat(String.valueOf(total))/pageSize);
        pageInfo.setTotal(total);
        pageInfo.setPages(pages);
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        //根据当前页所需记录,查询当前页记录
        int startNum = (pageNum-1)*pageSize+1;
        int endNum = pageNum*pageSize;
        //最后一个算法:上面不应该先查询所有记录,应该取count. 这后面定位到哪个表或哪几张表后,采取limit获取当前页记录数;
        //格式:{表名,[limit 2,20]}
        Map<String,List<Integer>> tableAndLimitMap = MathUtil.getQueryTableAndLimit(startNum,endNum,pageSize,queryCountMap);
        Set<String> keySet = tableAndLimitMap.keySet();
        List<Object> dataList = new LinkedList<>();
        for (String key : keySet) {
            List<Date> queryTime = queryTimeForSubTables.get(key);
            //====== 根据不同类型类型对象对应调整 ======
            String tableName = key.equals("default") ? tablePrefix : tablePrefix + "_" + key;
           if (pojo instanceof DalmDto) {
                DalmDto dto = (DalmDto) pojo;
                dto.setStartTime(queryTime.get(0));
                dto.setEndTime(queryTime.get(1));
                List<Integer> limitList = tableAndLimitMap.get(key);
                dto.setLimitStart(limitList.get(0));
                dto.setLimitEnd(limitList.get(1));
                dto.setTableName(tableName);
                List list =  service.getListDevAlm(dto);
                dataList.addAll(list);
            }
        }
        pageInfo.setList(dataList);
        return pageInfo;
    }
    /**按月分表,分页查询*/
    public PageInfo<Object> getPageInfoByMonthTable(int pageNum, int pageSize,
                                                    Date startTime, Date endTime,
                                                    String dbName, String tablePrefix,
                                                    Object pojo) throws ParseException, InterruptedException {
        Map<String, List<Date>> queryTimeForSubTables = DateUtil.getQueryTimeForSubTablesByMonthDesc(startTime, endTime);
        //查询分表是否存在,存在则查询结果
        Map<String,Integer> queryCountMap = new LinkedHashMap<>();
        Set<String> tableYearKeySet = queryTimeForSubTables.keySet();
        //优化1-查询所有的符合月份规则的表和主表
        List<String> tableNameListDB = getTableList(dbName, tablePrefix, tablePrefix + "(_[0-9]{4}_[0-9]{2})?");
        List<String> tableYearListInDB = new LinkedList<>(); //查询时间段内的年月分表集合且在数据库中存在
        //过滤掉时间段内数据库中不存在的年月分表
        for (String tableYear : tableYearKeySet) {
            String tableName;
            if(!tableYear.equals("default")){
                //数值
                tableName = tablePrefix+"_"+tableYear;
                //String existTableName = commonMapper.existTable(dbName, tableName);
                if(!tableNameListDB.contains(tableName)){ //优化1-数据库中不存在,去除多次查表,一次查出
                    continue;
                }
            }
            tableYearListInDB.add(tableYear);
        }
        //查询年月分表的记录数
        //优化2:多线程读取
        ThreadPoolExecutor pool = ThreadPoolExecutorFactory.getPoolExecutor();
        CountDownLatch latch = new CountDownLatch(tableYearListInDB.size());
        for (String tableYear : tableYearListInDB) {
            List<Date> queryTime = queryTimeForSubTables.get(tableYear);
            String tableName;
            if(!tableYear.equals("default")){
                //数值
                tableName = tablePrefix+"_"+tableYear;
            }else{
                tableName = tablePrefix;
            }
            pool.execute(()-> {
                //====== 根据不同类型类型对象对应调整 ======
                /*if (pojo instanceof BattAlarmHis) {
                    BattAlarmHis battAlarmHis = new BattAlarmHis();
                    BeanUtils.copyProperties(pojo,battAlarmHis);
                    battAlarmHis.setAlmStartTime(queryTime.get(0));
                    battAlarmHis.setAlmEndTime(queryTime.get(1));
                    battAlarmHis.setRecordYear(tableName);
                    int currentCount = service.getBattHisCount(battAlarmHis);
                    queryCountMap.put(tableYear, currentCount);
                 }*/
                latch.countDown();
            });
        }
        latch.await();
        //因为多线程后无序,需要重排序
        List<String> keySetDesc = queryCountMap.keySet().stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        Map<String,Integer> queryCountMapDesc = new LinkedHashMap<>();
        for (String key : keySetDesc) {
            Integer count = queryCountMap.get(key);
            queryCountMapDesc.put(key,count);
        }
        //分页信息
        //确认总页数,总记录数
        PageInfo<Object> pageInfo = new PageInfo<>();
        int total = 0;
        Set<String> queryKeySet = queryCountMap.keySet();
        for (String queryKey : queryKeySet) {
            int size = queryCountMap.get(queryKey);
            total+=size;
        }
        int pages = (int) Math.ceil(Float.parseFloat(String.valueOf(total))/pageSize);
        pageInfo.setTotal(total);
        pageInfo.setPages(pages);
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        //根据当前页所需记录,查询当前页记录
        int startNum = (pageNum-1)*pageSize+1;
        int endNum = pageNum*pageSize;
        //最后一个算法:上面不应该先查询所有记录,应该取count. 这后面定位到哪个表或哪几张表后,采取limit获取当前页记录数;
        //格式:{表名,[limit 2,20]}
        Map<String,List<Integer>> tableAndLimitMap = MathUtil.getQueryTableAndLimit(startNum,endNum,pageSize,queryCountMapDesc);
        Set<String> keySet = tableAndLimitMap.keySet();
        List<Object> dataList = new LinkedList<>();
        for (String key : keySet) {
            List<Date> queryTime = queryTimeForSubTables.get(key);
            //====== 根据不同类型类型对象对应调整 ======
            String recordYear = key.equals("default") ? tablePrefix : tablePrefix + "_" + key;
            /*if(pojo instanceof BattAlarmHis) {
                BattAlarmHis battAlarmHis = new BattAlarmHis();
                BeanUtils.copyProperties(pojo,battAlarmHis);
                battAlarmHis.setAlmStartTime(queryTime.get(0));
                battAlarmHis.setAlmEndTime(queryTime.get(1));
                battAlarmHis.setRecordYear(recordYear);
                List<Integer> limitList = tableAndLimitMap.get(key);
                battAlarmHis.setLimitStart(limitList.get(0));
                battAlarmHis.setLimitEnd(limitList.get(1));
                List<BattAlarmHis> list =  service.getBattHisList(battAlarmHis);
                dataList.addAll(list);
            }*/
        }
        pageInfo.setList(dataList);
        return pageInfo;
    }
    /**查询是否包含特定规则的表,存在,则返回表名*/
    public List<String> getTableList(String dbName,String tableLike,String regex){
        List<String> resultTableList = new LinkedList<>();
        List<String> tableList = commonMapper.getTableListLike(dbName,tableLike);
        for (String tableName : tableList) {
            boolean matches = Pattern.matches(regex, tableName);
            if(matches){
                resultTableList.add(tableName);
            }
        }
        return resultTableList;
    }
}
src/main/java/com/whyc/util/ThreadLocalUtil.java
New file
@@ -0,0 +1,48 @@
package com.whyc.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ThreadLocalUtil {
    public static ThreadLocal<SimpleDateFormat> sdf = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    public static ThreadLocal<SimpleDateFormat> sdfwithOutday = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy_MM"));
    public static ThreadLocal<SimpleDateFormat> sdfwithday = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
    public static ThreadLocal<SimpleDateFormat> sdfwithtime = ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm:ss"));
    public static ThreadLocal<SimpleDateFormat> sdfwithTABLE=ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM"));
    public static ThreadLocal<SimpleDateFormat> sdfwithtime_yyyyMMdd_HH_mm_ss=ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss"));
    public static ThreadLocal<SimpleDateFormat> YYYY_MM_DD_HH_MM_SS_UNION=ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMddHHmmss"));
    /*
    * flag:1(sdf),2(sdfwithOutday),3(sdfwithday),4(sdfwithtime)
    * */
    public static Date parse(String timeStr,int flag) {
        Date date=null;
        try {
            switch (flag){
                case 1:date=sdf.get().parse(timeStr);break;
                case 2:date=sdfwithOutday.get().parse(timeStr);break;
                case 3:date=sdfwithday.get().parse(timeStr);break;
                case 4:date=sdfwithtime.get().parse(timeStr);break;
                default:date=sdf.get().parse(timeStr);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
    public static String format(Date date,int flag) {
        String timeStr="";
        switch (flag){
            case 1:timeStr=sdf.get().format(date);break;
            case 2:timeStr=sdfwithOutday.get().format(date);break;
            case 3:timeStr=sdfwithday.get().format(date);break;
            case 4:timeStr=sdfwithtime.get().format(date);break;
            case 5:timeStr=sdfwithTABLE.get().format(date);break;
            case 6:timeStr=sdfwithtime_yyyyMMdd_HH_mm_ss.get().format(date);break;
            case 7:timeStr=YYYY_MM_DD_HH_MM_SS_UNION.get().format(date);break;
            default:timeStr=sdf.get().format(date);
        }
        return timeStr;
    }
}
src/main/java/com/whyc/webSocket/DevalarmSocket.java
New file
@@ -0,0 +1,111 @@
package com.whyc.webSocket;
import com.whyc.config.WebSocketConfig;
import com.whyc.dto.DalmDto;
import com.whyc.dto.DevInfDto;
import com.whyc.dto.Response;
import com.whyc.pojo.db_alarm.DevalarmData;
import com.whyc.service.DevInfService;
import com.whyc.service.DevalarmDataService;
import com.whyc.util.ActionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
/**
 * 设备实时连接信息
 */
@Component
@ServerEndpoint(value = "/dalmSocket",encoders = WebSocketEncoder.class,configurator = WebSocketConfig.class)
public class DevalarmSocket {
    private Session session;
    private Thread thread;
    private static DevalarmDataService dalmService;
    private HttpSession httpSession;
    private volatile boolean runFlag = true;
    private volatile Map<String, Thread> threadMap = new HashMap<>();
    private volatile Map<Long,Boolean> threadFlagMap = new HashMap<>();
    @Autowired
    public void setDevalarmDataService(DevalarmDataService dalmService) {
        DevalarmSocket.dalmService = dalmService;
    }
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        this.session = session;
        this.httpSession = (HttpSession) config.getUserProperties().get("httpSession");
    }
    @OnMessage
    public void onMessage(Session session, String message) {
        DalmDto dto = ActionUtil.getGson("yyyy-MM-dd HH:mm:ss").fromJson(message, DalmDto.class);
        //UserInf user = (UserInf) this.httpSession.getAttribute("user");
        //final int userId = user.getUid();
        final int userId = 101;
        thread = new Thread("Thread_DevalarmSocket") {
            @Override
            public void run() {
                while (runFlag && !isInterrupted()) {
                    Thread thread = currentThread();
                    threadFlagMap.put(thread.getId(), true);
                    try {
                        Response res=dalmService.getDAlmInf(userId, dto);
                        if (session.isOpen()) {
                            //推送信息
                            synchronized (session) {
                                session.getBasicRemote().sendObject(res);
                            }
                            threadFlagMap.put(thread.getId(), false);
                        }
                        sleep(4000);
                    } catch (Exception e) {
                        interrupt();
                    }
                }
            }
        };
        thread.start();
        threadFlagMap.put(thread.getId(),true);
        //停止老的socket线程
        Thread threadBefore = threadMap.get(session.getId());
        if(threadBefore !=null && threadBefore.isAlive()){
            while (threadFlagMap.get(threadBefore.getId())){
            }
            threadBefore.interrupt();
        }
        //将线程存储,便于调用定位
        threadMap.put(session.getId(), this.thread);
    }
    @OnClose
    public void onClose(CloseReason closeReason){
        System.err.println("closeReason = " + closeReason);
        runFlag = false;
        if (thread != null && thread.isAlive()) {
            thread.interrupt();
        }
        threadMap.remove(session.getId());
    }
    @OnError
    public void onError(Throwable error) {
        error.printStackTrace();
        if (thread != null && thread.isAlive()) {
            thread.interrupt();
        }
        threadMap.remove(session.getId());
    }
}
src/main/resources/mapper/DevalarmDataMapper.xml
New file
@@ -0,0 +1,31 @@
<?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="com.whyc.mapper.DevalarmDataMapper">
    <select id="getDAlmInf" resultType="com.whyc.pojo.db_alarm.DevalarmData">
        select * from db_alarm.tb_devalarm_data
        <where>
            <if test="dto.devType!=null">
                and  FLOOR(dev_id/100000000)  =#{dto.devType}
            </if>
            <if test="dto.almId!=null">
                and alm_id=#{dto.almId}
            </if>
            <if test="dto.startTime!=null">
                and alm_starttime>=#{dto.startTime}
            </if>
            <if test="dto.endTime!=null">
                and alm_starttime&lt;=#{dto.endTime}
            </if>
            and dev_id in (
            SELECT distinct dev_id from db_user.tb_battgroup_baojigroup,db_user.tb_battgroup_usr
            <where>
                tb_battgroup_baojigroup.baoji_group_id=tb_battgroup_usr.baoji_group_id
                <if test="dto.uid!=null">
                    and uid=#{dto.uid}
                </if>
            </where>
            )
        </where>
    </select>
</mapper>