This commit is contained in:
淋雨一直走YH
2023-09-28 15:38:29 +08:00
commit 7bc57c75dc
1480 changed files with 144393 additions and 0 deletions

202
mjkf-xinke-common/pom.xml Normal file
View File

@@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>mjkf.xinke</groupId>
<artifactId>mjkf-xinke-boot</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>mjkf-xinke-common</artifactId>
<packaging>jar</packaging>
<description>基础通用模块</description>
<distributionManagement>
<repository>
<id>admin</id>
<name>release</name>
<url>http://192.168.137.98:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>xx</id>
<name>snapshot</name>
<url>http://192.168.137.98:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
<dependencies>
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- easy-trans -->
<dependency>
<groupId>com.fhs-opensource</groupId>
<artifactId>easy-trans-spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<artifactId>mybatis-plus-annotation</artifactId>
<groupId>com.baomidou</groupId>
</exclusion>
<exclusion>
<artifactId>springfox-schema</artifactId>
<groupId>io.springfox</groupId>
</exclusion>
<exclusion>
<artifactId>error_prone_annotations</artifactId>
<groupId>com.google.errorprone</groupId>
</exclusion>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<artifactId>commons-collections</artifactId>
<groupId>commons-collections</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- easy-trans-mybatis-plus-extend -->
<dependency>
<groupId>com.fhs-opensource</groupId>
<artifactId>easy-trans-mybatis-plus-extend</artifactId>
<exclusions>
<exclusion>
<artifactId>mybatis-plus-extension</artifactId>
<groupId>com.baomidou</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<!-- jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- pinyin4j -->
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
</dependency>
<!-- ip2region -->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<!-- easy-poi -->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<artifactId>javassist</artifactId>
<groupId>org.javassist</groupId>
</exclusion>
<exclusion>
<artifactId>poi</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
<exclusion>
<artifactId>poi-ooxml</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
<exclusion>
<artifactId>poi-ooxml-schemas</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- sm-crypto -->
<dependency>
<groupId>com.antherd</groupId>
<artifactId>sm-crypto</artifactId>
</dependency>
<!-- easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<!-- json-flattener -->
<dependency>
<groupId>com.github.wnameless.json</groupId>
<artifactId>json-flattener</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,21 @@
package mjkf.xinke.common.annotation;
import java.lang.annotation.*;
/**
* 自定义日志注解
*
*
* @date 2022/6/20 14:25
**/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CommonLog {
/**
* 日志的名称,例如:"修改菜单"
*/
String value() default "未命名";
}

View File

@@ -0,0 +1,21 @@
package mjkf.xinke.common.annotation;
import java.lang.annotation.*;
/**
* 自定义节流防抖注解
*
*
* @date 2022/6/20 14:25
**/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CommonNoRepeat {
/**
* 间隔时间(ms)小于此时间视为重复提交默认5000ms
*/
int interval() default 5000;
}

View File

@@ -0,0 +1,24 @@
package mjkf.xinke.common.annotation;
import mjkf.xinke.common.pojo.CommonWrapperInterface;
import java.lang.annotation.*;
/**
* 自定义包装注解,对响应结果包装
*
*
* @date 2022/9/15 21:12
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CommonWrapper {
/**
* 具体包装类
*/
Class<? extends CommonWrapperInterface<?>>[] value();
}

View File

@@ -0,0 +1,75 @@
package mjkf.xinke.common.cache;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 通用Redis缓存操作器
*
*
* @date 2022/6/21 16:00
**/
@Component
public class CommonCacheOperator {
/** 所有缓存Key的前缀 */
private static final String CACHE_KEY_PREFIX = "Cache:";
@Resource
private RedisTemplate<String, Object> redisTemplate;
public void put(String key, Object value) {
redisTemplate.boundValueOps(CACHE_KEY_PREFIX + key).set(value);
}
public void put(String key, Object value, long timeoutSeconds) {
redisTemplate.boundValueOps(CACHE_KEY_PREFIX + key).set(value, timeoutSeconds, TimeUnit.SECONDS);
}
public Object get(String key) {
return redisTemplate.boundValueOps(CACHE_KEY_PREFIX + key).get();
}
public void remove(String... key) {
ArrayList<String> keys = CollectionUtil.toList(key);
List<String> withPrefixKeys = keys.stream().map(i -> CACHE_KEY_PREFIX + i).collect(Collectors.toList());
redisTemplate.delete(withPrefixKeys);
}
public Collection<String> getAllKeys() {
Set<String> keys = redisTemplate.keys(CACHE_KEY_PREFIX + "*");
if (keys != null) {
// 去掉缓存key的common prefix前缀
return keys.stream().map(key -> StrUtil.removePrefix(key, CACHE_KEY_PREFIX)).collect(Collectors.toSet());
} else {
return CollectionUtil.newHashSet();
}
}
public Collection<Object> getAllValues() {
Set<String> keys = redisTemplate.keys(CACHE_KEY_PREFIX + "*");
if (keys != null) {
return redisTemplate.opsForValue().multiGet(keys);
} else {
return CollectionUtil.newArrayList();
}
}
public Map<String, Object> getAllKeyValues() {
Collection<String> allKeys = this.getAllKeys();
HashMap<String, Object> results = MapUtil.newHashMap();
for (String key : allKeys) {
results.put(key, this.get(key));
}
return results;
}
}

View File

@@ -0,0 +1,20 @@
package mjkf.xinke.common.enums;
import lombok.Getter;
/**
* 通用删除标志枚举
*
*
* @date 2021/10/11 14:02
**/
@Getter
public enum CommonDeleteFlagEnum {
/** 未删除 */
NOT_DELETE,
/** 已删除 */
DELETED
}

View File

@@ -0,0 +1,31 @@
package mjkf.xinke.common.enums;
import lombok.Getter;
/**
* 异常码枚举
*
*
* @date 2022/8/15 16:09
**/
@Getter
public enum CommonExceptionEnum {
OK200(200, "请求成功"),
ERROR401(401, "未登录"),
ERROR403(403, "无权限"),
ERROR404(404, "路径不存在"),
ERROR405(405, "请求方法不正确"),
ERROR415(415, "参数传递异常"),
ERROR500(500, "业务异常");
private final Integer code;
private final String message;
CommonExceptionEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}

View File

@@ -0,0 +1,34 @@
package mjkf.xinke.common.enums;
import lombok.Getter;
import mjkf.xinke.common.exception.CommonException;
/**
* 通用排序方式枚举
*
*
* @date 2022/7/13 17:48
**/
@Getter
public enum CommonSortOrderEnum {
/** 升序 */
ASC("ASCEND"),
/** 降序 */
DESC("DESCEND");
private final String value;
CommonSortOrderEnum(String value) {
this.value = value.toUpperCase();
}
public static void validate(String value) {
boolean flag = ASC.getValue().toLowerCase().equals(value) || DESC.getValue().toLowerCase().equals(value);
if(!flag) {
throw new CommonException("不支持该排序方式:{}", value);
}
}
}

View File

@@ -0,0 +1,101 @@
package mjkf.xinke.common.excel;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.ArrayList;
import java.util.List;
/**
* EasyExcel自定义合并策略 该类继承了AbstractMergeStrategy抽象合并策略需要重写merge()方法
*
*
* @date 2023/3/6 13:21
**/
public class CommonExcelCustomMergeStrategy extends AbstractMergeStrategy {
/**
* 分组,每几行合并一次
*/
private final List<Integer> exportFieldGroupCountList;
/**
* 目标合并列index
*/
private final Integer targetColumnIndex;
/**
* 需要开始合并单元格的首行index
*/
private Integer rowIndex;
/**
* exportDataList为待合并目标列的值
*
*
* @date 2023/3/6 13:23
**/
public CommonExcelCustomMergeStrategy(List<String> exportDataList, Integer targetColumnIndex) {
this.exportFieldGroupCountList = getGroupCountList(exportDataList);
this.targetColumnIndex = targetColumnIndex;
}
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
if (null == rowIndex) {
rowIndex = cell.getRowIndex();
}
// 仅从首行以及目标列的单元格开始合并,忽略其他
if (cell.getRowIndex() == rowIndex && cell.getColumnIndex() == targetColumnIndex) {
mergeGroupColumn(sheet);
}
}
private void mergeGroupColumn(Sheet sheet) {
int rowCount = rowIndex;
for (Integer count : exportFieldGroupCountList) {
if(count == 1) {
rowCount += count;
continue ;
}
// 合并单元格
CellRangeAddress cellRangeAddress = new CellRangeAddress(rowCount, rowCount + count - 1, targetColumnIndex, targetColumnIndex);
sheet.addMergedRegionUnsafe(cellRangeAddress);
rowCount += count;
}
}
/*
* 该方法将目标列根据值是否相同连续可合并,存储可合并的行数
*
*
* @date 2023/3/6 13:23
**/
private List<Integer> getGroupCountList(List<String> exportDataList){
if (CollectionUtils.isEmpty(exportDataList)) {
return new ArrayList<>();
}
List<Integer> groupCountList = new ArrayList<>();
int count = 1;
for (int i = 1; i < exportDataList.size(); i++) {
if (exportDataList.get(i).equals(exportDataList.get(i - 1))) {
count++;
} else {
groupCountList.add(count);
count = 1;
}
}
// 处理完最后一条后
groupCountList.add(count);
return groupCountList;
}
}

View File

@@ -0,0 +1,39 @@
package mjkf.xinke.common.exception;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import lombok.Setter;
/**
* 通用异常
*
*
* @date 2020/4/8 15:54
*/
@Getter
@Setter
public class CommonException extends RuntimeException {
private Integer code;
private String msg;
public CommonException() {
super("服务器异常");
this.code = 500;
this.msg = "服务器异常";
}
public CommonException(String msg, Object... arguments) {
super(StrUtil.format(msg, arguments));
this.code = 500;
this.msg = StrUtil.format(msg, arguments);
}
public CommonException(Integer code, String msg, Object... arguments) {
super(StrUtil.format(msg, arguments));
this.code = code;
this.msg = StrUtil.format(msg, arguments);
}
}

View File

@@ -0,0 +1,50 @@
package mjkf.xinke.common.handler;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import mjkf.xinke.common.util.CommonCryptogramUtil;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Sm4Cbc加解密
*
*
* @date 2022/9/30 15:24
**/
@MappedJdbcTypes(JdbcType.VARCHAR)
public class CommonSm4CbcTypeHandler<T> extends BaseTypeHandler<T> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, CommonCryptogramUtil.doSm4CbcEncrypt((String)parameter));
}
@SuppressWarnings("ALL")
@Override
public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
String columnValue = rs.getString(columnName);
//有一些可能是空字符
return StringUtils.isBlank(columnValue) ? (T)columnValue : (T) CommonCryptogramUtil.doSm4CbcDecrypt(columnValue);
}
@SuppressWarnings("ALL")
@Override
public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String columnValue = rs.getString(columnIndex);
return StringUtils.isBlank(columnValue) ? (T)columnValue : (T) CommonCryptogramUtil.doSm4CbcDecrypt(columnValue);
}
@SuppressWarnings("ALL")
@Override
public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String columnValue = cs.getString(columnIndex);
return StringUtils.isBlank(columnValue) ? (T)columnValue : (T) CommonCryptogramUtil.doSm4CbcDecrypt(columnValue);
}
}

View File

@@ -0,0 +1,164 @@
package mjkf.xinke.common.listener;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import mjkf.xinke.common.exception.CommonException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 通用数据变化事件中心 事件发布器
*
*
* @date 2023/3/3 10:14
**/
public class CommonDataChangeEventCenter {
// --------- 注册侦听器
private static List<CommonDataChangeListener> listenerList = new ArrayList<>();
/**
* 获取已注册的所有侦听器
* @return /
*/
public static List<CommonDataChangeListener> getListenerList() {
return listenerList;
}
/**
* 重置侦听器集合
* @param listenerList /
*/
public static void setListenerList(List<CommonDataChangeListener> listenerList) {
if(listenerList == null) {
throw new CommonException("重置的侦听器集合不可以为空");
}
CommonDataChangeEventCenter.listenerList = listenerList;
}
/**
* 注册一个侦听器
* @param listener /
*/
public static void registerListener(CommonDataChangeListener listener) {
if(listener == null) {
throw new CommonException("注册的侦听器不可以为空");
}
listenerList.add(listener);
}
/**
* 注册一组侦听器
* @param listenerList /
*/
public static void registerListenerList(List<CommonDataChangeListener> listenerList) {
if(listenerList == null) {
throw new CommonException("注册的侦听器不可以为空");
}
for (CommonDataChangeListener listener : listenerList) {
if(listener == null) {
throw new CommonException("注册的侦听器不可以为空");
}
}
CommonDataChangeEventCenter.listenerList.addAll(listenerList);
}
/**
* 移除一个侦听器
* @param listener /
*/
public static void removeListener(CommonDataChangeListener listener) {
listenerList.remove(listener);
}
/**
* 移除指定类型的所有侦听器
* @param cls /
*/
public static void removeListener(Class<? extends CommonDataChangeListener> cls) {
ArrayList<CommonDataChangeListener> listenerListCopy = new ArrayList<>(listenerList);
for (CommonDataChangeListener listener : listenerListCopy) {
if(cls.isAssignableFrom(listener.getClass())) {
listenerList.remove(listener);
}
}
}
/**
* 清空所有已注册的侦听器
*/
public static void clearListener() {
listenerList.clear();
}
/**
* 判断是否已经注册了指定侦听器
* @param listener /
* @return /
*/
public static boolean hasListener(CommonDataChangeListener listener) {
return listenerList.contains(listener);
}
/**
* 判断是否已经注册了指定类型的侦听器
* @param cls /
* @return /
*/
public static boolean hasListener(Class<? extends CommonDataChangeListener> cls) {
for (CommonDataChangeListener listener : listenerList) {
if(cls.isAssignableFrom(listener.getClass())) {
return true;
}
}
return false;
}
// --------- 事件发布-添加 --------- //
/**
* 执行添加事件发布,数据集合
*
*
* @date 2023/3/3 10:22
**/
public static void doAddWithData(String dataType, JSONArray jsonArray) {
for (CommonDataChangeListener listener : listenerList) {
listener.doAddWithDataIdList(dataType, jsonArray.stream().map(o -> JSONUtil.parseObj(o).getStr("id")).collect(Collectors.toList()));
listener.doAddWithDataList(dataType, jsonArray);
}
}
// --------- 事件发布-更新 --------- //
/**
* 执行更新事件发布,数据集合
*
*
* @date 2023/3/3 10:22
**/
public static void doUpdateWithData(String dataType, JSONArray jsonArray) {
for (CommonDataChangeListener listener : listenerList) {
listener.doUpdateWithDataIdList(dataType, jsonArray.stream().map(o -> JSONUtil.parseObj(o).getStr("id")).collect(Collectors.toList()));
listener.doUpdateWithDataList(dataType, jsonArray);
}
}
// --------- 事件发布-删除 --------- //
/**
* 执行删除事件发布ID集合
*
*
* @date 2023/3/3 10:22
**/
public static void doDeleteWithDataId(String dataType, List<String> dataIdList) {
for (CommonDataChangeListener listener : listenerList) {
listener.doDeleteWithDataIdList(dataType, dataIdList);
}
}
}

View File

@@ -0,0 +1,65 @@
package mjkf.xinke.common.listener;
import cn.hutool.json.JSONArray;
import java.util.List;
/**
* 通用数据变化侦听器你可以实现该侦听器接口在数据新增、更新、删除时进行一些AOP操作
*
*
* @date 2023/3/3 10:14
**/
public interface CommonDataChangeListener {
/**
* 执行添加ID集合
*
* @param dataType 数据类型如USER、ORG自行定义
* @param dataIdList 被添加的数据ID集合
*
* @date 2023/3/3 10:24
**/
void doAddWithDataIdList(String dataType, List<String> dataIdList);
/**
* 执行添加,数据集合
*
* @param dataType 数据类型如USER、ORG自行定义
* @param jsonArray 被添加的数据集合
*
* @date 2023/3/3 10:24
**/
void doAddWithDataList(String dataType, JSONArray jsonArray);
/**
* 执行更新ID集合
*
* @param dataType 数据类型如USER、ORG自行定义
* @param dataIdList 被更新的数据ID集合
*
* @date 2023/3/3 10:24
**/
void doUpdateWithDataIdList(String dataType, List<String> dataIdList);
/**
* 执行更新,数据集合
*
* @param dataType 数据类型如USER、ORG自行定义
* @param jsonArray 被更新的数据集合
*
* @date 2023/3/3 10:24
**/
void doUpdateWithDataList(String dataType, JSONArray jsonArray);
/**
* 执行删除ID集合
*
* @param dataType 数据类型如USER、ORG自行定义
* @param dataIdList 被删除的数据ID集合
*
* @date 2023/3/3 10:24
**/
void doDeleteWithDataIdList(String dataType, List<String> dataIdList);
}

View File

@@ -0,0 +1,68 @@
package mjkf.xinke.common.page;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import mjkf.xinke.common.util.CommonServletUtil;
import java.util.List;
/**
* 通用分页请求
*
*
* @date 2021/12/18 14:43
*/
@Slf4j
public class CommonPageRequest {
private static final String PAGE_SIZE_PARAM_NAME = "size";
private static final String PAGE_PARAM_NAME = "current";
private static final Integer PAGE_SIZE_MAX_VALUE = 100;
public static <T> Page<T> defaultPage() {
return defaultPage(null);
}
public static <T> Page<T> defaultPage(List<OrderItem> orderItemList) {
int size = 20;
int page = 1;
//每页条数
String pageSizeString = CommonServletUtil.getParamFromRequest(PAGE_SIZE_PARAM_NAME);
if (ObjectUtil.isNotEmpty(pageSizeString)) {
try {
size = Convert.toInt(pageSizeString);
if(size > PAGE_SIZE_MAX_VALUE) {
size = PAGE_SIZE_MAX_VALUE;
}
} catch (Exception e) {
log.error(">>> 分页条数转换异常:", e);
size = 20;
}
}
//第几页
String pageString = CommonServletUtil.getParamFromRequest(PAGE_PARAM_NAME);
if (ObjectUtil.isNotEmpty(pageString)) {
try {
page = Convert.toInt(pageString);
} catch (Exception e) {
log.error(">>> 分页页数转换异常:", e);
page = 1;
}
}
Page<T> objectPage = new Page<>(page, size);
if (ObjectUtil.isNotEmpty(orderItemList)) {
objectPage.setOrders(orderItemList);
}
return objectPage;
}
}

View File

@@ -0,0 +1,52 @@
package mjkf.xinke.common.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 通用基础字段实体:创建时间、创建人、修改时间、修改人,需要此通用字段的实体可继承此类,
* 继承此类要求数据表有对应的字段
* </p>
*
*
* @date 2020/3/10 16:02
*/
@Getter
@Setter
public class CommonEntity implements Serializable {
/** 删除标志 */
@TableLogic
@ApiModelProperty(value = "删除标志", position = 999)
@TableField(fill = FieldFill.INSERT)
private String deleteFlag;
/** 创建时间 */
@ApiModelProperty(value = "创建时间", position = 1000)
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/** 创建人 */
@ApiModelProperty(value = "创建人", position = 1001)
@TableField(fill = FieldFill.INSERT)
private String createUser;
/** 更新时间 */
@ApiModelProperty(value = "更新时间", position = 1002)
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
/** 更新人 */
@ApiModelProperty(value = "更新人", position = 1003)
@TableField(fill = FieldFill.UPDATE)
private String updateUser;
}

View File

@@ -0,0 +1,149 @@
package mjkf.xinke.common.pojo;
import io.swagger.annotations.ApiModelProperty;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.service.ResponseMessage;
import mjkf.xinke.common.enums.CommonExceptionEnum;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 对Ajax请求返回Json格式数据的简易封装
*
*
* @date 2022/8/15 16:08
**/
public class CommonResult<T> implements Serializable{
private static final long serialVersionUID = 1L;
public static final int CODE_SUCCESS = 200;
public static final int CODE_ERROR = 500;
@ApiModelProperty(value = "状态码")
private int code;
@ApiModelProperty(value = "提示语")
private String msg;
@ApiModelProperty(value = "返回数据")
private T data;
public CommonResult() {
}
public CommonResult(int code, String msg, T data) {
this.setCode(code);
this.setMsg(msg);
this.setData(data);
}
/**
* 获取code
* @return code
*/
public Integer getCode() {
return this.code;
}
/**
* 获取msg
* @return msg
*/
public String getMsg() {
return this.msg;
}
/**
* 获取data
* @return data
*/
public T getData() {
return this.data;
}
/**
* 给code赋值连缀风格
* @param code code
* @return 对象自身
*/
public CommonResult<T> setCode(int code) {
this.code = code;
return this;
}
/**
* 给msg赋值连缀风格
* @param msg msg
* @return 对象自身
*/
public CommonResult<T> setMsg(String msg) {
this.msg = msg;
return this;
}
/**
* 给data赋值连缀风格
* @param data data
* @return 对象自身
*/
public CommonResult<T> setData(T data) {
this.data = data;
return this;
}
// ============================ 构建 ==================================
// 构建成功
public static <T> CommonResult<T> ok() {
return new CommonResult<>(CODE_SUCCESS, "操作成功", null);
}
public static <T> CommonResult<T> ok(String msg) {
return new CommonResult<>(CODE_SUCCESS, msg, null);
}
public static <T> CommonResult<T> code(int code) {
return new CommonResult<>(code, null, null);
}
public static <T> CommonResult<T> data(T data) {
return new CommonResult<>(CODE_SUCCESS, "操作成功", data);
}
// 构建失败
public static <T> CommonResult<T> error() {
return new CommonResult<>(CODE_ERROR, "服务器异常", null);
}
public static <T> CommonResult<T> error(String msg) {
return new CommonResult<>(CODE_ERROR, msg, null);
}
// 构建指定状态码
public static <T> CommonResult<T> get(int code, String msg, T data) {
return new CommonResult<>(code, msg, data);
}
/*
* toString()
*/
@Override
public String toString() {
return "{"
+ "\"code\": " + this.getCode()
+ ", \"msg\": \"" + this.getMsg() + "\""
+ ", \"data\": \"" + this.getData() + "\""
+ "}";
}
/**
* 响应状态码集合
*
*
* @date 2022/7/25 13:36
**/
public static List<ResponseMessage> responseList() {
return Arrays.stream(CommonExceptionEnum.values()).map(commonExceptionEnum -> new ResponseMessageBuilder()
.code(commonExceptionEnum.getCode()).message(commonExceptionEnum.getMessage()).build())
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,135 @@
package mjkf.xinke.common.pojo;
import lombok.Data;
import javax.validation.Valid;
import java.util.*;
/**
* 可被校验的通用List
*
*
* @date 2022/7/28 16:08
**/
@Data
public class CommonValidList<E> implements List<E> {
@Valid
private List<E> list = new LinkedList<>();
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
@Override
public boolean add(E e) {
return list.add(e);
}
@Override
public boolean remove(Object o) {
return list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return list.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
@Override
public void clear() {
list.clear();
}
@Override
public E get(int index) {
return list.get(index);
}
@Override
public E set(int index, E element) {
return list.set(index, element);
}
@Override
public void add(int index, E element) {
list.add(index, element);
}
@Override
public E remove(int index) {
return list.remove(index);
}
@Override
public int indexOf(Object o) {
return list.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
@Override
public ListIterator<E> listIterator() {
return list.listIterator();
}
@Override
public ListIterator<E> listIterator(int index) {
return list.listIterator(index);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
}

View File

@@ -0,0 +1,21 @@
package mjkf.xinke.common.pojo;
import cn.hutool.json.JSONObject;
/**
* 通用包装接口
*
*
* @date 2022/9/15 21:17
*/
public interface CommonWrapperInterface<T> {
/**
* 执行包装
*
*
* @date 2022/9/15 21:17
*/
JSONObject doWrap(T wrapperObject);
}

View File

@@ -0,0 +1,26 @@
package mjkf.xinke.common.prop;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 通用基础配置
*
*
* @date 2022/1/2 17:03
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "mjkf-xinke.config.common")
public class CommonProperties {
/** 前端地址 */
private String frontUrl;
/** 后端地址 */
private String backendUrl;
}

View File

@@ -0,0 +1,20 @@
package mjkf.xinke.common.sse;
import lombok.Getter;
import lombok.Setter;
/**
* 通用SSE参数
*
* @author diantu
* @date 2023/7/10
*/
@Getter
@Setter
public class CommonSseParam {
private String clientId;
private String loginId;
}

View File

@@ -0,0 +1,19 @@
package mjkf.xinke.common.timer;
/**
* 定时器执行者定时器都要实现本接口并需要把实现类加入到spring容器中
*
*
* @date 2022/8/15 16:09
**/
public interface CommonTimerTaskRunner {
/**
* 任务执行的具体内容
*
*
* @date 2022/8/15 16:09
**/
void action();
}

View File

@@ -0,0 +1,115 @@
package mjkf.xinke.common.util;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 通用头像工具类,生成文字头像
*
*
* @date 2022/7/5 17:36
**/
public class CommonAvatarUtil {
/**
* 绘制字体头像,如果是英文名,只显示首字母大写,
* 如果是中文名,只显示最后两个字
* 返回图片base64
*
*
* @date 2022/7/5 17:36
**/
public static String generateImg(String name) {
int width = 100;
int height = 100;
int nameLength = name.length();
String nameWritten;
// 如果用户输入的姓名少于等于2个字符不用截取
if (nameLength <= 2) {
nameWritten = name;
} else {
// 如果用户输入的姓名大于等于3个字符截取后面两位
String first = StrUtil.sub(name, 0, 1);
if (isChinese(first)) {
// 截取倒数两位汉字
nameWritten = name.substring(nameLength - 2);
} else {
// 截取前面的两个英文字母
nameWritten = StrUtil.sub(name, 0, 1).toUpperCase();
}
}
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D) bufferedImage.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setBackground(getRandomColor());
g2.clearRect(0, 0, width, height);
g2.setPaint(Color.WHITE);
Font font;
// 两个字及以上
if(nameWritten.length() >= 2) {
font = new Font("微软雅黑", Font.BOLD, 30);
g2.setFont(font);
String firstWritten = StrUtil.sub(nameWritten, 0, 1);
String secondWritten = StrUtil.sub(nameWritten, 0, 2);
// 两个中文 如 言曌
if (isChinese(firstWritten) && isChinese(secondWritten)) {
g2.drawString(nameWritten, 20, 60);
}
// 首中次英 如 罗Q
else if (isChinese(firstWritten) && !isChinese(secondWritten)) {
g2.drawString(nameWritten, 27, 60);
// 首英 如 AB
} else {
nameWritten = nameWritten.substring(0,1);
}
}
// 一个字
if(nameWritten.length() == 1) {
// 中文
if(isChinese(nameWritten)) {
font = new Font("微软雅黑", Font.PLAIN, 50);
g2.setFont(font);
g2.drawString(nameWritten, 25, 70);
} else {
font = new Font("微软雅黑", Font.PLAIN, 55);
g2.setFont(font);
g2.drawString(nameWritten.toUpperCase(), 33, 67);
}
}
return ImgUtil.toBase64DataUri(bufferedImage, "jpg");
}
/**
* 获得随机颜色
*
*
* @date 2022/7/5 17:41
**/
private static Color getRandomColor() {
String[] beautifulColors =
new String[]{"114,101,230", "255,191,0", "0,162,174", "245,106,0", "24,144,255", "96,109,128"};
String[] color = beautifulColors[RandomUtil.randomInt(beautifulColors.length)].split(StrUtil.COMMA);
return new Color(Integer.parseInt(color[0]), Integer.parseInt(color[1]),
Integer.parseInt(color[2]));
}
/**
* 判断字符串是否为中文
*
*
* @date 2022/7/5 17:41
**/
private static boolean isChinese(String str) {
String regEx = "[\\u4e00-\\u9fa5]+";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
return m.find();
}
}

View File

@@ -0,0 +1,131 @@
package mjkf.xinke.common.util;
import com.antherd.smcrypto.sm2.Sm2;
import com.antherd.smcrypto.sm3.Sm3;
import com.antherd.smcrypto.sm4.Sm4;
import com.antherd.smcrypto.sm4.Sm4Options;
import lombok.extern.slf4j.Slf4j;
/**
* 加密工具类,本框架目前使用 https://github.com/antherd/sm-crypto 项目中一些加解密方式
* 使用小伙伴需要过等保密评相关,请在此处更改为自己的加密方法,或加密机,使用加密机同时需要替换公钥,私钥在内部无法导出,提供加密的方法
* 如果不涉及到加密机方面的内容请更改公私要为自己重新生成的生成方式请看集成的sm-crypto主页
*
*
* @date 2022/9/15 21:51
*/
@Slf4j
public class CommonCryptogramUtil {
/** 公钥 */
private static final String PUBLIC_KEY = "04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54";
/** 私钥 */
private static final String PRIVATE_KEY = "3037723d47292171677ec8bd7dc9af696c7472bc5f251b2cec07e65fdef22e25";
/** SM4的对称秘钥生产环境需要改成自己使用的 16 进制字符串,要求为 128 比特 */
private static final String KEY = "0123456789abcdeffedcba9876543210";
/**
* 加密方法Sm2 的专门针对前后端分离,非对称秘钥对的方式,暴露出去的公钥,对传输过程中的密码加个密)
*
*
* @date 2022/9/15 21:51
* @param str 待加密数据
* @return 加密后的密文
*/
public static String doSm2Encrypt(String str) {
return Sm2.doEncrypt(str, PUBLIC_KEY);
}
/**
* 解密方法
* 如果采用加密机的方法用try catch 捕捉异常,返回原文值即可
*
*
* @date 2022/9/15 21:51
* @param str 密文
* @return 解密后的明文
*/
public static String doSm2Decrypt(String str) {
// 解密
return Sm2.doDecrypt(str, PRIVATE_KEY);
}
/**
* 加密方法
*
*
* @date 2022/9/15 21:51
* @param str 待加密数据
* @return 加密后的密文
*/
public static String doSm4CbcEncrypt(String str) {
// SM4 加密 cbc模式
Sm4Options sm4Options4 = new Sm4Options();
sm4Options4.setMode("cbc");
sm4Options4.setIv("fedcba98765432100123456789abcdef");
return Sm4.encrypt(str, KEY, sm4Options4);
}
/**
* 解密方法
* 如果采用加密机的方法用try catch 捕捉异常,返回原文值即可
*
*
* @date 2022/9/15 21:51
* @param str 密文
* @return 解密后的明文
*/
public static String doSm4CbcDecrypt(String str) {
// 解密cbc 模式,输出 utf8 字符串
Sm4Options sm4Options8 = new Sm4Options();
sm4Options8.setMode("cbc");
sm4Options8.setIv("fedcba98765432100123456789abcdef");
String docString = Sm4.decrypt(str, KEY, sm4Options8);
if ("".equals(docString)) {
log.warn(">>> 字段解密失败,返回原文值:{}", str);
return str;
} else {
return docString;
}
}
/**
* 纯签名
*
*
* @date 2022/9/15 21:51
* @param str 待签名数据
* @return 签名结果
*/
public static String doSignature(String str) {
return Sm2.doSignature(str, PRIVATE_KEY);
}
/**
* 验证签名结果
*
*
* @date 2022/9/15 21:51
* @param originalStr 签名原文数据
* @param str 签名结果
* @return 是否通过
*/
public static boolean doVerifySignature(String originalStr, String str) {
return Sm2.doVerifySignature(originalStr, str, PUBLIC_KEY);
}
/**
* 通过杂凑算法取得hash值用于做数据完整性保护
*
*
* @date 2022/9/15 21:51
* @param str 字符串
* @return hash 值
*/
public static String doHashValue(String str) {
return Sm3.sm3(str);
}
}

View File

@@ -0,0 +1,52 @@
package mjkf.xinke.common.util;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.URLUtil;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
/**
* 文件下载工具类使用本类前对参数校验的异常使用CommonResponseUtil.renderError()方法进行渲染
*
*
* @date 2020/8/5 21:45
*/
@Slf4j
public class CommonDownloadUtil {
/**
* 下载文件
*
* @param file 要下载的文件
* @param response 响应
*
* @date 2020/8/5 21:46
*/
public static void download(File file, HttpServletResponse response) {
download(file.getName(), FileUtil.readBytes(file), response);
}
/**
* 下载文件
*
*
* @date 2022/7/31 10:57
*/
public static void download(String fileName, byte[] fileBytes, HttpServletResponse response) {
try {
response.setHeader("Content-Disposition", "attachment;filename=" + URLUtil.encode(fileName));
response.addHeader("Content-Length", "" + fileBytes.length);
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setContentType("application/octet-stream;charset=UTF-8");
IoUtil.write(response.getOutputStream(), true, fileBytes);
} catch (IOException e) {
log.error(">>> 文件下载异常:", e);
}
}
}

View File

@@ -0,0 +1,39 @@
package mjkf.xinke.common.util;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import mjkf.xinke.common.exception.CommonException;
/**
* 通用邮件工具类
*
*
* @date 2022/8/25 15:10
**/
public class CommonEmailUtil {
/**
* 判断是否邮箱
*
*
* @date 2022/8/15 13:32
**/
public static boolean isEmail(String email) {
return Validator.isEmail(email);
}
/**
* 校验邮箱格式
*
*
* @date 2022/8/15 13:32
**/
public static void validEmail(String emails) {
StrUtil.split(emails, StrUtil.COMMA).forEach(email -> {
if(!isEmail(email)) {
throw new CommonException("邮件地址:{}格式错误", email);
}
});
}
}

View File

@@ -0,0 +1,29 @@
package mjkf.xinke.common.util;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* 过滤器异常工具类,用于处理过滤器中的异常
* 原理:将异常转发到/errorView进行处理
*
*
* @date 2022/7/18 18:59
**/
public class CommonFilterExceptionUtil {
/**
* 处理过滤器中的异常
*
*
* @date 2022/7/18 19:00
**/
public static void handleFilterException(ServletRequest request, ServletResponse response, Exception e) {
try {
request.setAttribute("model", e);
request.getRequestDispatcher("/errorView").forward(request, response);
} catch (Exception ignored) {
}
}
}

View File

@@ -0,0 +1,94 @@
package mjkf.xinke.common.util;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.Ipv4Util;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import mjkf.xinke.common.exception.CommonException;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.InputStream;
/**
* 根据ip地址定位工具类离线方式
* 参考地址https://gitee.com/lionsoul/ip2region/tree/master/binding/java
*
*
* @date 2020/3/16 11:25
*/
@Slf4j
public class CommonIpAddressUtil {
private static final String LOCAL_REMOTE_HOST = "0:0:0:0:0:0:0:1";
private static final Searcher searcher;
static {
String fileName = "/ip2region.xdb";
File existFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);
if(!FileUtil.exist(existFile)) {
InputStream resourceAsStream = CommonIpAddressUtil.class.getResourceAsStream(fileName);
FileUtil.writeFromStream(resourceAsStream, existFile);
}
String dbPath = existFile.getPath();
// 1、从 dbPath 加载整个 xdb 到内存。
byte[] cBuff;
try {
cBuff = Searcher.loadContentFromFile(dbPath);
} catch (Exception e) {
log.error(">>> CommonIpAddressUtil初始化异常", e);
throw new CommonException("CommonIpAddressUtil初始化异常");
}
// 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
try {
searcher = Searcher.newWithBuffer(cBuff);
} catch (Exception e) {
log.error(">>> CommonIpAddressUtil初始化异常", e);
throw new CommonException("CommonIpAddressUtil初始化异常");
}
}
/**
* 获取客户端ip
*
*
* @date 2020/3/19 9:32
*/
public static String getIp(HttpServletRequest request) {
if (ObjectUtil.isEmpty(request)) {
return Ipv4Util.LOCAL_IP;
} else {
try {
String remoteHost = ServletUtil.getClientIP(request);
return LOCAL_REMOTE_HOST.equals(remoteHost) ? Ipv4Util.LOCAL_IP : remoteHost;
} catch (Exception e) {
log.error(">>> 获取客户端ip异常", e);
return Ipv4Util.LOCAL_IP;
}
}
}
/**
* 根据IP地址离线获取城市
*
*
* @date 2022/4/27 23:14
*/
public static String getCityInfo(String ip) {
try {
ip = ip.trim();
// 3、执行查询
String region = searcher.searchByStr(ip);
return region.replace("0|", "").replace("|0", "");
} catch (Exception e) {
return "未知";
}
}
}

View File

@@ -0,0 +1,61 @@
package mjkf.xinke.common.util;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* Spring切面工具类
*
*
* @date 2022/9/2 15:51
*/
public class CommonJoinPointUtil {
/**
* 获取切面的参数JSON
*
*
* @date 2022/9/2 15:51
*/
public static String getArgsJsonString(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
// 参数名数组
String[] parameterNames = ((MethodSignature) signature).getParameterNames();
// 构造参数组集合
Map<String, Object> map = MapUtil.newHashMap();
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
if(ObjectUtil.isNotEmpty(args[i]) && isUsefulParam(args[i])) {
if(JSONUtil.isTypeJSON(StrUtil.toString(args[i]))) {
map.put(parameterNames[i], JSONUtil.parseObj(args[i]));
} else {
map.put(parameterNames[i], JSONUtil.toJsonStr(args[i]));
}
}
}
return JSONUtil.toJsonStr(map);
}
/**
* 判断是否需要拼接的参数过滤掉HttpServletRequest,MultipartFile,HttpServletResponse等类型参数
*
*
* @date 2022/9/2 15:51
*/
private static boolean isUsefulParam(Object arg) {
return !(arg instanceof MultipartFile) &&
!(arg instanceof HttpServletRequest) &&
!(arg instanceof HttpServletResponse);
}
}

View File

@@ -0,0 +1,114 @@
package mjkf.xinke.common.util;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.system.SystemUtil;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
/**
* 通用获取当前网速工具类
*
*
* @date 2022/9/1 23:45
*/
@Slf4j
public class CommonNetWorkInfoUtil {
/**
* 网速测速时间2s
*/
private static final int SLEEP_SECONDS = 2;
/**
* 获取网络上下行速率,格式{"UP": "123KB/S, "DOWN": "345KB/S"}
*
*
* @date 2022/9/1 23:51
*/
public static Map<String, String> getNetworkUpRate() {
Map<String, String> result = new HashMap<>();
Process pro = null;
Runtime r = Runtime.getRuntime();
BufferedReader input = null;
try {
boolean isWindows = SystemUtil.getOsInfo().isWindows();
String command = isWindows ? "netstat -e" : "ifconfig";
pro = r.exec(command);
input = new BufferedReader(new InputStreamReader(pro.getInputStream()));
long[] result1 = readInLine(input, isWindows);
Thread.sleep(SLEEP_SECONDS * 1000);
pro.destroy();
input.close();
pro = r.exec(command);
input = new BufferedReader(new InputStreamReader(pro.getInputStream()));
long[] result2 = readInLine(input, isWindows);
String upSpeed = FileUtil.readableFileSize(Convert.toLong(NumberUtil
.div(NumberUtil.sub(result2[0], result1[0]), SLEEP_SECONDS)));
String downSpeed = FileUtil.readableFileSize(Convert.toLong(NumberUtil
.div(NumberUtil.sub(result2[1], result1[1]), SLEEP_SECONDS)));
result.put("UP", upSpeed + (upSpeed.endsWith("B")?"/S":"B/S"));
result.put("DOWN", downSpeed + (downSpeed.endsWith("B")?"/S":"B/S"));
} catch (Exception e) {
log.info(">>> 网络测速失败:", e);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
log.info(">>> 网络测速失败:", e);
}
}
Optional.ofNullable(pro).ifPresent(Process::destroy);
}
return result;
}
private static String formatNumber(double f) {
return new Formatter().format("%.2f", f).toString();
}
private static long[] readInLine(BufferedReader input, boolean isWindows) {
long[] arr = new long[2];
StringTokenizer tokenStat;
try {
if (isWindows) {
// 获取windows环境下的网口上下行速率
input.readLine();
input.readLine();
input.readLine();
input.readLine();
tokenStat = new StringTokenizer(input.readLine());
tokenStat.nextToken();
arr[0] = Long.parseLong(tokenStat.nextToken());
arr[1] = Long.parseLong(tokenStat.nextToken());
} else {
// 获取linux环境下的网口上下行速率
long rx = 0, tx = 0;
String line = null;
//RX packets:4171603 errors:0 dropped:0 overruns:0 frame:0
//TX packets:4171603 errors:0 dropped:0 overruns:0 carrier:0
while ((line = input.readLine()) != null) {
if (line.contains("RX packets")) {
rx += Long.parseLong(line.substring(line.indexOf("RX packets") + 11, line.indexOf(" ",
line.indexOf("RX packets") + 11)));
} else if (line.contains("TX packets")) {
tx += Long.parseLong(line.substring(line.indexOf("TX packets") + 11, line.indexOf(" ",
line.indexOf("TX packets") + 11)));
}
}
arr[0] = rx;
arr[1] = tx;
}
} catch (Exception e) {
log.error(">>> 网络测速异常:", e);
}
return arr;
}
}

View File

@@ -0,0 +1,54 @@
package mjkf.xinke.common.util;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.ContentType;
import cn.hutool.json.JSONUtil;
import mjkf.xinke.common.pojo.CommonResult;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 通用响应工具类
*
*
* @date 2022/8/4 9:40
**/
public class CommonResponseUtil {
/**
* 以流的方式响应错误信息,默认错误消息
*
*
* @date 2022/8/4 9:41
**/
public static void renderError(HttpServletResponse response) throws IOException {
renderError(response, null);
}
/**
* 以流的方式响应错误信息,指定错误消息
*
*
* @date 2022/8/4 9:41
**/
public static void renderError(HttpServletResponse response, String msg) throws IOException {
response.setCharacterEncoding(CharsetUtil.UTF_8);
response.setContentType(ContentType.JSON.toString());
response.getWriter().write(JSONUtil.toJsonStr(ObjectUtil.isNotEmpty(msg)?CommonResult.error(msg):CommonResult.error()));
}
/**
* 以流的方式响应错误信息,指定错误码和错误消息
*
*
* @date 2022/8/4 9:41
**/
public static void renderError(HttpServletResponse response, Integer code, String msg) throws IOException {
response.setCharacterEncoding(CharsetUtil.UTF_8);
response.setContentType(ContentType.JSON.toString());
response.getWriter().write(JSONUtil.toJsonStr(CommonResult.get(code, msg, null)));
}
}

View File

@@ -0,0 +1,88 @@
package mjkf.xinke.common.util;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import mjkf.xinke.common.exception.CommonException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* HttpServlet工具类获取当前request和response
*
*
* @date 2020/3/30 15:09
*/
@Slf4j
public class CommonServletUtil {
/**
* 从请求中中获取参数
*
*
* @date 2021/10/14 10:44
**/
public static String getParamFromRequest(String paramName) {
HttpServletRequest request = getRequest();
// 1. 尝试从请求体里面读取
String paramValue = request.getParameter(paramName);
// 2. 尝试从header里读取
if (ObjectUtil.isEmpty(paramValue)) {
paramValue = request.getHeader(paramName);
}
// 3. 尝试从cookie里读取
if (ObjectUtil.isEmpty(paramValue)) {
Cookie[] cookies = request.getCookies();
if(ObjectUtil.isNotEmpty(cookies)) {
for (Cookie cookie : cookies) {
String cookieName = cookie.getName();
if (cookieName.equals(paramName)) {
return cookie.getValue();
}
}
}
}
// 4. 返回
return paramValue;
}
public static HttpServletRequest getRequest() {
ServletRequestAttributes servletRequestAttributes;
try {
servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
} catch (Exception e) {
log.error(">>> 非Web上下文无法获取Request", e);
throw new CommonException("非Web上下文无法获取Request");
}
if (servletRequestAttributes == null) {
throw new CommonException("非Web上下文无法获取Request");
} else {
return servletRequestAttributes.getRequest();
}
}
public static HttpServletResponse getResponse() {
ServletRequestAttributes servletRequestAttributes;
try {
servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
} catch (Exception e) {
log.error(">>> 非Web上下文无法获取Response", e);
throw new CommonException("非Web上下文无法获取Response");
}
if (servletRequestAttributes == null) {
throw new CommonException("非Web上下文无法获取Response");
} else {
return servletRequestAttributes.getResponse();
}
}
public static boolean isWeb() {
return RequestContextHolder.getRequestAttributes() != null;
}
}

View File

@@ -0,0 +1,172 @@
package mjkf.xinke.common.util;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import java.util.Date;
/**
* 时间格式化工具类
*
*
* @date 2022/6/24 15:28
**/
public class CommonTimeFormatUtil {
private static final long ONE_MINUTE_SECONDS = 60;
private static final int BEFORE_DAWN_HOUR = 6;
private static final int MORNING_END_HOUR = 12;
private static final int NOON_END_HOUR = 13;
private static final int AFTERNOON_END_HOUR = 18;
private static final int NIGHT_END_HOUR = 24;
/**
* 将日期格式化为仿微信的日期
*
*
* @date 2022/6/24 15:28
**/
public static String formatWxPastTime(Date date) {
if (DateUtil.between(date, DateUtil.date(), DateUnit.SECOND, false) < 0) {
//今天之后的时间显示年月日时分
return DateUtil.format(date, DatePattern.NORM_DATETIME_MINUTE_PATTERN);
} else {
//如果是今年
if (DateUtil.thisYear() == DateUtil.year(date)) {
//如果是今天
if (DateUtil.isSameDay(date, DateUtil.date())) {
//相差分钟数
long betweenMinute = DateUtil.between(date, DateUtil.date(), DateUnit.MINUTE);
//如果在1小时之内
if (betweenMinute < ONE_MINUTE_SECONDS) {
//一分钟之内,显示刚刚
if (betweenMinute < 1) {
return "刚刚";
} else {
//一分钟之外显示xx分钟前
return betweenMinute + "分钟前";
}
} else {
//一小时之外,显示时分
return getTodayHour(date) + " " + DateUtil.format(date, "HH:mm");
}
} else if (DateUtil.isSameDay(date, DateUtil.yesterday())) {
//如果是昨天,显示昨天时分
return "昨天 " + DateUtil.format(date, "HH:mm");
} else if (isThisWeek(date)) {
//如果是本周
String weekday;
//获取是本周的第几天
int dayOfWeek = DateUtil.dayOfWeek(date) - 1;
switch (dayOfWeek) {
case 1:
weekday = "周一";
break;
case 2:
weekday = "周二";
break;
case 3:
weekday = "周三";
break;
case 4:
weekday = "周四";
break;
case 5:
weekday = "周五";
break;
case 6:
weekday = "周六";
break;
default:
weekday = "周日";
break;
}
//显示本周时分
return weekday + " " + DateUtil.format(date, "HH:mm");
} else {
//否则显示月日时分
return DateUtil.format(date, "MM-dd HH:mm");
}
} else {
//本年之外显示年月日时分
return DateUtil.format(date, DatePattern.NORM_DATETIME_MINUTE_PATTERN);
}
}
}
/**
* 将秒数格式化为天时分秒
*
*
* @date 2022/6/24 15:29
**/
public static String formatSeconds(long secondsParam) {
String result;
long days = secondsParam / ( ONE_MINUTE_SECONDS * ONE_MINUTE_SECONDS * NIGHT_END_HOUR);
long hours = (secondsParam % ( ONE_MINUTE_SECONDS * ONE_MINUTE_SECONDS * NIGHT_END_HOUR)) / (ONE_MINUTE_SECONDS * ONE_MINUTE_SECONDS);
long minutes = (secondsParam % ( ONE_MINUTE_SECONDS * ONE_MINUTE_SECONDS)) /ONE_MINUTE_SECONDS;
long seconds = secondsParam % ONE_MINUTE_SECONDS;
if(days > 0) {
result = days + "" + hours + "小时" + minutes + "分钟" + seconds + "";
} else if(hours > 0) {
result = hours + "小时" + minutes + "分钟" + seconds + "";
} else if(minutes > 0) {
result = minutes + "分钟" + seconds + "";
} else {
result = seconds + "";
}
return result;
}
/**
* 判断日期是否是本周
*
* @param date 要判断的日期
* @return boolean
*
* @date 2020/8/6 12:10
**/
private static boolean isThisWeek(Date date) {
//获取本周开始时间
DateTime beginOfWeek = DateUtil.beginOfWeek(DateUtil.date());
//获取与本周开始时间相差的天数
long betweenBegin = DateUtil.between(date, beginOfWeek, DateUnit.DAY, false) + 1;
//如果是同一天或相差天数小于0则是本周
return DateUtil.isSameDay(date, beginOfWeek) || betweenBegin < 0;
}
/**
* 根据今天日期获取早中晚
*
*
* @date 2020/8/6 14:42
**/
private static String getTodayHour(Date date) {
String result = "";
int hour = DateUtil.hour(date, true);
if (hour >= 0 && hour <= BEFORE_DAWN_HOUR) {
result = "凌晨";
}
if (hour > BEFORE_DAWN_HOUR && hour < MORNING_END_HOUR) {
result = "上午";
}
if (hour == MORNING_END_HOUR) {
result = "中午";
}
if (hour >= NOON_END_HOUR && hour <= AFTERNOON_END_HOUR) {
result = "下午";
}
if (hour > AFTERNOON_END_HOUR && hour <= NIGHT_END_HOUR) {
result = "晚上";
}
return result;
}
}

View File

@@ -0,0 +1,69 @@
package mjkf.xinke.common.util;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.Browser;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import javax.servlet.http.HttpServletRequest;
/**
* 用户代理工具类
*
*
* @date 2022/9/2 15:34
*/
public class CommonUaUtil {
/**
* 获取客户端浏览器
*
*
* @date 2020/3/19 14:53
*/
public static String getBrowser(HttpServletRequest request) {
UserAgent userAgent = getUserAgent(request);
if (ObjectUtil.isEmpty(userAgent)) {
return StrUtil.DASHED;
} else {
String browser = userAgent.getBrowser().toString();
return "Unknown".equals(browser) ? StrUtil.DASHED : browser;
}
}
/**
* 获取客户端操作系统
*
*
* @date 2022/9/2 15:36
*/
public static String getOs(HttpServletRequest request) {
UserAgent userAgent = getUserAgent(request);
if (ObjectUtil.isEmpty(userAgent)) {
return StrUtil.DASHED;
} else {
String os = userAgent.getOs().toString();
return "Unknown".equals(os) ? StrUtil.DASHED : os;
}
}
/**
* 获取请求代理头
*
*
* @date 2022/9/2 15:36
*/
private static UserAgent getUserAgent(HttpServletRequest request) {
String userAgentStr = ServletUtil.getHeaderIgnoreCase(request, "User-Agent");
UserAgent userAgent = UserAgentUtil.parse(userAgentStr);
if (ObjectUtil.isNotEmpty(userAgentStr)) {
if ("Unknown".equals(userAgent.getBrowser().getName())) {
userAgent.setBrowser(new Browser(userAgentStr, null, ""));
}
}
return userAgent;
}
}

Binary file not shown.