🎉 添加工具类
This commit is contained in:
parent
269dd51d6e
commit
02d7d63276
@ -1,4 +1,4 @@
|
||||
package com.darkness.common.pojo;
|
||||
package com.darkness.common;
|
||||
|
||||
/**
|
||||
* 公共常量类
|
104
src/main/java/com/darkness/common/util/Base64Utils.java
Normal file
104
src/main/java/com/darkness/common/util/Base64Utils.java
Normal file
@ -0,0 +1,104 @@
|
||||
package com.darkness.common.util;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class Base64Utils {
|
||||
|
||||
/**
|
||||
* BASE64编码解码工具包
|
||||
* 依赖javabase64-1.3.1.jar
|
||||
*
|
||||
* @date 2012-5-19
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* 文件读取缓冲区大小
|
||||
*/
|
||||
private static final int CACHE_SIZE = 1024;
|
||||
|
||||
/**
|
||||
* BASE64字符串解码为二进制数据
|
||||
*/
|
||||
public static byte[] decode(String base64) throws Exception {
|
||||
return Base64.decodeBase64(base64.getBytes());
|
||||
// return Base64.decode(base64.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 二进制数据编码为BASE64字符串
|
||||
*/
|
||||
public static String encode(byte[] bytes) throws Exception {
|
||||
return new String(Base64.encodeBase64(bytes));
|
||||
// return new String(Base64.encode(bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文件编码为BASE64字符串
|
||||
* 大文件慎用,可能会导致内存溢出
|
||||
*
|
||||
* @param filePath 文件绝对路径
|
||||
*/
|
||||
public static String encodeFile(String filePath) throws Exception {
|
||||
byte[] bytes = fileToByte(filePath);
|
||||
return encode(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* BASE64字符串转回文件
|
||||
* @param filePath 文件绝对路径
|
||||
* @param base64 编码字符串
|
||||
*/
|
||||
public static void decodeToFile(String filePath, String base64) throws Exception {
|
||||
byte[] bytes = decode(base64);
|
||||
byteArrayToFile(bytes, filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件转换为二进制数组
|
||||
* @param filePath 文件路径
|
||||
*/
|
||||
public static byte[] fileToByte(String filePath) throws Exception {
|
||||
byte[] data = new byte[0];
|
||||
File file = new File(filePath);
|
||||
if (file.exists()) {
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
|
||||
byte[] cache = new byte[CACHE_SIZE];
|
||||
int nRead = 0;
|
||||
while ((nRead = in.read(cache)) != -1) {
|
||||
out.write(cache, 0, nRead);
|
||||
out.flush();
|
||||
}
|
||||
out.close();
|
||||
in.close();
|
||||
data = out.toByteArray();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 二进制数据写文件
|
||||
* @param bytes 二进制数据
|
||||
* @param filePath 文件生成目录
|
||||
*/
|
||||
public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
|
||||
InputStream in = new ByteArrayInputStream(bytes);
|
||||
File destFile = new File(filePath);
|
||||
if (!destFile.getParentFile().exists()) {
|
||||
destFile.getParentFile().mkdirs();
|
||||
}
|
||||
destFile.createNewFile();
|
||||
OutputStream out = new FileOutputStream(destFile);
|
||||
byte[] cache = new byte[CACHE_SIZE];
|
||||
int nRead = 0;
|
||||
while ((nRead = in.read(cache)) != -1) {
|
||||
out.write(cache, 0, nRead);
|
||||
out.flush();
|
||||
}
|
||||
out.close();
|
||||
in.close();
|
||||
}
|
||||
}
|
51
src/main/java/com/darkness/common/util/CamelCaseUtil.java
Normal file
51
src/main/java/com/darkness/common/util/CamelCaseUtil.java
Normal file
@ -0,0 +1,51 @@
|
||||
package com.darkness.common.util;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class CamelCaseUtil {
|
||||
|
||||
/**
|
||||
* 数据表字段名转换为驼峰式名字的实体类属性名
|
||||
* @param tabAttr 数据表字段名
|
||||
* @return 转换后的驼峰式命名
|
||||
*/
|
||||
public static String camelize(String tabAttr){
|
||||
if(isBlank(tabAttr))
|
||||
return tabAttr;
|
||||
Pattern pattern = Pattern.compile("(.*)_(\\w)(.*)");
|
||||
Matcher matcher = pattern.matcher(tabAttr);
|
||||
if(matcher.find()){
|
||||
return camelize(matcher.group(1) + matcher.group(2).toUpperCase() + matcher.group(3));
|
||||
}else{
|
||||
return tabAttr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰式的实体类属性名转换为数据表字段名
|
||||
* @param camelCaseStr 驼峰式的实体类属性名
|
||||
* @return 转换后的以"_"分隔的数据表字段名
|
||||
*/
|
||||
public static String decamelize(String camelCaseStr){
|
||||
return isBlank(camelCaseStr) ? camelCaseStr : camelCaseStr.replaceAll("[A-Z]", "_$0").toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串是否为空
|
||||
* @param cs 待检查的字符串
|
||||
* @return 空:true; 非空:false
|
||||
*/
|
||||
public static boolean isBlank(final CharSequence cs) {
|
||||
int strLen;
|
||||
if (cs == null || (strLen = cs.length()) == 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < strLen; i++) {
|
||||
if (!Character.isWhitespace(cs.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
67
src/main/java/com/darkness/common/util/CryptoUtils.java
Normal file
67
src/main/java/com/darkness/common/util/CryptoUtils.java
Normal file
@ -0,0 +1,67 @@
|
||||
package com.darkness.common.util;
|
||||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.Security;
|
||||
|
||||
public class CryptoUtils {
|
||||
|
||||
static {
|
||||
if (Security.getProvider("BC") == null) {
|
||||
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
|
||||
} else {
|
||||
Security.removeProvider("BC");
|
||||
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用AES-128-CBC加密模式,key需要为16位,key和iv可以相同,也可以不同!
|
||||
*/
|
||||
private static final String KEY = "UNo49jvVsvz5idwx";
|
||||
private static final String IV = "UNo49jvVsvz5idwx";
|
||||
private static Cipher cipher = null;
|
||||
private static final byte[] raw = KEY.getBytes(StandardCharsets.UTF_8);
|
||||
private static final SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
||||
private static final IvParameterSpec iv = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8));// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
|
||||
|
||||
static {
|
||||
try {
|
||||
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
|
||||
} catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密
|
||||
*/
|
||||
public static String encryptAESPkcs7(String sourceStr) throws Exception{
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
|
||||
byte[] encrypted = cipher.doFinal(sourceStr.getBytes(StandardCharsets.UTF_8));
|
||||
return Hex.encodeHexString(encrypted);
|
||||
|
||||
}
|
||||
|
||||
public static String decryptAESPkcs7(String sourceStr) throws Exception{
|
||||
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
|
||||
byte[] original = cipher.doFinal(Hex.decodeHex(sourceStr));
|
||||
return new String(original, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
// 文章参考 https://blog.csdn.net/haoyafei_/article/details/106826423
|
||||
public static void main(String[] args) throws Exception{
|
||||
String str = "3.141592653579";
|
||||
String enc = encryptAESPkcs7(str);
|
||||
String dec = decryptAESPkcs7(enc);
|
||||
System.out.println(enc);
|
||||
System.out.println(dec);
|
||||
}
|
||||
}
|
101
src/main/java/com/darkness/common/util/DateTimeUtils.java
Normal file
101
src/main/java/com/darkness/common/util/DateTimeUtils.java
Normal file
@ -0,0 +1,101 @@
|
||||
package com.darkness.common.util;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class DateTimeUtils {
|
||||
|
||||
/**
|
||||
* 计算两个日期之间相差的天数
|
||||
* @param smdate 开始时间
|
||||
* @param bdate 结束时间
|
||||
*/
|
||||
public static int daysBetween(Date smdate, Date bdate) throws ParseException {
|
||||
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
|
||||
smdate=sdf.parse(sdf.format(smdate));
|
||||
bdate=sdf.parse(sdf.format(bdate));
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(smdate);
|
||||
long time1 = cal.getTimeInMillis();
|
||||
cal.setTime(bdate);
|
||||
long time2 = cal.getTimeInMillis();
|
||||
long between_days=(time2-time1)/(1000*3600*24);
|
||||
return Integer.parseInt(String.valueOf(between_days));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算临期/超期天数
|
||||
* 临期 包括今天
|
||||
* 超期 不包括今天
|
||||
* @param endDate 截至时间
|
||||
* @param finishDate 完成时间
|
||||
*/
|
||||
public static TimeOverdueAdventPojo overdueAdvent(Date endDate, Date finishDate) throws ParseException {
|
||||
|
||||
TimeOverdueAdventPojo timeOverdueAdventPojo = new TimeOverdueAdventPojo();
|
||||
|
||||
SimpleDateFormat sdf_YMD2359 = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
|
||||
SimpleDateFormat sdf_YMDHMS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
SimpleDateFormat sdf_YMD = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
String format = sdf_YMD2359.format(endDate);
|
||||
|
||||
//当前时间
|
||||
Date nowTime = new Date(Timestamp.from(Instant.now()).getTime());
|
||||
Date endTime = new Date(sdf_YMD.parse(format).getTime());
|
||||
Date endTime_flag = new Date(sdf_YMDHMS.parse(format).getTime());
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(endTime);
|
||||
long timeEnd = cal.getTimeInMillis();
|
||||
cal.setTime(nowTime);
|
||||
long timeNow = cal.getTimeInMillis();
|
||||
|
||||
if (Objects.isNull(finishDate)){
|
||||
if (nowTime.after(endTime_flag)){
|
||||
long between_days = (timeEnd - timeNow) / (1000 * 3600 * 24);
|
||||
timeOverdueAdventPojo.setFlag((byte) 1);
|
||||
timeOverdueAdventPojo.setOaFlag("逾期");
|
||||
timeOverdueAdventPojo.setDays(Integer.parseInt(String.valueOf(between_days)));
|
||||
}else {
|
||||
long between_days = (endTime_flag.getTime() - nowTime.getTime()) / (1000 * 3600 * 24);
|
||||
timeOverdueAdventPojo.setFlag((byte) 0);
|
||||
timeOverdueAdventPojo.setOaFlag("临期");
|
||||
timeOverdueAdventPojo.setDays(Integer.parseInt(String.valueOf(between_days + 1)));
|
||||
}
|
||||
}else {
|
||||
Date finishTime = new Date(finishDate.getTime());
|
||||
cal.setTime(finishTime);
|
||||
long timeFinish = cal.getTimeInMillis();
|
||||
if (finishDate.after(endTime_flag)){
|
||||
long between_days = (timeEnd - timeFinish) / (1000 * 3600 * 24);
|
||||
timeOverdueAdventPojo.setFlag((byte) 1);
|
||||
timeOverdueAdventPojo.setOaFlag("逾期");
|
||||
timeOverdueAdventPojo.setDays(Integer.parseInt(String.valueOf(between_days)));
|
||||
}else {
|
||||
long between_days = (endTime_flag.getTime() - timeFinish) / (1000 * 3600 * 24);
|
||||
timeOverdueAdventPojo.setFlag((byte) 0);
|
||||
timeOverdueAdventPojo.setOaFlag("临期");
|
||||
timeOverdueAdventPojo.setDays(Integer.parseInt(String.valueOf(between_days + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
return timeOverdueAdventPojo;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class TimeOverdueAdventPojo {
|
||||
|
||||
private int days;
|
||||
private byte flag; //未逾期 0 逾期 1
|
||||
private String oaFlag; //临期 advent 逾期 overdue
|
||||
}
|
||||
}
|
74
src/main/java/com/darkness/common/util/EntityUtil.java
Normal file
74
src/main/java/com/darkness/common/util/EntityUtil.java
Normal file
@ -0,0 +1,74 @@
|
||||
package com.darkness.common.util;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class EntityUtil {
|
||||
|
||||
/**
|
||||
* 实体类转Map<String,Object>
|
||||
*/
|
||||
public static Map<String, Object> entityToMap(Object entity) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
Field[] fields = entity.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
result.put(field.getName(), field.get(entity));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体类中所有不为空的字段名
|
||||
*/
|
||||
public static List<String> findNotNullFields(Object obj) {
|
||||
List<String> notNullFields = new ArrayList<>();
|
||||
Class<?> clazz = obj.getClass();
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
Object value = field.get(obj);
|
||||
if (value!= null) {
|
||||
notNullFields.add(field.getName());
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return notNullFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字段名获取值
|
||||
*/
|
||||
public static Object getFieldValue(String fieldName, Object obj) throws Exception {
|
||||
Class<?> clazz = obj.getClass();
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field.get(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析json字符串为MultiValueMap
|
||||
*/
|
||||
public static MultiValueMap<String, Object> getMultiValueMap(String json) throws Exception {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
Map<String, Object> map = objectMapper.readValue(json, Map.class);
|
||||
MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
multiValueMap.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return multiValueMap;
|
||||
}
|
||||
}
|
299
src/main/java/com/darkness/common/util/FileUtils.java
Normal file
299
src/main/java/com/darkness/common/util/FileUtils.java
Normal file
@ -0,0 +1,299 @@
|
||||
package com.darkness.common.util;
|
||||
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Base64;
|
||||
|
||||
public class FileUtils {
|
||||
|
||||
/**
|
||||
* 根据文件后缀名,获取base64的文件头
|
||||
* @param str 文件名后缀
|
||||
*/
|
||||
public static String suffix(String str){
|
||||
String strSuffix = null;
|
||||
switch (str) {
|
||||
case "txt": strSuffix = "data:text/plain;base64,"; break;
|
||||
case "doc": strSuffix = "data:application/msword;base64,";break;
|
||||
case "docx": strSuffix = "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,";break;
|
||||
case "xls": strSuffix = "data:application/vnd.ms-excel;base64,";break;
|
||||
case "xlsx": strSuffix = "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,";break;
|
||||
case "pdf": strSuffix = "data:application/pdf;base64,";break;
|
||||
case "pptx": strSuffix = "data:application/vnd.openxmlformats-officedocument.presentationml.presentation;base64,";break;
|
||||
case "ppt": strSuffix = "data:application/vnd.ms-powerpoint;base64,";break;
|
||||
case "png": strSuffix = "data:image/png;base64,";break;
|
||||
case "jpg": strSuffix = "data:image/jpeg;base64,";break;
|
||||
case "gif": strSuffix = "data:image/gif;base64,";break;
|
||||
case "svg": strSuffix = "data:image/svg+xml;base64,";break;
|
||||
case "ico": strSuffix = "data:image/x-icon;base64,";break;
|
||||
case "bmp": strSuffix = "data:image/bmp;base64,";break;
|
||||
default: strSuffix = "data:image/bmp;base64,";break;
|
||||
}
|
||||
return strSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件转base64
|
||||
* @param path 文件地址
|
||||
*/
|
||||
public static String fileToBase64(String path) throws Exception {
|
||||
byte[] b = Files.readAllBytes(Paths.get(path));
|
||||
String strSuffix = suffix(path.substring(path.lastIndexOf(".") + 1));
|
||||
String base64 = Base64.getEncoder().encodeToString(b);
|
||||
return strSuffix + base64;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件
|
||||
* @param path 文件地址
|
||||
* @param multipartFile 文件
|
||||
*/
|
||||
public static void saveFile(String path, MultipartFile multipartFile) throws Exception {
|
||||
File dest = new File(path);
|
||||
assert multipartFile != null;
|
||||
multipartFile.transferTo(dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将InputStream写入本地文件
|
||||
* @param destination 写入本地目录 指定到文件名
|
||||
* @param input 输入流
|
||||
*/
|
||||
public static void writeToLocal(String destination, InputStream input)
|
||||
throws IOException {
|
||||
int index;
|
||||
byte[] bytes = new byte[1024];
|
||||
FileOutputStream downloadFile = new FileOutputStream(destination);
|
||||
while ((index = input.read(bytes)) != -1) {
|
||||
downloadFile.write(bytes, 0, index);
|
||||
downloadFile.flush();
|
||||
}
|
||||
downloadFile.close();
|
||||
input.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 网络文件转File
|
||||
* @param url
|
||||
*/
|
||||
public static File getFile(String url) throws Exception {
|
||||
//对本地文件命名
|
||||
String fileName = url.substring(url.lastIndexOf("."),url.length());
|
||||
File file = null;
|
||||
|
||||
URL urlfile;
|
||||
InputStream inStream = null;
|
||||
OutputStream os = null;
|
||||
try {
|
||||
file = File.createTempFile("net_url", fileName);
|
||||
//下载
|
||||
urlfile = new URL(url);
|
||||
inStream = urlfile.openStream();
|
||||
os = new FileOutputStream(file);
|
||||
|
||||
int bytesRead = 0;
|
||||
byte[] buffer = new byte[8192];
|
||||
while ((bytesRead = inStream.read(buffer, 0, 8192)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (null != os) {
|
||||
os.close();
|
||||
}
|
||||
if (null != inStream) {
|
||||
inStream.close();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* base64转MultiFile
|
||||
*/
|
||||
public static class Base64ToMultipartFile implements MultipartFile {
|
||||
|
||||
private final byte[] imgContent;
|
||||
private final String header;
|
||||
|
||||
|
||||
public Base64ToMultipartFile(byte[] imgContent, String header) {
|
||||
this.imgContent = imgContent;
|
||||
this.header = header.split(";")[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return System.currentTimeMillis() + (int) Math.random() * 10000 + "." + header.split("/")[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return header.split(":")[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return imgContent == null || imgContent.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return imgContent.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() throws IOException {
|
||||
return imgContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(imgContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(File dest) throws IOException, IllegalStateException {
|
||||
new FileOutputStream(dest).write(imgContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* base转为MultipartFile base64需要带着头
|
||||
*/
|
||||
public static MultipartFile base64ToMultipart(String base64) {
|
||||
String[] baseStrs = base64.split(",");
|
||||
|
||||
Base64.Decoder decoder = Base64.getDecoder();
|
||||
byte[] b = new byte[0];
|
||||
b = decoder.decode(baseStrs[1]);
|
||||
|
||||
for (int i = 0; i < b.length; ++i) {
|
||||
if (b[i] < 0) {
|
||||
b[i] += 256;
|
||||
}
|
||||
}
|
||||
return new Base64ToMultipartFile(b, baseStrs[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* file转MultipartFile的时候会用到MockMultipartFile
|
||||
* 当你导入spring-test依赖的时候 会跟某些依赖冲突(暂未找到具体是哪个冲突)
|
||||
* 解决方法 重写一个类去实现MultipartFile接口
|
||||
* 直接用MockMultipartFile的源码
|
||||
*/
|
||||
public static class MockMultipartFile implements MultipartFile {
|
||||
private final String name;
|
||||
|
||||
private String originalFilename;
|
||||
|
||||
private String contentType;
|
||||
|
||||
private final byte[] content;
|
||||
|
||||
/**
|
||||
* Create a new MultipartFileDto with the given content.
|
||||
* @param name the name of the file
|
||||
* @param content the content of the file
|
||||
*/
|
||||
public MockMultipartFile(String name, byte[] content) {
|
||||
this(name, "", null, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MultipartFileDto with the given content.
|
||||
* @param name the name of the file
|
||||
* @param contentStream the content of the file as stream
|
||||
* @throws IOException if reading from the stream failed
|
||||
*/
|
||||
public MockMultipartFile(String name, InputStream contentStream) throws IOException {
|
||||
this(name, "", null, FileCopyUtils.copyToByteArray(contentStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MultipartFileDto with the given content.
|
||||
* @param name the name of the file
|
||||
* @param originalFilename the original filename (as on the client's machine)
|
||||
* @param contentType the content type (if known)
|
||||
* @param content the content of the file
|
||||
*/
|
||||
public MockMultipartFile(String name, String originalFilename, String contentType, byte[] content) {
|
||||
this.name = name;
|
||||
this.originalFilename = (originalFilename != null ? originalFilename : "");
|
||||
this.contentType = contentType;
|
||||
this.content = (content != null ? content : new byte[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MultipartFileDto with the given content.
|
||||
* @param name the name of the file
|
||||
* @param originalFilename the original filename (as on the client's machine)
|
||||
* @param contentType the content type (if known)
|
||||
* @param contentStream the content of the file as stream
|
||||
* @throws IOException if reading from the stream failed
|
||||
*/
|
||||
public MockMultipartFile(String name, String originalFilename, String contentType, InputStream contentStream)
|
||||
throws IOException {
|
||||
|
||||
this(name, originalFilename, contentType, FileCopyUtils.copyToByteArray(contentStream));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return this.originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return (this.content.length == 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return this.content.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() throws IOException {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(this.content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(File dest) throws IOException, IllegalStateException {
|
||||
FileCopyUtils.copy(this.content, dest);
|
||||
}
|
||||
}
|
||||
}
|
17
src/main/java/com/darkness/common/util/HandlePage.java
Normal file
17
src/main/java/com/darkness/common/util/HandlePage.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.darkness.common.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HandlePage {
|
||||
|
||||
/**分页 start = (page - 1) * size, end = page * size*/
|
||||
private <T> List<T> handlePage(List<T> source, int start, int end){
|
||||
int total = source.size();
|
||||
// end = end > total ? total : end;
|
||||
end = Math.min(end, total);
|
||||
if (end <= start) {
|
||||
return null;
|
||||
}
|
||||
return source.subList(start,end);
|
||||
}
|
||||
}
|
90
src/main/java/com/darkness/common/util/MethodGetAndSet.java
Normal file
90
src/main/java/com/darkness/common/util/MethodGetAndSet.java
Normal file
@ -0,0 +1,90 @@
|
||||
package com.darkness.common.util;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class MethodGetAndSet {
|
||||
|
||||
/**根据属性,获取get方法*/
|
||||
public static Object getGetMethod(Object ob , String name)throws Exception{
|
||||
Method[] m = ob.getClass().getMethods();
|
||||
for(int i = 0;i < m.length;i++){
|
||||
if(("get"+name).toLowerCase().equals(m[i].getName().toLowerCase())){
|
||||
return m[i].invoke(ob);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**根据属性,拿到set方法,并把值set到对象中*/
|
||||
public static void setValue(Object obj, Class<?> clazz, String filedName, Class<?> typeClass, Object value){
|
||||
filedName = removeLine(filedName);
|
||||
String methodName = "set" + filedName.substring(0,1).toUpperCase()+filedName.substring(1);
|
||||
try{
|
||||
Method method = clazz.getDeclaredMethod(methodName, new Class[]{typeClass});
|
||||
method.invoke(obj, new Object[]{getClassTypeValue(typeClass, value)});
|
||||
}catch(Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**通过class类型获取获取对应类型的值*/
|
||||
public static Object getClassTypeValue(Class<?> typeClass, Object value){
|
||||
if(typeClass == int.class || value instanceof Integer){
|
||||
if(null == value){
|
||||
return 0;
|
||||
}
|
||||
return value;
|
||||
}else if(typeClass == short.class){
|
||||
if(null == value){
|
||||
return 0;
|
||||
}
|
||||
return value;
|
||||
}else if(typeClass == byte.class){
|
||||
if(null == value){
|
||||
return 0;
|
||||
}
|
||||
return value;
|
||||
}else if(typeClass == double.class){
|
||||
if(null == value){
|
||||
return 0;
|
||||
}
|
||||
return value;
|
||||
}else if(typeClass == long.class){
|
||||
if(null == value){
|
||||
return 0;
|
||||
}
|
||||
return value;
|
||||
}else if(typeClass == String.class){
|
||||
if(null == value){
|
||||
return "";
|
||||
}
|
||||
return value;
|
||||
}else if(typeClass == boolean.class){
|
||||
if(null == value){
|
||||
return true;
|
||||
}
|
||||
return value;
|
||||
}else if(typeClass == BigDecimal.class){
|
||||
if(null == value){
|
||||
return new BigDecimal(0);
|
||||
}
|
||||
return new BigDecimal(value+"");
|
||||
}else {
|
||||
return typeClass.cast(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**处理字符串 如: abc_dex ---> abcDex*/
|
||||
public static String removeLine(String str){
|
||||
if(null != str && str.contains("_")){
|
||||
int i = str.indexOf("_");
|
||||
char ch = str.charAt(i+1);
|
||||
char newCh = (ch+"").substring(0, 1).toUpperCase().toCharArray()[0];
|
||||
String newStr = str.replace(str.charAt(i+1), newCh);
|
||||
String newStr2 = newStr.replace("_", "");
|
||||
return newStr2;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
293
src/main/java/com/darkness/common/util/SM2Util.java
Normal file
293
src/main/java/com/darkness/common/util/SM2Util.java
Normal file
@ -0,0 +1,293 @@
|
||||
package com.darkness.common.util;
|
||||
|
||||
import org.bouncycastle.asn1.gm.GMNamedCurves;
|
||||
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
|
||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||
import org.bouncycastle.crypto.engines.SM2Engine;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ParametersWithRandom;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
|
||||
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.*;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class SM2Util {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SM2Util.class.getSimpleName());
|
||||
//ECC 曲线 SM2命名曲线
|
||||
private final static String NAME_CURVE = "sm2p256v1";
|
||||
private final static ECGenParameterSpec SM2_SPEC = new ECGenParameterSpec(NAME_CURVE);
|
||||
|
||||
//椭圆曲线ECParameters ASN.1 结构
|
||||
private static final X9ECParameters x9ECParameters = GMNamedCurves.getByName(NAME_CURVE);
|
||||
//椭圆曲线公钥或私钥的基本域参数。
|
||||
private static final ECParameterSpec ecDomainParameters = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
|
||||
|
||||
/**
|
||||
* 生成密钥
|
||||
*/
|
||||
public static Map<String, String> generateKey() {
|
||||
Map<String, String> resultMap = new HashMap<>();
|
||||
KeyPair keyPair = initECKeyPair();
|
||||
if (null != keyPair) {
|
||||
//生成公钥
|
||||
PublicKey publicKey = keyPair.getPublic();
|
||||
if (publicKey instanceof BCECPublicKey) {
|
||||
byte[] publicKeyByte = ((BCECPublicKey) publicKey).getQ().getEncoded(false);
|
||||
logger.info("publicKey is : " + Hex.toHexString(publicKeyByte));
|
||||
logger.info("publicKey byte size : " + publicKeyByte.length);
|
||||
if (publicKeyByte.length > 0) {
|
||||
resultMap.put("PublicKey", Hex.toHexString(publicKeyByte));
|
||||
}
|
||||
}
|
||||
//生成私钥
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
if (privateKey instanceof BCECPrivateKey) {
|
||||
byte[] privateKeyByte = ((BCECPrivateKey) privateKey).getD().toByteArray();
|
||||
logger.info("privateKey is : " + Hex.toHexString(privateKeyByte));
|
||||
logger.info("privateKey byte size : " + privateKeyByte.length);
|
||||
if (privateKeyByte.length > 0)
|
||||
resultMap.put("PrivateKey", Hex.toHexString(privateKeyByte));
|
||||
}
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化密钥
|
||||
*/
|
||||
private static KeyPair initECKeyPair() {
|
||||
KeyPairGenerator kpg;
|
||||
try {
|
||||
kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
|
||||
kpg.initialize(SM2_SPEC, new SecureRandom());
|
||||
return kpg.generateKeyPair();
|
||||
} catch (Exception e) {
|
||||
logger.error("生成密钥错误:" + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 内容加密
|
||||
*/
|
||||
public static byte[] encrypt(byte[] publicKeyByte, byte[] data) {
|
||||
//通过公钥对象获取公钥的基本与参数
|
||||
BCECPublicKey publicKey = getECPublicKeyByPublicKeyHex(Hex.toHexString(publicKeyByte));
|
||||
ECParameterSpec ecParameterSpec = publicKey.getParameters();
|
||||
ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(), ecParameterSpec.getG(), ecParameterSpec.getN());
|
||||
ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(publicKey.getQ(), ecDomainParameters);
|
||||
|
||||
SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
|
||||
sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));
|
||||
byte[] arrayOfBytes = null;
|
||||
try {
|
||||
arrayOfBytes = sm2Engine.processBlock(data, 0, data.length);
|
||||
} catch (Exception e) {
|
||||
logger.error("加密错误:" + e.getMessage());
|
||||
}
|
||||
return arrayOfBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内容公钥加密 返回字符串
|
||||
*/
|
||||
public static String encrypt(String publicKeyHex, String data) {
|
||||
byte[] publicKeyByte = Hex.decode(publicKeyHex);
|
||||
byte[] dataByte = data.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] encryptByte = encrypt(publicKeyByte, dataByte);
|
||||
return Hex.toHexString(encryptByte);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*/
|
||||
public static byte[] decrypt(byte[] privateKeyByte, byte[] data) {
|
||||
//通过私钥对象获取私钥的基本域参数。
|
||||
BCECPrivateKey privateKey = getBCECPrivateKeyByPrivateKeyHex(Hex.toHexString(privateKeyByte));
|
||||
ECParameterSpec ecParameterSpec = privateKey.getParameters();
|
||||
ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
|
||||
ecParameterSpec.getG(), ecParameterSpec.getN());
|
||||
|
||||
//通过私钥值和私钥钥基本参数创建私钥参数对象
|
||||
ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(privateKey.getD(),
|
||||
ecDomainParameters);
|
||||
|
||||
//通过解密模式创建解密引擎并初始化
|
||||
SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
|
||||
sm2Engine.init(false, ecPrivateKeyParameters);
|
||||
|
||||
try {
|
||||
//通过解密引擎对密文字节串进行解密
|
||||
//将解密后的字节串转换为utf8字符编码的字符串(需要与明文加密时字符串转换成字节串所指定的字符编码保持一致)
|
||||
return sm2Engine.processBlock(data, 0, data.length);
|
||||
} catch (Exception e) {
|
||||
logger.error("解密错误:" + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥解密 返回字符串
|
||||
*/
|
||||
public static String decrypt(String privateKeyHex, String data) {
|
||||
byte[] privateKeyByte = Hex.decode(privateKeyHex);
|
||||
byte[] dataByte = Hex.decode(data);
|
||||
byte[] decryptByte = decrypt(privateKeyByte, dataByte);
|
||||
return new String(decryptByte, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名
|
||||
*/
|
||||
public static byte[] sign(String privateKeyHex, byte[] message) {
|
||||
try {
|
||||
Signature signature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), new BouncyCastleProvider());
|
||||
signature.initSign(getBCECPrivateKeyByPrivateKeyHex(privateKeyHex));
|
||||
signature.update(message);
|
||||
return signature.sign();
|
||||
} catch (Exception e) {
|
||||
logger.error("签名错误:" + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥生成签名 返回字符串
|
||||
*/
|
||||
public static String sign(String privateKeyHex, String message) {
|
||||
byte[] messageByte = message.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] signByte = sign(privateKeyHex, messageByte);
|
||||
return Hex.toHexString(signByte);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验签
|
||||
*/
|
||||
public static boolean verifySign(String publicKeyHex, byte[] signedMsg, byte[] originMsg) {
|
||||
try {
|
||||
Signature signature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), new BouncyCastleProvider());
|
||||
signature.initVerify(getECPublicKeyByPublicKeyHex(publicKeyHex));
|
||||
signature.update(originMsg);
|
||||
return signature.verify(signedMsg);
|
||||
} catch (Exception e) {
|
||||
logger.error("验签错误:" + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 公钥验签 返回布尔值
|
||||
*/
|
||||
public static boolean verifySign(String publicKeyHex, String signedMsg, String originMsg) {
|
||||
byte[] signedMsgByte = Hex.decode(signedMsg);
|
||||
byte[] originMsgByte = originMsg.getBytes(StandardCharsets.UTF_8);
|
||||
return verifySign(publicKeyHex, signedMsgByte, originMsgByte);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据16进制内容生成公钥
|
||||
*/
|
||||
public static BCECPublicKey getECPublicKeyByPublicKeyHex(String pubKeyHex) {
|
||||
//截取64字节有效的SM2公钥(如果公钥首个字节为0x04)
|
||||
if (pubKeyHex.length() > 128) {
|
||||
pubKeyHex = pubKeyHex.substring(pubKeyHex.length() - 128);
|
||||
}
|
||||
//将公钥拆分为x,y分量(各32字节)
|
||||
String stringX = pubKeyHex.substring(0, 64);
|
||||
String stringY = pubKeyHex.substring(stringX.length());
|
||||
//将公钥x、y分量转换为BigInteger类型
|
||||
BigInteger x = new BigInteger(stringX, 16);
|
||||
BigInteger y = new BigInteger(stringY, 16);
|
||||
//通过公钥x、y分量创建椭圆曲线公钥规范
|
||||
ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(x9ECParameters.getCurve().createPoint(x, y), ecDomainParameters);
|
||||
//通过椭圆曲线公钥规范,创建出椭圆曲线公钥对象(可用于SM2加密及验签)
|
||||
return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 私钥字符串转换为 BCECPrivateKey 私钥对象
|
||||
*
|
||||
* @param privateKeyHex: 32字节十六进制私钥字符串
|
||||
* @return BCECPrivateKey:SM2私钥对象
|
||||
*/
|
||||
public static BCECPrivateKey getBCECPrivateKeyByPrivateKeyHex(String privateKeyHex) {
|
||||
//将十六进制私钥字符串转换为BigInteger对象
|
||||
BigInteger d = new BigInteger(privateKeyHex, 16);
|
||||
//通过私钥和私钥域参数集创建椭圆曲线私钥规范
|
||||
ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecDomainParameters);
|
||||
//通过椭圆曲线私钥规范,创建出椭圆曲线私钥对象(可用于SM2解密和签名)
|
||||
return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 生成密钥对
|
||||
Map<String, String> map = generateKey();
|
||||
|
||||
/*
|
||||
* 密钥对
|
||||
* 通常加解密 和 签名验签 所用的公私钥不是一套
|
||||
* 公钥加密 私钥解密 私钥签名 公钥验签
|
||||
*/
|
||||
String signPublicKey = map.get("PublicKey");
|
||||
String signPrivateKey = map.get("PrivateKey");
|
||||
|
||||
//加密内容
|
||||
String info = "Test123Test123Test1234567";
|
||||
|
||||
// //加密
|
||||
// byte[] encodeInfoBytes = encrypt(Hex.decode(signPublicKey),info.getBytes(StandardCharsets.UTF_8));
|
||||
// String encodeInfo = Hex.toHexString(encodeInfoBytes);
|
||||
// logger.info("加密内容"+encodeInfo);
|
||||
//
|
||||
// // 解密
|
||||
// byte[] decodeInfoBytes = decrypt(Hex.decode(signPrivateKey),Hex.decode(encodeInfo));
|
||||
// String decodeInfo = null;
|
||||
// if (decodeInfoBytes != null) {
|
||||
// decodeInfo = new String(decodeInfoBytes);
|
||||
// }
|
||||
// logger.info("解密内容"+decodeInfo);
|
||||
//
|
||||
// String signedInfo = Hex.toHexString(Objects.requireNonNull(sign(signPrivateKey, encodeInfo.getBytes(StandardCharsets.UTF_8))));
|
||||
// logger.info("签名:" + signedInfo);
|
||||
//
|
||||
// boolean isSigned = verifySign(signPublicKey,Hex.decode(signedInfo),encodeInfo.getBytes(StandardCharsets.UTF_8));
|
||||
// logger.info("验签:" + isSigned);
|
||||
|
||||
//加密
|
||||
String encodeInfo = encrypt(signPublicKey,info);
|
||||
logger.info("加密内容"+encodeInfo);
|
||||
|
||||
//解密
|
||||
String decodeInfo = decrypt(signPrivateKey,encodeInfo);
|
||||
logger.info("解密内容"+decodeInfo);
|
||||
|
||||
//签名
|
||||
String signedInfo = sign(signPrivateKey,encodeInfo);
|
||||
logger.info("签名:" + signedInfo);
|
||||
|
||||
//验签
|
||||
boolean isSigned = verifySign(signPublicKey,signedInfo,encodeInfo);
|
||||
logger.info("验签:" + isSigned);
|
||||
|
||||
}
|
||||
}
|
89
src/main/java/com/darkness/common/util/page/PageHelper.java
Normal file
89
src/main/java/com/darkness/common/util/page/PageHelper.java
Normal file
@ -0,0 +1,89 @@
|
||||
package com.darkness.common.util.page;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author fuhouyin
|
||||
* @time 2023/2/17 17:37
|
||||
*/
|
||||
@Data
|
||||
public class PageHelper implements Serializable {
|
||||
private static final long serialVersionUID = -4653064203154489390L;
|
||||
|
||||
public static final Integer MAX_PAGE_SIZE = 1000000;
|
||||
|
||||
private Integer pageNum;
|
||||
private Integer pageSize;
|
||||
private Integer totalRowCount;
|
||||
private Integer nextPageNum;
|
||||
|
||||
public PageHelper() {
|
||||
}
|
||||
|
||||
public PageHelper(Integer pageNum, Integer pageSize) {
|
||||
if (pageNum == null || pageNum <= 0) {
|
||||
this.pageNum = 1;
|
||||
} else {
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
|
||||
if (pageSize == null || pageSize < 0) {
|
||||
this.pageSize = MAX_PAGE_SIZE;
|
||||
} else {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
}
|
||||
|
||||
public PageHelper(PageReqCmd reqCmd, Integer totalRowCount){
|
||||
if (reqCmd.getPageNum() == null || reqCmd.getPageNum() <= 0) {
|
||||
this.pageNum = 1;
|
||||
} else {
|
||||
this.pageNum = reqCmd.getPageNum();
|
||||
}
|
||||
|
||||
if (reqCmd.getPageSize() == null || reqCmd.getPageSize() < 0) {
|
||||
this.pageSize = MAX_PAGE_SIZE;
|
||||
} else {
|
||||
this.pageSize = reqCmd.getPageSize();
|
||||
}
|
||||
|
||||
setTotalRowCount(totalRowCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 以页码从1开始计算的偏移量
|
||||
* @return
|
||||
*/
|
||||
public Integer offset() {
|
||||
if (null == pageNum || null == totalRowCount) {
|
||||
return 0;
|
||||
}
|
||||
int offset = (pageNum - 1) * pageSize;
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Java分页
|
||||
* @param sourceList
|
||||
* @return
|
||||
*/
|
||||
public List pageList(List sourceList){
|
||||
if (CollectionUtils.isEmpty(sourceList)) {
|
||||
return sourceList;
|
||||
}
|
||||
Integer offset = offset();
|
||||
if (offset > (totalRowCount - 1)) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
int end = offset + pageSize;
|
||||
end = Math.min(end,totalRowCount);
|
||||
return sourceList.subList(offset,end);
|
||||
}
|
||||
|
||||
}
|
||||
|
16
src/main/java/com/darkness/common/util/page/PageReq.java
Normal file
16
src/main/java/com/darkness/common/util/page/PageReq.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.darkness.common.util.page;
|
||||
|
||||
/**
|
||||
* @author fuhouyin
|
||||
* @time 2023/2/17 17:38
|
||||
*/
|
||||
public interface PageReq {
|
||||
|
||||
Integer getPageNum();
|
||||
|
||||
void setPageNum(Integer pageNum);
|
||||
|
||||
Integer getPageSize();
|
||||
|
||||
void setPageSize(Integer pageSize);
|
||||
}
|
14
src/main/java/com/darkness/common/util/page/PageReqCmd.java
Normal file
14
src/main/java/com/darkness/common/util/page/PageReqCmd.java
Normal file
@ -0,0 +1,14 @@
|
||||
package com.darkness.common.util.page;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author fuhouyin
|
||||
* @time 2023/2/17 17:38
|
||||
*/
|
||||
@Data
|
||||
public class PageReqCmd<T> implements PageReq {
|
||||
private T filter;
|
||||
private Integer pageNum = 1;
|
||||
private Integer pageSize = 20;
|
||||
}
|
15
src/main/java/com/darkness/common/util/page/PageResp.java
Normal file
15
src/main/java/com/darkness/common/util/page/PageResp.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.darkness.common.util.page;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author fuhouyin
|
||||
* @time 2023/2/17 17:26
|
||||
*/
|
||||
@Data
|
||||
public class PageResp<T> {
|
||||
private List<T> list;
|
||||
private Integer totalCount;
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
package com.darkness.common.util.redis;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author fuhouyin
|
||||
* @time 2023/4/11 9:30
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class RedisCacheUtils {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplateProvider redisTemplateProvider;
|
||||
@Autowired
|
||||
private RedisTemplate redisTemplate;
|
||||
private final StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||
public static final String SETNX_SCRIPT = "return redis.call('setnx',KEYS[1], ARGV[1])";
|
||||
|
||||
public void setValue(String key, Object value){
|
||||
RedisTemplate redisTemplate = getRedisTemplate();
|
||||
redisTemplate.opsForValue().set(key,value);
|
||||
}
|
||||
|
||||
public void setValue(String key, Object value,Long timeout, TimeUnit timeUnit){
|
||||
RedisTemplate redisTemplate = getRedisTemplate();
|
||||
redisTemplate.opsForValue().set(key,value,timeout, timeUnit);
|
||||
}
|
||||
|
||||
public Object getValue(String key){
|
||||
RedisTemplate redisTemplate = getRedisTemplate();
|
||||
return redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
public String getCacheKey(Object... keys) {
|
||||
return StringUtils.join(Arrays.asList(keys), ":");
|
||||
}
|
||||
|
||||
public Long hashIncrement(String key, String hashKey){
|
||||
RedisTemplate redisTemplate = getRedisTemplate();
|
||||
Long increment = redisTemplate.opsForHash().increment(key, hashKey, 1);
|
||||
return increment;
|
||||
}
|
||||
|
||||
public boolean hasKey(String key){
|
||||
return getRedisTemplate().hasKey(key);
|
||||
}
|
||||
|
||||
public boolean delKey(String key){
|
||||
if (StringUtils.isEmpty(key)) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
RedisTemplate redisTemplate = getRedisTemplate();
|
||||
if (redisTemplate.hasKey(key)) {
|
||||
return redisTemplate.delete(key);
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
public boolean hashHasKey(String key, String hashKey){
|
||||
return getRedisTemplate().opsForHash().hasKey(key, hashKey);
|
||||
}
|
||||
|
||||
public Object hashGet(String key, String hashKey){
|
||||
return getRedisTemplate().opsForHash().get(key, hashKey);
|
||||
}
|
||||
|
||||
private RedisTemplate getRedisTemplate(){
|
||||
RedisTemplate<String, Object> template = redisTemplateProvider.getTemplate(stringRedisSerializer);
|
||||
return template;
|
||||
}
|
||||
|
||||
public void hashPut(String key,String hashKey, String value){
|
||||
getRedisTemplate().opsForHash().put(key,hashKey,value);
|
||||
}
|
||||
|
||||
public void hashPutIfAbsent(String key, String hashKey, String value) {
|
||||
getRedisTemplate().opsForHash().putIfAbsent(key,hashKey,value);
|
||||
}
|
||||
|
||||
public Boolean expire(String key, long time, TimeUnit timeUnit){
|
||||
Boolean result = getRedisTemplate().expire(key, time, timeUnit);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定缓存失效时间
|
||||
*/
|
||||
public void expire(String key, long time) {
|
||||
redisTemplate.expire(key, time, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
/**
|
||||
* 根据key 获取过期时间
|
||||
*
|
||||
* @param key 键 不能为null
|
||||
* @return 时间(毫秒) 返回0代表为永久有效
|
||||
*/
|
||||
public long getExpire(String key) {
|
||||
return redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public Boolean lock(String key){
|
||||
return getRedisTemplate().opsForValue().setIfAbsent(key, BigDecimal.ZERO.intValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* redis实现分布式锁
|
||||
* @param key time是:毫秒毫秒毫秒毫秒毫秒
|
||||
* @return
|
||||
*/
|
||||
public boolean lock(String key,Long time) {
|
||||
//自定义脚本
|
||||
DefaultRedisScript<List> script = new DefaultRedisScript<>(SETNX_SCRIPT, List.class);
|
||||
//执行脚本,传入参数,由于value没啥用,这里随便写死的"1"
|
||||
List<Long> rst = (List<Long>) redisTemplate.execute(script, Collections.singletonList(key), "1");
|
||||
//返回1,表示设置成功,拿到锁
|
||||
if(rst.get(0) == 1){
|
||||
log.info(key+"成功拿到锁");
|
||||
//设置过期时间
|
||||
expire(key,time);
|
||||
log.info(key+"已成功设置过期时间:"+time +" 秒");
|
||||
return true;
|
||||
}else{
|
||||
long expire = getExpire(key);
|
||||
log.info(key+"未拿到到锁,还有"+expire+"释放");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean tryLock(String key){
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (lock(key)) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
Thread.sleep(100L);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
public void unlock(String key){
|
||||
getRedisTemplate().delete(key);
|
||||
}
|
||||
|
||||
|
||||
public Long increment(String key, Long delta){
|
||||
return getRedisTemplate().opsForValue().increment(key,delta);
|
||||
}
|
||||
|
||||
public Boolean setIfAbsent(String key, Object value){
|
||||
return getRedisTemplate().opsForValue().setIfAbsent(key,value);
|
||||
}
|
||||
|
||||
public Set<String> keys(String keyPattern) {
|
||||
return getRedisTemplate().keys(keyPattern);
|
||||
}
|
||||
|
||||
public Object getAndSet(String key, Object value){
|
||||
return getRedisTemplate().opsForValue().getAndSet(key,value);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.darkness.common.util.redis;
|
||||
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
|
||||
/**
|
||||
* @author fuhouyin
|
||||
* @time 2023/4/11 9:30
|
||||
*/
|
||||
public interface RedisTemplateProvider {
|
||||
RedisTemplate<String, Object> getTemplate();
|
||||
|
||||
RedisTemplate<String, Object> getTemplate(RedisSerializer valueSerializer);
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.darkness.common.util.redis;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
* @author fuhouyin
|
||||
* @time 2023/4/11 9:30
|
||||
*/
|
||||
@Component
|
||||
public class RedisTemplateProviderImpl implements RedisTemplateProvider {
|
||||
public static final RedisSerializer<Object> JDK_SERIALIZER = new JdkSerializationRedisSerializer();
|
||||
public static final RedisSerializer<String> STRING_SERIALIZER = new StringRedisSerializer();
|
||||
private final Map<String, RedisTemplate<String, Object>> redisTemplateMap = new HashMap();
|
||||
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
|
||||
private final Lock r;
|
||||
private final Lock w;
|
||||
private final RedisConnectionFactory redisStoreConnectionFactory;
|
||||
|
||||
public RedisTemplateProviderImpl(RedisConnectionFactory redisStoreConnectionFactory) {
|
||||
this.r = this.rwl.readLock();
|
||||
this.w = this.rwl.writeLock();
|
||||
this.redisStoreConnectionFactory = redisStoreConnectionFactory;
|
||||
}
|
||||
|
||||
public RedisTemplate<String, Object> getTemplate() {
|
||||
return this.getTemplate(STRING_SERIALIZER);
|
||||
}
|
||||
|
||||
public RedisTemplate<String, Object> getTemplate(RedisSerializer valueSerializer) {
|
||||
return this.getTemplate(STRING_SERIALIZER, valueSerializer);
|
||||
}
|
||||
|
||||
private RedisTemplate<String, Object> getTemplate(RedisSerializer<String> keySerializer, RedisSerializer valueSerializer) {
|
||||
String cacheKey = this.getTemplateCacheKey(keySerializer, valueSerializer);
|
||||
|
||||
try {
|
||||
this.r.lock();
|
||||
RedisTemplate<String, Object> template = (RedisTemplate)this.redisTemplateMap.get(cacheKey);
|
||||
if (template != null) {
|
||||
RedisTemplate var5 = template;
|
||||
return var5;
|
||||
}
|
||||
} finally {
|
||||
this.r.unlock();
|
||||
}
|
||||
|
||||
return this.createAndPut(keySerializer, valueSerializer, cacheKey);
|
||||
}
|
||||
|
||||
private RedisTemplate<String, Object> createAndPut(RedisSerializer<String> keySerializer, RedisSerializer valueSerializer, String cacheKey) {
|
||||
RedisTemplate var5;
|
||||
try {
|
||||
this.w.lock();
|
||||
RedisTemplate<String, Object> template = (RedisTemplate)this.redisTemplateMap.get(cacheKey);
|
||||
if (template == null) {
|
||||
template = this.createRedisTemplate(keySerializer, valueSerializer);
|
||||
this.redisTemplateMap.put(cacheKey, template);
|
||||
}
|
||||
|
||||
var5 = template;
|
||||
} finally {
|
||||
this.w.unlock();
|
||||
}
|
||||
|
||||
return var5;
|
||||
}
|
||||
|
||||
private RedisTemplate<String, Object> createRedisTemplate(RedisSerializer<String> keySerializer, RedisSerializer valueSerializer) {
|
||||
RedisTemplate<String, Object> template = new RedisTemplate();
|
||||
template.setKeySerializer(keySerializer);
|
||||
template.setHashKeySerializer(keySerializer);
|
||||
template.setHashValueSerializer(valueSerializer);
|
||||
template.setValueSerializer(valueSerializer);
|
||||
template.setConnectionFactory(this.redisStoreConnectionFactory);
|
||||
template.afterPropertiesSet();
|
||||
return template;
|
||||
}
|
||||
|
||||
private String getTemplateCacheKey(RedisSerializer keySerializer, RedisSerializer valueSerializer) {
|
||||
Assert.notNull(keySerializer, "keySerializer should not null");
|
||||
Assert.notNull(valueSerializer, "valueSerializer should not null");
|
||||
return keySerializer.getClass().getName() + "-" + valueSerializer.getClass().getName();
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package com.darkness.common.util.response;
|
||||
|
||||
/**
|
||||
* @author fuhouyin
|
||||
* @time 2023/2/17 18:03
|
||||
*/
|
||||
public enum ResultEnums {
|
||||
TRUE_200(200, "成功"),
|
||||
FALSE_300(300, "失败"),
|
||||
FALSE_400(400, "内部错误"),
|
||||
FALSE_423(423, "数据不存在"),
|
||||
FALSE_424(424, "数据已存在"),
|
||||
FALSE_500(500, "错误"),
|
||||
FALSE_600(600, "session超时或未登录");
|
||||
|
||||
private int code;
|
||||
private String message;
|
||||
|
||||
ResultEnums(){}
|
||||
|
||||
ResultEnums(int code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public static String valueOfCode(String code) {
|
||||
for (ResultEnums obj : ResultEnums.values()) {
|
||||
if (java.util.Objects.equals(obj.code, code)) {
|
||||
return obj.message;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Number valueOfMessage(String message) {
|
||||
for (ResultEnums obj : ResultEnums.values()) {
|
||||
if (java.util.Objects.equals(obj.message, message)) {
|
||||
return obj.code;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
148
src/main/java/com/darkness/common/util/response/VoResult.java
Normal file
148
src/main/java/com/darkness/common/util/response/VoResult.java
Normal file
@ -0,0 +1,148 @@
|
||||
package com.darkness.common.util.response;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author fuhouyin
|
||||
* @time 2023/2/17 18:02
|
||||
*/
|
||||
public class VoResult {
|
||||
|
||||
private Integer resultCode;
|
||||
|
||||
private String resultMsg;
|
||||
|
||||
private Map<String,Object> resultData = new HashMap<String,Object>();
|
||||
|
||||
public Map<String, Object> getResultData() {
|
||||
return resultData;
|
||||
}
|
||||
|
||||
public void setResultData(Map<String, Object> resultData) {
|
||||
this.resultData = resultData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sessionn超时或未登录
|
||||
*/
|
||||
public static VoResult sessionNotExists(){
|
||||
VoResult result = new VoResult();
|
||||
result.setResultCode(ResultEnums.FALSE_600.getCode());
|
||||
result.setResultMsg(ResultEnums.FALSE_600.getMessage());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据已存在
|
||||
*/
|
||||
public static VoResult dataExists(){
|
||||
VoResult result = new VoResult();
|
||||
result.setResultCode(ResultEnums.FALSE_424.getCode());
|
||||
result.setResultMsg(ResultEnums.FALSE_424.getMessage());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据不存在
|
||||
*/
|
||||
public static VoResult dataNotExists(){
|
||||
VoResult result = new VoResult();
|
||||
result.setResultCode(ResultEnums.FALSE_423.getCode());
|
||||
result.setResultMsg(ResultEnums.FALSE_423.getMessage());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据不存在
|
||||
*/
|
||||
public static VoResult dataNotExists(String resultMsg){
|
||||
VoResult result = new VoResult();
|
||||
result.setResultCode(ResultEnums.FALSE_423.getCode());
|
||||
result.setResultMsg(resultMsg);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
public static VoResult success(){
|
||||
VoResult result = new VoResult();
|
||||
result.setResultCode(ResultEnums.TRUE_200.getCode());
|
||||
result.setResultMsg(ResultEnums.TRUE_200.getMessage());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
public static VoResult fail(){
|
||||
VoResult result = new VoResult();
|
||||
result.setResultCode(ResultEnums.FALSE_300.getCode());
|
||||
result.setResultMsg(ResultEnums.FALSE_300.getMessage());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部错误(参数错误)
|
||||
*/
|
||||
public static VoResult errorParam(){
|
||||
VoResult result = new VoResult();
|
||||
result.setResultCode(ResultEnums.FALSE_400.getCode());
|
||||
result.setResultMsg(ResultEnums.FALSE_400.getMessage());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如需自定义错误信息,请使用该方法
|
||||
*/
|
||||
public static VoResult errorParam(String msg){
|
||||
VoResult result = new VoResult();
|
||||
result.setResultCode(ResultEnums.FALSE_400.getCode());
|
||||
result.setResultMsg(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
public VoResult add(String key, Object value){
|
||||
this.getResultData().put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public VoResult addData(Object value){
|
||||
this.getResultData().put("data", value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public VoResult add(Map map){
|
||||
this.setResultData(map);
|
||||
return this;
|
||||
}
|
||||
|
||||
public VoResult(){
|
||||
|
||||
}
|
||||
|
||||
public VoResult(Integer resultCode, String resultMsg, Map<String,Object> resultData) {
|
||||
this.resultCode = resultCode;
|
||||
this.resultMsg = resultMsg;
|
||||
this.resultData = resultData;
|
||||
}
|
||||
|
||||
public Integer getResultCode() {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
public void setResultCode(Integer resultCode) {
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
public String getResultMsg() {
|
||||
return resultMsg;
|
||||
}
|
||||
|
||||
public void setResultMsg(String resultMsg) {
|
||||
this.resultMsg = resultMsg;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user