集合操作(排序、分组、分页)

点击查看
  1. stream分组:groupingBy(Function)groupingBy(Function,Collector)groupingBy(Function,Supplier,Collector)

    • 一个参数:一个分组器,使用提供的字段对集合元素进行分组,返回一个Map<字段,相同字段值的元素集>

      Map<String, List<Employee>> map = emps.stream().collect(Collectors.groupingBy(Employee::getCity));
    • 两个参数:一个是分组器,按提供的字段进行分组。一个收集器,下面举例了3种用途

      // 先按city分组,再对组里面的成员,统计总销售额
      Map<String, Integer> map = emps.stream()
      .collect(Collectors.groupingBy(Employee::getCity, Collectors.summingInt(Employee::getSales)));

      // 先按城市分组,再对每个组里面的员工姓名放入Set,得到每个城市的姓氏集
      Map<String, Set<String>> map = emps.stream()
      .collect(Collectors.groupingBy(Employee::getCity, Collectors.mapping(Employee::getName, Collectors.toSet())));

      // 先按城市分组,在求分组里面销售额最大的员工
      Map<String, Employee> map = emps.stream()
      .collect(Collectors.groupingBy(Employee::getCity,
      Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Employee::getSales)), Optional::get)));
    • 三个参数:一个分组器,一个最终类型的生产者,一个收集器

      // 要求:要计算每个城市中人的姓氏集,并对城市名称进行排序
      TreeMap<String, Set<String>> map = emps.stream()
      .collect(Collectors.groupingBy(Employee::getCity, TreeMap::new, Collectors.mapping(Employee::getName, Collectors.toSet())));
  2. stream排序:需要倒叙的话后面调用reversed()方法

    • 降序

      list.stream().sorted(Comparator.comparing(实体::get属性).reversed()).collect(Collectors.toList());

      只对属性进行排序(此属性是封装类)该属性有为 null 的情况会报错,此时需要 在Comparator.comparing()入参多加一个nullsLast()的方法

    • 单个排序

      personnelList.stream()
      .sorted(Comparator.comparing(Personnel::getId, Comparator.nullsLast(Integer::compareTo)))
      .collect(Collectors.toList());
    • 多个排序

      personnels.stream().sorted(Comparator.comparing(Personnel::getName, Comparator.nullsLast(String::compareTo))
      .thenComparing(Personnel::getEmail,Comparator.nullsLast(String::compareTo)))
      .collect(Collectors.toList());
  3. stream分页

    • 计算总页数

      int totalPage = msgList.size()/pageSize + (msgList.size()%pageSize == 0 ? 0:1);
    • 分页

      // num:当前页,skipnum:起始数
      int skipnum = pageSize * (num - 1);
      List list= msgList.stream().skip(skipnum).limit(pageSize).collect(Collectors.toList());


LocalDate(Time)常用用法

点击查看
  1. 获取每周、月、季、年的第一天和最后一天方法
/**
* 获取每周、月、季、年的第一天和最后一天
* @param sign 1周 2月 3季 4年
*/
public static Map<String,String> getTimeMap(Integer sign){
Map<String, String> map = new HashMap<>();
String sTime = "";
String eTime = "";

LocalDate nowDate = LocalDate.now();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
if(sign==2){
sTime = nowDate.with(TemporalAdjusters.firstDayOfMonth()).format(df);
eTime = nowDate.with(TemporalAdjusters.lastDayOfMonth()).format(df);
}else if(sign==3){
// 本季度第一天
int month = nowDate.getMonthValue();
LocalDate firstDayOfQuarter;
if (month <= 3) {
firstDayOfQuarter = LocalDate.of(nowDate.getYear(), Month.JANUARY, 1);
} else if (month <= 6) {
firstDayOfQuarter = LocalDate.of(nowDate.getYear(), Month.APRIL, 1);
} else if (month <= 9) {
firstDayOfQuarter = LocalDate.of(nowDate.getYear(), Month.JULY, 1);
} else {
firstDayOfQuarter = LocalDate.of(nowDate.getYear(), Month.OCTOBER, 1);
}

sTime = firstDayOfQuarter.format(df);
eTime = nowDate.plusMonths(3 - nowDate.getMonthValue() % 3).with(TemporalAdjusters.lastDayOfMonth()).format(df);
}else if(sign==4){
sTime = nowDate.with(TemporalAdjusters.firstDayOfYear()).format(df);
eTime = nowDate.with(TemporalAdjusters.lastDayOfYear()).format(df);
}else {
// DayOfWeek可指定一周从星期几开始
sTime = nowDate.with(DayOfWeek.MONDAY).format(df);
eTime = nowDate.with(DayOfWeek.SUNDAY).format(df);
}

if(CharSequenceUtil.isNotEmpty(sTime)&&CharSequenceUtil.isNotEmpty(eTime)){
map.put("sTime",sTime);
map.put("eTime",eTime);
}
return map;
}
  • 周第一天最后一天、月第一天最后一天
/**
* 获取本月第一天
* @return String
**/
public static String getMonthStart() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date time = cal.getTime();
return new SimpleDateFormat("yyyy-MM-dd").format(time) + " 00:00:00";
}

/**
* 获取本月最后一天
* @return String
**/
public static String getMonthEnd() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
Date time = cal.getTime();
return new SimpleDateFormat("yyyy-MM-dd").format(time) + " 23:59:59";
}

/**
* 获取本周的第一天
* @return String
**/
public static String getWeekStart() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.WEEK_OF_MONTH, 0);
cal.set(Calendar.DAY_OF_WEEK, 2);
Date time = cal.getTime();
return new SimpleDateFormat("yyyy-MM-dd").format(time) + " 00:00:00";
}

/**
* 获取本周的最后一天
* @return String
**/
public static String getWeekEnd() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_WEEK, cal.getActualMaximum(Calendar.DAY_OF_WEEK));
cal.add(Calendar.DAY_OF_WEEK, 1);
Date time = cal.getTime();
return new SimpleDateFormat("yyyy-MM-dd").format(time) + " 23:59:59";
}
  • 申明定义
LocalDate formatDate = LocalDate.of(2020, 2, 5); // 自定义
LocalDate today = LocalDate.now(); // 获取当前日期

LocalDateTime now1 = LocalDateTime.of(2023, 1, 30, 14, 0 ,0); // 自定义
LocalDateTime now2 = LocalDateTime.now(); // 获取当前时间
  • 获取年月日
System.out.println(formatDate.getMonth()); // 结果:FEBRUARY。 获取所在月份(英文)
System.out.println(formatDate.getMonthValue()); // 结果:2。 获取所在月份(数字)
System.out.println(formatDate.getDayOfMonth()); // 结果:5。 获取所在天
  • 增减年月日:plusX()minusX()
LocalDate nextDay = formatDate.plusDays(1);
System.out.println(nextDay); // 2020-02-06 明天
LocalDate nextWeek = formatDate.plusWeeks(1);
System.out.println(nextWeek); // 2020-02-12 下周当天
LocalDate lastMonth = formatDate.minusMonths(1);
System.out.println(lastMonth); // 2020-01-05 上月当天
  • 比较先后:compareToisAfterisBefore
LocalDateTime now1 = LocalDateTime.now();
Thread.sleep(1000);
LocalDateTime now2 = LocalDateTime.now();
System.out.println(now1.isAfter(now2)); // false now1不晚于now2
System.out.println(now1.isBefore(now2)); // true now1早于now2
System.out.println(now1.compareTo(now2)); // -1 now1早于now2
System.out.println(now2.compareTo(now1)); // 1 now2晚于now1
System.out.println(now1.compareTo(now1)); // 0 相等
  • 本周第一天、本月第一天…
LocalDate firstWeekDay = formatDate.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
System.out.println(firstWeekDay); // 2020-02-03 本周第一天
LocalDate firstMonthDay = formatDate.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(firstMonthDay); // 2020-02-01 本月第一天
LocalDate firstYearDay = formatDate.with(TemporalAdjusters.firstDayOfYear());
System.out.println(firstYearDay); // 2020-01-01 本年第一天
//获取当月第一天
System.out.println("当月第一天:"+now.with(TemporalAdjusters.firstDayOfMonth()));
//获取下月第一天
System.out.println("下月第一天:"+now.with(TemporalAdjusters.firstDayOfNextMonth()));
//获取明年第一天
System.out.println("明年第一天:"+now.with(TemporalAdjusters.firstDayOfNextYear()));
//获取本年第一天
System.out.println("本年第一天:"+now.with(TemporalAdjusters.firstDayOfYear()));
//获取当月最后一天
System.out.println("当月最后一天:"+now.with(TemporalAdjusters.lastDayOfMonth()));
//获取本年最后一天
System.out.println("本年最后一天:"+now.with(TemporalAdjusters.lastDayOfYear()));
//获取当月第三周星期五
System.out.println("当月第三周星期五:"+now.with(TemporalAdjusters.dayOfWeekInMonth(3, DayOfWeek.FRIDAY)));
//获取上周一
System.out.println("上周一:"+now.with(TemporalAdjusters.previous(DayOfWeek.MONDAY)));
//获取下周日
System.out.println("下周日:"+now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY)));
  • 计算两个日期的间隔天数
LocalDate start = LocalDate.parse("2019-12-01");
LocalDate end = LocalDate.parse("2020-02-05");
long days = start.until(end, ChronoUnit.DAYS);
  • localdatatime相差时间数
LocalDateTime now = LocalDateTime.now();
System.out.println(“计算两个时间的差:”);
LocalDateTime end = LocalDateTime.now();
Duration duration = Duration.between(now,end);
long days = duration.toDays(); //相差的天数
long hours = duration.toHours();//相差的小时数
long minutes = duration.toMinutes();//相差的分钟数
long millis = duration.toMillis();//相差毫秒数
  • 时间转string
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate formatDate = LocalDate.of(2023, 1, 15);
String dateStr = formatDate.format(df);
System.out.println("LocalDate => String: " + dateStr); // 2023-01-15

DateTimeFormatter df2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime formatDateTime = LocalDateTime.of(2023, 1, 30, 14, 0, 0);
String dateTimeStr = formatDateTime.format(df2);
System.out.println("String => LocalDateTime: " + dateTimeStr); // 2023-01-30 14:00:00
  • string转时间
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate dateParam = LocalDate.parse(dateStr, df);
System.out.println("String => LocalDate: " + dateParam); // 2023-01-15

DateTimeFormatter df2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTimeParam = LocalDateTime.parse(dateTimeStr, df2);
System.out.println("String => LocalDateTime: " + dateTimeParam); // 2023-01-30T14:00
  • LocalDateTime转TimeStamp
LocalDateTime aa = LocalDateTime.now();
Timestamp bb = Timestamp.valueOf(aa);
Timestamp cc = new Timestamp(System.currentTimeMillis());
System.out.println("LocalDateTime => Timestamp: " + bb); // 2023-01-30 14:31:21.244
System.out.println("获取时间戳: " + bb.getTime()); // 1675060281244
System.out.println("new Timestamp(): " + cc); // 2023-01-30 14:33:41.414
  • String与TimeStamp
String dd = "2023-01-30 15:00:00";
System.out.println("String => Timestamp: " + Timestamp.valueOf(dd)); // 2023-01-30 15:00:00.0

SimpleDateFormat df3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Timestamp => String: " + df3.format(cc)); // 2023-01-30 14:40:51


时间操作工具类(直接使用)

点击查看
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;

public class TimeUtils {

/**
* 显示年月日时分秒,例如 2015-08-11 09:51:53.
*/
public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

/**
* 仅显示年月日,例如 2015-08-11.
*/
public static final String DATE_PATTERN = "yyyy-MM-dd";

/**
* 仅显示时分秒,例如 09:51:53.
*/
public static final String TIME_PATTERN = "HH:mm:ss";

/**
* 显示年月日时分秒(无符号),例如 20150811095153.
*/
public static final String UNSIGNED_DATETIME_PATTERN = "yyyyMMddHHmmss";

/**
* 仅显示年月日(无符号),例如 20150811.
*/
public static final String UNSIGNED_DATE_PATTERN = "yyyyMMdd";

/**
* 春天;
*/
public static final Integer SPRING = 1;

/**
* 夏天;
*/
public static final Integer SUMMER = 2;

/**
* 秋天;
*/
public static final Integer AUTUMN = 3;

/**
* 冬天;
*/
public static final Integer WINTER = 4;

/**
* 星期日;
*/
public static final String SUNDAY = "星期日";

/**
* 星期一;
*/
public static final String MONDAY = "星期一";

/**
* 星期二;
*/
public static final String TUESDAY = "星期二";

/**
* 星期三;
*/
public static final String WEDNESDAY = "星期三";

/**
* 星期四;
*/
public static final String THURSDAY = "星期四";

/**
* 星期五;
*/
public static final String FRIDAY = "星期五";

/**
* 星期六;
*/
public static final String SATURDAY = "星期六";

/**
* 年
*/
private static final String YEAR = "year";

/**
* 月
*/
private static final String MONTH = "month";

/**
* 周
*/
private static final String WEEK = "week";

/**
* 日
*/
private static final String DAY = "day";

/**
* 时
*/
private static final String HOUR = "hour";

/**
* 分
*/
private static final String MINUTE = "minute";

/**
* 秒
*/
private static final String SECOND = "second";

/**
* 获取当前日期和时间字符串.
*
* @return String 日期时间字符串,例如 2015-08-11 09:51:53
*/
public static String getLocalDateTimeStr() {
return format(LocalDateTime.now(), DATETIME_PATTERN);
}

/**
* 获取当前日期字符串.
*
* @return String 日期字符串,例如2015-08-11
*/
public static String getLocalDateStr() {
return format(LocalDate.now(), DATE_PATTERN);
}

/**
* 获取当前时间字符串.
*
* @return String 时间字符串,例如 09:51:53
*/
public static String getLocalTimeStr() {
return format(LocalTime.now(), TIME_PATTERN);
}

/**
* 获取当前星期字符串.
*
* @return String 当前星期字符串,例如 星期二
*/
public static String getDayOfWeekStr() {
return format(LocalDate.now(), "E");
}

/**
* 获取指定日期是星期几
*
* @param localDate 日期
* @return String 星期几
*/
public static String getDayOfWeekStr(LocalDate localDate) {
String[] weekOfDays = {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY};
int dayOfWeek = localDate.getDayOfWeek().getValue() - 1;
return weekOfDays[dayOfWeek];
}

/**
* 获取日期时间字符串
*
* @param temporal 需要转化的日期时间
* @param pattern 时间格式
* @return String 日期时间字符串,例如 2015-08-11 09:51:53
*/
public static String format(TemporalAccessor temporal, String pattern) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
return dateTimeFormatter.format(temporal);
}

/**
* 日期时间字符串转换为日期时间(java.time.LocalDateTime)
*
* @param localDateTimeStr 日期时间字符串
* @param pattern 日期时间格式 例如DATETIME_PATTERN
* @return LocalDateTime 日期时间
*/
public static LocalDateTime parseLocalDateTime(String localDateTimeStr, String pattern) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
return LocalDateTime.parse(localDateTimeStr, dateTimeFormatter);
}

/**
* 日期字符串转换为日期(java.time.LocalDate)
*
* @param localDateStr 日期字符串
* @param pattern 日期格式 例如DATE_PATTERN
* @return LocalDate 日期
*/
public static LocalDate parseLocalDate(String localDateStr, String pattern) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
return LocalDate.parse(localDateStr, dateTimeFormatter);
}

/**
* 获取指定日期时间加上指定数量日期时间单位之后的日期时间.
*
* @param localDateTime 日期时间
* @param num 数量
* @param chronoUnit 日期时间单位
* @return LocalDateTime 新的日期时间
*/
public static LocalDateTime plus(LocalDateTime localDateTime, int num, ChronoUnit chronoUnit) {
return localDateTime.plus(num, chronoUnit);
}

/**
* 获取指定日期时间减去指定数量日期时间单位之后的日期时间.
*
* @param localDateTime 日期时间
* @param num 数量
* @param chronoUnit 日期时间单位
* @return LocalDateTime 新的日期时间
*/
public static LocalDateTime minus(LocalDateTime localDateTime, int num, ChronoUnit chronoUnit) {
return localDateTime.minus(num, chronoUnit);
}

/**
* 根据ChronoUnit计算两个日期时间之间相隔日期时间
*
* @param start 开始日期时间
* @param end 结束日期时间
* @param chronoUnit 日期时间单位
* @return long 相隔日期时间
*/
public static long getChronoUnitBetween(LocalDateTime start, LocalDateTime end, ChronoUnit chronoUnit) {
return Math.abs(start.until(end, chronoUnit));
}

/**
* 根据ChronoUnit计算两个日期之间相隔年数或月数或天数
*
* @param start 开始日期
* @param end 结束日期
* @param chronoUnit 日期时间单位,(ChronoUnit.YEARS,ChronoUnit.MONTHS,ChronoUnit.WEEKS,ChronoUnit.DAYS)
* @return long 相隔年数或月数或天数
*/
public static long getChronoUnitBetween(LocalDate start, LocalDate end, ChronoUnit chronoUnit) {
return Math.abs(start.until(end, chronoUnit));
}

/**
* 获取本年第一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfYearStr() {
return getFirstDayOfYearStr(LocalDateTime.now());
}

/**
* 获取本年最后一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfYearStr() {
return getLastDayOfYearStr(LocalDateTime.now());
}

/**
* 获取指定日期当年第一天的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfYearStr(LocalDateTime localDateTime) {
return getFirstDayOfYearStr(localDateTime, DATETIME_PATTERN);
}

/**
* 获取指定日期当年最后一天的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfYearStr(LocalDateTime localDateTime) {
return getLastDayOfYearStr(localDateTime, DATETIME_PATTERN);
}

/**
* 获取指定日期当年第一天的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfYearStr(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.withDayOfYear(1).withHour(0).withMinute(0).withSecond(0), pattern);
}

/**
* 获取指定日期当年最后一天的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfYearStr(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.with(TemporalAdjusters.lastDayOfYear()).withHour(23).withMinute(59).withSecond(59), pattern);
}

/**
* 获取本月第一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfMonthStr() {
return getFirstDayOfMonthStr(LocalDateTime.now());
}

/**
* 获取本月最后一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfMonthStr() {
return getLastDayOfMonthStr(LocalDateTime.now());
}

/**
* 获取指定日期当月第一天的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getFirstDayOfMonthStr(LocalDateTime localDateTime) {
return getFirstDayOfMonthStr(localDateTime, DATETIME_PATTERN);
}

/**
* 获取指定日期当月最后一天的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfMonthStr(LocalDateTime localDateTime) {
return getLastDayOfMonthStr(localDateTime, DATETIME_PATTERN);
}

/**
* 获取指定日期当月第一天的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfMonthStr(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0), pattern);
}

/**
* 获取指定日期当月最后一天的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfMonthStr(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59), pattern);
}

/**
* 获取本周第一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfWeekStr() {
return getFirstDayOfWeekStr(LocalDateTime.now());
}

/**
* 获取本周最后一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfWeekStr() {
return getLastDayOfWeekStr(LocalDateTime.now());
}

/**
* 获取指定日期当周第一天的日期字符串,这里第一天为周一
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfWeekStr(LocalDateTime localDateTime) {
return getFirstDayOfWeekStr(localDateTime, DATETIME_PATTERN);
}

/**
* 获取指定日期当周最后一天的日期字符串,这里最后一天为周日
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfWeekStr(LocalDateTime localDateTime) {
return getLastDayOfWeekStr(localDateTime, DATETIME_PATTERN);
}

/**
* 获取指定日期当周第一天的日期字符串,这里第一天为周一,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfWeekStr(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.with(DayOfWeek.MONDAY).withHour(0).withMinute(0).withSecond(0), pattern);
}

/**
* 获取指定日期当周最后一天的日期字符串,这里最后一天为周日,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfWeekStr(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.with(DayOfWeek.SUNDAY).withHour(23).withMinute(59).withSecond(59), pattern);
}

/**
* 获取今天开始时间的日期字符串
*
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getStartTimeOfDayStr() {
return getStartTimeOfDayStr(LocalDateTime.now());
}

/**
* 获取今天结束时间的日期字符串
*
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getEndTimeOfDayStr() {
return getEndTimeOfDayStr(LocalDateTime.now());
}

/**
* 获取指定日期开始时间的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getStartTimeOfDayStr(LocalDateTime localDateTime) {
return getStartTimeOfDayStr(localDateTime, DATETIME_PATTERN);
}

/**
* 获取指定日期结束时间的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getEndTimeOfDayStr(LocalDateTime localDateTime) {
return getEndTimeOfDayStr(localDateTime, DATETIME_PATTERN);
}

/**
* 获取指定日期开始时间的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd HH:mm:ss
*/
public static String getStartTimeOfDayStr(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.withHour(0).withMinute(0).withSecond(0), pattern);
}

/**
* 获取指定日期结束时间的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getEndTimeOfDayStr(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.withHour(23).withMinute(59).withSecond(59), pattern);
}

/**
* 切割日期。按照周期切割成小段日期段。例如: <br>
*
* @param startDate 开始日期(yyyy-MM-dd)
* @param endDate 结束日期(yyyy-MM-dd)
* @param period 周期(天,周,月,年)
* @return 切割之后的日期集合
* <li>startDate="2019-02-28",endDate="2019-03-05",period="day"</li>
* <li>结果为:[2019-02-28, 2019-03-01, 2019-03-02, 2019-03-03, 2019-03-04, 2019-03-05]</li><br>
* <li>startDate="2019-02-28",endDate="2019-03-25",period="week"</li>
* <li>结果为:[2019-02-28,2019-03-06, 2019-03-07,2019-03-13, 2019-03-14,2019-03-20,
* 2019-03-21,2019-03-25]</li><br>
* <li>startDate="2019-02-28",endDate="2019-05-25",period="month"</li>
* <li>结果为:[2019-02-28,2019-02-28, 2019-03-01,2019-03-31, 2019-04-01,2019-04-30,
* 2019-05-01,2019-05-25]</li><br>
* <li>startDate="2019-02-28",endDate="2020-05-25",period="year"</li>
* <li>结果为:[2019-02-28,2019-12-31, 2020-01-01,2020-05-25]</li><br>
*/
public static List<String> listDateStrs(String startDate, String endDate, String period) {
List<String> result = new ArrayList<>();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
LocalDate end = LocalDate.parse(endDate, dateTimeFormatter);
LocalDate start = LocalDate.parse(startDate, dateTimeFormatter);
LocalDate tmp = start;
switch (period) {
case DAY:
while (start.isBefore(end) || start.isEqual(end)) {
result.add(start.toString());
start = start.plusDays(1);
}
break;
case WEEK:
while (tmp.isBefore(end) || tmp.isEqual(end)) {
if (tmp.plusDays(6).isAfter(end)) {
result.add(tmp.toString() + "," + end);
} else {
result.add(tmp.toString() + "," + tmp.plusDays(6));
}
tmp = tmp.plusDays(7);
}
break;
case MONTH:
while (tmp.isBefore(end) || tmp.isEqual(end)) {
LocalDate lastDayOfMonth = tmp.with(TemporalAdjusters.lastDayOfMonth());
if (lastDayOfMonth.isAfter(end)) {
result.add(tmp.toString() + "," + end);
} else {
result.add(tmp.toString() + "," + lastDayOfMonth);
}
tmp = lastDayOfMonth.plusDays(1);
}
break;
case YEAR:
while (tmp.isBefore(end) || tmp.isEqual(end)) {
LocalDate lastDayOfYear = tmp.with(TemporalAdjusters.lastDayOfYear());
if (lastDayOfYear.isAfter(end)) {
result.add(tmp.toString() + "," + end);
} else {
result.add(tmp.toString() + "," + lastDayOfYear);
}
tmp = lastDayOfYear.plusDays(1);
}
break;
default:
break;
}
return result;
}


java连接sqlserve

点击查看
  1. maven依赖

    <dependency>
    <groupId>net.sourceforge.jtds</groupId>
    <artifactId>jtds</artifactId>
    <version>1.3.1</version>
    </dependency>
  2. 获取连接,取得结果 import java.sql.*;

    /**
    * java连接sqlserver
    * @param sql 要执行的sql语句
    * @return 执行结果对象
    */
    public ResultSet getConnection(String sql) {
    Connection con = null;
    ResultSet rs = null;
    try {
    Class.forName("net.sourceforge.jtds.jdbc.Driver");
    con = DriverManager.getConnection("jdbc:jtds:sqlserver://121.49.0.161:1433;DatabaseName=jpzjk", "sa", "123.com");
    Statement st = con.createStatement();
    rs = st.executeQuery(sql);// 返回结果
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    if (con != null)
    try {
    con.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    return rs;
    }
  3. 使用(处理结果)

    public void test() throws SQLException {
    String sql = "SELECT t2.CARDNO barcode,t2.USERNAME name,t1.CREATETIME time FROM CirculateLog t1 " +
    "INNER JOIN Reader t2 ON t1.READERBARCODE=t2.BARCODE " +
    "WHERE t1.CONTROLTYPE='J' AND t1.CREATETIME>='" + "2023-05-01 00:00:00" + "' " +
    "and t1.CREATETIME<='" + "2023-05-01 23:59:59" + "'";
    ResultSet rs = this.getConnection(sql);

    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    List<CirculateInfoDto> results = new ArrayList<>();// 结果集
    while (rs.next()) {
    CirculateInfoDto dto = new CirculateInfoDto();// 封装为自定义对象
    dto.setBarcode(rs.getString(1));
    dto.setName(rs.getString(2));
    dto.setTime(LocalDateTime.parse(rs.getString(3).substring(0, 19), df));
    results.add(dto);
    }

    System.out.println("封装后的接口集合:"+results);
    }


java调用第三方接口

点击查看

利用 HttpClientBuilder创建连接对象

  1. post方式

    public static String postMethod(String url, JSONObject json){
    try {
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    HttpPost post = new HttpPost(url);
    post.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
    StringEntity s = new StringEntity(json.toString());
    s.setContentEncoding("UTF-8");
    //发送json数据需要设置contentType
    s.setContentType("application/x-www-form-urlencoded");
    post.setEntity(s); //设置请求参数
    HttpResponse response = httpClient.execute(post);
    int statusCode = response.getStatusLine().getStatusCode();
    if (HttpStatus.SC_OK == statusCode){
    //返回String
    String res = EntityUtils.toString(response.getEntity());
    System.out.println(res);
    return res;
    }

    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }
  2. get方式

    public static String getMethod(String url){
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    HttpGet get = new HttpGet(url);
    try{
    //这里可以设置请求参数,token等
    get.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
    HttpResponse response = httpClient.execute(get);//执行获取响应
    if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){//根据状态码处理
    //返回字符串
    String res = EntityUtils.toString(response.getEntity());
    System.out.println(res);
    return res;
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    return null;
    }


计算地图上两坐标点距离

点击查看
  1. 计算方法

    private static final double EARTH_RADIUS = 6378.137;// 地球半径,单位千米

    private static double rad(double d) {
    //角度转换成弧度
    return d * Math.PI / 180.0;
    }




    /**
    * 计算两个地点的距离
    *
    * @param lat1 第一个纬度
    * @param lng1 第一个经度
    * @param lat2 第二个纬度
    * @param lng2 第二个经度
    * @return 两个经纬度的距离
    */
    public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
    double radLat1 = rad(lat1);//纬度
    double radLat2 = rad(lat2);
    double a = radLat1 - radLat2;//两点纬度之差
    double b = rad(lng1) - rad(lng2);//经度之差

    //计算两点之间距离的公式
    double s = 2 * Math.asin(Math.sqrt(
    Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
    //弧长乘地球半径(半径)
    s = s * EARTH_RADIUS;
    //精确距离的数值(单位千米)
    s = Math.round(s * 10000) / 10000;
    return s;

    }
  1. 演示使用

    public static void main(String[] args) {
    try {
    System.out.println("太原-上海:" + getDistance(37.87, 112.53, 31.22, 121.48));
    System.out.println("宁波-上海:" + getDistance(29.86, 121.56, 31.22, 121.48));
    } catch (Exception e) {
    e.printStackTrace();
    }
    }


easyexcel导入、导出

点击查看
  1. maven依赖

    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.5</version>
    </dependency>
  2. 导入、导出的操作对象

    @ExcelProperty()就是用来设置表头的,也可以这样写:@ExcelProperty(value="名称",index=索引),如果不需要某个字段,可以使用@ExcelIgnore注解忽略;此外@ExcelProperty()还有很多配置各种类型的表头,详情可以参考EasyExcel官方文档

    @TableName(value = "user")
    @Data
    public class User implements Serializable {
    //@ExcelProperty:配置表头
    @ExcelProperty("主键")
    private String id;
    @ExcelProperty("姓名")
    private String yhxm;
    @ExcelProperty("性别")
    private String yhxb;
    @ExcelProperty("登陆账号")
    private String yhzh;
    @ExcelProperty("登陆密码")
    private String yhmm;
    @ExcelProperty("出生年月")
    private Date csrq;
    }
  1. 导出

    public void exportRecord(SelectCardManageListParam param, HttpServletResponse response) {
    try {
    //1.设置response的基本数据
    response.setContentType("application/vnd.ms-excel");
    response.setCharacterEncoding("utf-8");
    // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
    String fileName = URLEncoder.encode("卡片信息", "UTF-8");
    response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

    //2.查询数据
    List<SelectCardManageListDto> data = new ArrayList<>();
    if (param.getType() == null && param.getIsSend() == null && param.getStatus() == null && (param.getKeyword() == null || "".equals(param.getKeyword()))) {
    data = syncCardData;
    } else {
    param.setPageSize(99999);
    BaseReturnDto<com.example.java.tool.Page<SelectCardManageListDto>> dto = new BaseReturnDto<>();
    this.list(param, dto);
    data = dto.getData().getList();
    }


    //4,使用工具导出
    EasyExcel.write(response.getOutputStream(), SelectCardManageListDto.class)
    .sheet("卡片信息")
    .doWrite(data);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
  1. 导入
@PostMapping("ImportExcel")
public void ImportExcel(MultipartFile multipartFile) throws IOException {
if (multipartFile.isEmpty()) {
return;
}
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
// 这里每次会读取3000条数据 然后返回过来 直接调用使用数据就行
EasyExcel.read(multipartFile.getInputStream(), User.class, new PageReadListener<User>(dataList -> {
for (User user : dataList) {
//将导入的数据用mybatisPlus一个个添加进数据库
loginMapper.insert(user);
}
})).sheet().doRead();
}

拦截器

public class BatchJoinListener extends AnalysisEventListener<JoinTempDTO> {

private List<JoinArmyDTO> list = new ArrayList<>();
private ArmedServiceImpl armedService;

public BatchJoinListener(ArmedServiceImpl armedService) {
this.armedService = armedService;
}

@Override
public void invoke(JoinTempDTO data, AnalysisContext context)
{
if(CharSequenceUtil.isNotEmpty(data.getNumber())
&&CharSequenceUtil.isNotEmpty(data.getDay())){
JoinArmyDTO dto = new JoinArmyDTO();

String[] split = new String[]{};
if(data.getDay().contains("-")){
split = data.getDay().split("-");
}else if(data.getDay().contains("/")){
split = data.getDay().split("/");
}
String m = split[1];
if (m.length() == 1) {
m = "0" + m;
}
String d = split[2];
if (d.length() == 1) {
d = "0" + d;
}

dto.setDay(split[0] + "-" + m + "-" + d);
dto.setNumber(data.getNumber());
list.add(dto);
}
}

@Override
public void doAfterAllAnalysed(AnalysisContext context)
{
if(!list.isEmpty()){
for(JoinArmyDTO dto:list){
armedService.joinArmy(dto,new BaseReturnDto<>());
}

list.clear();
}
}
}


Linux定时任务

点击查看
  1. 关于crontab

    使用命令rpm -qa | grep cron查看系统是否已经安装有crontab软件,如显示如下图则证明已经安装crontab,若执行命令无返回值则证明尚未安装crontab。

    image-20230615143640848

    安装、启动、开机自启

    yum install -y vixie-cron crontabs  #安装

    /sbin/service crond start #启动服务

    /sbin/service crond stop #关闭服务

    /sbin/service crond restart #重启服务

    /sbin/service crond reload #重新载入配置

    corn表达式实例

    0 */2 * * * /sbin/service httpd restart  #意思是每两个小时重启一次apache 

    50 7 * * * /sbin/service sshd start #意思是每天7:50开启ssh服务

    50 22 * * * /sbin/service sshd stop #意思是每天22:50关闭ssh服务

    0 0 1,15 * * fsck /home #每月1号和15号检查/home 磁盘

    1 * * * * /home/bruce/backup #每小时的第一分执行 /home/bruce/backup这个文件

    00 03 * * 1-5 find /home "*.xxx" -mtime +4 -exec rm {} \; #每周一至周五3点钟,在目录/home中,查找文件名为*.xxx的文件,并删除4天前的文件。

    30 6 */10 * * ls #意思是每月的1、11、21、31日是的6:30执行一次ls命令

  2. 每天定时重启java服务

    编写sh脚本文件,如:restart-blog.sh

    #! /bin/bash
    #jdk路径,根据你自己的jdk安装位置修改
    export PATH=$PATH:/usr/java/jdk1.8.0_162/bin/
    #要执行的jar包路径
    cd /home/application/govern/
    #要执行的jar包名称
    APP_NAME=data-govern-1.0.0.jar
    #找到服务的pid
    pid=`ps -ef | grep $APP_NAME | grep -v grep | awk '{print $2}' `
    #停止服务
    kill -9 $pid
    #启动服务
    nohup java -jar $APP_NAME --spring.profiles.active=dev --javax.security.auth.useSubjectCredsOnly=false --java.security.krb5.debug=true --server.port=8888 > govern.log 2>&1 &
    echo $(date +%F)":restart end *************" >> /opt/shFile/equipment/restartLog #重启完成后打印日志

    给脚本文件赋予777权限

    chmod 777 restart-blog.sh

    查看jdk安装路径(前提是需要配置环境变量),得到的路径需要去确认,会变,如下图

    echo $JAVA_HOME

    image-20230615145151364

    image-20230615145322222

    也可以使用命令vi /etc/profile

    image-20230615153444999

添加crontab定时规则:50 23 * * * /workspace/restart-blog.sh

crontab -e #按下键盘i进行编辑,q!不保存退出,wq保存退出

image-20230615145736351

然后重启crontab

/sbin/service crond restart

参考文章:https://blog.csdn.net/sun_luming/article/details/120421150


poi操作word文档

点击查看
  1. maven依赖

    <dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
    </dependency>

    <dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
    </dependency>
    <dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>4.1.2</version>
    </dependency>
  2. 可能会报错:UnsupportedFileFormatException,是因为jar包的原因,可能版本太低(4.0.0),三个版本要一致,我报错的原因是,我在公共模块服务引入的此依赖,但是在我使用模块就用不了,干脆就直接在那使用,就在那个模块引入

  3. 工具类



    import org.apache.poi.hwpf.HWPFDocument;
    import org.apache.poi.hwpf.usermodel.Range;
    import org.apache.poi.ooxml.POIXMLDocument;
    import org.apache.poi.xwpf.usermodel.*;
    import org.apache.xmlbeans.XmlCursor;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
    import org.springframework.stereotype.Component;

    import java.io.*;
    import java.math.BigInteger;
    import java.util.*;

    /**
    * @Author:李明光
    * @Date:2023-6-14 14:22
    */

    @Component
    public class CommonTool {

    public static void main(String[] args) throws IOException {
    // String filePath = "C:\\Users\\Administrator\\Desktop\\1.docx";
    // String formart = "DOCX";
    // Map<String, String> textMap = new HashMap<>();
    // textMap.put("${标题}", "隐患整改通知书**");
    // textMap.put("${内容}", "统计报告。文档形式 配置项:报告模板、统计周期等设置。报告列表(1月季度隐患报告),可下载。按年月日\n" +
    // "\t通报:生成--需要设置模板,不需要设置周期,它是根据统计报告的数据生成的,他的生成周期与统计报告一致。发布--是否自动发布(定时、条件-年月日)、发布范围(具体那些部门)。通报列表--可以发布、下载\n" +
    // "\n" +
    // "\t自动分派 手动分派");
    // textMap.put("${姓名}", "安全管理处");
    // textMap.put("${时间}", "2023-06-01");
    // textMap.put("${aaa}", "2023-06-0100");
    // wordTextSubstitution(filePath, formart, textMap, "隐患整改通知书");
    //替换的内容,根据key为关键字指定替换成value的值
    HashMap<String, String> textMap = new HashMap<>();
    textMap.put("${标题}", "隐患整改通知书**");
    textMap.put("${内容}", "统计报告。文档形式 配置项:报告模板、统计周期等设置。报告列表(1月季度隐患报告),可下载。按年月日\n" +
    "\t通报:生成--需要设置模板,不需要设置周期,它是根据统计报告的数据生成的,他的生成周期与统计报告一致。发布--是否自动发布(定时、条件-年月日)、发布范围(具体那些部门)。通报列表--可以发布、下载\n" +
    "\n" +
    "\t自动分派 手动分派");
    textMap.put("${姓名}", "安全管理处");
    textMap.put("${时间}", "2023-06-01");
    textMap.put("${aaa}", "2023-06-0100");

    String srcPath = "C:\\Users\\Administrator\\Desktop\\3.docx"; //模板文件的地址
    String destPath = "C:\\Users\\Administrator\\Desktop\\2.docx"; //替换后保存的地址
    // searchAndReplace(srcPath, destPath, textMap);

    List<String> headList = new ArrayList<>();
    headList.add("责任单位");
    headList.add("单位负责人");
    headList.add("统计时间段");
    headList.add("完成率");
    headList.add("及时率");

    List<String[]> bodyList = new ArrayList<>();
    String[] arr1 = {"保安部", "张三","2023-06-01——2023-06-07","50%","80%"};
    String[] arr2 = {"保安部", "李四","2023-06-01——2023-06-07","50%","80%"};
    String[] arr3 = {"保安部", "王五","2023-06-01——2023-06-07","50%","80%"};
    bodyList.add(arr1);
    bodyList.add(arr2);
    bodyList.add(arr3);

    wordTextSubstitution(srcPath, "DOCX", textMap,"aaa",headList,bodyList);

    }

    /**
    * 只能替换文档内容
    * 可在 ${table} 关键字出替换为生成的表格
    *
    * @param filePath 替换文件所在路径
    * @param formart 替换文件扩展名
    * @param map 替换数据集合(关键字-实际值)
    * @param newName 新生成的文件名
    * @param headList 标题集合
    * @param bodyList 每一行每一列的数据集合
    */
    public static void wordTextSubstitution(String filePath, String formart, Map<String, String> map, String newName,List<String> headList,List<String[]> bodyList) {
    String textPath = "";
    File file = new File(filePath);
    String fileName = file.getName();
    try {
    if ("DOCX".equals(formart)) {
    if (!"".equals(fileName)) {
    textPath = filePath.replaceAll(fileName, newName + "_" + System.currentTimeMillis() + ".docx");
    }
    XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(filePath));
    // 替换段落中的指定文字
    Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();

    while (itPara.hasNext()) {
    XWPFParagraph paragraph = itPara.next();
    List<XWPFRun> runs = paragraph.getRuns();
    for (int i = 0; i < runs.size(); i++) {
    String oneparaString = runs.get(i).getText(runs.get(i).getTextPosition());
    if (oneparaString != null) {
    if(oneparaString.equals("${table}")){ // 判断该关键字是否为table,是则将数据转为表格插入
    oneparaString = oneparaString.replace("${table}","");
    runs.get(i).setText(oneparaString, 0);
    XmlCursor cursor = paragraph.getCTP().newCursor();
    // 在指定游标位置插入表格
    XWPFTable table = document.insertNewTbl(cursor);

    CTTblPr tablePr = table.getCTTbl().getTblPr();
    CTTblWidth width = tablePr.addNewTblW();
    width.setW(BigInteger.valueOf(8500));

    if(headList==null||headList.isEmpty()||bodyList==null||bodyList.isEmpty()){
    continue;
    }
    insertTable(table,headList,bodyList);

    }else { // 不是table关键字则按照文档替换进行
    for (Map.Entry<String, String> entry : map.entrySet()) {
    oneparaString = oneparaString.replace(entry.getKey(), entry.getValue());
    }
    runs.get(i).setText(oneparaString, 0);
    }
    }
    }
    }

    // 创建新文件存放新内容
    FileOutputStream outStream = new FileOutputStream(textPath);
    document.write(outStream);
    outStream.close();
    } else if ("DOC".equals(formart)) {
    if (!"".equals(fileName)) {
    textPath = filePath.replaceAll(fileName, newName + "_" + System.currentTimeMillis() + ".doc");
    }
    HWPFDocument document = new HWPFDocument(new FileInputStream(filePath));
    Range range = document.getRange();
    for (Map.Entry<String, String> entry : map.entrySet()) {
    range.replaceText(entry.getKey(), entry.getValue());
    }
    // 创建新文件存放新内容
    FileOutputStream outStream = new FileOutputStream(textPath);
    document.write(outStream);
    outStream.close();
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    /**
    * 替换string中的预设关键字
    *
    * @param str 源字符串
    * @param map 关键字-要替换的值
    * @return
    */
    public static String replaceStr(String str, Map<String, String> map) {
    for (String key : map.keySet()) {
    str = str.replace(key, map.get(key));
    }

    return str;
    }


    /**
    * 无论替换文档和表格都可以,但没有新增表格能力
    * @param srcPath 模板文件的地址
    * @param destPath 导出的文件保存地址
    * @param map 替换的内容
    */
    public static void searchAndReplace(String srcPath, String destPath, Map<String, Object> map) {
    try {
    // 替换的的关键字存放到Set集合中
    Set<String> set = map.keySet();
    // 读取模板文档
    XWPFDocument document = new XWPFDocument(new FileInputStream(srcPath));
    /**
    * 替换段落中的指定文字
    */
    // 读取文档中的段落,回车符为一个段落。
    // 同一个段落里面会被“:”等符号隔开为多个对象
    Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();
    while (itPara.hasNext()) {
    // 获取文档中当前的段落文字信息
    XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
    List<XWPFRun> run = paragraph.getRuns();
    // 遍历段落文字对象
    for (int i = 0; i < run.size(); i++) {
    // 获取段落对象
    if (run.get(i) == null) { //段落为空跳过
    continue;
    }
    String sectionItem = run.get(i).getText(run.get(i).getTextPosition()); //段落内容
    // 遍历自定义表单关键字,替换Word文档中的内容
    Iterator<String> iterator = set.iterator();
    while (iterator.hasNext()) {
    // 当前关键字
    String key = iterator.next();
    // 替换内容
    sectionItem = sectionItem.replace(key, String.valueOf(map.get(key)));
    }
    run.get(i).setText(sectionItem, 0);
    }
    }

    /**
    * 替换表格中的指定文字
    */
    //获取文档中所有的表格,每个表格是一个元素
    Iterator<XWPFTable> itTable = document.getTablesIterator();
    while (itTable.hasNext()) {
    XWPFTable table = (XWPFTable) itTable.next(); //获取表格内容
    int count = table.getNumberOfRows(); //表格的行数
    //遍历表格行的对象
    for (int i = 0; i < count; i++) {
    XWPFTableRow row = table.getRow(i); //表格每行的内容
    List<XWPFTableCell> cells = row.getTableCells(); //每个单元格的内容
    //遍历表格的每行单元格对象
    for (int j = 0; j < cells.size(); j++) {
    XWPFTableCell cell = cells.get(j); //获取每个单元格的内容
    List<XWPFParagraph> paragraphs = cell.getParagraphs(); //获取单元格里所有的段落
    for (XWPFParagraph paragraph : paragraphs) {
    //获取段落的内容
    List<XWPFRun> run = paragraph.getRuns();
    // 遍历段落文字对象
    for (int o = 0; o < run.size(); o++) {
    // 获取段落对象
    if (run.get(o) == null || run.get(o).equals("")) {
    continue;
    }
    String sectionItem = run.get(o).getText(run.get(o).getTextPosition()); //获取段落内容
    if (sectionItem == null || sectionItem.equals("")) { //段落为空跳过
    continue;
    }
    //遍历自定义表单关键字,替换Word文档中表格单元格的内容
    for (String key : map.keySet()) {
    // 替换内容
    sectionItem = sectionItem.replace(key, String.valueOf(map.get(key)));
    run.get(o).setText(sectionItem, 0);
    }
    }
    }
    }
    }
    }
    FileOutputStream outStream = null;
    outStream = new FileOutputStream(destPath);
    document.write(outStream);
    outStream.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    /**
    * 根据数据生成表格,并插入到word中
    * @param table 表格对象
    * @param headList 标题集合
    * @param bodyList 每一行每一列的数据集合
    */
    private static void insertTable(XWPFTable table,List<String> headList,List<String[]> bodyList) {
    table.setWidthType(TableWidthType.AUTO);
    XWPFTableRow row = table.getRow(0);

    for (int col = 1; col < headList.size(); col++) {//默认会创建一列,即从第2列开始
    // 第一行创建了多少列,后续增加的行自动增加列
    row.createCell().getCTTc().addNewTcPr();
    }

    // 设置头部标题
    for(int i=0;i<headList.size();i++){
    setText(row.getCell(i),headList.get(i));
    }

    // 设置每一行内容
    for(int i=0;i<bodyList.size();i++){//外层循环为行数,内层循环为列数
    row = table.createRow(); // 创建一个新行
    String[] cols = bodyList.get(i); // 得到该行的列值数组
    for(int j=0;j<cols.length;j++){ // 循环列值挨个插入
    setText(row.getCell(j),cols[j]);
    }
    }
    }

    /**
    * 设置表格中要被替换的字段值
    */
    private static void setText(XWPFTableCell cell,String text){
    // 设置内容居中
    CTTc ctTc = cell.getCTTc();
    CTTcPr ctPr = ctTc.addNewTcPr();
    ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
    ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);

    // 替换值
    cell.setText(text);
    }

    }





idea相关

点击查看
1、maven模块显示不是maven项目--解决

可能缺少.iml文件,idea无法识别

image-20230704151328253

先打开对应模块的命令终端,生成iml文件

image-20230704151453872

然后输入命令

mvn idea:module

image-20230704152034746

导入对应的模块

image-20230704152115503

image-20230704152200271

image-20230704152213335

然后再设置文件夹,点到对应的文件夹,再点击文件类型

image-20230704152345022


mysql相关cc

点击查看
1、设置最大连接数
SHOW VARIABLES LIKE 'max_connections'; #查看当前的最大连接数

SET GLOBAL max_connections=2000; #设置最大连接数


webSocket相关

点击查看
1、springboot整合webSocket基础Demo

  • maven依赖

    <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">
    <modelVersion>4.0.0</modelVersion>
    <groupId>shenzhanwang</groupId>
    <artifactId>Spring-websocket</artifactId>
    <version>1.1.0</version>
    <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
    <version>2.1.6.RELEASE</version>
    </dependency>

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.1.6.RELEASE</version>
    </dependency>

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.1.6.RELEASE</version>
    </dependency>

    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.68</version>
    </dependency>
    </dependencies>
    </project>
  • WebSocketConfig配置类

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;

    /**
    * WebScoket配置处理器
    */
    @Configuration
    public class WebSocketConfig {
    /**
    * ServerEndpointExporter 作用
    *
    * 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint
    *
    * @return
    */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
    return new ServerEndpointExporter();
    }

    }
  • webSocket服务类

    import org.springframework.stereotype.Component;

    import javax.websocket.OnMessage;
    import javax.websocket.server.ServerEndpoint;

    // 该注解表示,此类为WebSocket的服务类
    @ServerEndpoint("/webSocket/{id}")
    @Component
    public class EchoServer {
    @OnMessage
    public String encho(String in){
    return "hello world";
    }

    }
  • yaml端口配置

    server.port=8080
  • 前端调用方式

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>SseEmitter</title>
    </head>
    <body>
    <div id="message"></div>
    </body>
    <script>
    var limitConnect = 0;
    init();
    function init() {
    // 8080未默认端口,可自行替换
    var ws = new WebSocket('ws://localhost:8080/notice/2');
    // 获取连接状态
    console.log('ws连接状态:' + ws.readyState);
    //监听是否连接成功
    ws.onopen = function () {
    console.log('ws连接状态:' + ws.readyState);
    limitConnect = 0;
    //连接成功则发送一个数据
    ws.send('我们建立连接啦');
    }
    // 接听服务器发回的信息并处理展示
    ws.onmessage = function (data) {
    console.log('接收到来自服务器的消息:');
    console.log(data);
    //完成通信后关闭WebSocket连接
    // ws.close();
    }
    // 监听连接关闭事件
    ws.onclose = function () {
    // 监听整个过程中websocket的状态
    console.log('ws连接状态:' + ws.readyState);
    reconnect();

    }
    // 监听并处理error事件
    ws.onerror = function (error) {
    console.log(error);
    }
    }
    function reconnect() {
    limitConnect ++;
    console.log("重连第" + limitConnect + "次");
    setTimeout(function(){
    init();
    },2000);

    }
    </script>
    </html>

  • 在线查看是否连接成功:> websocket/ws/wss在线调试测试工具 (jackxiang.com)

  • ​ 测试结果

    image-20230818162530269

2、webSocket使用升级——聊天室

待续…


将办公软件转为PDF—文件预览

点击查看
1、maven依赖
aspose-words(用于word、txt转pdf),itextpdf(用于ppt、图片、excel转pdf)
<dependency>    
<groupId>com.luhuiguo</groupId>
<artifactId>aspose-words</artifactId>
<version>23.1</version>
</dependency>
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>5.2.0</version>
</dependency>
<!-- itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.2</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
2、操作文件的工具类

import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
* @author fhey
* @date 2023-04-20 11:15:58
* @description: 文件工具类
*/
public class FileUtil {
private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);

//获取新文件的全路径
public static String getNewFileFullPath(String sourceFilePath, String destFilePath, String ext) {
File destFile = new File(destFilePath);
if (destFile.isFile()) {
return destFilePath;
}
File sourceFile = new File(sourceFilePath);
String sourceFileName = sourceFile.getName();
sourceFileName = sourceFileName.substring(0,sourceFileName.lastIndexOf("."));
if (sourceFile.isFile()) {
return destFilePath + File.separator + sourceFileName.substring(0, sourceFileName.lastIndexOf(StrUtil.DOT)) + StrUtil.DOT + ext;
}
return destFilePath + File.separator + sourceFileName + StrUtil.DOT + ext;
}

//判断文件是否是图片
public static boolean isImage(File file) throws IOException {
FileInputStream is = new FileInputStream(file);
byte[] bytes = new byte[8];
is.read(bytes);
is.close();
String type = bytesToHexString(bytes).toUpperCase();
if (type.contains("FFD8FF") //JPEG(jpg)
|| type.contains("89504E47") //PNG
|| type.contains("47494638") //GIF
|| type.contains("49492A00") //TIFF(tif)
|| type.contains("424D") //Bitmap(bmp)
) {
return true;
}
return false;
}

//将文件头转换成16进制字符串
public static String bytesToHexString(byte[] src) {
StringBuilder builder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
builder.append(0);
}
builder.append(hv);
}
return builder.toString();
}

}


3、文件转换工具类

import com.aspose.words.Document;
import com.example.java.feign.Feign;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xslf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.awt.Color;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.util.List;


@Component
public class FileToPdf {
private final Logger logger = LoggerFactory.getLogger(FileToPdf.class);

@Autowired
Feign feign;

//将word转成pdf
public String wordToPdf(String wordPath) throws Exception {
String pdfPath = "C:/school/copy" + wordPath.substring(wordPath.lastIndexOf("/")-11,wordPath.lastIndexOf("/")+1);
pdfPath = FileUtil.getNewFileFullPath(wordPath, pdfPath, "pdf");
File file = new File(pdfPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
FileOutputStream os = new FileOutputStream(file);
String path = "http://192.168.0.65" + wordPath;
Document doc = new Document(CommonTool.getInputStreamByUrl(path));
doc.save(os, com.aspose.words.SaveFormat.PDF);
os.close();

// 跨服务器传输(67->65)
Tool tool = new Tool();
MultipartFile multipartFile = tool.getMultipartFile(new File(pdfPath));
return feign.BaseFeign.BaseCommonFeign.uploads(multipartFile).getData();
}

public static void wordToPdf(String wordPath, String pdfPath) throws Exception {
pdfPath = FileUtil.getNewFileFullPath(wordPath, pdfPath, "pdf");
File file = new File(pdfPath);
FileOutputStream os = new FileOutputStream(file);
Document doc = new Document(wordPath);
doc.save(os, com.aspose.words.SaveFormat.PDF);
}


/**
* 将网络地址文件保存到本地,并且返回本地地址
*/
public String getUrl(String wordPath) throws Exception {
String path = "C:/school/copy" + wordPath.substring(wordPath.lastIndexOf("/")-11);
File file = new File(path);
File fileParent = file.getParentFile();
if(!fileParent.exists()){
fileParent.mkdirs();
}

FileOutputStream os = new FileOutputStream(file);
InputStream is = CommonTool.getInputStreamByUrl("http://192.168.0.65" + wordPath);
byte[] bytes = new byte[1024];
int len;
while ((len = is.read(bytes)) != -1){
os.write(bytes,0,len);
}
os.close();
is.close();

return path;
}
public static void main(String[] args) {
String wordPath= "/demo/base/uploads/2023-08-24/1692855303812608.xlsx";
System.out.println("C:/school/copy" + wordPath.substring(wordPath.lastIndexOf("/")-11,wordPath.lastIndexOf("/")+1));
System.out.println(wordPath.substring(wordPath.lastIndexOf(".")+1));

System.out.println("aaa.txt".substring(0,"aaa.txt".lastIndexOf(".")));
}

//将txt转成pdf
public String txtToPdf(String txtPath) throws Exception {
return wordToPdf(txtPath);
}

/**
* InputStream转file
* @param inputStream
* @return
* @throws IOException
*/
public File asFile(InputStream inputStream) throws IOException{
File tmp = File.createTempFile("img", "png", new File("C:/school/copy"));
if(!tmp.getParentFile().exists()){
tmp.getParentFile().mkdirs();
}
OutputStream os = new FileOutputStream(tmp);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
inputStream.close();
os.close();
return tmp;
}

//将图片转成pdf
public String imageToPdf(String imagePath) throws Exception {
String pdfPath = "C:/school/copy" + imagePath.substring(imagePath.lastIndexOf("/")-11,imagePath.lastIndexOf("/")+1);
pdfPath = FileUtil.getNewFileFullPath(imagePath, pdfPath, "pdf");
File file = new File(pdfPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}

InputStream is = CommonTool.getInputStreamByUrl("http://192.168.0.65"+imagePath);
File imageFile = asFile(is);
File[] files;
if (imageFile.isDirectory()) {
files = imageFile.listFiles();
} else {
files = new File[]{imageFile};
}
imageToPdf(files, pdfPath);

// 跨服务器传输(67->65)
Tool tool = new Tool();
MultipartFile multipartFile = tool.getMultipartFile(new File(pdfPath));
return feign.BaseFeign.BaseCommonFeign.uploads(multipartFile).getData();
}

//将图片转成pdf
public void imageToPdf(File[] imageFiles, String pdfPath) throws Exception {
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
OutputStream os = Files.newOutputStream(Paths.get(pdfPath));
PdfWriter.getInstance(document, os);
document.open();
for (File file : imageFiles) {
if (file.isFile() && FileUtil.isImage(file)) {
try {
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(file.getAbsolutePath());
float width = image.getWidth();
float height = image.getHeight();
float space = 10f;
if (width > PageSize.A4.getWidth() - space || height > PageSize.A4.getHeight() - space) {
image.scaleToFit(PageSize.A4.getWidth() - space, PageSize.A4.getHeight() - space);
}
image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER);
//document.setMargins(50, 150, 50, 50);
//document.setPageSize(new com.itextpdf.text.Rectangle(width, height));
document.newPage();
document.add(image);
} catch (Exception e) {
logger.error("图片转换失败", e);
}
}
}
document.close();
os.close();
}


//将excel文件转成pdf
public String excelToPdf(String excelPath) throws Exception {
String pdfPath = "C:/school/copy" + excelPath.substring(excelPath.lastIndexOf("/")-11,excelPath.lastIndexOf("/")+1);
pdfPath = FileUtil.getNewFileFullPath(excelPath, pdfPath, "pdf");
File file = new File(pdfPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}


InputStream is = CommonTool.getInputStreamByUrl("http://192.168.0.65"+excelPath);
try (Workbook workbook = WorkbookFactory.create(is)) {
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
FileOutputStream os = new FileOutputStream(pdfPath);
PdfWriter.getInstance(document, os);
document.open();
BaseFont chineseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font font = new Font(chineseFont, 12, Font.NORMAL);
DecimalFormat df = new DecimalFormat("#");
for (Sheet sheet : workbook) {
PdfPTable table = new PdfPTable(sheet.getRow(0).getPhysicalNumberOfCells());
for (Row row : sheet) {
for (Cell cell : row) {
if (cell.getCellType() == CellType.NUMERIC) {
PdfPCell pdfPCell = new PdfPCell(new Paragraph(df.format(cell.getNumericCellValue()), font));
table.addCell(pdfPCell);
} else {
PdfPCell pdfPCell = new PdfPCell(new Paragraph(cell.toString(), font));
table.addCell(pdfPCell);
}
}
}
table.setHeaderRows(1);
document.add(table);
}

document.close();
os.close();
is.close();
}

// 跨服务器传输(67->65)
Tool tool = new Tool();
MultipartFile multipartFile = tool.getMultipartFile(new File(pdfPath));
return feign.BaseFeign.BaseCommonFeign.uploads(multipartFile).getData();
}

//将excel文件转成pdf
// public void excelToPdf2(String excelPath, String pdfPath) throws DocumentException, IOException, InvalidFormatException {
// pdfPath = FileUtil.getNewFileFullPath(excelPath, pdfPath, "pdf");
// com.spire.xls.Workbook wb = new com.spire.xls.Workbook();
// wb.loadFromFile(excelPath);
// wb.saveToFile(pdfPath, com.spire.xls.FileFormat.PDF);
// }

//将html转成pdf
public void htmlToPdf(String htmlPath, String pdfPath) throws IOException {
FileOutputStream os = null;
try {
pdfPath = FileUtil.getNewFileFullPath(pdfPath, pdfPath, "pdf");
File file = new File(pdfPath); // 新建一个空白pdf文档
os = new FileOutputStream(file);
Document doc = new Document(htmlPath); // Address是将要被转化的word文档
doc.save(os, com.aspose.words.SaveFormat.PDF);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (os != null)
os.close();
}
}

//将ppt文件转成pdf
public String pptToPdf(String pptPath) throws Exception {
String pdfPath = "C:/school/copy" + pptPath.substring(pptPath.lastIndexOf("/")-11,pptPath.lastIndexOf("/")+1);
pdfPath = FileUtil.getNewFileFullPath(pptPath, pdfPath, "pdf");
File file = new File(pdfPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}

com.itextpdf.text.Document document = null;
FileOutputStream fileOutputStream = null;
InputStream inputStream = null;
PdfWriter pdfWriter = null;
try {
// inputStream = Files.newInputStream(Paths.get(pptPath));
inputStream = CommonTool.getInputStreamByUrl("http://192.168.0.65"+Paths.get(pptPath).toString());
SlideShow<?, ?> slideShow;
String ext = pptPath.substring(pptPath.lastIndexOf("."));
if (ext.equals(".pptx")) {
slideShow = new XMLSlideShow(inputStream);
} else {
slideShow = new HSLFSlideShow(inputStream);
}
Dimension dimension = slideShow.getPageSize();
fileOutputStream = new FileOutputStream(pdfPath);
//document = new com.itextpdf.text.Document();
document = new com.itextpdf.text.Document(new com.itextpdf.text.Rectangle((float) dimension.getWidth(), (float) dimension.getHeight()));
pdfWriter = PdfWriter.getInstance(document, fileOutputStream);
document.open();
for (Slide<?, ?> slide : slideShow.getSlides()) {
// 设置字体, 解决中文乱码
setPPTFont(slide, "宋体");
BufferedImage bufferedImage = new BufferedImage((int) dimension.getWidth(), (int) dimension.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2d = bufferedImage.createGraphics();
graphics2d.setPaint(Color.white);
graphics2d.setFont(new java.awt.Font("宋体", java.awt.Font.PLAIN, 12));
slide.draw(graphics2d);
graphics2d.dispose();
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(bufferedImage, null);
image.scaleToFit((float) dimension.getWidth(), (float) dimension.getHeight());
document.add(image);
document.newPage();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (document != null) {
document.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (pdfWriter != null) {
pdfWriter.close();
}
if(inputStream!=null){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

// 跨服务器传输(67->65)
Tool tool = new Tool();
MultipartFile multipartFile = tool.getMultipartFile(new File(pdfPath));
return feign.BaseFeign.BaseCommonFeign.uploads(multipartFile).getData();
}

private void setPPTFont(Slide<?, ?> slide, String fontFamily) {
// 设置字体, 解决中文乱码
for (Shape<?, ?> shape : slide.getShapes()) {
if (shape instanceof TextShape) {
TextShape textShape = (TextShape) shape;
List<TextParagraph> textParagraphs = textShape.getTextParagraphs();
for (TextParagraph textParagraph : textParagraphs) {
List<TextRun> textRuns = textParagraph.getTextRuns();
for (TextRun textRun : textRuns) {
textRun.setFontFamily(fontFamily);
}
}
}
}
}

/**
* 接口调用此方法--同一判断
* @return
*/
public String allToPdf(String path){
String url = "";

try {
String subStr = path.substring(path.lastIndexOf(".") + 1);
if("DOC".equalsIgnoreCase(subStr)||"DOCX".equalsIgnoreCase(subStr)){
url = wordToPdf(path);
}else if("XLS".equalsIgnoreCase(subStr)||"XLSX".equalsIgnoreCase(subStr)){
url = excelToPdf(path);
}else if("PPT".equalsIgnoreCase(subStr)||"PPTX".equalsIgnoreCase(subStr)){
url = pptToPdf(path);
}else if("GPG".equalsIgnoreCase(subStr)||"PNG".equalsIgnoreCase(subStr)){
url = imageToPdf(path);
}else if("TXT".equalsIgnoreCase(subStr)){
url = txtToPdf(path);
}
}catch (Exception e){
e.printStackTrace();
}

return url;
}
}
4、实际调用

image-20230828103811229


滑块验证码

点击查看
1、滑块拼图信息实体类

import lombok.Data;

import java.awt.image.BufferedImage;

/**
* 滑块拼图信息实体类
*
* @Author:李明光
* @Date:2023-8-28 9:13
*/

@Data
public class SliderPuzzleInfo {
/**
* 大图宽度
*/
private Integer bigWidth;

/**
* 大图高度
*/
private Integer bigHeight;

/**
* 大图转BASE64字符串
*/
private String bigImageBase64;

/**
* 大图
*/
private BufferedImage bigImage;

/**
* 随机坐标Y
*/
private Integer posY;
/**
* 随机坐标X
*/
private Integer posX;

/**
* 小图宽度
*/
private Integer smallWidth;
/**
* 小图高度
*/
private Integer smallHeight;

/**
* 小图转BASE64字符串
*/
private String smallImageBase64;

/**
* 小图
*/
private BufferedImage smallImage;

}


2、操作工具类

import com.example.java.dto.other.rules.SliderPuzzleInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Base64;
import java.util.Random;

/**
* 滑块验证码
*
* @Author:李明光
* @Date:2023-8-28 9:14
*/
public class SlidePuzzleUtil {

static Logger logger = LoggerFactory.getLogger(SlidePuzzleUtil.class);

// 大图宽度(原图裁剪拼图后的背景图)
private static final Integer bigWidth = 320;
// 大图高度
private static final Integer bigHeight = 160;
// 小图宽度(滑块拼图)
private static int smallWidth = 40;
// 小图高度
private static int smallHeight = 40;
// 小圆半径,即拼图上的凹凸轮廓半径
private static final Integer smallCircle = 8;
// 小圆距离点
private static int smallCircleR1 = smallCircle / 2;

public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\Administrator\\Downloads\\1.jpg");
SliderPuzzleInfo sliderPuzzleInfo = SlidePuzzleUtil.createImage(new FileInputStream(file));

if (sliderPuzzleInfo == null) {
System.out.println("图片验证码生成失败");
}

File file1 = new File("C:\\Users\\Administrator\\Desktop\\big.jpg");
File file2 = new File("C:\\Users\\Administrator\\Desktop\\small.jpg");
ImageIO.write(sliderPuzzleInfo.getBigImage(), "jpg", file1);
ImageIO.write(sliderPuzzleInfo.getSmallImage(), "jpg", file2);

}

/**
* 生成滑块拼图验证码
*
* @param input
* @return 返回null,表示生成滑块拼图验证码异常
*/
public static SliderPuzzleInfo createImage(InputStream input) {
SliderPuzzleInfo sliderPuzzleInfo = new SliderPuzzleInfo();
try {
// 1.获取原图对象
BufferedImage originalImage = ImageIO.read(input);
// 规范原图的大小
BufferedImage bigImage = resizeImage(originalImage, bigWidth, bigHeight, true);

// 2.随机生成离左上角的(X,Y)坐标,上限为 [bigWidth-smallWidth, bigHeight-smallHeight]。最好离大图左边远一点,上限不要紧挨着大图边界
Random random = new Random();
int randomX = random.nextInt(bigWidth - 4 * smallWidth - smallCircle) + 2 * smallWidth; // X范围:[2*smallWidth, bigWidth - 2*smallWidth - smallCircle)
int randomY = random.nextInt(bigHeight - smallHeight - 2 * smallCircle) + smallCircle; // Y范围:[smallCircle, bigHeight - smallHeight - smallCircle)
logger.info("原图大小:{} x {},大图大小:{} x {},随机生成的坐标:(X,Y)=({},{})", originalImage.getWidth(), originalImage.getHeight(), bigImage.getWidth(), bigImage.getHeight(),
randomX, randomY);

// 3.创建小图对象
BufferedImage smallImage = new BufferedImage(smallWidth, smallHeight, BufferedImage.TYPE_4BYTE_ABGR);

// 4.随机生成拼图轮廓数据
int[][] slideTemplateData = getSlideTemplateData(smallWidth, smallHeight, smallCircle, smallCircleR1);

// 5.从大图中裁剪拼图。抠原图,裁剪拼图
cutByTemplate(bigImage, smallImage, slideTemplateData, randomX, randomY);

sliderPuzzleInfo.setPosX(randomX);
sliderPuzzleInfo.setPosY(randomY);
sliderPuzzleInfo.setBigWidth(bigWidth);
sliderPuzzleInfo.setBigHeight(bigHeight);
sliderPuzzleInfo.setBigImage(bigImage);
sliderPuzzleInfo.setBigImageBase64(getImageBASE64(bigImage));
sliderPuzzleInfo.setSmallWidth(smallWidth);
sliderPuzzleInfo.setSmallHeight(smallHeight);
sliderPuzzleInfo.setSmallImage(smallImage);
sliderPuzzleInfo.setSmallImageBase64(getImageBASE64(smallImage));
} catch (Exception e) {
sliderPuzzleInfo = null;
logger.info("创建生成滑块拼图验证码异常,e=", e);
} finally {
return sliderPuzzleInfo;
}
}

/**
* 获取拼图图轮廓数据
* @param smallWidth
* @param smallHeight
* @param smallCircle
* @param r1
* @return 0和1,其中0表示没有颜色,1有颜色
*/
private static int[][] getSlideTemplateData(int smallWidth, int smallHeight, int smallCircle, int r1) {
// 拼图轮廓数据
int[][] data = new int[smallWidth][smallHeight];

//拼图去掉凹凸的白色距离
int xBlank = smallWidth - smallCircle - smallCircleR1; // 不写smallCircleR1时,凹凸为半圆
int yBlank = smallHeight - smallCircle - smallCircleR1;

// 圆的位置
int rxa = xBlank / 2;
int ryb = smallHeight - smallCircle;
double rPow = Math.pow(smallCircle, 2);

/**
* 计算需要的拼图轮廓(方块和凹凸),用二维数组来表示,二维数组有两张值,0和1,其中0表示没有颜色,1有颜色
* 圆的标准方程 (x-a)²+(y-b)²=r²,标识圆心(a,b),半径为r的圆
*/
for (int i = 0; i < smallWidth; i++) {
for (int j = 0; j < smallHeight; j++) {
// 圆在拼图下方内
double topR = Math.pow(i - rxa, 2) + Math.pow(j - 2, 2);
// 圆在拼图下方外
double downR = Math.pow(i - rxa, 2) + Math.pow(j - ryb, 2);
// 圆在拼图左侧内 || (i <= xBlank && leftR <= rPow)
//double leftR = Math.pow(i - 2, 2) + Math.pow(j - rxa, 2);
// 圆在拼图右侧外
double rightR = Math.pow(i - ryb, 2) + Math.pow(j - rxa, 2);
if ((j <= yBlank && topR <= rPow) || (j >= yBlank && downR >= rPow)
|| (i >= xBlank && rightR >= rPow)) {
data[i][j] = 0;
} else {
data[i][j] = 1;
}
}
}
return data;
}


/**
* 裁剪拼图
* @param bigImage - 原图规范大小之后的大图
* @param smallImage - 小图
* @param slideTemplateData - 拼图轮廓数据
* @param x - 坐标x
* @param y - 坐标y
*/
private static void cutByTemplate(BufferedImage bigImage, BufferedImage smallImage, int[][] slideTemplateData, int x, int y) {
int[][] martrix = new int[3][3];
int[] values = new int[9];
//拼图去掉凹凸的白色距离
int xBlank = smallWidth - smallCircle - smallCircleR1; // 不写smallCircleR1时,凹凸为半圆
int yBlank = smallHeight - smallCircle - smallCircleR1;

// 创建shape区域,即原图抠图区域模糊和抠出小图
/**
* 遍历小图轮廓数据,创建shape区域。即原图抠图处模糊和抠出小图
*/
for (int i = 0; i < smallImage.getWidth(); i++) {
for (int j = 0; j < smallImage.getHeight(); j++) {
// 获取大图中对应位置变色
//logger.info("随机生成的坐标:(X,Y)=({},{}),(i,j=({},{}),获取原图大小:{} x {}", x, y, i, j, x + i, y + j);
int rgb_ori = bigImage.getRGB(x + i, y + j);

//0和1,其中0表示没有颜色,1有颜色
int rgb = slideTemplateData[i][j];
if (rgb == 1) {
// 设置小图中对应位置变色
smallImage.setRGB(i, j, rgb_ori);

// 大图抠图区域高斯模糊
readPixel(bigImage, x + i, y + j, values);
fillMatrix(martrix, values);
bigImage.setRGB(x + i, y + j, avgMatrix(martrix));

//边框颜色
Color white = new Color(230,230,230);
Color black = new Color(20,20,20);
//左侧边界,加重高亮阴暗
if (j < yBlank) {
bigImage.setRGB(x, y + j, black.getRGB());
//smallImage.setRGB(0, j, white.getRGB());
}
} else {
// 这里把背景设为透明
smallImage.setRGB(i, j, rgb_ori & 0x00ffffff);
}
}
}
}

/**
* 图片转BASE64
*
* @param image
* @return
* @throws IOException
*/
public static String getImageBASE64(BufferedImage image) throws IOException {
byte[] imagedata = null;
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ImageIO.write(image, "png", bao);
imagedata = bao.toByteArray();
String BASE64IMAGE = Base64.getEncoder().encodeToString(imagedata);
return BASE64IMAGE;
}

/**
* 改变图片大小
*
* @param image
* 原图
* @param width
* 目标宽度
* @param height
* 目标高度
* @return 目标图
*/
public static BufferedImage resizeImage(final Image image, int width, int height, boolean type) {
BufferedImage bufferedImage;
if (type) {
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
} else {
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
}

final Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.setComposite(AlphaComposite.Src);
// below three lines are for RenderingHints for better image quality at cost of
// higher processing time
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics2D.drawImage(image, 0, 0, width, height, null);
graphics2D.dispose();
return bufferedImage;
}


private static void readPixel(BufferedImage img, int x, int y, int[] pixels) {
int xStart = x - 1;
int yStart = y - 1;
int current = 0;
for (int i = xStart; i < 3 + xStart; i++) {
for (int j = yStart; j < 3 + yStart; j++) {
int tx = i;
if (tx < 0) {
tx = -tx;

} else if (tx >= img.getWidth()) {
tx = x;
}
int ty = j;
if (ty < 0) {
ty = -ty;
} else if (ty >= img.getHeight()) {
ty = y;
}
pixels[current++] = img.getRGB(tx, ty);

}
}

}

private static void fillMatrix(int[][] matrix, int[] values) {
int filled = 0;
for (int i = 0; i < matrix.length; i++) {
int[] x = matrix[i];
for (int j = 0; j < x.length; j++) {
x[j] = values[filled++];
}
}
}

private static int avgMatrix(int[][] matrix) {
int r = 0;
int g = 0;
int b = 0;
for (int i = 0; i < matrix.length; i++) {
int[] x = matrix[i];
for (int j = 0; j < x.length; j++) {
if (j == 1) {
continue;
}
Color c = new Color(x[j]);
r += c.getRed();
g += c.getGreen();
b += c.getBlue();
}
}
return new Color(r / 8, g / 8, b / 8).getRGB();
}

}


3、实际使用
/**
* 生成滑块拼图验证码
*
* @param index
* - 本地照片
*/
@RequestMapping(value = "/getImageCode.json", method = RequestMethod.GET)
@ResponseBody
public SliderPuzzleInfo getImageCode(int index, HttpServletRequest request) throws Exception {
int i = index <= 0 ? 1 : index;
File file = new File("D:/TempFiles/slide/slidebase" + i + ".png");
SliderPuzzleInfo sliderPuzzleInfo = SlidePuzzleUtil.createImage(new FileInputStream(file));
if (sliderPuzzleInfo == null) {
System.out.println("图片验证码生成失败");
return sliderPuzzleInfo;
}

File file1 = new File("D:/TempFiles/slide/demo2BigImage.png");
File file2 = new File("D:/TempFiles/slide/demo2SmallImage.png");
ImageIO.write(sliderPuzzleInfo.getBigImage(), "png", file1);
ImageIO.write(sliderPuzzleInfo.getSmallImage(), "png", file2);

HttpSession session = request.getSession();
// 保存到Redis,这里临时存
session.setAttribute("posX", sliderPuzzleInfo.getPosX());
sliderPuzzleInfo.setBigImage(null);
sliderPuzzleInfo.setSmallImage(null);
return sliderPuzzleInfo;
}

/**
* 校验滑块拼图验证码
*
* @param movePosX
* 移动距离
*/
@ResponseBody
@RequestMapping(value = "/verifyImageCode.json", method = RequestMethod.GET)
public Map<String, Object> verifyImageCode(@RequestParam(value = "movePosX") Integer movePosX, HttpServletRequest request) {
Map<String, Object> resultMap = new HashMap<>();
HttpSession session = request.getSession();
try {
if (movePosX == null) {
resultMap.put("errcode", 1);
resultMap.put("errmsg", "参数缺失");
return resultMap;
}
Integer posX = (Integer) session.getAttribute("posX");
if (posX == null) {
resultMap.put("errcode", 1);
resultMap.put("errmsg", "验证过期,请重试");
return resultMap;
}
if (Math.abs(posX - movePosX) > 5) {
resultMap.put("errcode", 1);
resultMap.put("errmsg", "验证不通过");
} else {
resultMap.put("errcode", 0);
resultMap.put("errmsg", "验证通过");
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
session.removeAttribute("posX");
}
return resultMap;
}

4、效果

image-20230828104526264


@TableName注解的表名动态

点击查看
1、使用背景

一个实体类对应对个表,由于数据表数据量过大,所以有时候不得不对表进行横向拆分拆分为多张表

2、实体类
    @Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("armed_type")// 这里
public class ArmedTypeEntity implements Serializable {

private static final long serialVersionUID = 1L;

private String id;

/**
* 民兵类别名称
*/
@TableField("`name`")
private String name;

/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;

/**
* 创建人id
*/
@TableField("user_id")
private String userId;

/**
* 创建人姓名
*/
@TableField("user_name")
private String userName;

@TableField(exist = false)
private String tableName = "armed_type";// 默认值--这里
}

3、配置类

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.parsers.DynamicTableNameParser;
import com.baomidou.mybatisplus.extension.parsers.ITableNameHandler;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;

import java.util.Collections;
import java.util.HashMap;

/**
* @author miemie
* @since 2018-08-10
*/
@Configuration
@MapperScan("com.example.java.*")
public class MybatisPlusConfig {

// 存储表名
private static ThreadLocal<String> table = new ThreadLocal<>();


/**
* 分页插件注入
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser();
dynamicTableNameParser.setTableNameHandlerMap(new HashMap<String, ITableNameHandler>(2) {{
put("armed_type", (metaObject, sql, tableName) -> {
String dynamicTableName = getDynamicTableName(metaObject);
if (!"null".equals(dynamicTableName)){
return dynamicTableName;
}else{
return table.get();
}
});
}});
paginationInterceptor.setSqlParserList(Collections.singletonList(dynamicTableNameParser));

return paginationInterceptor;
}

/**
* 获取元数据里的动态表名
* @param metaObject 元数据对象
* @return 表名
*/
private String getDynamicTableName(MetaObject metaObject){
Object originalObject = metaObject.getOriginalObject();
JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(originalObject));
JSONObject boundSql = jsonObject.getJSONObject("boundSql");
JSONObject parameterObject = boundSql.getJSONObject("parameterObject");
return String.valueOf(parameterObject.get("tableName"));
}

// 设置表名
public static void setDynamicTableName(String tableName){
table.set(tableName);
}
}

4、操作表数据时
// 查询
@Override
public void typeList(TypeListDTO dto, BaseReturnDto<Page<TypeListVO>> data) {
// 靠着一句区分表
MybatisPlusConfig.setDynamicTableName("armed_type_1");// 这里需要根据业务判断,这里是写死了的

IPage<ArmedTypeEntity> iPage = armedTypeServerPlus.page(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>());
List<ArmedTypeEntity> list = iPage.getRecords();
ArrayList<TypeListVO> dtoList = new ArrayList<>();
for(ArmedTypeEntity entity:list){
TypeListVO vo = new TypeListVO();
BeanUtils.copyProperties(entity,vo);
dtoList.add(vo);
}

data.setData(new Page<>(dtoList,10,1,10));
}

// 添加-修改一样的
@Override
public void addType(AddTypeDTO dto, BaseReturnDto<String> data) {
ArmedTypeEntity entity = new ArmedTypeEntity();
entity.setId(IdUtil.simpleUUID());
entity.setName("aaa_"+System.currentTimeMillis());
entity.setUserId(System.currentTimeMillis()+"");
entity.setCreateTime(LocalDateTime.now());
entity.setUserName("bbbb");

// 下面是根据时间来区分表的
LocalDate now = LocalDate.now();
String day = "2023-08-31";
LocalDate date = LocalDate.parse(day, dateDF);
if(now.isBefore(date)){
entity.setTableName("armed_type_1");// 靠着一句区分表
}
armedTypeServerPlus.save(entity);
}

// 删除
@Override
public void deleteType(List<String> ids, BaseReturnDto<String> data) {
// 靠着一句区分表
MybatisPlusConfig.setDynamicTableName("armed_type");// 这里需要根据业务判断,这里是写死了的

armedTypeServerPlus.removeByIds(ids);
}


SpringBoot整合MongoDB

点击查看
1、maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.2.6.RELEASE</version> <!--2.2.6.RELEASE也是这里的springboot版本-->
</dependency>

2、配置
# spring.data.mongodb.uri=mongodb://用户名:密码@IP:端口/数据库?authSource=admin
spring.data.mongodb.uri=mongodb://root:admin@192.168.10.102:27017/demo?authSource=admin

#上面配置可写为以下配置
#spring.data.mongodb.database=demo
#spring.data.mongodb.host=192.168.10.102
#spring.data.mongodb.port=27017
#spring.data.mongodb.username=root
#spring.data.mongodb.password=admin
#spring.data.mongodb.authentication-database=admin

3、插入
@Autowired
private MongoTemplate mongoTemplate;
@GetMapping("/test1")
public void insertDemo(){
mongoTemplate.insert(new User(1314L,"zzj&mhz&wyq",new Date(),1));
}

4、查询
@Autowired
private MongoTemplate mongoTemplate;

@GetMapping("/test2")
public void queryDemo(){
System.out.println("=============查询所有====================");
List<User> all = mongoTemplate.findAll(User.class);
all.forEach(System.out::println);//方法引用
System.out.println();

System.out.println("===============根据id查询=======================");
User user = mongoTemplate.findById(1314, User.class);
System.out.println(user);
System.out.println();

System.out.println("===============条件查询=======================");
//regex传正则表达式 查询sex为1并且name中包含zzj的用户
String name="zzj";
Pattern pattern = Pattern.compile(String.format("%s%s%s", "^.*", name, ".*$"),Pattern.CASE_INSENSITIVE);
Query query = new Query(Criteria.where("sex").is(1).and("name").regex(pattern));
List<User> users = mongoTemplate.find(query, User.class);
users.forEach(System.out::println);
System.out.println();

System.out.println("===============分页查询=======================");
int pageSize=2,currentPage=1;
long count = mongoTemplate.count(new Query(), User.class);
List<User> userList = mongoTemplate.find(new Query().skip((currentPage - 1) * pageSize).limit(pageSize), User.class);
System.out.println("记录数 = "+count);
userList.forEach(System.out::println);
}

5、修改
@Autowired
private MongoTemplate mongoTemplate;

@GetMapping("/test3")
public void updateDemo(){
Query query = new Query(Criteria.where("_id").is(1314));
Update update=new Update();
update.set("name","wyq&mhz&zzj&zdn");
mongoTemplate.upsert(query,update,User.class);
}

6、删除
@Autowired
private MongoTemplate mongoTemplate;

@GetMapping("/test4")
public void deleteDemo(){
Query query = new Query(Criteria.where("_id").is(6666));
mongoTemplate.remove(query,User.class);
}


SpringBoot整合redis

点击查看
1、maven依赖
<!-- 集成redis依赖  -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- redis连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2、配置文件
spring:
redis:
host: 10.255.144.111
port: 6379
password: 123456
database: 1
lettuce:
pool:
max-idle: 16
max-active: 32
min-idle: 8
3、配置类
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(factory);

StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

redisTemplate.setKeySerializer(stringRedisSerializer); // key的序列化类型

Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 方法过期,改为下面代码
// objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value的序列化类型
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
4、封装的操作工具类
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
* @className: RedisUtil
* @description:
* @author: sh.Liu
* @date: 2022-03-09 14:07
*/
@Component
public class RedisUtil {

@Autowired
private RedisTemplate redisTemplate;
/**
* 给一个指定的 key 值附加过期时间
*
* @param key
* @param time
* @return
*/
public boolean expire(String key, long time) {
return redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
/**
* 根据key 获取过期时间
*
* @param key
* @return
*/
public long getTime(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 根据key 获取过期时间
*
* @param key
* @return
*/
public boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
/**
* 移除指定key 的过期时间
*
* @param key
* @return
*/
public boolean persist(String key) {
return redisTemplate.boundValueOps(key).persist();
}

//- - - - - - - - - - - - - - - - - - - - - String类型 - - - - - - - - - - - - - - - - - - - -

/**
* 根据key获取值
*
* @param key 键
* @return
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}

/**
* 将值放入缓存
*
* @param key 键
* @param value 值
* @return true成功 false 失败
*/
public void set(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}

/**
* 将值放入缓存并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) -1为无期限
* @return true成功 false 失败
*/
public void set(String key, String value, long time) {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
redisTemplate.opsForValue().set(key, value);
}
}

/**
* 批量添加 key (重复的键会覆盖)
*
* @param keyAndValue
*/
public void batchSet(Map<String, String> keyAndValue) {
redisTemplate.opsForValue().multiSet(keyAndValue);
}

/**
* 批量添加 key-value 只有在键不存在时,才添加
* map 中只要有一个key存在,则全部不添加
*
* @param keyAndValue
*/
public void batchSetIfAbsent(Map<String, String> keyAndValue) {
redisTemplate.opsForValue().multiSetIfAbsent(keyAndValue);
}

/**
* 对一个 key-value 的值进行加减操作,
* 如果该 key 不存在 将创建一个key 并赋值该 number
* 如果 key 存在,但 value 不是长整型 ,将报错
*
* @param key
* @param number
*/
public Long increment(String key, long number) {
return redisTemplate.opsForValue().increment(key, number);
}

/**
* 对一个 key-value 的值进行加减操作,
* 如果该 key 不存在 将创建一个key 并赋值该 number
* 如果 key 存在,但 value 不是 纯数字 ,将报错
*
* @param key
* @param number
*/
public Double increment(String key, double number) {
return redisTemplate.opsForValue().increment(key, number);
}

//- - - - - - - - - - - - - - - - - - - - - set类型 - - - - - - - - - - - - - - - - - - - -

/**
* 将数据放入set缓存
*
* @param key 键
* @return
*/
public void sSet(String key, String value) {
redisTemplate.opsForSet().add(key, value);
}

/**
* 获取变量中的值
*
* @param key 键
* @return
*/
public Set<Object> members(String key) {
return redisTemplate.opsForSet().members(key);
}

/**
* 随机获取变量中指定个数的元素
*
* @param key 键
* @param count 值
* @return
*/
public void randomMembers(String key, long count) {
redisTemplate.opsForSet().randomMembers(key, count);
}

/**
* 随机获取变量中的元素
*
* @param key 键
* @return
*/
public Object randomMember(String key) {
return redisTemplate.opsForSet().randomMember(key);
}

/**
* 弹出变量中的元素
*
* @param key 键
* @return
*/
public Object pop(String key) {
return redisTemplate.opsForSet().pop("setValue");
}

/**
* 获取变量中值的长度
*
* @param key 键
* @return
*/
public long size(String key) {
return redisTemplate.opsForSet().size(key);
}

/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
return redisTemplate.opsForSet().isMember(key, value);
}

/**
* 检查给定的元素是否在变量中。
*
* @param key 键
* @param obj 元素对象
* @return
*/
public boolean isMember(String key, Object obj) {
return redisTemplate.opsForSet().isMember(key, obj);
}

/**
* 转移变量的元素值到目的变量。
*
* @param key 键
* @param value 元素对象
* @param destKey 元素对象
* @return
*/
public boolean move(String key, String value, String destKey) {
return redisTemplate.opsForSet().move(key, value, destKey);
}

/**
* 批量移除set缓存中元素
*
* @param key 键
* @param values 值
* @return
*/
public void remove(String key, Object... values) {
redisTemplate.opsForSet().remove(key, values);
}

/**
* 通过给定的key求2个set变量的差值
*
* @param key 键
* @param destKey 键
* @return
*/
public Set<Set> difference(String key, String destKey) {
return redisTemplate.opsForSet().difference(key, destKey);
}


//- - - - - - - - - - - - - - - - - - - - - hash类型 - - - - - - - - - - - - - - - - - - - -

/**
* 加入缓存
*
* @param key 键
* @param map 键
* @return
*/
public void add(String key, Map<String, String> map) {
redisTemplate.opsForHash().putAll(key, map);
}

/**
* 获取 key 下的 所有 hashkey 和 value
*
* @param key 键
* @return
*/
public Map<Object, Object> getHashEntries(String key) {
return redisTemplate.opsForHash().entries(key);
}

/**
* 验证指定 key 下 有没有指定的 hashkey
*
* @param key
* @param hashKey
* @return
*/
public boolean hashKey(String key, String hashKey) {
return redisTemplate.opsForHash().hasKey(key, hashKey);
}

/**
* 获取指定key的值string
*
* @param key 键
* @param key2 键
* @return
*/
public String getMapString(String key, String key2) {
return redisTemplate.opsForHash().get("map1", "key1").toString();
}

/**
* 获取指定的值Int
*
* @param key 键
* @param key2 键
* @return
*/
public Integer getMapInt(String key, String key2) {
return (Integer) redisTemplate.opsForHash().get("map1", "key1");
}

/**
* 弹出元素并删除
*
* @param key 键
* @return
*/
public String popValue(String key) {
return redisTemplate.opsForSet().pop(key).toString();
}

/**
* 删除指定 hash 的 HashKey
*
* @param key
* @param hashKeys
* @return 删除成功的 数量
*/
public Long delete(String key, String... hashKeys) {
return redisTemplate.opsForHash().delete(key, hashKeys);
}

/**
* 给指定 hash 的 hashkey 做增减操作
*
* @param key
* @param hashKey
* @param number
* @return
*/
public Long increment(String key, String hashKey, long number) {
return redisTemplate.opsForHash().increment(key, hashKey, number);
}

/**
* 给指定 hash 的 hashkey 做增减操作
*
* @param key
* @param hashKey
* @param number
* @return
*/
public Double increment(String key, String hashKey, Double number) {
return redisTemplate.opsForHash().increment(key, hashKey, number);
}

/**
* 获取 key 下的 所有 hashkey 字段
*
* @param key
* @return
*/
public Set<Object> hashKeys(String key) {
return redisTemplate.opsForHash().keys(key);
}

/**
* 获取指定 hash 下面的 键值对 数量
*
* @param key
* @return
*/
public Long hashSize(String key) {
return redisTemplate.opsForHash().size(key);
}

//- - - - - - - - - - - - - - - - - - - - - list类型 - - - - - - - - - - - - - - - - - - - -

/**
* 在变量左边添加元素值
*
* @param key
* @param value
* @return
*/
public void leftPush(String key, Object value) {
redisTemplate.opsForList().leftPush(key, value);
}

/**
* 获取集合指定位置的值。
*
* @param key
* @param index
* @return
*/
public Object index(String key, long index) {
return redisTemplate.opsForList().index("list", 1);
}

/**
* 获取指定区间的值。
*
* @param key
* @param start
* @param end
* @return
*/
public List<Object> range(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}

/**
* 把最后一个参数值放到指定集合的第一个出现中间参数的前面,
* 如果中间参数值存在的话。
*
* @param key
* @param pivot
* @param value
* @return
*/
public void leftPush(String key, String pivot, String value) {
redisTemplate.opsForList().leftPush(key, pivot, value);
}

/**
* 向左边批量添加参数元素。
*
* @param key
* @param values
* @return
*/
public void leftPushAll(String key, String... values) {
// redisTemplate.opsForList().leftPushAll(key,"w","x","y");
redisTemplate.opsForList().leftPushAll(key, values);
}

/**
* 向集合最右边添加元素。
*
* @param key
* @param value
* @return
*/
public void leftPushAll(String key, String value) {
redisTemplate.opsForList().rightPush(key, value);
}

/**
* 向左边批量添加参数元素。
*
* @param key
* @param values
* @return
*/
public void rightPushAll(String key, String... values) {
//redisTemplate.opsForList().leftPushAll(key,"w","x","y");
redisTemplate.opsForList().rightPushAll(key, values);
}

/**
* 向已存在的集合中添加元素。
*
* @param key
* @param value
* @return
*/
public void rightPushIfPresent(String key, Object value) {
redisTemplate.opsForList().rightPushIfPresent(key, value);
}

/**
* 向已存在的集合中添加元素。
*
* @param key
* @return
*/
public long listLength(String key) {
return redisTemplate.opsForList().size(key);
}

/**
* 移除集合中的左边第一个元素。
*
* @param key
* @return
*/
public void leftPop(String key) {
redisTemplate.opsForList().leftPop(key);
}

/**
* 移除集合中左边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
*
* @param key
* @return
*/
public void leftPop(String key, long timeout, TimeUnit unit) {
redisTemplate.opsForList().leftPop(key, timeout, unit);
}

/**
* 移除集合中右边的元素。
*
* @param key
* @return
*/
public void rightPop(String key) {
redisTemplate.opsForList().rightPop(key);
}

/**
* 移除集合中右边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
*
* @param key
* @return
*/
public void rightPop(String key, long timeout, TimeUnit unit) {
redisTemplate.opsForList().rightPop(key, timeout, unit);
}
}


Linux定时任务重启jar服务

点击查看
1、检查是否你的操作系统已经安装了crontab
rpm -qa | grep crontab

image-20231012143208907

如未安装,参考:https://blog.csdn.net/Mou_O/article/details/127049665

2、编写脚本文件
#! /bin/bash
export PATH=$PATH:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.322.b06-1.el7_9.x86_64/jre/bin/
cd /work/jar/equipment/
APP_NAME=equipment-0.0.1-SNAPSHOT.jar
pid=`ps -ef | grep $APP_NAME | grep -v grep | awk '{print $2}' `
kill -9 $pid
#启动服务
nohup java -jar $APP_NAME --spring.profiles.active=dev --baseImgUrl=http://172.19.100.253:6040 -Xms2g -Xmx2g -Xmn1g >/dev/null 2>&1 &
echo $(date +%F)":restart end *************" >> /opt/shFile/equipment/restartLog
3、添加启动命令到配置文件
crontab -e  #输入命令
20 6,12,18 * * * startup.sh #比如每天6:20,12:20,18:20启动

image-20231012143938029

4、重启crond,将修改生效
service crond restart


判断ip是否在指定ip段内

点击查看
/**
* 判断IP是否在指定IP段内
* ipRange IP段(以'-'分隔)
*
* @param ipRange
* @param ip
* @return boolean
*/
public boolean ipIsInRange(String ip, String ipRange) {
if (ipRange == null)
throw new NullPointerException("IP段不能为空!");
if (ip == null)
throw new NullPointerException("IP不能为空!");
ipRange = ipRange.trim();
ip = ip.trim();
final String REGX_IP = "((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
final String REGX_IPB = REGX_IP + "\\-" + REGX_IP;
if (!ipRange.matches(REGX_IPB) || !ip.matches(REGX_IP))
return false;
int idx = ipRange.indexOf('-');
String[] sips = ipRange.substring(0, idx).split("\\.");
String[] sipe = ipRange.substring(idx + 1).split("\\.");
String[] sipt = ip.split("\\.");
long ips = 0L, ipe = 0L, ipt = 0L;
for (int i = 0; i < 4; ++i) {
ips = ips << 8 | Integer.parseInt(sips[i]);
ipe = ipe << 8 | Integer.parseInt(sipe[i]);
ipt = ipt << 8 | Integer.parseInt(sipt[i]);
}
if (ips > ipe) {
long t = ips;
ips = ipe;
ipe = t;
}
return ips <= ipt && ipt <= ipe;
}


判断指定日期是否为节假日(包含周末)

点击查看
1、HolidayUtil 工具类

/**
* 判断今天是工作日/周末/节假日 工具类
* //0 上班 1周末 2节假日
*/
public class HolidayUtil {


static Map<String,List<String>> holiday =new HashMap<>();//假期
static Map<String,List<String>> extraWorkDay =new HashMap<>();//调休日

//判断是否为节假日
/**
*
* @param time 日期参数 格式‘yyyy-MM-dd’,不传参则默认当前日期
* @return
*/
public static String isWorkingDay(String time) throws ParseException {
Date parse = null;
//为空则返回当前时间
if (StringUtils.isNotBlank(time)){
SimpleDateFormat getYearFormat = new SimpleDateFormat("yyyy-MM-dd");
parse = getYearFormat.parse(time);
}else {
parse = new Date();
}
String newDate = new SimpleDateFormat("yyyy").format(parse);

//判断key是否有参数年份
if(!holiday.containsKey(newDate)){
String holiday = getYearHoliday(newDate);
if ("No!".equals(holiday)){
return "该年份未分配日期安排!";
}
}

//得到日期是星期几
Date date = DateUtil.formatStringToDate(time, false);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int weekday = DateUtil.getDayOfWeek(calendar);


//是否节假日
if(holiday.get(newDate).contains(time)){
return "2";
}else if(extraWorkDay.get(newDate).contains(time)){//是否为调休
return "0";
}else if(weekday == Calendar.SATURDAY || weekday == Calendar.FRIDAY){//是否为周末
return "1";
}else{
return "0";
}
}

/**
*
* @param date 日期参数 格式‘yyyy’,不传参则默认当前日期
* @return
*/
public static String getYearHoliday(String date) throws ParseException {

//获取免费api地址
String httpUrl="https://timor.tech/api/holiday/year/"+date;
BufferedReader reader = null;
String result = null;
StringBuffer sbf = new StringBuffer();

try {
URL url = new URL(httpUrl);
URLConnection connection = url.openConnection();
//connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
connection.setRequestProperty("User-Agent", "Mozilla/4.76");
//使用Get方式请求数据
//connection.setRequestMethod("GET");
//connection.connect();
InputStream is = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));

String strRead = null;
while ((strRead = reader.readLine()) != null) {
sbf.append(strRead);
sbf.append("\r\n");
}
reader.close();

//字符串转json
JSONObject json = JSON.parseObject(sbf.toString());
//根据holiday字段获取jsonObject内容
JSONObject holiday = json.getJSONObject("holiday");
if (holiday.size() == 0){
return "No!";
}
List hoList = new ArrayList<>();
List extraList = new ArrayList<>();
for (Map.Entry<String, Object> entry : holiday.entrySet()) {
String value = entry.getValue().toString();
JSONObject jsonObject = JSONObject.parseObject(value);
String hoBool = jsonObject.getString("holiday");
String extra = jsonObject.getString("date");
//判断不是假期后调休的班
if(hoBool.equals("true")){
hoList.add(extra);
HolidayUtil.holiday.put(date,hoList);
}else {
extraList.add(extra);
HolidayUtil.extraWorkDay.put(date,extraList);
}
}

} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}

2、DateUtil 工具类
/**
* 日期工具
*/
public class DateUtil {
/**
* 输出当天的时间,格式如:20151207
*
* @return
*/
public static String today() {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
return format.format(new Date());
}

/**
* 当前时间
* @return
*/
public static String currTime() {
SimpleDateFormat sdfDetail = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
return sdfDetail.format(date);
}

/**
* 当前年
* @return
*/
public static String currYear() {
SimpleDateFormat sdfDetail = new SimpleDateFormat("yyyy");
Date date = new Date();
return sdfDetail.format(date);
}

public static String format(Date date, String tpl) {
SimpleDateFormat format = new SimpleDateFormat(tpl);
return format.format(date);
}

/**
* 任意一天的开始时间
*
* @return date
*/
public static Date startOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date returnDate = calendar.getTime();
return returnDate;
}

/**
* 任意一天的结束时间
*
* @return date
*/
public static Date endOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
Date returnDate = calendar.getTime();
return returnDate;
}

/**
* 获取时间戳的开始时间
* @param timestamp
*/
public static Long startOfDayByTimestamp(Long timestamp) {
Date date = new Date(timestamp);
return startOfDay(date).getTime();
}

/**
* 获取时间戳的结束时间
* zg
* @param timestamp
*/
public static Long endOfDayByTimestamp(Long timestamp) {
Date date = new Date(timestamp);
return endOfDay(date).getTime();
}

/**
* 当天的开始时间
*
* @return
*/
public static Date startOfTodDay() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date date = calendar.getTime();
return date;
}

/**
* 当天的结束时间
*
* @return
*/
public static Date endOfTodDay() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
Date date = calendar.getTime();
return date;
}

/**
* 昨天的开始时间
*
* @return
*/
public static Date startOfyesterday() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.add(Calendar.DATE, -1);
calendar.set(Calendar.MILLISECOND, 0);
Date date = calendar.getTime();
return date;
}

/**
* 昨天的结束时间
*
* @return
*/
public static Date endOfyesterday() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
calendar.add(Calendar.DATE, -1);
Date date = calendar.getTime();
return date;
}

/**
* 功能:获取本周的开始时间 示例:2013-05-13 00:00:00
*/
public static Date startOfThisWeek() {// 当周开始时间
Calendar currentDate = Calendar.getInstance();
currentDate.setFirstDayOfWeek(Calendar.MONDAY);
currentDate.set(Calendar.HOUR_OF_DAY, 0);
currentDate.set(Calendar.MINUTE, 0);
currentDate.set(Calendar.SECOND, 0);
currentDate.set(Calendar.MILLISECOND, 0);
currentDate.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
Date date = currentDate.getTime();
return date;
}

/**
* 功能:获取String日期对应的时间戳
* format 格式自定
*
* @return
*/
public static Long formatStringToStamp(String base, String format) {
DateFormat df = new SimpleDateFormat(format);
Date baseTime;
Long stamp = null;
try {
baseTime = df.parse(base);
stamp = baseTime.getTime();
} catch (Exception e) {
return null;
}
return stamp;
}

/**
* 功能:获取String日期对应的时间
* isTotal = false ;yyyy-MM-dd格式限定
* isTotal = true ;yyyy-MM-dd hh-mm-ss格式限定
*/
public static Date formatStringToDate(String base, Boolean isTotal) {
String format = isTotal ? "yyyy-MM-dd hh-mm-ss" : "yyyy-MM-dd";
DateFormat df = new SimpleDateFormat(format);
Date baseTime;
try {
baseTime = df.parse(base);
} catch (Exception e) {
return null;
}
return baseTime;
}

/**
* 功能:获取本周的结束时间 示例:2013-05-19 23:59:59
*/
public static Date endOfThisWeek() {// 当周结束时间
Calendar currentDate = Calendar.getInstance();
currentDate.setFirstDayOfWeek(Calendar.MONDAY);
currentDate.set(Calendar.HOUR_OF_DAY, 23);
currentDate.set(Calendar.MINUTE, 59);
currentDate.set(Calendar.SECOND, 59);
currentDate.set(Calendar.MILLISECOND, 999);
currentDate.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
Date date = currentDate.getTime();
return date;
}

/**
* 功能:获取本月的开始时间
*/
public static Date startOfThisMonth() {// 当周开始时间
Calendar currentDate = Calendar.getInstance();
currentDate.set(Calendar.HOUR_OF_DAY, 0);
currentDate.set(Calendar.MINUTE, 0);
currentDate.set(Calendar.SECOND, 0);
currentDate.set(Calendar.MILLISECOND, 0);
currentDate.set(Calendar.DAY_OF_MONTH, 1);
Date date = currentDate.getTime();
return date;
}

public static Date endOfThisMonth() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
cal.add(Calendar.MONTH, 1);
cal.add(Calendar.DATE, -1);
Date date = cal.getTime();
return date;
}

/**
* 功能:获取上月的开始时间
*/
public static Date startOfLastMonth() {// 当周开始时间
Calendar currentDate = Calendar.getInstance();
currentDate.set(Calendar.HOUR_OF_DAY, 0);
currentDate.set(Calendar.MINUTE, 0);
currentDate.set(Calendar.SECOND, 0);
currentDate.set(Calendar.MILLISECOND, 0);
currentDate.set(Calendar.DAY_OF_MONTH, 1);
currentDate.add(Calendar.MONTH, -1);
Date date = currentDate.getTime();
return date;
}

/**
* 功能:获取上月的结束时间
*/
public static Date endOfLastMonth() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
cal.add(Calendar.DATE, -1);
Date date = cal.getTime();
return date;
}

private static final int[] DAY_OF_MONTH = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

public static final String[] DATE_FORMATS = new String[]{"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd",
"yyyy-MM", "yyyy-MM-dd HH:mm:ss.S", "yyyy年MM月dd日", "yyyy年MM月dd日 HH:mm", "yyyyMMdd", "yyyy年MM月dd日 HH:mm:ss",
"MM.dd"};

/**
* 将传入的日期转化为"yyyy-MM-dd"形式的字符串
*
* @param dt 日期
* @return 指定日期格式的字符串
*/
public static String formatDate(Date dt) {

return formatDate("yyyy-MM-dd", dt);
}

/**
* 将传入的日期转化为"yyyy-MM-dd HH:mm:ss"形式的字符串
*
* @param dt 日期
* @return 指定日期格式的字符串
*/
public static String formatDateYMDHMS(Date dt) {

return formatDate("yyyy-MM-dd HH:mm:ss", dt);
}

/**
* 将传入的日期转化为"yyyy-MM-dd HH:mm"形式的字符串
*
* @param dt 日期
* @return 指定日期格式的字符串
*/
public static String formatDateYMDHM(Date dt) {

return formatDate("yyyy-MM-dd HH:mm", dt);
}

/**
* 将传入的日期以指定格式转成字符串
*
* @param format
* @param dt
* @return
*/
public static String formatDate(String format, Date dt) {
if (dt == null) {
return "";
}
if (format.isEmpty()) {
format = "yyyy-MM-dd";
}

SimpleDateFormat fmt = new SimpleDateFormat(format);
return fmt.format(dt);
}

/**
* 将日期字符串转为日期
*
* @param dateStr 日期字符串
* @return
*/
public static Date parseDate(String dateStr) {

return parseDate(dateStr, DATE_FORMATS);
}

/**
* 将日期字符串转为指定格式的日期
*
* @param dateStr 日期字符串
* @param format 日期格式
* @return
*/
public static Date parseDate(String dateStr, String format) {

return parseDate(dateStr, new String[]{format});
}

private static Date parseDate(String dateStr, String[] parsePatterns) {

try {
return DateUtils.parseDate(dateStr, parsePatterns);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}

/**
* 获取今天的日期
*
* @return
*/
public static Date getToday() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);

return cal.getTime();
}

/**
* 得到传入日期n天后的日期,如果传入日期为null,则表示当前日期n天后的日期
*
* @param dt 日期
* @param days 可以为任何整数,负数表示前days天,正数表示后days天
* @return Date
*/
public static Date getAddDayDate(Date dt, int days) {
Calendar cal = Calendar.getInstance();
if (dt != null) {
cal.setTime(dt);
}
cal.add(Calendar.DAY_OF_MONTH, days);
return cal.getTime();
}

/**
* 得到当前日期几天后(plusDays>0)or 几天前(plusDays<0)的指定格式的字符串日期
*
* @param dt
* @param plusDays
* @param dateFormat
* @return
*/
public static String getAddDayDateFromToday(int plusDays, String dateFormat) {
Calendar cal = Calendar.getInstance();

cal.add(Calendar.DAY_OF_MONTH, plusDays);

return formatDate(dateFormat, cal.getTime());
}

/**
* 给定的时间再加上指定小时数,如果传入日期为null,能以当前时间计算
*
* @param dt
* @param hours
* @return
* @author Alex Zhang
*/
public static Date getAddHourDate(Date dt, int hours) {

if (dt == null)
dt = new Date(System.currentTimeMillis());
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
cal.add(Calendar.HOUR, hours);

return cal.getTime();
}

/**
* 给定的时间再加上指定分钟数
*
* @param dt
* @param minutes
* @return
*/
public static Date getAddMinuteDate(Date dt, int minutes) {
if (dt == null)
dt = new Date(System.currentTimeMillis());
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
cal.add(Calendar.MINUTE, minutes);

return cal.getTime();
}

/**
* 给定的时间再加上指定月份数
*
* @param dt
* @param months
* @return
*/
public static Date getAddMonthDate(Date dt, int months) {

if (dt == null)
dt = new Date(System.currentTimeMillis());
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
cal.add(Calendar.MONTH, months);

return cal.getTime();
}

/**
* 给定的时间再加上指定年
* @param dt
* @param year
* @return
*/
public static Date getAddYearDate(Date dt, int year) {

if (dt == null)
dt = new Date(System.currentTimeMillis());
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
cal.add(Calendar.YEAR, year);

return cal.getTime();
}

/**
* 获得某天的零点时刻0:0:0
*
* @param date 日期
* @return
*/
public static Date getDayBegin(Date date) {

if (date == null)
return null;
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}

/**
* 获得某天的截至时刻23:59:59
*
* @param date
* @return
*/
public static Date getDayEnd(Date date) {

if (date == null)
return null;
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
return cal.getTime();
}

/**
* 某月的起始时间,eg:param:2011-11-10 12:10:50.999, return:2011-11-1 00:00:00.000
*/
public static Date getMonthBeginTime(Date dt) {

if (dt == null)
dt = new Date(System.currentTimeMillis());
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}

/**
* 某月的截止时间,eg:param:2011-11-10 12:10:50.999, return:2011-11-30 23:59:59.999
*/
public static Date getMonthEndTime(Date dt) {

if (dt == null)
dt = new Date(System.currentTimeMillis());
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, -1);
return cal.getTime();
}

/**
* 获得传入日期的年\月\日,以整型数组方式返回
*
* @param dt
* @return int[]
*/
public static int[] getTimeArray(Date dt) {

if (dt == null)
dt = new Date(System.currentTimeMillis());
int[] timeArray = new int[3];
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
timeArray[0] = cal.get(Calendar.YEAR);
timeArray[1] = cal.get(Calendar.MONTH) + 1;
timeArray[2] = cal.get(Calendar.DAY_OF_MONTH);
return timeArray;
}

/**
* 获得传入日期的年\月\日\小时\分,以整型数组方式返回
*
* @param dt
* @return
*/
public static int[] timeArray(Date dt) {

if (dt == null)
dt = new Date(System.currentTimeMillis());
int[] timeArray = new int[5];
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
timeArray[0] = cal.get(Calendar.YEAR);
timeArray[1] = cal.get(Calendar.MONTH) + 1;
timeArray[2] = cal.get(Calendar.DAY_OF_MONTH);
timeArray[3] = cal.get(Calendar.HOUR_OF_DAY);
timeArray[4] = cal.get(Calendar.MINUTE);
return timeArray;
}

/**
* 根据年月日得到Date类型时间
*
* @param year
* @param month
* @param day
* @return Date
*/
public static Date getTime(Integer year, Integer month, Integer day) {

Calendar cal = Calendar.getInstance();
if (year != null)
cal.set(Calendar.YEAR, year);
if (month != null)
cal.set(Calendar.MONTH, month - 1);
if (day != null)
cal.set(Calendar.DAY_OF_MONTH, day);
return cal.getTime();
}

/**
* @param parrern 格式化字符串 例如:yyyy-MM-dd
* @param str 时间字符串 例如:2007-08-01
* @return 出错返回null
* 通过格式化字符串得到时间
*/
public static Date getDateFromPattern(String parrern, String str) {
SimpleDateFormat fmt = new SimpleDateFormat(parrern);
try {
return fmt.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}

/**
* 计算两个日期间相隔的小时
*
* @param d1 日期1
* @param d2 日期2
* @return
*/
public static int getHourBetween(Date d1, Date d2) {

long m = d1.getTime();
long n = d2.getTime();
return (int) ((m - n) / 3600000);
}

/**
* 取得两个时间之间的天数,可能是负数(第二个时间的日期小于第一个时间的日期)。如果两个时间在同一天,则返回0
*
* @param d1 第一个时间
* @param d2 第二个时间
* @return
* @author Derek
* @version 1.0 2009-10-14
*/
public static int getDayBetween(Date d1, Date d2) {

Calendar c1 = Calendar.getInstance();
c1.setTime(d1);
Calendar c2 = Calendar.getInstance();
c2.setTime(d2);
return (int) ((c2.getTimeInMillis() - c1.getTimeInMillis()) / 86400000);
}

/**
* 计算两个日期间相隔的秒数
*
* @param d1 日期1
* @param d2 日期2
* @return
*/
public static long getSecondBetweem(Date d1, Date d2) {

return (d1.getTime() - d2.getTime()) / 1000;
}

/**
* 计算两个日期间相隔的月份数
*
* @param d1 日期1
* @param d2 日期2
* @return
*/
public static int getMonthBetween(Date d1, Date d2) {

Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.setTime(d1);
c2.setTime(d2);

return (c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR)) * 12 + (c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH));
}

/**
* 通过生日得到当前年龄
*
* @param birthDay 以字符串表示的生日
* @return 返回以以字符串表示的年龄, 最小为0
*/
public static String getAge(String birthDay) {

if (birthDay.startsWith("0000")) {
return "未知";
}
if (!birthDay.matches("[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}")) {
return "未知";
}
return getAge(parseDate(birthDay, "yyyy-MM-dd"));
}

/**
* 通过生日得到当前年龄
*
* @param birthDate 以日期表示的生日
* @return 返回以以字符串表示的年龄, 最小为0
*/
public static String getAge(Date birthDate) {

if (birthDate == null) {
return "未知";
}

Calendar cal = Calendar.getInstance();
if (cal.before(birthDate)) {
throw new IllegalArgumentException("The birthDay is before Now. It is unbelievable!");
}
int yearNow = cal.get(Calendar.YEAR);
int monthNow = cal.get(Calendar.MONTH);
int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
cal.setTime(birthDate);
int yearBirth = cal.get(Calendar.YEAR);
int monthBirth = cal.get(Calendar.MONTH);
int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
int age = yearNow - yearBirth;
if (monthNow <= monthBirth) {
if (monthNow == monthBirth) {
if (dayOfMonthNow < dayOfMonthBirth) {
age--;
} else {
}
} else {
age--;
}
} else {
}
return age + "";
}

@SuppressWarnings("deprecation")
public static int getIntAge(Date brithday) {

if (brithday != null) {
int dateMiss = Calendar.getInstance().getTime().getDate() - brithday.getDate();// 日差距
int monthMiss = Calendar.getInstance().getTime().getMonth() - brithday.getMonth();// 月份差距
int yearMiss = Calendar.getInstance().getTime().getYear() - brithday.getYear();// 年份差距
if (monthMiss > 0 || (monthMiss == 0 && dateMiss >= 0)) {
return yearMiss;
} else {
return yearMiss - 1;// 周岁少两岁,SO在去掉一年
}
}
return 0;
}

/**
* 根据周几的数字标记获得周几的汉字描述
*/
public static String getCnWeekDesc(int weekNum) {
String strWeek = "";
switch (weekNum) {
case 1:
strWeek = "周一";
break;
case 2:
strWeek = "周二";
break;
case 3:
strWeek = "周三";
break;
case 4:
strWeek = "周四";
break;
case 5:
strWeek = "周五";
break;
case 6:
strWeek = "周六";
break;
case 7:
strWeek = "周日";
break;
}
return strWeek;
}

/**
* 获得"上下午"标识
*
* @param date
* @return
*/
public static String getCnAMPM(Date date) {

Calendar cal = Calendar.getInstance();
cal.setTime(date);
if (Calendar.AM == cal.get(Calendar.AM_PM))
return "上午";
else
return "下午";

}

/**
* 判断两个日期是否相等
*
* @param d1 日期1
* @param d2 日期2
* @return
*/
public static boolean isTimeEquals(Date d1, Date d2) {

if (d1 == null || d2 == null)
return false;
return Math.abs(d1.getTime() - d2.getTime()) < 50;
}

/**
* 获取一个日期的年份
*
* @param date 日期
* @return
*/
public static int getYear(Date date) {

Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal.get(Calendar.YEAR);
}

/**
* 获取一个日期的月份
*
* @param date 日期
* @return
*/
public static int getMonthOfYear(Date date) {

Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal.get(Calendar.MONTH);
}

/**
* 获取一个日期的天数
*
* @param date
* @return
*/
public static int getDay(Date date) {

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);

return calendar.get(Calendar.DAY_OF_MONTH);
}

/**
* 获取一个日期的小时数
*
* @param date
* @return
*/
public static int getHour(Date date) {

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);

return calendar.get(Calendar.HOUR_OF_DAY);
}

/**
* 获取一个日期的分钟
*
* @param date 日期
* @return
*/
public static int getMinute(Date date) {

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);

return calendar.get(Calendar.MINUTE);
}

/**
* 获取一个日期的秒数
*
* @param date 日期
* @return
*/
public static int getSecond(Date date) {

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);

return calendar.get(Calendar.SECOND);
}

/**
* 获取一个月的最大天数
*
* @param year 年份
* @param month 月份
* @return
*/
public static int getMaxDayOfMonth(int year, int month) {

if (month == 1 && isLeapYear(year)) {
return 29;
}
return DAY_OF_MONTH[month];
}

/**
* 判断是否是润年
*
* @param year 年份
* @return
*/
public static boolean isLeapYear(int year) {

Calendar calendar = Calendar.getInstance();
return ((GregorianCalendar) calendar).isLeapYear(year);
}

/**
* 得到本周的起始时间
*
* @param currentDate
* @return
*/
public static Date getBeginDateofThisWeek(Date currentDate) {
Calendar current = Calendar.getInstance();
current.setTime(currentDate);
int dayOfWeek = current.get(Calendar.DAY_OF_WEEK);

if (dayOfWeek == 1) { // 如果是星期天,星期一则往前退6天
current.add(Calendar.DAY_OF_MONTH, -6);
} else {
current.add(Calendar.DAY_OF_MONTH, 2 - dayOfWeek);
}

current.set(Calendar.HOUR_OF_DAY, 0);
current.set(Calendar.MINUTE, 0);
current.set(Calendar.SECOND, 0);
current.set(Calendar.MILLISECOND, 0);

return current.getTime();
}

@SuppressWarnings("deprecation")
public static void main(String[] args) {

Date addYearDate = getAddYearDate(new Date(), 2);
System.out.println(formatDateYMDHMS(addYearDate));
}

/**
* 转化时间从指定格式日期为长整形
*
* @param format
* @param time
* @return
*/
public static Long convertDateStringToDateLong(String format, String time) throws ParseException {
if (time == null || time.trim().equals("")) {
return null;
}
SimpleDateFormat fmt = new SimpleDateFormat(format);
Date d = fmt.parse(time);
return d.getTime();
}

/**
* 获得指定格式日期
*
* @param date 日期
* @param format 指定格式
* @return
*/
public static Date getFormatDate(Date date, String format) {
if (null == date) {
return null;
}
if (null == format) {
return parseDate(formatDate("yyyy-MM-dd", date), "yyyy-MM-dd");
}
return parseDate(formatDate(format, date), format);
}

public static int getMinuteBetween(Date d1, Date d2) {
if (d1 == null || d2 == null)
return 0;
long m = d1.getTime();
long n = d2.getTime();
return (int) ((m - n) / 60000);
}

/**
* 计算创建时间到现在过去多久了
*
* @param createTime
* @return
*/
public static String getPastTime(Date createTime) {

String pastTime;
Date current = new Date();
int days = getDayBetween(current, createTime);
int hours = 0;
int mins = 0;
if (days > 0) {
pastTime = "1天前";
} else if ((hours = getHourBetween(current, createTime)) > 0) {
pastTime = hours + "小时前";
} else if ((mins = getMinuteBetween(current, createTime)) > 0) {
pastTime = mins + "分钟前";
} else {
long seconds = getSecondBetweem(current, createTime);
if (seconds > 5) {
pastTime = seconds + "秒前";
} else {
pastTime = "刚刚";
}
}
return pastTime;
}

/**
* 获取从今天开始未来一周的星期和日期的映射表 1-星期一:2014-05-12,2-星期二:2014-05-13.....
*
* @return
*/
public static Map<String, Date> getDateForWeekDay() {
Map<String, Date> weekDayDateMap = new HashMap<String, Date>();
Calendar calendar = Calendar.getInstance();
for (int i = 1; i <= 7; i++) {
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
if (dayOfWeek == 0) {
dayOfWeek = 7;
}
weekDayDateMap.put(dayOfWeek + "", calendar.getTime());
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
return weekDayDateMap;
}

/**
* 获得本日星期数,星期一:1,星期日:7 如果传入null则默认为本日
*
* @return
*/
public static int getDayOfWeek(Calendar calendar) {
int today;
if (calendar != null) {
today = calendar.get(Calendar.DAY_OF_WEEK);
} else {
today = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
}
if (today == 1)
return 7;
else
return today - 1;
}

/**
* 获取日期的中国式星期几(1-7分别代表周一至周日)
*
* @param date
* @return
*/
public static int getDayOfWeek(Date date) {
if (date == null) {
date = new Date();
}

Calendar cal = Calendar.getInstance();
cal.setTime(date);
return getDayOfWeek(cal);
}

/**
* 判断两个日期是否为同一天
*
* @param date1
* @param date2
* @return
*/
public static boolean isSameDate(Date date1, Date date2) {
if (date1 == null || date2 == null) {
return false;
}

Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.setTime(date1);
calendar2.setTime(date2);

if (calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR)
&& calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH)
&& calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH)) {
return true;
}

return false;
}

public static String formatDuration(long duration) {
float secondUnit = 1000;
String formatDuration = "";
DecimalFormat decimalFormat = new DecimalFormat(".00");

if (duration < secondUnit) {
formatDuration = duration + "(毫秒)";
} else if (duration < secondUnit * 60) {
formatDuration = decimalFormat.format(duration / secondUnit) + "(秒)";
} else if (duration < secondUnit * 3600) {
formatDuration = decimalFormat.format(duration / (secondUnit * 60)) + "(分钟)";
} else if (duration < secondUnit * 3600 * 60) {
formatDuration = decimalFormat.format(duration / (secondUnit * 3600)) + "(小时)";
} else {
formatDuration = decimalFormat.format(duration / (secondUnit * 3600 * 24)) + "(天)";
}

return formatDuration;
}

public static long getTodayBeginTime() {
return getDayBegin(new Date()).getTime();
}

public static long getTodayEndTime() {
return getDayEnd(new Date()).getTime();
}

/**
* 比较两个时间大小
*
* @param startTime
* @param endTime
* @return int
* @method compareDate()
*/
public static int compareDate(String startTime, String endTime) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = sdf.parse(startTime);
Date d2 = sdf.parse(endTime);
return d1.compareTo(d2);
}

/**
* 是否是一个日期格式
* @param time
* @param pattern
* @return
*/
public static boolean isTime(String time,String pattern) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
try {
sdf.setLenient(false);
sdf.parse(time);
} catch (ParseException e) {
return false;
}
return true;
}

/**
* 转换时间标准格式 yyyy-MM-dd HH:mm:ss
*/
public static final ThreadLocal<DateFormat> yMdHms = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};


/**
* 转换时间标准格式 yyyy-MM-dd
*/
public static final ThreadLocal<DateFormat> yMd = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};

/**
* 转换时间标准格式 yyyy-MM-dd HH:mm
*/
public static final ThreadLocal<DateFormat> yMdHm = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm");
}
};

/**
* 校验时间冲突
* @param dateA 2021-02-08 13:00~2021-02-08 13:00
* @param dateB 2021-02-08 13:00~2021-02-08 13:00
* @return 冲突返回true,不冲突返回false
*/
public static Boolean checkDateConflict(String dateA, String dateB) {
List<String> dateAList = new ArrayList<>(Arrays.asList(dateA.split("~")));
List<String> dateBList = new ArrayList<>(Arrays.asList(dateB.split("~")));
try {
Date dateA1 = DateUtil.yMdHm.get().parse(dateAList.get(0));
Date dateA2 = DateUtil.yMdHm.get().parse(dateAList.get(1));
Date dateB1 = DateUtil.yMdHm.get().parse(dateBList.get(0));
Date dateB2 = DateUtil.yMdHm.get().parse(dateBList.get(1));
//dateA开始时间大于dateB结束时间,不冲突
if (dateA1.compareTo(dateB2) >= 0) {
return false;
}
//dateA结束时间小于dateB开始时间,不冲突
if (dateA2.compareTo(dateB1) <= 0) {
return false;
}
} catch (ParseException e) {
throw new MessageException("时间格式异常");
}
return true;
}

/**
* 计算一个日期N天后的时间
* @param date
* @param n
* @return
* @throws ParseException
*/
public static String afterNDay(Date date,int n){
Calendar c=Calendar.getInstance();
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
c.setTime(date);
c.add(Calendar.DATE,n);
Date d2=c.getTime();
String s=df.format(d2);
return s;
}

/**
* 计算两个日期相差了多少天
* @param date1
* @param date2
* @return
*/
public static int differentDaysByMillisecond(Date date1,Date date2) {
int days = (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24));
return days;
}

/**
* 计算两个字符串日期(格式“yyyy-MM-dd”)相差了多少天
* @param date1
* @param date2
* @return
*/
public static int differentStrDaysByMillisecond(String date1,String date2) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date parse1 = null;
Date parse2 = null;
try {
parse1 = sdf.parse(date1);
parse2 = sdf.parse(date2);
} catch (ParseException e) {
e.printStackTrace();
}
int days = (int) ((parse1.getTime() - parse2.getTime()) / (1000*3600*24));
return days;
}

/**
* 获取本周周一 yyyy-MM-dd
* @return
*/
public static String getWeekBegin(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
//设置一个星期的第一天,按中国的习惯一个星期的第一天是星期一
cal.setFirstDayOfWeek(Calendar.MONDAY);
//获得当前日期是一个星期的第几天
int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
if(dayWeek==1){
dayWeek = 8;
}
// 根据日历的规则,给当前日期减去星期几与一个星期第一天的差值
cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - dayWeek);
Date mondayDate = cal.getTime();
String weekBegin = sdf.format(mondayDate);
return weekBegin;
}

/**
* 获取本周周一 yyyy-MM-dd
* @return
*/
public static String getWeekEnd(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
//设置一个星期的第一天,按中国的习惯一个星期的第一天是星期一
cal.setFirstDayOfWeek(Calendar.MONDAY);
//获得当前日期是一个星期的第几天
int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
if(dayWeek==1){
dayWeek = 8;
}
cal.add(Calendar.DATE, 4 +cal.getFirstDayOfWeek());
Date sundayDate = cal.getTime();
String weekEnd = sdf.format(sundayDate);
return weekEnd;
}

}


3、调用
public static void main(String[] args) {
String date = "2023-07-12";
String yearHoliday = HolidayUtil.isWorkingDay(date);
System.out.println(yearHoliday);
}


将网络图片存储在服务器,并返回访问地址

点击查看
/**
* 备份网络地址到本地服务器
* @param httpUrl 网络地址
* @return 返回服务器访问地址
*/
public String backupsImg(String httpUrl){
InputStream ips = null;
ByteArrayOutputStream bos = null;
String filename = RandomUtil.randomString(16)+".jpg";
String day = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
try {
// 创建URL对象,参数传递一个String类型的URL解析地址
URL url = new URL(httpUrl);
HttpURLConnection huc = (HttpURLConnection) url.openConnection();
// 从HTTP响应消息获取状态码
int code = huc.getResponseCode();
if (code == 200) {
// 获取输入流
ips = huc.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
bos = new ByteArrayOutputStream();
while ((len = ips.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.close();
uploadFileByBytes(bos.toByteArray(), filename,day);
}
} catch (Exception e) {
tool.info("读取文件失败:"+e+"---原地址:"+httpUrl);
e.printStackTrace();
} finally {
try {
if (ips != null)
ips.close();
if (bos != null)
bos.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
return "/demo/base/uploads/" + day +"/" +filename;
}

private void uploadFileByBytes(byte[] bytes, String fileName,String date) throws Exception {
for (int i = 0; i < bytes.length; i++) {
if (bytes[i] < 0) {
bytes[i] += 256;
}
}

String uploads_path;// 文件上传路径
String os = System.getProperty("os.name");
if (os.toLowerCase().startsWith("win")) {
uploads_path = uploads_win;
} else {
uploads_path = uploads_linux;
}
String realPath = uploads_path + date;


// 文件路径
String url = realPath+ "/" + fileName;
// 判断文件路径是否存在,如果没有则新建文件夹
File files = new File(realPath);
if (!files.exists()) {
files.mkdirs();
}
// 把文件写入到指定路径下
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(url, false));
out.write(bytes);
} catch (Exception e) {
tool.info("写出文件失败:"+e+"---写出地址:"+url);
e.printStackTrace();
} finally {
if (out != null)
out.close();
}
}


点击查看

持续更新中......