Skip to content
标签
工具
字数
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&nbsp;RFC&nbsp;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['\''] = "&#039;".toCharArray(); // 单引号
        TEXT['"'] = "&#34;".toCharArray(); // 单引号
        TEXT['&'] = "&#38;".toCharArray(); // &符
        TEXT['<'] = "&#60;".toCharArray(); // 小于号
        TEXT['>'] = "&#62;".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, "&amp;", result);
        result = regexReplace(P_QUOTE, "&quot;", result);
        result = regexReplace(P_LEFT_ARROW, "&lt;", result);
        result = regexReplace(P_RIGHT_ARROW, "&gt;", 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, "&lt;$1", s);
            s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", 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); // (<|$)
                // 不替换双引号为&quot;,防止json格式无效 regexReplace(P_QUOTE, "&quot;", 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 : "&amp;" + 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&nbsp;RFC&nbsp;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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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节点值 如在 &lt;SSO&gt; &lt;items&gt; &lt; item name='1' pwd='1'&gt;&lt;/ item &gt; &lt;/items&gt;&lt;/SSO&gt; 获取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节点值 如在 &lt;SSO&gt; &lt;name&gt;1&lt;/name&gt;&lt;password&gt;1&lt;/password&gt;&lt;/SSO&gt; 获取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节点值 如在 &lt;SSO&gt; &lt; result &gt;0&lt;/ result &gt; &lt; result1 &gt;1&lt;/ result1 &gt;
	 * &lt;/SSO&gt; 获取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属性
	 * 
	 * 如:&lt;?xml version="1.0" encoding="utf-8"?&gt;
	 *	&lt;sso&gt;
	 *		&lt;item att1="1" att2="2"&gt;&lt;/item&gt;
	 *	&lt;/sso&gt;
	 * @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 带返回值
	 * 
	 * 如:&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;sso&gt; &lt;returncode&gt;0&lt;/returncode&gt;
	 * &lt;newsysid&gt;2132132132132&lt;/newsysid&gt; //other 中存放 other.put("newsysid",
	 * "2132132132132"); &lt;/sso&gt;
	 * 
	 * @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 如:&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;sso&gt; &lt;list&gt;
	 * &lt;item argid="" appid="" argname="" argfieldname="" argfieldvalue=""
	 * memo=""&gt;&lt;/item&gt; &lt;/list&gt; &lt;returncode&gt;0&lt;/returncode&gt; &lt;totalcount&gt;&lt;/totalcount&gt;
	 * &lt;totalpage&gt;&lt;/totalpage&gt; &lt;nowpage&gt;&lt;/nowpage&gt; &lt;/sso&gt;
	 * 
	 * @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/\">{&quot;result&quot;:&quot;1001&quot;,&quot;errmsg&quot;:&quot;&#x4E1A;&#x52A1;&#x7CFB;&#x7EDF;&#x672A;&#x88AB;&#x5141;&#x8BB8;&#x540C;&#x6B65;&quot;}</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];
    }

}