标签
工具
字数
47795 字
阅读时间
256 分钟
UUID工具类
java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import com.ruoyi.common.exception.UtilException;
/**
* 提供通用唯一识别码(universally unique identifier)(UUID)实现
*
* @author ruoyi
*/
public final class UUID implements java.io.Serializable, Comparable<UUID>
{
private static final long serialVersionUID = -1185015143654744140L;
/**
* SecureRandom 的单例
*
*/
private static class Holder
{
static final SecureRandom numberGenerator = getSecureRandom();
}
/** 此UUID的最高64有效位 */
private final long mostSigBits;
/** 此UUID的最低64有效位 */
private final long leastSigBits;
/**
* 私有构造
*
* @param data 数据
*/
private UUID(byte[] data)
{
long msb = 0;
long lsb = 0;
assert data.length == 16 : "data must be 16 bytes in length";
for (int i = 0; i < 8; i++)
{
msb = (msb << 8) | (data[i] & 0xff);
}
for (int i = 8; i < 16; i++)
{
lsb = (lsb << 8) | (data[i] & 0xff);
}
this.mostSigBits = msb;
this.leastSigBits = lsb;
}
/**
* 使用指定的数据构造新的 UUID。
*
* @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
* @param leastSigBits 用于 {@code UUID} 的最低有效 64 位
*/
public UUID(long mostSigBits, long leastSigBits)
{
this.mostSigBits = mostSigBits;
this.leastSigBits = leastSigBits;
}
/**
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。
*
* @return 随机生成的 {@code UUID}
*/
public static UUID fastUUID()
{
return randomUUID(false);
}
/**
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
*
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID()
{
return randomUUID(true);
}
/**
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
*
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID(boolean isSecure)
{
final Random ng = isSecure ? Holder.numberGenerator : getRandom();
byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes);
randomBytes[6] &= 0x0f; /* clear version */
randomBytes[6] |= 0x40; /* set to version 4 */
randomBytes[8] &= 0x3f; /* clear variant */
randomBytes[8] |= 0x80; /* set to IETF variant */
return new UUID(randomBytes);
}
/**
* 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。
*
* @param name 用于构造 UUID 的字节数组。
*
* @return 根据指定数组生成的 {@code UUID}
*/
public static UUID nameUUIDFromBytes(byte[] name)
{
MessageDigest md;
try
{
md = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException nsae)
{
throw new InternalError("MD5 not supported");
}
byte[] md5Bytes = md.digest(name);
md5Bytes[6] &= 0x0f; /* clear version */
md5Bytes[6] |= 0x30; /* set to version 3 */
md5Bytes[8] &= 0x3f; /* clear variant */
md5Bytes[8] |= 0x80; /* set to IETF variant */
return new UUID(md5Bytes);
}
/**
* 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。
*
* @param name 指定 {@code UUID} 字符串
* @return 具有指定值的 {@code UUID}
* @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常
*
*/
public static UUID fromString(String name)
{
String[] components = name.split("-");
if (components.length != 5)
{
throw new IllegalArgumentException("Invalid UUID string: " + name);
}
for (int i = 0; i < 5; i++)
{
components[i] = "0x" + components[i];
}
long mostSigBits = Long.decode(components[0]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[1]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[2]).longValue();
long leastSigBits = Long.decode(components[3]).longValue();
leastSigBits <<= 48;
leastSigBits |= Long.decode(components[4]).longValue();
return new UUID(mostSigBits, leastSigBits);
}
/**
* 返回此 UUID 的 128 位值中的最低有效 64 位。
*
* @return 此 UUID 的 128 位值中的最低有效 64 位。
*/
public long getLeastSignificantBits()
{
return leastSigBits;
}
/**
* 返回此 UUID 的 128 位值中的最高有效 64 位。
*
* @return 此 UUID 的 128 位值中最高有效 64 位。
*/
public long getMostSignificantBits()
{
return mostSigBits;
}
/**
* 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。
* <p>
* 版本号具有以下含意:
* <ul>
* <li>1 基于时间的 UUID
* <li>2 DCE 安全 UUID
* <li>3 基于名称的 UUID
* <li>4 随机生成的 UUID
* </ul>
*
* @return 此 {@code UUID} 的版本号
*/
public int version()
{
// Version is bits masked by 0x000000000000F000 in MS long
return (int) ((mostSigBits >> 12) & 0x0f);
}
/**
* 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。
* <p>
* 变体号具有以下含意:
* <ul>
* <li>0 为 NCS 向后兼容保留
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于此类
* <li>6 保留,微软向后兼容
* <li>7 保留供以后定义使用
* </ul>
*
* @return 此 {@code UUID} 相关联的变体号
*/
public int variant()
{
// This field is composed of a varying number of bits.
// 0 - - Reserved for NCS backward compatibility
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
// 1 1 0 Reserved, Microsoft backward compatibility
// 1 1 1 Reserved for future definition.
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
}
/**
* 与此 UUID 相关联的时间戳值。
*
* <p>
* 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br>
* 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。
*
* <p>
* 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
* 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
*
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。
*/
public long timestamp() throws UnsupportedOperationException
{
checkTimeBase();
return (mostSigBits & 0x0FFFL) << 48//
| ((mostSigBits >> 16) & 0x0FFFFL) << 32//
| mostSigBits >>> 32;
}
/**
* 与此 UUID 相关联的时钟序列值。
*
* <p>
* 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。
* <p>
* {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出
* UnsupportedOperationException。
*
* @return 此 {@code UUID} 的时钟序列
*
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
*/
public int clockSequence() throws UnsupportedOperationException
{
checkTimeBase();
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
}
/**
* 与此 UUID 相关的节点值。
*
* <p>
* 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。
* <p>
* 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
* 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
*
* @return 此 {@code UUID} 的节点值
*
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
*/
public long node() throws UnsupportedOperationException
{
checkTimeBase();
return leastSigBits & 0x0000FFFFFFFFFFFFL;
}
/**
* 返回此{@code UUID} 的字符串表现形式。
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述:
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @return 此{@code UUID} 的字符串表现形式
* @see #toString(boolean)
*/
@Override
public String toString()
{
return toString(false);
}
/**
* 返回此{@code UUID} 的字符串表现形式。
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述:
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串
* @return 此{@code UUID} 的字符串表现形式
*/
public String toString(boolean isSimple)
{
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low
builder.append(digits(mostSigBits >> 32, 8));
if (false == isSimple)
{
builder.append('-');
}
// time_mid
builder.append(digits(mostSigBits >> 16, 4));
if (false == isSimple)
{
builder.append('-');
}
// time_high_and_version
builder.append(digits(mostSigBits, 4));
if (false == isSimple)
{
builder.append('-');
}
// variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4));
if (false == isSimple)
{
builder.append('-');
}
// node
builder.append(digits(leastSigBits, 12));
return builder.toString();
}
/**
* 返回此 UUID 的哈希码。
*
* @return UUID 的哈希码值。
*/
@Override
public int hashCode()
{
long hilo = mostSigBits ^ leastSigBits;
return ((int) (hilo >> 32)) ^ (int) hilo;
}
/**
* 将此对象与指定对象比较。
* <p>
* 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。
*
* @param obj 要与之比较的对象
*
* @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
*/
@Override
public boolean equals(Object obj)
{
if ((null == obj) || (obj.getClass() != UUID.class))
{
return false;
}
UUID id = (UUID) obj;
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
}
// Comparison Operations
/**
* 将此 UUID 与指定的 UUID 比较。
*
* <p>
* 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。
*
* @param val 与此 UUID 比较的 UUID
*
* @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
*
*/
@Override
public int compareTo(UUID val)
{
// The ordering is intentionally set up so that the UUIDs
// can simply be numerically compared as two numbers
return (this.mostSigBits < val.mostSigBits ? -1 : //
(this.mostSigBits > val.mostSigBits ? 1 : //
(this.leastSigBits < val.leastSigBits ? -1 : //
(this.leastSigBits > val.leastSigBits ? 1 : //
0))));
}
// -------------------------------------------------------------------------------------------------------------------
// Private method start
/**
* 返回指定数字对应的hex值
*
* @param val 值
* @param digits 位
* @return 值
*/
private static String digits(long val, int digits)
{
long hi = 1L << (digits * 4);
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}
/**
* 检查是否为time-based版本UUID
*/
private void checkTimeBase()
{
if (version() != 1)
{
throw new UnsupportedOperationException("Not a time-based UUID");
}
}
/**
* 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
*
* @return {@link SecureRandom}
*/
public static SecureRandom getSecureRandom()
{
try
{
return SecureRandom.getInstance("SHA1PRNG");
}
catch (NoSuchAlgorithmException e)
{
throw new UtilException(e);
}
}
/**
* 获取随机数生成器对象<br>
* ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
*
* @return {@link ThreadLocalRandom}
*/
public static ThreadLocalRandom getRandom()
{
return ThreadLocalRandom.current();
}
}java
/**
* ID生成器工具类
*
* @author ruoyi
*/
public class IdUtils
{
/**
* 获取随机UUID
*
* @return 随机UUID
*/
public static String randomUUID()
{
return UUID.randomUUID().toString();
}
/**
* 简化的UUID,去掉了横线
*
* @return 简化的UUID,去掉了横线
*/
public static String simpleUUID()
{
return UUID.randomUUID().toString(true);
}
/**
* 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID
*
* @return 随机UUID
*/
public static String fastUUID()
{
return UUID.fastUUID().toString();
}
/**
* 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
*
* @return 简化的UUID,去掉了横线
*/
public static String fastSimpleUUID()
{
return UUID.fastUUID().toString(true);
}
}媒体类型工具类
java
/**
* 媒体类型工具类
*
* @author ruoyi
*/
public class MimeTypeUtils {
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPG = "image/jpg";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
public static final String[] FLASH_EXTENSION = {"swf", "flv"};
public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb"};
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// pdf
"pdf"};
public static String getExtension(String prefix) {
switch (prefix) {
case IMAGE_PNG:
return "png";
case IMAGE_JPG:
return "jpg";
case IMAGE_JPEG:
return "jpeg";
case IMAGE_BMP:
return "bmp";
case IMAGE_GIF:
return "gif";
default:
return "";
}
}
/**
* 生成缩略图或视频第一帧图
* @param desFile 源文件
* @param type 文件类型
* @param name 原文件名
* @param path 原文件路径
* @param dir 文件夹ID
* @param fileDirFileId 源文件保存ID
* @param extargs 扩展参数
* @param size 源文件大小
* @author Run the ant(wangyijie)
* @data 2018年4月11日
*/
private void buildImg (java.io.File desFile, String type, String name, String path, Integer dir, Integer fileDirFileId, String extargs, Long size) {
//图片缩略图生成
if (StringUtils.equals(FILE_TYPE_IMAGE, type)) {
//缩略图最大长度限制
Integer thumbnaimax = PropertyEnum.PLATFORM_FILE_IMG_THUMBNAILMAX.getIntValue();
//中间图最大长度限制
Integer middlemax = PropertyEnum.PLATFORM_FILE_IMG_MIDDLEMAX.getIntValue();
//图片长宽比限制
Integer hwratio = PropertyEnum.PLATFORM_FILE_IMG_HWRATIO.getIntValue();
//图片生成中间图大小限制
Integer middlesize = PropertyEnum.PLATFORM_FILE_IMG_MIDDLESIZE.getIntValue();
//图片生成缩略图大小限制
Integer thumbnailsize = PropertyEnum.PLATFORM_FILE_IMG_THUMBNAILSIZE.getIntValue();
boolean flag = false;
if (thumbnaimax == null) {
logger.error("缩略图最大长度限制未配置!");
flag = true;
}
if (middlemax == null) {
logger.error("中间图最大长度限制未配置!");
flag = true;
}
if (hwratio == null) {
logger.error("图片长宽比限制未配置!");
flag = true;
}
if (middlesize == null) {
logger.error("图片生成中间图大小限制未配置!");
flag = true;
}
if (thumbnailsize == null) {
logger.error("图片生成缩略图大小限制未配置!");
flag = true;
}
if (flag) {
return;
}
//开启文件流
FileInputStream fis = null;
try {
fis = new FileInputStream(desFile);
//获取原图的高和宽
BufferedImage bufferedImg = ImageIO.read(fis);
int imgWidth = bufferedImg.getWidth();
int imgHeight = bufferedImg.getHeight();
//默认长的边为h
int h = imgWidth > imgHeight ? imgWidth : imgHeight;
//默认短的边为w
int w = imgWidth <= imgHeight ? imgWidth : imgHeight;
//算出长宽比
Integer hw_ratio = h/w;
//是否需要生成缩略图
boolean isthumbnai = false;
//是否需要生成中间图
boolean ismiddle = false;
//需要进行压缩的文件袋对象
java.io.File tempFile = null;
//长宽比是否超出限制
if (hw_ratio > hwratio) {
/**
* 超出限制需裁剪
*/
java.io.File pFile = null;
//生成新的裁剪图文件名
String pName = fileUtil.buildFileName(name);
if (imgWidth > imgHeight) {
/**
* 横向较长
*/
//计算裁剪左上角x坐标
Integer x = (imgWidth - (imgHeight * hwratio)) / 2;
//裁剪
ImgUtil.cutImage(desFile.getPath(), StringUtils.replace(desFile.getPath(), desFile.getName(), pName), x, 0, imgHeight * hwratio, imgHeight);
} else {
/**
* 纵向较长
*/
//计算裁剪左上角x坐标
Integer x = (imgHeight - (imgWidth * hwratio)) / 2 + imgWidth * hwratio;
//裁剪
ImgUtil.cutImage(desFile.getPath(), StringUtils.replace(desFile.getPath(), desFile.getName(), pName), 0, x, imgWidth, imgWidth * hwratio);
}
//生成裁剪图文件
pFile = new java.io.File(path, pName);
fis = new FileInputStream(pFile);
//获取裁剪图的高和宽
BufferedImage pbufferedImg = ImageIO.read(fis);
int pimgWidth = pbufferedImg.getWidth();
int pimgHeight = pbufferedImg.getHeight();
//默认长的边为h
int ph = pimgWidth > pimgHeight ? pimgWidth : pimgHeight;
//判断裁剪后图片最长的边是否大于系统设置的缩略图最大边长限制,大于则压缩
if (ph > thumbnaimax) {
/**
* 满足生成缩略图标准
*/
isthumbnai = true;
tempFile = pFile;
} else {
//小于直接将裁剪后图片作为缩略图保存
Result<Integer> thumbnaicode = fileUtil.insertLocal(pName, pFile, dir, null, extargs, FileDirFile.VIEWTYPE_THUMBNAIL, fileDirFileId);
if (ErrorCodeUtil.isFail(thumbnaicode)) {
logger.error("生成的缩略图保存失败!文件名称=" + pName + "所属文件名=" + desFile.getName() + "所属文件ID=" + fileDirFileId);
}
}
//是否生成中间图
if (ph > middlemax) {
/**
* 满足生成中间图标准
*/
ismiddle = true;
tempFile = pFile;
}
} else {
//判断文件大小是否满足生成缩略图标准
if (size > thumbnailsize * 1024L) {
//判断该图片最长的边是否大于系统设置的缩略图最大边长限制(大于则压缩,小于则不生成缩略图)
if (h > thumbnaimax) {
/**
* 满足生成缩略图标准
*/
isthumbnai = true;
tempFile = desFile;
}
}
if (size > middlesize * 1024L) {
/**
* 满足生成中间图标准
*/
ismiddle = true;
tempFile = desFile;
}
}
if (isthumbnai) {
//生成新的缩略图文件名
String pName = fileUtil.buildFileName(name);
//图片压缩
ImgUtil.cutImage(thumbnaimax, thumbnaimax, tempFile.getPath(), StringUtils.replace(tempFile.getPath(), tempFile.getName(), pName));
//生成缩略图文件
java.io.File pFile = new java.io.File(path, pName);
//缩略图信息保存到数据库
Result<Integer> thumbnaicode = fileUtil.insertLocal(pName, pFile, dir, null, extargs, FileDirFile.VIEWTYPE_THUMBNAIL, fileDirFileId);
if (ErrorCodeUtil.isFail(thumbnaicode)) {
logger.error("生成的缩略图保存失败!文件名称=" + pName + "所属文件名=" + desFile.getName() + "所属文件ID=" + fileDirFileId);
}
}
if (ismiddle) {
//生成新的中间图文件名
String pName = fileUtil.buildFileName(name);
//压缩
ImgUtil.cutImage(middlemax, middlemax, tempFile.getPath(), StringUtils.replace(tempFile.getPath(), tempFile.getName(), pName));
//生成中间图文件
java.io.File pFile = new java.io.File(path, pName);
//中间图信息保存到数据库
Result<Integer> thumbnaicode = fileUtil.insertLocal(pName, pFile, dir, null, extargs, FileDirFile.VIEWTYPE_MEDIANIMG, fileDirFileId);
if (ErrorCodeUtil.isFail(thumbnaicode)) {
logger.error("生成的中间图保存失败!文件名称=" + pName + "所属文件名=" + desFile.getName() + "所属文件ID=" + fileDirFileId);
}
}
} catch (Exception e) {
logger.error("生成缩略图或中间图错误!文件名称=" + desFile.getName() + "文件路径=" + desFile.getPath() + "错误信息:{}",e);
} finally {
try {
fis.close();
} catch (IOException e) {
logger.error("生成缩略图或中间图错误!文件流关闭异常!" + "错误信息:{}",e);
}
}
} else if (StringUtils.equals(FILE_TYPE_VIDEO, type)) {
/**
* 视频文件 保存视频文件第一帧
*/
//生成新的第一帧图文件名
String srcfile = desFile.getPath();
int i = srcfile.lastIndexOf('.');
String jpgfile = srcfile;
if(i>0){
jpgfile = jpgfile.substring(0,i);
}
jpgfile = jpgfile + ".jpg";
handler(srcfile, jpgfile);
//生成图文件
java.io.File pFile = new java.io.File(jpgfile);
//图信息保存到数据库
Result<Integer> thumbnaicode = fileUtil.insertLocal(pFile.getName(), pFile, dir, null, extargs, FileDirFile.VIEWTYPE_FIRSTIMG, fileDirFileId);
if (ErrorCodeUtil.isFail(thumbnaicode)) {
logger.error("生成的视频第一帧图保存失败!文件名称=" + pFile.getName() + "所属文件名=" + desFile.getName() + "所属文件ID=" + fileDirFileId);
}
}
}
/**
* 截取视频第一帧
* @param upFilePath 源文件路径
* @param mediaPicPath 输出路径
* @author Run the ant(wangyijie)
* @data 2018年4月12日
*/
private static void handler(String upFilePath, String mediaPicPath) {
List<String> cutpic = new ArrayList<String>();
cutpic.add("ffmpeg");
cutpic.add("-i");
cutpic.add(upFilePath); // 指定的文件即可以是转换为flv格式之前的文件,也可以是转换的flv文件
cutpic.add("-y");
cutpic.add("-f");
cutpic.add("image2");
cutpic.add("-ss"); // 添加参数"-ss",该参数指定截取的起始时间
cutpic.add("0"); // 添加起始时间为第0秒
cutpic.add("-t"); // 添加参数"-t",该参数指定持续时间
cutpic.add("0.001"); // 添加持续时间为1毫秒
cutpic.add(mediaPicPath); // 添加截取的图片的保存路径
ProcessBuilder builder = new ProcessBuilder();
try {
builder.command(cutpic);
builder.redirectErrorStream(true);
// 如果此属性为 true,则任何由通过此对象的 start() 方法启动的后续子进程生成的错误输出都将与标准输出合并,
builder.start();
} catch (Exception e) {
logger.error("根据视频生成第一帧图片错误! 源文件路径=" + upFilePath + "输出路径=" + mediaPicPath + "错误信息:{}",e);
}
}
}文件类型工具类
java
/**
* 文件类型工具类
*
* @author ruoyi
*/
public class FileTypeUtils {
/**
* 获取文件类型
* <p>
* 例如: ruoyi.txt, 返回: txt
*
* @param file 文件名
* @return 后缀(不含".")
*/
public static String getFileType(File file) {
if (null == file) {
return StringUtils.EMPTY;
}
return getFileType(file.getName());
}
/**
* 获取文件类型
* <p>
* 例如: ruoyi.txt, 返回: txt
*
* @param fileName 文件名
* @return 后缀(不含".")
*/
public static String getFileType(String fileName) {
int separatorIndex = fileName.lastIndexOf(".");
if (separatorIndex < 0) {
return "";
}
return fileName.substring(separatorIndex + 1).toLowerCase();
}
/**
* 获取文件类型
*
* @param photoByte 文件字节码
* @return 后缀(不含".")
*/
public static String getFileExtendName(byte[] photoByte) {
String strFileExtendName = "JPG";
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) {
strFileExtendName = "GIF";
} else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) {
strFileExtendName = "JPG";
} else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {
strFileExtendName = "BMP";
} else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {
strFileExtendName = "PNG";
}
return strFileExtendName;
}
}文件处理工具类
java
/**
* 文件处理工具类
*
* @author ruoyi
*/
public class FileUtils extends org.apache.commons.io.FileUtils {
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/**
* 输出指定文件的byte数组
*
* @param filePath 文件路径
* @param os 输出流
* @return
*/
public static void writeBytes(String filePath, OutputStream os) throws IOException {
FileInputStream fis = null;
try {
File file = new File(filePath);
if (!file.exists()) {
throw new FileNotFoundException(filePath);
}
fis = new FileInputStream(file);
byte[] b = new byte[1024];
int length;
while ((length = fis.read(b)) > 0) {
os.write(b, 0, length);
}
} catch (IOException e) {
throw e;
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
/**
* 删除文件
*
* @param filePath 文件
* @return
*/
public static boolean deleteFile(String filePath) {
boolean flag = false;
File file = new File(filePath);
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists()) {
file.delete();
flag = true;
}
return flag;
}
/**
* 文件名称验证
*
* @param filename 文件名称
* @return true 正常 false 非法
*/
public static boolean isValidFilename(String filename) {
return filename.matches(FILENAME_PATTERN);
}
/**
* 检查文件是否可下载
*
* @param resource 需要下载的文件
* @return true 正常 false 非法
*/
public static boolean checkAllowDownload(String resource) {
// 禁止目录上跳级别
if (StringUtils.contains(resource, "..")) {
return false;
}
// 检查允许下载的文件规则
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) {
return true;
}
// 不在允许下载的文件规则
return false;
}
/**
* 下载文件名重新编码
*
* @param request 请求对象
* @param fileName 文件名
* @return 编码后的文件名
*/
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
final String agent = request.getHeader("USER-AGENT");
String filename = fileName;
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
filename = new String(fileName.getBytes(), "ISO8859-1");
} else if (agent.contains("Chrome")) {
// google浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
* @return
*/
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
String percentEncodedFileName = percentEncode(realFileName);
StringBuilder contentDispositionValue = new StringBuilder();
contentDispositionValue.append("attachment; filename=")
.append(percentEncodedFileName)
.append(";")
.append("filename*=")
.append("utf-8''")
.append(percentEncodedFileName);
response.setHeader("Content-disposition", contentDispositionValue.toString());
}
/**
* 百分号编码工具方法
*
* @param s 需要百分号编码的字符串
* @return 百分号编码后的字符串
*/
public static String percentEncode(String s) throws UnsupportedEncodingException {
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
}
import org.apache.commons.lang3.ArrayUtils;
import java.io.*;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
/**
* 文件工具类
* @author sunwen
* @since 2019/12/27
*/
public class FileUtils extends org.apache.commons.io.FileUtils {
/**
* 创建文件夹
* @author sunwen
* @since 2020/1/7
*/
public static File mkdirs(String path) throws IOException {
File file = new File(path);
if(file.isDirectory()){
return file;
}else if(file.mkdirs()){
return file;
}
throw new IOException();
}
/**
* 根据文件获取mimeType
* @author sunwen
* @since 2019/12/27
*/
public static String getMimeType(File file){
return getMimeType(file.getName());
}
/**
* 根据文件获取mimeType
* @author sunwen
* @since 2019/12/27
*/
public static String getMimeType(String fileName){
FileNameMap fileNameMap = URLConnection.getFileNameMap();
return fileNameMap.getContentTypeFor(fileName);
}
/**
* 获取文件后缀
* @param fileName 文件名
* @author wuzm
* @date 2020/7/1
*/
public static String getSuffix(String fileName){
if(StringUtils.isBlank(fileName)){
return null;
}
return StringUtils.substringAfterLast(fileName,".");
}
/**
* 拆分大文件
* @param inputStream
* @param size 拆分后每个小文件的大小(单位:MB)
* @param fileName 原文件名称(带后缀)
* @author lijx
* @date 2020/12/11
*/
public static List<File> splitFile(InputStream inputStream, int size, String fileName) throws IOException {
if (size == 0 || null == inputStream) {
return null;
}
//获取文件名和文件后缀
String suffix = "";
if (StringUtils.isNotBlank(fileName)) {
String[] split = StringUtils.split(fileName, ".");
if (ArrayUtils.isNotEmpty(split) && split.length == 2) {
fileName = split[0];
suffix = "." + split[1];
}
} else {
fileName = UUIDUtils.generate();
}
File tempDirPath = new File(System.getProperty("java.io.tmpdir"));
List<File> files = new ArrayList<>();
FileOutputStream fos = null;
byte[] buffer = new byte[1024 * 1024];
int length = 0;
int total = 0;//每次写入1MB,每个文件写入的次数
int index = 0;
try {
File newFile = new File(tempDirPath, fileName + "_" + index + suffix);
fos = new FileOutputStream(newFile);
while ((length = inputStream.read(buffer)) != -1) {//不能一次性读完,大文件会内存溢出
fos.write(buffer, 0, length);
total++;
if (total != size) {
continue;
}
index++;
total = 0;
files.add(newFile);
newFile = new File(tempDirPath, fileName + "_" + index + suffix);
fos = new FileOutputStream(newFile);
}
if (total != 0) {
files.add(newFile);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != fos) fos.close();
}
return files;
}
/**
* 拆分大文件
* @param file
* @param size 拆分后每个小文件的大小(单位:MB)
* @author lijx
* @date 2020/12/11
*/
public static List<File> splitFile(File file, int size) throws IOException {
if (null == file) {
return null;
}
FileInputStream fileInputStream = null;
List<File> files = null;
try {
fileInputStream = new FileInputStream(file);
files = splitFile(fileInputStream, size, file.getName());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != fileInputStream) fileInputStream.close();
}
return files;
}
}文件上传工具类
java
/**
* 文件上传工具类
*
* @author ruoyi
*/
public class FileUploadUtils {
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 默认上传的地址
*/
private static String defaultBaseDir = RuoYiConfig.getProfile();
public static void setDefaultBaseDir(String defaultBaseDir) {
FileUploadUtils.defaultBaseDir = defaultBaseDir;
}
public static String getDefaultBaseDir() {
return defaultBaseDir;
}
/**
* 以默认配置进行文件上传
*
* @param file 上传的文件
* @return 文件名称
* @throws Exception
*/
public static final String upload(MultipartFile file) throws IOException {
try {
return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException {
try {
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException {
int fileNamelength = file.getOriginalFilename().length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
File desc = getAbsoluteFile(baseDir, fileName);
file.transferTo(desc);
String pathFileName = getPathFileName(baseDir, fileName);
return pathFileName;
}
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file) {
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
return fileName;
}
private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.getParentFile().exists()) {
desc.getParentFile().mkdirs();
}
if (!desc.exists()) {
desc.createNewFile();
}
return desc;
}
private static final String getPathFileName(String uploadDir, String fileName) throws IOException {
int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
return pathFileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @return
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException {
long size = file.getSize();
if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE) {
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
} else {
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension) {
for (String str : allowedExtension) {
if (str.equalsIgnoreCase(extension)) {
return true;
}
}
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static final String getExtension(MultipartFile file) {
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension)) {
extension = MimeTypeUtils.getExtension(file.getContentType());
}
return extension;
}
}Servlet客户端工具类
java
/**
* 客户端工具类
*
* @author ruoyi
*/
public class ServletUtils {
/**
* 获取String参数
*/
public static String getParameter(String name) {
return getRequest().getParameter(name);
}
/**
* 获取String参数
*/
public static String getParameter(String name, String defaultValue) {
return Convert.toStr(getRequest().getParameter(name), defaultValue);
}
/**
* 获取Integer参数
*/
public static Integer getParameterToInt(String name) {
return Convert.toInt(getRequest().getParameter(name));
}
/**
* 获取Integer参数
*/
public static Integer getParameterToInt(String name, Integer defaultValue) {
return Convert.toInt(getRequest().getParameter(name), defaultValue);
}
/**
* 获取request
*/
public static HttpServletRequest getRequest() {
return getRequestAttributes().getRequest();
}
/**
* 获取response
*/
public static HttpServletResponse getResponse() {
return getRequestAttributes().getResponse();
}
/**
* 获取session
*/
public static HttpSession getSession() {
return getRequest().getSession();
}
public static ServletRequestAttributes getRequestAttributes() {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
}
/**
* 将字符串渲染到客户端
*
* @param response 渲染对象
* @param string 待渲染的字符串
* @return null
*/
public static String renderString(HttpServletResponse response, String string) {
try {
response.setStatus(200);
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().print(string);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 是否是Ajax异步请求
*
* @param request
*/
public static boolean isAjaxRequest(HttpServletRequest request) {
String accept = request.getHeader("accept");
if (accept != null && accept.indexOf("application/json") != -1) {
return true;
}
String xRequestedWith = request.getHeader("X-Requested-With");
if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) {
return true;
}
String uri = request.getRequestURI();
if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) {
return true;
}
String ajax = request.getParameter("__ajax");
if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) {
return true;
}
return false;
}
}安全服务工具类(获取信息)
java
/**
* 安全服务工具类
*
* @author ruoyi
*/
public class SecurityUtils {
/**
* 获取用户账户
**/
public static String getUsername() {
try {
return getLoginUser().getUsername();
} catch (Exception e) {
throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取用户
**/
public static LoginUser getLoginUser() {
try {
return (LoginUser) getAuthentication().getPrincipal();
} catch (Exception e) {
throw new CustomException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取Authentication
*/
public static Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
/**
* 生成BCryptPasswordEncoder密码
*
* @param password 密码
* @return 加密字符串
*/
public static String encryptPassword(String password) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder.encode(password);
}
/**
* 判断密码是否相同
*
* @param rawPassword 真实密码
* @param encodedPassword 加密后字符
* @return 结果
*/
public static boolean matchesPassword(String rawPassword, String encodedPassword) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder.matches(rawPassword, encodedPassword);
}
/**
* 是否为管理员
*
* @param userId 用户ID
* @return 结果
*/
public static boolean isAdmin(Long userId) {
return userId != null && 1L == userId;
}
}线程相关工具类
java
/**
* 线程相关工具类.
*
* @author ruoyi
*/
public class Threads {
private static final Logger logger = LoggerFactory.getLogger(Threads.class);
/**
* sleep等待,单位为毫秒
*/
public static void sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
return;
}
}
/**
* 停止线程池
* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
* 如果仍人超時,則強制退出.
* 另对在shutdown时线程本身被调用中断做了处理.
*/
public static void shutdownAndAwaitTermination(ExecutorService pool) {
if (pool != null && !pool.isShutdown()) {
pool.shutdown();
try {
if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
logger.info("Pool did not terminate");
}
}
} catch (InterruptedException ie) {
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
/**
* 打印线程异常信息
*/
public static void printException(Runnable r, Throwable t) {
if (t == null && r instanceof Future<?>) {
try {
Future<?> future = (Future<?>) r;
if (future.isDone()) {
future.get();
}
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
if (t != null) {
logger.error(t.getMessage(), t);
}
}
}Spring获取bean工具类
java
/**
* spring工具类 方便在非spring管理环境中获取bean
*
* @author ruoyi
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware {
/**
* Spring应用上下文环境
*/
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringUtils.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringUtils.applicationContext = applicationContext;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T) beanFactory.getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*/
public static <T> T getBean(Class<T> clz) throws BeansException {
T result = (T) beanFactory.getBean(clz);
return result;
}
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name) {
return beanFactory.containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
*
* @param name
* @return boolean
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return beanFactory.isSingleton(name);
}
/**
* @param name
* @return Class 注册对象的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getType(name);
}
/**
* 如果给定的bean名字在bean定义中有别名,则返回这些别名
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getAliases(name);
}
/**
* 获取aop代理对象
*
* @param invoker
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker) {
return (T) AopContext.currentProxy();
}
/**
* 获取当前的环境配置,无配置返回null
*
* @return 当前的环境配置
*/
public static String[] getActiveProfiles() {
return applicationContext.getEnvironment().getActiveProfiles();
}
/**
* 获取当前的环境配置,当有多个环境配置时,只获取第一个
*
* @return 当前的环境配置
*/
public static String getActiveProfile() {
final String[] activeProfiles = getActiveProfiles();
return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
}
}StringUtil扩展工具类
java
/**
* 字符串工具类
*
* @author ruoyi
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils {
/**
* 空字符串
*/
private static final String NULLSTR = "";
/**
* 下划线
*/
private static final char SEPARATOR = '_';
/**
* 获取参数不为空值
*
* @param value defaultValue 要判断的value
* @return value 返回值
*/
public static <T> T nvl(T value, T defaultValue) {
return value != null ? value : defaultValue;
}
/**
* * 判断一个Collection是否为空, 包含List,Set,Queue
*
* @param coll 要判断的Collection
* @return true:为空 false:非空
*/
public static boolean isEmpty(Collection<?> coll) {
return isNull(coll) || coll.isEmpty();
}
/**
* * 判断一个Collection是否非空,包含List,Set,Queue
*
* @param coll 要判断的Collection
* @return true:非空 false:空
*/
public static boolean isNotEmpty(Collection<?> coll) {
return !isEmpty(coll);
}
/**
* * 判断一个对象数组是否为空
*
* @param objects 要判断的对象数组
* * @return true:为空 false:非空
*/
public static boolean isEmpty(Object[] objects) {
return isNull(objects) || (objects.length == 0);
}
/**
* * 判断一个对象数组是否非空
*
* @param objects 要判断的对象数组
* @return true:非空 false:空
*/
public static boolean isNotEmpty(Object[] objects) {
return !isEmpty(objects);
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true:为空 false:非空
*/
public static boolean isEmpty(Map<?, ?> map) {
return isNull(map) || map.isEmpty();
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true:非空 false:空
*/
public static boolean isNotEmpty(Map<?, ?> map) {
return !isEmpty(map);
}
/**
* * 判断一个字符串是否为空串
*
* @param str String
* @return true:为空 false:非空
*/
public static boolean isEmpty(String str) {
return isNull(str) || NULLSTR.equals(str.trim());
}
/**
* * 判断一个字符串是否为非空串
*
* @param str String
* @return true:非空串 false:空串
*/
public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}
/**
* * 判断一个对象是否为空
*
* @param object Object
* @return true:为空 false:非空
*/
public static boolean isNull(Object object) {
return object == null;
}
/**
* * 判断一个对象是否非空
*
* @param object Object
* @return true:非空 false:空
*/
public static boolean isNotNull(Object object) {
return !isNull(object);
}
/**
* * 判断一个对象是否是数组类型(Java基本型别的数组)
*
* @param object 对象
* @return true:是数组 false:不是数组
*/
public static boolean isArray(Object object) {
return isNotNull(object) && object.getClass().isArray();
}
/**
* 去空格
*/
public static String trim(String str) {
return (str == null ? "" : str.trim());
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @return 结果
*/
public static String substring(final String str, int start) {
if (str == null) {
return NULLSTR;
}
if (start < 0) {
start = str.length() + start;
}
if (start < 0) {
start = 0;
}
if (start > str.length()) {
return NULLSTR;
}
return str.substring(start);
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @param end 结束
* @return 结果
*/
public static String substring(final String str, int start, int end) {
if (str == null) {
return NULLSTR;
}
if (end < 0) {
end = str.length() + end;
}
if (start < 0) {
start = str.length() + start;
}
if (end > str.length()) {
end = str.length();
}
if (start > end) {
return NULLSTR;
}
if (start < 0) {
start = 0;
}
if (end < 0) {
end = 0;
}
return str.substring(start, end);
}
/**
* 格式化文本, {} 表示占位符<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* 例:<br>
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param template 文本模板,被替换的部分用 {} 表示
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(String template, Object... params) {
if (isEmpty(params) || isEmpty(template)) {
return template;
}
return StrFormatter.format(template, params);
}
/**
* 字符串转set
*
* @param str 字符串
* @param sep 分隔符
* @return set集合
*/
public static final Set<String> str2Set(String str, String sep) {
return new HashSet<String>(str2List(str, sep, true, false));
}
/**
* 字符串转list
*
* @param str 字符串
* @param sep 分隔符
* @param filterBlank 过滤纯空白
* @param trim 去掉首尾空白
* @return list集合
*/
public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
List<String> list = new ArrayList<String>();
if (StringUtils.isEmpty(str)) {
return list;
}
// 过滤空白字符串
if (filterBlank && StringUtils.isBlank(str)) {
return list;
}
String[] split = str.split(sep);
for (String string : split) {
if (filterBlank && StringUtils.isBlank(string)) {
continue;
}
if (trim) {
string = string.trim();
}
list.add(string);
}
return list;
}
/**
* 下划线转驼峰命名
*/
public static String toUnderScoreCase(String str) {
if (str == null) {
return null;
}
StringBuilder sb = new StringBuilder();
// 前置字符是否大写
boolean preCharIsUpperCase = true;
// 当前字符是否大写
boolean curreCharIsUpperCase = true;
// 下一字符是否大写
boolean nexteCharIsUpperCase = true;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (i > 0) {
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
} else {
preCharIsUpperCase = false;
}
curreCharIsUpperCase = Character.isUpperCase(c);
if (i < (str.length() - 1)) {
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
}
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
sb.append(SEPARATOR);
} else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
sb.append(SEPARATOR);
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs) {
if (str != null && strs != null) {
for (String s : strs) {
if (str.equalsIgnoreCase(trim(s))) {
return true;
}
}
}
return false;
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name) {
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty()) {
// 没必要转换
return "";
} else if (!name.contains("_")) {
// 不含下划线,仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels) {
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty()) {
continue;
}
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
/**
* 驼峰式命名法 例如:user_name->userName
*/
public static String toCamelCase(String s) {
if (s == null) {
return null;
}
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == SEPARATOR) {
upperCase = true;
} else if (upperCase) {
sb.append(Character.toUpperCase(c));
upperCase = false;
} else {
sb.append(c);
}
}
return sb.toString();
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj) {
return (T) obj;
}
}
import org.apache.commons.collections.CollectionUtils;
import java.util.Collection;
import java.util.List;
/**
* 字符串工具类
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils {
public static String defaultString(Object obj, String defaultStr){
return obj == null ? defaultStr : obj.toString();
}
/**
* 判断字符是否是纯字母
* @author sunwen
* @since 2019/9/11
*/
public static boolean isLetter(final CharSequence cs){
if (isEmpty(cs)) {
return false;
}
final int sz = cs.length();
for (int i = 0; i < sz; i++) {
char c = cs.charAt(i);
if (!(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')){
return false;
}
}
return true;
}
/**
* 判断字符是否是纯字母+数字
* @author sunwen
* @since 2019/9/11
*/
public static boolean isLetternumeric(final CharSequence cs){
if (isEmpty(cs)) {
return false;
}
final int sz = cs.length();
for (int i = 0; i < sz; i++) {
char c = cs.charAt(i);
if (!(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9')){
return false;
}
}
return true;
}
/**
* 判断字符串是否一个hex数字
* @author sunwen
* @since 2019/8/7
*/
public static boolean isHexNumeric(final CharSequence cs) {
if (isEmpty(cs)) {
return false;
}
final int sz = cs.length();
for (int i = 0; i < sz; i++) {
char c = cs.charAt(i);
if (!Character.isDigit(c) && !(c >= 'A' && c <= 'F') && !(c >= 'a' && c <= 'f')) {
return false;
}
}
return true;
}
/**
* 判断字符串是否符合java标识符名称
* @author sunwen
* @since 2019/4/2
*/
public static boolean isJavaIdentifier(final CharSequence cs) {
if (isEmpty(cs)) {
return false;
}
final int sz = cs.length();
for (int i = 0; i < sz; i++) {
if (i == 0) {
if (!Character.isJavaIdentifierStart(cs.charAt(i))) {
return false;
}
} else {
if (!Character.isJavaIdentifierPart(cs.charAt(i))) {
return false;
}
}
}
return true;
}
public static boolean isJavaIdentifierPart(final CharSequence cs) {
if (isEmpty(cs)) {
return false;
}
final int sz = cs.length();
for (int i = 0; i < sz; i++) {
if (!Character.isJavaIdentifierPart(cs.charAt(i))) {
return false;
}
}
return true;
}
/**
* 判断字符串是否复合java包名
* @author sunwen
* @since 2019/6/11
*/
public static boolean isJavaPackage(final String cs) {
if (isEmpty(cs)) {
return false;
}
if (startsWith(cs, "\\.") || endsWith(cs, "\\.")) {
return false;
}
String[] parts = split(cs, "\\.");
for (String str : parts) {
if (!isJavaIdentifier(str)) {
return false;
}
}
return true;
}
/**
* 数字分割
* @author sunwen
* @since 2019/5/10
*/
public static Integer[] splitInt(String str, String separatorChars) {
String[] parts = split(str, separatorChars);
Integer[] ints = new Integer[parts.length];
for (int i = 0; i < parts.length; i++) {
ints[i] = Integer.parseInt(parts[i]);
}
return ints;
}
public static String byteToHex(byte[] bytes){
StringBuilder builder = new StringBuilder();
if (bytes == null || bytes.length <= 0) {
return null;
}
for (int i = 0; i < bytes.length; i++) {
int v = bytes[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
builder.append(0);
}
builder.append(hv);
}
return builder.toString();
}
/**
* 将集合用指定字符进行合并成字符串
* @param collection 集合
* @param separatorChars 指定字符
* @author wuzm
* @date 2020/5/17
*/
public static String castToString(Collection collection ,String separatorChars){
if(CollectionUtils.isEmpty(collection)){
return "";
}
StringBuilder stringBuilder = new StringBuilder();
for (Object collectEle : collection) {
if(stringBuilder.length() > 0){
stringBuilder.append(separatorChars);
}
stringBuilder.append(collectEle);
}
return stringBuilder.toString();
}
}redis工具类
java
/**
* spring redis 工具类
*
* @author ruoyi
**/
@SuppressWarnings(value = {"unchecked", "rawtypes"})
@Component
public class RedisCache {
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setCacheObject(final String key, final T value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean deleteObject(final String key) {
return redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public long deleteObject(final Collection collection) {
return redisTemplate.delete(collection);
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList) {
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(final String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext()) {
setOperation.add(it.next());
}
return setOperation;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getCacheMapValue(final String key, final String hKey) {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern) {
return redisTemplate.keys(pattern);
}
}字符集工具类
java
/**
* 字符集工具类
*
* @author ruoyi
*/
public class CharsetKit {
/**
* ISO-8859-1
*/
public static final String ISO_8859_1 = "ISO-8859-1";
/**
* UTF-8
*/
public static final String UTF_8 = "UTF-8";
/**
* GBK
*/
public static final String GBK = "GBK";
/**
* ISO-8859-1
*/
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
/**
* UTF-8
*/
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
/**
* GBK
*/
public static final Charset CHARSET_GBK = Charset.forName(GBK);
/**
* 转换为Charset对象
*
* @param charset 字符集,为空则返回默认字符集
* @return Charset
*/
public static Charset charset(String charset) {
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集,默认ISO-8859-1
* @param destCharset 目标字符集,默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, String srcCharset, String destCharset) {
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集,默认ISO-8859-1
* @param destCharset 目标字符集,默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, Charset srcCharset, Charset destCharset) {
if (null == srcCharset) {
srcCharset = StandardCharsets.ISO_8859_1;
}
if (null == destCharset) {
destCharset = StandardCharsets.UTF_8;
}
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) {
return source;
}
return new String(source.getBytes(srcCharset), destCharset);
}
/**
* @return 系统字符集编码
*/
public static String systemCharset() {
return Charset.defaultCharset().name();
}
}类型转换工具类
java
/**
* 类型转换器
*
* @author ruoyi
*/
public class Convert {
/**
* 转换为字符串<br>
* 如果给定的值为null,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static String toStr(Object value, String defaultValue) {
if (null == value) {
return defaultValue;
}
if (value instanceof String) {
return (String) value;
}
return value.toString();
}
/**
* 转换为字符串<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static String toStr(Object value) {
return toStr(value, null);
}
/**
* 转换为字符<br>
* 如果给定的值为null,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Character toChar(Object value, Character defaultValue) {
if (null == value) {
return defaultValue;
}
if (value instanceof Character) {
return (Character) value;
}
final String valueStr = toStr(value, null);
return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
}
/**
* 转换为字符<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Character toChar(Object value) {
return toChar(value, null);
}
/**
* 转换为byte<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Byte toByte(Object value, Byte defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Byte) {
return (Byte) value;
}
if (value instanceof Number) {
return ((Number) value).byteValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Byte.parseByte(valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为byte<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Byte toByte(Object value) {
return toByte(value, null);
}
/**
* 转换为Short<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Short toShort(Object value, Short defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Short) {
return (Short) value;
}
if (value instanceof Number) {
return ((Number) value).shortValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Short.parseShort(valueStr.trim());
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为Short<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Short toShort(Object value) {
return toShort(value, null);
}
/**
* 转换为Number<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Number toNumber(Object value, Number defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Number) {
return (Number) value;
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return NumberFormat.getInstance().parse(valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为Number<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Number toNumber(Object value) {
return toNumber(value, null);
}
/**
* 转换为int<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Integer toInt(Object value, Integer defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Integer) {
return (Integer) value;
}
if (value instanceof Number) {
return ((Number) value).intValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Integer.parseInt(valueStr.trim());
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为int<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Integer toInt(Object value) {
return toInt(value, null);
}
/**
* 转换为Integer数组<br>
*
* @param str 被转换的值
* @return 结果
*/
public static Integer[] toIntArray(String str) {
return toIntArray(",", str);
}
/**
* 转换为Long数组<br>
*
* @param str 被转换的值
* @return 结果
*/
public static Long[] toLongArray(String str) {
return toLongArray(",", str);
}
/**
* 转换为Integer数组<br>
*
* @param split 分隔符
* @param split 被转换的值
* @return 结果
*/
public static Integer[] toIntArray(String split, String str) {
if (StringUtils.isEmpty(str)) {
return new Integer[]{};
}
String[] arr = str.split(split);
final Integer[] ints = new Integer[arr.length];
for (int i = 0; i < arr.length; i++) {
final Integer v = toInt(arr[i], 0);
ints[i] = v;
}
return ints;
}
/**
* 转换为Long数组<br>
*
* @param split 分隔符
* @param str 被转换的值
* @return 结果
*/
public static Long[] toLongArray(String split, String str) {
if (StringUtils.isEmpty(str)) {
return new Long[]{};
}
String[] arr = str.split(split);
final Long[] longs = new Long[arr.length];
for (int i = 0; i < arr.length; i++) {
final Long v = toLong(arr[i], null);
longs[i] = v;
}
return longs;
}
/**
* 转换为String数组<br>
*
* @param str 被转换的值
* @return 结果
*/
public static String[] toStrArray(String str) {
return toStrArray(",", str);
}
/**
* 转换为String数组<br>
*
* @param split 分隔符
* @param split 被转换的值
* @return 结果
*/
public static String[] toStrArray(String split, String str) {
return str.split(split);
}
/**
* 转换为long<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Long toLong(Object value, Long defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Long) {
return (Long) value;
}
if (value instanceof Number) {
return ((Number) value).longValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
// 支持科学计数法
return new BigDecimal(valueStr.trim()).longValue();
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为long<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Long toLong(Object value) {
return toLong(value, null);
}
/**
* 转换为double<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Double toDouble(Object value, Double defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Double) {
return (Double) value;
}
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
// 支持科学计数法
return new BigDecimal(valueStr.trim()).doubleValue();
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为double<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Double toDouble(Object value) {
return toDouble(value, null);
}
/**
* 转换为Float<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Float toFloat(Object value, Float defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Float) {
return (Float) value;
}
if (value instanceof Number) {
return ((Number) value).floatValue();
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Float.parseFloat(valueStr.trim());
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为Float<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Float toFloat(Object value) {
return toFloat(value, null);
}
/**
* 转换为boolean<br>
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static Boolean toBool(Object value, Boolean defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
valueStr = valueStr.trim().toLowerCase();
switch (valueStr) {
case "true":
return true;
case "false":
return false;
case "yes":
return true;
case "ok":
return true;
case "no":
return false;
case "1":
return true;
case "0":
return false;
default:
return defaultValue;
}
}
/**
* 转换为boolean<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Boolean toBool(Object value) {
return toBool(value, null);
}
/**
* 转换为Enum对象<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
*
* @param clazz Enum的Class
* @param value 值
* @param defaultValue 默认值
* @return Enum
*/
public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue) {
if (value == null) {
return defaultValue;
}
if (clazz.isAssignableFrom(value.getClass())) {
@SuppressWarnings("unchecked")
E myE = (E) value;
return myE;
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return Enum.valueOf(clazz, valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为Enum对象<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
*
* @param clazz Enum的Class
* @param value 值
* @return Enum
*/
public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value) {
return toEnum(clazz, value, null);
}
/**
* 转换为BigInteger<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static BigInteger toBigInteger(Object value, BigInteger defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof BigInteger) {
return (BigInteger) value;
}
if (value instanceof Long) {
return BigInteger.valueOf((Long) value);
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return new BigInteger(valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为BigInteger<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigInteger toBigInteger(Object value) {
return toBigInteger(value, null);
}
/**
* 转换为BigDecimal<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @param defaultValue 转换错误时的默认值
* @return 结果
*/
public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
if (value == null) {
return defaultValue;
}
if (value instanceof BigDecimal) {
return (BigDecimal) value;
}
if (value instanceof Long) {
return new BigDecimal((Long) value);
}
if (value instanceof Double) {
return new BigDecimal((Double) value);
}
if (value instanceof Integer) {
return new BigDecimal((Integer) value);
}
final String valueStr = toStr(value, null);
if (StringUtils.isEmpty(valueStr)) {
return defaultValue;
}
try {
return new BigDecimal(valueStr);
} catch (Exception e) {
return defaultValue;
}
}
/**
* 转换为BigDecimal<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigDecimal toBigDecimal(Object value) {
return toBigDecimal(value, null);
}
/**
* 将对象转为字符串<br>
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @return 字符串
*/
public static String utf8Str(Object obj) {
return str(obj, CharsetKit.CHARSET_UTF_8);
}
/**
* 将对象转为字符串<br>
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @param charsetName 字符集
* @return 字符串
*/
public static String str(Object obj, String charsetName) {
return str(obj, Charset.forName(charsetName));
}
/**
* 将对象转为字符串<br>
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @param charset 字符集
* @return 字符串
*/
public static String str(Object obj, Charset charset) {
if (null == obj) {
return null;
}
if (obj instanceof String) {
return (String) obj;
} else if (obj instanceof byte[] || obj instanceof Byte[]) {
return str((Byte[]) obj, charset);
} else if (obj instanceof ByteBuffer) {
return str((ByteBuffer) obj, charset);
}
return obj.toString();
}
/**
* 将byte数组转为字符串
*
* @param bytes byte数组
* @param charset 字符集
* @return 字符串
*/
public static String str(byte[] bytes, String charset) {
return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
}
/**
* 解码字节码
*
* @param data 字符串
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
* @return 解码后的字符串
*/
public static String str(byte[] data, Charset charset) {
if (data == null) {
return null;
}
if (null == charset) {
return new String(data);
}
return new String(data, charset);
}
/**
* 将编码的byteBuffer数据转换为字符串
*
* @param data 数据
* @param charset 字符集,如果为空使用当前系统字符集
* @return 字符串
*/
public static String str(ByteBuffer data, String charset) {
if (data == null) {
return null;
}
return str(data, Charset.forName(charset));
}
/**
* 将编码的byteBuffer数据转换为字符串
*
* @param data 数据
* @param charset 字符集,如果为空使用当前系统字符集
* @return 字符串
*/
public static String str(ByteBuffer data, Charset charset) {
if (null == charset) {
charset = Charset.defaultCharset();
}
return charset.decode(data).toString();
}
// ----------------------------------------------------------------------- 全角半角转换
/**
* 半角转全角
*
* @param input String.
* @return 全角字符串.
*/
public static String toSBC(String input) {
return toSBC(input, null);
}
/**
* 半角转全角
*
* @param input String
* @param notConvertSet 不替换的字符集合
* @return 全角字符串.
*/
public static String toSBC(String input, Set<Character> notConvertSet) {
char c[] = input.toCharArray();
for (int i = 0; i < c.length; i++) {
if (null != notConvertSet && notConvertSet.contains(c[i])) {
// 跳过不替换的字符
continue;
}
if (c[i] == ' ') {
c[i] = '\u3000';
} else if (c[i] < '\177') {
c[i] = (char) (c[i] + 65248);
}
}
return new String(c);
}
/**
* 全角转半角
*
* @param input String.
* @return 半角字符串
*/
public static String toDBC(String input) {
return toDBC(input, null);
}
/**
* 替换全角为半角
*
* @param text 文本
* @param notConvertSet 不替换的字符集合
* @return 替换后的字符
*/
public static String toDBC(String text, Set<Character> notConvertSet) {
char c[] = text.toCharArray();
for (int i = 0; i < c.length; i++) {
if (null != notConvertSet && notConvertSet.contains(c[i])) {
// 跳过不替换的字符
continue;
}
if (c[i] == '\u3000') {
c[i] = ' ';
} else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
c[i] = (char) (c[i] - 65248);
}
}
String returnString = new String(c);
return returnString;
}
/**
* 数字金额大写转换 先写个完整的然后将如零拾替换成零
*
* @param n 数字
* @return 中文大写数字
*/
public static String digitUppercase(double n) {
String[] fraction = {"角", "分"};
String[] digit = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
String[][] unit = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}};
String head = n < 0 ? "负" : "";
n = Math.abs(n);
String s = "";
for (int i = 0; i < fraction.length; i++) {
s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
}
if (s.length() < 1) {
s = "整";
}
int integerPart = (int) Math.floor(n);
for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
String p = "";
for (int j = 0; j < unit[1].length && n > 0; j++) {
p = digit[integerPart % 10] + unit[1][j] + p;
integerPart = integerPart / 10;
}
s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
}
return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
}
}字符串格式化工具类
java
/**
* 字符串格式化
*
* @author ruoyi
*/
public class StrFormatter {
public static final String EMPTY_JSON = "{}";
public static final char C_BACKSLASH = '\\';
public static final char C_DELIM_START = '{';
public static final char C_DELIM_END = '}';
/**
* 格式化字符串<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* 例:<br>
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param strPattern 字符串模板
* @param argArray 参数列表
* @return 结果
*/
public static String format(final String strPattern, final Object... argArray) {
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) {
return strPattern;
}
final int strPatternLength = strPattern.length();
// 初始化定义好的长度以获得更好的性能
StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
int handledPosition = 0;
int delimIndex;// 占位符所在位置
for (int argIndex = 0; argIndex < argArray.length; argIndex++) {
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
if (delimIndex == -1) {
if (handledPosition == 0) {
return strPattern;
} else { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
sbuf.append(strPattern, handledPosition, strPatternLength);
return sbuf.toString();
}
} else {
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) {
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) {
// 转义符之前还有一个转义符,占位符依旧有效
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
} else {
// 占位符被转义
argIndex--;
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(C_DELIM_START);
handledPosition = delimIndex + 1;
}
} else {
// 正常占位符
sbuf.append(strPattern, handledPosition, delimIndex);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
}
}
// 加入最后一个占位符后所有的字符
sbuf.append(strPattern, handledPosition, strPattern.length());
return sbuf.toString();
}
}Bean扩展工具类
java
/**
* Bean 工具类
*
* @author ruoyi
*/
public class BeanUtils extends org.springframework.beans.BeanUtils {
/**
* Bean方法名中属性名开始的下标
*/
private static final int BEAN_METHOD_PROP_INDEX = 3;
/**
* 匹配getter方法的正则表达式
*/
private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");
/**
* 匹配setter方法的正则表达式
*/
private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");
/**
* Bean属性复制工具方法。
*
* @param dest 目标对象
* @param src 源对象
*/
public static void copyBeanProp(Object dest, Object src) {
try {
copyProperties(src, dest);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取对象的setter方法。
*
* @param obj 对象
* @return 对象的setter方法列表
*/
public static List<Method> getSetterMethods(Object obj) {
// setter方法列表
List<Method> setterMethods = new ArrayList<Method>();
// 获取所有方法
Method[] methods = obj.getClass().getMethods();
// 查找setter方法
for (Method method : methods) {
Matcher m = SET_PATTERN.matcher(method.getName());
if (m.matches() && (method.getParameterTypes().length == 1)) {
setterMethods.add(method);
}
}
// 返回setter方法列表
return setterMethods;
}
/**
* 获取对象的getter方法。
*
* @param obj 对象
* @return 对象的getter方法列表
*/
public static List<Method> getGetterMethods(Object obj) {
// getter方法列表
List<Method> getterMethods = new ArrayList<Method>();
// 获取所有方法
Method[] methods = obj.getClass().getMethods();
// 查找getter方法
for (Method method : methods) {
Matcher m = GET_PATTERN.matcher(method.getName());
if (m.matches() && (method.getParameterTypes().length == 0)) {
getterMethods.add(method);
}
}
// 返回getter方法列表
return getterMethods;
}
/**
* 检查Bean方法名中的属性名是否相等。<br>
* 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。
*
* @param m1 方法名1
* @param m2 方法名2
* @return 属性名一样返回true,否则返回false
*/
public static boolean isMethodPropEquals(String m1, String m2) {
return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
}
}
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.cglib.beans.BeanMap;
import java.util.*;
/**
* 对Bean进行操作的相关工具方法
* @author sunwen
* date 2019/4/20
*/
public class BeanUtils {
/** NULL属性过滤 */
public static final PropertyFilter FILTER_NULL = new NullPropertyFilter();
/** 空属性过滤 */
public static final PropertyFilter FILTER_EMPTY = new EmptyPropertyFilter();
public interface PropertyFilter{
boolean accept(String name, Object value);
}
public interface BeanCopier<S, T>{
void copyBean(S source, T target);
}
public static class NullPropertyFilter implements PropertyFilter{
@Override
public boolean accept(String name, Object value) {
return value != null;
}
}
public static class EmptyPropertyFilter implements PropertyFilter{
@Override
public boolean accept(String name, Object value) {
return value != null && (!(value instanceof CharSequence) || !"".equals(value));
}
}
/**
* 批量对象拷贝(支持Map -> Bean Bean -> Map)
* Note: 暂不支持不同范型对象的拷贝(例如Result<User> -> Result<UserBean>)
* @param source 源对象
* @param targetClass 目标对象
* @author sunwen
* @since 2019/4/20
*/
public static <T, S> List<T> batchCopyProperties(List<S> source, Class<T> targetClass) throws BeansException{
return batchCopyProperties(source, targetClass, null);
}
/**
* 批量对象拷贝(支持Map -> Bean Bean -> Map)
* Note: 暂不支持不同范型对象的拷贝(例如Result<User> -> Result<UserBean>)
* @param source 源对象
* @param targetClass 目标对象
* @author sunwen
* @since 2019/4/20
*/
public static <S, T> List<T> batchCopyProperties(List<S> source, Class<T> targetClass, BeanCopier<S, T> copier) throws BeansException{
List<T> list = new ArrayList<>();
for(S obj : source){
T target;
try {
target = targetClass.newInstance();
}catch (Exception e){
throw new BeanCreationException(targetClass.getName(), "Bean创建失败", e);
}
copyProperties(obj, target, null);
if(copier != null){
copier.copyBean(obj, target);
}
list.add(target);
}
return list;
}
/**
* 对象拷贝(支持Map -> Bean Bean -> Map)
* Note: 暂不支持不同范型对象的拷贝(例如Result<User> -> Result<UserBean>)
* @param source 源对象
* @param target 目标对象
* @author sunwen
* @since 2019/4/20
*/
public static void copyProperties(Object source, Object target) throws BeansException{
copyProperties(source, target, null);
}
/**
* 拷贝对象(支持Map -> Bean Bean -> Map)
* Note: 暂不支持不同范型对象的拷贝(例如Result<User> -> Result<UserBean>)
* @param source 源对象
* @param target 目标对象
* @param filter 属性过滤
* @author sunwen
* @since 2019/4/20
*/
public static void copyProperties(Object source, Object target, PropertyFilter filter) throws BeansException{
//TODO sunwen 范型拷贝
if(target == null || source == null){
return;
}
if(target instanceof Map){
Map<?, ?> sourceMap;
if(source instanceof Map){
sourceMap = (Map<?, ?>) source;
}else{
sourceMap = BeanMap.create(source);
}
if(filter != null){
Map<String, Object> filted = new HashMap<>();
for(Map.Entry entry : sourceMap.entrySet()){
String key = entry.getKey().toString();
Object value = entry.getValue();
if(filter.accept(key, value)){
filted.put(key, value);
}
}
sourceMap = filted;
}
((Map) target).putAll(sourceMap);
}else if(source instanceof Map || filter != null){
Map<?, ?> sourceMap;
if(source instanceof Map){
sourceMap = (Map<?, ?>) source;
}else{
sourceMap = BeanMap.create(source);
}
for(Map.Entry entry : sourceMap.entrySet()){
String key = entry.getKey().toString();
Object value = entry.getValue();
if(filter == null || filter.accept(key, value)){
try {
PropertyUtils.setSimpleProperty(target, key, value);
}catch (Exception e){
//ignore
}
}
}
}else{
org.springframework.beans.BeanUtils.copyProperties(source, target);
}
}
/**
* 比较新/老数据,返回发生变更的数据
* Note:
* 1.变更的数据包括新增的数据和变化的数据
* 2.old_obj的属性如果在new_obj中不存在(map表现为key不存在)或被过滤的属性将不进行比较
* @param old_obj 老数据
* @param new_obj 新数据
* @param filter 属性过滤(例如:去除new_obj中为空的属性)
* @author sunwen
* @since 2019/4/20
*/
public static Map<String, Object> compareDifferent(Object old_obj, Object new_obj, PropertyFilter filter) {
Map<String, Object> old_map = new HashMap<>();
copyProperties(old_obj, old_map, filter);
Map<String, Object> new_map = new HashMap<>();
copyProperties(new_obj, new_map, filter);
return compareMap(old_map, new_map);
}
/**
* new_map中存在的数据和old_map数据比较,返回与old不相同或old中不存在的数据
* @param old_map 老数据
* @param new_map 新数据
* @author sunwen
* @since 2019/7/16
*/
private static Map<String, Object> compareMap(Map<String, Object> old_map, Map<String, Object> new_map) {
Map<String, Object> change = new HashMap<String, Object>();
if(new_map == null || new_map.size() == 0){
return change;
}else if(old_map == null || old_map.size() == 0){
change.putAll(new_map);
return change;
}
//新增或者修改的
for (Map.Entry<String, Object> entry : new_map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if(value == null){
if(old_map.get(key) == null){
continue;
}
}else if(value.equals(old_map.get(key))){
continue;
}
change.put(key, value);
}
return change;
}
/**
* 该方法将给定的所有对象参数列表转换合并生成一个Map,对于同名属性,依次由后面替换前面的对象属性
* @param objs 对象列表
* @return 对于值为null的对象将忽略掉
*/
public static Map<String, Object> toMap(Object... objs) {
Map<String, Object> map = new HashMap<String, Object>();
for (Object object : objs) {
if (object != null) {
map.putAll(BeanMap.create(object));
}
}
return map;
}
}图片处理工具类
java
/**
* 图片处理工具类
*
* @author ruoyi
*/
public class ImageUtils {
private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
public static byte[] getImage(String imagePath) {
InputStream is = getFile(imagePath);
try {
return IOUtils.toByteArray(is);
} catch (Exception e) {
log.error("图片加载异常 {}", e);
return null;
} finally {
IOUtils.closeQuietly(is);
}
}
public static InputStream getFile(String imagePath) {
try {
byte[] result = readFile(imagePath);
result = Arrays.copyOf(result, result.length);
return new ByteArrayInputStream(result);
} catch (Exception e) {
log.error("获取图片异常 {}", e);
}
return null;
}
/**
* 读取文件为字节数据
*
* @param key 地址
* @return 字节数据
*/
public static byte[] readFile(String url) {
InputStream in = null;
ByteArrayOutputStream baos = null;
try {
if (url.startsWith("http")) {
// 网络地址
URL urlObj = new URL(url);
URLConnection urlConnection = urlObj.openConnection();
urlConnection.setConnectTimeout(30 * 1000);
urlConnection.setReadTimeout(60 * 1000);
urlConnection.setDoInput(true);
in = urlConnection.getInputStream();
} else {
// 本机地址
String localPath = RuoYiConfig.getProfile();
String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
in = new FileInputStream(downloadPath);
}
return IOUtils.toByteArray(in);
} catch (Exception e) {
log.error("获取文件路径异常 {}", e);
return null;
} finally {
IOUtils.closeQuietly(baos);
}
}
}转义和反转义工具类
java
/**
* 转义和反转义工具类
*
* @author ruoyi
*/
public class EscapeUtil {
public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
private static final char[][] TEXT = new char[64][];
static {
for (int i = 0; i < 64; i++) {
TEXT[i] = new char[]{(char) i};
}
// special HTML characters
TEXT['\''] = "'".toCharArray(); // 单引号
TEXT['"'] = """.toCharArray(); // 单引号
TEXT['&'] = "&".toCharArray(); // &符
TEXT['<'] = "<".toCharArray(); // 小于号
TEXT['>'] = ">".toCharArray(); // 大于号
}
/**
* 转义文本中的HTML字符为安全的字符
*
* @param text 被转义的文本
* @return 转义后的文本
*/
public static String escape(String text) {
return encode(text);
}
/**
* 还原被转义的HTML特殊字符
*
* @param content 包含转义符的HTML内容
* @return 转换后的字符串
*/
public static String unescape(String content) {
return decode(content);
}
/**
* 清除所有HTML标签,但是不删除标签内的内容
*
* @param content 文本
* @return 清除标签后的文本
*/
public static String clean(String content) {
return new HTMLFilter().filter(content);
}
/**
* Escape编码
*
* @param text 被编码的文本
* @return 编码后的字符
*/
private static String encode(String text) {
int len;
if ((text == null) || ((len = text.length()) == 0)) {
return StringUtils.EMPTY;
}
StringBuilder buffer = new StringBuilder(len + (len >> 2));
char c;
for (int i = 0; i < len; i++) {
c = text.charAt(i);
if (c < 64) {
buffer.append(TEXT[c]);
} else {
buffer.append(c);
}
}
return buffer.toString();
}
/**
* Escape解码
*
* @param content 被转义的内容
* @return 解码后的字符串
*/
public static String decode(String content) {
if (StringUtils.isEmpty(content)) {
return content;
}
StringBuilder tmp = new StringBuilder(content.length());
int lastPos = 0, pos = 0;
char ch;
while (lastPos < content.length()) {
pos = content.indexOf("%", lastPos);
if (pos == lastPos) {
if (content.charAt(pos + 1) == 'u') {
ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
tmp.append(ch);
lastPos = pos + 6;
} else {
ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
tmp.append(ch);
lastPos = pos + 3;
}
} else {
if (pos == -1) {
tmp.append(content.substring(lastPos));
lastPos = content.length();
} else {
tmp.append(content.substring(lastPos, pos));
lastPos = pos;
}
}
}
return tmp.toString();
}
public static void main(String[] args) {
String html = "<script>alert(1);</script>";
// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
// String html = "<123";
// String html = "123>";
System.out.println(EscapeUtil.clean(html));
System.out.println(EscapeUtil.escape(html));
System.out.println(EscapeUtil.unescape(html));
}
}HTML过滤器
java
/**
* HTML过滤器,用于去除XSS漏洞隐患。
*
* @author ruoyi
*/
public final class HTMLFilter {
/**
* regex flag union representing /si modifiers in php
**/
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
private static final Pattern P_END_ARROW = Pattern.compile("^>");
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_AMP = Pattern.compile("&");
private static final Pattern P_QUOTE = Pattern.compile("\"");
private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
// @xxx could grow large... maybe use sesat's ReferenceMap
private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
/**
* set of allowed html elements, along with allowed attributes for each element
**/
private final Map<String, List<String>> vAllowed;
/**
* counts of open tags for each (allowable) html element
**/
private final Map<String, Integer> vTagCounts = new HashMap<>();
/**
* html elements which must always be self-closing (e.g. "<img />")
**/
private final String[] vSelfClosingTags;
/**
* html elements which must always have separate opening and closing tags (e.g. "<b></b>")
**/
private final String[] vNeedClosingTags;
/**
* set of disallowed html elements
**/
private final String[] vDisallowed;
/**
* attributes which should be checked for valid protocols
**/
private final String[] vProtocolAtts;
/**
* allowed protocols
**/
private final String[] vAllowedProtocols;
/**
* tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
**/
private final String[] vRemoveBlanks;
/**
* entities allowed within html markup
**/
private final String[] vAllowedEntities;
/**
* flag determining whether comments are allowed in input String.
*/
private final boolean stripComment;
private final boolean encodeQuotes;
/**
* flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>"
* becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
*/
private final boolean alwaysMakeTags;
/**
* Default constructor.
*/
public HTMLFilter() {
vAllowed = new HashMap<>();
final ArrayList<String> a_atts = new ArrayList<>();
a_atts.add("href");
a_atts.add("target");
vAllowed.put("a", a_atts);
final ArrayList<String> img_atts = new ArrayList<>();
img_atts.add("src");
img_atts.add("width");
img_atts.add("height");
img_atts.add("alt");
vAllowed.put("img", img_atts);
final ArrayList<String> no_atts = new ArrayList<>();
vAllowed.put("b", no_atts);
vAllowed.put("strong", no_atts);
vAllowed.put("i", no_atts);
vAllowed.put("em", no_atts);
vSelfClosingTags = new String[]{"img"};
vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};
vDisallowed = new String[]{};
vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.
vProtocolAtts = new String[]{"src", "href"};
vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
stripComment = true;
encodeQuotes = true;
alwaysMakeTags = false;
}
/**
* Map-parameter configurable constructor.
*
* @param conf map containing configuration. keys match field names.
*/
@SuppressWarnings("unchecked")
public HTMLFilter(final Map<String, Object> conf) {
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
vDisallowed = (String[]) conf.get("vDisallowed");
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
vProtocolAtts = (String[]) conf.get("vProtocolAtts");
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
vAllowedEntities = (String[]) conf.get("vAllowedEntities");
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
}
private void reset() {
vTagCounts.clear();
}
// ---------------------------------------------------------------
// my versions of some PHP library functions
public static String chr(final int decimal) {
return String.valueOf((char) decimal);
}
public static String htmlSpecialChars(final String s) {
String result = s;
result = regexReplace(P_AMP, "&", result);
result = regexReplace(P_QUOTE, """, result);
result = regexReplace(P_LEFT_ARROW, "<", result);
result = regexReplace(P_RIGHT_ARROW, ">", result);
return result;
}
// ---------------------------------------------------------------
/**
* given a user submitted input String, filter out any invalid or restricted html.
*
* @param input text (i.e. submitted by a user) than may contain html
* @return "clean" version of input, with only valid, whitelisted html elements allowed
*/
public String filter(final String input) {
reset();
String s = input;
s = escapeComments(s);
s = balanceHTML(s);
s = checkTags(s);
s = processRemoveBlanks(s);
// s = validateEntities(s);
return s;
}
public boolean isAlwaysMakeTags() {
return alwaysMakeTags;
}
public boolean isStripComments() {
return stripComment;
}
private String escapeComments(final String s) {
final Matcher m = P_COMMENTS.matcher(s);
final StringBuffer buf = new StringBuffer();
if (m.find()) {
final String match = m.group(1); // (.*?)
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
}
m.appendTail(buf);
return buf.toString();
}
private String balanceHTML(String s) {
if (alwaysMakeTags) {
//
// try and form html
//
s = regexReplace(P_END_ARROW, "", s);
// 不追加结束标签
s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
} else {
//
// escape stray brackets
//
s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s);
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s);
//
// the last regexp causes '<>' entities to appear
// (we need to do a lookahead assertion so that the last bracket can
// be used in the next pass of the regexp)
//
s = regexReplace(P_BOTH_ARROWS, "", s);
}
return s;
}
private String checkTags(String s) {
Matcher m = P_TAGS.matcher(s);
final StringBuffer buf = new StringBuffer();
while (m.find()) {
String replaceStr = m.group(1);
replaceStr = processTag(replaceStr);
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
}
m.appendTail(buf);
// these get tallied in processTag
// (remember to reset before subsequent calls to filter method)
final StringBuilder sBuilder = new StringBuilder(buf.toString());
for (String key : vTagCounts.keySet()) {
for (int ii = 0; ii < vTagCounts.get(key); ii++) {
sBuilder.append("</").append(key).append(">");
}
}
s = sBuilder.toString();
return s;
}
private String processRemoveBlanks(final String s) {
String result = s;
for (String tag : vRemoveBlanks) {
if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) {
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
}
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) {
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
}
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
}
return result;
}
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {
Matcher m = regex_pattern.matcher(s);
return m.replaceAll(replacement);
}
private String processTag(final String s) {
// ending tags
Matcher m = P_END_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
if (allowed(name)) {
if (false == inArray(name, vSelfClosingTags)) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) - 1);
return "</" + name + ">";
}
}
}
}
// starting tags
m = P_START_TAG.matcher(s);
if (m.find()) {
final String name = m.group(1).toLowerCase();
final String body = m.group(2);
String ending = m.group(3);
// debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
if (allowed(name)) {
final StringBuilder params = new StringBuilder();
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
final List<String> paramNames = new ArrayList<>();
final List<String> paramValues = new ArrayList<>();
while (m2.find()) {
paramNames.add(m2.group(1)); // ([a-z0-9]+)
paramValues.add(m2.group(3)); // (.*?)
}
while (m3.find()) {
paramNames.add(m3.group(1)); // ([a-z0-9]+)
paramValues.add(m3.group(3)); // ([^\"\\s']+)
}
String paramName, paramValue;
for (int ii = 0; ii < paramNames.size(); ii++) {
paramName = paramNames.get(ii).toLowerCase();
paramValue = paramValues.get(ii);
// debug( "paramName='" + paramName + "'" );
// debug( "paramValue='" + paramValue + "'" );
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
if (allowedAttribute(name, paramName)) {
if (inArray(paramName, vProtocolAtts)) {
paramValue = processParamProtocol(paramValue);
}
params.append(' ').append(paramName).append("=\"").append(paramValue).append("\"");
}
}
if (inArray(name, vSelfClosingTags)) {
ending = " /";
}
if (inArray(name, vNeedClosingTags)) {
ending = "";
}
if (ending == null || ending.length() < 1) {
if (vTagCounts.containsKey(name)) {
vTagCounts.put(name, vTagCounts.get(name) + 1);
} else {
vTagCounts.put(name, 1);
}
} else {
ending = " /";
}
return "<" + name + params + ending + ">";
} else {
return "";
}
}
// comments
m = P_COMMENT.matcher(s);
if (!stripComment && m.find()) {
return "<" + m.group() + ">";
}
return "";
}
private String processParamProtocol(String s) {
s = decodeEntities(s);
final Matcher m = P_PROTOCOL.matcher(s);
if (m.find()) {
final String protocol = m.group(1);
if (!inArray(protocol, vAllowedProtocols)) {
// bad protocol, turn into local anchor link instead
s = "#" + s.substring(protocol.length() + 1);
if (s.startsWith("#//")) {
s = "#" + s.substring(3);
}
}
}
return s;
}
private String decodeEntities(String s) {
StringBuffer buf = new StringBuffer();
Matcher m = P_ENTITY.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.decode(match).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENTITY_UNICODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENCODE.matcher(s);
while (m.find()) {
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
s = validateEntities(s);
return s;
}
private String validateEntities(final String s) {
StringBuffer buf = new StringBuffer();
// validate entities throughout the string
Matcher m = P_VALID_ENTITIES.matcher(s);
while (m.find()) {
final String one = m.group(1); // ([^&;]*)
final String two = m.group(2); // (?=(;|&|$))
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
}
m.appendTail(buf);
return encodeQuotes(buf.toString());
}
private String encodeQuotes(final String s) {
if (encodeQuotes) {
StringBuffer buf = new StringBuffer();
Matcher m = P_VALID_QUOTES.matcher(s);
while (m.find()) {
final String one = m.group(1); // (>|^)
final String two = m.group(2); // ([^<]+?)
final String three = m.group(3); // (<|$)
// 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two)
m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three));
}
m.appendTail(buf);
return buf.toString();
} else {
return s;
}
}
private String checkEntity(final String preamble, final String term) {
return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble;
}
private boolean isValidEntity(final String entity) {
return inArray(entity, vAllowedEntities);
}
private static boolean inArray(final String s, final String[] array) {
for (String item : array) {
if (item != null && item.equals(s)) {
return true;
}
}
return false;
}
private boolean allowed(final String name) {
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
}
private boolean allowedAttribute(final String name, final String paramName) {
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
}
}通用http发送
java
/**
* 通用http发送方法
*
* @author ruoyi
*/
public class HttpUtils {
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
return sendGet(url, param, Constants.UTF8);
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @param contentType 编码类型
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param, String contentType) {
StringBuilder result = new StringBuilder();
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
log.info("sendGet - {}", urlNameString);
URL realUrl = new URL(urlNameString);
URLConnection connection = realUrl.openConnection();
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
log.info("recv - {}", result);
} catch (ConnectException e) {
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
} catch (SocketTimeoutException e) {
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
} catch (IOException e) {
log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
} catch (Exception e) {
log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception ex) {
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try {
String urlNameString = url;
log.info("sendPost - {}", urlNameString);
URL realUrl = new URL(urlNameString);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
log.info("recv - {}", result);
} catch (ConnectException e) {
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
} catch (SocketTimeoutException e) {
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
} catch (IOException e) {
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
} catch (Exception e) {
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
public static String sendSSLPost(String url, String param) {
StringBuilder result = new StringBuilder();
String urlNameString = url + "?" + param;
try {
log.info("sendSSLPost - {}", urlNameString);
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());
URL console = new URL(urlNameString);
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.connect();
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String ret = "";
while ((ret = br.readLine()) != null) {
if (ret != null && !"".equals(ret.trim())) {
result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8"));
}
}
log.info("recv - {}", result);
conn.disconnect();
br.close();
} catch (ConnectException e) {
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
} catch (SocketTimeoutException e) {
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
} catch (IOException e) {
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
} catch (Exception e) {
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
}
return result.toString();
}
private static class TrustAnyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
private static class TrustAnyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
}
import org.apache.commons.collections.MapUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class HttpUtils {
private static CloseableHttpClient httpClient = HttpClients.createDefault();
/**
* post请求支持文件参数(params put {@link FileBody})
* @author sunwen
* @since 2019/12/26
*/
public static String postMultipart(String url, Map<String, Object> params) throws IOException, HttpException {
// SSLContext sslContext = SSLContexts.createSystemDefault();
//// sslcontext.init(null, new X509TrustManager[]{new HttpsTrustManager()}, new SecureRandom());
// SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
// httpClient = HttpClients.custom().setSSLSocketFactory(factory).build();
MultipartEntityBuilder bulider = MultipartEntityBuilder.create()
.setCharset(StandardCharsets.UTF_8)
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
for(Map.Entry<String, Object> entry : params.entrySet()){
String key = entry.getKey();
Object value = entry.getValue();
if(value instanceof FileBody){
bulider.addPart(key, (FileBody) value);
}else{
bulider.addTextBody(key, StringUtils.defaultString(value, ""),
ContentType.create("text/plain", StandardCharsets.UTF_8));
}
}
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(bulider.build());
String result;
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPost);
int status = response.getStatusLine().getStatusCode();
if (HttpStatus.SC_OK == status) {
HttpEntity entity = response.getEntity();
try {
result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
}finally {
EntityUtils.consume(entity);
}
}else{
throw new HttpException("请求失败:" + status);
}
} finally {
if(response != null){
response.close();
}
// httpPost.releaseConnection();
}
return result;
}
/**
* 将文件转换为一个FileBody对象
* @param filename 自定义文件名 为空从文件中获取
* @author sunwen
* @since 2020/1/7
*/
public static FileBody fromFile(File file, String filename){
if(StringUtils.isEmpty(filename)){
filename = file.getName();
}
ContentType contentType = ContentType.create(StringUtils.defaultString(FileUtils.getMimeType(filename),
"*/*"), StandardCharsets.UTF_8);
return new FileBody(file, contentType, filename);
}
public static String post(String url, Map<String, Object> args) throws Exception {
return post(url, null, args);
}
/**
* Post调用,请求响应参数使用UTF-8字符集
* @param url HTTP URL
* @param header 请求头
* @param args 参数集合
* @return
* @throws Exception
*/
public static String post(String url, Map<String, Object> header, Map<String, Object> args) throws Exception {
return post(url,header,args,StandardCharsets.UTF_8.toString(),StandardCharsets.UTF_8.toString());
}
/**
* Post调用
*
* @param url HTTP URL
* @param header 请求头
* @param args 参数集合
* @param reqCharset 请求参数字符集
* @param respCharset 响应参数字符集
* @return
* @throws Exception
*/
public static String post(String url, Map<String, Object> header, Map<String, Object> args,String reqCharset,String respCharset) throws Exception {
HttpPost httpPost = new HttpPost(url);
CloseableHttpResponse response = null;
try {
if(header != null){
for(Map.Entry<String, Object> entry : header.entrySet()){
Object value = entry.getValue();
if(value == null){
httpPost.setHeader(entry.getKey(), "");
}else{
if(null!=reqCharset){
httpPost.setHeader(entry.getKey(), URLEncoder.encode(value.toString(), reqCharset));
}else{
httpPost.setHeader(entry.getKey(), value.toString());
}
}
}
}
List<NameValuePair> pairList = new ArrayList<>(args.size());
for (Map.Entry<String, Object> entry : args.entrySet()) {
NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue()==null?"":entry.getValue().toString());
pairList.add(pair);
}
if(null!=reqCharset){
httpPost.setEntity(new UrlEncodedFormEntity(pairList, reqCharset));
}else{
httpPost.setEntity(new UrlEncodedFormEntity(pairList));
}
response = httpClient.execute(httpPost);
int status = response.getStatusLine().getStatusCode();
if (HttpStatus.SC_OK == status) {
HttpEntity entity = response.getEntity();
if (entity != null) {
String result=null;
if(null!=respCharset){
result = EntityUtils.toString(response.getEntity(), respCharset);
}else{
result = EntityUtils.toString(response.getEntity());
}
return result;
}
}
} finally {
httpPost.releaseConnection();
if (response != null) {
try {
EntityUtils.consume(response.getEntity());
response.close();
} catch (IOException e) {
//ignore
}
}
}
return null;
}
/**
* get请求
*/
public static String sendGet(String url) throws IOException {
return sendGet(url, null);
}
//添加是否验签方法
public static String sendGet(String url,boolean isSign) throws IOException {
Map<String, String> headers = new HashMap<>();
if(isSign){
headers.put("X-Sign",SignUtils.generate(SignUtils.DEFAULT_KEY,""));
}
return sendGet(url, headers);
}
public static String sendGet(String url, Map<String, String> headers,boolean isSign) throws IOException {
if(isSign){
if(MapUtils.isEmpty(headers)){
headers = new HashMap<>();
}
headers.put("X-Sign", SignUtils.generate(SignUtils.DEFAULT_KEY, ""));
}
return new String(sendGetByte(url, headers), StandardCharsets.UTF_8);
}
public static String sendGet(String url, Map<String, String> headers) throws IOException {
return new String(sendGetByte(url, headers), StandardCharsets.UTF_8);
}
public static byte[] sendGetByte(String url, Map<String, String> headers) throws IOException {
try (InputStream is = get(url, headers)) {
return readByte(is);
}
}
public static InputStream get(String url, Map<String, String> headers) throws IOException {
URL realUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
setHeader(conn, headers);
// 发送POST请求必须设置如下两行
conn.setDoOutput(false);
conn.setDoInput(true);
// 定义BufferedReader输入流来读取URL的响应
int statusCode = conn.getResponseCode();
if(HttpStatus.SC_OK == statusCode){
return conn.getInputStream();
}
throw new IOException( url + " 请求失败:" + statusCode);
}
public static void setHeader(URLConnection conn, Map<String, String> headers) {
// 设置通用的请求属性
Map<String, String> defaultHeaders = new HashMap<>();
defaultHeaders.put("Accept", "*/*");
defaultHeaders.put("Connection", "Keep-Alive");
defaultHeaders.put("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
if (headers != null) {
Map<String, String> lowerCaseHeaders = new HashMap<>();
for (String hKey : headers.keySet()) {
lowerCaseHeaders.put(hKey.toLowerCase(), headers.get(hKey));
}
for (String hKey : defaultHeaders.keySet()) {
if (!lowerCaseHeaders.containsKey(hKey.toLowerCase())) {
headers.put(hKey, defaultHeaders.get(hKey));
}
}
} else {
headers = defaultHeaders;
}
for (String hKey : headers.keySet()) {
conn.setRequestProperty(hKey, headers.get(hKey));
}
}
public static byte[] readByte(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
return out.toByteArray();
}
/**
* Post调用,传递JSON 数据格式
*
* @param url HTTP URL
* @param jsonString 参数
* @return
* @throws Exception
*/
public static String postJson(String url, String jsonString) {
return postJson(url,jsonString,false);
}
public static String postJson(String url, String jsonString,boolean isSign) {
return postJson(url,jsonString,isSign,30000,30000,30000);
}
public static String postJson(String url, String jsonString,boolean isSign,Integer connTime,Integer requestTimeOut,Integer socketTime) {
CloseableHttpResponse response = null;
BufferedReader in = null;
String result = "";
try {
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connTime).setConnectionRequestTimeout(requestTimeOut).setSocketTimeout(socketTime).build();
httpPost.setConfig(requestConfig);
httpPost.setConfig(requestConfig);
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
httpPost.setHeader("Accept", "application/json");
httpPost.setEntity(new StringEntity(jsonString, Charset.forName("UTF-8")));
if(isSign){
httpPost.addHeader("X-Sign",SignUtils.generate(SignUtils.DEFAULT_KEY,httpPost.getEntity().getContent()));
}
response = httpClient.execute(httpPost);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer();
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
result = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != response) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
public static String postFormUrl(String url, Map<String,Object> params,boolean isSign,Integer connTime,Integer requestTimeOut,Integer socketTime) {
CloseableHttpResponse response = null;
BufferedReader in = null;
String result = "";
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connTime).setConnectionRequestTimeout(requestTimeOut).setSocketTimeout(socketTime).build();
HttpPost httpPost = new HttpPost(url);
try {
httpPost.setConfig(requestConfig);
List<NameValuePair> pairList = new ArrayList<>(params.size());
if(MapUtils.isNotEmpty(params)){
for (Map.Entry<String, Object> entry : params.entrySet()) {
NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue()==null?"":entry.getValue().toString());
pairList.add(pair);
}
}
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(pairList, StandardCharsets.UTF_8);
httpPost.setEntity(urlEncodedFormEntity);
if(isSign){
httpPost.addHeader("X-Sign",SignUtils.generate(SignUtils.DEFAULT_KEY,httpPost.getEntity().getContent()));
}
response = httpClient.execute(httpPost);
int status = response.getStatusLine().getStatusCode();
if (HttpStatus.SC_OK == status) {
HttpEntity entity = response.getEntity();
try {
result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
}finally {
EntityUtils.consume(entity);
}
}else{
throw new HttpException("请求失败:" + status);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpPost.releaseConnection();
if (response != null) {
try {
EntityUtils.consume(response.getEntity());
response.close();
} catch (IOException e) {
//ignore
}
}
}
return result;
}
public static String postFormUrl(String url, Map<String,Object> params,boolean isSign) {
return postFormUrl(url, params, isSign, 30000, 30000, 30000);
}
/**
* Post调用
*
* @param url HTTP URL
* @param headers 请求头
* @param params 参数集合
* @return
* @throws Exception
*/
public static String sendPost(String url, Map<String, String> headers, Map<String, String> params) {
String result = "";
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(url);
// 创建header
if (headers != null && headers.size() > 0) {
Set<String> headerKeys = headers.keySet();
for (String headerKey : headerKeys) {
httppost.addHeader(headerKey, headers.get(headerKey));
}
}
// 创建参数队列
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
if (params != null && params.size() > 0) {
Set<String> paramKeys = params.keySet();
for (String paramKey : paramKeys) {
formparams.add(new BasicNameValuePair(paramKey, params.get(paramKey)));
}
}
UrlEncodedFormEntity uefEntity;
try {
uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
httppost.setEntity(uefEntity);
CloseableHttpResponse response = httpClient.execute(httppost);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity, "UTF-8");
}
} finally {
response.close();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭连接,释放资源
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
}根据ip获取地址工具类
java
/**
* 获取地址类
*
* @author ruoyi
*/
public class AddressUtils {
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
// IP地址查询
public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
// 未知地址
public static final String UNKNOWN = "XX XX";
public static String getRealAddressByIP(String ip) {
String address = UNKNOWN;
// 内网不查询
if (IpUtils.internalIp(ip)) {
return "内网IP";
}
if (RuoYiConfig.isAddressEnabled()) {
try {
String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
if (StringUtils.isEmpty(rspStr)) {
log.error("获取地理位置异常 {}", ip);
return UNKNOWN;
}
JSONObject obj = JSONObject.parseObject(rspStr);
String region = obj.getString("pro");
String city = obj.getString("city");
return String.format("%s %s", region, city);
} catch (Exception e) {
log.error("获取地理位置异常 {}", ip);
}
}
return address;
}
}获取ip
java
/**
* 获取IP方法
*
* @author ruoyi
*/
public class IpUtils {
public static String getIpAddr(HttpServletRequest request) {
if (request == null) {
return "unknown";
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : EscapeUtil.clean(ip);
}
public static boolean internalIp(String ip) {
byte[] addr = textToNumericFormatV4(ip);
return internalIp(addr) || "127.0.0.1".equals(ip);
}
private static boolean internalIp(byte[] addr) {
if (StringUtils.isNull(addr) || addr.length < 2) {
return true;
}
final byte b0 = addr[0];
final byte b1 = addr[1];
// 10.x.x.x/8
final byte SECTION_1 = 0x0A;
// 172.16.x.x/12
final byte SECTION_2 = (byte) 0xAC;
final byte SECTION_3 = (byte) 0x10;
final byte SECTION_4 = (byte) 0x1F;
// 192.168.x.x/16
final byte SECTION_5 = (byte) 0xC0;
final byte SECTION_6 = (byte) 0xA8;
switch (b0) {
case SECTION_1:
return true;
case SECTION_2:
if (b1 >= SECTION_3 && b1 <= SECTION_4) {
return true;
}
case SECTION_5:
switch (b1) {
case SECTION_6:
return true;
}
default:
return false;
}
}
/**
* 将IPv4地址转换成字节
*
* @param text IPv4地址
* @return byte 字节
*/
public static byte[] textToNumericFormatV4(String text) {
if (text.length() == 0) {
return null;
}
byte[] bytes = new byte[4];
String[] elements = text.split("\\.", -1);
try {
long l;
int i;
switch (elements.length) {
case 1:
l = Long.parseLong(elements[0]);
if ((l < 0L) || (l > 4294967295L)) {
return null;
}
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 2:
l = Integer.parseInt(elements[0]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[0] = (byte) (int) (l & 0xFF);
l = Integer.parseInt(elements[1]);
if ((l < 0L) || (l > 16777215L)) {
return null;
}
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 3:
for (i = 0; i < 2; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
l = Integer.parseInt(elements[2]);
if ((l < 0L) || (l > 65535L)) {
return null;
}
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 4:
for (i = 0; i < 4; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
break;
default:
return null;
}
} catch (NumberFormatException e) {
return null;
}
return bytes;
}
public static String getHostIp() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
}
return "127.0.0.1";
}
public static String getHostName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
}
return "未知";
}
}反射工具类
java
/**
* 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
*
* @author ruoyi
*/
@SuppressWarnings("rawtypes")
public class ReflectUtils {
private static final String SETTER_PREFIX = "set";
private static final String GETTER_PREFIX = "get";
private static final String CGLIB_CLASS_SEPARATOR = "$$";
private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
/**
* 调用Getter方法.
* 支持多级,如:对象名.对象名.方法
*/
@SuppressWarnings("unchecked")
public static <E> E invokeGetter(Object obj, String propertyName) {
Object object = obj;
for (String name : StringUtils.split(propertyName, ".")) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
}
return (E) object;
}
/**
* 调用Setter方法, 仅匹配方法名。
* 支持多级,如:对象名.对象名.方法
*/
public static <E> void invokeSetter(Object obj, String propertyName, E value) {
Object object = obj;
String[] names = StringUtils.split(propertyName, ".");
for (int i = 0; i < names.length; i++) {
if (i < names.length - 1) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
} else {
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
invokeMethodByName(object, setterMethodName, new Object[]{value});
}
}
}
/**
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*/
@SuppressWarnings("unchecked")
public static <E> E getFieldValue(final Object obj, final String fieldName) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
return null;
}
E result = null;
try {
result = (E) field.get(obj);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常{}", e.getMessage());
}
return result;
}
/**
* 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
*/
public static <E> void setFieldValue(final Object obj, final String fieldName, final E value) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
// throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
return;
}
try {
field.set(obj, value);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常: {}", e.getMessage());
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符.
* 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
* 同时匹配方法名+参数类型,
*/
@SuppressWarnings("unchecked")
public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
final Object[] args) {
if (obj == null || methodName == null) {
return null;
}
Method method = getAccessibleMethod(obj, methodName, parameterTypes);
if (method == null) {
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
return null;
}
try {
return (E) method.invoke(obj, args);
} catch (Exception e) {
String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
throw convertReflectionExceptionToUnchecked(msg, e);
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符,
* 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
* 只匹配函数名,如果有多个同名函数调用第一个。
*/
@SuppressWarnings("unchecked")
public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
Method method = getAccessibleMethodByName(obj, methodName, args.length);
if (method == null) {
// 如果为空不报错,直接返回空。
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
return null;
}
try {
// 类型转换(将参数数据类型转换为目标方法参数类型)
Class<?>[] cs = method.getParameterTypes();
for (int i = 0; i < cs.length; i++) {
if (args[i] != null && !args[i].getClass().equals(cs[i])) {
if (cs[i] == String.class) {
args[i] = Convert.toStr(args[i]);
if (StringUtils.endsWith((String) args[i], ".0")) {
args[i] = StringUtils.substringBefore((String) args[i], ".0");
}
} else if (cs[i] == Integer.class) {
args[i] = Convert.toInt(args[i]);
} else if (cs[i] == Long.class) {
args[i] = Convert.toLong(args[i]);
} else if (cs[i] == Double.class) {
args[i] = Convert.toDouble(args[i]);
} else if (cs[i] == Float.class) {
args[i] = Convert.toFloat(args[i]);
} else if (cs[i] == Date.class) {
if (args[i] instanceof String) {
args[i] = DateUtils.parseDate(args[i]);
} else {
args[i] = DateUtil.getJavaDate((Double) args[i]);
}
} else if (cs[i] == boolean.class || cs[i] == Boolean.class) {
args[i] = Convert.toBool(args[i]);
}
}
}
return (E) method.invoke(obj, args);
} catch (Exception e) {
String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
throw convertReflectionExceptionToUnchecked(msg, e);
}
}
/**
* 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
*/
public static Field getAccessibleField(final Object obj, final String fieldName) {
// 为空不报错。直接返回 null
if (obj == null) {
return null;
}
Validate.notBlank(fieldName, "fieldName can't be blank");
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
Field field = superClass.getDeclaredField(fieldName);
makeAccessible(field);
return field;
} catch (NoSuchFieldException e) {
continue;
}
}
return null;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
* 匹配函数名+参数类型。
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public static Method getAccessibleMethod(final Object obj, final String methodName,
final Class<?>... parameterTypes) {
// 为空不报错。直接返回 null
if (obj == null) {
return null;
}
Validate.notBlank(methodName, "methodName can't be blank");
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
try {
Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
makeAccessible(method);
return method;
} catch (NoSuchMethodException e) {
continue;
}
}
return null;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
* 只匹配函数名。
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) {
// 为空不报错。直接返回 null
if (obj == null) {
return null;
}
Validate.notBlank(methodName, "methodName can't be blank");
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
Method[] methods = searchType.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) {
makeAccessible(method);
return method;
}
}
}
return null;
}
/**
* 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
*/
public static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) {
method.setAccessible(true);
}
}
/**
* 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
*/
public static void makeAccessible(Field field) {
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
|| Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {
field.setAccessible(true);
}
}
/**
* 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
* 如无法找到, 返回Object.class.
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> getClassGenricType(final Class clazz) {
return getClassGenricType(clazz, 0);
}
/**
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
* 如无法找到, 返回Object.class.
*/
public static Class getClassGenricType(final Class clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
return Object.class;
}
return (Class) params[index];
}
public static Class<?> getUserClass(Object instance) {
if (instance == null) {
throw new RuntimeException("Instance must not be null");
}
Class clazz = instance.getClass();
if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
Class<?> superClass = clazz.getSuperclass();
if (superClass != null && !Object.class.equals(superClass)) {
return superClass;
}
}
return clazz;
}
/**
* 将反射时的checked exception转换为unchecked exception.
*/
public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) {
if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
|| e instanceof NoSuchMethodException) {
return new IllegalArgumentException(msg, e);
} else if (e instanceof InvocationTargetException) {
return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
}
return new RuntimeException(msg, e);
}
}Base64工具类
java
/**
* Base64工具类
*
* @author ruoyi
*/
public final class Base64 {
static private final int BASELENGTH = 128;
static private final int LOOKUPLENGTH = 64;
static private final int TWENTYFOURBITGROUP = 24;
static private final int EIGHTBIT = 8;
static private final int SIXTEENBIT = 16;
static private final int FOURBYTE = 4;
static private final int SIGN = -128;
static private final char PAD = '=';
static final private byte[] base64Alphabet = new byte[BASELENGTH];
static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
static {
for (int i = 0; i < BASELENGTH; ++i) {
base64Alphabet[i] = -1;
}
for (int i = 'Z'; i >= 'A'; i--) {
base64Alphabet[i] = (byte) (i - 'A');
}
for (int i = 'z'; i >= 'a'; i--) {
base64Alphabet[i] = (byte) (i - 'a' + 26);
}
for (int i = '9'; i >= '0'; i--) {
base64Alphabet[i] = (byte) (i - '0' + 52);
}
base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63;
for (int i = 0; i <= 25; i++) {
lookUpBase64Alphabet[i] = (char) ('A' + i);
}
for (int i = 26, j = 0; i <= 51; i++, j++) {
lookUpBase64Alphabet[i] = (char) ('a' + j);
}
for (int i = 52, j = 0; i <= 61; i++, j++) {
lookUpBase64Alphabet[i] = (char) ('0' + j);
}
lookUpBase64Alphabet[62] = (char) '+';
lookUpBase64Alphabet[63] = (char) '/';
}
private static boolean isWhiteSpace(char octect) {
return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
}
private static boolean isPad(char octect) {
return (octect == PAD);
}
private static boolean isData(char octect) {
return (octect < BASELENGTH && base64Alphabet[octect] != -1);
}
/**
* Encodes hex octects into Base64
*
* @param binaryData Array containing binaryData
* @return Encoded Base64 array
*/
public static String encode(byte[] binaryData) {
if (binaryData == null) {
return null;
}
int lengthDataBits = binaryData.length * EIGHTBIT;
if (lengthDataBits == 0) {
return "";
}
int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
char encodedData[] = null;
encodedData = new char[numberQuartet * 4];
byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
int encodedIndex = 0;
int dataIndex = 0;
for (int i = 0; i < numberTriplets; i++) {
b1 = binaryData[dataIndex++];
b2 = binaryData[dataIndex++];
b3 = binaryData[dataIndex++];
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
}
// form integral number of 6-bit groups
if (fewerThan24bits == EIGHTBIT) {
b1 = binaryData[dataIndex];
k = (byte) (b1 & 0x03);
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
encodedData[encodedIndex++] = PAD;
encodedData[encodedIndex++] = PAD;
} else if (fewerThan24bits == SIXTEENBIT) {
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex + 1];
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
encodedData[encodedIndex++] = PAD;
}
return new String(encodedData);
}
/**
* Decodes Base64 data into octects
*
* @param encoded string containing Base64 data
* @return Array containind decoded data.
*/
public static byte[] decode(String encoded) {
if (encoded == null) {
return null;
}
char[] base64Data = encoded.toCharArray();
// remove white spaces
int len = removeWhiteSpace(base64Data);
if (len % FOURBYTE != 0) {
return null;// should be divisible by four
}
int numberQuadruple = (len / FOURBYTE);
if (numberQuadruple == 0) {
return new byte[0];
}
byte decodedData[] = null;
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
int i = 0;
int encodedIndex = 0;
int dataIndex = 0;
decodedData = new byte[(numberQuadruple) * 3];
for (; i < numberQuadruple - 1; i++) {
if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
|| !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) {
return null;
} // if found "no data" just return null
b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4];
decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
}
if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
return null;// if found "no data" just return null
}
b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
d3 = base64Data[dataIndex++];
d4 = base64Data[dataIndex++];
if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters
if (isPad(d3) && isPad(d4)) {
if ((b2 & 0xf) != 0)// last 4 bits should be zero
{
return null;
}
byte[] tmp = new byte[i * 3 + 1];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
return tmp;
} else if (!isPad(d3) && isPad(d4)) {
b3 = base64Alphabet[d3];
if ((b3 & 0x3) != 0)// last 2 bits should be zero
{
return null;
}
byte[] tmp = new byte[i * 3 + 2];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
return tmp;
} else {
return null;
}
} else { // No PAD e.g 3cQl
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4];
decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
}
return decodedData;
}
/**
* remove WhiteSpace from MIME containing encoded Base64 data.
*
* @param data the byte array of base64 data (with WS)
* @return the new length
*/
private static int removeWhiteSpace(char[] data) {
if (data == null) {
return 0;
}
// count characters that's not whitespace
int newSize = 0;
int len = data.length;
for (int i = 0; i < len; i++) {
if (!isWhiteSpace(data[i])) {
data[newSize++] = data[i];
}
}
return newSize;
}
}Md5加密工具类
java
/**
* Md5加密方法
*
* @author ruoyi
*/
public class Md5Utils {
private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
private static byte[] md5(String s) {
MessageDigest algorithm;
try {
algorithm = MessageDigest.getInstance("MD5");
algorithm.reset();
algorithm.update(s.getBytes("UTF-8"));
byte[] messageDigest = algorithm.digest();
return messageDigest;
} catch (Exception e) {
log.error("MD5 Error...", e);
}
return null;
}
private static final String toHex(byte hash[]) {
if (hash == null) {
return null;
}
StringBuffer buf = new StringBuffer(hash.length * 2);
int i;
for (i = 0; i < hash.length; i++) {
if ((hash[i] & 0xff) < 0x10) {
buf.append("0");
}
buf.append(Long.toString(hash[i] & 0xff, 16));
}
return buf.toString();
}
public static String hash(String s) {
try {
return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8");
} catch (Exception e) {
log.error("not supported charset...{}", e);
return s;
}
}
}
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
public class EncryptUtils {
public static byte[] hexToByte(String hex){
byte[] bytes = null;
if(hex != null && hex.length() > 2){
int len = hex.length();
bytes = new byte[len / 2];
char[] hexChars = hex.toCharArray();
for(int i = 0; i < bytes.length; i++){
int pos = i * 2;
bytes[i] = (byte) Integer.parseInt("" + hexChars[pos] + hexChars[pos + 1], 16);
}
}
return bytes;
}
/**
* AES加解密
*/
public static class AES {
private static final String ECB_PKCS5_PADDING = "AES/ECB/PKCS5Padding";//AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式
private static final String AES = "AES";//AES 加密
private static final String defaultSalt = "e083097fab6ac6cac27604e1965f0155";
public static Key getKey(String key) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec keySpec = new PBEKeySpec(key.toCharArray(), hexToByte(defaultSalt), 1000, 256);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKey sk = keyFactory.generateSecret(keySpec);
return new SecretKeySpec(sk.getEncoded(), AES);
}
public static Key getSunKey(String key) throws NoSuchAlgorithmException, NoSuchProviderException{
KeyGenerator kg = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG","SUN");
secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8));
kg.init(128, secureRandom);
return kg.generateKey();
}
public static Key getHexKey(String hexString){
return new SecretKeySpec(hexToByte(hexString), AES);
}
public static String encrypt(String data) throws Exception {
return encrypt(getHexKey(defaultSalt), data.getBytes(StandardCharsets.UTF_8));
}
public static String encrypt(Key key, String data) throws Exception {
return encrypt(key, data.getBytes(StandardCharsets.UTF_8));
}
private static String encrypt(Key key, byte[] data) throws Exception {
Cipher cipher = Cipher.getInstance(ECB_PKCS5_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, key);
// cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(new byte[cipher.getBlockSize()]));
byte[] encrypted = cipher.doFinal(data);
return Hex.encodeHexString(encrypted);
}
public static String decrypt(String encrypted) throws Exception {
return decrypt(getHexKey(defaultSalt), hexToByte(encrypted));
}
public static String decrypt(Key key, String encrypted) throws Exception {
return decrypt(key, hexToByte(encrypted));
}
private static String decrypt(Key key, byte[] encrypted) throws Exception {
Cipher cipher = Cipher.getInstance(ECB_PKCS5_PADDING);
cipher.init(Cipher.DECRYPT_MODE, key);
// cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(new byte[cipher.getBlockSize()]));
byte[] decrypted = cipher.doFinal(encrypted);
return new String(decrypted, StandardCharsets.UTF_8);
}
}
/**
* MD5加密
*/
public static class MD5 {
public static String encrypt(String val) {
return DigestUtils.md5Hex(val);
}
}
}Sql操作工具类
java
/**
* sql操作工具类
*
* @author ruoyi
*/
public class SqlUtil {
/**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
*/
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
/**
* 检查字符,防止注入绕过
*/
public static String escapeOrderBySql(String value) {
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) {
throw new BaseException("参数不符合规范,不能进行查询");
}
return value;
}
/**
* 验证 order by 语法是否符合规范
*/
public static boolean isValidOrderBySql(String value) {
return value.matches(SQL_PATTERN);
}
}Id生成工具类
java
/**
* ID生成器工具类
*
* @author ruoyi
*/
public class IdUtils {
/**
* 获取随机UUID
*
* @return 随机UUID
*/
public static String randomUUID() {
return UUID.randomUUID().toString();
}
/**
* 简化的UUID,去掉了横线
*
* @return 简化的UUID,去掉了横线
*/
public static String simpleUUID() {
return UUID.randomUUID().toString(true);
}
/**
* 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID
*
* @return 随机UUID
*/
public static String fastUUID() {
return UUID.fastUUID().toString();
}
/**
* 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
*
* @return 简化的UUID,去掉了横线
*/
public static String fastSimpleUUID() {
return UUID.fastUUID().toString(true);
}
}UUID工具类
java
/**
* 提供通用唯一识别码(universally unique identifier)(UUID)实现
*
* @author ruoyi
*/
public final class UUID implements java.io.Serializable, Comparable<UUID> {
private static final long serialVersionUID = -1185015143654744140L;
/**
* SecureRandom 的单例
*/
private static class Holder {
static final SecureRandom numberGenerator = getSecureRandom();
}
/**
* 此UUID的最高64有效位
*/
private final long mostSigBits;
/**
* 此UUID的最低64有效位
*/
private final long leastSigBits;
/**
* 私有构造
*
* @param data 数据
*/
private UUID(byte[] data) {
long msb = 0;
long lsb = 0;
assert data.length == 16 : "data must be 16 bytes in length";
for (int i = 0; i < 8; i++) {
msb = (msb << 8) | (data[i] & 0xff);
}
for (int i = 8; i < 16; i++) {
lsb = (lsb << 8) | (data[i] & 0xff);
}
this.mostSigBits = msb;
this.leastSigBits = lsb;
}
/**
* 使用指定的数据构造新的 UUID。
*
* @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
* @param leastSigBits 用于 {@code UUID} 的最低有效 64 位
*/
public UUID(long mostSigBits, long leastSigBits) {
this.mostSigBits = mostSigBits;
this.leastSigBits = leastSigBits;
}
/**
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。
*
* @return 随机生成的 {@code UUID}
*/
public static UUID fastUUID() {
return randomUUID(false);
}
/**
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
*
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID() {
return randomUUID(true);
}
/**
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
*
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID(boolean isSecure) {
final Random ng = isSecure ? Holder.numberGenerator : getRandom();
byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes);
randomBytes[6] &= 0x0f; /* clear version */
randomBytes[6] |= 0x40; /* set to version 4 */
randomBytes[8] &= 0x3f; /* clear variant */
randomBytes[8] |= 0x80; /* set to IETF variant */
return new UUID(randomBytes);
}
/**
* 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。
*
* @param name 用于构造 UUID 的字节数组。
* @return 根据指定数组生成的 {@code UUID}
*/
public static UUID nameUUIDFromBytes(byte[] name) {
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsae) {
throw new InternalError("MD5 not supported");
}
byte[] md5Bytes = md.digest(name);
md5Bytes[6] &= 0x0f; /* clear version */
md5Bytes[6] |= 0x30; /* set to version 3 */
md5Bytes[8] &= 0x3f; /* clear variant */
md5Bytes[8] |= 0x80; /* set to IETF variant */
return new UUID(md5Bytes);
}
/**
* 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。
*
* @param name 指定 {@code UUID} 字符串
* @return 具有指定值的 {@code UUID}
* @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常
*/
public static UUID fromString(String name) {
String[] components = name.split("-");
if (components.length != 5) {
throw new IllegalArgumentException("Invalid UUID string: " + name);
}
for (int i = 0; i < 5; i++) {
components[i] = "0x" + components[i];
}
long mostSigBits = Long.decode(components[0]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[1]).longValue();
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[2]).longValue();
long leastSigBits = Long.decode(components[3]).longValue();
leastSigBits <<= 48;
leastSigBits |= Long.decode(components[4]).longValue();
return new UUID(mostSigBits, leastSigBits);
}
/**
* 返回此 UUID 的 128 位值中的最低有效 64 位。
*
* @return 此 UUID 的 128 位值中的最低有效 64 位。
*/
public long getLeastSignificantBits() {
return leastSigBits;
}
/**
* 返回此 UUID 的 128 位值中的最高有效 64 位。
*
* @return 此 UUID 的 128 位值中最高有效 64 位。
*/
public long getMostSignificantBits() {
return mostSigBits;
}
/**
* 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。
* <p>
* 版本号具有以下含意:
* <ul>
* <li>1 基于时间的 UUID
* <li>2 DCE 安全 UUID
* <li>3 基于名称的 UUID
* <li>4 随机生成的 UUID
* </ul>
*
* @return 此 {@code UUID} 的版本号
*/
public int version() {
// Version is bits masked by 0x000000000000F000 in MS long
return (int) ((mostSigBits >> 12) & 0x0f);
}
/**
* 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。
* <p>
* 变体号具有以下含意:
* <ul>
* <li>0 为 NCS 向后兼容保留
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于此类
* <li>6 保留,微软向后兼容
* <li>7 保留供以后定义使用
* </ul>
*
* @return 此 {@code UUID} 相关联的变体号
*/
public int variant() {
// This field is composed of a varying number of bits.
// 0 - - Reserved for NCS backward compatibility
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
// 1 1 0 Reserved, Microsoft backward compatibility
// 1 1 1 Reserved for future definition.
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
}
/**
* 与此 UUID 相关联的时间戳值。
*
* <p>
* 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br>
* 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。
*
* <p>
* 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
* 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
*
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。
*/
public long timestamp() throws UnsupportedOperationException {
checkTimeBase();
return (mostSigBits & 0x0FFFL) << 48//
| ((mostSigBits >> 16) & 0x0FFFFL) << 32//
| mostSigBits >>> 32;
}
/**
* 与此 UUID 相关联的时钟序列值。
*
* <p>
* 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。
* <p>
* {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出
* UnsupportedOperationException。
*
* @return 此 {@code UUID} 的时钟序列
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
*/
public int clockSequence() throws UnsupportedOperationException {
checkTimeBase();
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
}
/**
* 与此 UUID 相关的节点值。
*
* <p>
* 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。
* <p>
* 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
* 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
*
* @return 此 {@code UUID} 的节点值
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
*/
public long node() throws UnsupportedOperationException {
checkTimeBase();
return leastSigBits & 0x0000FFFFFFFFFFFFL;
}
/**
* 返回此{@code UUID} 的字符串表现形式。
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述:
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @return 此{@code UUID} 的字符串表现形式
* @see #toString(boolean)
*/
@Override
public String toString() {
return toString(false);
}
/**
* 返回此{@code UUID} 的字符串表现形式。
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述:
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
* </blockquote>
*
* @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串
* @return 此{@code UUID} 的字符串表现形式
*/
public String toString(boolean isSimple) {
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low
builder.append(digits(mostSigBits >> 32, 8));
if (false == isSimple) {
builder.append('-');
}
// time_mid
builder.append(digits(mostSigBits >> 16, 4));
if (false == isSimple) {
builder.append('-');
}
// time_high_and_version
builder.append(digits(mostSigBits, 4));
if (false == isSimple) {
builder.append('-');
}
// variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4));
if (false == isSimple) {
builder.append('-');
}
// node
builder.append(digits(leastSigBits, 12));
return builder.toString();
}
/**
* 返回此 UUID 的哈希码。
*
* @return UUID 的哈希码值。
*/
@Override
public int hashCode() {
long hilo = mostSigBits ^ leastSigBits;
return ((int) (hilo >> 32)) ^ (int) hilo;
}
/**
* 将此对象与指定对象比较。
* <p>
* 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。
*
* @param obj 要与之比较的对象
* @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
*/
@Override
public boolean equals(Object obj) {
if ((null == obj) || (obj.getClass() != UUID.class)) {
return false;
}
UUID id = (UUID) obj;
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
}
// Comparison Operations
/**
* 将此 UUID 与指定的 UUID 比较。
*
* <p>
* 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。
*
* @param val 与此 UUID 比较的 UUID
* @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
*/
@Override
public int compareTo(UUID val) {
// The ordering is intentionally set up so that the UUIDs
// can simply be numerically compared as two numbers
return (this.mostSigBits < val.mostSigBits ? -1 : //
(this.mostSigBits > val.mostSigBits ? 1 : //
(this.leastSigBits < val.leastSigBits ? -1 : //
(this.leastSigBits > val.leastSigBits ? 1 : //
0))));
}
// -------------------------------------------------------------------------------------------------------------------
// Private method start
/**
* 返回指定数字对应的hex值
*
* @param val 值
* @param digits 位
* @return 值
*/
private static String digits(long val, int digits) {
long hi = 1L << (digits * 4);
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}
/**
* 检查是否为time-based版本UUID
*/
private void checkTimeBase() {
if (version() != 1) {
throw new UnsupportedOperationException("Not a time-based UUID");
}
}
/**
* 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
*
* @return {@link SecureRandom}
*/
public static SecureRandom getSecureRandom() {
try {
return SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
throw new UtilException(e);
}
}
/**
* 获取随机数生成器对象<br>
* ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
*
* @return {@link ThreadLocalRandom}
*/
public static ThreadLocalRandom getRandom() {
return ThreadLocalRandom.current();
}
/**
* uuid格式校验
*/
public static boolean isUuid(String uuid){
if (StringUtils.isBlank(uuid)) {
return false;
}
//String regex = "^[0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12}$";
String regex = "^[0-9a-f]{32}$";
if (uuid.matches(regex)) {
return true;
}
return false;
}
}浮点数运算工具类
java
/**
* 精确的浮点数运算
*
* @author ruoyi
*/
public class Arith {
/**
* 默认除法运算精度
*/
private static final int DEF_DIV_SCALE = 10;
/**
* 这个类不能实例化
*/
private Arith() {
}
/**
* 提供精确的加法运算。
*
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
*
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
*
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入。
*
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入。
*
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
if (b1.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO.doubleValue();
}
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
}
}时间工具类
java
/**
* 时间工具类
*
* @author ruoyi
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM";
public static String YYYY_MM_DD = "yyyy-MM-dd";
public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
/**
* 获取当前Date型日期
*
* @return Date() 当前日期
*/
public static Date getNowDate() {
return new Date();
}
/**
* 获取当前日期, 默认格式为yyyy-MM-dd
*
* @return String
*/
public static String getDate() {
return dateTimeNow(YYYY_MM_DD);
}
public static final String getTime() {
return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
}
public static final String dateTimeNow() {
return dateTimeNow(YYYYMMDDHHMMSS);
}
public static final String dateTimeNow(final String format) {
return parseDateToStr(format, new Date());
}
public static final String dateTime(final Date date) {
return parseDateToStr(YYYY_MM_DD, date);
}
public static final String parseDateToStr(final String format, final Date date) {
return new SimpleDateFormat(format).format(date);
}
public static final Date dateTime(final String format, final String ts) {
try {
return new SimpleDateFormat(format).parse(ts);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
/**
* 日期路径 即年/月/日 如2018/08/08
*/
public static final String datePath() {
Date now = new Date();
return DateFormatUtils.format(now, "yyyy/MM/dd");
}
/**
* 日期路径 即年/月/日 如20180808
*/
public static final String dateTime() {
Date now = new Date();
return DateFormatUtils.format(now, "yyyyMMdd");
}
/**
* 日期型字符串转化为日期 格式
*/
public static Date parseDate(Object str) {
if (str == null) {
return null;
}
try {
return parseDate(str.toString(), parsePatterns);
} catch (ParseException e) {
return null;
}
}
/**
* 获取服务器启动时间
*/
public static Date getServerStartDate() {
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
return new Date(time);
}
/**
* 计算两个时间差
*/
public static String getDatePoor(Date endDate, Date nowDate) {
long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60;
long nm = 1000 * 60;
// long ns = 1000;
// 获得两个时间的毫秒时间差异
long diff = endDate.getTime() - nowDate.getTime();
// 计算差多少天
long day = diff / nd;
// 计算差多少小时
long hour = diff % nd / nh;
// 计算差多少分钟
long min = diff % nd % nh / nm;
// 计算差多少秒//输出结果
// long sec = diff % nd % nh % nm / ns;
return day + "天" + hour + "小时" + min + "分钟";
}
}
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.util.TypeUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* 时间工具类
* @author sunwen
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
public static String ISO_DATE_TIME = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
public static String DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static String FORMAT_TIME = "yyyy-MM-dd HH:mm";
public static String FORMAT_DAY = "yyyy-MM-dd";
public static String FORMAT_MONTH = "yyyy-MM";
public static String CH_FORMAT_MONTH = "yyyy年MM月";
public static String CH_FORMAT_DAY = "yyyy年MM月dd日";
public static String SPOT_FORMAT_MONTH = "yyyy.MM";
public static String SPOT_FORMAT_DAY = "yyyy.MM.dd";
public static String SHORT_FORMAT_MONTH = "yyyyMM";
public static String SHORT_FORMAT_DAY = "yyyyMMdd";
/**
* 时间戳 20190110121212
*/
public final static String TIMESTAMP_PATTERN = "yyyyMMddHHmmss";
/**
* 解析时间
* @author sunwen
* @since 2019/7/18
*/
public static Date parseDate(Object date) throws ParseException {
try {
return TypeUtils.castToDate(date);
}catch (JSONException e){
if(date instanceof String){
try {
return DateUtils.parseDate((String)date, FORMAT_TIME, FORMAT_MONTH, "yyyy");
} catch (ParseException ex) {
throw new ParseException(date + "无法转换时间类型", -1);
}
}else{
throw new ParseException(date + "无法转换时间类型", -1);
}
}
}
/**
* 判断是否同一天
* @author sunwen
*/
public static boolean isSameDay(Date date1, Date date2){
Calendar c1 = Calendar.getInstance();
c1.setTime(date1);
Calendar c2 = Calendar.getInstance();
c2.setTime(date2);
return isSameDay(c1, c2);
}
/**
* 根据指定格式输出当前时间
* @param pattern 格式
* @return
*/
public static String getDate(String pattern){
return DateFormatUtils.format(new Date(), pattern);
}
/**
* 当前时间按照时间戳格式输出 {@link #TIMESTAMP_PATTERN}
* @return
*/
public static String getTimestamp(){
return getDate(TIMESTAMP_PATTERN);
}
/**
* SQL相关时间工具内部类
*/
public static class Sql{
/**
* 获取当前时间的Timestamp对象
* @return
*/
public static Timestamp getTimestamp(){
return new Timestamp(System.currentTimeMillis());
}
}
/**
* 日期转化成默认格式{@link #DEFFAULT_DATE_FORMAT}
* @Param date
* @Return java.lang.String
* @Author wuzm
* Date 2019/7/21 23:25
*/
public static String parseDateToString(Date date) {
return parseDateToString(date, null);
}
/**
* 将日期转化成指定格式
* 如果格式为空则使用默认格式{@link #DEFFAULT_DATE_FORMAT}
* @Param date 日期
* @Param pattern 格式
* @Return java.lang.String
* @Author wuzm
* Date 2019/7/21 23:17
*/
public static String parseDateToString(Date date, String pattern){
if(date == null)
return "";
SimpleDateFormat sdf = null;
if(pattern != null && !pattern.equals("")) {
sdf = new SimpleDateFormat(pattern);
} else {
sdf = new SimpleDateFormat(DEFFAULT_DATE_FORMAT);
}
return sdf.format(date);
}
/**
* 按时间字段获取指定时间的开始时间
* @author sunwen
* @since 2020/11/30
*/
public static Date getStartTime(Date time, int field){
Calendar cal = Calendar.getInstance();
cal.clear();
if(field >= Calendar.YEAR) {
cal.set(Calendar.YEAR, time.getYear() + 1900);
}
if(field >= Calendar.MONTH){
cal.set(Calendar.MONTH, time.getMonth());
}
if(field >= Calendar.DAY_OF_MONTH){
cal.set(Calendar.DAY_OF_MONTH, time.getDate());
}
return cal.getTime();
}
/**
* 按时间字段获取指定时间的结束时间
* @author sunwen
* @since 2020/11/30
*/
public static Date getEndTime(Date time, int field){
Calendar cal = Calendar.getInstance();
cal.clear();
if(field == Calendar.YEAR){
cal.set(Calendar.YEAR, time.getYear() + 1901);
}else if(field > Calendar.YEAR) {
cal.set(Calendar.YEAR, time.getYear() + 1900);
}
if(field == Calendar.MONTH){
cal.set(Calendar.MONTH, time.getMonth() + 1);
}else if(field > Calendar.MONTH){
cal.set(Calendar.MONTH, time.getMonth());
}
if(field == Calendar.DAY_OF_MONTH){
cal.set(Calendar.DAY_OF_MONTH, time.getDate() + 1);
}else if(field > Calendar.DAY_OF_MONTH){
cal.set(Calendar.DAY_OF_MONTH, time.getDate());
}
return cal.getTime();
}
/**
* 获取当前时间距离第二天0点的时间间隔
* @author sunwen
* @since 2020/7/6
*/
public static long getMillisNextEarlyDay() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.MILLISECOND, 0);
return (cal.getTimeInMillis() - System.currentTimeMillis());
}
/**
* 获取当前时间距离下个月的时间间隔
* @author sunwen
* @since 2020/7/6
*/
public static long getMillisNextEarlyMonth() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, 1);
cal.set(Calendar.DAY_OF_MONTH, 0);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.MILLISECOND, 0);
return (cal.getTimeInMillis() - System.currentTimeMillis());
}
}验证码工具类
java
/**
* 验证码工具类
*
* @author ruoyi
*/
public class VerifyCodeUtils {
// 使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
public static final String VERIFY_CODES = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
private static Random random = new SecureRandom();
/**
* 使用系统默认字符源生成验证码
*
* @param verifySize 验证码长度
* @return
*/
public static String generateVerifyCode(int verifySize) {
return generateVerifyCode(verifySize, VERIFY_CODES);
}
/**
* 使用指定源生成验证码
*
* @param verifySize 验证码长度
* @param sources 验证码字符源
* @return
*/
public static String generateVerifyCode(int verifySize, String sources) {
if (sources == null || sources.length() == 0) {
sources = VERIFY_CODES;
}
int codesLen = sources.length();
Random rand = new Random(System.currentTimeMillis());
StringBuilder verifyCode = new StringBuilder(verifySize);
for (int i = 0; i < verifySize; i++) {
verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
}
return verifyCode.toString();
}
/**
* 输出指定验证码图片流
*
* @param w
* @param h
* @param os
* @param code
* @throws IOException
*/
public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {
int verifySize = code.length();
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Random rand = new Random();
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color[] colors = new Color[5];
Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA,
Color.ORANGE, Color.PINK, Color.YELLOW};
float[] fractions = new float[colors.length];
for (int i = 0; i < colors.length; i++) {
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
fractions[i] = rand.nextFloat();
}
Arrays.sort(fractions);
g2.setColor(Color.GRAY);// 设置边框色
g2.fillRect(0, 0, w, h);
Color c = getRandColor(200, 250);
g2.setColor(c);// 设置背景色
g2.fillRect(0, 2, w, h - 4);
// 绘制干扰线
Random random = new Random();
g2.setColor(getRandColor(160, 200));// 设置线条的颜色
for (int i = 0; i < 20; i++) {
int x = random.nextInt(w - 1);
int y = random.nextInt(h - 1);
int xl = random.nextInt(6) + 1;
int yl = random.nextInt(12) + 1;
g2.drawLine(x, y, x + xl + 40, y + yl + 20);
}
// 添加噪点
float yawpRate = 0.05f;// 噪声率
int area = (int) (yawpRate * w * h);
for (int i = 0; i < area; i++) {
int x = random.nextInt(w);
int y = random.nextInt(h);
int rgb = getRandomIntColor();
image.setRGB(x, y, rgb);
}
shear(g2, w, h, c);// 使图片扭曲
g2.setColor(getRandColor(100, 160));
int fontSize = h - 4;
Font font = new Font("Algerian", Font.ITALIC, fontSize);
g2.setFont(font);
char[] chars = code.toCharArray();
for (int i = 0; i < verifySize; i++) {
AffineTransform affine = new AffineTransform();
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1),
(w / verifySize) * i + fontSize / 2, h / 2);
g2.setTransform(affine);
g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
}
g2.dispose();
ImageIO.write(image, "jpg", os);
}
private static Color getRandColor(int fc, int bc) {
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
private static int getRandomIntColor() {
int[] rgb = getRandomRgb();
int color = 0;
for (int c : rgb) {
color = color << 8;
color = color | c;
}
return color;
}
private static int[] getRandomRgb() {
int[] rgb = new int[3];
for (int i = 0; i < 3; i++) {
rgb[i] = random.nextInt(255);
}
return rgb;
}
private static void shear(Graphics g, int w1, int h1, Color color) {
shearX(g, w1, h1, color);
shearY(g, w1, h1, color);
}
private static void shearX(Graphics g, int w1, int h1, Color color) {
int period = random.nextInt(2);
boolean borderGap = true;
int frames = 1;
int phase = random.nextInt(2);
for (int i = 0; i < h1; i++) {
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
g.copyArea(0, i, w1, 1, (int) d, 0);
if (borderGap) {
g.setColor(color);
g.drawLine((int) d, i, 0, i);
g.drawLine((int) d + w1, i, w1, i);
}
}
}
private static void shearY(Graphics g, int w1, int h1, Color color) {
int period = random.nextInt(40) + 10; // 50;
boolean borderGap = true;
int frames = 20;
int phase = 7;
for (int i = 0; i < w1; i++) {
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
g.copyArea(i, 0, 1, h1, 0, (int) d);
if (borderGap) {
g.setColor(color);
g.drawLine(i, (int) d, i, 0);
g.drawLine(i, (int) d + h1, i, h1);
}
}
}
}ClassUtils扩展
Java
/**
* 对工具包{@link org.apache.commons.lang3.ClassUtils}方法的补充
* @author chenli
* @date 2016-2-25
* @version 1.0
*/
public class ClassUtils extends org.apache.commons.lang3.ClassUtils{
private static final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
private static final String RESOURCE_PATTERN = "/**/*.class";
private static final Logger logger = LoggerFactory.getLogger(ClassUtils.class);
private static final String BASE_PACKAGE= "com.commnetsoft";
//使用软引用缓存数据提高性能
private static SoftReference<Map<String,Object>> sr;
private static Lock lock = new ReentrantLock();
/**
* 获取类的所有枚举子类。 不能获取jar中的,只能获取classes下面的
* @param c 查询类(接口)名
* @return
* @author chenli
* @data 2016-2-25
*/
public static <T> List<T> getChilderEnum(Class<T> clazz){
String key = "enum_"+clazz.getName();
List<T> result = new ArrayList<T>();
Object o = getCache(key);
if(o != null){
result = (List<T>)o;
}else{
List<Class<T>> list = ClassUtils.getChilderClass(clazz, false);
for (Class<T> c : list) {
if(c.isEnum()){
try {
Method method = c.getMethod("values");
T[] constats = (T[])method.invoke(null);
for (T iConstant : constats) {
result.add(iConstant);
}
} catch (Exception e) {
logger.error("获取常量枚举异常",e);
}
}
}
putCache(key, result);
}
return result;
}
/**
* 获取类的所有子类(包括接口)。 不能获取jar中的,只能获取classes下面的
* <br>等于{@link ClassUtils#getChilderClass(Class, boolean, String...)}中String wei
* @param c 查询类(接口)名
* @param containInterface 是否包括接口(和抽象类)
* @return
* @author chenli
* @data 2016-2-25
*/
public static <T> List<Class<T>> getChilderClass(Class<T> c, boolean containInterface){
return getChilderClass(c, containInterface, BASE_PACKAGE);
}
/**
* 获取类的所有子类(包括接口)。 不能获取jar中的,只能获取classes下面的
* @param c 查询类(接口)名
* @param containInterface 是否包括接口
* @param packageName 查询范围(在哪个包下查询)
* @return
* @author chenli
* @data 2016-2-25
*/
public static <T> List<Class<T>> getChilderClass(Class<T> c, boolean containInterface, String... packageName){
List<Class<T>> returnClassList = new ArrayList<Class<T>>(); //返回结果
try{
Set<Class<?>> allClass = getClassSet(packageName); //获得某个包以及子包下的所有类
for (Class<?> classes : allClass) {
if (c.isAssignableFrom(classes)){//判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同。
if (!c.equals(classes)){ //本身不加进去
if(containInterface || (containInterface==false && classes.isInterface() ==false && false == Modifier.isAbstract(classes.getModifiers()))){
returnClassList.add((Class<T>)classes);
}
}
}
}
}
catch (Exception e){
logger.error("在包{}下面获取【{}】的子类发生异常", packageName,c.getName(),e);
}
return returnClassList;
}
/**
* 将符合条件的Bean以Class集合的形式返回
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static Set<Class<?>> getClassSet(String... packagesList) throws IOException {
Set<Class<?>> classSet = new HashSet<Class<?>>();
for (String pkg : packagesList) {
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
org.springframework.util.ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;
Resource[] resources = resourcePatternResolver.getResources(pattern);
MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader reader = readerFactory.getMetadataReader(resource);
String className = reader.getClassMetadata().getClassName();
try {
classSet.add(Class.forName(className));
} catch (NoClassDefFoundError e) {
//IGNORE 忽略jar中
}catch (ClassNotFoundException ex) {
//IGNORE 忽略jar中
}
}
}
}
return classSet;
}
/**
* 将符合条件的Bean以Class集合的形式返回
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static Set<Class<?>> getClassSet(String pkg) throws IOException {
String key = "pkg_"+pkg;
Set<Class<?>> classSet = new HashSet<Class<?>>();
Object o = getCache(key);
if(o != null){
classSet = (Set<Class<?>>)o;
}else{
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
org.springframework.util.ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;
Resource[] resources = resourcePatternResolver.getResources(pattern);
MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader reader = readerFactory.getMetadataReader(resource);
String className = reader.getClassMetadata().getClassName();
try {
classSet.add(Class.forName(className));
} catch (NoClassDefFoundError e) {
//IGNORE 忽略jar中
}catch (ClassNotFoundException ex) {
//IGNORE 忽略jar中
}
}
}
putCache(key, classSet);
}
return classSet;
}
/**
* 通过反射,获得定义Class时声明的父类的范型参数的类型. 如public BookManager extends GenricManager<Book>
* @param clazz 类
* @return 返回该类或者父类的第一个参数类型
* @author chenli
* @data 2016-2-28
*/
public static Class getSuperClassGenricType(Class clazz) {
return getSuperClassGenricType(clazz, 0);
}
/**
* 通过反射,获得定义Class时声明的父类的范型参数的类型. 如public BookManager extends GenricManager<Book>
* @param clazz 类
* @param index 返回的泛型位置
* @return
* @author chenli
* @data 2016-2-28
*/
public static Class getSuperClassGenricType(Class clazz, int index) {
clazz.getGenericInterfaces();
Type genType = clazz.getGenericSuperclass();
//改造一下 最多向上获取三级父类的泛型 如果三级还没有则返回错误
int i =0 ;
while (!(genType instanceof ParameterizedType) && i<3) {
clazz = clazz.getSuperclass();
genType = clazz.getGenericSuperclass();
}
if(!(genType instanceof ParameterizedType)){
logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
return Object.class;
}
return (Class) params[index];
}
/**
* 通过反射,获得定义Class时声明的接口的范型参数的类型. 如public BookManager implements IGenricManager<Book>
* @param clazz 类
* @param interfaceClass 集成的接口类型。
* @return
* @author chenli
* @data 2016-2-28
*/
public static Class getSuperInterfaceGenricType(Class clazz, Class interfaceClass) {
Type[] genTypes = clazz.getGenericInterfaces();
for (Type type : genTypes) {
if(!(type instanceof ParameterizedType)){
continue;
}
Type rawType = ((ParameterizedType) type).getRawType();
if(rawType.equals(interfaceClass)){
Type[] params = ((ParameterizedType) type).getActualTypeArguments();
if(params.length == 1){
return (Class)params[0];
}
}
}
return Object.class;
}
/**
* 放入缓存
* @param key 存储key
* @param o 存储对象
* @author chenli
* @data 2016-3-29
*/
private static void putCache(String key, Object o){
if(sr == null){
try {
lock.lock();
if(sr == null){
Map<String, Object> map = new HashMap<String, Object>();
sr = new SoftReference<Map<String,Object>>(map);
}
} catch (Exception e) {
//IGNORE 忽略锁异常
}finally{
lock.unlock();
}
}
Map<String, Object> map = sr.get();
if(map == null){
try {
lock.lock();
if(map == null){
map = new HashMap<String, Object>();
sr = new SoftReference<Map<String,Object>>(map);
}
} catch (Exception e) {
//IGNORE 忽略锁异常
}finally{
lock.unlock();
}
}
map.put(key, o);
}
/**
* 从缓存中换取
* @param key 存储key
* @param o 存储对象
* @author chenli
* @data 2016-3-29
*/
private static Object getCache(String key){
if(sr == null){
return null;
}
Map<String, Object> map = sr.get();
if(map == null){
return null;
}
return map.get(key);
}
/**
* 获取枚举类的注解({@link PropertyDesc})。
*
* @param prop
* 必须是枚举类。
* @return
* @author chenli
* @throws NoSuchFieldException
* @throws SecurityException
* @data 2016-4-1
*/
public static PropertyDesc getAnnotation(IProperty prop) throws SecurityException, NoSuchFieldException {
Field file = prop.getClass().getField(prop.toString());
PropertyDesc desc = file.getAnnotation(PropertyDesc.class);
return desc;
}
/**
* 获取当前调用者方法名称;排除当前工具类方法
* @return
*/
public static String getMethodName(){
return Thread.currentThread().getStackTrace()[1].getMethodName();
}
}
import org.springframework.core.ResolvableType;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.Assert;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
public class ClassUtils {
private static final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
private static final String RESOURCE_PATTERN = "/**/*.class";
/**
* For a specific class that implements or extends a parameterized type, return the
* parameter of that interface at a given position. For example, for this class:
*
* <pre> {@code
* class MessageChannelBinder implements Binder<MessageChannel, ?, ?>
* } </pre>
*
* <pre> {@code
* getParameterType(MessageChannelBinder.class, Binder.class, 0);
* } </pre>
*
* will return {@code Binder}
* @param evaluatedClass the evaluated class
* @param interfaceClass the parametrized interface
* @param position the position
* @return the parameter type if any
* @throws IllegalStateException if the evaluated class does not implement the
* interface or
*/
public static Class<?> getParameterType(Class<?> evaluatedClass,
Class<?> interfaceClass, int position) {
Class<?> bindableType = null;
Assert.isTrue(interfaceClass.isInterface(),
"'interfaceClass' must be an interface");
if (!interfaceClass.isAssignableFrom(evaluatedClass)) {
throw new IllegalStateException(
evaluatedClass + " does not implement " + interfaceClass);
}
LinkedList<ResolvableType> queue = new LinkedList<>();
queue.add(ResolvableType.forType(evaluatedClass));
while (!queue.isEmpty() && bindableType == null) {
ResolvableType currentType = queue.removeFirst();
Class<?> rawClass = currentType.getRawClass();//接口的superType是EmptyType rawClass为空
if(rawClass == null || Enum.class.equals(rawClass) || Object.class.equals(rawClass)){
continue;
}
ResolvableType[] interfaces = currentType.getInterfaces();
ResolvableType resolvableType = null;
for (ResolvableType interfaceType : interfaces) {
if (interfaceClass.equals(interfaceType.getRawClass())) {
resolvableType = interfaceType;
break;
}
queue.add(interfaceType);
}
if (resolvableType == null) {
queue.addFirst(currentType.getSuperType());
}
else {
ResolvableType[] generics = resolvableType.getGenerics();
ResolvableType generic = generics[position];
Class<?> resolvedParameter = generic.resolve();
if (resolvedParameter != null) {
bindableType = resolvedParameter;
}
else {
bindableType = Object.class;
}
}
}
if (bindableType == null) {
throw new IllegalStateException(
"Cannot find parameter of " + evaluatedClass.getName() + " for "
+ interfaceClass + " at position " + position);
}
return bindableType;
}
/**
* 获取接口的泛型类型,如果不存在则返回null
* @param clazz
* @return
*/
public static Class<?> getGenericClass(Class<?> clazz) {
Type t = clazz.getGenericSuperclass();
if (t instanceof ParameterizedType) {
Type[] p = ((ParameterizedType) t).getActualTypeArguments();
return ((Class<?>) p[0]);
}
return null;
}
/**
* 获取类的所有子类(包括接口)。 不能获取jar中的,只能获取classes下面的
* <br>等于{@link ClassUtils#getChilderClass(Class, boolean, String...)}中String wei
* @param c 查询类(接口)名
* @param containInterface 是否包括接口(和抽象类)
* @return
* @author chenli
* @data 2016-2-25
*/
public static <T> List<Class<T>> getChilderClass(Class<T> c, boolean containInterface, String... packageName) throws IOException {
List<Class<T>> returnClassList = new ArrayList<Class<T>>(); //返回结果
Set<Class<?>> allClass = getClassSet(packageName); //获得某个包以及子包下的所有类
for (Class<?> classes : allClass) {
if (c.isAssignableFrom(classes)){//判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同。
if (!c.equals(classes)){ //本身不加进去
if(containInterface || (containInterface==false && classes.isInterface() ==false && false == Modifier.isAbstract(classes.getModifiers()))){
returnClassList.add((Class<T>)classes);
}
}
}
}
return returnClassList;
}
/**
* 将符合条件的Bean以Class集合的形式返回
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static Set<Class<?>> getClassSet(String... packagesList) throws IOException {
Set<Class<?>> classSet = new HashSet<Class<?>>();
for (String pkg : packagesList) {
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
org.springframework.util.ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;
Resource[] resources = resourcePatternResolver.getResources(pattern);
MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader reader = readerFactory.getMetadataReader(resource);
String className = reader.getClassMetadata().getClassName();
try {
classSet.add(Class.forName(className));
} catch (NoClassDefFoundError e) {
//IGNORE 忽略jar中
}catch (ClassNotFoundException ex) {
//IGNORE 忽略jar中
}
}
}
}
return classSet;
}
}CookieUtil
java
/**
* sso session操作扩展
* @author chenli
* @date 2016-11-23
* @version 1.0
*/
public class CookieUtil{
protected final static Logger logger = LoggerFactory.getLogger(CookieUtil.class);
protected static int timeOut = -1;//默认COOKIES有效时间(会话cookie 随浏览器关闭而关闭)
private static CookieUtil instance =null;
private final static EncryptUtil encrypt = new AESUtil();
private final static Key key = encrypt.getKey("you and me");
private final static String SESSION_TOKEN = "sso_token"; //令牌
private final static String SESSION_USERID = "sso_userid"; //令牌
private CookieUtil(){
try {
timeOut = Integer.valueOf(PropertyEnum.SSO_COOKIE_TIME.getValue());
}catch(Exception e){
logger.error("解析cookie配置异常",e);
timeOut=-1;
}
}
public static CookieUtil getInstance() {
if(null==instance){
instance=new CookieUtil();
}
return instance;
}
/**
* 设置Cookie值.
* @param response
* @param name cookie名
* @param value cookie值
* @param time 分钟
*/
public void setCookie(HttpServletResponse response,String name,String value,int time){
try {
if(StringUtils.isNotBlank(value)){
//进行AES加密
value = encrypt.encoder(value, key);
}
//设置P3P Cookie
response.setHeader("P3P","CP='IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT'");
Cookie cookie = new Cookie(name,value);
if(time>0){
cookie.setMaxAge(time* 60);//单位分种
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
logger.error("设置Cookie值错误", e);
}
}
/**
* 设置会话Cookie值,值不加密,谨慎使用.
* @param response
* @param name
* @param value
*/
public void setNoEncryptCookie(HttpServletResponse response,String name,String value){
setCookie(response, name, value, timeOut,false);
}
/**
* 设置会话Cookie值.
* @param response
* @param name
* @param value
*/
public void setCookie(HttpServletResponse response,String name,String value){
setCookie(response, name, value, timeOut);
}
/**
* 获取Cookie变量.
* @param request
* @param name
* @return
*/
public String getCookie(HttpServletRequest request,String name){
Cookie cookie[] = request.getCookies();
String value = null;
if(cookie == null || cookie.length <= 0) return null;
for(int i = 0; i < cookie.length; i++){
if(cookie[i].getName().equalsIgnoreCase(name)){
value = cookie[i].getValue();
if(StringUtils.isNotBlank(value)){
value = encrypt.decoder(value, key);
}
}
}
if(value==null||value.equals("null"))
{
value=null;
}
return value;
}
/**
* 设置Cookie值.
* @param response
* @param name cookie名
* @param value cookie值
* @param time 分钟
*/
public void setCookie(HttpServletResponse response,String name,String value,int time,boolean isEncrypt){
try {
if(isEncrypt&&StringUtils.isNotBlank(value)){
//进行AES加密
value = encrypt.encoder(value, key);
}
//设置P3P Cookie
response.setHeader("P3P","CP='IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT'");
Cookie cookie = new Cookie(name,value);
if(time>0){
cookie.setMaxAge(time* 60);//单位分种
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
logger.error("设置Cookie值错误", e);
}
}
/**
* 根据名字删除指定COOKIE
* @param request
* @param response
* @param cookieName 需要删除的cookie名
* @return
*/
public void removeCookie(HttpServletRequest request,HttpServletResponse response, String cookieName){
Cookie cookies[] = request.getCookies();
if(cookies != null && cookies.length > 1){
Cookie cookie = new Cookie(cookieName,null);
cookie.setMaxAge(-1);
response.addCookie(cookie);
}
}
/**
* 用户TOKEN
* @param request
* @return
*/
public String getToken(HttpServletRequest request) {
String cookie = SessionUtil.getInstance().getToken(request);
//session读取失败从COOKIED中读取
if(StringUtils.isBlank(cookie)){
cookie = getCookie(request,SESSION_TOKEN);
}
return cookie;
}
/**
* 用户id
* @param request
* @return
*/
public Integer getUserid(HttpServletRequest request) {
Integer result = SessionUtil.getInstance().getClientUserid(request);
//session读取失败从COOKIED中读取
if(result == null){
String cookie = getCookie(request,SESSION_USERID);
if(StringUtils.isNotBlank(cookie) && StringUtils.isNumeric(cookie)){
result = StrHelper.strToInt(cookie, null);
}
}
return result;
}
/**
* 设置用户TOKEN
* @param request
* @param tokenid tokenid
* @author chenli
* @data 2016-11-7
*/
public void setToken(HttpServletRequest request, HttpServletResponse response,String tokenid, Integer userid) {
if(StringUtils.isBlank(tokenid) || userid == null){
SessionUtil.getInstance().setToken(request, null);
setCookie(response,SESSION_TOKEN,null);
SessionUtil.getInstance().setClientUserid(request, userid);
setCookie(response,SESSION_USERID,null);
}else{
//request attribute 放入一份,防止存在cookie未写入读取数据的问题
SessionUtil.getInstance().setToken(request, tokenid);
setCookie(response,SESSION_TOKEN,tokenid, timeOut);
SessionUtil.getInstance().setClientUserid(request, userid);
setCookie(response,SESSION_USERID,userid+"",timeOut);
}
}
}HttpUtil调用
java
/**
* HTTP简单调用工具类。
* 自动分辨是否是ssl通道。
* @author chenli
* @date 2016-4-26
* @version 1.0
*/
public class HttpUtil {
private static AbstractHttp httpGet = new HttpGet();
private static AbstractHttp httpPost = new HttpPost();
public final static String HEAD_SOAPACTION = "SOAPAction";
public final static String FILE_SYNCMETHOD = "syncmethod";
public final static String FILE_NAMESPACE = "namespace";
private static MsgTemplateService msgTemplateService = SpringContext.getBean("msgTemplateService");
private final static Logger logger = LoggerFactory.getLogger(HttpUtil.class);
/**
* 发送HTTP 消息
* @param url 请求地址。可以是http 或者 https
* @param args 对应模板。填充参数
* @param temp http消息模板
* @return
* @author chenli
* @throws DataAnalyzeMapException
* @throws IOException
* @throws UnknownServiceException
* @throws ServiceUnavailableException
* @throws MalformedURLException
* @data 2016-9-18
*/
public static String send(String url, Map<String, Object> args, HttpTempLate temp) throws DataAnalyzeMapException, MalformedURLException, ServiceUnavailableException, UnknownServiceException, IOException{
return send(url, args, temp, temp.getEncodetype());
}
/**
* 发送HTTP 消息
* @param url 请求地址。可以是http 或者 https
* @param args 对应模板。填充参数
* @param temp http消息模板
* @param encodetype 内容编码方式。 {@link IConstant#ENCODING_GBK} {@link IConstant#ENCODING_UTF8} 为空则使用默认编码。
* @return
* @author chenli
* @throws DataAnalyzeMapException
* @throws IOException
* @throws UnknownServiceException
* @throws ServiceUnavailableException
* @throws MalformedURLException
* @data 2016-9-18
*/
public static String send(String url, Map<String, Object> args, HttpTempLate temp, Integer encodetype) throws DataAnalyzeMapException, MalformedURLException, ServiceUnavailableException, UnknownServiceException, IOException{
if(temp == null){
return Http.HTTP_TEMPLATE_NULL.getCode();
}
int connTime = AbstractHttp.connectTime;
int readTime = AbstractHttp.readTimeout;
if(temp.getConntimeout() != null){
connTime = temp.getConntimeout()*1000;
}
if(temp.getReadtimeout() != null){
readTime = temp.getReadtimeout()*1000;
}
//数据编码
encodeValue(args,temp,encodetype);
//消息体
String content = getMsgTemp(args, temp);
//消息头
Map<String, String> httphead = getHttphead(temp);
//假如是webservice 且未定义soapaction且(命名空间和方法都不为空则)
if(isWebservice(temp) && httphead.containsKey(HEAD_SOAPACTION) == false){
addSoapAction(httphead, args);
}
AbstractHttp http;
if(isGet(temp)){
http = httpGet;
}else{
http = httpPost;
}
String result = http.send(url, content, httphead, connTime, readTime, null);
if(HttpUtil.isWebservice(temp)){
result = HttpUtil.webServiceResult(result);
}
return result;
}
/**
* post发送HTTP 消息
* @param url 请求地址。可以是http 或者 https
* @param content 请求内容
* @return
* @author chenli
* @throws IOException
* @throws UnknownServiceException
* @throws ServiceUnavailableException
* @throws MalformedURLException
* @data 2016-9-18
*/
public static String sendPost(String url, String content) throws MalformedURLException, ServiceUnavailableException, UnknownServiceException, IOException{
return httpPost.send(url, content, null);
}
/**
* post发送HTTP 消息
* @param url 请求地址。可以是http 或者 https
* @param content 请求内容
* @param httphead 请求头需添加内容
* @return
* @throws MalformedURLException
* @throws ServiceUnavailableException
* @throws UnknownServiceException
* @throws IOException
* @author wangyijie
* @data 2017年11月6日
*/
public static String sendPost (String url, String content, Map<String, String> httphead) throws MalformedURLException, ServiceUnavailableException, UnknownServiceException, IOException{
return httpPost.send(url, content, httphead);
}
/**
* post发送HTTP 消息
* @param url 请求地址。可以是http 或者 https
* @param content 请求内容
* @param httphead 请求头需添加内容
* @return
* @throws MalformedURLException
* @throws ServiceUnavailableException
* @throws UnknownServiceException
* @throws IOException
* @author wangyijie
* @data 2017年11月6日
*/
public static String sendPost (String url, String content, Map<String, String> httphead,int connTime, int readTime, String charsetName) throws MalformedURLException, ServiceUnavailableException, UnknownServiceException, IOException{
return httpPost.send(url, content, httphead,connTime,readTime,charsetName);
}
/**
* get发送HTTP 消息
* @param url 请求地址。可以是http 或者 https
* @return
* @author chenli
* @throws IOException
* @throws UnknownServiceException
* @throws ServiceUnavailableException
* @throws MalformedURLException
* @data 2016-9-18
*/
public static String sendGet(String url) throws MalformedURLException, ServiceUnavailableException, UnknownServiceException, IOException{
return httpGet.send(url, null, null);
}
/**
* get发送HTTP 消息
* @param url 请求地址。可以是http 或者 https
* @param httphead 请求头需添加内容
* @return
* @throws MalformedURLException
* @throws ServiceUnavailableException
* @throws UnknownServiceException
* @throws IOException
* @author wangyijie
* @data 2017年11月6日
*/
public static String sendGet (String url, Map<String, String> httphead) throws MalformedURLException, ServiceUnavailableException, UnknownServiceException, IOException{
return httpGet.send(url, null, httphead);
}
/**
* 解析消息体模板
* @param args 参数值
* @param temp http模板
* @return
* @throws DataAnalyzeMapException
* @author chenli
* @data 2016-10-10
*/
protected static String getMsgTemp(Map<String, Object> args, HttpTempLate temp) throws DataAnalyzeMapException {
// 解析HTTP消息模板
String result = msgTemplateService.buildTemplate(temp.getBodymsgtemp(), args);
return result;
}
/**
* 获取http 消息头
* @param temp http模板
* @return
* @throws DataAnalyzeMapException
* @author chenli
* @data 2016-10-10
*/
protected static Map<String, String> getHttphead(HttpTempLate temp) throws DataAnalyzeMapException {
Map<String, String> result = null;
String headtemp = temp.getHeadtemp();
if(StrHelper.isJsonObj(headtemp)){
result = SerializerUtil.deserializeObj(temp.getHeadtemp(), Map.class);
}
return result;
}
/**
* 判断是否使用了webservice 接口
* @param app
* @return
* @author chenli
* @data 2016-5-5
*/
public static boolean isWebservice(HttpTempLate temp){
if(temp == null){
return false;
}
return HttpTempLate.HTTPTYPE_WEBSERVICE.equals(temp.getHttptype());
}
/**
* 解析webservice 真正的返回结果。WEBSERVICE 自带xml格式
* @param result
* @return
* @author chenli
* @data 2016-5-5
*/
public static String webServiceResult(String result){
if(StrHelper.isXML(result)){
try {
XMLUtil util = new XMLUtil(result);
result = util.getWebserviceResult();
} catch (Exception e) {
logger.error("webservice 返回结果{}解析异常", result);
}
}
return result;
}
/**
* 判断是否使用了webservice 接口
* @param app
* @return
* @author chenli
* @data 2016-5-5
*/
protected static boolean isGet(HttpTempLate temp){
if(temp == null){
return false;
}
return HttpTempLate.SUBMITMETHOD_GET.equals(temp.getSubmitmethod());
}
/**
* 获取编码
* @param encodetype
* @return
* @author chenli
* @data 2016-5-4
*/
public static String getEncode(Integer encodetype){
if(HttpTempLate.ENCODETYPE_GBK.equals(encodetype)){
return IConstant.ENCODING_GBK;
}else if(HttpTempLate.ENCODETYPE_UTF8.equals(encodetype)){
return IConstant.ENCODING_UTF8;
}
return null;
}
/**
* 对map中的value 进行编码。 目前只对第一级String类型进行编码
* @param map 同步数据
* @param encodetype 编码类型 见{@link HttpTempLate#ENCODETYPE_GBK}
* @author chenli
* @data 2016-12-19
*/
protected static void encodeValue(Map<String, Object> map, HttpTempLate httpTempLate, Integer encodetype){
if(HttpTempLate.ENCODETYPE_NO.equals(encodetype)){
encodetype = httpTempLate.getEncodetype();
}
String charset = getEncode(encodetype);
if(isWebservice(httpTempLate)){
try {
xmlEscape(map);
} catch (Exception e) {
//IGNORE
}
}else{
Set<Map.Entry<String, Object>> set = map.entrySet();
for (Map.Entry<String, Object> entry : set) {
Object value = entry.getValue();
if(value instanceof String){
String temp = (String)value;
if(StringUtils.isNotBlank(charset)){
entry.setValue(StrHelper.urlEncode(temp, charset));
}else if(StrHelper.isNeedUrlEscape(temp)){
entry.setValue(StrHelper.urlEscape(temp));
}
}
}
}
}
/**
* 当参数中有命名空间和调用方法时 增加soapaction http头信息。
* @param headmap
* @param args
* @author chenli
* @data 2016-12-6
*/
private static void addSoapAction(Map<String, String> headmap, Map<String,Object> args){
Object _namespace = args.get(FILE_NAMESPACE);
Object _syncmethod = args.get(FILE_SYNCMETHOD);
if(_namespace != null && _syncmethod != null){
String action = _namespace.toString();
if(action.endsWith("/") == false){
action += "/";
}
action = action+_syncmethod.toString();
headmap.put(HEAD_SOAPACTION, action);
}
}
/**
* 把map中value进行xml特殊字符转义
* @param map
* @author chenli
* @data 2016-5-4
*/
protected static void xmlEscape(Map<String,Object> map){
Set<Map.Entry<String, Object>> set = map.entrySet();
for (Map.Entry<String, Object> entry : set) {
xmlEscape(entry);
}
}
/**
* 把map中value进行xml特殊字符转义
* @param map
* @author chenli
* @data 2016-5-4
*/
protected static void xmlEscape(List<Object> list){
int length = list.size();
for (int i=0;i<length;i++) {
Object value = list.get(i);
if(value instanceof String){
String temp = (String)value;
if(StrHelper.isNeedXmlEscape(temp,false)){
list.remove(i);
list.add(StrHelper.xmlEscape(temp,false));
i--;
length--;
}
}else if(value instanceof List){
xmlEscape(list);
}else if(value instanceof Map){
Map<String,Object> map = (Map<String,Object>)value;
xmlEscape(map);
}
}
}
/**
* 把map中value进行xml特殊字符转义
* @param entry
* @author chenli
* @data 2016-5-4
*/
protected static void xmlEscape(Map.Entry<String, Object> entry){
Object value = entry.getValue();
if(value instanceof String){
String temp = (String)value;
if(StrHelper.isNeedXmlEscape(temp,false)){
entry.setValue(StrHelper.xmlEscape(temp,false));
}
}else if(value instanceof List){
List<Object> list = (List<Object>)value;
xmlEscape(list);
}else if(value instanceof Map){
Map<String,Object> map = (Map<String,Object>)value;
xmlEscape(map);
}
}
/**
* 把map中value进行url特殊字符转义
* @param map
* @author chenli
* @data 2016-5-4
*/
protected static void urlEscape(Map<String,Object> map){
Set<Map.Entry<String, Object>> set = map.entrySet();
for (Map.Entry<String, Object> entry : set) {
urlEscape(entry);
}
}
/**
* 把map中value进行url特殊字符转义
* @param map
* @author chenli
* @data 2016-5-4
*/
protected static void urlEscape(List<Object> list){
int length = list.size();
for (int i=0;i<length;i++) {
Object value = list.get(i);
if(value instanceof String){
String temp = (String)value;
if(StrHelper.isNeedUrlEscape(temp)){
list.remove(i);
list.add(StrHelper.urlEscape(temp));
i--;
length--;
}
}else if(value instanceof List){
urlEscape(list);
}else if(value instanceof Map){
Map<String,Object> map = (Map<String,Object>)value;
urlEscape(map);
}
}
}
/**
* 把map中value进行url特殊字符转义
* @param entry
* @author chenli
* @data 2016-5-4
*/
protected static void urlEscape(Map.Entry<String, Object> entry){
Object value = entry.getValue();
if(value instanceof String){
String temp = (String)value;
if(StrHelper.isNeedUrlEscape(temp)){
entry.setValue(StrHelper.urlEscape(temp));
}
}else if(value instanceof List){
List<Object> list = (List<Object>)value;
urlEscape(list);
}else if(value instanceof Map){
Map<String,Object> map = (Map<String,Object>)value;
urlEscape(map);
}
}
public static void main(String[] args) throws MalformedURLException, ServiceUnavailableException, UnknownServiceException, IOException {
//用户信息
// Map<String,Object> map = new HashMap<String, Object>();
//// map.put("userId", "100010613");
// map.put("userName", "张三");
// map.put("mobile", "13011111113");
// map.put("email", "zhangsan4@dtdream.com");
// List<Integer> a = new ArrayList<Integer>();
// a.add(100016016);
// map.put("orgList", a);
// map.put("position", "position");
// map.put("officeTel", "12345678");
// map.put("workPlace", "workPlace");
// map.put("office", "office");
// map.put("jobNumber", "jobNumber");
// String body = SerializerUtil.serialize(map);
// Map<String,String> head = new HashMap<String, String>();
// head.put("Content-Type", "application/json;charset=UTF-8");
//// 新增 成功返回值{"errorcode":0,"messsage":"success","result":{"userId":"100010613"}}
// System.out.println(httpPost.send("http://183.131.17.231:18003/oapi/user/create?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0OTI2MDI4ODI1MDIsInVpZCI6ImNzcmZ0b2tlbiIsImlhdCI6MTQ5MjU5NTY4MjUwMn0.2D4XY8DaI_hLbTXOr5IIxEVrO-wT5tyLcknn488asRI×tamp=2017-04-19T11:00:00Z",body,head));
// //更新
//// System.out.println(httpPost.send("http://183.131.17.231:18003/oapi/user/update?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0OTI2MDI4ODI1MDIsInVpZCI6ImNzcmZ0b2tlbiIsImlhdCI6MTQ5MjU5NTY4MjUwMn0.2D4XY8DaI_hLbTXOr5IIxEVrO-wT5tyLcknn488asRI×tamp=2017-04-19T10:00:00Z",body,head));
//
// //删除
// System.out.println(httpPost.send("http://183.131.17.231:18003/oapi/user/delete?timestamp=2017-04-19T11:00:00Z&userId=100010614&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0OTI2MDI4ODI1MDIsInVpZCI6ImNzcmZ0b2tlbiIsImlhdCI6MTQ5MjU5NTY4MjUwMn0.2D4XY8DaI_hLbTXOr5IIxEVrO-wT5tyLcknn488asRI",null,head));
//用户信息
// Map<String,Object> map = new HashMap<String, Object>();
//// map.put("userId", "100010613");
// map.put("userName", "张三");
// map.put("mobile", "13011111113");
// map.put("email", "zhangsan4@dtdream.com");
// List<Integer> a = new ArrayList<Integer>();
// a.add(100016016);
// map.put("orgList", a);
// map.put("position", "position");
// map.put("officeTel", "12345678");
// map.put("workPlace", "workPlace");
// map.put("office", "office");
// map.put("jobNumber", "jobNumber");
// String body = SerializerUtil.serialize(map);
// Map<String,String> head = new HashMap<String, String>();
// head.put("Content-Type", "application/json;charset=UTF-8");
//// 新增 成功返回值{"errorcode":0,"messsage":"success","result":{"userId":"100010613"}}
// System.out.println(httpPost.send("http://183.131.17.231:18003/oapi/user/create?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0OTI2MDI4ODI1MDIsInVpZCI6ImNzcmZ0b2tlbiIsImlhdCI6MTQ5MjU5NTY4MjUwMn0.2D4XY8DaI_hLbTXOr5IIxEVrO-wT5tyLcknn488asRI×tamp=2017-04-19T11:00:00Z",body,head));
// //更新
//// System.out.println(httpPost.send("http://183.131.17.231:18003/oapi/user/update?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0OTI2MDI4ODI1MDIsInVpZCI6ImNzcmZ0b2tlbiIsImlhdCI6MTQ5MjU5NTY4MjUwMn0.2D4XY8DaI_hLbTXOr5IIxEVrO-wT5tyLcknn488asRI×tamp=2017-04-19T10:00:00Z",body,head));
//
// //删除
// System.out.println(httpPost.send("http://183.131.17.231:18003/oapi/user/delete?timestamp=2017-04-19T11:00:00Z&userId=100010614&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0OTI2MDI4ODI1MDIsInVpZCI6ImNzcmZ0b2tlbiIsImlhdCI6MTQ5MjU5NTY4MjUwMn0.2D4XY8DaI_hLbTXOr5IIxEVrO-wT5tyLcknn488asRI",null,head));
//组织信息
// Map<String,Object> map = new HashMap<String, Object>();
// map.put("orgNumber", 100016042);
// map.put("name", "测试三级1");
//
// map.put("deptHiding", false);
// map.put("fullName", "组织全称");
// map.put("orgCode", "12345678");
// map.put("postCode", "workPlace");
// String body = SerializerUtil.serialize(map);
// Map<String,String> head = new HashMap<String, String>();
// head.put("Content-Type", "application/json;charset=UTF-8");
//新增 成功返回值{"errorcode":0,"messsage":"success","result":{"userId":"100010613"}}
// //{"errorcode":0,"messsage":"success","result":{"orgNumber":"100016040"}}
// System.out.println(httpPost.send("http://183.131.17.231:18003/oapi/org/create?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0OTI2MDI4ODI1MDIsInVpZCI6ImNzcmZ0b2tlbiIsImlhdCI6MTQ5MjU5NTY4MjUwMn0.2D4XY8DaI_hLbTXOr5IIxEVrO-wT5tyLcknn488asRI×tamp=2017-04-19T11:00:00Z",body,head));
//更新
// System.out.println(body);
// System.out.println(httpPost.send("http://183.131.17.231:18003/oapi/org/update?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0OTI2MTA0NDk5NjcsInVpZCI6ImNzcmZ0b2tlbiIsImlhdCI6MTQ5MjYwMzI0OTk2N30.Owg1nPwhwEoSOyMLZ8u2O_4L4KoKGpEHcjZbtyZoCTk×tamp=2017-04-19T12:00:00Z",body,head));
//
// //删除
// System.out.println(httpPost.send("http://183.131.17.231:18003/oapi/org/delete?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHQiOjE0OTI2MTA0NDk5NjcsInVpZCI6ImNzcmZ0b2tlbiIsImlhdCI6MTQ5MjYwMzI0OTk2N30.Owg1nPwhwEoSOyMLZ8u2O_4L4KoKGpEHcjZbtyZoCTk×tamp=2017-04-19T12:00:00Z&orgNumber=100016042",null,head));
}
/**
* 获取application/json HTTP消息头
* @return
*/
public static Map<String,String> applicationJsonHttpHead(){
Map<String, String> httphead=new HashMap<>();
httphead.put(AbstractHttp.HEAD_CONTENT_TYPE, AbstractHttp.HEAD_CONTENT_TYPE_APPJSON);
httphead.put(AbstractHttp.HEAD_ACCEPT, AbstractHttp.HEAD_ACCEPT_APPJSON);
return httphead;
}
}身份证信息工具类
java
public class IdcardUtil {
/** 中国公民身份证号码最小长度。 */
public static final int CHINA_ID_MIN_LENGTH = 15;
/** 中国公民身份证号码最大长度。 */
public static final int CHINA_ID_MAX_LENGTH = 18;
/** 省、直辖市代码表 */
public static final String cityCode[] = {
"11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36", "37", "41",
"42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65", "71",
"81", "82", "91"
};
/** 每位加权因子 */
public static final int power[] = {
7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2
};
/** 第18位校检码 */
public static final String verifyCode[] = {
"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"
};
/** 最低年限 */
public static final int MIN = 1930;
public static Map<String, String> cityCodes = new HashMap<String, String>();
/** 台湾身份首字母对应数字 */
public static Map<String, Integer> twFirstCode = new HashMap<String, Integer>();
/** 香港身份首字母对应数字 */
public static Map<String, Integer> hkFirstCode = new HashMap<String, Integer>();
/**
* 性别 1男 2女
*/
public final static Integer SEX_MALE = 1;
public final static Integer SEX_FEMALE = 2;
static {
cityCodes.put("11", "北京");
cityCodes.put("12", "天津");
cityCodes.put("13", "河北");
cityCodes.put("14", "山西");
cityCodes.put("15", "内蒙古");
cityCodes.put("21", "辽宁");
cityCodes.put("22", "吉林");
cityCodes.put("23", "黑龙江");
cityCodes.put("31", "上海");
cityCodes.put("32", "江苏");
cityCodes.put("33", "浙江");
cityCodes.put("34", "安徽");
cityCodes.put("35", "福建");
cityCodes.put("36", "江西");
cityCodes.put("37", "山东");
cityCodes.put("41", "河南");
cityCodes.put("42", "湖北");
cityCodes.put("43", "湖南");
cityCodes.put("44", "广东");
cityCodes.put("45", "广西");
cityCodes.put("46", "海南");
cityCodes.put("50", "重庆");
cityCodes.put("51", "四川");
cityCodes.put("52", "贵州");
cityCodes.put("53", "云南");
cityCodes.put("54", "西藏");
cityCodes.put("61", "陕西");
cityCodes.put("62", "甘肃");
cityCodes.put("63", "青海");
cityCodes.put("64", "宁夏");
cityCodes.put("65", "新疆");
cityCodes.put("71", "台湾");
cityCodes.put("81", "香港");
cityCodes.put("82", "澳门");
cityCodes.put("91", "国外");
twFirstCode.put("A", 10);
twFirstCode.put("B", 11);
twFirstCode.put("C", 12);
twFirstCode.put("D", 13);
twFirstCode.put("E", 14);
twFirstCode.put("F", 15);
twFirstCode.put("G", 16);
twFirstCode.put("H", 17);
twFirstCode.put("J", 18);
twFirstCode.put("K", 19);
twFirstCode.put("L", 20);
twFirstCode.put("M", 21);
twFirstCode.put("N", 22);
twFirstCode.put("P", 23);
twFirstCode.put("Q", 24);
twFirstCode.put("R", 25);
twFirstCode.put("S", 26);
twFirstCode.put("T", 27);
twFirstCode.put("U", 28);
twFirstCode.put("V", 29);
twFirstCode.put("X", 30);
twFirstCode.put("Y", 31);
twFirstCode.put("W", 32);
twFirstCode.put("Z", 33);
twFirstCode.put("I", 34);
twFirstCode.put("O", 35);
hkFirstCode.put("A", 1);
hkFirstCode.put("B", 2);
hkFirstCode.put("C", 3);
hkFirstCode.put("R", 18);
hkFirstCode.put("U", 21);
hkFirstCode.put("Z", 26);
hkFirstCode.put("X", 24);
hkFirstCode.put("W", 23);
hkFirstCode.put("O", 15);
hkFirstCode.put("N", 14);
}
/**
* 将15位身份证转成18位身份证
* @param idCard 身份证
* @return
* 2017年10月29日
* wuzm
*/
public static String conver15CardTo18(String idCard) {
String idCard18 = "";
if (idCard.length() != CHINA_ID_MIN_LENGTH) {
return null;
}
if (isNum(idCard)) {
// 获取出生年月日
String birthday = idCard.substring(6, 12);
Date birthDate = null;
try {
birthDate = new SimpleDateFormat("yyMMdd").parse(birthday);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar cal = Calendar.getInstance();
if (birthDate != null)
cal.setTime(birthDate);
// 获取出生年(完全表现形式,如:2010)
String sYear = String.valueOf(cal.get(Calendar.YEAR));
idCard18 = idCard.substring(0, 6) + sYear + idCard.substring(8);
// 转换字符数组
char[] cArr = idCard18.toCharArray();
if (cArr != null) {
int[] iCard = converCharToInt(cArr);
int iSum17 = getPowerSum(iCard);
// 获取校验位
String sVal = getCheckCode18(iSum17);
if (sVal.length() > 0) {
idCard18 += sVal;
} else {
return null;
}
}
} else {
return null;
}
return idCard18;
}
/**
* 验证身份证是否合法
*/
public static boolean validateCard(String idCard) {
String card = idCard.trim();
if (validateIdCard18(card)) {
return true;
}
if (validateIdCard15(card)) {
return true;
}
String[] cardval = validateIdCard10(card);
if (cardval != null) {
if (cardval[2].equals("true")) {
return true;
}
}
return false;
}
/**
* 验证18位身份编码是否合法
* @param idCard 身份编码
* @return 是否合法
*/
public static boolean validateIdCard18(String idCard) {
boolean bTrue = false;
if (idCard.length() == CHINA_ID_MAX_LENGTH) {
// 前17位
String code17 = idCard.substring(0, 17);
// 第18位
String code18 = idCard.substring(17, CHINA_ID_MAX_LENGTH);
if (isNum(code17)) {
char[] cArr = code17.toCharArray();
if (cArr != null) {
int[] iCard = converCharToInt(cArr);
int iSum17 = getPowerSum(iCard);
// 获取校验位
String val = getCheckCode18(iSum17);
if (val.length() > 0) {
if (val.equalsIgnoreCase(code18)) {
bTrue = true;
}
}
}
}
}
return bTrue;
}
/**
* 验证15位身份编码是否合法
* @param idCard 身份编码
* @return 是否合法
*/
public static boolean validateIdCard15(String idCard) {
if (idCard.length() != CHINA_ID_MIN_LENGTH) {
return false;
}
if (isNum(idCard)) {
String proCode = idCard.substring(0, 2);
if (cityCodes.get(proCode) == null) {
return false;
}
String birthCode = idCard.substring(6, 12);
Date birthDate = null;
try {
birthDate = new SimpleDateFormat("yy").parse(birthCode.substring(0, 2));
} catch (ParseException e) {
e.printStackTrace();
}
Calendar cal = Calendar.getInstance();
if (birthDate != null)
cal.setTime(birthDate);
if (!valiDate(cal.get(Calendar.YEAR), Integer.valueOf(birthCode.substring(2, 4)),
Integer.valueOf(birthCode.substring(4, 6)))) {
return false;
}
} else {
return false;
}
return true;
}
/**
* 验证10位身份编码是否合法
* @param idCard 身份编码
* @return 身份证信息数组
* <p>
* [0] - 台湾、澳门、香港 [1] - 性别(男M,女F,未知N) [2] - 是否合法(合法true,不合法false)
* 若不是身份证件号码则返回null
* </p>
*/
public static String[] validateIdCard10(String idCard) {
String[] info = new String[3];
String card = idCard.replaceAll("[\\(|\\)]", "");
if (card.length() != 8 && card.length() != 9 && idCard.length() != 10) {
return null;
}
if (idCard.matches("^[a-zA-Z][0-9]{9}$")) { // 台湾
info[0] = "台湾";
String char2 = idCard.substring(1, 2);
if (char2.equals("1")) {
info[1] = "M";
} else if (char2.equals("2")) {
info[1] = "F";
} else {
info[1] = "N";
info[2] = "false";
return info;
}
info[2] = validateTWCard(idCard) ? "true" : "false";
} else if (idCard.matches("^[1|5|7][0-9]{6}\\(?[0-9A-Z]\\)?$")) { // 澳门
info[0] = "澳门";
info[1] = "N";
// TODO
} else if (idCard.matches("^[A-Z]{1,2}[0-9]{6}\\(?[0-9A]\\)?$")) { // 香港
info[0] = "香港";
info[1] = "N";
info[2] = validateHKCard(idCard) ? "true" : "false";
} else {
return null;
}
return info;
}
/**
* 验证台湾身份证号码
* @param idCard 身份证号码
* @return 验证码是否符合
*/
public static boolean validateTWCard(String idCard) {
String start = idCard.substring(0, 1);
String mid = idCard.substring(1, 9);
String end = idCard.substring(9, 10);
Integer iStart = twFirstCode.get(start);
Integer sum = iStart / 10 + (iStart % 10) * 9;
char[] chars = mid.toCharArray();
Integer iflag = 8;
for (char c : chars) {
sum = sum + Integer.valueOf(c + "") * iflag;
iflag--;
}
return (sum % 10 == 0 ? 0 : (10 - sum % 10)) == Integer.valueOf(end) ? true : false;
}
/**
* 验证香港身份证号码(存在Bug,部份特殊身份证无法检查)
* <p>
* 身份证前2位为英文字符,如果只出现一个英文字符则表示第一位是空格,对应数字58 前2位英文字符A-Z分别对应数字10-35
* 最后一位校验码为0-9的数字加上字符"A","A"代表10
* </p>
* <p>
* 将身份证号码全部转换为数字,分别对应乘9-1相加的总和,整除11则证件号码有效
* </p>
* @param idCard 身份证号码
* @return 验证码是否符合
*/
public static boolean validateHKCard(String idCard) {
String card = idCard.replaceAll("[\\(|\\)]", "");
Integer sum = 0;
if (card.length() == 9) {
sum = (Integer.valueOf(card.substring(0, 1).toUpperCase().toCharArray()[0]) - 55) * 9
+ (Integer.valueOf(card.substring(1, 2).toUpperCase().toCharArray()[0]) - 55) * 8;
card = card.substring(1, 9);
} else {
sum = 522 + (Integer.valueOf(card.substring(0, 1).toUpperCase().toCharArray()[0]) - 55) * 8;
}
String mid = card.substring(1, 7);
String end = card.substring(7, 8);
char[] chars = mid.toCharArray();
Integer iflag = 7;
for (char c : chars) {
sum = sum + Integer.valueOf(c + "") * iflag;
iflag--;
}
if (end.toUpperCase().equals("A")) {
sum = sum + 10;
} else {
sum = sum + Integer.valueOf(end);
}
return (sum % 11 == 0) ? true : false;
}
/**
* 将字符数组转换成数字数组
* @param ca 字符数组
* @return 数字数组
*/
public static int[] converCharToInt(char[] ca) {
int len = ca.length;
int[] iArr = new int[len];
try {
for (int i = 0; i < len; i++) {
iArr[i] = Integer.parseInt(String.valueOf(ca[i]));
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
return iArr;
}
/**
* 将身份证的每位和对应位的加权因子相乘之后,再得到和值
* @param iArr
* @return 身份证编码。
*/
public static int getPowerSum(int[] iArr) {
int iSum = 0;
if (power.length == iArr.length) {
for (int i = 0; i < iArr.length; i++) {
for (int j = 0; j < power.length; j++) {
if (i == j) {
iSum = iSum + iArr[i] * power[j];
}
}
}
}
return iSum;
}
/**
* 将power和值与11取模获得余数进行校验码判断
* @param iSum
* @return 校验位
*/
public static String getCheckCode18(int iSum) {
String sCode = "";
switch (iSum % 11) {
case 10:
sCode = "2";
break;
case 9:
sCode = "3";
break;
case 8:
sCode = "4";
break;
case 7:
sCode = "5";
break;
case 6:
sCode = "6";
break;
case 5:
sCode = "7";
break;
case 4:
sCode = "8";
break;
case 3:
sCode = "9";
break;
case 2:
sCode = "X";
break;
case 1:
sCode = "0";
break;
case 0:
sCode = "1";
break;
}
return sCode;
}
/**
* 根据身份编号获取年龄
* @param idCard 身份编号
* @return 年龄
*/
public static int getAgeByIdCard(String idCard) {
int iAge = 0;
if(StringUtils.isBlank(idCard)){
return iAge;
}
if (idCard.length() == CHINA_ID_MIN_LENGTH) {
idCard = conver15CardTo18(idCard);
}
String year = idCard.substring(6, 10);
Calendar cal = Calendar.getInstance();
int iCurrYear = cal.get(Calendar.YEAR);
iAge = iCurrYear - Integer.valueOf(year);
return iAge;
}
/**
* 根据身份编号获取生日
* @param idCard 身份编号
* @return 生日(yyyy-MM-dd)
*/
public static String getBirthByIdCard(String idCard) {
Integer len = idCard.length();
if (len < CHINA_ID_MIN_LENGTH) {
return null;
} else if (len == CHINA_ID_MIN_LENGTH) {
idCard = conver15CardTo18(idCard);
}
return idCard.substring(6, 10)+"-"+idCard.substring(10, 12)+"-"+idCard.substring(12, 14);
}
/**
* 根据身份编号获取生日年
* @param idCard 身份编号
* @return 生日(yyyy)
*/
public static Short getYearByIdCard(String idCard) {
Integer len = idCard.length();
if (len < CHINA_ID_MIN_LENGTH) {
return null;
} else if (len == CHINA_ID_MIN_LENGTH) {
idCard = conver15CardTo18(idCard);
}
return Short.valueOf(idCard.substring(6, 10));
}
/**
* 根据身份编号获取生日月
* @param idCard 身份编号
* @return 生日(MM)
*/
public static Short getMonthByIdCard(String idCard) {
Integer len = idCard.length();
if (len < CHINA_ID_MIN_LENGTH) {
return null;
} else if (len == CHINA_ID_MIN_LENGTH) {
idCard = conver15CardTo18(idCard);
}
return Short.valueOf(idCard.substring(10, 12));
}
/**
* 根据身份编号获取生日天
* @param idCard 身份编号
* @return 生日(dd)
*/
public static Short getDateByIdCard(String idCard) {
Integer len = idCard.length();
if (len < CHINA_ID_MIN_LENGTH) {
return null;
} else if (len == CHINA_ID_MIN_LENGTH) {
idCard = conver15CardTo18(idCard);
}
return Short.valueOf(idCard.substring(12, 14));
}
/**
* 根据身份编号获取性别
* @param idCard 身份编号
* @return 性别(1-男,2-女,NULL-未知)
*/
public static Integer getGenderByIdCard(String idCard) {
Integer sGender = null;
if(StringUtils.isBlank(idCard)){
return sGender;
}
if (idCard.length() == CHINA_ID_MIN_LENGTH) {
idCard = conver15CardTo18(idCard);
}
String sCardNum = idCard.substring(16, 17);
if (Integer.parseInt(sCardNum) % 2 != 0) {
sGender = SEX_MALE;
} else {
sGender = SEX_FEMALE;
}
return sGender;
}
/**
* 根据身份编号获取户籍省份
* @param idCard 身份编码
* @return 省级编码。
*/
public static String getProvinceByIdCard(String idCard) {
int len = idCard.length();
String sProvince = null;
String sProvinNum = "";
if (len == CHINA_ID_MIN_LENGTH || len == CHINA_ID_MAX_LENGTH) {
sProvinNum = idCard.substring(0, 2);
}
sProvince = cityCodes.get(sProvinNum);
return sProvince;
}
/**
* 数字验证
* @param val
* @return 提取的数字。
*/
public static boolean isNum(String val) {
return val == null || "".equals(val) ? false : val.matches("^[0-9]*$");
}
/**
* 验证小于当前日期 是否有效
* @param iYear 待验证日期(年)
* @param iMonth 待验证日期(月 1-12)
* @param iDate 待验证日期(日)
* @return 是否有效
*/
public static boolean valiDate(int iYear, int iMonth, int iDate) {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int datePerMonth;
if (iYear < MIN || iYear >= year) {
return false;
}
if (iMonth < 1 || iMonth > 12) {
return false;
}
switch (iMonth) {
case 4:
case 6:
case 9:
case 11:
datePerMonth = 30;
break;
case 2:
boolean dm = ((iYear % 4 == 0 && iYear % 100 != 0) || (iYear % 400 == 0))
&& (iYear > MIN && iYear < year);
datePerMonth = dm ? 29 : 28;
break;
default:
datePerMonth = 31;
}
return (iDate >= 1) && (iDate <= datePerMonth);
}
}图片处理工具类
java
/**
* 图片处理工具类
* @author Run the ant(wangyijie)
* @date 2018年4月11日
* @version 1.0
*/
public class ImgUtil {
private final static Logger logger = LoggerFactory.getLogger(ImgUtil.class);
/**
* 根据坐标裁剪图片
*
* @param srcPath 要裁剪图片的路径
* @param newPath 裁剪图片后的路径
* @param x 起始横坐标
* @param y 起始纵坐标
* @param width 截取宽度
* @param height 截取高度
* @author Run the ant(wangyijie)
* @data 2018年4月11日
*/
public static void cutImage (String srcPath, String newPath, int x, int y, int width, int height) {
try {
GMOperation op = new GMOperation();
op.addImage(srcPath);
op.crop(width, height, x, y);
//设置输出的图片压缩比,有效值范围是0.0-100.0,数值越大,缩略图越清晰
op.quality(95.0);
op.addImage(newPath);
//如果使用ImageMagick,设为false,使用GraphicsMagick,就设为true,默认为false
ConvertCmd convert = new ConvertCmd(true);
//本地测试用,linux下不要设置此值,不然会报错
//convert.setSearchPath("E:\\Program Files\\GraphicsMagick-1.3.28-Q16");
convert.run(op);
} catch (IOException e) {
logger.error("根据坐标裁剪图片失败!srcPath="+srcPath+"newPath="+newPath,e);
} catch (InterruptedException e) {
logger.error("根据坐标裁剪图片失败!srcPath="+srcPath+"newPath="+newPath,e);
} catch (IM4JavaException e) {
logger.error("根据坐标裁剪图片失败!srcPath="+srcPath+"newPath="+newPath,e);
} catch (Exception e) {
logger.error("根据坐标裁剪图片失败!srcPath="+srcPath+"newPath="+newPath,e);
}
}
/**
* 根据尺寸缩放图片
* @param width 缩放后的图片宽度
* @param height 缩放后的图片高度
* @param srcPath 源图片路径
* @param newPath 缩放后图片的路径
* @author Run the ant(wangyijie)
* @data 2018年4月11日
*/
public static void cutImage (int width, int height, String srcPath, String newPath) {
try {
GMOperation op = new GMOperation();
op.addImage(srcPath);
op.resize(width, height);
// op.quality(95.0);
op.addImage(newPath);
//如果使用ImageMagick,设为false,使用GraphicsMagick,就设为true,默认为false
ConvertCmd convert = new ConvertCmd(true);
//本地测试用,linux下不要设置此值,不然会报错
// convert.setSearchPath("E:\\Program Files\\GraphicsMagick-1.3.28-Q16");
convert.run(op);
} catch (IOException e) {
logger.error("根据尺寸缩放图片失败!srcPath="+srcPath+"newPath="+newPath,e);
} catch (InterruptedException e) {
logger.error("根据尺寸缩放图片失败!srcPath="+srcPath+"newPath="+newPath,e);
} catch (IM4JavaException e) {
logger.error("根据尺寸缩放图片失败!srcPath="+srcPath+"newPath="+newPath,e);
} catch (Exception e) {
logger.error("根据尺寸缩放图片失败!srcPath="+srcPath+"newPath="+newPath,e);
}
}
/**
* 给图片加水印
* @param srcPath 源图片路径
* @param text 添加的水印文字
* @param fontsize 文字大小
* @param color 文字颜色
* @param fontfamily 文字样式
* @author Run the ant(wangyijie)
* @data 2018年4月11日
*/
public static void addImgText (String srcPath, String text, Integer fontsize, String color, String fontfamily) {
try {
GMOperation op = new GMOperation();
op.font(fontfamily).gravity("southeast").pointsize(fontsize).fill(color).draw(text);
op.addImage();
op.addImage();
ConvertCmd convert = new ConvertCmd(true);
//本地测试用,linux下不要设置此值,不然会报错
// convert.setSearchPath("E:\\Program Files\\GraphicsMagick-1.3.28-Q16");
convert.run(op,srcPath,srcPath);
} catch (IOException e) {
logger.error("根据尺寸缩放图片失败!srcPath="+srcPath+"text="+text,e);
} catch (InterruptedException e) {
logger.error("根据尺寸缩放图片失败!srcPath="+srcPath+"text="+text,e);
} catch (IM4JavaException e) {
logger.error("根据尺寸缩放图片失败!srcPath="+srcPath+"text="+text,e);
} catch (Exception e) {
logger.error("根据尺寸缩放图片失败!srcPath="+srcPath+"text="+text,e);
}
}
public static void main(String[] args) {
// cutImage(1920, 1920, "C:\\Users\\Administrator\\Desktop\\IMG_20180411_163456.jpg", "C:\\Users\\Administrator\\Desktop\\test1.jpg");
//cutImage("C:\\Users\\Administrator\\Desktop\\1实时监测-01标准20180328.jpg", "C:\\Users\\Administrator\\Desktop\\123424324.jpg", 100, 100, 111, 111);
}
}ip地址工具类
java
public class IpExceptionLoginUtil {
private final static Logger logger = LoggerFactory.getLogger(IpExceptionLoginUtil.class);
/**
* 调用高德接口
* @param zone 地域(市)
* @param _ip ip地址
*
* @return 返回zone
* @author yzg
* @throws IOException
* @data 2019-3-26
*/
public String GetZoneByIp(String _ip) throws ServiceUnavailableException, IOException{
String url="https://restapi.amap.com/v3/ip?ip="+"_ip"
+ "&output=json&key=66e9388609d4c9a82b05b52c0e2d5ceb";
String result = HttpUtil.sendGet(url);
//String result = ToInterface.get(url);
JSONObject object = JSONObject.parseObject(result);
String zone = object.getString("city");
System.out.println(zone);
return zone;
}
}ip工具类
java
/**
* @author zhuwd
* @date 2016-7-11
* @version 1.0
*/
public class IpUtil {
private final static Logger logger = LoggerFactory.getLogger(IpUtil.class);
/**
* 检验某个ip地址是否在某个ip地址段区间内
* @param _ipArea ip地址区间段
* @param _ip 待验证的ip地址
* @return ip段区间为空或者ip验证通过返回true,否则返回false
* @author zhuwd
* @data 2016-7-4
*/
public static boolean isIpRange(String _ipArea, String _ip) {
boolean flag = true;
if (StringUtils.isBlank(_ipArea)) {// ip段为空时,直接返回true
return true;
}
if (false == isIp(_ip)) {// ip地址为空时,直接返回false
return false;
}
// 判断待验证ip地址是否合法(包括数字、"."两类字符)
String[] ipAreas = _ipArea.split("\\.");
String[] ips = _ip.split("\\.");
if(ipAreas.length != 4){
return false;
}
//验证ip地址是否在ip段范围内
String ipArea;
for (int i = 0; i < ipAreas.length; i++) {
if (ipAreas[i].equals(ips[i])) { // ip段规则和待验证ip地址相同
continue;
}
ipArea = ipAreas[i];
if(false == ipArea.contains("-")){
flag = false;
break;
}
int temp = i;// 将规则段中含ip段的索引记录下来
String[] ipa = ipArea.split("\\-");
if (!StringUtils.isNumeric(ips[temp])) {//判断是否由数字组成
flag = false;
break;
}
if (!StringUtils.isNumeric(ipa[0])) {
flag = false;
break;
}
if (!StringUtils.isNumeric(ipa[1])) {
flag = false;
break;
}
int is = Integer.parseInt(ips[temp]);
int area0 = Integer.parseInt(ipa[0]);
int area1 = Integer.parseInt(ipa[1]);
if (is > area1 || is < area0) {
flag = false;
break;
}
}
return flag;
}
/**
* 判断是否为ip, 包括ipV4 和 ipV6
* @param ip
* @return
* @author chenli
* @data 2016-8-17
*/
public static boolean isIp(String ip){
if(StringUtils.isBlank(ip)){
return false;
}
if(ip.indexOf('.')>-1){
return isIpV4(ip);
}else if(ip.indexOf(':')>-1){
return isIpV6(ip);
}
return false;
}
/**
* 判断是否为ipV4。 为空返回false
* @param ip ip地址
* @return
* @author chenli
* @data 2016-8-17
*/
public static boolean isIpV4(String ip){
boolean result = false;
if(StringUtils.isBlank(ip)){
return result;
}
if(ip.length()<7||ip.length()>15){
return false;
}
String[] ips = ip.split("\\.");
if(ips.length != 4){
return false;
}
//对待验证的ip地址(含三个“.”字符,即分割的长度为四)的每一位分割判断取值范围是否为0-255之间
result = true;
for (int i = 0; i < ips.length; i++) {
if (false == StringUtils.isNumeric(ips[i])) {//判断是否为数字组成
result = false;
break;
}
int is = Integer.parseInt(ips[i]);// 判断按“.”分割后每一位的数值取值范围是否在0-255之间
if (is >= 0 && is <= 255) {
continue;
}else{
result=false;
break;
}
}
return result;
}
/**
* 判断是否为ipV6。 为空返回false
* @param ip ip地址
* @return
* @author chenli
* @data 2016-8-17
*/
public static boolean isIpV6(String ip){
boolean result = false;
if(StringUtils.isBlank(ip)){
return result;
}
String[] ips = ip.split(":");
if(ips.length != 6){
return false;
}
result = true;
//FIXME ipV6判断
return result;
}
/**
* 验证ip地址是否满足以IP限制list集合中规则
* 是否满足验证通配符?、任意符* 或是IP段三种规则
* 三种规则示例如:127.0.0.? 、127.0.0.*、127.0.0.1-20
*
* @param ipsJson ipsJson 限制ip集合 JSON 数据
* @param ip 待验证ip地址
* @param isAllowNull 当ipsJson为空或者转成list之后的长度为0时返回值
* (比如:当设置该值为true时,则如果传入的ipsJson为null或者序列化为list之后的size为0则返回true)
* @return
* @author wangyijie
* @data 2018年1月3日
*/
public static boolean validateForJson (String ipsJson, String ip, boolean isAllowNull) {
if (ipsJson == null) {
return isAllowNull;
}
List<String> list = null;
try {
list = SerializerUtil.deserializeArray(ipsJson, String.class);
} catch (Exception e) {
logger.error("【ipsjson={}】 数据系列化异常", ipsJson);
}
if (list.size() < 1) {
return isAllowNull;
}
return validate(list, ip);
}
/**
* 验证ip地址是否满足以IP限制list集合中规则
* 是否满足验证通配符?、任意符* 或是IP段三种规则
* 三种规则示例如:127.0.0.? 、127.0.0.*、127.0.0.1-20
* @param ipsJson 限制ip集合 多个之间使用“,”隔开
* @param ip 待验证ip地址
* @return 当list集合为空或长度为0或待验证IP通过验证时返回true,否则返回false
* @author zhuwd
* @data 2016-7-11
*/
public static boolean validateForArrays(String ipsJson, String ip) {
if (ipsJson == null) { // 限制IP集合为空或是长度为0时,返回true
return true;
}
List<String> list = null;
try {
list = Arrays.asList(ipsJson.split(IConstant.SPLIT_SEP));
} catch (Exception e) {
logger.error("【ipsjson={}】 数据系列化异常", ipsJson);
}
return validate(list, ip);
}
/**
* 验证ip地址是否满足以IP限制list集合中规则
* 是否满足验证通配符?、任意符* 或是IP段三种规则
* 三种规则示例如:127.0.0.? 、127.0.0.*、127.0.0.1-20
* @param list 限制ip集合
* @param ip 待验证ip地址
* @return 当list集合为空或长度为0或待验证IP通过验证时返回true,否则返回false
* @author zhuwd
* @data 2016-7-11
*/
public static boolean validate(List<String> list, String ip) {
boolean flag = false;
if (list == null||list.size()==0) { // 限制IP集合为空或是长度为0时,返回true
return true;
}
if (StringUtils.isBlank(ip)) {
return false;
}
for (String string : list) {
if (string.contains("-")) {
flag = isIpRange(string, ip);
} else {
flag = StrHelper.match(string, ip);
}
if(flag)
break;
}
return flag;
}
/**
* 将十进制整数形式ip转long
* @param ipAddress
* @return
* 2017年10月27日
* wuzm
*/
public static long ipToLong(String ipAddress) {
long result = 0L;
//FIXME 目前只支持IPV4
if(!isIpV4(ipAddress)){
return result;
}
String[] ipAddressInArray = ipAddress.split("\\.");
for (int i = 3; i >= 0; i--) {
long ip = Long.parseLong(ipAddressInArray[3 - i]);
//left shifting 24,16,8,0 and bitwise OR
//1. 192 << 24
//1. 168 << 16
//1. 1 << 8
//1. 2 << 0
result |= ip << (i * 8);
}
return result;
}
/**
* 将十进制整数形式转换成127.0.0.1形式的ip地址
* @param ip
* @return
* 2017年11月14日
* wuzm
*/
public static String longToIp(Long ip){
if(null == ip){
return null;
}
StringBuilder sb = new StringBuilder();
//直接右移24位
sb.append(ip >> 24);
sb.append(".");
//将高8位置0,然后右移16
sb.append((ip & 0x00FFFFFF) >> 16);
sb.append(".");
//将高16位置0,然后右移8位
sb.append((ip & 0x0000FFFF) >> 8);
sb.append(".");
//将高24位置0
sb.append((ip & 0x000000FF));
return sb.toString();
}
public static String getHostAddress(){
try {
InetAddress candidateAddress = null;
// 遍历所有的网络接口
for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
// 在所有的接口下再遍历IP
for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
if (!inetAddr.isLoopbackAddress()) {// 排除loopback类型地址
if (inetAddr.isSiteLocalAddress()) {
// 如果是site-local地址,就是它了
return inetAddr.getHostAddress();
} else if (candidateAddress == null) {
// site-local类型的地址未被发现,先记录候选地址
candidateAddress = inetAddr;
}
}
}
}
if (candidateAddress != null) {
return candidateAddress.getHostAddress();
}
// 如果没有发现 non-loopback地址.只能用最次选的方案
InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
return jdkSuppliedAddress.getHostAddress();
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
public static void main(String[] args) {
//System.err.println(longToIp(16909567L));
System.err.println(getHostAddress());
}
/**
* 获取本地InetAddress对象
* 当存在多个网络接口时,这种方法效果很好。它总是返回首选的出站IP。目的地223.5.5.5(阿里DNS)不需要到达。 参考:
* https://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java
*
* @return
*/
public static InetAddress getLocalInetAddress() {
try (final DatagramSocket socket = new DatagramSocket()) {
socket.connect(InetAddress.getByName("223.5.5.5"), 10002);
return socket.getLocalAddress();
} catch (Exception e) {
// ignore
}
return null;
}
}服务器信息工具类
java
/**
* 电脑工具类
* @author chenli
* @date:2014-7-17 下午4:19:13
* @version :4.2
*
*/
public class MachineUtil {
/**
* 获取本机ip
* @return
* @author chenli
* @data 2014-7-17
*/
public static String getIp()
{
String mac = "";
try{
InetAddress localIP = InetAddress.getLocalHost();
mac = localIP.getHostAddress();
} catch (UnknownHostException e) {
}
return mac;
}
/**
* 获取本机mac地址
* @return
* @throws Exception
*/
public static String getMACAddress() throws IOException {
// 获取本地IP对象
InetAddress ia = InetAddress.getLocalHost();
// 获得网络接口对象(即网卡),并得到mac地址,mac地址存在于一个byte数组中。
byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
if(mac == null){//使用命名获取
return getMACAddress2();
}
// 下面代码是把mac地址拼装成String
StringBuffer sb = new StringBuffer();
for (int i = 0; i < mac.length; i++) {
if (i != 0) {
sb.append("-");
}
// mac[i] & 0xFF 是为了把byte转化为正整数
String s = Integer.toHexString(mac[i] & 0xFF);
sb.append(s.length() == 1 ? 0 + s : s);
}
// 把字符串所有小写字母改为大写成为正规的mac地址并返回
return sb.toString().toUpperCase();
}
/**
* 获得操作系统的名称
* @return
*/
public static String getOsName() {
String os = "";
os = System.getProperty("os.name");
return os;
}
/**
* 获得mac地址
* @return
*/
private static String getMACAddress2() throws IOException {
String address = "";
String os = getOsName();
if (os.startsWith("Windows")) {
String command = "cmd.exe /c ipconfig /all";
Process p = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
if (line.indexOf("Physical Address") > 0) {
int index = line.indexOf(":");
index += 2;
address = line.substring(index);
break;
}
}
br.close();
} else if (os.startsWith("Linux")) {
String command = "/bin/sh -c ifconfig -a";
Process p;
p = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
if (line.indexOf("HWaddr") > 0) {
int index = line.indexOf("HWaddr") + "HWaddr".length();
address = line.substring(index);
break;
}
}
br.close();
}
address = address.trim().replaceAll("-", "");
return address;
}
}请求响应参数工具类
java
/**
*
* Title:本类包,主要用于提交参数
* Description: Copyright: Copyright (c) 2007
* @author hzc
* @version 1.0
*/
public final class ParameterUtil {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ParameterUtil.class.getName());
public ParameterUtil() {
}
/**
* 取得提交的参数,同时过滤掉空值;
* @param request HttpServletRequest
* @param paramName String
* @return String
*/
public static String getParameter(HttpServletRequest request,
String paramName) {
String temp = request.getParameter(paramName);
if (temp != null) {
return (temp.trim());
} else {
return "";
}
}
/**
* 取得提交的内容,若为空则以默认的字符串代替
*
* @param request HttpServletRequest
* @param paramName String
* @param defalutString String
* @return String
*/
public static String getParameter(HttpServletRequest request,String paramName, String defalutString) {
String string = getParameter(request, paramName);
if (string.length() == 0 || string == null) {
return defalutString;
}
return string.trim();
}
/**
* 取得int类型属性值
*
* @param request HttpServletRequest
* @param paramName String
* @param defaultNum int
* @return int
*/
public static int getIntParameter(HttpServletRequest request,String paramName, int defaultNum) {
String temp = request.getParameter(paramName);
if (temp != null && !temp.equals("")) {
int num = defaultNum;
try {
num = Integer.parseInt(temp);
} catch (Exception exception) {logger.error("ParameterFactory 类 getIntParameter错误", exception);}
return num;
} else {
return defaultNum;
}
}
public static float getFloatParameter(HttpServletRequest request,String paramName, float defaultNum) {
String temp = request.getParameter(paramName);
if (temp != null && !temp.equals("")) {
float num = defaultNum;
try {
num = Float.parseFloat(temp);
} catch (Exception exception) {logger.error("ParameterFactory 类 getFloatParameter错误", exception);}
return num;
} else {
return defaultNum;
}
}
/**
* 将数据转成String,自动过滤空值
*
* @param Object o
* @return String
*/
public static String toString(Object o) {
if (o == null || o.toString().toUpperCase().trim().equals("NULL")|| o == "NULL") {
return "";
}
return o.toString().trim();
}
/**
* 将数据转成long,自动过滤空值
* @param Object o
* @return long
*/
public static long toLong(Object o) {
if (o == null || o.toString().toUpperCase().trim().equals("NULL")|| o == "NULL") {
return 0l;
}
return Long.parseLong(o.toString());
}
/**
* 将数据转成long,自动过滤空值
* @param Object o
* @return long
*/
public static int toInt(Object o) {
if (o == null || o.toString().toUpperCase().trim().equals("NULL")|| o == "NULL") {
return 0;
}
return Integer.parseInt(o.toString());
}
public static Timestamp toTimestamp(Object o) {
if (o == null || o.toString().toUpperCase().trim().equals("NULL")|| o == "NULL") {
return null;
}
return Timestamp.valueOf(o.toString());
}
/**
* 获取ip地址
* @param request
* @return
* @author chenli
* @data 2014-8-7
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
//特殊处理ip可能有多个 取第一个
if(StringUtils.contains(ip, IConstant.SPLIT_SEP)){
ip = StringUtils.substringBefore(ip, IConstant.SPLIT_SEP);
}
//防止头信息被注入,对ip处理
if(false == IpUtil.isIp(ip)){
ip = "";
logger.info("用户ip={}不合法,已重置为空字符串",ip);
}
return ip;
}
/**
* 获取项目发布地址
* @param request
* @return
* @author zhuwd
* @data 2017-10-25
*/
public static String getPublishAddress(HttpServletRequest request) {
String url = request.getRequestURL().toString();
String servletPath = request.getServletPath();
url = AccessDecisionUtil.dealUrlJsessionid(url);
return url.replaceFirst(servletPath, "");
}
/**
* 获取域名地址
* @param request
* @return
* @author chenli
* @data 2018-4-8
*/
public static String getDomain(HttpServletRequest request) {
StringBuffer url = request.getRequestURL();
int start= url.indexOf(IConstant.SPLIT_URL_SEP)+2;
int end = url.indexOf(IConstant.SPLIT_URL_SEP, 10);//没有端口的情况
int end2 = url.indexOf(":", 10);//有端口的情况
if(end2 != -1 && end2 < end){
end = end2;
}
if(end == -1){
end = url.length();
}
return url.substring(start, end);
}
/**
* 获取用户使用的浏览器
* @author chenli
* @data 2014-8-7
*/
public static String getUserAgent(HttpServletRequest request) {
String userAgent = getHeader(request, "User-Agent");
//防止头信息被注入,对特殊字符进行转义
return StrHelper.escapeUrlXss(userAgent);
}
/**
* 获取指定请求头数据
*/
public static String getHeader(HttpServletRequest request, String name) {
return request.getHeader(name);
}
private final static String[] mobileAgent = {"android","iphone os","ipad","windows phone"};
private final static String[] wechatAgent = {"micromessenger"};
/**
* 判断是否是微信内部浏览器
* @param request
* @return
* @author wangyujie
* @data 2018年4月2日
*/
public static boolean isWechatDev(HttpServletRequest request){
boolean result = false;
String userAgent = getUserAgent(request);
if(StringUtils.isBlank(userAgent)){
return result;
}
userAgent = userAgent.toLowerCase();
for (String agent : wechatAgent) {
if(userAgent.indexOf(agent) != -1){
result = true;
break;
}
}
return result;
}
/**
* 判断是否是手机端访问
* @author chenli
* @data 2016-11-18
*/
public static boolean isMobileDev(HttpServletRequest request) {
String userAgent = getUserAgent(request);
return isMobileDev(userAgent);
}
/**
* 判断是否手机端访问
* @param userAgent 用户使用的浏览器
* @return
* @author Run the ant(wangyijie)
* @data 2018年5月3日
*/
public static boolean isMobileDev (String userAgent) {
boolean result = false;
if(StringUtils.isBlank(userAgent)){
return result;
}
userAgent = userAgent.toLowerCase();
for (String agent : mobileAgent) {
if(userAgent.indexOf(agent) != -1){
result = true;
break;
}
}
return result;
}
/**
* 是否为电脑端
* @param request
* @return
* @author chenli
* @data 2017-7-14
*/
public static boolean isPCDev(HttpServletRequest request) {
return isMobileDev(request) == false;
}
/**
* 是否为电脑端
* @param userAgent 用户使用的浏览器
* @return
* @author Run the ant(wangyijie)
* @data 2018年5月3日
*/
public static boolean isPCDev (String userAgent) {
return isMobileDev(userAgent) == false;
}
/**
* 是否为安卓手机端
* @param request
* @return
* @author chenli
* @data 2017-7-14
*/
public static boolean isAndroidDev(HttpServletRequest request) {
return PHONE_ANDROID.equals(phoneType(request));
}
/**
* 移动端 安卓 IOS OTHER 类型返回
* @param request
* @return
* @author wangyujie
* @data 2017年12月21日
*/
public transient final static Integer PHONE_ANDROID = 1;
public transient final static Integer PHONE_IOS = 2;
public transient final static Integer PHONE_OTHER = 3;
public static Integer phoneType(HttpServletRequest request){
Integer result = null;
String userAgent = getUserAgent(request);
if(StringUtils.isNotBlank(userAgent)){
userAgent = userAgent.toLowerCase();
if(isMobileDev(request)){
result = PHONE_OTHER;
if(userAgent.indexOf("android") != -1){
result = PHONE_ANDROID;
}
if(userAgent.indexOf("iphone os") != -1 || userAgent.indexOf("ipad") != -1){
result = PHONE_IOS;
}
}
}
return result;
}
/**
* 移动端 安卓 IOS OTHER 类型返回
* @param userAgent 用户使用的浏览器
* @return
* @author Run the ant(wangyijie)
* @data 2018年5月3日
*/
public static Integer phoneType (String userAgent) {
Integer result = null;
if(StringUtils.isNotBlank(userAgent)){
userAgent = userAgent.toLowerCase();
if(isMobileDev(userAgent)){
result = PHONE_OTHER;
if(userAgent.indexOf("android") != -1 || userAgent.indexOf("samsung") != -1 || userAgent.indexOf("OPPO") != -1
|| userAgent.indexOf("Xiaomi") != -1 || userAgent.indexOf("vivo") != -1 ){
result = PHONE_ANDROID;
}
if(userAgent.indexOf("iphone os") != -1 || userAgent.indexOf("ipad") != -1){
result = PHONE_IOS;
}
}
}
return result;
}
/**
* 解析参数为map。 如a=1&b=2 则返回 a:1 b:2的map
* @param extargs a=1&b=2
* @return
* @author chenli
* @data 2016-11-18
*/
public static Map<String, String> parseArgs(String extargs){
Map<String, String> result = new HashMap<String, String>();
if(StringUtils.isBlank(extargs)|| extargs.indexOf('=')<0){
return result;
}
String[] args = extargs.split("&");
int i = 0;
for (String temp : args) {
i = temp.indexOf('=');
if(i>0){
result.put(temp.substring(0, i), temp.substring(i+1));
}
}
return result;
}
/**
* 生成参数为a=1&b=2
* @param map 参数键值对
* @return
* @author chenli
* @data 2017-10-18
*/
public static String bulidArgs(Map<String, String> map){
return bulidArgs(map, null);
}
/**
* 生成参数为a=1&b=2
* @param map 参数键值对. 值将以参数 encoding 进行编码
* @param encoding 编码 参见{@link IConstant#ENCODING_GBK} {@link IConstant#ENCODING_UTF8} 为空则默认编码
* @return
* @author chenli
* @data 2017-10-18
*/
public static String bulidArgs(Map<String, String> map, String encoding){
StringBuffer result = new StringBuffer();
if(map == null || map.size() ==0){
return result.toString();
}
String key = "";
String value = "";
for (Map.Entry<String, String> entry : map.entrySet()) {
key = entry.getKey();
value = entry.getValue();
if(StringUtils.isBlank(key) || StringUtils.isBlank(value)){
continue;
}
if(result.length()>0){
result.append("&");
}
result.append(key).append("=").append(StrHelper.urlEncode(value, encoding));
}
return result.toString();
}
/**
* 生成geturl
* @param url
* @param map 参数键值对.
* @return
* @author chenli
* @data 2016-11-18
*/
public static String bulidUrl(String url,Map<String, String> map){
return bulidUrl(url, map, null);
}
/**
* 生成geturl
* @param url
* @param map 值将以参数 encoding 进行编码
* @param encoding 编码 参见{@link IConstant#ENCODING_GBK} {@link IConstant#ENCODING_UTF8} 为空则默认编码
* @return
* @author chenli
* @data 2016-11-18
*/
public static String bulidUrl(String url,Map<String, String> map, String encoding){
if(StringUtils.isBlank(url)){
return "";
}
String args = bulidArgs(map,encoding);
if(StringUtils.isBlank(args)){
return url;
}
if(url.indexOf("?")>0){
url +="&";
}else{
url +="?";
}
return url + args;
}
/**
* 根据datatype的不同设置对应的返回格式,默认返回text格式
* @param response
* @param text 返回文本内容
* @param contentType 返回类型,默认text
* @author wuzm
* @data 2016年11月7日
*/
public static void contextType(HttpServletResponse response,String text,String contentType){
if(StringUtils.equalsIgnoreCase(SerializeFactory.DATATYPE_XML, contentType)){
renderXML(response,text);
}else if(StringUtils.equalsIgnoreCase(SerializeFactory.DATATYPE_JSON, contentType)){
renderJson(response,text);
}else {
renderText(response, text);
}
}
/**
* 直接输出.
*
* @param contentType 内容的类型.html,text,xml的值见后,json为"text/x-json;charset=UTF-8"
*/
public static void render(HttpServletResponse response, String text,String contentType){
try {
logger.debug("response {}:{}", contentType, text);
response.setContentType(contentType);
response.setContentLength(text.getBytes("UTF-8").length);
response.getWriter().write(text);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
/**
* 直接输出纯XML.
*/
public static void renderXML(HttpServletResponse response, String text) {
render(response,text,"text/xml;charset=UTF-8");
}
/**
* 直接输出纯Json.
*/
public static void renderJson(HttpServletResponse response, String text) {
render(response, text, "application/json;charset=UTF-8");
}
/**
* 直接输出纯字符串.
*/
public static void renderText(HttpServletResponse response, String text) {
render(response,text,"text/plain;charset=UTF-8");
}
/**
* 直接输出纯HTML.
*/
public static void renderHtml(HttpServletResponse response, String text) {
render(response,text,"text/html;charset=UTF-8");
}
/**
* 直接输出纯js.
*/
public static void renderJs(HttpServletResponse response, String text) {
render(response,text,"application/javascript");
}
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
c.set(2017, 6, 1);
System.out.println(c.getTime());
System.out.println(SerializerUtil.serialize(Base.SUCCESS));
}
}汉字转拼音工具类
java
/**
* 汉字转换成拼音工具类
* @author chenli
* @date 2016-4-7
* @version 1.0
*/
public class PinYinUtil {
private final static Logger logger = LoggerFactory.getLogger(PinYinUtil.class);
private final static HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
static{
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_V);
}
/**
* 把输入转成全拼音。
* @param src 输入字符串。
* @return
* @author chenli
* @data 2016-4-7
*/
public static String getPingYin(String src) {
if(StringUtils.isBlank(src)){
return src;
}
StringBuffer result = new StringBuffer();
try {
Character temp;
for (int i = 0; i < src.length(); i++) {
// 判断是否为汉字字符
temp = src.charAt(i);
if (Character.toString(temp).matches(
"[\\u4E00-\\u9FA5]+")) {
String[] t2 = PinyinHelper.toHanyuPinyinStringArray(temp, format);
result.append(t2[0]);
} else
result.append(temp);
}
} catch (BadHanyuPinyinOutputFormatCombination e1) {
logger.error("转换拼音失败。待转换字符串:"+src,e1);
}
return result.toString();
}
/**
* 转换中文的首字母
* @param str
* @return
* @author chenli
* @data 2016-4-7
*/
public static String getPinYinHeadChar(String str) {
if(StringUtils.isBlank(str)){
return str;
}
StringBuffer convert = new StringBuffer();
for (int j = 0; j < str.length(); j++) {
char word = str.charAt(j);
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
if (pinyinArray != null) {
convert.append(pinyinArray[0].charAt(0));
} else {
convert.append(word);
}
}
return convert.toString();
}
}非对称加密实现
java
/**
* RSA 非对称加密算法实现
* @author chenli
* @date 2016-7-28
* @version 1.0
*/
@Service
public class RSAUtil {
@Resource(name = "cache")
private BaseCache<Key> cache;
private ReentrantLock queueLock = new ReentrantLock();
/**
* 缓存的公钥和私钥的key
*/
private transient final static String NAMESPACE = "rsa";
private transient final static String NAMESPACE_PRIVATE_KEY = "privatekey";
private transient final static String NAMESPACE_PUBLIC_KEY = "publickey";
private static final Logger logger = LoggerFactory.getLogger(RSAUtil.class);
/**
* 获取RSA 私钥
* @return
* @author chenli
* @data 2017-12-7
*/
private PrivateKey getPrivatekey(){
PrivateKey key = (PrivateKey)cache.get(NAMESPACE, NAMESPACE_PRIVATE_KEY);
if(key == null){
init();
key = (PrivateKey)cache.get(NAMESPACE, NAMESPACE_PRIVATE_KEY);
}
return key;
}
/**
* 获取RSA 公钥
* @return
* @author chenli
* @data 2017-12-7
*/
private PublicKey getPublickey(){
PublicKey key = (PublicKey)cache.get(NAMESPACE, NAMESPACE_PUBLIC_KEY);
if(key == null){
init();
key = (PublicKey)cache.get(NAMESPACE, NAMESPACE_PUBLIC_KEY);
}
return key;
}
/**
* 生成公钥和私钥
*
*/
public void init(){
try {
queueLock.lock();
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA", "BC");
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
cache.put(NAMESPACE, NAMESPACE_PRIVATE_KEY, keyPair.getPrivate());
cache.put(NAMESPACE, NAMESPACE_PUBLIC_KEY, keyPair.getPublic());
} catch (Exception e) {
logger.error("RSA 算法生成公私钥对异常",e);
}finally{
queueLock.unlock();
}
}
/**
* 获取RSA 默认公钥
* @return
* @author chenli
* @data 2016-7-28
*/
public String getPublickeyBase64(){
byte[] b = getPublickey().getEncoded();
return Base64.encodeBase64String(b);
}
/**
* 使用默认的公钥,进行RAS明文加密。 返回结果为BASE64编码的字符串
* @param data
* @return
* @throws Exception
* @author chenli
* @data 2016-7-28
*/
public String encryptBase64(String data) throws Exception{
byte[] b = encrypt(data, getPublickey());
return Base64.encodeBase64String(b);
}
/**
* 使用默认的私钥,进行RAS密文解密。 密文是base64编码的字符串
* @param data base64编码的字符串
* @return
* @throws Exception
* @author chenli
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws UnsupportedEncodingException
* @throws NoSuchPaddingException
* @throws NoSuchProviderException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @data 2016-7-28
*/
public String decryptBase64(String data) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException{
byte[] b = Base64.decodeBase64(data);
return decrypt(b, getPrivatekey());
}
/**
* RSA 加密
* @param data 明文
* @param publicKey 公钥
* @return
* @throws Exception
* @author chenli
* @throws NoSuchPaddingException
* @throws NoSuchProviderException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws UnsupportedEncodingException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @data 2016-7-28
*/
public static byte[] encrypt(String data, PublicKey publicKey) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] b =cipher.doFinal(data.getBytes("UTF-8"));
return b;
}
/**
* RSA 解密
* @param data 密文
* @param privateKey 私钥
* @return
* @throws Exception
* @author chenli
* @throws NoSuchPaddingException
* @throws NoSuchProviderException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws UnsupportedEncodingException
* @data 2016-7-28
*/
public static String decrypt(byte[] data, PrivateKey privateKey) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//模长
return new String(cipher.doFinal(data),"UTF-8");
}
}本地线程工具类
java
/**
* 线程本地变量工具类
*
* @author Brack.zhu
* @date 2018-1-4
*/
public class ThreadLocalUtil {
private static final ThreadLocal<ConcurrentHashMap<String, Object>> threadSession = new ThreadLocal<ConcurrentHashMap<String, Object>>();
private static String defKey = "_defKey_";
private static String secDomain = "_secDomainKey_";
/**
* 设置线程本地变量
*
* @param key
* @param obj
*/
public static void set(String key, Object obj) {
getMap().put(key, obj);
}
/**
* 设置线程本地变量
*
* @param obj
*/
public static void setDef(Object obj) {
set(defKey, obj);
}
/**
* 设置二级域名线程本地变量
*
* @param secDoamin
*/
public static void setSecDomain(String secDoamin) {
set(secDomain, secDoamin);
}
/**
* 获取线程本地变量
*
* @param key
* @return
*/
public static Object get(String key) {
return getMap().get(key);
}
/**
* 获取线程本地默认变量
*
* @return
*/
public static Object getDef() {
return get(defKey);
}
/**
* 获取线程本地二级域名变量
*
* @return
*/
public static String getSecDomain() {
return String.valueOf(get(secDomain));
}
/**
* 移除线程本地变量
*
* @param key
*/
public static void del(String key) {
getMap().remove(key);
}
/**
* 移除线程本地默认变量
*
*/
public static void delDef() {
del(defKey);
}
/**
* 删除线程本地二级域名变量
*
* @return
*/
public static void delSecDomain() {
del(secDomain);
}
/**
* 是否默认域名
* @return
*/
public static boolean isDefSecDomain(){
return isDefSecDomain(getSecDomain());
}
/**
* 是否默认域名
* @return
*/
public static boolean isDefSecDomain(String domain){
if(IConstant.WWW.contains(domain)){
return true;
}else{
return false;
}
}
/**
* 获取线程本地变量内部Map,无则新增
*
* @return
*/
private static ConcurrentHashMap<String, Object> getMap() {
ConcurrentHashMap<String, Object> res = threadSession.get();
if (null == res) {
res = new ConcurrentHashMap<String, Object>();
threadSession.set(res);
}
return res;
}
}字符编码解码工具类
java
/**
* Copyright (c) 2005-2007, 易和互联软件技术有限公司
* Commnet Software Tech All Rights Reserved.
*
* 工具类,包含一些常用方法.
* @author josson.jin
* @date 2007-4-4
*/
public class Utilities {
private static Logger log= LoggerFactory.getLogger(Utilities.class);
/**
* 将字符串转换为UTF-8解码
* @param aValue
* @return
* @throws Exception
*/
public static String decode(String str) {
return decode(str,"UTF-8");
}
/**
* 对字符串按指定字符集进行解码转换.
* @param str
* @param charsetName 字符集名称
* @return
* @throws Exception
*/
public static String decode(String str,String charsetName) {
try {
if (str == null)
return null;
return new String(str.getBytes("ISO-8859-1"), charsetName);
// 注: 这里的UTF-8, 应视提交页面的编码而定, 若提交表单的页面是GBK编码的,
// 这里应当设置为GBK. 否则, 仍然无法正常转换成中文.
} catch (Exception ex) {
return str;
}
}
/**
* 将字符串按UTF-8进行编码.
* @param str
* @return
*/
public static String encode(String str) {
return encode(str,"UTF-8");
}
/**
* 将字符串按指定字符集进行编码.
* @param str
* @param charsetName
* @return
*/
public static String encode(String str,String charsetName) {
if (str == null) return null;
try {
return (URLEncoder.encode(str, charsetName));
}
catch (Exception ex) {
return str;
}
}
public static String expandStr(String str, int len, char ch, boolean fillOnLeft){
if(fillOnLeft){
return StringUtils.leftPad(str, len, ch);
}else{
return StringUtils.rightPad(str, len, ch);
}
}
/**
* 将byte数组转换成16进制字符串
* @param b
* @return
*/
public static String byte2hex(byte[] b){
StringBuffer hs=new StringBuffer();
String stmp="";
for (int n=0;n<b.length;n++){
stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length()==1)
hs.append("0").append(stmp);
else hs.append(stmp);
if (n<b.length-1) hs.append(":");
}
return hs.toString().toUpperCase();
}
/**
* 判断字符串是否为数字函数,正则表达式
*/
public static boolean isDigitalChar(String strNumber){
if(strNumber == null || strNumber.length() == 0) return false;
Pattern p = Pattern.compile("[^0-9]");
Matcher m = p.matcher(strNumber);
return !m.find();
}
/**
* 将16进制字符串获取的字节数组转换成二进制字节数组
* @param b
* @return
*/
public static byte[] hex2byte(byte[] b){
if ((b.length % 2) != 0)
throw new IllegalArgumentException("长度不是偶数");
byte[] b2 = new byte[b.length / 2];
for (int n = 0; n < b.length; n += 2) {
String item = new String(b, n, 2);
//两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个进制字节
b2[n / 2] = (byte) Integer.parseInt(item, 16);
}
return b2;
}
/**
* 将不存于目的集合中的对象从源集合中移除
* @param src 源集合
* @param dest 目的集合
* @return
*/
public static boolean retainAll(Collection src,Collection dest) {
boolean modified = false;
Iterator itr = src.iterator();
while (itr.hasNext()) {
if(dest.contains(itr.next())) {
itr.remove();
modified = true;
}
}
return modified;
}
public static boolean retain(Collection src,Collection dest) {
boolean modified = false;
Iterator itr = src.iterator();
while (itr.hasNext()) {
if(!dest.contains(itr.next())) {
itr.remove();
modified = true;
}
}
return modified;
}
/**
* 根据文件路径,输入流写文件
* @param filepath 文件路径如:D:/text.txt
* @param in
* @return
*/
public static boolean writeFile(String filepath,InputStream in){
try{
FileOutputStream fo=new FileOutputStream(filepath);
byte[] temp=new byte[1024*2];
while(in.read(temp)!=-1){
fo.write(temp);
}
fo.close();
in.close();
return true;
}catch(Exception e){
log.error("工具类中写文件异常(参数:filepath="+filepath+"):", e);
}
return false;
}
/**
* 获取随机四位的验证码
* @return
*/
public static String getValiCode(){
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i= 0 ; i<4; i++) {
sb.append(random.nextInt(10));
}
return sb.toString();
}
static String ssource = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
static char[] src = ssource.toCharArray();
/**
* 除字符串中的空格、回车、换行符、制表符
* @param str
* @return
*/
public static String replaceBlank(String str){
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(str);
String after = m.replaceAll("");
return after;
}
}xml工具类
java
/**
* xml工具类
* @author chenli
*
*/
public class XMLUtil {
private Document doc = null;
public XMLUtil(File file) throws DocumentException {
SAXReader saxReader = new SAXReader();
doc = saxReader.read(file);
}
public XMLUtil(String file) throws DocumentException,
UnsupportedEncodingException {
SAXReader saxReader = new SAXReader();
doc = saxReader.read(new ByteArrayInputStream(file.getBytes("utf-8")));
}
/**
*
* @param node
* @return
*/
public List<Map<String, String>> getListNode(String node){
return this.getListNode("list", node);
}
/**
* 获取xml节点值 如在 <SSO> <items> < item name='1' pwd='1'></ item > </items></SSO> 获取result值
* 则传firstNode值为: items, node的值为 item;返回 name=1 pwd=1 的map数组
*
* @param pro
* @return
*/
public List<Map<String, String>> getListNode(String firstNode, String node) {
if (node == null) {
return new ArrayList<Map<String, String>>();
}
List<Map<String, String>> mapArray = new ArrayList<Map<String, String>>();
Element element = doc.getRootElement();
if (firstNode != null) {
element = element.element(firstNode);
}
Iterator<Element> root = element.elementIterator(node);
while (root.hasNext()) {
Element ele = root.next();
List<DefaultAttribute> att = ele.attributes();
Map<String, String> map = new HashMap<String, String>();
for (DefaultAttribute a : att) {
map.put(a.getName(), a.getText());
}
mapArray.add(map);
}
return mapArray;
}
/**
* 解析webservice中的返回值
* @return
* @author chenli
* @data 2016-11-11
*/
public String getWebserviceResult(){
Element element = doc.getRootElement();
while(true){
List<Element> temps = element.elements();
if(temps.size()>0){
element = temps.get(0);
}else{
break;
}
}
return element.getText();
}
/**
* 获取xml节点值 如在 <SSO> <name>1</name><password>1</password></SSO> 获取result值
* 返回 name=1 password=1 的map
*
* @param pro
* @return
*/
public Map<String, String> getMapNode() {
Map<String, String> map = new HashMap<String, String>();
Element element = doc.getRootElement();
List<DefaultElement> att = element.elements();
for (DefaultElement ele : att) {
map.put(ele.getName(), ele.getText());
}
return map;
}
/**
* 获取xml节点值 如在 <SSO> < result >0</ result > < result1 >1</ result1 >
* </SSO> 获取result值 传的pro值为: result 加入不存在放回null
*
* @param pro
* @return
*/
public String getProperty(String pro) {
Element element = doc.getRootElement();
if (pro == null)
return null;
String result = element.elementText(pro);
return StringUtils.trimToNull(result);
}
/**
* 获取根节点的名字
* @return
*/
public String getRootName(){
Element element = doc.getRootElement();
return (element == null)? null:element.getName();
}
/**
* 创建XML 带有Elemenet属性
*
* 如:<?xml version="1.0" encoding="utf-8"?>
* <sso>
* <item att1="1" att2="2"></item>
* </sso>
* @param rootname 根Element名称
* @param itemName Elemenet名称
* @param list Elemenet属性列表
* @return
*/
public static String newAttrXML(String rootname,String itemName, List<Hashtable<String, String>> list){
Document doc=DocumentHelper.createDocument();
doc.setXMLEncoding("UTF-8");
Element root=doc.addElement(rootname);
for(int i=0;i<list.size();i++){
Hashtable<String, String> table=list.get(i);
Element itemEl=root.addElement(itemName);
Enumeration<String> keys=table.keys();
while(keys.hasMoreElements()){
String key=keys.nextElement();
itemEl.addAttribute(key, table.get(key));
}
}
return doc.asXML();
}
/**
* 创建XML 带返回值
*
* 如:<?xml version="1.0" encoding="utf-8"?> <sso> <returncode>0</returncode>
* <newsysid>2132132132132</newsysid> //other 中存放 other.put("newsysid",
* "2132132132132"); </sso>
*
* @param rootname
* 根Element名称
* @param other
* other.put("newsysid", "2132132132132");
* @return
*/
public static String newRecXML(String rootname,
Map<String, String> other) {
Document doc = DocumentHelper.createDocument();
doc.setXMLEncoding("UTF-8");
Element root = doc.addElement(rootname);
if (other != null) {
Set<Map.Entry<String, String>> er = other.entrySet();
for (Map.Entry<String, String> entry : er) {
root.addElement(entry.getKey()).addText(entry.getValue());
}
}
return doc.asXML();
}
/**
* 以默认的 rootname 创建xml
*
* @param other
* @return
*/
public static String newRecXML(Map<String, String> other) {
return XMLUtil.newRecXML("sso", other);
}
/**
* 创建XML 查询接口返回的XML 如:<?xml version="1.0" encoding="utf-8"?> <sso> <list>
* <item argid="" appid="" argname="" argfieldname="" argfieldvalue=""
* memo=""></item> </list> <returncode>0</returncode> <totalcount></totalcount>
* <totalpage></totalpage> <nowpage></nowpage> </sso>
*
* @param rootname
* 根Element名称
* @param listname
* list Element名称
* @param itemName
* list 中的Element名字 如:item
* @param item
* item的List集合,List中存放Hashtable对象
* @param otherElem
* 其他Element
* @return
*/
public static String newListXML(String rootname, String listname,
String itemName, List<Hashtable<String, String>> item,
Hashtable<String, String> otherElem) {
Document doc = DocumentHelper.createDocument();
doc.setXMLEncoding("UTF-8");
Element root = doc.addElement(rootname);
Element list = root.addElement(listname);
for (int i = 0; i < item.size(); i++) {
Element itemname = list.addElement(itemName);
Hashtable<String, String> itemTab = item.get(i);
Enumeration<String> er = itemTab.keys();
while (er.hasMoreElements()) {
String key = er.nextElement();
itemname.addAttribute(key, itemTab.get(key));
}
}
Enumeration<String> erout = otherElem.keys();
while (erout.hasMoreElements()) {
String key = erout.nextElement();
root.addElement(key).addText(otherElem.get(key));
}
return doc.asXML();
}
/**
* 创建XML 查询接口返回的XML 如:
* @param rootname 根Element名称
* @param map 跟下面的子节点
* @return
* @author chenli
* @data 2016-11-1
*/
public static String newListXML(String rootname, Map<String,Object> map) {
Document doc = DocumentHelper.createDocument();
doc.setXMLEncoding("UTF-8");
Element root = doc.addElement(rootname);
String key;
Set<Map.Entry<String,Object>> set = map.entrySet();
for (Map.Entry<String, Object> entry : set) {
key = entry.getKey();
if(StringUtils.isBlank(key)){
continue;
}
add(root, key, entry.getValue());
}
return doc.asXML();
}
/**
* 以默认 rootname=sso listname=list item=item 创建查询xml
*
* @param item
* @param otherElem
* @return
*/
public static String newListXML(List<Hashtable<String, String>> item,
Hashtable<String, String> otherElem) {
return XMLUtil.newListXML("sso", "list", "item", item, otherElem);
}
/**
* 在节点上添加元素
* @param ele 节点
* @param key 新节点名称
* @param value 节点值
* @author chenli
* @data 2016-11-1
*/
private static void add(Element ele, String key, Object value){
if(StringUtils.isBlank(key)){
return;
}
if(value == null){
ele.addElement(key).addText("");
}
if(value instanceof List){
List v = (List)value;
add(ele, key, v);
}else if(value instanceof Map){
Map<String,Object> v = (Map<String,Object>)value;
add(ele, key, v);
}else if(value instanceof UserOrganize){
UserOrganize v = (UserOrganize)value;
add(ele, key, v);
}else if(value instanceof Integer){
Integer v = (Integer)value;
add(ele, key, v);
}else if(value instanceof String){
String v = (String)value;
add(ele, key, v);
}else if(value instanceof Long){
Long v = (Long)value;
add(ele, key, v);
}else{
if(null != value){
String v = value.toString();
add(ele, key, v);
}
}
}
/**
* 在节点上添加元素
* @param ele 节点
* @param key 新节点名称
* @param value 节点值
* @author chenli
* @data 2016-11-1
*/
private static void add(Element ele, String key, String value){
ele.addElement(key).addText(value+"");
}
/**
* 在节点上添加元素
* @param ele 节点
* @param key 新节点名称
* @param value 节点值
* @author chenli
* @data 2016-11-1
*/
private static void add(Element ele, String key, Integer value){
ele.addElement(key).addText(value+"");
}
/**
* 在节点上添加元素
* @param ele 节点
* @param key 新节点名称
* @param value 节点值
* @author chenli
* @data 2016-11-1
*/
private static void add(Element ele, String key, Long value){
ele.addElement(key).addText(value+"");
}
/**
* 在节点上添加元素
* @param ele 节点
* @param key 新节点名称
* @param value 节点值
* @author chenli
* @data 2016-11-1
*/
private static void add(Element ele, String key, List value){
String p_node;
String c_node;
if(key.endsWith("s")){
p_node = key;
c_node = key.substring(0, key.length()-1);
}else{
p_node = key+"s";
c_node = key;
}
Element child = ele.addElement(p_node);
for (Object object : value) {
add(child, c_node, object);
}
}
/**
* 在节点上添加元素
* @param ele 节点
* @param key 新节点名称
* @param value 节点值
* @author chenli
* @data 2016-11-1
*/
private static void add(Element ele, String key, Map<String,Object> value){
String k;
Object v;
Set<Map.Entry<String,Object>> set = value.entrySet();
Element c_ele = ele.addElement(key);
for (Map.Entry<String, Object> entry : set) {
k = entry.getKey();
v = entry.getValue();
if(key == null){
continue;
}
add(c_ele, k, v);
}
}
/**
* 在节点上添加元素
* @param ele 节点
* @param key 新节点名称
* @param value 节点值
* @author chenli
* @data 2016-11-1
*/
private static void add(Element ele, String key, UserOrganize value){
UserOrganize userorg = (UserOrganize)value;
Element userorgEle = ele.addElement("userorg");
add(userorgEle, "userid", userorg.getUserid());
add(userorgEle, "orgid", userorg.getOrgid());
add(userorgEle, "jobids", userorg.getJobids());
add(userorgEle, "positionids", userorg.getPositionids());
add(userorgEle, "orderby", userorg.getOrderby());
}
public static void main(String[] args) throws Exception {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("test", "测试");
Map<String, Object> table = new HashMap<String, Object>();
table.put("aa", "11");
table.put("bb", 22);
List<UserOrganize> l = new ArrayList<UserOrganize>();
UserOrganize userorg = new UserOrganize();
userorg.setUserid(12);
userorg.setOrgid(21);
userorg.setOrderby(21L);
userorg.setJobids("1,231");
l.add(userorg);
// table.put("userorg", l);
map.put("item", table);
Integer i = null;
StringBuffer sb = new StringBuffer();
System.out.println(sb.toString());
list.add(table);
// System.out.println(XMLUtil.newRecXML(table));
// String t = XMLUtil.newListXML("list", "items", "item", list, table);
String t2 = XMLUtil.newListXML("sso", map);
System.out.println(t2);
// XMLUtil util = new XMLUtil(t);
// System.out.println(util.getMapNode());
String a = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body><ns1:synchronizeOrgResponse soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"http://service.api.commnetsoft.com\"><synchronizeOrgReturn xsi:type=\"soapenc:string\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">{"result":"1001","errmsg":"业务系统未被允许同步"}</synchronizeOrgReturn></ns1:synchronizeOrgResponse></soapenv:Body></soapenv:Envelope>";
XMLUtil util = new XMLUtil(a);
System.out.println("输出:"+util.getWebserviceResult());;
int start = a.indexOf("<out>");
int end = a.indexOf("</out>");
if(end>start+5){
a = a.substring(start+5, end);
}
String cdata = "<![CDATA[";
if(a.startsWith(cdata)){
a = a.substring(cdata.length(), a.length()-3);
}else{
a = StrHelper.xmlDeescape(a);
}
System.out.println(a);
System.out.println(StrHelper.xmlEscape("<?xml version=\"1.0\" encoding=\"UTF-8\"?><SSO><result>9900</result><errmsg>接入代码不存在!</errmsg></SSO>",true));
// System.out.println(xml.getProperty(null));
// List<Map<String, String>> mapArray = xml.getListNode("item");
// for (Map<String, String> map : mapArray) {
// System.out.println(map.get("k"));
// }
// String a = "<extenduserxml> <item id=\"1\" name=\"2\" value=\"3\" memo=\"4\"></item><item id=\"11\" name=\"22\" value=\"33\" memo=\"44\"></item></extenduserxml>";
// XMLUtil xml = new XMLUtil(a);
// System.out.println(xml.getProperty(null));
// List<Map<String, String>> mapArray = xml.getListNode(null, "item");
// for (Map<String, String> map : mapArray) {
// System.out.println(map.get("id"));
// }
}
}Zip工具类
java
/**
* 功能: 1 、实现把指定文件夹下的所有文件压缩为指定文件夹下指定 zip 文件 2 、实现把指定文件夹下的 zip 文件解压到指定目录下
*
* @author
*
*/
public class ZipUtils {
private static final Logger logger = LoggerFactory.getLogger(ZipUtils.class);
/**
* 功能:把 sourceDir 目录下的所有文件进行 zip 格式的压缩,保存为指定 zip 文件 create date:2009- 6- 9
* author:Administrator
*
* @param sourceDir
* E:\\ 我的备份
* @param zipFile
* 格式: E:\\stu \\zipFile.zip 注意:加入 zipFile 我们传入的字符串值是
* : "E:\\stu \\" 或者 "E:\\stu "
* 如果 E 盘已经存在 stu 这个文件夹的话,那么就会出现 java.io.FileNotFoundException: E:\stu
* ( 拒绝访问。 ) 这个异常,所以要注意正确传参调用本函数哦
*
*/
public static void zip(String sourceDir, String zipFile) {
OutputStream os;
try {
os = new FileOutputStream(zipFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
ZipOutputStream zos = new ZipOutputStream(bos);
File file = new File(sourceDir);
String basePath = null ;
if (file.isDirectory()) {
basePath = file.getPath();
} else {
basePath = file.getParent();
}
zipFile (file, basePath, zos);
zos.closeEntry();
zos.close();
} catch (Exception e) {
}
}
/**
*
* create date:2009- 6- 9 author:Administrator
*
* @param source
* @param basePath
* @param zos
* @throws IOException
*/
private static void zipFile(File source, String basePath,
ZipOutputStream zos) {
File[] files = new File[0];
if (source.isDirectory()) {
files = source.listFiles();
} else {
files = new File[1];
files[0] = source;
}
String pathName;
byte [] buf = new byte [1024];
int length = 0;
try {
for (File file : files) {
if (file.isDirectory()) {
pathName = file.getPath().substring(basePath.length() + 1)
+ "/" ;
zos.putNextEntry( new ZipEntry(pathName));
zipFile (file, basePath, zos);
} else {
pathName = file.getPath().substring(basePath.length() + 1);
InputStream is = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
zos.putNextEntry( new ZipEntry(pathName));
while ((length = bis.read(buf)) > 0) {
zos.write(buf, 0, length);
}
is.close();
}
}
} catch (Exception e) {
logger.error("zip文件处理失败",e);
}
}
/**
* 解压 zip 文件,注意不能解压 rar 文件哦,只能解压 zip 文件 解压 rar 文件 会出现 java.io.IOException: Negative
* seek offset 异常 create date:2009- 6- 9 author:Administrator
*
* @param zipfile
* zip 文件,注意要是正宗的 zip 文件哦,不能是把 rar 的直接改为 zip 这样会出现 java.io.IOException:
* Negative seek offset 异常
* @param destDir
* @throws IOException
*/
public static void unZip(String zipfile, String destDir) {
destDir = destDir.endsWith("\\") ? destDir : destDir + "\\" ;
// System.out.println(zipfile);
// System.out.println(destDir);
byte b[] = new byte [1024];
int length;
ZipFile zipFile = null;
OutputStream outputStream = null;
InputStream inputStream = null;
File loadFile = null;
try {
zipFile = new ZipFile( new File(zipfile));
Enumeration enumeration = zipFile.getEntries();
ZipEntry zipEntry = null ;
while (enumeration.hasMoreElements()) {
zipEntry = (ZipEntry) enumeration.nextElement();
loadFile = new File(destDir + zipEntry.getName());
if (zipEntry.isDirectory()) {
// 这段都可以不要,因为每次都貌似从最底层开始遍历的
loadFile.mkdirs();
} else {
if (!loadFile.getParentFile().exists())
loadFile.getParentFile().mkdirs();
outputStream = new FileOutputStream(loadFile);
inputStream = zipFile.getInputStream(zipEntry);
while ((length = inputStream.read(b)) > 0)
outputStream.write(b, 0, length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
zipFile.close();
logger.info("文件解压成功.");
} catch (IOException e) {
logger.error("文件解压失败.");
}finally{
try{
//关闭流
outputStream.close();
inputStream.close();
zipFile.close();
}catch(IOException e) {
logger.error("zip解压缩文件关闭文件流失败",e);
}
}
}
public String zip(List<File> files, String zipFile){
OutputStream os;
byte [] buf = new byte [1024];
int length = 0;
try {
os = new FileOutputStream(zipFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
ZipOutputStream zos = new ZipOutputStream(bos);
zos.setEncoding("GBK");
for (File f : files) {
InputStream is = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(is);
zos.putNextEntry( new ZipEntry(f.getName()));
while ((length = bis.read(buf)) > 0) {
zos.write(buf, 0, length);
}
is.close();
}
zos.closeEntry();
zos.close();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
public String zip(Map<File,String> files, String zipFile){
OutputStream os;
byte [] buf = new byte [1024];
int length = 0;
try {
os = new FileOutputStream(zipFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
ZipOutputStream zos = new ZipOutputStream(bos);
zos.setEncoding("GBK");
Set<Map.Entry<File, String>> set = files.entrySet();
for (Map.Entry<File, String> en : set) {
InputStream is = new FileInputStream(en.getKey());
BufferedInputStream bis = new BufferedInputStream(is);
zos.putNextEntry( new ZipEntry(en.getValue()));
while ((length = bis.read(buf)) > 0) {
zos.write(buf, 0, length);
}
is.close();
}
zos.closeEntry();
zos.close();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
List<File> files = new ArrayList<File>();
files.add(new File("G:\\文档\\jquery-easyui-EDT-1.4-build1\\我的CSDN EasyUI专辑.txt"));
files.add(new File("G:\\文档\\jquery-easyui-EDT-1.4-build1\\中文版开发工具包说明1.txt"));
new ZipUtils().zip(files, "G:\\文档\\jquery-easyui-EDT-1.4-build1\\test.zip");
// ZipUtils.zip("G:\\文档\\jquery-easyui-EDT-1.4-build1\\jquery-easyui-1.4", "G:\\文档\\jquery-easyui-EDT-1.4-build1\\test.zip");
}
}数字工具类
java
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class NumberUtils extends org.apache.commons.lang3.math.NumberUtils {
/**
* 将一个十进制数转换成一个二进制位数组
* @author sunwen
* @since 2019/9/30
*/
public static Integer[] dec2Bit(Integer num){
if(num != null){
List<Integer> bits = new ArrayList<>();
for(int i=0; i<32; i++){
if((num & (1 << i)) != 0){
bits.add(i);
}
}
return bits.toArray(new Integer[0]);
}
return null;
}
/**
* 将一个二进制位数组转换成一个十进制数
* @author sunwen
* @since 2019/9/30
*/
public static Integer bit2dec(Integer... bits){
int dec = 0;
if(bits != null && bits.length > 0){
for(Integer i : bits){
dec |= (1 << i);
}
}
return dec;
}
/**
* 将一个二进制位数组转换成一个十进制数
* @author sunwen
* @since 2019/9/30
*/
public static Integer bit2dec(Collection<Integer> bits){
int dec = 0;
if(bits != null && bits.size() > 0){
for(Integer i : bits){
dec |= (1 << i);
}
}
return dec;
}
/**
* 转换null为0
* @author sunwen
* @since 2019/11/9
*/
public static Integer defaultInt(Integer i){
return defaultInt(i, 0);
}
/**
* 转换null为默认值
* @author sunwen
* @since 2019/11/9
*/
public static Integer defaultInt(Integer i, int defaultValue){
return i == null ? defaultValue : i;
}
/**
* 数字转换成中文数字
* @author sunwen
* @since 2020/6/3
*/
public static String toChinese(int number) {
String[] s1 = { "〇", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
String[] s2 = { "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千" };
StringBuilder result = new StringBuilder();
String str = String.valueOf(number);
int n = str.length();
boolean zero = false;
for (int i = 0; i < n; i++) {
int num = str.charAt(i) - '0';
String numStr = s1[num];
if (i != n - 1) {
String unit = s2[n - 2 - i];
if(numStr.equals("〇")){
zero = true;
}else{
if(zero){
result.append("〇");
}
zero = false;
if(i == 0 && numStr.equals("一") && unit.equals("十")){//第一位如果是1且后面单位是十,忽略前面的1
result.append(unit);
}else{
result.append(numStr).append(unit);
}
}
} else if(!numStr.equals("〇") || n == 1){//最后一位不是0
if(zero){
result.append("〇");
}
result.append(numStr);
}
}
return result.toString();
}
}数据签名工具类
java
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
/**
* 数据签名工具类
* @author sunwen
* @since 2020/4/1
*/
public class SignUtils {
public static final String DEFAULT_KEY = "dev2020@commnetsoft.com";
/**
* 生成签名
* @author sunwen
* @since 2020/4/1
*/
public static String generate(String key, String data){
return DigestUtils.md5Hex(data + StringUtils.defaultString(key));
}
/**
* 生成签名
* @author sunwen
* @since 2020/4/1
*/
public static String generate(String key, String data, Charset charsets){
if(charsets == null){
return generate(key, data);
}else{
String str = data + StringUtils.defaultString(key);
return DigestUtils.md5Hex(str.getBytes(charsets));
}
}
/**
* 生成签名
* @author sunwen
* @since 2020/4/1
*/
public static String generate(String key, InputStream data) throws IOException {
return generate(key, data, StandardCharsets.UTF_8);
}
/**
* 生成签名
* @author sunwen
* @since 2020/4/1
*/
public static String generate(String key, InputStream data, Charset charsets) throws IOException {
MessageDigest digest = DigestUtils.getMd5Digest();
//2020-9-28对签名算法修改.顺序由data+key调整为key+data
//key
digest.update(key.getBytes(charsets));
//data
byte[] buffer = new byte[1024];
for(int read = data.read(buffer, 0, 1024); read > -1; read = data.read(buffer, 0, 1024)) {
digest.update(buffer, 0, read);
}
return Hex.encodeHexString(digest.digest());
}
/**
* 生成签名
* @author sunwen
* @since 2020/4/1
*/
public static String generate(String key, byte[] data, Charset charsets) throws IOException {
MessageDigest digest = DigestUtils.getMd5Digest();
digest.update(data);
digest.update(key.getBytes(charsets));
return Hex.encodeHexString(digest.digest());
}
}简单类型工具类
java
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
/**
* 参考 org.apache.ibatis.type.SimpleTypeRegistry
*/
public class SimpleTypeUtil {
public static final String[] JAVA8_DATE_TIME = {
"java.time.Instant",
"java.time.LocalDateTime",
"java.time.LocalDate",
"java.time.LocalTime",
"java.time.OffsetDateTime",
"java.time.OffsetTime",
"java.time.ZonedDateTime",
"java.time.Year",
"java.time.Month",
"java.time.YearMonth"
};
private static final Set<Class<?>> SIMPLE_TYPE_SET = new HashSet<Class<?>>();
static {
SIMPLE_TYPE_SET.add(byte[].class);
SIMPLE_TYPE_SET.add(String.class);
SIMPLE_TYPE_SET.add(Byte.class);
SIMPLE_TYPE_SET.add(Short.class);
SIMPLE_TYPE_SET.add(Character.class);
SIMPLE_TYPE_SET.add(Integer.class);
SIMPLE_TYPE_SET.add(Long.class);
SIMPLE_TYPE_SET.add(Float.class);
SIMPLE_TYPE_SET.add(Double.class);
SIMPLE_TYPE_SET.add(Boolean.class);
SIMPLE_TYPE_SET.add(Date.class);
SIMPLE_TYPE_SET.add(Timestamp.class);
SIMPLE_TYPE_SET.add(Class.class);
SIMPLE_TYPE_SET.add(BigInteger.class);
SIMPLE_TYPE_SET.add(BigDecimal.class);
//反射方式设置 java8 中的日期类型
for (String time : JAVA8_DATE_TIME) {
registerSimpleTypeSilence(time);
}
//注册 8 种基本类型
registerPrimitiveTypes();
}
/**
* 注册新的类型
*
* @param clazz
*/
public static void registerSimpleType(Class<?> clazz){
SIMPLE_TYPE_SET.add(clazz);
}
/**
* 注册 8 种基本类型
*/
public static void registerPrimitiveTypes(){
registerSimpleType(boolean.class);
registerSimpleType(byte.class);
registerSimpleType(short.class);
registerSimpleType(int.class);
registerSimpleType(long.class);
registerSimpleType(char.class);
registerSimpleType(float.class);
registerSimpleType(double.class);
}
/**
* 注册新的类型,不存在时忽略
*
* @param clazz
*/
private static void registerSimpleTypeSilence(String clazz) {
try {
SIMPLE_TYPE_SET.add(Class.forName(clazz));
} catch (ClassNotFoundException e) {
//ignore
}
}
/*
* Tells us if the class passed in is a known common type
*
* @param clazz The class to check
* @return True if the class is known
*/
public static boolean isSimpleType(Class<?> clazz) {
return SIMPLE_TYPE_SET.contains(clazz);
}
}URI工具类
java
/**
* URI工具类
*
* @author Brack.zhu
* @date 2019/7/31
*/
public class UriUtil {
private UriUtil() {
}
/**
* 获取最后一个path<br/>
* http://127.0.0.1:8080/styles/font/fontawesome-webfont.woff?v=4.7.0<br/>
* 返回 fontawesome-webfont.woff
*
* @param uri
* @return 无返回null
*/
public static String lastPath(URI uri) {
String[] paths = getPaths(uri);
if (null != paths && paths.length > 0) {
return paths[paths.length - 1];
}
return null;
}
/**
* 获取URI path集合<br/>
* http://127.0.0.1:8080/styles/font/fontawesome-webfont.woff?v=4.7.0<br/>
* 返回 [styles,font,fontawesome-webfont.woff]
*
* @param uri
* @return 无返回null
*/
public static String[] getPaths(URI uri) {
Objects.requireNonNull(uri);
String path = uri.getPath();
if (StringUtils.isNotEmpty(path)) {
return path.split("/");
}
return null;
}
/**
* URI路径提取文件扩展名
* @param path 路径地址(如:"/products/index.html")
* @return 文件扩展名 (如:"html")
*/
@Nullable
public static String getFileExtension(String path) {
int end = path.indexOf('?');
int fragmentIndex = path.indexOf('#');
if (fragmentIndex != -1 && (end == -1 || fragmentIndex < end)) {
end = fragmentIndex;
}
if (end == -1) {
end = path.length();
}
int begin = path.lastIndexOf('/', end) + 1;
int paramIndex = path.indexOf(';', begin);
end = (paramIndex != -1 && paramIndex < end ? paramIndex : end);
int extIndex = path.lastIndexOf('.', end);
if (extIndex != -1 && extIndex > begin) {
return path.substring(extIndex + 1, end);
}
return null;
}
/**
* Get the query of an URI.
*
* @param uri a string regarded an URI
* @return the query string; <code>null</code> if empty or undefined
*/
public static String getQuery(String uri) {
if (uri == null || uri.length() == 0) { return null; }
// consider of net_path
int at = uri.indexOf("//");
int from = uri.indexOf(
"/",
at >= 0 ? (uri.lastIndexOf("/", at - 1) >= 0 ? 0 : at + 2) : 0
);
// the authority part of URI ignored
int to = uri.length();
// reuse the at and from variables to consider the query
at = uri.indexOf("?", from);
if (at >= 0) {
from = at + 1;
} else {
return null;
}
// check the fragment
if (uri.lastIndexOf("#") > from) {
to = uri.lastIndexOf("#");
}
// get the path and query.
return (from < 0 || from == to) ? null : uri.substring(from, to);
}
/**
* 获取路径中的指定参数值
* @author wuzm
* Date 2020/1/9 21:08
*/
public static String getParam(String uri,String paramName){
if(StringUtils.isBlank(paramName)){
return uri;
}
String params = getQuery(uri);
if(StringUtils.isBlank(params)){
return null;
}
String[] paramsArr = StringUtils.split(params,"&");
if(null == paramsArr && paramsArr.length == 0){
return null;
}
String prefix = paramName + "=";
for (String paramMap : paramsArr) {
if (!StringUtils.startsWith(paramMap, prefix)) {
continue;
}
return StringUtils.substringAfter(paramMap, prefix);
}
return null;
}
/**
* 截取掉路由后最后的斜杠
* @author wuzm
* Date 2020/3/31 14:18
*/
public static String subUriLastSlash(String uri){
if(StringUtils.isBlank(uri)){
return uri;
}
return StringUtils.endsWith(uri, "/") ? uri.substring(0,uri.length()-1) : uri;
}
}校验类
java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 对象字段合法性验证类
*/
public class ValidateUtils {
/**
* 验证是否是手机号码
* @param mobilePhone
* @return 验证成功 true,验证失败 false
*/
public static boolean valMobilePhone(String mobilePhone){
if(StringUtils.isBlank(mobilePhone) || StringUtils.isNumeric(mobilePhone) == false || mobilePhone.length()!=11){
return false;
}
/*移动号段16个 134, 135, 136, 137, 138, 139, 150, 151, 152,157, 158, 159, 187, 188, 182, 183,178,184,147,1705,198,148,1440 */
/*联通号段7个 130, 131, 132, 155, 156, 185, 186,176,145,1709,166,146 */
/*电信号段4个 133, 153, 180, 189, 181,177,1700,1701,1702,173,199,149,141 */
//String check = "^0{0,1}(13[0-9]|14[1456789]|15[0-3]|15[5-9]|16[2567]|18[0-9]|17[0-9]|19[189])[0-9]{8}$";
//考虑到运营商不断对外开放新号段,不对号码格式做过多的限制(如需精确限制,请模块内部进行自我完善)
String check = "^0{0,1}(1[3-9][0-9])[0-9]{8}$";
Pattern regex = Pattern.compile(check);
Matcher matcher = regex.matcher(mobilePhone);
boolean isMatched = matcher.matches();
return isMatched;
}
/**
* 验证是否是<code>email</code>
* @param email
* @return 验证成功 true,验证失败 false
*/
public static boolean valEmail(String email){
if(StringUtils.isBlank(email)){
return false;
}
String check = "^[-_a-z0-9A-Z.]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$|^[.-_a-z0-9A-Z]+@[a-z0-9A-Z]+$";
Pattern regex = Pattern.compile(check);
Matcher matcher = regex.matcher(email);
boolean isMatched = matcher.matches();
return isMatched;
}
/**
* 本地校验号码
* @param idcard
* @return
*/
public static boolean valIdcard(String idcard) {
if(idcard == null)
return false;
//假如位数为15位,且都为数字则返回true
if (idcard.length() == 15 && StringUtils.isNumeric(idcard)) {
return true;
}
if (idcard.length() != 18) {
return false;
}
//获取最后一位校验码 进行验证
char verify = idcard.charAt(17);
//前17位都不为数字返回false
idcard = idcard.substring(0, 17);
if(!StringUtils.isNumeric(idcard)){
return false;
}
if (verify == getVerify(idcard)) {
return true;
}
return false;
}
/**
* 计算最后一位校验码
* @param eighteen
* @return
*/
private static final int[] wi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 };
private static final char[] vi = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2' };
private static char getVerify(String eighteen) {
int[] ai = new int[18];
int remain = 0;
if (eighteen.length() == 18) {
eighteen = eighteen.substring(0, 17);
}
if (eighteen.length() == 17) {
int sum = 0;
for (int i = 0; i < 17; i++) {
char k = eighteen.charAt(i);
ai[i] = Character.getNumericValue(k);
}
for (int i = 0; i < 17; i++) {
sum += wi[i] * ai[i];
}
remain = sum % 11;
}
return vi[remain];
}
}