refactor: 根包由 com.bestsch.bschclassmanage 重命名为 com.yunhai.bschclassmanage

- git mv src/main/java/com/bestsch/bschclassmanage -> src/main/java/com/yunhai/bschclassmanage
- 255 个 Java 文件的 package/import 同步替换为 com.yunhai.bschclassmanage
- pom.xml 项目 groupId 设为 com.yunhai(与外部依赖 com.bestsch:bsch-* 无关,未改动)
- IDE 缓存 workspace.xml 路径同步更新(外部依赖坐标 com.bestsch:bsch-* 保持不动)
This commit is contained in:
Allen
2026-08-12 17:21:22 +08:00
parent 66cd0f1515
commit dc217ca7a9
258 changed files with 1082 additions and 1067 deletions
@@ -0,0 +1,40 @@
package com.yunhai.bschclassmanage.utils;
import java.util.Calendar;
public class CalendarUtils {
private static Calendar c = Calendar.getInstance();
public static int getYear(){
return c.get(Calendar.YEAR);
}
public static int getMonth(){
return c.get(Calendar.MONTH)+1; //获取月份
}
public static int getDay(){
return c.get(Calendar.DATE);
}
public static int get12Hour(){
return c.get(Calendar.HOUR);
}
public static int get24Hour(){
return c.get(Calendar.HOUR_OF_DAY);
}
public static int getMinute(){
return c.get(Calendar.MINUTE);
}
public static int getSecond(){
return c.get(Calendar.SECOND);
}
public static int getDayOfWeek(){
return c.get(Calendar.DAY_OF_WEEK);
}
}
@@ -0,0 +1,322 @@
package com.yunhai.bschclassmanage.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class ChinaDate {
// private static final Logger logger = LoggerFactory.getLogger(CalendarUtil.class);
// 计算阴历日期参照1900年到2049年
private final static int[] LUNAR_INFO = {
0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,
0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,
0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,
0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,
0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,
0x06ca0,0x0b550,0x15355,0x04da0,0x0a5d0,0x14573,0x052d0,0x0a9a8,0x0e950,0x06aa0,
0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,0x195a6,
0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,
0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,
0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,
0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,
0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0
};
// 允许输入的最小年份
private final static int MIN_YEAR = 1900;
// 允许输入的最大年份
private final static int MAX_YEAR = 2049;
// 当年是否有闰月
private static boolean isLeapYear;
// 阳历日期计算起点
private final static String START_DATE = "1900-01-30";
/**
* 计算阴历 {@code year}年闰哪个月 1-12 , 没闰传回 0
* @param year 阴历年
* @return (int)月份
*/
private static int getLeapMonth(int year) {
return (int) (LUNAR_INFO[year - 1900] & 0xf);
}
/**
* 计算阴历{@code year}年闰月多少天
* @param year 阴历年
* @return (int)天数
*/
private static int getLeapMonthDays(int year) {
if(getLeapMonth(year)!=0){
if((LUNAR_INFO[year - 1900] & 0xf0000)==0){
return 29;
}else {
return 30;
}
}else{
return 0;
}
}
/**
* 计算阴历{@code lunarYeay}年{@code month}月的天数
* @param lunarYeay 阴历年
* @param month 阴历月
* @return (int)该月天数
* @throws Exception
*/
private static int getMonthDays(int lunarYeay, int month) throws Exception {
if ((month > 31) || (month < 0)) {
throw(new Exception("月份有错!"));
}
// 0X0FFFF[0000 {1111 1111 1111} 1111]中间12位代表12个月,1为大月,0为小月
int bit = 1 << (16-month);
if(((LUNAR_INFO[lunarYeay - 1900] & 0x0FFFF)&bit)==0){
return 29;
}else {
return 30;
}
}
/**
* 计算阴历{@code year}年的总天数
* @param year 阴历年
* @return (int)总天数
*/
private static int getYearDays(int year) {
int sum = 29*12;
for(int i=0x8000;i>=0x8;i>>=1){
if((LUNAR_INFO[year-1900]&0xfff0&i)!=0){
sum++;
}
}
return sum+getLeapMonthDays(year);
}
/**
* 计算两个阳历日期相差的天数。计算不准确,已经废弃
* @param startDate 开始时间
* @param endDate 截至时间
* @return (int)天数
*/
@Deprecated
private static int daysBetween2(Date startDate, Date endDate) {
long between_days=(endDate.getTime()-startDate.getTime())/(1000*3600*24);
return Integer.parseInt(String.valueOf(between_days));
}
/**
* 计算两个阳历日期相差的天数。
* @param startDate 开始时间
* @param endDate 截至时间
* @return (int)天数
*/
private static int daysBetween(Date startDate, Date endDate) {
int days = 0;
//将转换的两个时间对象转换成Calendar对象
Calendar can1 = Calendar.getInstance();
can1.setTime(startDate);
Calendar can2 = Calendar.getInstance();
can2.setTime(endDate);
//拿出两个年份
int year1 = can1.get(Calendar.YEAR);
int year2 = can2.get(Calendar.YEAR);
//天数
Calendar can = null;
//如果can1 < can2
//减去小的时间在这一年已经过了的天数
//加上大的时间已过的天数
if(can1.before(can2)){
days -= can1.get(Calendar.DAY_OF_YEAR);
days += can2.get(Calendar.DAY_OF_YEAR);
can = can1;
}else{
days -= can2.get(Calendar.DAY_OF_YEAR);
days += can1.get(Calendar.DAY_OF_YEAR);
can = can2;
}
for (int i = 0; i < Math.abs(year2-year1); i++) {
//获取小的时间当前年的总天数
days += can.getActualMaximum(Calendar.DAY_OF_YEAR);
//再计算下一年。
can.add(Calendar.YEAR, 1);
}
return days;
}
/**
* 检查阴历日期是否合法
* @param lunarYear 阴历年
* @param lunarMonth 阴历月
* @param lunarDay 阴历日
* @param leapMonthFlag 闰月标志
* @throws Exception
*/
private static void checkLunarDate(int lunarYear, int lunarMonth, int lunarDay, boolean leapMonthFlag) throws Exception {
if ((lunarYear < MIN_YEAR) || (lunarYear > MAX_YEAR)) {
throw(new Exception("非法农历年份!"));
}
if ((lunarMonth < 1) || (lunarMonth > 12)) {
throw(new Exception("非法农历月份!"));
}
if ((lunarDay < 1) || (lunarDay > 30)) { // 中国的月最多30天
throw(new Exception("非法农历天数!"));
}
int leap = getLeapMonth(lunarYear);// 计算该年应该闰哪个月
if ((leapMonthFlag == true) && (lunarMonth != leap)) {
throw(new Exception("非法闰月!"));
}
}
/**
* 阴历转换为阳历
* @param lunarDate 阴历日期,格式YYYYMMDD
* @param leapMonthFlag 是否为闰月
* @return 阳历日期,格式:YYYYMMDD
* @throws Exception
*/
public static String lunarToSolar(String lunarDate, boolean leapMonthFlag) throws Exception{
int lunarYear = Integer.parseInt(lunarDate.substring(0, 4));
int lunarMonth = Integer.parseInt(lunarDate.substring(4, 6));
int lunarDay = Integer.parseInt(lunarDate.substring(6, 8));
checkLunarDate(lunarYear, lunarMonth, lunarDay, leapMonthFlag);
int offset = 0;
for (int i = MIN_YEAR; i < lunarYear; i++) {
int yearDaysCount = getYearDays(i); // 求阴历某年天数
offset += yearDaysCount;
}
//计算该年闰几月
int leapMonth = getLeapMonth(lunarYear);
if(leapMonthFlag & leapMonth != lunarMonth){
throw(new Exception("您输入的闰月标志有误!"));
}
//当年没有闰月或月份早于闰月或和闰月同名的月份
if(leapMonth==0|| (lunarMonth < leapMonth) || (lunarMonth==leapMonth && !leapMonthFlag)){
for (int i = 1; i < lunarMonth; i++) {
int tempMonthDaysCount = getMonthDays(lunarYear, i);
offset += tempMonthDaysCount;
}
// 检查日期是否大于最大天
if (lunarDay > getMonthDays(lunarYear, lunarMonth)) {
throw(new Exception("不合法的农历日期!"));
}
offset += lunarDay; // 加上当月的天数
}else{//当年有闰月,且月份晚于或等于闰月
for (int i = 1; i < lunarMonth; i++) {
int tempMonthDaysCount = getMonthDays(lunarYear, i);
offset += tempMonthDaysCount;
}
if (lunarMonth>leapMonth) {
int temp = getLeapMonthDays(lunarYear); // 计算闰月天数
offset += temp; // 加上闰月天数
if (lunarDay > getMonthDays(lunarYear, lunarMonth)) {
throw(new Exception("不合法的农历日期!"));
}
offset += lunarDay;
}else { // 如果需要计算的是闰月,则应首先加上与闰月对应的普通月的天数
// 计算月为闰月
int temp = getMonthDays(lunarYear, lunarMonth); // 计算非闰月天数
offset += temp;
if (lunarDay > getLeapMonthDays(lunarYear)) {
throw(new Exception("不合法的农历日期!"));
}
offset += lunarDay;
}
}
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date myDate = null;
myDate = formatter.parse(START_DATE);
Calendar c = Calendar.getInstance();
c.setTime(myDate);
c.add(Calendar.DATE, offset);
myDate = c.getTime();
return formatter.format(myDate);
}
/**
* 阳历日期转换为阴历日期
* @param solarDate 阳历日期,格式YYYYMMDD
* @return 阴历日期
* @throws Exception
*/
public static String solarToLunar(String solarDate, Boolean isFormat) throws Exception{
int i;
int temp = 0;
int lunarYear;
int lunarMonth; //农历月份
int lunarDay; //农历当月第几天
boolean leapMonthFlag =false;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date myDate = null;
Date startDate = null;
try {
myDate = formatter.parse(solarDate);
startDate = formatter.parse(START_DATE);
} catch (ParseException e) {
// e.printStackTrace();
}
int offset = daysBetween(startDate,myDate);
for (i = MIN_YEAR; i <= MAX_YEAR; i++){
temp = getYearDays(i); //求当年农历年天数
if (offset - temp < 1){
break;
}else{
offset -= temp;
}
}
lunarYear = i;
int leapMonth = getLeapMonth(lunarYear);//计算该年闰哪个月
//设定当年是否有闰月
if (leapMonth > 0){
isLeapYear = true;
}else{
isLeapYear = false;
}
for (i = 1; i<=12; i++) {
if(i==leapMonth+1 && isLeapYear){
temp = getLeapMonthDays(lunarYear);
isLeapYear = false;
leapMonthFlag = true;
i--;
}else{
temp = getMonthDays(lunarYear, i);
}
offset -= temp;
if(offset<=0){
break;
}
}
offset += temp;
lunarMonth = i;
lunarDay = offset;
if(isFormat)
return "阴历:"+lunarYear+"年"+(leapMonthFlag&(lunarMonth==leapMonth)?"闰":"")+lunarMonth+"月"+lunarDay+"日";
return "" + lunarYear + lunarMonth + lunarDay;
}
}
@@ -0,0 +1,19 @@
package com.yunhai.bschclassmanage.utils;
public class ConstantUtil {
/**
* redis过期时间
*/
public static final long EXPIRE_TIME=60*60*8;
/**
* redis前缀
*/
public static final String PREFIX_KEY="bsch.evaluate.";//redis前缀
/**
* 个人常用应用
*/
public static final String USEDAPP_KEY=PREFIX_KEY+"usedapp";
}
@@ -0,0 +1,47 @@
package com.yunhai.bschclassmanage.utils;
import org.apache.http.client.utils.DateUtils;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
public class DateRangeUtil {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
/**
* 根据类型获取日期范围
* @param type 1:今日 2:本周 3:本月
* @return Map containing "startDate" and "endDate" in yyyy-MM-dd format
*/
public static Map<String, Date> getDateRange(int type) {
Map<String, Date> result = new HashMap<>();
LocalDate today = LocalDate.now();
switch (type) {
case 1: // 今日
result.put("startDate", DateUtils.parseDate(today.format(FORMATTER)+" 00:00:00"));
result.put("endDate", DateUtils.parseDate(today.format(FORMATTER)+" 23:59:00"));
break;
case 2: // 本周
LocalDate monday = today.with(DayOfWeek.MONDAY);
LocalDate sunday = today.with(DayOfWeek.SUNDAY);
result.put("startDate", DateUtils.parseDate(monday.format(FORMATTER)+" 00:00:00"));
result.put("endDate",DateUtils.parseDate( sunday.format(FORMATTER)+" 23:59:00"));
break;
case 3: // 本月
LocalDate firstDay = today.withDayOfMonth(1);
LocalDate lastDay = today.withDayOfMonth(today.lengthOfMonth());
result.put("startDate", DateUtils.parseDate(firstDay.format(FORMATTER)+" 00:00:00"));
result.put("endDate", DateUtils.parseDate(lastDay.format(FORMATTER)+" 23:59:00"));
break;
default:
throw new IllegalArgumentException("不支持的type类型: " + type);
}
return result;
}
}
@@ -0,0 +1,374 @@
package com.yunhai.bschclassmanage.utils;
/**
* @ Description : 存储魔法值
* @ Author : cls
* @ CreateDate : 2020/2/1 9:24
* @ Company : bestsch
*/
public class DicUtil {
/**
* 超管id
*/
public static final Integer SUPER_ADMIN_ID = 100000;
public static final String UNKNOWN = "未知";
/**
* 一般hashMap初始化大小
*/
public static final int initialCapacity = 6;
/**
* 缓存时间,单位毫秒
*/
public static final long ONE_DAY = 1000 * 60 * 60 * 24;
public static final long TEN_MINUTES = 1000 * 60 * 10;
public static final long FIVE_MINUTES = 1000 * 60 * 5;
public static final long ONE_MINUTE = 1000 * 60;
public static final long HALF_MINUTE = 1000 * 30;
public static final long THREE_SECONDS = 1000 * 3;
/**
* 默认的学科类型 6 代表其他
*/
public static final String DEFAULT_RESOURCE_TYPE = "6";
/**
* 数据状态 1 有效
*/
public static final Integer STATUS_VALID = 1;
/**
* 数据状态 0 无效
*/
public static final Integer STATUS_INVALID = 0;
/**
* 审核状态 0 待审
*/
public static final Integer REVIEW_STATUS_TODO = 0;
/**
* 审核状态 1 通过
*/
public static final Integer REVIEW_STATUS_PASS = 1;
/**
* 审核状态 2 未通过
*/
public static final Integer REVIEW_STATUS_NOPASS = 2;
/**
* 用户类别 用户中心数据,2 组管理员
*/
// public static final Integer USER_TYPE_GROUP_MANAGER = 2;
/**
* 用户类别 用户中心数据,1 超级管理员
*/
public static final Integer USER_TYPE_SUPER_MANAGER = 1;
/**
* 目录所属来源 “我的文件”模块
*/
public static final Integer SOURCE_MY_FILES = 0;
/**
* 目录所属来源 “我的收藏”模块
*/
public static final Integer SOURCE_MY_COLLECTION = 1;
/**
* 目录所属来源 “教研组共享”模块
*/
public static final Integer SOURCE_GROUP = 2;
/**
* 目录所属来源 “草稿箱模块[学校]”
*/
public static final Integer SOURCE_DRAFTS_SYSTEM= 3;
/**
* 目录所属来源 “草稿箱模块[个人]”
*/
public static final Integer SOURCE_DRAFTS_USER= 4;
/**
* 根目录默认名称
*/
public static final String ROOT_FOLDER_NAME = "根目录";
/**
* 文印系统资源默认保存文件夹名称
*/
public static final String SEAL_FOLDER_NAME = "文印文档";
/**
* 外部系统资源默认保存文件夹名称
*/
public static final String DEFAULT_OUTER_FOLDER = "外部系统文档";
/**
* 默认头像
*/
public static final String DEFAULT_PIC = "http://base.bestsch.com/img/defprofilepic.png";
/**
* 排序 降序 0
*/
public static final Integer ORDER_DESC = 0;
/**
* 排序 升序 1
*/
public static final Integer ORDER_ASC = 1;
/**
* 垃圾来源,0文件夹-资源
*/
public static final Integer RUBBISH_SOURCE_FOLDER_TO_RESOURCE = 0;
/**
* 垃圾来源,1知识章节-资源
*/
public static final Integer RUBBISH_SOURCE_KNOWLEDGE_TO_RESOURCE = 1;
/**
* 垃圾来源,2文件夹
*/
public static final Integer RUBBISH_SOURCE_FOLDER = 2;
/**
* 垃圾来源,3 专题资源
*/
public static final Integer RUBBISH_SOURCE_SPECIAL = 3;
/**
* 文件类型 资源
*/
public static final Integer FILE_TYPE_RESOURCE = 0;
/**
* 文件类型 文件夹
*/
public static final Integer FILE_TYPE_FOLDER = 1;
/**
* memCached全局标签
*/
public static final String MEMCACHED_GLOBAL_TAG = "_ziyuanku_";
/**
* 区间参数 不包括
*/
public static final int SECTION_NO_INCLUDE = 0;
/**
* 区间参数 包括
*/
public static final int SECTION_INCLUDE = 1;
/**
* 51铃铛关键词
*/
public static final String LINGDANG_KEY = "51lingdang";
/**
* 学习中心路径头部
*/
public static final String LEARN_CENTER_HEADER = "http:///learn.bestsch.com";
/**
* 分享去向 folder
*/
public static final String WHEREABOUTS_FOLDER = "folder";
/**
* 分享去向 knowledge
*/
public static final String WHEREABOUTS_KNOWLEDGE = "knowledge";
/**
* 分享去向 special
*/
public static final String WHEREABOUTS_SPECIAL = "special";
/**
* 分享去向 node
*/
public static final String WHEREABOUTS_NODE = "node";
/**
* 错误消息,数据不存在
*/
public static final String ERROR_MSG_NOT_FOUND = "数据不存在,可能已被删除";
/**
* 错误消息,无操作权限
*/
public static final String ERROR_MSG_NO_POWER = "您无操作权限";
/**
* 错误信息,上传文件失败
*/
public static final String ERROR_MSG_IMPORT_WRONG = "上传失败,请稍后再试";
/**
* 错误信息,对应关系已存在
*/
public static final String ERROR_MSG_RELATION_EXISTED = "您选择的节点下已存在此文件";
/**
* 错误信息,无法对收藏来的文件夹进行操作
*/
public static final String ERROR_MSG_IS_OTHERS_FOLDER = "无法对收藏来的文件夹进行操作";
/**
* 错误消息,重复收藏
*/
public static final String ERROR_MSG_COLLECT_EXISTED = "此文件已在您的收藏夹里";
/**
* 错误消息,目标文件夹不是收藏模块里的文件夹
*/
public static final String ERROR_MSG_COLLECT_NOT_YOUR = "此文件夹不属于‘我的收藏’模块";
/**
* 错误消息,资源大小超出限制
*/
public static final String ERROR_MSG_TOO_BIG = "文件大小超出限制";
/**
* 错误消息,网盘空间超出限制
*/
public static final String ERROR_MSG_ZONE_BREAK = "网盘空间不足";
/**
* 错误消息,文件类型不符合要求
*/
public static final String ERROR_MSG_NO_EXT = "文件类型不符合要求";
/**
* 错误消息,名称冲突
*/
public static final String ERROR_NAME_EXISTED = "此位置已经包含同名文件";
/**
* 错误消息,不能跨层级移动
*/
public static final String ERROR_NO_LEVEL = "不支持跨层级移动";
/**
* 错误消息,资源不属于51
*/
public static final String ERROR_NOT_51LINGDANG = "此资源不属于51铃铛平台,请调用正确的接口";
/**
* 错误消息,资源属于51
*/
public static final String ERROR_ONLY_ON_OUTER = "此资源属于外部平台,请调用正确的接口";
/**
* 错误消息,文件不存在
*/
public static final String ERROR_FILE_NOT_FOUND = "文件不存在,可能已被删除";
/**
* 错误消息,角色已存在
*/
public static final String ERROR_ROLE_IS_EXISTED = "当前用户已拥有此角色";
/**
* 错误消息,身份未指定
*/
public static final String NO_CHOICE_ID = "请先指定您的身份";
/**
* 错误消息,身份中没有相关联的学校
*/
public static final String NO_SCHOOL_IN_ID = "您的身份不存在关联的学校信息";
/**
* 错误消息,超过层级上限
*/
//public static final String OVER_MAX_LEVEL = "层级超过上限,最多支持" + (MAX_LEVEL + 1) + "层";
/**
* 错误消息,没有资源录入权限,也就没有查看/编辑/移动资源的权限
*/
//public static final String NO_ZYLR_OF_NODE = "您缺少此节点的【" + ZYLR.getCnKey() + "】权限";
/**
* 错误消息,没有节点编辑权限
*/
//public static final String NO_JDBJ_OF_NODE = "您缺少此节点的【" + JDBJ.getCnKey() + "】权限";
/**
* 错误消息,没有根节点编辑权限
*/
//public static final String NO_JDBJ_OF_ROOT_NODE = "您缺少根节点的【" + JDBJ.getCnKey() + "】权限";
/**
* 错误消息,无权删除资源
*/
public static final String NO_POWER_TO_DEL_RESOURCE = "您无法删除此文件";
/**
* 错误消息,无权编辑资源
*/
public static final String NO_POWER_TO_MODIFY_RESOURCE = "您无法编辑/移动此文件";
/**
* 错误消息,无权移动到新节点
*/
//public static final String NO_POWER_TO_MOVE_RESOURCE = "您无法把文件移至新节点,因为" + NO_ZYLR_OF_NODE;
/**
* 错误消息,无权移动到根节点
*/
public static final String NO_MOVE_TO_ROOT = "您无法把文件移至根节点";
/**
* 错误消息,无法删除此节点
*/
public static final String NOT_DEL_NODE = "无法删除,请先移动或删除此节点下的文件";
/**
* 错误消息,没有可查看的节点
*/
public static final String NO_NODE_BY_WATCH = "您暂无可查看的节点";
/**
* 错误消息,未知的教材来源
*/
public static final String UNKNOWN_TEXTBOOK_SOURCE = "未知的教材来源";
/**
* 错误消息,无法对根节点进行操作
*/
public static final String CANT_OPERATE_FOR_ROOT = "无法对根节点进行操作";
/**
* 错误消息,未知的权限类型
*/
public static final String UNKNOWN_AUTHORITY_TYPE = "未知的权限类型";
/**
* 错误消息,无权编辑资源
*/
public static final String NO_STUDENT = "不是学生身份无法查看";
/**
* 错误消息,节点不存在
*/
public static final String NO_NODE = "节点不存在";
/**
* 错误消息,无权删除已分享的资源
*/
public static final String NO_TO_DEL_RESOURCE_OF_SHARE = "该文件已被分享,无法删除。若需删除,请先取消分享";
}
@@ -0,0 +1,56 @@
package com.yunhai.bschclassmanage.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import java.io.*;
@Slf4j
public class DownloadFileUtil {
public static final String separator = File.separator;
/**
* 下载样表
* @param filePath 文件上级目录
* @param fileName 文件名
* @param newName 下载的展示文件名
* @return 响应
*/
public static ResponseEntity<InputStreamResource> download(String filePath, String fileName, String newName) {
// String route = "static" + separator + "templates" + separator;
// String path = null;
ResponseEntity<InputStreamResource> response = null;
try {
// path = route + filePath + separator + fileName;
File file = new File(filePath);
System.out.println(file.exists());
// ClassPathResource classPathResource = new ClassPathResource(filePath);
InputStream inputStream = new FileInputStream(file);
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Content-Disposition",
"attachment; filename="
+ new String(newName.getBytes("gbk"), "iso8859-1"));
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
response = ResponseEntity.ok().headers(headers)
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(new InputStreamResource(inputStream));
} catch (FileNotFoundException e1) {
log.error("找不到指定的文件", e1);
} catch (IOException e) {
log.error("获取不到文件流", e);
}
return response;
}
}
@@ -0,0 +1,82 @@
package com.yunhai.bschclassmanage.utils;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.word.WordExportUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
public final class EasyPoiUtils {
private EasyPoiUtils() {}
/**
* 只能xls
* @param fileName
* @param response
* @param workbook
*/
public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
workbook.write(response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static<T> void defaultExport(List<T> dataList, Class<?> clz, String fileName, HttpServletResponse response, ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, clz, dataList);
if (workbook != null) {
downLoadExcel(fileName, response, workbook);
}
}
public static<T> void exportExcel(List<T> dataList, String title, String sheetName, Class<?> clz, String fileName, boolean isCreateHeader, HttpServletResponse response) {
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setCreateHeadRows(isCreateHeader);
defaultExport(dataList, clz, fileName, response, exportParams);
}
public static<T> void exportExcel(List<T> dataList, String title, String sheetName, Class<?> clz, String fileName, HttpServletResponse response) {
defaultExport(dataList, clz, fileName, response, new ExportParams(title, sheetName));
}
/**
* 导出word
*/
public static void exportWord(String fileName, Map<String, Object> map, HttpServletRequest request, HttpServletResponse response) {
try {
String userAgent = request.getHeader("user-agent").toLowerCase();
if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
fileName = URLEncoder.encode(fileName, "UTF-8");
} else {
fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
}
XWPFDocument doc = WordExportUtil.exportWord07(
"/Users/luona/Downloads/模版.docx", map);
// 设置强制下载不打开
response.setContentType("application/force-download");
// 设置文件名
response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
OutputStream out = response.getOutputStream();
doc.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,150 @@
package com.yunhai.bschclassmanage.utils;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @program: ResearchLearn
* @description: 枚举工具类
* @author: chenx
* @create: 2023-05-26 14:05
**/
public final class EnumUtil {
/**
* 枚举转List格式
*
* @param targetEnumClazz 目标枚举Clazz
*/
public static List<Map<String, Object>> toMapList(Class targetEnumClazz) {
//获取方法
Method[] methods = targetEnumClazz.getMethods();
Field[] fields = targetEnumClazz.getDeclaredFields();
List<Field> fieldList = new ArrayList();
for (Method method : methods) {
for (Field field : fields) {
if (method.getName().endsWith(StringUtils.capitalize(field.getName()))) {
fieldList.add(field);
}
}
}
List<Map<String, Object>> resultList = new ArrayList();
//获取值
Enum[] enums = (Enum[]) targetEnumClazz.getEnumConstants();
Object value = null;
try {
for (Enum e : enums) {
Map<String, Object> eMap = new HashMap();
String enumNameValue = e.name();
for (Field field : fieldList) {
// 对于private的属性,如果不解锁,那么将无法访问,会报错
field.setAccessible(true);
// 通过反射的字段获取实体中的值
value = field.get(e);
eMap.put(field.getName(), value);
}
eMap.put("enum",e);
resultList.add(eMap);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return resultList;
}
/**
* 通过枚举key获取对应的枚举值
*
* @param targetEnumClazz 目标枚举Clazz
* @param key 对应的枚举值
*/
public static String getValue(Class targetEnumClazz, String key) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
for (Map map : list) {
if (map.get("key").toString().equals(key)) {
return map.get("value").toString();
}
}
return "";
}
/**
* 通过枚举值获取对应的枚举key
*
* @param targetEnumClazz 目标枚举Clazz
* @param value 对应的枚举值
*/
public static String getKey(Class targetEnumClazz, String value) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
for (Map map : list) {
if (map.get("value").toString().equals(value)) {
return map.get("key").toString();
}
}
return "";
}
/**
* 通过枚举key获取对应的枚举
*
* @param targetEnumClazz 目标枚举Clazz
* @param key 对应的枚举值
*/
public static Object getEnumByKey(Class targetEnumClazz, String key) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
for (Map map : list) {
if (map.get("key").toString().equals(key)) {
return map.get("enum");
}
}
return null;
}
/**
* 是否存在此key
*
* @param targetEnumClazz 目标枚举Clazz
* @param key 对应的枚举值
*/
public static boolean isExistKey(Class targetEnumClazz,String key){
List<Map<String, Object>> list = toMapList(targetEnumClazz);
return list.stream().filter(x->x.get("key").equals(key)).count()>0;
}
/**
* 是否存在此value
*
* @param targetEnumClazz 目标枚举Clazz
* @param value 对应的枚举值
*/
public static boolean isExistValue(Class targetEnumClazz,String value){
List<Map<String, Object>> list = toMapList(targetEnumClazz);
return list.stream().filter(x->x.get("value").equals(value)).count()>0;
}
/**
* 是否存在此value
*
* @param keyName 自定义key
* @param valueName 自定义value
*/
public static List<Map<String, Object>> toMapList(Class targetEnumClazz,String keyName,String valueName) {
List<Map<String, Object>> list = toMapList(targetEnumClazz);
List result = new ArrayList();
for (Map map : list) {
Map newMap = new HashMap();
newMap.put(keyName, map.get("key"));
newMap.put(valueName, map.get("value"));
result.add(newMap);
}
return result;
}
}
@@ -0,0 +1,143 @@
package com.yunhai.bschclassmanage.utils;
import com.yunhai.platform.utils.exception.DException;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
public class HttpUtils {
static {
try {
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier
(
(urlHostName, session) -> true
);
} catch (Exception e) {
}
}
/**
* 跳过ssl证书
*
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
private static void trustAllHttpsCertificates()
throws NoSuchAlgorithmException, KeyManagementException {
TrustManager[] trustAllCerts = new TrustManager[1];
trustAllCerts[0] = (TrustManager) new TrustAllManager();
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
private static class TrustAllManager implements X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
}
public static String get(String aUrl,Integer timeout){
int respCode = 0;
HttpURLConnection conn = null;
String var3;
try {
conn = getHttpURLConnection(aUrl, "GET",timeout);
conn.setDoInput(true);
respCode = conn.getResponseCode();
if (respCode != 301) {
InputStream is = conn.getInputStream();
int contentLen = conn.getContentLength();
byte[] resultData = read(is, contentLen);
is.close();
String var6 = new String(resultData, "utf-8");
return var6;
}
var3 = get(conn.getHeaderField("Location"),timeout);
} catch (Exception var10) {
throw new DException("网络连接失败");
} finally {
close(conn);
}
return var3;
}
private static HttpURLConnection getHttpURLConnection(String uri, String method,int timeout) throws IOException {
URL url = new URL(uri);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod(method);
conn.setConnectTimeout(timeout);
conn.setReadTimeout(timeout);
return conn;
}
private static byte[] read(InputStream is, int contentLen) throws IOException {
if (contentLen <= 0) {
int BUF_SIZE = 102400;
byte[] buf = new byte[102400];
ByteBuffer byteBuffer = ByteBuffer.allocate(102400);
int readed;
do {
if (byteBuffer.position() + 102400 > byteBuffer.capacity()) {
byteBuffer = reallocByteBuffer(byteBuffer, byteBuffer.capacity() + 102400);
}
readed = is.read(buf, 0, 102400);
if (readed > 0) {
byteBuffer.put(buf, 0, readed);
}
} while(readed != -1);
byte[] data = new byte[byteBuffer.position()];
System.arraycopy(byteBuffer.array(), 0, data, 0, byteBuffer.position());
return data;
} else {
byte[] data = new byte[contentLen];
int readed;
for(int remain = contentLen; remain > 0; remain -= readed) {
readed = is.read(data, contentLen - remain, remain);
if (readed == -1) {
break;
}
}
return data;
}
}
private static ByteBuffer reallocByteBuffer(ByteBuffer buffer, int size) {
ByteBuffer newBuf = ByteBuffer.allocate(size);
newBuf.put(buffer.array(), 0, buffer.position());
return newBuf;
}
private static void close(HttpURLConnection conn) {
try {
if (conn == null) {
return;
}
conn.disconnect();
} catch (Exception var2) {
var2.printStackTrace();
}
}
}
@@ -0,0 +1,73 @@
package com.yunhai.bschclassmanage.utils;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.apache.http.client.utils.DateUtils;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @ Description : javaBean工具类
* @ Author : cls
* @ CreateDate : 2020/2/3 20:21
* @ Company : bestsch
*/
public class JavaBeanUtil {
/**
* bean转map
* @param obj
* @return
*/
public static Map<String, Object> beanToMap(Object obj) {
if (obj == null) {
return new HashMap<>();
}
Map<String, Object> map = new HashMap<String, Object>();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
// 过滤class属性
if (!key.equals("class")) {
//若属性被jsonignore注解修饰,则跳过转换
JsonIgnoreProperties jsonIgnore = property.getPropertyType().getAnnotation(JsonIgnoreProperties.class);
if(jsonIgnore != null){
continue;
}
// 得到property对应的getter方法
Method getter = property.getReadMethod();
Object value = getter.invoke(obj);
if(value != null && value.getClass().equals(Timestamp.class)){
JsonFormat jsonFormat = property.getPropertyType().getAnnotation(JsonFormat.class);
if(jsonFormat != null){
value = DateUtils.formatDate((Date)value,jsonFormat.pattern());
}else{
value = DateUtils.formatDate((Date)value);
}
}
if(null == value){
map.put(key,null);
}else{
map.put(key,value);
}
}
}
} catch (Exception e) {
}
return map;
}
public static Map<String,Object> beanToJsonMap(Object object){
return (Map<String, Object>) JSONObject.toJSON(object);
}
}
@@ -0,0 +1,47 @@
package com.yunhai.bschclassmanage.utils;
import java.util.List;
import java.util.Map;
import java.util.Comparator;
public class ListMapSortUtil {
// 针对Integer类型的排序
public static void sortByIntegerKey(List<Map> list, String key) {
list.sort(Comparator.comparing(map -> (Integer) map.get(key)));
}
// 针对Double类型的排序
public static void sortByDoubleKey(List<Map> list, String key) {
list.sort(Comparator.comparing(map -> (Double) map.get(key)));
}
// 更通用的方法,使用Number并转换为Double进行比较(适用于整数和浮点数)
public static void sortByNumberKey(List<Map> list, String key) {
list.sort(Comparator.comparing(map -> ((Number) map.get(key)).doubleValue()));
}
// 支持升序降序
public static void sortByIntegerKey(List<Map> list, String key, boolean ascending) {
Comparator<Map> comparator = Comparator.comparing(map -> (Integer) map.get(key));
if (!ascending) {
comparator = comparator.reversed();
}
list.sort(comparator);
}
// 支持null值处理,将null视为最小值
public static void sortByIntegerKeyWithNullsFirst(List<Map> list, String key) {
list.sort(Comparator.comparing(
map -> (Integer) map.get(key),
Comparator.nullsFirst(Comparator.naturalOrder())
));
}
// 更通用的方法,支持任意Comparable类型,包括String、Integer等
@SuppressWarnings("unchecked")
public static <T extends Comparable<T>> void sortByKey(List<Map> list, String key) {
list.sort(Comparator.comparing(map -> (T) map.get(key)));
}
}
@@ -0,0 +1,17 @@
package com.yunhai.bschclassmanage.utils;
public class LogContextHolder {
private static final ThreadLocal<String> LOG_DESCRIPTION = new ThreadLocal<>();
public static void setDescription(String desc) {
LOG_DESCRIPTION.set(desc);
}
public static String getDescription() {
return LOG_DESCRIPTION.get();
}
public static void clear() {
LOG_DESCRIPTION.remove();
}
}
@@ -0,0 +1,255 @@
package com.yunhai.bschclassmanage.utils;
import com.yunhai.bschclassmanage.model.vo.SelectIntVO;
import com.yunhai.bschclassmanage.model.vo.SelectStrVO;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 对象映射转换工具类,转换逻辑属性名完全匹配进行转换
*
* @Description:
* @Time: 2019-11-28 20:18
* @Author:
*/
public final class ModelMapperUtil {
public static final ModelMapper MODEL_MAPPER;
static {
MODEL_MAPPER = new ModelMapper();
// 完全类型匹配
//MODEL_MAPPER.getConfiguration().setFullTypeMatchingRequired(true);
// 设置属性匹配规则,设置为最严格匹配,必须属性名相同
MODEL_MAPPER.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
}
/**
* 禁止实列化该类
* @throws InstantiationException 不能实列化
*/
private ModelMapperUtil() throws InstantiationException {
throw new InstantiationException("Tool Class Cannot Be Created Instantiation !");
}
/**
* 将对象转换为指定class类型对象。
* @param source 源对象
* @param targetClass 转换目标类型
* @return 转换后对象
* @param <Target> 目标类型
*/
public static <Target> Target map(Object source, Class<Target> targetClass) {
return source == null ? null : MODEL_MAPPER.map(source, targetClass);
}
/**
* 将源对象中的属性转换到目标对象中,源对象与目标对象属性名相同的则转换
* @param source 源对象
* @param target 目标对象
*/
public static void map(Object source, Object target) {
if (source == null || target == null) {
return;
} else {
MODEL_MAPPER.map(source, target);
}
}
/**
* 将对象转换为指定class类型对象,并对转换后对象进行处理
* @param source 源对象
* @param targetClass 转换目标类型
* @param consumer 对转换后对象进行消费处理
* @return 转换后对象
* @param <Target> 目标类型
*/
public static <Target> Target map(Object source, Class<Target> targetClass, Consumer<Target> consumer) {
Target target = source == null ? null : MODEL_MAPPER.map(source, targetClass);
if (consumer != null) {
consumer.accept(target);
}
return target;
}
/**
* 将对象转换为指定class类型对象,并对转换后对象进行处理
* @param source 源对象
* @param targetClass 转换目标类型
* @param consumer 对转换后对象进行消费处理
* @return 转换后对象
* @param <Source> 源对象类型
* @param <Target> 目标类型
*/
public static <Source, Target> Target map(Source source, Class<Target> targetClass, BiConsumer<Source, Target> consumer) {
Target target = source == null ? null : MODEL_MAPPER.map(source, targetClass);
if (consumer != null) {
consumer.accept(source, target);
}
return target;
}
/**
* 将集合中的元素抓换为指定类型
* @param sourceList 源集合
* @param targetClass 转换目标类型
* @return 转换后的目标类型集合
* @param <TSource> 源类型
* @param <Target> 目标类型
*/
public static <TSource, Target> List<Target> mapList(Collection<TSource> sourceList, Class<Target> targetClass) {
if (sourceList == null) {
return new ArrayList<Target>();
}
ArrayList<Target> targets = new ArrayList<>(sourceList.size());
sourceList.forEach(p -> {
Target item = map(p, targetClass);
});
return targets;
}
/**
* 将集合中的元素抓换为指定类型,并对转换后的元素处理
* @param sourceList 源集合
* @param targetClass 转换目标类型
* @param consumer 对转换后元素处理
* @return 转换后的集合
* @param <TSource> 源类型
* @param <Target> 目标类型
*/
public static <TSource, Target> List<Target> mapList(Collection<TSource> sourceList, Class<Target> targetClass, Consumer<Target> consumer) {
if (sourceList == null) {
return new ArrayList<Target>();
}
ArrayList<Target> targets = new ArrayList<>(sourceList.size());
sourceList.forEach(p -> {
Target item = map(p, targetClass);
if (consumer != null) {
consumer.accept(item);
}
targets.add(item);
});
return targets;
}
/**
* 将集合中的元素抓换为指定类型,并对转换后的元素处理
* @param sourceList 源集合
* @param targetClass 转换目标类型
* @param consumer 对转换后元素处理
* @return 转换后的集合
* @param <TSource> 源类型
* @param <Target> 目标类型
*/
public static <TSource, Target> List<Target> mapList(Collection<TSource> sourceList, Class<Target> targetClass, BiConsumer<TSource, Target> consumer) {
if (sourceList == null) {
return new ArrayList<Target>();
}
ArrayList<Target> targets = new ArrayList<>(sourceList.size());
sourceList.forEach(p -> {
Target map = ModelMapperUtil.map(p, targetClass);
if (consumer != null) {
consumer.accept(p, map);
}
targets.add(map);
});
return targets;
}
public static <T> T deepCopy(T obj) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (T) ois.readObject();
} catch (Exception e) {
throw new RuntimeException("Deep copy failed", e);
}
}
/**
* 将实体列表转换为 Map<键, 名称>,自动过滤键为 null 的记录
* @param list 实体列表
* @param keyMapper 提取键的函数(可为 Integer / String / 其他)
* @param valueMapper 提取值的函数(返回 String)
* @param <T> 实体类型
* @param <K> 键类型
* @return Map<K, String>
*/
public static <T, K> Map<K, String> toMap(List<T> list,
Function<T, K> keyMapper,
Function<T, String> valueMapper) {
if (list == null || list.isEmpty()) {
return Collections.emptyMap();
}
return list.stream()
.filter(item -> keyMapper.apply(item) != null)
.collect(Collectors.toMap(keyMapper, valueMapper, (a, b) -> a));
}
/**
* 将列表转换为 SelectIntVO 列表
*/
public static <T> List<SelectIntVO> toSelectIntVOList(
List<T> sourceList,
Function<T, Integer> idMapper,
Function<T, String> nameMapper) {
if (sourceList == null || sourceList.isEmpty()) {
return Collections.emptyList();
}
return sourceList.stream()
.map(item -> new SelectIntVO(idMapper.apply(item), nameMapper.apply(item)))
.collect(Collectors.toList());
}
public static <T> List<SelectStrVO> toSelectStrVOList(
List<T> sourceList,
Function<T, String> idMapper,
Function<T, String> nameMapper) {
if (sourceList == null || sourceList.isEmpty()) {
return Collections.emptyList();
}
return sourceList.stream()
.map(item -> new SelectStrVO(idMapper.apply(item), nameMapper.apply(item)))
.collect(Collectors.toList());
}
}
@@ -0,0 +1,181 @@
package com.yunhai.bschclassmanage.utils;
import okhttp3.*;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Component
public class OkHttpUtil {
private static OkHttpClient DEFAULT_CLIENT = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build();
private OkHttpClient client;
public OkHttpUtil() {
this.client = DEFAULT_CLIENT;
}
public OkHttpUtil(OkHttpClient client) {
this.client = client;
}
public String get(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
// public String post(String url, String json) throws IOException {
// MediaType JSON = MediaType.get("application/json; charset=utf-8");
// RequestBody body = RequestBody.create(json, JSON);
// Request request = new Request.Builder()
// .url(url)
// .post(body)
// .build();
//
// try (Response response = client.newCall(request).execute()) {
// return response.body().string();
// }
// }
public String post(String aUrl, Map<String, Object> param,
Map<String, Object> formData, Map<String, String> header)throws IOException
{
return post(aUrl,param,formData,header,null);
}
public String post(String aUrl, Map<String, Object> param,
Map<String, Object> formData, Map<String, String> header,
MediaType type) throws IOException {
// 构建URL(添加查询参数)
HttpUrl.Builder urlBuilder = HttpUrl.parse(aUrl).newBuilder();
if (param != null) {
for (Map.Entry<String, Object> entry : param.entrySet()) {
urlBuilder.addQueryParameter(entry.getKey(), String.valueOf(entry.getValue()));
}
}
String finalUrl = urlBuilder.build().toString();
// 构建请求体
RequestBody requestBody = null;
if (formData != null && !formData.isEmpty()) {
if (type == null) {
type = MediaType.parse("application/x-www-form-urlencoded");
}
if ("application/x-www-form-urlencoded".equals(type.toString())) {
FormBody.Builder formBuilder = new FormBody.Builder();
for (Map.Entry<String, Object> entry : formData.entrySet()) {
formBuilder.add(entry.getKey(), String.valueOf(entry.getValue()));
}
requestBody = formBuilder.build();
} else if ("multipart/form-data".equals(type.toString())) {
MultipartBody.Builder bodyBuilder =new MultipartBody.Builder().setType(type);
for (Map.Entry<String, Object> entry : formData.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof File) {
// 处理文件类型参数
File file = (File) value;
MediaType mediaType = MediaType.parse(getMimeType(file.getName()));
RequestBody fileBody = RequestBody.create(mediaType, file);
bodyBuilder.addFormDataPart(key, file.getName(), fileBody);
} else if (value instanceof byte[]) {
// 处理字节数组(文件流)
byte[] bytes = (byte[]) value;
MediaType mediaType = MediaType.parse("application/octet-stream");
bodyBuilder.addFormDataPart(key, "file",
RequestBody.create(mediaType, bytes));
} else {
// 处理普通字符串参数
bodyBuilder.addFormDataPart(key, value.toString());
}
}
requestBody = bodyBuilder.build();
}else {
// 对于JSON或其他格式
StringBuilder content = new StringBuilder();
if ("application/json".equals(type.toString())) {
content.append("{");
int i = 0;
for (Map.Entry<String, Object> entry : formData.entrySet()) {
if (i > 0) content.append(",");
content.append("\"").append(entry.getKey()).append("\":");
if (entry.getValue() instanceof String) {
content.append("\"").append(entry.getValue()).append("\"");
} else {
content.append(entry.getValue());
}
i++;
}
content.append("}");
} else
{
// 其他格式简单处理为键值对
for (Map.Entry<String, Object> entry : formData.entrySet()) {
if (content.length() > 0) content.append("&");
content.append(entry.getKey()).append("=").append(entry.getValue());
}
}
requestBody = RequestBody.create(type, content.toString());
}
}
// 构建请求
Request.Builder requestBuilder = new Request.Builder()
.url(finalUrl)
.post(requestBody != null ? requestBody : RequestBody.create(null, new byte[0]));
// 添加请求头
if (header != null) {
for (Map.Entry<String, String> entry : header.entrySet()) {
requestBuilder.addHeader(entry.getKey(), entry.getValue());
}
}
// 执行请求
Request request = requestBuilder.build();
try (Response response = client.newCall(request).execute()) {
ResponseBody responseBody = response.body();
if (responseBody != null) {
return responseBody.string();
} else {
return null; // 或者根据实际情况返回 null 或空字符串
}
}
}
private String getMimeType(String fileName) {
if (fileName.endsWith(".png")) {
return "image/png";
} else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
return "image/jpeg";
} else if (fileName.endsWith(".pdf")) {
return "application/pdf";
} else if (fileName.endsWith(".txt")) {
return "text/plain";
}
// 默认类型
return "application/octet-stream";
}
}
@@ -0,0 +1,21 @@
package com.yunhai.bschclassmanage.utils;
import org.json.JSONArray;
import org.springframework.stereotype.Service;
@Service
public class OrgJsonUtil {
public static String[][] getJsonStrig(String answer){
JSONArray jsonArray = new JSONArray(answer);
String[][] result = new String[jsonArray.length()][];
for (int i = 0; i < jsonArray.length(); i++) {
JSONArray innerArray = jsonArray.getJSONArray(i);
result[i] = new String[innerArray.length()];
for (int j = 0; j < innerArray.length(); j++) {
result[i][j] = innerArray.getString(j);
}
}
return result;
}
}
@@ -0,0 +1,415 @@
package com.yunhai.bschclassmanage.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.yunhai.bschclassmanage.entity.BaseEntity;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yunhai.platform.utils.exception.DException;
import io.netty.util.internal.StringUtil;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/*
* 杂项公用方法集合
* */
public class OtherUtil {
private static final ObjectMapper objectMapper = new ObjectMapper();
private OtherUtil() {}
/**
* @Description: 判断字符串能否序列化
* @Author: chenx
* @Date: 2023/4/20
*/
public final static boolean isJSONValid(String str) {
try {
JSONObject.parse(str);
} catch (JSONException ex) {
return false;
}
return true;
}
/**
* @Description: 判断字符串能否序列化为json数组
* @Author: chenx
* @Date: 2023/4/20
*/
public final static boolean isJsonArray(String str) {
if (!isJSONValid(str)) return false;
try {
Object object = JSON.parse(str);
return object instanceof JSONArray;
} catch (JSONException ex) {
return false;
}
}
/**
* JSON序列化方式实现集合跨类型拷贝
* @param src 源集合
* @param targetClazz 目标类
* @return 新集合
*/
public final static <S, T> List<T> deepCopy(List<S> src, Class<T> targetClazz) {
if (src == null) {
return new ArrayList<>();
}
String jsonStr = JSON.toJSONString(src);
return JSONArray.parseArray(jsonStr, targetClazz);
}
public final static <T> T deepCopy(T source, Class<T> clazz) {
try {
return objectMapper.readValue(objectMapper.writeValueAsString(source), clazz);
} catch (Exception e) {
throw new RuntimeException("深拷贝失败", e);
}
}
/**
* double类型的加法运算(不需要舍入)
* @param m1
* @param m2
* @return 不加doubleValue()则, 返回BigDecimal对象
*/
public static double additionDouble(double m1, double m2) {
BigDecimal p1 = new BigDecimal(Double.toString(m1));
BigDecimal p2 = new BigDecimal(Double.toString(m2));
return p1.add(p2).doubleValue();
}
/**
* double类型的除法运算(直接删除多余位数)
* @param m1
* @param m2
* @return 不加doubleValue()则, 返回BigDecimal对象
*/
public static double divideDouble(double m1, double m2) {
if (m1 == 0 || m2 == 0) return 0;
BigDecimal p1 = new BigDecimal(Double.toString(m1));
BigDecimal p2 = new BigDecimal(Double.toString(m2));
BigDecimal p3 = p1.divide(p2,4, BigDecimal.ROUND_DOWN );
return p3.doubleValue();
}
/**
* double类型转化为字符串,统一位数
* @param num
* @return 保留2位小数-直接舍弃2位之后的数据
*/
public static String formatDouble(double num) {
DecimalFormat df = new DecimalFormat("0.##");
df.setRoundingMode(RoundingMode.DOWN);
return df.format(num);
}
/**
* 字符串值 类型转化为double,统一位数
* @param numStr
* @return 保Str留2位小数-直接舍弃2位之后的数据
*/
public static Double formatDouble(String numStr) {
try {
double num = Double.parseDouble(numStr);
DecimalFormat df = new DecimalFormat("0.##");
df.setRoundingMode(RoundingMode.DOWN);
numStr = df.format(num);
return Double.parseDouble(numStr);
} catch (NumberFormatException e) {
return null;
}
}
public static <T extends BaseEntity> void setBaseEntityValue(UserContext.UserInfo user, T entity) {
if (user == null || entity == null) {
throw new IllegalArgumentException("参数不能为null");
}
Date now = new Date();
Integer userId = user.getUserId();
entity.setUpdateDate(now);
entity.setUpdateUserId(userId);
// 判断是否为新增:id为null或0视为新增
Integer id = entity.getId();
if (id == null || id == 0) {
entity.setCreateDate(now);
entity.setCreateUserId(userId);
entity.setSchId(user.getSchId());
}
}
public static Map<String, Object> convertJsonToMap(String json) {
try {
return objectMapper.readValue(json, Map.class);
} catch (Exception e) {
System.out.println("convertJsonToMap json to Map 失败!json="+json);
e.printStackTrace();
return null;
}
}
public static List<Map<String, Object>> convertJsonToMapList(String json) {
List<Map<String, Object>> list=new ArrayList<>();
try {
list = objectMapper.readValue(json, new TypeReference<List<Map<String, Object>>>() {});
} catch (Exception e) {
try{
list = objectMapper.readValue("["+json+"]", new TypeReference<List<Map<String, Object>>>() {});
}catch (Exception e2) {
}
System.out.println("convertJsonToMapList json to MapList 失败!json="+json);
e.printStackTrace();
}
return list;
}
public static List<Map<String, Object>> jsonToMapTree(String json) {
List<Map<String, Object>> result = new ArrayList<>();
try {
JsonNode rootNode = objectMapper.readTree(json);
for (JsonNode node : rootNode) {
result.add(jsonNodeToMap(node));
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private static Map<String, Object> jsonNodeToMap(JsonNode node) {
Map<String, Object> retMap = new HashMap<>();
node.fields().forEachRemaining(entry -> {
if (entry.getValue().isObject()) {
retMap.put(entry.getKey(), jsonNodeToMap(entry.getValue()));
} else if (entry.getValue().isArray()) {
List<Object> list = new ArrayList<>();
for (JsonNode element : entry.getValue()) {
list.add(jsonNodeToMap(element));
}
retMap.put(entry.getKey(), list);
} else {
retMap.put(entry.getKey(), entry.getValue().asText());
}
});
return retMap;
}
public static String convertMarkdownToHtml(String markdown) {
Parser parser = Parser.builder().build();
Node document = parser.parse(markdown);
HtmlRenderer renderer = HtmlRenderer.builder().build();
return renderer.render(document);
}
public static <Target> Target mapToClass(Map<String,Object> map, Class<Target> targetClass) {
return objectMapper.convertValue(map,targetClass);
}
public static <TSource, Target> List<Target> mapToList(List<Map<String,Object>> sourceList, Class<Target> targetClass) {
if (sourceList == null) {
return new ArrayList<Target>();
}
ArrayList<Target> targets = new ArrayList<>(sourceList.size());
sourceList.forEach(p -> {
Target item = mapToClass(p, targetClass);
targets.add(item);
});
return targets;
}
public static <TSource,Target> List<Map> mapList(List<Map<String,Object>> sourceList, Class<Target> targetClass) {
List<Target> sList=mapToList(sourceList,targetClass);
return sList.stream()
.map(student -> objectMapper.convertValue(student, new TypeReference<Map>() {}))
.collect(Collectors.toList());
}
/**
* 将 JSON 数组字符串解析为指定类型的 List
* @param json JSON 数组字符串(如 "[{...},{...}]")
* @param targetClass 目标元素类型(如 BaseTree.class)
* @param <T> 目标类型
* @return 解析后的 List,若失败或为空则返回 null
*/
public static <T> List<T> jsonParseList(String json, Class<T> targetClass) {
if (json == null || json.trim().isEmpty()) {
return null;
}
try {
// 使用 TypeReference 保留泛型信息,避免类型擦除
return objectMapper.readValue(json, new TypeReference<List<T>>() {});
} catch (Exception e) {
System.err.println("解析 JSON 数组失败,json 前缀: " + json);
e.printStackTrace();
return null;
}
}
/**
* 将 JSON 字符串解析为单个对象(非数组)
* @param json JSON 对象字符串
* @param targetClass 目标类型
* @param <T> 目标类型
* @return 解析后的对象,失败返回 null
*/
public static <T> T jsonParseObject(String json, Class<T> targetClass) {
if (json == null || json.trim().isEmpty()) {
return null;
}
try {
return objectMapper.readValue(json, targetClass);
} catch (Exception e) {
System.err.println("解析 JSON 数组失败,json 前缀: " + json);
e.printStackTrace();
return null;
}
}
public static <T> List<T> jsonParseArrayTree(String json, Class<T> elementClass) {
if (json == null || json.trim().isEmpty()) {
return null;
}
try {
// 使用 TypeFactory 动态构建 List<Element> 的 JavaType
JavaType listType = objectMapper.getTypeFactory()
.constructCollectionType(List.class, elementClass);
return objectMapper.readValue(json, listType);
} catch (Exception e) {
System.err.println("解析 JSON 数组失败: " + json);
e.printStackTrace();
return null;
}
}
public static <T> T jsonParseTree(String json, Class<T> elementClass) {
if (json == null || json.trim().isEmpty()) {
return null;
}
try {
JavaType javaType = objectMapper.getTypeFactory().constructType(elementClass);
return objectMapper.readValue(json, javaType);
} catch (Exception e) {
System.err.println("解析 JSON 数组失败: " + json);
e.printStackTrace();
return null;
}
}
public static HttpServletRequest getRequest() {
ServletRequestAttributes attributes = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
if (attributes == null) {
throw new IllegalStateException("当前线程中不存在Request上下文");
}
return attributes.getRequest();
}
// public static String getHeader(String headerName) {
// HttpServletRequest request = getRequest();
// return request.getHeader(headerName);
// }
public static String getHeader(String headerName) {
String value = getHeader(headerName);
if(StringUtils.hasText(value))
return value;
else
throw new DException(headerName+" is null");
}
public static Integer[] convertToArray(String idsStr) {
if (idsStr == null || idsStr.trim().isEmpty()) {
return new Integer[0];
}
String[] parts = idsStr.split(",");
Integer[] result = new Integer[parts.length];
for (int i = 0; i < parts.length; i++) {
result[i] = Integer.parseInt(parts[i].trim());
}
return result;
}
/**
* 获取客户端真实 IP 地址(支持代理转发)
*/
public static String getClientIp() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes == null) {
return "unknown";
}
HttpServletRequest request = attributes.getRequest();
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
// 多个代理的情况,取第一个 IP
if (ip != null && ip.contains(",")) {
ip = ip.split(",")[0].trim();
}
return ip;
}
public static String nullToStr(Object obj) {
return obj == null ? "null":(obj==""? "空字符串": obj.toString());
}
public static int extractClassNumber(String className) {
if (StringUtil.isNullOrEmpty(className)) return -1;
// 优先匹配 "数字+班"
Matcher matcher = Pattern.compile("(\\d+)\\s*班").matcher(className);
if (matcher.find()) {
return Integer.parseInt(matcher.group(1));
}
// 若无“班”,尝试提取所有数字中的最后一个(且长度≤2,视为班级号)
Matcher fallback = Pattern.compile("\\d+").matcher(className);
int lastNum = -1;
while (fallback.find()) {
String numStr = fallback.group();
if (numStr.length() <= 2) { // 只接受1~2位数字作为班级号
lastNum = Integer.parseInt(numStr);
}
}
return lastNum; // 若没有符合的数字,返回 -1
}
}
@@ -0,0 +1,49 @@
package com.yunhai.bschclassmanage.utils;
import com.yunhai.bschclassmanage.model.tool.PageInfo;
import org.springframework.data.domain.Pageable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author wanghu
* @Date 2025-11-10 14:47 (可以根据需要修改)
* @Description:
*/
public class PageUtil {
public static List<Map> paginate(List<Map> list,Pageable pageable) {
if (list == null || list.isEmpty()) {
return new ArrayList<>();
}
int total = list.size();
int fromIndex = pageable.getPageNumber() * pageable.getPageSize();
// 检查页码是否有效
if (fromIndex >= total) {
return new ArrayList<>();
}
int toIndex = Math.min(fromIndex + pageable.getPageSize(), total);
return list.subList(fromIndex, toIndex);
}
/**
* 获取分页信息
* @param list 原始数据列表
* @param pageNum 页码
* @param pageSize 每页大小
* @return 分页信息对象
*/
public static PageInfo getPageInfo(List<Map> list,int pageNum, int pageSize) {
int total = list.size();
int totalPages = (int) Math.ceil((double) total / pageSize);
boolean hasNext = pageNum < totalPages;
boolean hasPrev = pageNum > 0;
return new PageInfo(pageNum, pageSize, total, totalPages, hasNext, hasPrev);
}
}
@@ -0,0 +1,84 @@
package com.yunhai.bschclassmanage.utils;
public class RedisConstants {
public static final String CachePrefix = "bsch.classmanage";
//-----------------------------过期时间--------------------------
public static final long CACHE_EXPIRE_5M = 5 * 60 * 1000;
public static final long CACHE_EXPIRE_10M = 10 * 60 * 1000;
public static final long CACHE_EXPIRE_30M = 3 * CACHE_EXPIRE_10M;
public static final long CACHE_EXPIRE_1H = 60 * 60 * 1000;
public static final long CACHE_EXPIRE_1D= 24 * CACHE_EXPIRE_1H ;
public static final long CACHE_EXPIRE_7D= 7 * CACHE_EXPIRE_1D ;
public static final long CACHE_EXPIRE_30D=30 * CACHE_EXPIRE_1D;
//-------------------------------系统---------------------------------------
//系统年级
public static final String SYSTEM_GRAGE =CachePrefix+ ".system_grdae";
//系统年级
public static final String SYSTEM_SUBJECT =CachePrefix+ ".system_subject";
//系统学制
public static final String SYSTEM_SCHSYSTEM =CachePrefix+ ".system_schsystem";
//系统年级
public static final String SYSTEM_YEARTERM =CachePrefix+ ".system_yearterm";
//执行进度Progress
public static final String EXTERNAL_PROGRESS = CachePrefix + "external_progress";
//执行任务数据缓存
public static final String EXTERNAL_PLAN_DATA = CachePrefix + "external_plan_data";
//---------------------------学校-------------------------------------------------------
//学校树
public static final String SCHOOL_TREE =CachePrefix+ ".sch_tree";
//学校列表
public static final String SCHOOL_LIST =CachePrefix+ ".sch_list";
//学校年级
public static final String SCHOOL_SUBJECT =CachePrefix+ ".sch_subject";
//学校院校
public static final String SCHOOL_CAMPUS =CachePrefix+ ".sch_campus";
//学部
public static final String SCHOOL_DICISION =CachePrefix+ ".sch_division";
//专业
public static final String SCHOOL_MAJORS =CachePrefix+ ".sch_majors";
//课程
public static final String SCHOOL_COURSE =CachePrefix+ ".sch_course";
//学校年级
public static final String SCHOOL_GRAGE =CachePrefix+ ".sch_grdae";
//班级
public static final String SCHOOL_CLASS =CachePrefix+ ".sch_class";
public static final String SCHOOL_TEACHER =CachePrefix+ ".sch_teacher";
public static final String SCHOOL_CLASS_TEACH =CachePrefix+ ".sch_class_teach";
public static final String SCHOOL_CLASS_STUDENT=CachePrefix+ ".sch_class_student";
public static final String SCHOOL_CUSTOM_GROUP=CachePrefix+ ".sch_group_teacher";
}
@@ -0,0 +1,929 @@
package com.yunhai.bschclassmanage.utils;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* Redis工具类
*/
@Component
public final class RedisUtil {
@Autowired
private RedisTemplate redisTemplate;
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
// ============================String=============================
// /**
// * 普通缓存获取
// *
// * @param key 键
// * @return 值
// */
//
// public Object get(String key) {
//
// return key == null ? null : redisTemplate.opsForValue().get(key);
//
// }
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
*
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
// ================================Map=================================
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于)
* @return
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于)
* @return
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
// ============================set=============================
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0)
expire(key, time);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
// ===============================list=================================
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* * @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 根据模式匹配获取所有 Key
* @param pattern 匹配模式,如 "school_class_teach_1_*"
* @return 匹配的 Key 集合
*/
public Set<String> keys(String pattern) {
try {
return redisTemplate.keys(pattern);
} catch (Exception e) {
return Collections.emptySet();
}
}
public <T> T get(String key, Class<T> clazz) {
Object obj = redisTemplate.opsForValue().get(key);
if (obj == null) return null;
if (clazz.isInstance(obj)) {
return clazz.cast(obj);
}
// 如果类型不匹配,尝试用 FastJson 转换
return JSON.parseObject(JSON.toJSONString(obj), clazz);
}
/**
* 获取缓存并转换为目标 List 类型(专门解决 LinkedHashMap 问题)
*/
public <T> List<T> getList(String key, Class<T> clazz) {
Object obj = redisTemplate.opsForValue().get(key);
if (obj instanceof List) {
return JSON.parseArray(JSON.toJSONString(obj), clazz);
}
return null;
}
/**
* 批量获取多个 Key 的 List 数据
* @param keys 缓存 Key 列表
* @param clazz 元素类型
* @return Key -> List 映射
*/
public <T> Map<String, List<T>> mgetList(List<String> keys, Class<T> clazz) {
if (keys == null || keys.isEmpty()) {
return Collections.emptyMap();
}
try {
List<Object> results = redisTemplate.opsForValue().multiGet(keys);
Map<String, List<T>> resultMap = new HashMap<>();
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
Object value = results.get(i);
if (value != null) {
resultMap.put(key,JSON.parseArray(JSON.toJSONString(value), clazz));
}
}
return resultMap;
} catch (Exception e) {
return Collections.emptyMap();
}
}
}
@@ -0,0 +1,121 @@
package com.yunhai.bschclassmanage.utils;
import com.yunhai.platform.utils.exception.DException;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class Signature {
public static String getSign(String data, String timeStamp, String secret) {
return getHmacSHA256(data + timeStamp, secret);
}
public static int getTimestamp(Date time)
{
Calendar cal = Calendar.getInstance();
Calendar newDate;
if (time != null)
{
cal.setTime(time);
newDate = cal;
}
else
newDate = cal;
return newDate.get(Calendar.HOUR_OF_DAY) * 3600 + newDate.get(Calendar.MINUTE) * 60 + newDate.get(Calendar.SECOND);
}
public static Map getHeaderMap(String data,String app_key,String app_secret)
{
int timeLong=getTimestamp(new Date());
Map headerMap=new HashMap();
headerMap.put("t",timeLong);
headerMap.put("sign",Signature.getSign(data,String.valueOf(timeLong),app_secret));
headerMap.put("appkey",app_key);
return headerMap;
}
public static String getHmacSHA256(String data,String secret)
{
try
{ // 创建密钥规范
SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
// 获取Mac实例并初始化
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKeySpec);
byte[] hmacSHA256Bytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
// 将哈希值转换为十六进制字符串表示
StringBuilder hexString = new StringBuilder(2 * hmacSHA256Bytes.length);
for (byte b : hmacSHA256Bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
// 输出结果
return hexString.toString();
}
catch(Exception ex)
{
return "";
}
}
public static String getRequestBody(HttpServletRequest request,HttpServletResponse response){
try {
StringBuilder buffer = new StringBuilder();
String line;
try (BufferedReader reader = request.getReader()) {
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
}
String requestBody = buffer.toString();
return requestBody;
} catch (IOException ex) {
throw new DException("body is null");
}
}
public static void verifySign(HttpServletRequest request,String data,String app_key,String app_secret)
{
String appkey = request.getHeader("appkey");
if(StringUtils.isEmpty(appkey)) throw new DException("appkey is null");
if(!app_key.equals(appkey))throw new DException("appkey value error");
String sign = request.getHeader("sign");
if(StringUtils.isEmpty(sign)) throw new DException("sign is null");
String t = request.getHeader("t");
if(StringUtils.isEmpty(t)) throw new DException("t is null");
long currentTimeMillis = System.currentTimeMillis();
long pastTimeMillis = Long.parseLong(t);
long timeDifference = currentTimeMillis - pastTimeMillis ;
long timeDifferenceInSeconds = timeDifference / 1000;
if(timeDifferenceInSeconds>300) throw new DException("request expire");
String sign2= getSign(data,t,app_secret);
if(!sign.equals(sign2)){
//签名验不过,表示这个API返回的数据有可能已经被篡改了
throw new DException("sign verify fail");
}
}
}
@@ -0,0 +1,144 @@
package com.yunhai.bschclassmanage.utils;
import java.text.SimpleDateFormat;
import java.util.*;
public class TimeUtils {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
/**
* 日期转星期
*/
public static String dateToWeek(String datetime) {
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
Calendar cal = Calendar.getInstance(); // 获得一个日历
Date date = null;
try {
date = f.parse(datetime);
cal.setTime(date);
} catch (Exception e) {
}
int w = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的某天。
if (w < 0)
w = 0;
return weekDays[w];
}
public static String getTodayDate() {
String date = sdf.format(new Date());
return date;
}
public static String timstamp2DateTime(String timestamp)
{
String[] split = timestamp.split("-");
if (split.length > 1)
{
return timestamp;
}
else
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Long.parseLong(timestamp));
}
/**
* 获取这个月的第一天
*/
public static String getFirstDayOfCurrentMonth() {
Calendar cal = Calendar.getInstance();
// 获取某月最大天数
int lastDay = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
// 设置日历中月份的最大天数
cal.set(Calendar.DAY_OF_MONTH, lastDay);
// 格式化日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String firstDayOfMonth = sdf.format(cal.getTime());
return firstDayOfMonth;
}
/**
* 获取这个月的最后一天
*/
public static String getLastDayOfCurrentMonth() {
Calendar cal = Calendar.getInstance();
// 获取某月最大天数
int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
// 设置日历中月份的最大天数
cal.set(Calendar.DAY_OF_MONTH, lastDay);
// 格式化日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String lastDayOfMonth = sdf.format(cal.getTime());
return lastDayOfMonth;
}
/**
* 每周的第一天
*/
public static String getFirstOfWeek(){
Calendar cal = Calendar.getInstance();
Date current = new Date();
cal.setTime(current);
int d = 0;
if (cal.get(Calendar.DAY_OF_WEEK) == 1) {
d = 0;
} else {
d = 1 - cal.get(Calendar.DAY_OF_WEEK);
}
cal.add(Calendar.DAY_OF_WEEK, d+1);
// 所在周开始日期
String data1 = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
return data1;
}
/**
* 每周的最后一天
*/
public static String getLastOfWeek(){
Calendar cal = Calendar.getInstance();
Date current = new Date();
cal.setTime(current);
int d = 0;
if (cal.get(Calendar.DAY_OF_WEEK) == 1) {
d = 6;
} else {
d = 7 - cal.get(Calendar.DAY_OF_WEEK);
}
cal.add(Calendar.DAY_OF_WEEK, d+1);
// 所在周结束日期
String data2 = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
return data2;
}
// 获取两个时间之间的月份
public static List<String> getMonthBetweenDate(Date startDate,Date endDate){
ArrayList<String> result = new ArrayList<String>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");//格式化,调整为自己需要的格式
Calendar min = Calendar.getInstance();
Calendar max = Calendar.getInstance();
// 给calendar设置开始时间
min.setTime(startDate);
// set方法设置年月日 年为开始时间的年份 后面同理
min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);
// 给calendar设置结束时间
max.setTime(endDate);
// set方法设置年月日 年为结束时间的年份 后面同理,最后面的1和2不要改
max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);
// 创建一个临时的变量,代表当前的时间
Calendar curr = min;
// 如果当前的时间在结束时间之前,循环知道超过结束时间就结束,返回结果集合
while (curr.before(max)) {
// 将这个当前的时间格式化之后保存到result集合
result.add(sdf.format(curr.getTime()));
// 将当前的时间加上1个月
curr.add(Calendar.MONTH, 1);
}
return result;
}
}
@@ -0,0 +1,16 @@
package com.yunhai.bschclassmanage.utils;
import java.util.UUID;
/**
* @ Description : java类作用描述
* @ Author : cls
* @ CreateDate : 2020/2/15 17:15
* @ Company : bestsch
*/
public class UUIDUtils {
public static String getUUID(){
return UUID.randomUUID().toString().replace("-","");
}
}
@@ -0,0 +1,96 @@
package com.yunhai.bschclassmanage.utils;
import lombok.Value;
public class UserContext {
private static final ThreadLocal<Integer> USER_ID = new ThreadLocal<>();
private static final ThreadLocal<String> USER_NAME = new ThreadLocal<>();
private static final ThreadLocal<Integer> ROLE_ID = new ThreadLocal<>();
private static final ThreadLocal<Integer> SCH_ID = new ThreadLocal<>();
private static final ThreadLocal<String> IP = new ThreadLocal<>();
// 原有 setter/getter 示例(请确保都有)
public static void setUserId(Integer userId) {
USER_ID.set(userId);
}
public static Integer getUserId() {
return USER_ID.get();
}
public static void setUserName(String userName) {
USER_NAME.set(userName);
}
public static String getUserName() {
return USER_NAME.get();
}
public static void setRoleId(Integer roleId) {
ROLE_ID.set(roleId);
}
public static Integer getRoleId() {
return ROLE_ID.get();
}
public static void setSchId(Integer schId) {
SCH_ID.set(schId);
}
public static Integer getSchId() {
return SCH_ID.get();
}
// ⬇️ 新增 IP 的 setter/getter
public static void setIp(String ip) {
IP.set(ip);
}
public static String getIp() {
return IP.get();
}
@Value
public static class UserInfo {
Integer userId;
String userName;
Integer roleId;
Integer schId;
String ip;
}
public static UserInfo getCurrentUserInfo() {
return new UserInfo(
USER_ID.get(),
USER_NAME.get(),
ROLE_ID.get(),
SCH_ID.get(),
IP.get()
);
}
public static void setUserInfo(UserInfo info) {
if (info == null) return; // 或抛异常
USER_ID.set(info.getUserId());
USER_NAME.set(info.getUserName());
ROLE_ID.set(info.getRoleId());
SCH_ID.set(info.getSchId());
IP.set(info.getIp());
}
public static Runnable wrap(Runnable task) {
UserInfo info = getCurrentUserInfo();
return () -> {
try {
setUserInfo(info);
task.run();
} finally {
clear();
}
};
}
public static void clear() {
USER_ID.remove();
USER_NAME.remove();
ROLE_ID.remove();
SCH_ID.remove();
IP.remove();
}
}
@@ -0,0 +1,148 @@
package com.yunhai.bschclassmanage.utils;
import cn.hutool.core.util.StrUtil;
import java.util.regex.Pattern;
public class ValidateUtil {
// ==================== 身份证号验证 ====================
// 格式正则(允许空串)
private static final String ID_CARD_REGEX =
"^$|^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$";
private static final Pattern PATTERN = Pattern.compile(ID_CARD_REGEX);
// 校验位权重因子(前17位)
private static final int[] WEIGHT = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
// 校验码映射表
private static final char[] VERIFY_CODE = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
/**
* 基础格式校验(允许空串)
* @param idCard 身份证号(可为 null)
* @return true 格式正确或空串;false 格式错误(包括 null)
*/
public static boolean isValidIdCard(String idCard) {
if (idCard == null) {
return false;
}
return PATTERN.matcher(idCard).matches();
}
/**
* 校验最后一位校验码是否正确(仅用于18位身份证)
* @param idCard 18位身份证号(必须符合基本格式,此方法不检查格式)
* @return true 校验位匹配;false 不匹配或输入无效
*/
private static boolean verifyCheckDigit(String idCard) {
if (idCard == null || idCard.length() != 18) {
return false;
}
// 转为大写(兼容小写x)
idCard = idCard.toUpperCase();
int sum = 0;
for (int i = 0; i < 17; i++) {
char c = idCard.charAt(i);
if (c < '0' || c > '9') {
return false; // 前17位必须全数字
}
sum += (c - '0') * WEIGHT[i];
}
char expected = VERIFY_CODE[sum % 11];
return idCard.charAt(17) == expected;
}
/**
* 全量校验:格式正确 + 校验位正确(空串仍视为合法)
* @param idCard 身份证号
* @return true 完全合法(或空串);false 任何一项不合法(包括 null)
*/
public static boolean isValidIdCardStrict(String idCard) {
if (idCard == null) {
return false;
}
// 先用格式校验
if (!isValidIdCard(idCard)) {
return false;
}
// 空串直接通过(业务允许不填)
if (idCard.isEmpty()) {
return true;
}
// 18位长度,校验校验位
return verifyCheckDigit(idCard);
}
/**
* 获取详细的错误信息(用于前端提示)
* @param idCard 身份证号
* @return 若合法返回 null,否则返回具体错误原因
*/
public static String getValidateMessage(String idCard) {
if (idCard == null) {
return "身份证号不能为null";
}
if (!isValidIdCard(idCard)) {
return "身份证号码格式不正确(需为18位有效格式)";
}
if (!idCard.isEmpty() && !verifyCheckDigit(idCard)) {
return "身份证号码校验位错误(最后一位不匹配)";
}
return null; // 合法
}
// ==================== 密码验证 ====================
/**
* 条件校验:若密码不为空,则必须符合强密码规则
* @param password 待校验密码
* @return true 表示允许(要么为空,要么符合规则);false 表示填写了但格式不对
*/
public static boolean validatePasswordIfPresent(String password) {
// 1. 如果为空,直接放行(不校验)
if (StrUtil.isBlank(password)) {
return true;
}
// 2. 如果有值,则必须符合强密码规则
return isValidStrongPassword(password);
}
// 强密码正则(复用之前的)
private static boolean isValidStrongPassword(String password) {
String regex = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?]).{8,}$";
return Pattern.matches(regex, password);
}
// ==================== 手机号验证 ====================
// 手机号正则(允许空串;11位,1开头,第二位3-9,后跟9位数字)
private static final String MOBILE_REGEX = "^$|^1[3-9]\\d{9}$";
private static final Pattern MOBILE_PATTERN = Pattern.compile(MOBILE_REGEX);
/**
* 校验手机号格式(允许空串)
* @param mobile 手机号(可为 null)
* @return true 表示格式正确或为空串;false 表示格式错误(包括 null)
*/
public static boolean isValidMobile(String mobile) {
if (mobile == null) {
return false;
}
return MOBILE_PATTERN.matcher(mobile).matches();
}
/**
* 获取手机号的详细错误信息(用于前端提示)
* @param mobile 手机号
* @return 若合法返回 null,否则返回具体错误原因
*/
public static String getMobileValidateMessage(String mobile) {
if (mobile == null) {
return "手机号不能为null";
}
if (!isValidMobile(mobile)) {
return "手机号格式不正确(需为11位有效号码,如 13800138000)";
}
return null; // 合法
}
}
@@ -0,0 +1,46 @@
package com.yunhai.bschclassmanage.utils;
import javax.validation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class ValidationUtil {
private static final Validator validator;
static {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
public static void validate(Object object) {
Set<ConstraintViolation<Object>> violations = validator.validate(object);
if (!violations.isEmpty()) {
for (ConstraintViolation<Object> violation : violations) {
System.out.println(violation.getMessage()); // 输出错误信息
}
throw new ConstraintViolationException(violations); // 可以根据需要抛出异常
}
}
/**
* 校验对象,返回所有错误信息(去重)
* @param object 待校验对象
* @return 错误信息列表(若无错误,返回空列表)
*/
public static List<String> validateMsgs(Object object) {
if (object == null) {
return new ArrayList<>(); // 或 throw new IllegalArgumentException("校验对象不能为空")
}
Set<ConstraintViolation<Object>> violations = validator.validate(object);
if (violations.isEmpty()) {
return new ArrayList<>(); // 空列表
}
// 提取错误信息并去重
return violations.stream()
.map(ConstraintViolation::getMessage)
.distinct()
.collect(Collectors.toList());
}
}