正在显示
37 个修改的文件
包含
4292 行增加
和
0 行删除
lh-common/lh-common-util/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 5 | + <modelVersion>4.0.0</modelVersion> | ||
| 6 | + <parent> | ||
| 7 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 8 | + <artifactId>lh-common</artifactId> | ||
| 9 | + <version>1.0.0</version> | ||
| 10 | + </parent> | ||
| 11 | + | ||
| 12 | + <artifactId>lh-common-util</artifactId> | ||
| 13 | + <description>核心工具</description> | ||
| 14 | + | ||
| 15 | + <properties> | ||
| 16 | + <maven.compiler.source>8</maven.compiler.source> | ||
| 17 | + <maven.compiler.target>8</maven.compiler.target> | ||
| 18 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| 19 | + </properties> | ||
| 20 | + | ||
| 21 | + <dependencies> | ||
| 22 | + <dependency> | ||
| 23 | + <groupId>jakarta.validation</groupId> | ||
| 24 | + <artifactId>jakarta.validation-api</artifactId> | ||
| 25 | + </dependency> | ||
| 26 | + <!-- 文件上传工具类 --> | ||
| 27 | + <dependency> | ||
| 28 | + <groupId>commons-fileupload</groupId> | ||
| 29 | + <artifactId>commons-fileupload</artifactId> | ||
| 30 | + </dependency> | ||
| 31 | + <!--常用工具类 --> | ||
| 32 | + <dependency> | ||
| 33 | + <groupId>org.apache.commons</groupId> | ||
| 34 | + <artifactId>commons-lang3</artifactId> | ||
| 35 | + </dependency> | ||
| 36 | + | ||
| 37 | + <dependency> | ||
| 38 | + <groupId>com.google.code.gson</groupId> | ||
| 39 | + <artifactId>gson</artifactId> | ||
| 40 | + </dependency> | ||
| 41 | + | ||
| 42 | + <dependency> | ||
| 43 | + <groupId>cn.hutool</groupId> | ||
| 44 | + <artifactId>hutool-all</artifactId> | ||
| 45 | + </dependency> | ||
| 46 | + | ||
| 47 | + <!-- 阿里JSON解析器 --> | ||
| 48 | + <dependency> | ||
| 49 | + <groupId>com.alibaba</groupId> | ||
| 50 | + <artifactId>fastjson</artifactId> | ||
| 51 | + </dependency> | ||
| 52 | + </dependencies> | ||
| 53 | +</project> |
| 1 | +package com.zhonglai.luhui.util; | ||
| 2 | + | ||
| 3 | +import java.math.BigDecimal; | ||
| 4 | +import java.math.RoundingMode; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 精确的浮点数运算 | ||
| 8 | + * | ||
| 9 | + * @author ruoyi | ||
| 10 | + */ | ||
| 11 | +public class Arith | ||
| 12 | +{ | ||
| 13 | + | ||
| 14 | + /** 默认除法运算精度 */ | ||
| 15 | + private static final int DEF_DIV_SCALE = 10; | ||
| 16 | + | ||
| 17 | + /** 这个类不能实例化 */ | ||
| 18 | + private Arith() | ||
| 19 | + { | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 提供精确的加法运算。 | ||
| 24 | + * @param v1 被加数 | ||
| 25 | + * @param v2 加数 | ||
| 26 | + * @return 两个参数的和 | ||
| 27 | + */ | ||
| 28 | + public static double add(double v1, double v2) | ||
| 29 | + { | ||
| 30 | + BigDecimal b1 = new BigDecimal(Double.toString(v1)); | ||
| 31 | + BigDecimal b2 = new BigDecimal(Double.toString(v2)); | ||
| 32 | + return b1.add(b2).doubleValue(); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 提供精确的减法运算。 | ||
| 37 | + * @param v1 被减数 | ||
| 38 | + * @param v2 减数 | ||
| 39 | + * @return 两个参数的差 | ||
| 40 | + */ | ||
| 41 | + public static double sub(double v1, double v2) | ||
| 42 | + { | ||
| 43 | + BigDecimal b1 = new BigDecimal(Double.toString(v1)); | ||
| 44 | + BigDecimal b2 = new BigDecimal(Double.toString(v2)); | ||
| 45 | + return b1.subtract(b2).doubleValue(); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 提供精确的乘法运算。 | ||
| 50 | + * @param v1 被乘数 | ||
| 51 | + * @param v2 乘数 | ||
| 52 | + * @return 两个参数的积 | ||
| 53 | + */ | ||
| 54 | + public static double mul(double v1, double v2) | ||
| 55 | + { | ||
| 56 | + BigDecimal b1 = new BigDecimal(Double.toString(v1)); | ||
| 57 | + BigDecimal b2 = new BigDecimal(Double.toString(v2)); | ||
| 58 | + return b1.multiply(b2).doubleValue(); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 | ||
| 63 | + * 小数点以后10位,以后的数字四舍五入。 | ||
| 64 | + * @param v1 被除数 | ||
| 65 | + * @param v2 除数 | ||
| 66 | + * @return 两个参数的商 | ||
| 67 | + */ | ||
| 68 | + public static double div(double v1, double v2) | ||
| 69 | + { | ||
| 70 | + return div(v1, v2, DEF_DIV_SCALE); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 | ||
| 75 | + * 定精度,以后的数字四舍五入。 | ||
| 76 | + * @param v1 被除数 | ||
| 77 | + * @param v2 除数 | ||
| 78 | + * @param scale 表示表示需要精确到小数点以后几位。 | ||
| 79 | + * @return 两个参数的商 | ||
| 80 | + */ | ||
| 81 | + public static double div(double v1, double v2, int scale) | ||
| 82 | + { | ||
| 83 | + if (scale < 0) | ||
| 84 | + { | ||
| 85 | + throw new IllegalArgumentException( | ||
| 86 | + "The scale must be a positive integer or zero"); | ||
| 87 | + } | ||
| 88 | + BigDecimal b1 = new BigDecimal(Double.toString(v1)); | ||
| 89 | + BigDecimal b2 = new BigDecimal(Double.toString(v2)); | ||
| 90 | + if (b1.compareTo(BigDecimal.ZERO) == 0) | ||
| 91 | + { | ||
| 92 | + return BigDecimal.ZERO.doubleValue(); | ||
| 93 | + } | ||
| 94 | + return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + /** | ||
| 98 | + * 提供精确的小数位四舍五入处理。 | ||
| 99 | + * @param v 需要四舍五入的数字 | ||
| 100 | + * @param scale 小数点后保留几位 | ||
| 101 | + * @return 四舍五入后的结果 | ||
| 102 | + */ | ||
| 103 | + public static double round(double v, int scale) | ||
| 104 | + { | ||
| 105 | + if (scale < 0) | ||
| 106 | + { | ||
| 107 | + throw new IllegalArgumentException( | ||
| 108 | + "The scale must be a positive integer or zero"); | ||
| 109 | + } | ||
| 110 | + BigDecimal b = new BigDecimal(Double.toString(v)); | ||
| 111 | + BigDecimal one = BigDecimal.ONE; | ||
| 112 | + return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); | ||
| 113 | + } | ||
| 114 | +} |
| 1 | +package com.zhonglai.luhui.util; | ||
| 2 | + | ||
| 3 | +import java.util.Arrays; | ||
| 4 | + | ||
| 5 | +public class ByteUtil { | ||
| 6 | + /** | ||
| 7 | + * byte数组中取int数值,本方法适用于(低位在前,高位在后)的顺序,和和intToBytes()配套使用 | ||
| 8 | + * | ||
| 9 | + * @param src | ||
| 10 | + * byte数组 | ||
| 11 | + * @param offset | ||
| 12 | + * 从数组的第offset位开始 | ||
| 13 | + * @return int数值 | ||
| 14 | + */ | ||
| 15 | + public static long bytesToLongASC(byte[] src, int offset,int lenth) { | ||
| 16 | + int value = 0; | ||
| 17 | + for(int i=0;i<lenth;i++) | ||
| 18 | + { | ||
| 19 | + value = value | ((src[offset+i] & 0xFF)<<(8*i)); | ||
| 20 | + } | ||
| 21 | + return value; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 把16进制字符串转换成字节数组 | ||
| 26 | + * | ||
| 27 | + * @param hex | ||
| 28 | + * @return | ||
| 29 | + */ | ||
| 30 | + public static byte[] hexStringToByte(String hex) { | ||
| 31 | + int len = (hex.length() / 2); | ||
| 32 | + byte[] result = new byte[len]; | ||
| 33 | + char[] achar = hex.toCharArray(); | ||
| 34 | + for (int i = 0; i < len; i++) { | ||
| 35 | + int pos = i * 2; | ||
| 36 | + result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1])); | ||
| 37 | + } | ||
| 38 | + return result; | ||
| 39 | + } | ||
| 40 | + private static byte toByte(char c) { | ||
| 41 | + byte b = (byte) "0123456789ABCDEF".indexOf(c); | ||
| 42 | + return b; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * 把16进制字符串转换成字节数组 | ||
| 47 | + * | ||
| 48 | + * @param hex | ||
| 49 | + * @return | ||
| 50 | + */ | ||
| 51 | + public static String hexStringToSpace(String hex) { | ||
| 52 | + if (null == hex) { | ||
| 53 | + return null; | ||
| 54 | + } else { | ||
| 55 | + StringBuilder sb = new StringBuilder(hex.length() << 1); | ||
| 56 | + | ||
| 57 | + for(int i = 0; i < hex.length(); i+=2) { | ||
| 58 | + sb.append(hex.substring(i,i+2)).append(" "); | ||
| 59 | + } | ||
| 60 | + return sb.toString(); | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 把原数组加点目标数组后面 | ||
| 66 | + * @param dest 目标数组 | ||
| 67 | + * @param src 原数组 | ||
| 68 | + * @return | ||
| 69 | + */ | ||
| 70 | + public static byte[] addBytes(byte[] dest,byte[] src ) | ||
| 71 | + { | ||
| 72 | + int dl = dest.length; | ||
| 73 | + int sl = src.length; | ||
| 74 | + dest = Arrays.copyOf(dest, dl+sl);//数组扩容 | ||
| 75 | + System.arraycopy(src,0,dest,dl,src.length); | ||
| 76 | + return dest; | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 将int数值转换为占四个字节的byte数组,本方法适用于(高位在前,低位在后)的顺序。 和bytesToInt2()配套使用 | ||
| 81 | + */ | ||
| 82 | + public static byte[] intToBytesDESC(long value,int lenth) | ||
| 83 | + { | ||
| 84 | + byte[] src = new byte[lenth]; | ||
| 85 | + for(int i=0;i<lenth;i++) | ||
| 86 | + { | ||
| 87 | + src[i] = (byte) ((value>>(8*(lenth-i-1))) & 0xFF); | ||
| 88 | + } | ||
| 89 | + return src; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + /** | ||
| 93 | + * 将int数值转换为占四个字节的byte数组,本方法适用于(低位在前,高位在后)的顺序。 和bytesToInt()配套使用 | ||
| 94 | + * @param value | ||
| 95 | + * 要转换的int值 | ||
| 96 | + * @return byte数组 | ||
| 97 | + */ | ||
| 98 | + public static byte[] intToBytesASC( long value,int lenth) | ||
| 99 | + { | ||
| 100 | + byte[] src = new byte[lenth]; | ||
| 101 | + for(int i=lenth;i>0;i--) | ||
| 102 | + { | ||
| 103 | + src[i-1] = (byte) ((value>>(8*(i-1))) & 0xFF); | ||
| 104 | + } | ||
| 105 | + return src; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + public static void main(String[] args) { | ||
| 109 | + System.out.println(ByteUtil.toHexString( ByteUtil.intToBytesASC(2011239256,4))); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + /** | ||
| 113 | + * ip转化位4byte | ||
| 114 | + * @param ip | ||
| 115 | + * @return | ||
| 116 | + */ | ||
| 117 | + public static byte[] ipTo4Byte(String ip) | ||
| 118 | + { | ||
| 119 | + String[] ips = ip.split("."); | ||
| 120 | + return new byte[]{(byte) Integer.parseInt(ips[0]),(byte) Integer.parseInt(ips[1]),(byte) Integer.parseInt(ips[2]),(byte) Integer.parseInt(ips[3])}; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + /** | ||
| 124 | + * byte数组中取int数值,本方法适用于(低位在后,高位在前)的顺序。和intToBytes2()配套使用 | ||
| 125 | + */ | ||
| 126 | + public static long bytesToLongDESC(byte[] src, int offset,int lenth) { | ||
| 127 | + long value = 0; | ||
| 128 | + for(int i=lenth;i>0;i--) | ||
| 129 | + { | ||
| 130 | + value = value | ((src[offset+(lenth-i)] & 0xFF)<<(8*(i-1))); | ||
| 131 | + } | ||
| 132 | + return value; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + private static final char[] hex = "0123456789abcdef".toCharArray(); | ||
| 136 | + public static String toHexString(byte[] bytes) { | ||
| 137 | + if (null == bytes) { | ||
| 138 | + return null; | ||
| 139 | + } else { | ||
| 140 | + StringBuilder sb = new StringBuilder(bytes.length << 1); | ||
| 141 | + | ||
| 142 | + for(int i = 0; i < bytes.length; ++i) { | ||
| 143 | + sb.append(hex[(bytes[i] & 240) >> 4]).append(hex[bytes[i] & 15]); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + return sb.toString(); | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + /** | ||
| 151 | + * 计算CRC16/Modbus校验码 低位在前,高位在后 | ||
| 152 | + * | ||
| 153 | + * @param str 十六进制字符串 | ||
| 154 | + * @return | ||
| 155 | + */ | ||
| 156 | + public static String getCRC16(String str) { | ||
| 157 | + byte[] bytes = hexStringToByte(str); | ||
| 158 | + return getCRC16(bytes); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + /** | ||
| 162 | + * 计算CRC16/Modbus校验码 低位在前,高位在后 | ||
| 163 | + * | ||
| 164 | + * @return | ||
| 165 | + */ | ||
| 166 | + public static String getCRC16( byte[] bytes) { | ||
| 167 | + int CRC = 0x0000ffff; | ||
| 168 | + int POLYNOMIAL = 0x0000a001; | ||
| 169 | + | ||
| 170 | + int i, j; | ||
| 171 | + for (i = 0; i < bytes.length; i++) { | ||
| 172 | + CRC ^= ((int) bytes[i] & 0x000000ff); | ||
| 173 | + for (j = 0; j < 8; j++) { | ||
| 174 | + if ((CRC & 0x00000001) != 0) { | ||
| 175 | + CRC >>= 1; | ||
| 176 | + CRC ^= POLYNOMIAL; | ||
| 177 | + } else { | ||
| 178 | + CRC >>= 1; | ||
| 179 | + } | ||
| 180 | + } | ||
| 181 | + } | ||
| 182 | + String crc = Integer.toHexString(CRC); | ||
| 183 | + if (crc.length() == 2) { | ||
| 184 | + crc = "00" + crc; | ||
| 185 | + } else if (crc.length() == 3) { | ||
| 186 | + crc = "0" + crc; | ||
| 187 | + } | ||
| 188 | + crc = crc.substring(2, 4) + crc.substring(0, 2); | ||
| 189 | + return crc.toUpperCase(); | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + /** | ||
| 193 | + * 用于从一个 long 值中指定的起始位置和结束位置读取位数据。该方法使用位掩码操作来获取指定位范围内的数据。 | ||
| 194 | + * @param value | ||
| 195 | + * @param startPosition | ||
| 196 | + * @param endPosition | ||
| 197 | + * @return | ||
| 198 | + */ | ||
| 199 | + public static long readBits(long value, int startPosition, int endPosition) { | ||
| 200 | + long mask = (1L << (endPosition - startPosition + 1)) - 1; | ||
| 201 | + return (value >> startPosition) & mask; | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + /** | ||
| 205 | + * 用于简化给变量的不同位赋值的操作。该方法接收四个参数:value 是要被赋值的变量,bitValue 是要赋给指定位的值,startPosition 和 endPosition 是指定位的起始位置和结束位置。 | ||
| 206 | + * @param value | ||
| 207 | + * @param bitValue | ||
| 208 | + * @param startPosition | ||
| 209 | + * @param endPosition | ||
| 210 | + * @return | ||
| 211 | + */ | ||
| 212 | + public static int assignBits(int value, int bitValue, int startPosition, int endPosition) { | ||
| 213 | + int mask = ((1 << (endPosition - startPosition + 1)) - 1) << startPosition; | ||
| 214 | + value &= ~mask; | ||
| 215 | + value |= (bitValue << startPosition); | ||
| 216 | + return value; | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | +} |
| 1 | +package com.zhonglai.luhui.util; | ||
| 2 | + | ||
| 3 | +import org.apache.commons.lang3.StringUtils; | ||
| 4 | + | ||
| 5 | +import javax.crypto.Cipher; | ||
| 6 | +import javax.crypto.SecretKey; | ||
| 7 | +import javax.crypto.SecretKeyFactory; | ||
| 8 | +import javax.crypto.spec.DESKeySpec; | ||
| 9 | +import java.security.SecureRandom; | ||
| 10 | +import java.util.Random; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 采用MD5加密解密 | ||
| 14 | + * @author tfq | ||
| 15 | + * @datetime 2011-10-13 | ||
| 16 | + */ | ||
| 17 | +public class DESUtil { | ||
| 18 | + | ||
| 19 | + private static final String KEY = "kimwaynet";// 密钥 | ||
| 20 | + private final static String DES = "DES";// DES算法名称 | ||
| 21 | + | ||
| 22 | + //加密 | ||
| 23 | + private static byte[] encrypt(byte[] src, byte[] key) throws Exception { | ||
| 24 | + SecureRandom sr = new SecureRandom(); | ||
| 25 | + DESKeySpec dks = new DESKeySpec(key); | ||
| 26 | + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); | ||
| 27 | + SecretKey securekey = keyFactory.generateSecret(dks); | ||
| 28 | + Cipher cipher = Cipher.getInstance(DES); | ||
| 29 | + cipher.init(Cipher.ENCRYPT_MODE, securekey, sr); | ||
| 30 | + return cipher.doFinal(src); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + //解密 | ||
| 34 | + private static byte[] decrypt(byte[] src, byte[] key) throws Exception { | ||
| 35 | + SecureRandom sr = new SecureRandom(); | ||
| 36 | + DESKeySpec dks = new DESKeySpec(key); | ||
| 37 | + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); | ||
| 38 | + SecretKey securekey = keyFactory.generateSecret(dks); | ||
| 39 | + Cipher cipher = Cipher.getInstance(DES); | ||
| 40 | + cipher.init(Cipher.DECRYPT_MODE, securekey, sr); | ||
| 41 | + return cipher.doFinal(src); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + private static String byte2hex(byte[] b) { | ||
| 45 | + String hs = ""; | ||
| 46 | + String stmp = ""; | ||
| 47 | + for (int n = 0; n < b.length; n++) { | ||
| 48 | + stmp = (Integer.toHexString(b[n] & 0XFF)); | ||
| 49 | + if (stmp.length() == 1) | ||
| 50 | + hs = hs + "0" + stmp; | ||
| 51 | + else | ||
| 52 | + hs = hs + stmp; | ||
| 53 | + } | ||
| 54 | + return hs.toUpperCase(); | ||
| 55 | + | ||
| 56 | + } | ||
| 57 | + private static byte[] hex2byte(byte[] b) { | ||
| 58 | + if ((b.length % 2) != 0) | ||
| 59 | + throw new IllegalArgumentException("length not even"); | ||
| 60 | + byte[] b2 = new byte[b.length / 2]; | ||
| 61 | + for (int n = 0; n < b.length; n += 2) { | ||
| 62 | + String item = new String(b, n, 2); | ||
| 63 | + b2[n / 2] = (byte) Integer.parseInt(item, 16); | ||
| 64 | + } | ||
| 65 | + return b2; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + //解密 | ||
| 69 | + public static String decode(String src,String key) { | ||
| 70 | + if(StringUtils.isEmpty(key)) | ||
| 71 | + { | ||
| 72 | + key = KEY; | ||
| 73 | + } | ||
| 74 | + String decryptStr = ""; | ||
| 75 | + try { | ||
| 76 | + decryptStr = new String(decrypt(hex2byte(src.getBytes()),key.getBytes())); | ||
| 77 | + } catch (Exception ex) { | ||
| 78 | + ex.printStackTrace(); | ||
| 79 | + } | ||
| 80 | + return decryptStr; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + //加密 | ||
| 84 | + public static String encode(String src,String key){ | ||
| 85 | + if(StringUtils.isEmpty(key)) | ||
| 86 | + { | ||
| 87 | + key = KEY; | ||
| 88 | + } | ||
| 89 | + byte[] bytes = null; | ||
| 90 | + String encryptStr = ""; | ||
| 91 | + try { | ||
| 92 | + bytes = encrypt(src.getBytes(), key.getBytes()); | ||
| 93 | + } catch (Exception ex) { | ||
| 94 | + ex.printStackTrace(); | ||
| 95 | + } | ||
| 96 | + if (bytes != null) | ||
| 97 | + encryptStr = byte2hex(bytes); | ||
| 98 | + return encryptStr; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + public static String getDecodeMAC(String decryptStr){ | ||
| 102 | + String mac = ""; | ||
| 103 | + String[] strs = decryptStr.split(":"); | ||
| 104 | + if (strs.length == 5) { | ||
| 105 | + mac = strs[0]; | ||
| 106 | + } | ||
| 107 | + return mac; | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + /** | ||
| 111 | + * 生成指定长度的随机字符串 | ||
| 112 | + * @param args | ||
| 113 | + */ | ||
| 114 | + /** | ||
| 115 | + * 产生随机字符串 | ||
| 116 | + * */ | ||
| 117 | + private static Random randGen = null; | ||
| 118 | + private static char[] numbersAndLetters = null; | ||
| 119 | + | ||
| 120 | + public static final String randomString(int length) { | ||
| 121 | + if (length < 1) { | ||
| 122 | + return null; | ||
| 123 | + } | ||
| 124 | + if (randGen == null) { | ||
| 125 | + randGen = new Random(); | ||
| 126 | + numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" + | ||
| 127 | + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); | ||
| 128 | + //numbersAndLetters = ("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); | ||
| 129 | + } | ||
| 130 | + char [] randBuffer = new char[length]; | ||
| 131 | + for (int i=0; i<randBuffer.length; i++) { | ||
| 132 | + randBuffer[i] = numbersAndLetters[randGen.nextInt(71)]; | ||
| 133 | + //randBuffer[i] = numbersAndLetters[randGen.nextInt(35)]; | ||
| 134 | + } | ||
| 135 | + return new String(randBuffer); | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + // 测试主函数 | ||
| 139 | + public static void main(String args[]) { | ||
| 140 | +// String s = new String("F:/yu2le-service-log"); | ||
| 141 | +// System.out.println("原始:" + s); | ||
| 142 | +// s = encode(s,"LINUXYU2LE"); | ||
| 143 | +// System.out.println("加密的:" + s); | ||
| 144 | + System.out.println("解密的:" + decode("498CFDA0AA8A2E9A","kimwaynet")); | ||
| 145 | + | ||
| 146 | +// System.out.println(encode("13912927204","LS6GzB")); | ||
| 147 | + } | ||
| 148 | +} |
| 1 | +package com.zhonglai.luhui.util; | ||
| 2 | + | ||
| 3 | +import org.apache.commons.lang3.time.DateFormatUtils; | ||
| 4 | + | ||
| 5 | +import java.lang.management.ManagementFactory; | ||
| 6 | +import java.text.ParseException; | ||
| 7 | +import java.text.SimpleDateFormat; | ||
| 8 | +import java.time.*; | ||
| 9 | +import java.util.Date; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 时间工具类 | ||
| 13 | + * | ||
| 14 | + * @author ruoyi | ||
| 15 | + */ | ||
| 16 | +public class DateUtils extends org.apache.commons.lang3.time.DateUtils | ||
| 17 | +{ | ||
| 18 | + public static String YYYY = "yyyy"; | ||
| 19 | + | ||
| 20 | + public static String YYYY_MM = "yyyy-MM"; | ||
| 21 | + | ||
| 22 | + public static String YYYY_MM_DD = "yyyy-MM-dd"; | ||
| 23 | + | ||
| 24 | + public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; | ||
| 25 | + | ||
| 26 | + public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; | ||
| 27 | + | ||
| 28 | + private static String[] parsePatterns = { | ||
| 29 | + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", | ||
| 30 | + "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", | ||
| 31 | + "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 获取当前Date型日期 | ||
| 35 | + * | ||
| 36 | + * @return Date() 当前日期 | ||
| 37 | + */ | ||
| 38 | + public static Date getNowDate() | ||
| 39 | + { | ||
| 40 | + return new Date(); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * 获取当前日期, 默认格式为yyyy-MM-dd | ||
| 45 | + * | ||
| 46 | + * @return String | ||
| 47 | + */ | ||
| 48 | + public static String getDate() | ||
| 49 | + { | ||
| 50 | + return dateTimeNow(YYYY_MM_DD); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + public static final String getTime() | ||
| 54 | + { | ||
| 55 | + return dateTimeNow(YYYY_MM_DD_HH_MM_SS); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + public static final String dateTimeNow() | ||
| 59 | + { | ||
| 60 | + return dateTimeNow(YYYYMMDDHHMMSS); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + public static final String dateTimeNow(final String format) | ||
| 64 | + { | ||
| 65 | + return parseDateToStr(format, new Date()); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + public static final String dateTime(final Date date) | ||
| 69 | + { | ||
| 70 | + return parseDateToStr(YYYY_MM_DD, date); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + public static final String parseDateToStr(final String format, final Date date) | ||
| 74 | + { | ||
| 75 | + return new SimpleDateFormat(format).format(date); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + public static final Date dateTime(final String format, final String ts) | ||
| 79 | + { | ||
| 80 | + try | ||
| 81 | + { | ||
| 82 | + return new SimpleDateFormat(format).parse(ts); | ||
| 83 | + } | ||
| 84 | + catch (ParseException e) | ||
| 85 | + { | ||
| 86 | + throw new RuntimeException(e); | ||
| 87 | + } | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * 日期路径 即年/月/日 如2018/08/08 | ||
| 92 | + */ | ||
| 93 | + public static final String datePath() | ||
| 94 | + { | ||
| 95 | + Date now = new Date(); | ||
| 96 | + return DateFormatUtils.format(now, "yyyy/MM/dd"); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + /** | ||
| 100 | + * 日期路径 即年/月/日 如20180808 | ||
| 101 | + */ | ||
| 102 | + public static final String dateTime() | ||
| 103 | + { | ||
| 104 | + Date now = new Date(); | ||
| 105 | + return DateFormatUtils.format(now, "yyyyMMdd"); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + /** | ||
| 109 | + * 日期型字符串转化为日期 格式 | ||
| 110 | + */ | ||
| 111 | + public static Date parseDate(Object str) | ||
| 112 | + { | ||
| 113 | + if (str == null) | ||
| 114 | + { | ||
| 115 | + return null; | ||
| 116 | + } | ||
| 117 | + try | ||
| 118 | + { | ||
| 119 | + return parseDate(str.toString(), parsePatterns); | ||
| 120 | + } | ||
| 121 | + catch (ParseException e) | ||
| 122 | + { | ||
| 123 | + return null; | ||
| 124 | + } | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + /** | ||
| 128 | + * 获取服务器启动时间 | ||
| 129 | + */ | ||
| 130 | + public static Date getServerStartDate() | ||
| 131 | + { | ||
| 132 | + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); | ||
| 133 | + return new Date(time); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + /** | ||
| 137 | + * 计算相差天数 | ||
| 138 | + */ | ||
| 139 | + public static int differentDaysByMillisecond(Date date1, Date date2) | ||
| 140 | + { | ||
| 141 | + return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24))); | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + /** | ||
| 145 | + * 计算两个时间差 | ||
| 146 | + */ | ||
| 147 | + public static String getDatePoor(Date endDate, Date nowDate) | ||
| 148 | + { | ||
| 149 | + long nd = 1000 * 24 * 60 * 60; | ||
| 150 | + long nh = 1000 * 60 * 60; | ||
| 151 | + long nm = 1000 * 60; | ||
| 152 | + // long ns = 1000; | ||
| 153 | + // 获得两个时间的毫秒时间差异 | ||
| 154 | + long diff = endDate.getTime() - nowDate.getTime(); | ||
| 155 | + // 计算差多少天 | ||
| 156 | + long day = diff / nd; | ||
| 157 | + // 计算差多少小时 | ||
| 158 | + long hour = diff % nd / nh; | ||
| 159 | + // 计算差多少分钟 | ||
| 160 | + long min = diff % nd % nh / nm; | ||
| 161 | + // 计算差多少秒//输出结果 | ||
| 162 | + // long sec = diff % nd % nh % nm / ns; | ||
| 163 | + return day + "天" + hour + "小时" + min + "分钟"; | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + /** | ||
| 167 | + * 增加 LocalDateTime ==> Date | ||
| 168 | + */ | ||
| 169 | + public static Date toDate(LocalDateTime temporalAccessor) | ||
| 170 | + { | ||
| 171 | + ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault()); | ||
| 172 | + return Date.from(zdt.toInstant()); | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + /** | ||
| 176 | + * 增加 LocalDate ==> Date | ||
| 177 | + */ | ||
| 178 | + public static Date toDate(LocalDate temporalAccessor) | ||
| 179 | + { | ||
| 180 | + LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0)); | ||
| 181 | + ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault()); | ||
| 182 | + return Date.from(zdt.toInstant()); | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + public static Integer getNowTimeMilly() { | ||
| 186 | + String time = System.currentTimeMillis() / 1000L + ""; | ||
| 187 | + return Integer.parseInt(time); | ||
| 188 | + } | ||
| 189 | +} |
| 1 | +package com.zhonglai.luhui.util; | ||
| 2 | + | ||
| 3 | +import org.apache.commons.lang3.StringUtils; | ||
| 4 | +import org.apache.commons.lang3.exception.ExceptionUtils; | ||
| 5 | + | ||
| 6 | +import java.io.PrintWriter; | ||
| 7 | +import java.io.StringWriter; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 错误信息处理类。 | ||
| 11 | + * | ||
| 12 | + * @author ruoyi | ||
| 13 | + */ | ||
| 14 | +public class ExceptionUtil | ||
| 15 | +{ | ||
| 16 | + /** | ||
| 17 | + * 获取exception的详细错误信息。 | ||
| 18 | + */ | ||
| 19 | + public static String getExceptionMessage(Throwable e) | ||
| 20 | + { | ||
| 21 | + StringWriter sw = new StringWriter(); | ||
| 22 | + e.printStackTrace(new PrintWriter(sw, true)); | ||
| 23 | + return sw.toString(); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + public static String getRootErrorMessage(Exception e) | ||
| 27 | + { | ||
| 28 | + Throwable root = ExceptionUtils.getRootCause(e); | ||
| 29 | + root = (root == null ? e : root); | ||
| 30 | + if (root == null) | ||
| 31 | + { | ||
| 32 | + return ""; | ||
| 33 | + } | ||
| 34 | + String msg = root.getMessage(); | ||
| 35 | + if (msg == null) | ||
| 36 | + { | ||
| 37 | + return "null"; | ||
| 38 | + } | ||
| 39 | + return StringUtils.defaultString(msg); | ||
| 40 | + } | ||
| 41 | +} |
| 1 | +package com.zhonglai.luhui.util; | ||
| 2 | + | ||
| 3 | +import com.google.gson.FieldNamingPolicy; | ||
| 4 | +import com.google.gson.Gson; | ||
| 5 | +import com.google.gson.GsonBuilder; | ||
| 6 | + | ||
| 7 | +public class GsonConstructor { | ||
| 8 | + private static final Gson gson; | ||
| 9 | + | ||
| 10 | + public GsonConstructor() { | ||
| 11 | + } | ||
| 12 | + | ||
| 13 | + public static final Gson get() { | ||
| 14 | + return gson; | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + static { | ||
| 18 | + gson = (new GsonBuilder()).setVersion(1.0D).disableInnerClassSerialization().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).setDateFormat("yyyy-MM-dd").create(); | ||
| 19 | + } | ||
| 20 | +} |
| 1 | +package com.zhonglai.luhui.util; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.text.StrFormatter; | ||
| 4 | + | ||
| 5 | +import java.util.*; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 字符串工具类 | ||
| 9 | + * | ||
| 10 | + * @author ruoyi | ||
| 11 | + */ | ||
| 12 | +public class StringUtils extends org.apache.commons.lang3.StringUtils | ||
| 13 | +{ | ||
| 14 | + /** 空字符串 */ | ||
| 15 | + private static final String NULLSTR = ""; | ||
| 16 | + | ||
| 17 | + /** 下划线 */ | ||
| 18 | + private static final char SEPARATOR = '_'; | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 获取参数不为空值 | ||
| 22 | + * | ||
| 23 | + * @param value defaultValue 要判断的value | ||
| 24 | + * @return value 返回值 | ||
| 25 | + */ | ||
| 26 | + public static <T> T nvl(T value, T defaultValue) | ||
| 27 | + { | ||
| 28 | + return value != null ? value : defaultValue; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * * 判断一个Collection是否为空, 包含List,Set,Queue | ||
| 33 | + * | ||
| 34 | + * @param coll 要判断的Collection | ||
| 35 | + * @return true:为空 false:非空 | ||
| 36 | + */ | ||
| 37 | + public static boolean isEmpty(Collection<?> coll) | ||
| 38 | + { | ||
| 39 | + return isNull(coll) || coll.isEmpty(); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * * 判断一个Collection是否非空,包含List,Set,Queue | ||
| 44 | + * | ||
| 45 | + * @param coll 要判断的Collection | ||
| 46 | + * @return true:非空 false:空 | ||
| 47 | + */ | ||
| 48 | + public static boolean isNotEmpty(Collection<?> coll) | ||
| 49 | + { | ||
| 50 | + return !isEmpty(coll); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * * 判断一个对象数组是否为空 | ||
| 55 | + * | ||
| 56 | + * @param objects 要判断的对象数组 | ||
| 57 | + ** @return true:为空 false:非空 | ||
| 58 | + */ | ||
| 59 | + public static boolean isEmpty(Object[] objects) | ||
| 60 | + { | ||
| 61 | + return isNull(objects) || (objects.length == 0); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * * 判断一个对象数组是否非空 | ||
| 66 | + * | ||
| 67 | + * @param objects 要判断的对象数组 | ||
| 68 | + * @return true:非空 false:空 | ||
| 69 | + */ | ||
| 70 | + public static boolean isNotEmpty(Object[] objects) | ||
| 71 | + { | ||
| 72 | + return !isEmpty(objects); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + /** | ||
| 76 | + * * 判断一个Map是否为空 | ||
| 77 | + * | ||
| 78 | + * @param map 要判断的Map | ||
| 79 | + * @return true:为空 false:非空 | ||
| 80 | + */ | ||
| 81 | + public static boolean isEmpty(Map<?, ?> map) | ||
| 82 | + { | ||
| 83 | + return isNull(map) || map.isEmpty(); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + /** | ||
| 87 | + * * 判断一个Map是否为空 | ||
| 88 | + * | ||
| 89 | + * @param map 要判断的Map | ||
| 90 | + * @return true:非空 false:空 | ||
| 91 | + */ | ||
| 92 | + public static boolean isNotEmpty(Map<?, ?> map) | ||
| 93 | + { | ||
| 94 | + return !isEmpty(map); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + /** | ||
| 98 | + * * 判断一个字符串是否为空串 | ||
| 99 | + * | ||
| 100 | + * @param str String | ||
| 101 | + * @return true:为空 false:非空 | ||
| 102 | + */ | ||
| 103 | + public static boolean isEmpty(String str) | ||
| 104 | + { | ||
| 105 | + return isNull(str) || NULLSTR.equals(str.trim()); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + /** | ||
| 109 | + * * 判断一个字符串是否为非空串 | ||
| 110 | + * | ||
| 111 | + * @param str String | ||
| 112 | + * @return true:非空串 false:空串 | ||
| 113 | + */ | ||
| 114 | + public static boolean isNotEmpty(String str) | ||
| 115 | + { | ||
| 116 | + return !isEmpty(str); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + /** | ||
| 120 | + * * 判断一个对象是否为空 | ||
| 121 | + * | ||
| 122 | + * @param object Object | ||
| 123 | + * @return true:为空 false:非空 | ||
| 124 | + */ | ||
| 125 | + public static boolean isNull(Object object) | ||
| 126 | + { | ||
| 127 | + return object == null; | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + /** | ||
| 131 | + * * 判断一个对象是否非空 | ||
| 132 | + * | ||
| 133 | + * @param object Object | ||
| 134 | + * @return true:非空 false:空 | ||
| 135 | + */ | ||
| 136 | + public static boolean isNotNull(Object object) | ||
| 137 | + { | ||
| 138 | + return !isNull(object); | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + /** | ||
| 142 | + * * 判断一个对象是否是数组类型(Java基本型别的数组) | ||
| 143 | + * | ||
| 144 | + * @param object 对象 | ||
| 145 | + * @return true:是数组 false:不是数组 | ||
| 146 | + */ | ||
| 147 | + public static boolean isArray(Object object) | ||
| 148 | + { | ||
| 149 | + return isNotNull(object) && object.getClass().isArray(); | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + /** | ||
| 153 | + * 去空格 | ||
| 154 | + */ | ||
| 155 | + public static String trim(String str) | ||
| 156 | + { | ||
| 157 | + return (str == null ? "" : str.trim()); | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + /** | ||
| 161 | + * 截取字符串 | ||
| 162 | + * | ||
| 163 | + * @param str 字符串 | ||
| 164 | + * @param start 开始 | ||
| 165 | + * @return 结果 | ||
| 166 | + */ | ||
| 167 | + public static String substring(final String str, int start) | ||
| 168 | + { | ||
| 169 | + if (str == null) | ||
| 170 | + { | ||
| 171 | + return NULLSTR; | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + if (start < 0) | ||
| 175 | + { | ||
| 176 | + start = str.length() + start; | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + if (start < 0) | ||
| 180 | + { | ||
| 181 | + start = 0; | ||
| 182 | + } | ||
| 183 | + if (start > str.length()) | ||
| 184 | + { | ||
| 185 | + return NULLSTR; | ||
| 186 | + } | ||
| 187 | + | ||
| 188 | + return str.substring(start); | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + /** | ||
| 192 | + * 截取字符串 | ||
| 193 | + * | ||
| 194 | + * @param str 字符串 | ||
| 195 | + * @param start 开始 | ||
| 196 | + * @param end 结束 | ||
| 197 | + * @return 结果 | ||
| 198 | + */ | ||
| 199 | + public static String substring(final String str, int start, int end) | ||
| 200 | + { | ||
| 201 | + if (str == null) | ||
| 202 | + { | ||
| 203 | + return NULLSTR; | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + if (end < 0) | ||
| 207 | + { | ||
| 208 | + end = str.length() + end; | ||
| 209 | + } | ||
| 210 | + if (start < 0) | ||
| 211 | + { | ||
| 212 | + start = str.length() + start; | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + if (end > str.length()) | ||
| 216 | + { | ||
| 217 | + end = str.length(); | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + if (start > end) | ||
| 221 | + { | ||
| 222 | + return NULLSTR; | ||
| 223 | + } | ||
| 224 | + | ||
| 225 | + if (start < 0) | ||
| 226 | + { | ||
| 227 | + start = 0; | ||
| 228 | + } | ||
| 229 | + if (end < 0) | ||
| 230 | + { | ||
| 231 | + end = 0; | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + return str.substring(start, end); | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + /** | ||
| 238 | + * 格式化文本, {} 表示占位符<br> | ||
| 239 | + * 此方法只是简单将占位符 {} 按照顺序替换为参数<br> | ||
| 240 | + * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br> | ||
| 241 | + * 例:<br> | ||
| 242 | + * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br> | ||
| 243 | + * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br> | ||
| 244 | + * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br> | ||
| 245 | + * | ||
| 246 | + * @param template 文本模板,被替换的部分用 {} 表示 | ||
| 247 | + * @param params 参数值 | ||
| 248 | + * @return 格式化后的文本 | ||
| 249 | + */ | ||
| 250 | + public static String format(String template, Object... params) | ||
| 251 | + { | ||
| 252 | + if (isEmpty(params) || isEmpty(template)) | ||
| 253 | + { | ||
| 254 | + return template; | ||
| 255 | + } | ||
| 256 | + return StrFormatter.format(template, params); | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + | ||
| 260 | + | ||
| 261 | + /** | ||
| 262 | + * 字符串转set | ||
| 263 | + * | ||
| 264 | + * @param str 字符串 | ||
| 265 | + * @param sep 分隔符 | ||
| 266 | + * @return set集合 | ||
| 267 | + */ | ||
| 268 | + public static final Set<String> str2Set(String str, String sep) | ||
| 269 | + { | ||
| 270 | + return new HashSet<String>(str2List(str, sep, true, false)); | ||
| 271 | + } | ||
| 272 | + | ||
| 273 | + /** | ||
| 274 | + * 字符串转list | ||
| 275 | + * | ||
| 276 | + * @param str 字符串 | ||
| 277 | + * @param sep 分隔符 | ||
| 278 | + * @param filterBlank 过滤纯空白 | ||
| 279 | + * @param trim 去掉首尾空白 | ||
| 280 | + * @return list集合 | ||
| 281 | + */ | ||
| 282 | + public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) | ||
| 283 | + { | ||
| 284 | + List<String> list = new ArrayList<String>(); | ||
| 285 | + if (StringUtils.isEmpty(str)) | ||
| 286 | + { | ||
| 287 | + return list; | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + // 过滤空白字符串 | ||
| 291 | + if (filterBlank && StringUtils.isBlank(str)) | ||
| 292 | + { | ||
| 293 | + return list; | ||
| 294 | + } | ||
| 295 | + String[] split = str.split(sep); | ||
| 296 | + for (String string : split) | ||
| 297 | + { | ||
| 298 | + if (filterBlank && StringUtils.isBlank(string)) | ||
| 299 | + { | ||
| 300 | + continue; | ||
| 301 | + } | ||
| 302 | + if (trim) | ||
| 303 | + { | ||
| 304 | + string = string.trim(); | ||
| 305 | + } | ||
| 306 | + list.add(string); | ||
| 307 | + } | ||
| 308 | + | ||
| 309 | + return list; | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + /** | ||
| 313 | + * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 | ||
| 314 | + * | ||
| 315 | + * @param cs 指定字符串 | ||
| 316 | + * @param searchCharSequences 需要检查的字符串数组 | ||
| 317 | + * @return 是否包含任意一个字符串 | ||
| 318 | + */ | ||
| 319 | + public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) | ||
| 320 | + { | ||
| 321 | + if (isEmpty(cs) || isEmpty(searchCharSequences)) | ||
| 322 | + { | ||
| 323 | + return false; | ||
| 324 | + } | ||
| 325 | + for (CharSequence testStr : searchCharSequences) | ||
| 326 | + { | ||
| 327 | + if (containsIgnoreCase(cs, testStr)) | ||
| 328 | + { | ||
| 329 | + return true; | ||
| 330 | + } | ||
| 331 | + } | ||
| 332 | + return false; | ||
| 333 | + } | ||
| 334 | + | ||
| 335 | + /** | ||
| 336 | + * 驼峰转下划线命名 | ||
| 337 | + */ | ||
| 338 | + public static String toUnderScoreCase(String str) | ||
| 339 | + { | ||
| 340 | + if (str == null) | ||
| 341 | + { | ||
| 342 | + return null; | ||
| 343 | + } | ||
| 344 | + StringBuilder sb = new StringBuilder(); | ||
| 345 | + // 前置字符是否大写 | ||
| 346 | + boolean preCharIsUpperCase = true; | ||
| 347 | + // 当前字符是否大写 | ||
| 348 | + boolean curreCharIsUpperCase = true; | ||
| 349 | + // 下一字符是否大写 | ||
| 350 | + boolean nexteCharIsUpperCase = true; | ||
| 351 | + for (int i = 0; i < str.length(); i++) | ||
| 352 | + { | ||
| 353 | + char c = str.charAt(i); | ||
| 354 | + if (i > 0) | ||
| 355 | + { | ||
| 356 | + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); | ||
| 357 | + } | ||
| 358 | + else | ||
| 359 | + { | ||
| 360 | + preCharIsUpperCase = false; | ||
| 361 | + } | ||
| 362 | + | ||
| 363 | + curreCharIsUpperCase = Character.isUpperCase(c); | ||
| 364 | + | ||
| 365 | + if (i < (str.length() - 1)) | ||
| 366 | + { | ||
| 367 | + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); | ||
| 368 | + } | ||
| 369 | + | ||
| 370 | + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) | ||
| 371 | + { | ||
| 372 | + sb.append(SEPARATOR); | ||
| 373 | + } | ||
| 374 | + else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) | ||
| 375 | + { | ||
| 376 | + sb.append(SEPARATOR); | ||
| 377 | + } | ||
| 378 | + sb.append(Character.toLowerCase(c)); | ||
| 379 | + } | ||
| 380 | + | ||
| 381 | + return sb.toString(); | ||
| 382 | + } | ||
| 383 | + | ||
| 384 | + /** | ||
| 385 | + * 是否包含字符串 | ||
| 386 | + * | ||
| 387 | + * @param str 验证字符串 | ||
| 388 | + * @param strs 字符串组 | ||
| 389 | + * @return 包含返回true | ||
| 390 | + */ | ||
| 391 | + public static boolean inStringIgnoreCase(String str, String... strs) | ||
| 392 | + { | ||
| 393 | + if (str != null && strs != null) | ||
| 394 | + { | ||
| 395 | + for (String s : strs) | ||
| 396 | + { | ||
| 397 | + if (str.equalsIgnoreCase(trim(s))) | ||
| 398 | + { | ||
| 399 | + return true; | ||
| 400 | + } | ||
| 401 | + } | ||
| 402 | + } | ||
| 403 | + return false; | ||
| 404 | + } | ||
| 405 | + | ||
| 406 | + /** | ||
| 407 | + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld | ||
| 408 | + * | ||
| 409 | + * @param name 转换前的下划线大写方式命名的字符串 | ||
| 410 | + * @return 转换后的驼峰式命名的字符串 | ||
| 411 | + */ | ||
| 412 | + public static String convertToCamelCase(String name) | ||
| 413 | + { | ||
| 414 | + StringBuilder result = new StringBuilder(); | ||
| 415 | + // 快速检查 | ||
| 416 | + if (name == null || name.isEmpty()) | ||
| 417 | + { | ||
| 418 | + // 没必要转换 | ||
| 419 | + return ""; | ||
| 420 | + } | ||
| 421 | + else if (!name.contains("_")) | ||
| 422 | + { | ||
| 423 | + // 不含下划线,仅将首字母大写 | ||
| 424 | + return name.substring(0, 1).toUpperCase() + name.substring(1); | ||
| 425 | + } | ||
| 426 | + // 用下划线将原始字符串分割 | ||
| 427 | + String[] camels = name.split("_"); | ||
| 428 | + for (String camel : camels) | ||
| 429 | + { | ||
| 430 | + // 跳过原始字符串中开头、结尾的下换线或双重下划线 | ||
| 431 | + if (camel.isEmpty()) | ||
| 432 | + { | ||
| 433 | + continue; | ||
| 434 | + } | ||
| 435 | + // 首字母大写 | ||
| 436 | + result.append(camel.substring(0, 1).toUpperCase()); | ||
| 437 | + result.append(camel.substring(1).toLowerCase()); | ||
| 438 | + } | ||
| 439 | + return result.toString(); | ||
| 440 | + } | ||
| 441 | + | ||
| 442 | + /** | ||
| 443 | + * 驼峰式命名法 例如:user_name->userName | ||
| 444 | + */ | ||
| 445 | + public static String toCamelCase(String s) | ||
| 446 | + { | ||
| 447 | + if (s == null) | ||
| 448 | + { | ||
| 449 | + return null; | ||
| 450 | + } | ||
| 451 | + s = s.toLowerCase(); | ||
| 452 | + StringBuilder sb = new StringBuilder(s.length()); | ||
| 453 | + boolean upperCase = false; | ||
| 454 | + for (int i = 0; i < s.length(); i++) | ||
| 455 | + { | ||
| 456 | + char c = s.charAt(i); | ||
| 457 | + | ||
| 458 | + if (c == SEPARATOR) | ||
| 459 | + { | ||
| 460 | + upperCase = true; | ||
| 461 | + } | ||
| 462 | + else if (upperCase) | ||
| 463 | + { | ||
| 464 | + sb.append(Character.toUpperCase(c)); | ||
| 465 | + upperCase = false; | ||
| 466 | + } | ||
| 467 | + else | ||
| 468 | + { | ||
| 469 | + sb.append(c); | ||
| 470 | + } | ||
| 471 | + } | ||
| 472 | + return sb.toString(); | ||
| 473 | + } | ||
| 474 | + | ||
| 475 | + | ||
| 476 | + | ||
| 477 | + @SuppressWarnings("unchecked") | ||
| 478 | + public static <T> T cast(Object obj) | ||
| 479 | + { | ||
| 480 | + return (T) obj; | ||
| 481 | + } | ||
| 482 | + | ||
| 483 | + /** | ||
| 484 | + * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 | ||
| 485 | + * | ||
| 486 | + * @param num 数字对象 | ||
| 487 | + * @param size 字符串指定长度 | ||
| 488 | + * @return 返回数字的字符串格式,该字符串为指定长度。 | ||
| 489 | + */ | ||
| 490 | + public static final String padl(final Number num, final int size) | ||
| 491 | + { | ||
| 492 | + return padl(num.toString(), size, '0'); | ||
| 493 | + } | ||
| 494 | + | ||
| 495 | + /** | ||
| 496 | + * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 | ||
| 497 | + * | ||
| 498 | + * @param s 原始字符串 | ||
| 499 | + * @param size 字符串指定长度 | ||
| 500 | + * @param c 用于补齐的字符 | ||
| 501 | + * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 | ||
| 502 | + */ | ||
| 503 | + public static final String padl(final String s, final int size, final char c) | ||
| 504 | + { | ||
| 505 | + final StringBuilder sb = new StringBuilder(size); | ||
| 506 | + if (s != null) | ||
| 507 | + { | ||
| 508 | + final int len = s.length(); | ||
| 509 | + if (s.length() <= size) | ||
| 510 | + { | ||
| 511 | + for (int i = size - len; i > 0; i--) | ||
| 512 | + { | ||
| 513 | + sb.append(c); | ||
| 514 | + } | ||
| 515 | + sb.append(s); | ||
| 516 | + } | ||
| 517 | + else | ||
| 518 | + { | ||
| 519 | + return s.substring(len - size, len); | ||
| 520 | + } | ||
| 521 | + } | ||
| 522 | + else | ||
| 523 | + { | ||
| 524 | + for (int i = size; i > 0; i--) | ||
| 525 | + { | ||
| 526 | + sb.append(c); | ||
| 527 | + } | ||
| 528 | + } | ||
| 529 | + return sb.toString(); | ||
| 530 | + } | ||
| 531 | + | ||
| 532 | + /** | ||
| 533 | + * [简要描述]:首字母大写 | ||
| 534 | + * | ||
| 535 | + * @author com.zhonglai | ||
| 536 | + * @param str | ||
| 537 | + * @return | ||
| 538 | + */ | ||
| 539 | + public static String getName(String str) { | ||
| 540 | + char ch = str.toCharArray()[0]; | ||
| 541 | + ch = (char) ((ch - 97) + 'A'); | ||
| 542 | + str = ch + str.substring(1); | ||
| 543 | + return str; | ||
| 544 | + } | ||
| 545 | + | ||
| 546 | + public static void main(String[] args) { | ||
| 547 | + System.out.println(StringUtils.toUnderScoreCase("deviceInfoId")); | ||
| 548 | + } | ||
| 549 | +} |
| 1 | +package com.zhonglai.luhui.util; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import java.util.concurrent.*; | ||
| 5 | +import java.util.logging.Level; | ||
| 6 | +import java.util.logging.Logger; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 线程相关工具类. | ||
| 10 | + * | ||
| 11 | + * @author ruoyi | ||
| 12 | + */ | ||
| 13 | +public class Threads | ||
| 14 | +{ | ||
| 15 | + private static final Logger logger = Logger.getLogger(Threads.class.getName()); | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * sleep等待,单位为毫秒 | ||
| 19 | + */ | ||
| 20 | + public static void sleep(long milliseconds) | ||
| 21 | + { | ||
| 22 | + try | ||
| 23 | + { | ||
| 24 | + Thread.sleep(milliseconds); | ||
| 25 | + } | ||
| 26 | + catch (InterruptedException e) | ||
| 27 | + { | ||
| 28 | + return; | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 停止线程池 | ||
| 34 | + * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. | ||
| 35 | + * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数. | ||
| 36 | + * 如果仍然超時,則強制退出. | ||
| 37 | + * 另对在shutdown时线程本身被调用中断做了处理. | ||
| 38 | + */ | ||
| 39 | + public static void shutdownAndAwaitTermination(ExecutorService pool) | ||
| 40 | + { | ||
| 41 | + if (pool != null && !pool.isShutdown()) | ||
| 42 | + { | ||
| 43 | + pool.shutdown(); | ||
| 44 | + try | ||
| 45 | + { | ||
| 46 | + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) | ||
| 47 | + { | ||
| 48 | + pool.shutdownNow(); | ||
| 49 | + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) | ||
| 50 | + { | ||
| 51 | + logger.info("Pool did not terminate"); | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + } | ||
| 55 | + catch (InterruptedException ie) | ||
| 56 | + { | ||
| 57 | + pool.shutdownNow(); | ||
| 58 | + Thread.currentThread().interrupt(); | ||
| 59 | + } | ||
| 60 | + } | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * 打印线程异常信息 | ||
| 65 | + */ | ||
| 66 | + public static void printException(Runnable r, Throwable t) | ||
| 67 | + { | ||
| 68 | + if (t == null && r instanceof Future<?>) | ||
| 69 | + { | ||
| 70 | + try | ||
| 71 | + { | ||
| 72 | + Future<?> future = (Future<?>) r; | ||
| 73 | + if (future.isDone()) | ||
| 74 | + { | ||
| 75 | + future.get(); | ||
| 76 | + } | ||
| 77 | + } | ||
| 78 | + catch (CancellationException ce) | ||
| 79 | + { | ||
| 80 | + t = ce; | ||
| 81 | + } | ||
| 82 | + catch (ExecutionException ee) | ||
| 83 | + { | ||
| 84 | + t = ee.getCause(); | ||
| 85 | + } | ||
| 86 | + catch (InterruptedException ie) | ||
| 87 | + { | ||
| 88 | + Thread.currentThread().interrupt(); | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + if (t != null) | ||
| 92 | + { | ||
| 93 | + logger.log(Level.SEVERE,t.getMessage(), t); | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | +} |
| 1 | +package com.zhonglai.luhui.util.bean; | ||
| 2 | + | ||
| 3 | +import javax.validation.ConstraintViolation; | ||
| 4 | +import javax.validation.ConstraintViolationException; | ||
| 5 | +import javax.validation.Validator; | ||
| 6 | +import java.util.Set; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * bean对象属性验证 | ||
| 10 | + * | ||
| 11 | + * @author ruoyi | ||
| 12 | + */ | ||
| 13 | +public class BeanValidators | ||
| 14 | +{ | ||
| 15 | + public static void validateWithException(Validator validator, Object object, Class<?>... groups) | ||
| 16 | + throws ConstraintViolationException | ||
| 17 | + { | ||
| 18 | + Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups); | ||
| 19 | + if (!constraintViolations.isEmpty()) | ||
| 20 | + { | ||
| 21 | + throw new ConstraintViolationException(constraintViolations); | ||
| 22 | + } | ||
| 23 | + } | ||
| 24 | +} |
lh-common/lh-common-util/src/main/java/com/zhonglai/luhui/util/bean/MapToObjectConverter.java
0 → 100644
| 1 | +package com.zhonglai.luhui.util.bean; | ||
| 2 | + | ||
| 3 | +import java.lang.reflect.Field; | ||
| 4 | +import java.lang.reflect.Modifier; | ||
| 5 | +import java.util.Map; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * map操作 | ||
| 9 | + */ | ||
| 10 | +public class MapToObjectConverter { | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * map转指定对象 | ||
| 14 | + * @param map | ||
| 15 | + * @param clazz | ||
| 16 | + * @return | ||
| 17 | + * @param <T> | ||
| 18 | + * @throws IllegalAccessException | ||
| 19 | + * @throws InstantiationException | ||
| 20 | + */ | ||
| 21 | + public static <T> T convert(Map<String, Object> map, Class<T> clazz) throws IllegalAccessException, InstantiationException { | ||
| 22 | + T obj = clazz.newInstance(); | ||
| 23 | + for (Field field : clazz.getDeclaredFields()) { | ||
| 24 | + int mod = field.getModifiers(); | ||
| 25 | + if (Modifier.isStatic(mod) || Modifier.isFinal(mod) || Modifier.isTransient(mod)) { | ||
| 26 | + continue; | ||
| 27 | + } | ||
| 28 | + field.setAccessible(true); | ||
| 29 | + if (map.containsKey(field.getName())) { | ||
| 30 | + field.set(obj, map.get(field.getName())); | ||
| 31 | + } | ||
| 32 | + } | ||
| 33 | + return obj; | ||
| 34 | + } | ||
| 35 | +} |
| 1 | +package com.zhonglai.luhui.util.file; | ||
| 2 | + | ||
| 3 | +import org.apache.commons.lang3.StringUtils; | ||
| 4 | + | ||
| 5 | +import java.io.File; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 文件类型工具类 | ||
| 9 | + * | ||
| 10 | + * @author ruoyi | ||
| 11 | + */ | ||
| 12 | +public class FileTypeUtils | ||
| 13 | +{ | ||
| 14 | + /** | ||
| 15 | + * 获取文件类型 | ||
| 16 | + * <p> | ||
| 17 | + * 例如: ruoyi.txt, 返回: txt | ||
| 18 | + * | ||
| 19 | + * @param file 文件名 | ||
| 20 | + * @return 后缀(不含".") | ||
| 21 | + */ | ||
| 22 | + public static String getFileType(File file) | ||
| 23 | + { | ||
| 24 | + if (null == file) | ||
| 25 | + { | ||
| 26 | + return StringUtils.EMPTY; | ||
| 27 | + } | ||
| 28 | + return getFileType(file.getName()); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 获取文件类型 | ||
| 33 | + * <p> | ||
| 34 | + * 例如: ruoyi.txt, 返回: txt | ||
| 35 | + * | ||
| 36 | + * @param fileName 文件名 | ||
| 37 | + * @return 后缀(不含".") | ||
| 38 | + */ | ||
| 39 | + public static String getFileType(String fileName) | ||
| 40 | + { | ||
| 41 | + int separatorIndex = fileName.lastIndexOf("."); | ||
| 42 | + if (separatorIndex < 0) | ||
| 43 | + { | ||
| 44 | + return ""; | ||
| 45 | + } | ||
| 46 | + return fileName.substring(separatorIndex + 1).toLowerCase(); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 获取文件类型 | ||
| 51 | + * | ||
| 52 | + * @param photoByte 文件字节码 | ||
| 53 | + * @return 后缀(不含".") | ||
| 54 | + */ | ||
| 55 | + public static String getFileExtendName(byte[] photoByte) | ||
| 56 | + { | ||
| 57 | + String strFileExtendName = "JPG"; | ||
| 58 | + if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) | ||
| 59 | + && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) | ||
| 60 | + { | ||
| 61 | + strFileExtendName = "GIF"; | ||
| 62 | + } | ||
| 63 | + else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) | ||
| 64 | + { | ||
| 65 | + strFileExtendName = "JPG"; | ||
| 66 | + } | ||
| 67 | + else if ((photoByte[0] == 66) && (photoByte[1] == 77)) | ||
| 68 | + { | ||
| 69 | + strFileExtendName = "BMP"; | ||
| 70 | + } | ||
| 71 | + else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) | ||
| 72 | + { | ||
| 73 | + strFileExtendName = "PNG"; | ||
| 74 | + } | ||
| 75 | + return strFileExtendName; | ||
| 76 | + } | ||
| 77 | +} |
| 1 | +package com.zhonglai.luhui.util.file; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 媒体类型工具类 | ||
| 5 | + * | ||
| 6 | + * @author ruoyi | ||
| 7 | + */ | ||
| 8 | +public class MimeTypeUtils | ||
| 9 | +{ | ||
| 10 | + public static final String IMAGE_PNG = "image/png"; | ||
| 11 | + | ||
| 12 | + public static final String IMAGE_JPG = "image/jpg"; | ||
| 13 | + | ||
| 14 | + public static final String IMAGE_JPEG = "image/jpeg"; | ||
| 15 | + | ||
| 16 | + public static final String IMAGE_BMP = "image/bmp"; | ||
| 17 | + | ||
| 18 | + public static final String IMAGE_GIF = "image/gif"; | ||
| 19 | + | ||
| 20 | + public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }; | ||
| 21 | + | ||
| 22 | + public static final String[] FLASH_EXTENSION = { "swf", "flv" }; | ||
| 23 | + | ||
| 24 | + public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", | ||
| 25 | + "asf", "rm", "rmvb" }; | ||
| 26 | + | ||
| 27 | + public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" }; | ||
| 28 | + | ||
| 29 | + public static final String[] DEFAULT_ALLOWED_EXTENSION = { | ||
| 30 | + // 图片 | ||
| 31 | + "bmp", "gif", "jpg", "jpeg", "png", | ||
| 32 | + // word excel powerpoint | ||
| 33 | + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", | ||
| 34 | + // 压缩文件 | ||
| 35 | + "rar", "zip", "gz", "bz2", | ||
| 36 | + // 视频格式 | ||
| 37 | + "mp4", "avi", "rmvb", | ||
| 38 | |||
| 39 | + "pdf" }; | ||
| 40 | + | ||
| 41 | + public static String getExtension(String prefix) | ||
| 42 | + { | ||
| 43 | + switch (prefix) | ||
| 44 | + { | ||
| 45 | + case IMAGE_PNG: | ||
| 46 | + return "png"; | ||
| 47 | + case IMAGE_JPG: | ||
| 48 | + return "jpg"; | ||
| 49 | + case IMAGE_JPEG: | ||
| 50 | + return "jpeg"; | ||
| 51 | + case IMAGE_BMP: | ||
| 52 | + return "bmp"; | ||
| 53 | + case IMAGE_GIF: | ||
| 54 | + return "gif"; | ||
| 55 | + default: | ||
| 56 | + return ""; | ||
| 57 | + } | ||
| 58 | + } | ||
| 59 | +} |
| 1 | +package com.zhonglai.luhui.util.html; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import org.apache.commons.lang3.StringUtils; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 转义和反转义工具类 | ||
| 8 | + * | ||
| 9 | + * @author ruoyi | ||
| 10 | + */ | ||
| 11 | +public class EscapeUtil | ||
| 12 | +{ | ||
| 13 | + public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; | ||
| 14 | + | ||
| 15 | + private static final char[][] TEXT = new char[64][]; | ||
| 16 | + | ||
| 17 | + static | ||
| 18 | + { | ||
| 19 | + for (int i = 0; i < 64; i++) | ||
| 20 | + { | ||
| 21 | + TEXT[i] = new char[] { (char) i }; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + // special HTML characters | ||
| 25 | + TEXT['\''] = "'".toCharArray(); // 单引号 | ||
| 26 | + TEXT['"'] = """.toCharArray(); // 双引号 | ||
| 27 | + TEXT['&'] = "&".toCharArray(); // &符 | ||
| 28 | + TEXT['<'] = "<".toCharArray(); // 小于号 | ||
| 29 | + TEXT['>'] = ">".toCharArray(); // 大于号 | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 转义文本中的HTML字符为安全的字符 | ||
| 34 | + * | ||
| 35 | + * @param text 被转义的文本 | ||
| 36 | + * @return 转义后的文本 | ||
| 37 | + */ | ||
| 38 | + public static String escape(String text) | ||
| 39 | + { | ||
| 40 | + return encode(text); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * 还原被转义的HTML特殊字符 | ||
| 45 | + * | ||
| 46 | + * @param content 包含转义符的HTML内容 | ||
| 47 | + * @return 转换后的字符串 | ||
| 48 | + */ | ||
| 49 | + public static String unescape(String content) | ||
| 50 | + { | ||
| 51 | + return decode(content); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * 清除所有HTML标签,但是不删除标签内的内容 | ||
| 56 | + * | ||
| 57 | + * @param content 文本 | ||
| 58 | + * @return 清除标签后的文本 | ||
| 59 | + */ | ||
| 60 | + public static String clean(String content) | ||
| 61 | + { | ||
| 62 | + return new HTMLFilter().filter(content); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + /** | ||
| 66 | + * Escape编码 | ||
| 67 | + * | ||
| 68 | + * @param text 被编码的文本 | ||
| 69 | + * @return 编码后的字符 | ||
| 70 | + */ | ||
| 71 | + private static String encode(String text) | ||
| 72 | + { | ||
| 73 | + if (StringUtils.isEmpty(text)) | ||
| 74 | + { | ||
| 75 | + return StringUtils.EMPTY; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + final StringBuilder tmp = new StringBuilder(text.length() * 6); | ||
| 79 | + char c; | ||
| 80 | + for (int i = 0; i < text.length(); i++) | ||
| 81 | + { | ||
| 82 | + c = text.charAt(i); | ||
| 83 | + if (c < 256) | ||
| 84 | + { | ||
| 85 | + tmp.append("%"); | ||
| 86 | + if (c < 16) | ||
| 87 | + { | ||
| 88 | + tmp.append("0"); | ||
| 89 | + } | ||
| 90 | + tmp.append(Integer.toString(c, 16)); | ||
| 91 | + } | ||
| 92 | + else | ||
| 93 | + { | ||
| 94 | + tmp.append("%u"); | ||
| 95 | + if (c <= 0xfff) | ||
| 96 | + { | ||
| 97 | + // issue#I49JU8@Gitee | ||
| 98 | + tmp.append("0"); | ||
| 99 | + } | ||
| 100 | + tmp.append(Integer.toString(c, 16)); | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | + return tmp.toString(); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * Escape解码 | ||
| 108 | + * | ||
| 109 | + * @param content 被转义的内容 | ||
| 110 | + * @return 解码后的字符串 | ||
| 111 | + */ | ||
| 112 | + public static String decode(String content) | ||
| 113 | + { | ||
| 114 | + if (StringUtils.isEmpty(content)) | ||
| 115 | + { | ||
| 116 | + return content; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + StringBuilder tmp = new StringBuilder(content.length()); | ||
| 120 | + int lastPos = 0, pos = 0; | ||
| 121 | + char ch; | ||
| 122 | + while (lastPos < content.length()) | ||
| 123 | + { | ||
| 124 | + pos = content.indexOf("%", lastPos); | ||
| 125 | + if (pos == lastPos) | ||
| 126 | + { | ||
| 127 | + if (content.charAt(pos + 1) == 'u') | ||
| 128 | + { | ||
| 129 | + ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16); | ||
| 130 | + tmp.append(ch); | ||
| 131 | + lastPos = pos + 6; | ||
| 132 | + } | ||
| 133 | + else | ||
| 134 | + { | ||
| 135 | + ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16); | ||
| 136 | + tmp.append(ch); | ||
| 137 | + lastPos = pos + 3; | ||
| 138 | + } | ||
| 139 | + } | ||
| 140 | + else | ||
| 141 | + { | ||
| 142 | + if (pos == -1) | ||
| 143 | + { | ||
| 144 | + tmp.append(content.substring(lastPos)); | ||
| 145 | + lastPos = content.length(); | ||
| 146 | + } | ||
| 147 | + else | ||
| 148 | + { | ||
| 149 | + tmp.append(content.substring(lastPos, pos)); | ||
| 150 | + lastPos = pos; | ||
| 151 | + } | ||
| 152 | + } | ||
| 153 | + } | ||
| 154 | + return tmp.toString(); | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + public static void main(String[] args) | ||
| 158 | + { | ||
| 159 | + String html = "<script>alert(1);</script>"; | ||
| 160 | + String escape = EscapeUtil.escape(html); | ||
| 161 | + // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>"; | ||
| 162 | + // String html = "<123"; | ||
| 163 | + // String html = "123>"; | ||
| 164 | + System.out.println("clean: " + EscapeUtil.clean(html)); | ||
| 165 | + System.out.println("escape: " + escape); | ||
| 166 | + System.out.println("unescape: " + EscapeUtil.unescape(escape)); | ||
| 167 | + } | ||
| 168 | +} |
| 1 | +package com.zhonglai.luhui.util.html; | ||
| 2 | + | ||
| 3 | +import java.util.*; | ||
| 4 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 5 | +import java.util.concurrent.ConcurrentMap; | ||
| 6 | +import java.util.regex.Matcher; | ||
| 7 | +import java.util.regex.Pattern; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * HTML过滤器,用于去除XSS漏洞隐患。 | ||
| 11 | + * | ||
| 12 | + * @author ruoyi | ||
| 13 | + */ | ||
| 14 | +public final class HTMLFilter | ||
| 15 | +{ | ||
| 16 | + /** | ||
| 17 | + * regex flag union representing /si modifiers in php | ||
| 18 | + **/ | ||
| 19 | + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; | ||
| 20 | + private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL); | ||
| 21 | + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); | ||
| 22 | + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); | ||
| 23 | + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); | ||
| 24 | + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); | ||
| 25 | + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); | ||
| 26 | + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); | ||
| 27 | + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); | ||
| 28 | + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); | ||
| 29 | + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); | ||
| 30 | + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); | ||
| 31 | + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); | ||
| 32 | + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); | ||
| 33 | + private static final Pattern P_END_ARROW = Pattern.compile("^>"); | ||
| 34 | + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); | ||
| 35 | + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); | ||
| 36 | + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); | ||
| 37 | + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); | ||
| 38 | + private static final Pattern P_AMP = Pattern.compile("&"); | ||
| 39 | + private static final Pattern P_QUOTE = Pattern.compile("\""); | ||
| 40 | + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); | ||
| 41 | + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); | ||
| 42 | + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); | ||
| 43 | + | ||
| 44 | + // @xxx could grow large... maybe use sesat's ReferenceMap | ||
| 45 | + private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); | ||
| 46 | + private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * set of allowed html elements, along with allowed attributes for each element | ||
| 50 | + **/ | ||
| 51 | + private final Map<String, List<String>> vAllowed; | ||
| 52 | + /** | ||
| 53 | + * counts of open tags for each (allowable) html element | ||
| 54 | + **/ | ||
| 55 | + private final Map<String, Integer> vTagCounts = new HashMap<>(); | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * html elements which must always be self-closing (e.g. "<img />") | ||
| 59 | + **/ | ||
| 60 | + private final String[] vSelfClosingTags; | ||
| 61 | + /** | ||
| 62 | + * html elements which must always have separate opening and closing tags (e.g. "<b></b>") | ||
| 63 | + **/ | ||
| 64 | + private final String[] vNeedClosingTags; | ||
| 65 | + /** | ||
| 66 | + * set of disallowed html elements | ||
| 67 | + **/ | ||
| 68 | + private final String[] vDisallowed; | ||
| 69 | + /** | ||
| 70 | + * attributes which should be checked for valid protocols | ||
| 71 | + **/ | ||
| 72 | + private final String[] vProtocolAtts; | ||
| 73 | + /** | ||
| 74 | + * allowed protocols | ||
| 75 | + **/ | ||
| 76 | + private final String[] vAllowedProtocols; | ||
| 77 | + /** | ||
| 78 | + * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") | ||
| 79 | + **/ | ||
| 80 | + private final String[] vRemoveBlanks; | ||
| 81 | + /** | ||
| 82 | + * entities allowed within html markup | ||
| 83 | + **/ | ||
| 84 | + private final String[] vAllowedEntities; | ||
| 85 | + /** | ||
| 86 | + * flag determining whether comments are allowed in input String. | ||
| 87 | + */ | ||
| 88 | + private final boolean stripComment; | ||
| 89 | + private final boolean encodeQuotes; | ||
| 90 | + /** | ||
| 91 | + * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>" | ||
| 92 | + * becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped. | ||
| 93 | + */ | ||
| 94 | + private final boolean alwaysMakeTags; | ||
| 95 | + | ||
| 96 | + /** | ||
| 97 | + * Default constructor. | ||
| 98 | + */ | ||
| 99 | + public HTMLFilter() | ||
| 100 | + { | ||
| 101 | + vAllowed = new HashMap<>(); | ||
| 102 | + | ||
| 103 | + final ArrayList<String> a_atts = new ArrayList<>(); | ||
| 104 | + a_atts.add("href"); | ||
| 105 | + a_atts.add("target"); | ||
| 106 | + vAllowed.put("a", a_atts); | ||
| 107 | + | ||
| 108 | + final ArrayList<String> img_atts = new ArrayList<>(); | ||
| 109 | + img_atts.add("src"); | ||
| 110 | + img_atts.add("width"); | ||
| 111 | + img_atts.add("height"); | ||
| 112 | + img_atts.add("alt"); | ||
| 113 | + vAllowed.put("img", img_atts); | ||
| 114 | + | ||
| 115 | + final ArrayList<String> no_atts = new ArrayList<>(); | ||
| 116 | + vAllowed.put("b", no_atts); | ||
| 117 | + vAllowed.put("strong", no_atts); | ||
| 118 | + vAllowed.put("i", no_atts); | ||
| 119 | + vAllowed.put("em", no_atts); | ||
| 120 | + | ||
| 121 | + vSelfClosingTags = new String[] { "img" }; | ||
| 122 | + vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; | ||
| 123 | + vDisallowed = new String[] {}; | ||
| 124 | + vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp. | ||
| 125 | + vProtocolAtts = new String[] { "src", "href" }; | ||
| 126 | + vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; | ||
| 127 | + vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; | ||
| 128 | + stripComment = true; | ||
| 129 | + encodeQuotes = true; | ||
| 130 | + alwaysMakeTags = false; | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + /** | ||
| 134 | + * Map-parameter configurable constructor. | ||
| 135 | + * | ||
| 136 | + * @param conf map containing configuration. keys match field names. | ||
| 137 | + */ | ||
| 138 | + @SuppressWarnings("unchecked") | ||
| 139 | + public HTMLFilter(final Map<String, Object> conf) | ||
| 140 | + { | ||
| 141 | + | ||
| 142 | + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; | ||
| 143 | + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; | ||
| 144 | + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; | ||
| 145 | + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; | ||
| 146 | + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; | ||
| 147 | + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; | ||
| 148 | + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; | ||
| 149 | + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; | ||
| 150 | + | ||
| 151 | + vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed")); | ||
| 152 | + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); | ||
| 153 | + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); | ||
| 154 | + vDisallowed = (String[]) conf.get("vDisallowed"); | ||
| 155 | + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); | ||
| 156 | + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); | ||
| 157 | + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); | ||
| 158 | + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); | ||
| 159 | + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; | ||
| 160 | + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; | ||
| 161 | + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + private void reset() | ||
| 165 | + { | ||
| 166 | + vTagCounts.clear(); | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + // --------------------------------------------------------------- | ||
| 170 | + // my versions of some PHP library functions | ||
| 171 | + public static String chr(final int decimal) | ||
| 172 | + { | ||
| 173 | + return String.valueOf((char) decimal); | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + public static String htmlSpecialChars(final String s) | ||
| 177 | + { | ||
| 178 | + String result = s; | ||
| 179 | + result = regexReplace(P_AMP, "&", result); | ||
| 180 | + result = regexReplace(P_QUOTE, """, result); | ||
| 181 | + result = regexReplace(P_LEFT_ARROW, "<", result); | ||
| 182 | + result = regexReplace(P_RIGHT_ARROW, ">", result); | ||
| 183 | + return result; | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + // --------------------------------------------------------------- | ||
| 187 | + | ||
| 188 | + /** | ||
| 189 | + * given a user submitted input String, filter out any invalid or restricted html. | ||
| 190 | + * | ||
| 191 | + * @param input text (i.e. submitted by a user) than may contain html | ||
| 192 | + * @return "clean" version of input, with only valid, whitelisted html elements allowed | ||
| 193 | + */ | ||
| 194 | + public String filter(final String input) | ||
| 195 | + { | ||
| 196 | + reset(); | ||
| 197 | + String s = input; | ||
| 198 | + | ||
| 199 | + s = escapeComments(s); | ||
| 200 | + | ||
| 201 | + s = balanceHTML(s); | ||
| 202 | + | ||
| 203 | + s = checkTags(s); | ||
| 204 | + | ||
| 205 | + s = processRemoveBlanks(s); | ||
| 206 | + | ||
| 207 | + // s = validateEntities(s); | ||
| 208 | + | ||
| 209 | + return s; | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + public boolean isAlwaysMakeTags() | ||
| 213 | + { | ||
| 214 | + return alwaysMakeTags; | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + public boolean isStripComments() | ||
| 218 | + { | ||
| 219 | + return stripComment; | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | + private String escapeComments(final String s) | ||
| 223 | + { | ||
| 224 | + final Matcher m = P_COMMENTS.matcher(s); | ||
| 225 | + final StringBuffer buf = new StringBuffer(); | ||
| 226 | + if (m.find()) | ||
| 227 | + { | ||
| 228 | + final String match = m.group(1); // (.*?) | ||
| 229 | + m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->")); | ||
| 230 | + } | ||
| 231 | + m.appendTail(buf); | ||
| 232 | + | ||
| 233 | + return buf.toString(); | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + private String balanceHTML(String s) | ||
| 237 | + { | ||
| 238 | + if (alwaysMakeTags) | ||
| 239 | + { | ||
| 240 | + // | ||
| 241 | + // try and form html | ||
| 242 | + // | ||
| 243 | + s = regexReplace(P_END_ARROW, "", s); | ||
| 244 | + // 不追加结束标签 | ||
| 245 | + s = regexReplace(P_BODY_TO_END, "<$1>", s); | ||
| 246 | + s = regexReplace(P_XML_CONTENT, "$1<$2", s); | ||
| 247 | + | ||
| 248 | + } | ||
| 249 | + else | ||
| 250 | + { | ||
| 251 | + // | ||
| 252 | + // escape stray brackets | ||
| 253 | + // | ||
| 254 | + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); | ||
| 255 | + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); | ||
| 256 | + | ||
| 257 | + // | ||
| 258 | + // the last regexp causes '<>' entities to appear | ||
| 259 | + // (we need to do a lookahead assertion so that the last bracket can | ||
| 260 | + // be used in the next pass of the regexp) | ||
| 261 | + // | ||
| 262 | + s = regexReplace(P_BOTH_ARROWS, "", s); | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + return s; | ||
| 266 | + } | ||
| 267 | + | ||
| 268 | + private String checkTags(String s) | ||
| 269 | + { | ||
| 270 | + Matcher m = P_TAGS.matcher(s); | ||
| 271 | + | ||
| 272 | + final StringBuffer buf = new StringBuffer(); | ||
| 273 | + while (m.find()) | ||
| 274 | + { | ||
| 275 | + String replaceStr = m.group(1); | ||
| 276 | + replaceStr = processTag(replaceStr); | ||
| 277 | + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); | ||
| 278 | + } | ||
| 279 | + m.appendTail(buf); | ||
| 280 | + | ||
| 281 | + // these get tallied in processTag | ||
| 282 | + // (remember to reset before subsequent calls to filter method) | ||
| 283 | + final StringBuilder sBuilder = new StringBuilder(buf.toString()); | ||
| 284 | + for (String key : vTagCounts.keySet()) | ||
| 285 | + { | ||
| 286 | + for (int ii = 0; ii < vTagCounts.get(key); ii++) | ||
| 287 | + { | ||
| 288 | + sBuilder.append("</").append(key).append(">"); | ||
| 289 | + } | ||
| 290 | + } | ||
| 291 | + s = sBuilder.toString(); | ||
| 292 | + | ||
| 293 | + return s; | ||
| 294 | + } | ||
| 295 | + | ||
| 296 | + private String processRemoveBlanks(final String s) | ||
| 297 | + { | ||
| 298 | + String result = s; | ||
| 299 | + for (String tag : vRemoveBlanks) | ||
| 300 | + { | ||
| 301 | + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) | ||
| 302 | + { | ||
| 303 | + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">")); | ||
| 304 | + } | ||
| 305 | + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); | ||
| 306 | + if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) | ||
| 307 | + { | ||
| 308 | + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); | ||
| 309 | + } | ||
| 310 | + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); | ||
| 311 | + } | ||
| 312 | + | ||
| 313 | + return result; | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) | ||
| 317 | + { | ||
| 318 | + Matcher m = regex_pattern.matcher(s); | ||
| 319 | + return m.replaceAll(replacement); | ||
| 320 | + } | ||
| 321 | + | ||
| 322 | + private String processTag(final String s) | ||
| 323 | + { | ||
| 324 | + // ending tags | ||
| 325 | + Matcher m = P_END_TAG.matcher(s); | ||
| 326 | + if (m.find()) | ||
| 327 | + { | ||
| 328 | + final String name = m.group(1).toLowerCase(); | ||
| 329 | + if (allowed(name)) | ||
| 330 | + { | ||
| 331 | + if (!inArray(name, vSelfClosingTags)) | ||
| 332 | + { | ||
| 333 | + if (vTagCounts.containsKey(name)) | ||
| 334 | + { | ||
| 335 | + vTagCounts.put(name, vTagCounts.get(name) - 1); | ||
| 336 | + return "</" + name + ">"; | ||
| 337 | + } | ||
| 338 | + } | ||
| 339 | + } | ||
| 340 | + } | ||
| 341 | + | ||
| 342 | + // starting tags | ||
| 343 | + m = P_START_TAG.matcher(s); | ||
| 344 | + if (m.find()) | ||
| 345 | + { | ||
| 346 | + final String name = m.group(1).toLowerCase(); | ||
| 347 | + final String body = m.group(2); | ||
| 348 | + String ending = m.group(3); | ||
| 349 | + | ||
| 350 | + // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); | ||
| 351 | + if (allowed(name)) | ||
| 352 | + { | ||
| 353 | + final StringBuilder params = new StringBuilder(); | ||
| 354 | + | ||
| 355 | + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); | ||
| 356 | + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); | ||
| 357 | + final List<String> paramNames = new ArrayList<>(); | ||
| 358 | + final List<String> paramValues = new ArrayList<>(); | ||
| 359 | + while (m2.find()) | ||
| 360 | + { | ||
| 361 | + paramNames.add(m2.group(1)); // ([a-z0-9]+) | ||
| 362 | + paramValues.add(m2.group(3)); // (.*?) | ||
| 363 | + } | ||
| 364 | + while (m3.find()) | ||
| 365 | + { | ||
| 366 | + paramNames.add(m3.group(1)); // ([a-z0-9]+) | ||
| 367 | + paramValues.add(m3.group(3)); // ([^\"\\s']+) | ||
| 368 | + } | ||
| 369 | + | ||
| 370 | + String paramName, paramValue; | ||
| 371 | + for (int ii = 0; ii < paramNames.size(); ii++) | ||
| 372 | + { | ||
| 373 | + paramName = paramNames.get(ii).toLowerCase(); | ||
| 374 | + paramValue = paramValues.get(ii); | ||
| 375 | + | ||
| 376 | + // debug( "paramName='" + paramName + "'" ); | ||
| 377 | + // debug( "paramValue='" + paramValue + "'" ); | ||
| 378 | + // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); | ||
| 379 | + | ||
| 380 | + if (allowedAttribute(name, paramName)) | ||
| 381 | + { | ||
| 382 | + if (inArray(paramName, vProtocolAtts)) | ||
| 383 | + { | ||
| 384 | + paramValue = processParamProtocol(paramValue); | ||
| 385 | + } | ||
| 386 | + params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\""); | ||
| 387 | + } | ||
| 388 | + } | ||
| 389 | + | ||
| 390 | + if (inArray(name, vSelfClosingTags)) | ||
| 391 | + { | ||
| 392 | + ending = " /"; | ||
| 393 | + } | ||
| 394 | + | ||
| 395 | + if (inArray(name, vNeedClosingTags)) | ||
| 396 | + { | ||
| 397 | + ending = ""; | ||
| 398 | + } | ||
| 399 | + | ||
| 400 | + if (ending == null || ending.length() < 1) | ||
| 401 | + { | ||
| 402 | + if (vTagCounts.containsKey(name)) | ||
| 403 | + { | ||
| 404 | + vTagCounts.put(name, vTagCounts.get(name) + 1); | ||
| 405 | + } | ||
| 406 | + else | ||
| 407 | + { | ||
| 408 | + vTagCounts.put(name, 1); | ||
| 409 | + } | ||
| 410 | + } | ||
| 411 | + else | ||
| 412 | + { | ||
| 413 | + ending = " /"; | ||
| 414 | + } | ||
| 415 | + return "<" + name + params + ending + ">"; | ||
| 416 | + } | ||
| 417 | + else | ||
| 418 | + { | ||
| 419 | + return ""; | ||
| 420 | + } | ||
| 421 | + } | ||
| 422 | + | ||
| 423 | + // comments | ||
| 424 | + m = P_COMMENT.matcher(s); | ||
| 425 | + if (!stripComment && m.find()) | ||
| 426 | + { | ||
| 427 | + return "<" + m.group() + ">"; | ||
| 428 | + } | ||
| 429 | + | ||
| 430 | + return ""; | ||
| 431 | + } | ||
| 432 | + | ||
| 433 | + private String processParamProtocol(String s) | ||
| 434 | + { | ||
| 435 | + s = decodeEntities(s); | ||
| 436 | + final Matcher m = P_PROTOCOL.matcher(s); | ||
| 437 | + if (m.find()) | ||
| 438 | + { | ||
| 439 | + final String protocol = m.group(1); | ||
| 440 | + if (!inArray(protocol, vAllowedProtocols)) | ||
| 441 | + { | ||
| 442 | + // bad protocol, turn into local anchor link instead | ||
| 443 | + s = "#" + s.substring(protocol.length() + 1); | ||
| 444 | + if (s.startsWith("#//")) | ||
| 445 | + { | ||
| 446 | + s = "#" + s.substring(3); | ||
| 447 | + } | ||
| 448 | + } | ||
| 449 | + } | ||
| 450 | + | ||
| 451 | + return s; | ||
| 452 | + } | ||
| 453 | + | ||
| 454 | + private String decodeEntities(String s) | ||
| 455 | + { | ||
| 456 | + StringBuffer buf = new StringBuffer(); | ||
| 457 | + | ||
| 458 | + Matcher m = P_ENTITY.matcher(s); | ||
| 459 | + while (m.find()) | ||
| 460 | + { | ||
| 461 | + final String match = m.group(1); | ||
| 462 | + final int decimal = Integer.decode(match).intValue(); | ||
| 463 | + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); | ||
| 464 | + } | ||
| 465 | + m.appendTail(buf); | ||
| 466 | + s = buf.toString(); | ||
| 467 | + | ||
| 468 | + buf = new StringBuffer(); | ||
| 469 | + m = P_ENTITY_UNICODE.matcher(s); | ||
| 470 | + while (m.find()) | ||
| 471 | + { | ||
| 472 | + final String match = m.group(1); | ||
| 473 | + final int decimal = Integer.valueOf(match, 16).intValue(); | ||
| 474 | + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); | ||
| 475 | + } | ||
| 476 | + m.appendTail(buf); | ||
| 477 | + s = buf.toString(); | ||
| 478 | + | ||
| 479 | + buf = new StringBuffer(); | ||
| 480 | + m = P_ENCODE.matcher(s); | ||
| 481 | + while (m.find()) | ||
| 482 | + { | ||
| 483 | + final String match = m.group(1); | ||
| 484 | + final int decimal = Integer.valueOf(match, 16).intValue(); | ||
| 485 | + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); | ||
| 486 | + } | ||
| 487 | + m.appendTail(buf); | ||
| 488 | + s = buf.toString(); | ||
| 489 | + | ||
| 490 | + s = validateEntities(s); | ||
| 491 | + return s; | ||
| 492 | + } | ||
| 493 | + | ||
| 494 | + private String validateEntities(final String s) | ||
| 495 | + { | ||
| 496 | + StringBuffer buf = new StringBuffer(); | ||
| 497 | + | ||
| 498 | + // validate entities throughout the string | ||
| 499 | + Matcher m = P_VALID_ENTITIES.matcher(s); | ||
| 500 | + while (m.find()) | ||
| 501 | + { | ||
| 502 | + final String one = m.group(1); // ([^&;]*) | ||
| 503 | + final String two = m.group(2); // (?=(;|&|$)) | ||
| 504 | + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); | ||
| 505 | + } | ||
| 506 | + m.appendTail(buf); | ||
| 507 | + | ||
| 508 | + return encodeQuotes(buf.toString()); | ||
| 509 | + } | ||
| 510 | + | ||
| 511 | + private String encodeQuotes(final String s) | ||
| 512 | + { | ||
| 513 | + if (encodeQuotes) | ||
| 514 | + { | ||
| 515 | + StringBuffer buf = new StringBuffer(); | ||
| 516 | + Matcher m = P_VALID_QUOTES.matcher(s); | ||
| 517 | + while (m.find()) | ||
| 518 | + { | ||
| 519 | + final String one = m.group(1); // (>|^) | ||
| 520 | + final String two = m.group(2); // ([^<]+?) | ||
| 521 | + final String three = m.group(3); // (<|$) | ||
| 522 | + // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) | ||
| 523 | + m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); | ||
| 524 | + } | ||
| 525 | + m.appendTail(buf); | ||
| 526 | + return buf.toString(); | ||
| 527 | + } | ||
| 528 | + else | ||
| 529 | + { | ||
| 530 | + return s; | ||
| 531 | + } | ||
| 532 | + } | ||
| 533 | + | ||
| 534 | + private String checkEntity(final String preamble, final String term) | ||
| 535 | + { | ||
| 536 | + | ||
| 537 | + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; | ||
| 538 | + } | ||
| 539 | + | ||
| 540 | + private boolean isValidEntity(final String entity) | ||
| 541 | + { | ||
| 542 | + return inArray(entity, vAllowedEntities); | ||
| 543 | + } | ||
| 544 | + | ||
| 545 | + private static boolean inArray(final String s, final String[] array) | ||
| 546 | + { | ||
| 547 | + for (String item : array) | ||
| 548 | + { | ||
| 549 | + if (item != null && item.equals(s)) | ||
| 550 | + { | ||
| 551 | + return true; | ||
| 552 | + } | ||
| 553 | + } | ||
| 554 | + return false; | ||
| 555 | + } | ||
| 556 | + | ||
| 557 | + private boolean allowed(final String name) | ||
| 558 | + { | ||
| 559 | + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); | ||
| 560 | + } | ||
| 561 | + | ||
| 562 | + private boolean allowedAttribute(final String name, final String paramName) | ||
| 563 | + { | ||
| 564 | + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); | ||
| 565 | + } | ||
| 566 | +} |
lh-common/lh-common-util/src/main/java/com/zhonglai/luhui/util/poi/ExcelHandlerAdapter.java
0 → 100644
| 1 | +package com.zhonglai.luhui.util.poi; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * Excel数据格式处理适配器 | ||
| 5 | + * | ||
| 6 | + * @author ruoyi | ||
| 7 | + */ | ||
| 8 | +public interface ExcelHandlerAdapter | ||
| 9 | +{ | ||
| 10 | + /** | ||
| 11 | + * 格式化 | ||
| 12 | + * | ||
| 13 | + * @param value 单元格数据值 | ||
| 14 | + * @param args excel注解args参数组 | ||
| 15 | + * | ||
| 16 | + * @return 处理后的值 | ||
| 17 | + */ | ||
| 18 | + Object format(Object value, String[] args); | ||
| 19 | +} |
| 1 | +package com.zhonglai.luhui.util.sign; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * Base64工具类 | ||
| 5 | + * | ||
| 6 | + * @author ruoyi | ||
| 7 | + */ | ||
| 8 | +public final class Base64 | ||
| 9 | +{ | ||
| 10 | + static private final int BASELENGTH = 128; | ||
| 11 | + static private final int LOOKUPLENGTH = 64; | ||
| 12 | + static private final int TWENTYFOURBITGROUP = 24; | ||
| 13 | + static private final int EIGHTBIT = 8; | ||
| 14 | + static private final int SIXTEENBIT = 16; | ||
| 15 | + static private final int FOURBYTE = 4; | ||
| 16 | + static private final int SIGN = -128; | ||
| 17 | + static private final char PAD = '='; | ||
| 18 | + static final private byte[] base64Alphabet = new byte[BASELENGTH]; | ||
| 19 | + static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; | ||
| 20 | + | ||
| 21 | + static | ||
| 22 | + { | ||
| 23 | + for (int i = 0; i < BASELENGTH; ++i) | ||
| 24 | + { | ||
| 25 | + base64Alphabet[i] = -1; | ||
| 26 | + } | ||
| 27 | + for (int i = 'Z'; i >= 'A'; i--) | ||
| 28 | + { | ||
| 29 | + base64Alphabet[i] = (byte) (i - 'A'); | ||
| 30 | + } | ||
| 31 | + for (int i = 'z'; i >= 'a'; i--) | ||
| 32 | + { | ||
| 33 | + base64Alphabet[i] = (byte) (i - 'a' + 26); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + for (int i = '9'; i >= '0'; i--) | ||
| 37 | + { | ||
| 38 | + base64Alphabet[i] = (byte) (i - '0' + 52); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + base64Alphabet['+'] = 62; | ||
| 42 | + base64Alphabet['/'] = 63; | ||
| 43 | + | ||
| 44 | + for (int i = 0; i <= 25; i++) | ||
| 45 | + { | ||
| 46 | + lookUpBase64Alphabet[i] = (char) ('A' + i); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + for (int i = 26, j = 0; i <= 51; i++, j++) | ||
| 50 | + { | ||
| 51 | + lookUpBase64Alphabet[i] = (char) ('a' + j); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + for (int i = 52, j = 0; i <= 61; i++, j++) | ||
| 55 | + { | ||
| 56 | + lookUpBase64Alphabet[i] = (char) ('0' + j); | ||
| 57 | + } | ||
| 58 | + lookUpBase64Alphabet[62] = (char) '+'; | ||
| 59 | + lookUpBase64Alphabet[63] = (char) '/'; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + private static boolean isWhiteSpace(char octect) | ||
| 63 | + { | ||
| 64 | + return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + private static boolean isPad(char octect) | ||
| 68 | + { | ||
| 69 | + return (octect == PAD); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + private static boolean isData(char octect) | ||
| 73 | + { | ||
| 74 | + return (octect < BASELENGTH && base64Alphabet[octect] != -1); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * Encodes hex octects into Base64 | ||
| 79 | + * | ||
| 80 | + * @param binaryData Array containing binaryData | ||
| 81 | + * @return Encoded Base64 array | ||
| 82 | + */ | ||
| 83 | + public static String encode(byte[] binaryData) | ||
| 84 | + { | ||
| 85 | + if (binaryData == null) | ||
| 86 | + { | ||
| 87 | + return null; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + int lengthDataBits = binaryData.length * EIGHTBIT; | ||
| 91 | + if (lengthDataBits == 0) | ||
| 92 | + { | ||
| 93 | + return ""; | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; | ||
| 97 | + int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; | ||
| 98 | + int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; | ||
| 99 | + char encodedData[] = null; | ||
| 100 | + | ||
| 101 | + encodedData = new char[numberQuartet * 4]; | ||
| 102 | + | ||
| 103 | + byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; | ||
| 104 | + | ||
| 105 | + int encodedIndex = 0; | ||
| 106 | + int dataIndex = 0; | ||
| 107 | + | ||
| 108 | + for (int i = 0; i < numberTriplets; i++) | ||
| 109 | + { | ||
| 110 | + b1 = binaryData[dataIndex++]; | ||
| 111 | + b2 = binaryData[dataIndex++]; | ||
| 112 | + b3 = binaryData[dataIndex++]; | ||
| 113 | + | ||
| 114 | + l = (byte) (b2 & 0x0f); | ||
| 115 | + k = (byte) (b1 & 0x03); | ||
| 116 | + | ||
| 117 | + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); | ||
| 118 | + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); | ||
| 119 | + byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); | ||
| 120 | + | ||
| 121 | + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; | ||
| 122 | + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; | ||
| 123 | + encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; | ||
| 124 | + encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + // form integral number of 6-bit groups | ||
| 128 | + if (fewerThan24bits == EIGHTBIT) | ||
| 129 | + { | ||
| 130 | + b1 = binaryData[dataIndex]; | ||
| 131 | + k = (byte) (b1 & 0x03); | ||
| 132 | + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); | ||
| 133 | + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; | ||
| 134 | + encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; | ||
| 135 | + encodedData[encodedIndex++] = PAD; | ||
| 136 | + encodedData[encodedIndex++] = PAD; | ||
| 137 | + } | ||
| 138 | + else if (fewerThan24bits == SIXTEENBIT) | ||
| 139 | + { | ||
| 140 | + b1 = binaryData[dataIndex]; | ||
| 141 | + b2 = binaryData[dataIndex + 1]; | ||
| 142 | + l = (byte) (b2 & 0x0f); | ||
| 143 | + k = (byte) (b1 & 0x03); | ||
| 144 | + | ||
| 145 | + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); | ||
| 146 | + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); | ||
| 147 | + | ||
| 148 | + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; | ||
| 149 | + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; | ||
| 150 | + encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; | ||
| 151 | + encodedData[encodedIndex++] = PAD; | ||
| 152 | + } | ||
| 153 | + return new String(encodedData); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + /** | ||
| 157 | + * Decodes Base64 data into octects | ||
| 158 | + * | ||
| 159 | + * @param encoded string containing Base64 data | ||
| 160 | + * @return Array containind decoded data. | ||
| 161 | + */ | ||
| 162 | + public static byte[] decode(String encoded) | ||
| 163 | + { | ||
| 164 | + if (encoded == null) | ||
| 165 | + { | ||
| 166 | + return null; | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + char[] base64Data = encoded.toCharArray(); | ||
| 170 | + // remove white spaces | ||
| 171 | + int len = removeWhiteSpace(base64Data); | ||
| 172 | + | ||
| 173 | + if (len % FOURBYTE != 0) | ||
| 174 | + { | ||
| 175 | + return null;// should be divisible by four | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + int numberQuadruple = (len / FOURBYTE); | ||
| 179 | + | ||
| 180 | + if (numberQuadruple == 0) | ||
| 181 | + { | ||
| 182 | + return new byte[0]; | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + byte decodedData[] = null; | ||
| 186 | + byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; | ||
| 187 | + char d1 = 0, d2 = 0, d3 = 0, d4 = 0; | ||
| 188 | + | ||
| 189 | + int i = 0; | ||
| 190 | + int encodedIndex = 0; | ||
| 191 | + int dataIndex = 0; | ||
| 192 | + decodedData = new byte[(numberQuadruple) * 3]; | ||
| 193 | + | ||
| 194 | + for (; i < numberQuadruple - 1; i++) | ||
| 195 | + { | ||
| 196 | + | ||
| 197 | + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])) | ||
| 198 | + || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) | ||
| 199 | + { | ||
| 200 | + return null; | ||
| 201 | + } // if found "no data" just return null | ||
| 202 | + | ||
| 203 | + b1 = base64Alphabet[d1]; | ||
| 204 | + b2 = base64Alphabet[d2]; | ||
| 205 | + b3 = base64Alphabet[d3]; | ||
| 206 | + b4 = base64Alphabet[d4]; | ||
| 207 | + | ||
| 208 | + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); | ||
| 209 | + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); | ||
| 210 | + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) | ||
| 214 | + { | ||
| 215 | + return null;// if found "no data" just return null | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + b1 = base64Alphabet[d1]; | ||
| 219 | + b2 = base64Alphabet[d2]; | ||
| 220 | + | ||
| 221 | + d3 = base64Data[dataIndex++]; | ||
| 222 | + d4 = base64Data[dataIndex++]; | ||
| 223 | + if (!isData((d3)) || !isData((d4))) | ||
| 224 | + {// Check if they are PAD characters | ||
| 225 | + if (isPad(d3) && isPad(d4)) | ||
| 226 | + { | ||
| 227 | + if ((b2 & 0xf) != 0)// last 4 bits should be zero | ||
| 228 | + { | ||
| 229 | + return null; | ||
| 230 | + } | ||
| 231 | + byte[] tmp = new byte[i * 3 + 1]; | ||
| 232 | + System.arraycopy(decodedData, 0, tmp, 0, i * 3); | ||
| 233 | + tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); | ||
| 234 | + return tmp; | ||
| 235 | + } | ||
| 236 | + else if (!isPad(d3) && isPad(d4)) | ||
| 237 | + { | ||
| 238 | + b3 = base64Alphabet[d3]; | ||
| 239 | + if ((b3 & 0x3) != 0)// last 2 bits should be zero | ||
| 240 | + { | ||
| 241 | + return null; | ||
| 242 | + } | ||
| 243 | + byte[] tmp = new byte[i * 3 + 2]; | ||
| 244 | + System.arraycopy(decodedData, 0, tmp, 0, i * 3); | ||
| 245 | + tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); | ||
| 246 | + tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); | ||
| 247 | + return tmp; | ||
| 248 | + } | ||
| 249 | + else | ||
| 250 | + { | ||
| 251 | + return null; | ||
| 252 | + } | ||
| 253 | + } | ||
| 254 | + else | ||
| 255 | + { // No PAD e.g 3cQl | ||
| 256 | + b3 = base64Alphabet[d3]; | ||
| 257 | + b4 = base64Alphabet[d4]; | ||
| 258 | + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); | ||
| 259 | + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); | ||
| 260 | + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); | ||
| 261 | + | ||
| 262 | + } | ||
| 263 | + return decodedData; | ||
| 264 | + } | ||
| 265 | + | ||
| 266 | + /** | ||
| 267 | + * remove WhiteSpace from MIME containing encoded Base64 data. | ||
| 268 | + * | ||
| 269 | + * @param data the byte array of base64 data (with WS) | ||
| 270 | + * @return the new length | ||
| 271 | + */ | ||
| 272 | + private static int removeWhiteSpace(char[] data) | ||
| 273 | + { | ||
| 274 | + if (data == null) | ||
| 275 | + { | ||
| 276 | + return 0; | ||
| 277 | + } | ||
| 278 | + | ||
| 279 | + // count characters that's not whitespace | ||
| 280 | + int newSize = 0; | ||
| 281 | + int len = data.length; | ||
| 282 | + for (int i = 0; i < len; i++) | ||
| 283 | + { | ||
| 284 | + if (!isWhiteSpace(data[i])) | ||
| 285 | + { | ||
| 286 | + data[newSize++] = data[i]; | ||
| 287 | + } | ||
| 288 | + } | ||
| 289 | + return newSize; | ||
| 290 | + } | ||
| 291 | +} |
| 1 | +package com.zhonglai.luhui.util.sign; import java.nio.charset.StandardCharsets;import java.security.MessageDigest;import java.util.logging.Level;import java.util.logging.Logger; /** * Md5加密方法 * * @author ruoyi */public class Md5Utils{ private static final Logger log = Logger.getLogger(Md5Utils.class.getName()); 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.log(Level.WARNING,"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(StandardCharsets.UTF_8), StandardCharsets.UTF_8); } catch (Exception e) { log.log(Level.WARNING,"not supported charset...{}", e); return s; } }} |
| 1 | +package com.zhonglai.luhui.util.sql; | ||
| 2 | + | ||
| 3 | +import java.util.HashMap; | ||
| 4 | +import java.util.Map; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * Entity基类 | ||
| 8 | + * | ||
| 9 | + * @author ruoyi | ||
| 10 | + */ | ||
| 11 | +public class BaseEntity | ||
| 12 | +{ | ||
| 13 | + private Map<String,Object[]> timeMap; //时间条件(如:{"create_time":[开始时间,结束时间]}) | ||
| 14 | + private String[] keyValue; //模糊匹配的关键字(如:["value","name,no"]) | ||
| 15 | + private Map<String, QueryType> params; //字段对应的比较符号(如:{"id":"EQ"}) | ||
| 16 | + | ||
| 17 | + private String orderBy; //排序(如:"id,name") | ||
| 18 | + | ||
| 19 | + public Map<String, Object[]> getTimeMap() { | ||
| 20 | + return timeMap; | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + public void setTimeMap(Map<String, Object[]> timeMap) { | ||
| 24 | + this.timeMap = timeMap; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + public String[] getKeyValue() { | ||
| 29 | + return keyValue; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + public void setKeyValue(String[] keyValue) { | ||
| 33 | + this.keyValue = keyValue; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + public Map<String, QueryType> getParams() { | ||
| 37 | + return params; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public void setParams(Map<String, QueryType> params) { | ||
| 41 | + this.params = params; | ||
| 42 | + } | ||
| 43 | +} |
| 1 | +package com.zhonglai.luhui.util.sql; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import com.sun.xml.internal.ws.util.UtilException; | ||
| 5 | +import org.apache.commons.lang3.StringUtils; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * sql操作工具类 | ||
| 9 | + * | ||
| 10 | + * @author ruoyi | ||
| 11 | + */ | ||
| 12 | +public class SqlUtil | ||
| 13 | +{ | ||
| 14 | + /** | ||
| 15 | + * 定义常用的 sql关键字 | ||
| 16 | + */ | ||
| 17 | + public static String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare "; | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) | ||
| 21 | + */ | ||
| 22 | + public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 检查字符,防止注入绕过 | ||
| 26 | + */ | ||
| 27 | + public static String escapeOrderBySql(String value) | ||
| 28 | + { | ||
| 29 | + if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) | ||
| 30 | + { | ||
| 31 | + throw new UtilException("参数不符合规范,不能进行查询"); | ||
| 32 | + } | ||
| 33 | + return value; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 验证 order by 语法是否符合规范 | ||
| 38 | + */ | ||
| 39 | + public static boolean isValidOrderBySql(String value) | ||
| 40 | + { | ||
| 41 | + return value.matches(SQL_PATTERN); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * SQL关键字检查 | ||
| 46 | + */ | ||
| 47 | + public static void filterKeyword(String value) | ||
| 48 | + { | ||
| 49 | + if (StringUtils.isEmpty(value)) | ||
| 50 | + { | ||
| 51 | + return; | ||
| 52 | + } | ||
| 53 | + String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|"); | ||
| 54 | + for (String sqlKeyword : sqlKeywords) | ||
| 55 | + { | ||
| 56 | + if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) | ||
| 57 | + { | ||
| 58 | + throw new UtilException("参数存在SQL注入风险"); | ||
| 59 | + } | ||
| 60 | + } | ||
| 61 | + } | ||
| 62 | +} |
| 1 | +package com.zhonglai.luhui.util.uuid; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * ID生成器工具类 | ||
| 5 | + * | ||
| 6 | + * @author ruoyi | ||
| 7 | + */ | ||
| 8 | +public class IdUtils | ||
| 9 | +{ | ||
| 10 | + /** | ||
| 11 | + * 获取随机UUID | ||
| 12 | + * | ||
| 13 | + * @return 随机UUID | ||
| 14 | + */ | ||
| 15 | + public static String randomUUID() | ||
| 16 | + { | ||
| 17 | + return UUID.randomUUID().toString(); | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 简化的UUID,去掉了横线 | ||
| 22 | + * | ||
| 23 | + * @return 简化的UUID,去掉了横线 | ||
| 24 | + */ | ||
| 25 | + public static String simpleUUID() | ||
| 26 | + { | ||
| 27 | + return UUID.randomUUID().toString(true); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID | ||
| 32 | + * | ||
| 33 | + * @return 随机UUID | ||
| 34 | + */ | ||
| 35 | + public static String fastUUID() | ||
| 36 | + { | ||
| 37 | + return UUID.fastUUID().toString(); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID | ||
| 42 | + * | ||
| 43 | + * @return 简化的UUID,去掉了横线 | ||
| 44 | + */ | ||
| 45 | + public static String fastSimpleUUID() | ||
| 46 | + { | ||
| 47 | + return UUID.fastUUID().toString(true); | ||
| 48 | + } | ||
| 49 | +} |
| 1 | +package com.zhonglai.luhui.util.uuid; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import com.zhonglai.luhui.util.DateUtils; | ||
| 5 | +import com.zhonglai.luhui.util.StringUtils; | ||
| 6 | + | ||
| 7 | +import java.util.concurrent.atomic.AtomicInteger; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * @author ruoyi 序列生成类 | ||
| 11 | + */ | ||
| 12 | +public class Seq | ||
| 13 | +{ | ||
| 14 | + // 通用序列类型 | ||
| 15 | + public static final String commSeqType = "COMMON"; | ||
| 16 | + | ||
| 17 | + // 上传序列类型 | ||
| 18 | + public static final String uploadSeqType = "UPLOAD"; | ||
| 19 | + | ||
| 20 | + // 通用接口序列数 | ||
| 21 | + private static AtomicInteger commSeq = new AtomicInteger(1); | ||
| 22 | + | ||
| 23 | + // 上传接口序列数 | ||
| 24 | + private static AtomicInteger uploadSeq = new AtomicInteger(1); | ||
| 25 | + | ||
| 26 | + // 机器标识 | ||
| 27 | + private static String machineCode = "A"; | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * 获取通用序列号 | ||
| 31 | + * | ||
| 32 | + * @return 序列值 | ||
| 33 | + */ | ||
| 34 | + public static String getId() | ||
| 35 | + { | ||
| 36 | + return getId(commSeqType); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串 | ||
| 41 | + * | ||
| 42 | + * @return 序列值 | ||
| 43 | + */ | ||
| 44 | + public static String getId(String type) | ||
| 45 | + { | ||
| 46 | + AtomicInteger atomicInt = commSeq; | ||
| 47 | + if (uploadSeqType.equals(type)) | ||
| 48 | + { | ||
| 49 | + atomicInt = uploadSeq; | ||
| 50 | + } | ||
| 51 | + return getId(atomicInt, 3); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串 | ||
| 56 | + * | ||
| 57 | + * @param atomicInt 序列数 | ||
| 58 | + * @param length 数值长度 | ||
| 59 | + * @return 序列值 | ||
| 60 | + */ | ||
| 61 | + public static String getId(AtomicInteger atomicInt, int length) | ||
| 62 | + { | ||
| 63 | + String result = DateUtils.dateTimeNow(); | ||
| 64 | + result += machineCode; | ||
| 65 | + result += getSeq(atomicInt, length); | ||
| 66 | + return result; | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + /** | ||
| 70 | + * 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数 | ||
| 71 | + * | ||
| 72 | + * @return 序列值 | ||
| 73 | + */ | ||
| 74 | + private synchronized static String getSeq(AtomicInteger atomicInt, int length) | ||
| 75 | + { | ||
| 76 | + // 先取值再+1 | ||
| 77 | + int value = atomicInt.getAndIncrement(); | ||
| 78 | + | ||
| 79 | + // 如果更新后值>=10 的 (length)幂次方则重置为1 | ||
| 80 | + int maxSeq = (int) Math.pow(10, length); | ||
| 81 | + if (atomicInt.get() >= maxSeq) | ||
| 82 | + { | ||
| 83 | + atomicInt.set(1); | ||
| 84 | + } | ||
| 85 | + // 转字符串,用0左补齐 | ||
| 86 | + return StringUtils.padl(value, length); | ||
| 87 | + } | ||
| 88 | +} |
| 1 | +package com.zhonglai.luhui.util.uuid; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import com.sun.xml.internal.ws.util.UtilException; | ||
| 5 | + | ||
| 6 | +import java.security.MessageDigest; | ||
| 7 | +import java.security.NoSuchAlgorithmException; | ||
| 8 | +import java.security.SecureRandom; | ||
| 9 | +import java.util.Random; | ||
| 10 | +import java.util.concurrent.ThreadLocalRandom; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 提供通用唯一识别码(universally unique identifier)(UUID)实现 | ||
| 14 | + * | ||
| 15 | + * @author ruoyi | ||
| 16 | + */ | ||
| 17 | +public final class UUID implements java.io.Serializable, Comparable<UUID> | ||
| 18 | +{ | ||
| 19 | + private static final long serialVersionUID = -1185015143654744140L; | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * SecureRandom 的单例 | ||
| 23 | + * | ||
| 24 | + */ | ||
| 25 | + private static class Holder | ||
| 26 | + { | ||
| 27 | + static final SecureRandom numberGenerator = getSecureRandom(); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + /** 此UUID的最高64有效位 */ | ||
| 31 | + private final long mostSigBits; | ||
| 32 | + | ||
| 33 | + /** 此UUID的最低64有效位 */ | ||
| 34 | + private final long leastSigBits; | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 私有构造 | ||
| 38 | + * | ||
| 39 | + * @param data 数据 | ||
| 40 | + */ | ||
| 41 | + private UUID(byte[] data) | ||
| 42 | + { | ||
| 43 | + long msb = 0; | ||
| 44 | + long lsb = 0; | ||
| 45 | + assert data.length == 16 : "data must be 16 bytes in length"; | ||
| 46 | + for (int i = 0; i < 8; i++) | ||
| 47 | + { | ||
| 48 | + msb = (msb << 8) | (data[i] & 0xff); | ||
| 49 | + } | ||
| 50 | + for (int i = 8; i < 16; i++) | ||
| 51 | + { | ||
| 52 | + lsb = (lsb << 8) | (data[i] & 0xff); | ||
| 53 | + } | ||
| 54 | + this.mostSigBits = msb; | ||
| 55 | + this.leastSigBits = lsb; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * 使用指定的数据构造新的 UUID。 | ||
| 60 | + * | ||
| 61 | + * @param mostSigBits 用于 {@code UUID} 的最高有效 64 位 | ||
| 62 | + * @param leastSigBits 用于 {@code UUID} 的最低有效 64 位 | ||
| 63 | + */ | ||
| 64 | + public UUID(long mostSigBits, long leastSigBits) | ||
| 65 | + { | ||
| 66 | + this.mostSigBits = mostSigBits; | ||
| 67 | + this.leastSigBits = leastSigBits; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。 | ||
| 72 | + * | ||
| 73 | + * @return 随机生成的 {@code UUID} | ||
| 74 | + */ | ||
| 75 | + public static UUID fastUUID() | ||
| 76 | + { | ||
| 77 | + return randomUUID(false); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + /** | ||
| 81 | + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 | ||
| 82 | + * | ||
| 83 | + * @return 随机生成的 {@code UUID} | ||
| 84 | + */ | ||
| 85 | + public static UUID randomUUID() | ||
| 86 | + { | ||
| 87 | + return randomUUID(true); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 | ||
| 92 | + * | ||
| 93 | + * @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能 | ||
| 94 | + * @return 随机生成的 {@code UUID} | ||
| 95 | + */ | ||
| 96 | + public static UUID randomUUID(boolean isSecure) | ||
| 97 | + { | ||
| 98 | + final Random ng = isSecure ? Holder.numberGenerator : getRandom(); | ||
| 99 | + | ||
| 100 | + byte[] randomBytes = new byte[16]; | ||
| 101 | + ng.nextBytes(randomBytes); | ||
| 102 | + randomBytes[6] &= 0x0f; /* clear version */ | ||
| 103 | + randomBytes[6] |= 0x40; /* set to version 4 */ | ||
| 104 | + randomBytes[8] &= 0x3f; /* clear variant */ | ||
| 105 | + randomBytes[8] |= 0x80; /* set to IETF variant */ | ||
| 106 | + return new UUID(randomBytes); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + /** | ||
| 110 | + * 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。 | ||
| 111 | + * | ||
| 112 | + * @param name 用于构造 UUID 的字节数组。 | ||
| 113 | + * | ||
| 114 | + * @return 根据指定数组生成的 {@code UUID} | ||
| 115 | + */ | ||
| 116 | + public static UUID nameUUIDFromBytes(byte[] name) | ||
| 117 | + { | ||
| 118 | + MessageDigest md; | ||
| 119 | + try | ||
| 120 | + { | ||
| 121 | + md = MessageDigest.getInstance("MD5"); | ||
| 122 | + } | ||
| 123 | + catch (NoSuchAlgorithmException nsae) | ||
| 124 | + { | ||
| 125 | + throw new InternalError("MD5 not supported"); | ||
| 126 | + } | ||
| 127 | + byte[] md5Bytes = md.digest(name); | ||
| 128 | + md5Bytes[6] &= 0x0f; /* clear version */ | ||
| 129 | + md5Bytes[6] |= 0x30; /* set to version 3 */ | ||
| 130 | + md5Bytes[8] &= 0x3f; /* clear variant */ | ||
| 131 | + md5Bytes[8] |= 0x80; /* set to IETF variant */ | ||
| 132 | + return new UUID(md5Bytes); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + /** | ||
| 136 | + * 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。 | ||
| 137 | + * | ||
| 138 | + * @param name 指定 {@code UUID} 字符串 | ||
| 139 | + * @return 具有指定值的 {@code UUID} | ||
| 140 | + * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常 | ||
| 141 | + * | ||
| 142 | + */ | ||
| 143 | + public static UUID fromString(String name) | ||
| 144 | + { | ||
| 145 | + String[] components = name.split("-"); | ||
| 146 | + if (components.length != 5) | ||
| 147 | + { | ||
| 148 | + throw new IllegalArgumentException("Invalid UUID string: " + name); | ||
| 149 | + } | ||
| 150 | + for (int i = 0; i < 5; i++) | ||
| 151 | + { | ||
| 152 | + components[i] = "0x" + components[i]; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + long mostSigBits = Long.decode(components[0]).longValue(); | ||
| 156 | + mostSigBits <<= 16; | ||
| 157 | + mostSigBits |= Long.decode(components[1]).longValue(); | ||
| 158 | + mostSigBits <<= 16; | ||
| 159 | + mostSigBits |= Long.decode(components[2]).longValue(); | ||
| 160 | + | ||
| 161 | + long leastSigBits = Long.decode(components[3]).longValue(); | ||
| 162 | + leastSigBits <<= 48; | ||
| 163 | + leastSigBits |= Long.decode(components[4]).longValue(); | ||
| 164 | + | ||
| 165 | + return new UUID(mostSigBits, leastSigBits); | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + /** | ||
| 169 | + * 返回此 UUID 的 128 位值中的最低有效 64 位。 | ||
| 170 | + * | ||
| 171 | + * @return 此 UUID 的 128 位值中的最低有效 64 位。 | ||
| 172 | + */ | ||
| 173 | + public long getLeastSignificantBits() | ||
| 174 | + { | ||
| 175 | + return leastSigBits; | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + /** | ||
| 179 | + * 返回此 UUID 的 128 位值中的最高有效 64 位。 | ||
| 180 | + * | ||
| 181 | + * @return 此 UUID 的 128 位值中最高有效 64 位。 | ||
| 182 | + */ | ||
| 183 | + public long getMostSignificantBits() | ||
| 184 | + { | ||
| 185 | + return mostSigBits; | ||
| 186 | + } | ||
| 187 | + | ||
| 188 | + /** | ||
| 189 | + * 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。 | ||
| 190 | + * <p> | ||
| 191 | + * 版本号具有以下含意: | ||
| 192 | + * <ul> | ||
| 193 | + * <li>1 基于时间的 UUID | ||
| 194 | + * <li>2 DCE 安全 UUID | ||
| 195 | + * <li>3 基于名称的 UUID | ||
| 196 | + * <li>4 随机生成的 UUID | ||
| 197 | + * </ul> | ||
| 198 | + * | ||
| 199 | + * @return 此 {@code UUID} 的版本号 | ||
| 200 | + */ | ||
| 201 | + public int version() | ||
| 202 | + { | ||
| 203 | + // Version is bits masked by 0x000000000000F000 in MS long | ||
| 204 | + return (int) ((mostSigBits >> 12) & 0x0f); | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + /** | ||
| 208 | + * 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。 | ||
| 209 | + * <p> | ||
| 210 | + * 变体号具有以下含意: | ||
| 211 | + * <ul> | ||
| 212 | + * <li>0 为 NCS 向后兼容保留 | ||
| 213 | + * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于此类 | ||
| 214 | + * <li>6 保留,微软向后兼容 | ||
| 215 | + * <li>7 保留供以后定义使用 | ||
| 216 | + * </ul> | ||
| 217 | + * | ||
| 218 | + * @return 此 {@code UUID} 相关联的变体号 | ||
| 219 | + */ | ||
| 220 | + public int variant() | ||
| 221 | + { | ||
| 222 | + // This field is composed of a varying number of bits. | ||
| 223 | + // 0 - - Reserved for NCS backward compatibility | ||
| 224 | + // 1 0 - The IETF aka Leach-Salz variant (used by this class) | ||
| 225 | + // 1 1 0 Reserved, Microsoft backward compatibility | ||
| 226 | + // 1 1 1 Reserved for future definition. | ||
| 227 | + return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); | ||
| 228 | + } | ||
| 229 | + | ||
| 230 | + /** | ||
| 231 | + * 与此 UUID 相关联的时间戳值。 | ||
| 232 | + * | ||
| 233 | + * <p> | ||
| 234 | + * 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br> | ||
| 235 | + * 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。 | ||
| 236 | + * | ||
| 237 | + * <p> | ||
| 238 | + * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br> | ||
| 239 | + * 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 | ||
| 240 | + * | ||
| 241 | + * @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。 | ||
| 242 | + */ | ||
| 243 | + public long timestamp() throws UnsupportedOperationException | ||
| 244 | + { | ||
| 245 | + checkTimeBase(); | ||
| 246 | + return (mostSigBits & 0x0FFFL) << 48// | ||
| 247 | + | ((mostSigBits >> 16) & 0x0FFFFL) << 32// | ||
| 248 | + | mostSigBits >>> 32; | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + /** | ||
| 252 | + * 与此 UUID 相关联的时钟序列值。 | ||
| 253 | + * | ||
| 254 | + * <p> | ||
| 255 | + * 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。 | ||
| 256 | + * <p> | ||
| 257 | + * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出 | ||
| 258 | + * UnsupportedOperationException。 | ||
| 259 | + * | ||
| 260 | + * @return 此 {@code UUID} 的时钟序列 | ||
| 261 | + * | ||
| 262 | + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 | ||
| 263 | + */ | ||
| 264 | + public int clockSequence() throws UnsupportedOperationException | ||
| 265 | + { | ||
| 266 | + checkTimeBase(); | ||
| 267 | + return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); | ||
| 268 | + } | ||
| 269 | + | ||
| 270 | + /** | ||
| 271 | + * 与此 UUID 相关的节点值。 | ||
| 272 | + * | ||
| 273 | + * <p> | ||
| 274 | + * 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。 | ||
| 275 | + * <p> | ||
| 276 | + * 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br> | ||
| 277 | + * 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 | ||
| 278 | + * | ||
| 279 | + * @return 此 {@code UUID} 的节点值 | ||
| 280 | + * | ||
| 281 | + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 | ||
| 282 | + */ | ||
| 283 | + public long node() throws UnsupportedOperationException | ||
| 284 | + { | ||
| 285 | + checkTimeBase(); | ||
| 286 | + return leastSigBits & 0x0000FFFFFFFFFFFFL; | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + /** | ||
| 290 | + * 返回此{@code UUID} 的字符串表现形式。 | ||
| 291 | + * | ||
| 292 | + * <p> | ||
| 293 | + * UUID 的字符串表示形式由此 BNF 描述: | ||
| 294 | + * | ||
| 295 | + * <pre> | ||
| 296 | + * {@code | ||
| 297 | + * UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node> | ||
| 298 | + * time_low = 4*<hexOctet> | ||
| 299 | + * time_mid = 2*<hexOctet> | ||
| 300 | + * time_high_and_version = 2*<hexOctet> | ||
| 301 | + * variant_and_sequence = 2*<hexOctet> | ||
| 302 | + * node = 6*<hexOctet> | ||
| 303 | + * hexOctet = <hexDigit><hexDigit> | ||
| 304 | + * hexDigit = [0-9a-fA-F] | ||
| 305 | + * } | ||
| 306 | + * </pre> | ||
| 307 | + * | ||
| 308 | + * </blockquote> | ||
| 309 | + * | ||
| 310 | + * @return 此{@code UUID} 的字符串表现形式 | ||
| 311 | + * @see #toString(boolean) | ||
| 312 | + */ | ||
| 313 | + @Override | ||
| 314 | + public String toString() | ||
| 315 | + { | ||
| 316 | + return toString(false); | ||
| 317 | + } | ||
| 318 | + | ||
| 319 | + /** | ||
| 320 | + * 返回此{@code UUID} 的字符串表现形式。 | ||
| 321 | + * | ||
| 322 | + * <p> | ||
| 323 | + * UUID 的字符串表示形式由此 BNF 描述: | ||
| 324 | + * | ||
| 325 | + * <pre> | ||
| 326 | + * {@code | ||
| 327 | + * UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node> | ||
| 328 | + * time_low = 4*<hexOctet> | ||
| 329 | + * time_mid = 2*<hexOctet> | ||
| 330 | + * time_high_and_version = 2*<hexOctet> | ||
| 331 | + * variant_and_sequence = 2*<hexOctet> | ||
| 332 | + * node = 6*<hexOctet> | ||
| 333 | + * hexOctet = <hexDigit><hexDigit> | ||
| 334 | + * hexDigit = [0-9a-fA-F] | ||
| 335 | + * } | ||
| 336 | + * </pre> | ||
| 337 | + * | ||
| 338 | + * </blockquote> | ||
| 339 | + * | ||
| 340 | + * @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串 | ||
| 341 | + * @return 此{@code UUID} 的字符串表现形式 | ||
| 342 | + */ | ||
| 343 | + public String toString(boolean isSimple) | ||
| 344 | + { | ||
| 345 | + final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); | ||
| 346 | + // time_low | ||
| 347 | + builder.append(digits(mostSigBits >> 32, 8)); | ||
| 348 | + if (!isSimple) | ||
| 349 | + { | ||
| 350 | + builder.append('-'); | ||
| 351 | + } | ||
| 352 | + // time_mid | ||
| 353 | + builder.append(digits(mostSigBits >> 16, 4)); | ||
| 354 | + if (!isSimple) | ||
| 355 | + { | ||
| 356 | + builder.append('-'); | ||
| 357 | + } | ||
| 358 | + // time_high_and_version | ||
| 359 | + builder.append(digits(mostSigBits, 4)); | ||
| 360 | + if (!isSimple) | ||
| 361 | + { | ||
| 362 | + builder.append('-'); | ||
| 363 | + } | ||
| 364 | + // variant_and_sequence | ||
| 365 | + builder.append(digits(leastSigBits >> 48, 4)); | ||
| 366 | + if (!isSimple) | ||
| 367 | + { | ||
| 368 | + builder.append('-'); | ||
| 369 | + } | ||
| 370 | + // node | ||
| 371 | + builder.append(digits(leastSigBits, 12)); | ||
| 372 | + | ||
| 373 | + return builder.toString(); | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | + /** | ||
| 377 | + * 返回此 UUID 的哈希码。 | ||
| 378 | + * | ||
| 379 | + * @return UUID 的哈希码值。 | ||
| 380 | + */ | ||
| 381 | + @Override | ||
| 382 | + public int hashCode() | ||
| 383 | + { | ||
| 384 | + long hilo = mostSigBits ^ leastSigBits; | ||
| 385 | + return ((int) (hilo >> 32)) ^ (int) hilo; | ||
| 386 | + } | ||
| 387 | + | ||
| 388 | + /** | ||
| 389 | + * 将此对象与指定对象比较。 | ||
| 390 | + * <p> | ||
| 391 | + * 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。 | ||
| 392 | + * | ||
| 393 | + * @param obj 要与之比较的对象 | ||
| 394 | + * | ||
| 395 | + * @return 如果对象相同,则返回 {@code true};否则返回 {@code false} | ||
| 396 | + */ | ||
| 397 | + @Override | ||
| 398 | + public boolean equals(Object obj) | ||
| 399 | + { | ||
| 400 | + if ((null == obj) || (obj.getClass() != UUID.class)) | ||
| 401 | + { | ||
| 402 | + return false; | ||
| 403 | + } | ||
| 404 | + UUID id = (UUID) obj; | ||
| 405 | + return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); | ||
| 406 | + } | ||
| 407 | + | ||
| 408 | + // Comparison Operations | ||
| 409 | + | ||
| 410 | + /** | ||
| 411 | + * 将此 UUID 与指定的 UUID 比较。 | ||
| 412 | + * | ||
| 413 | + * <p> | ||
| 414 | + * 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。 | ||
| 415 | + * | ||
| 416 | + * @param val 与此 UUID 比较的 UUID | ||
| 417 | + * | ||
| 418 | + * @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。 | ||
| 419 | + * | ||
| 420 | + */ | ||
| 421 | + @Override | ||
| 422 | + public int compareTo(UUID val) | ||
| 423 | + { | ||
| 424 | + // The ordering is intentionally set up so that the UUIDs | ||
| 425 | + // can simply be numerically compared as two numbers | ||
| 426 | + return (this.mostSigBits < val.mostSigBits ? -1 : // | ||
| 427 | + (this.mostSigBits > val.mostSigBits ? 1 : // | ||
| 428 | + (this.leastSigBits < val.leastSigBits ? -1 : // | ||
| 429 | + (this.leastSigBits > val.leastSigBits ? 1 : // | ||
| 430 | + 0)))); | ||
| 431 | + } | ||
| 432 | + | ||
| 433 | + // ------------------------------------------------------------------------------------------------------------------- | ||
| 434 | + // Private method start | ||
| 435 | + /** | ||
| 436 | + * 返回指定数字对应的hex值 | ||
| 437 | + * | ||
| 438 | + * @param val 值 | ||
| 439 | + * @param digits 位 | ||
| 440 | + * @return 值 | ||
| 441 | + */ | ||
| 442 | + private static String digits(long val, int digits) | ||
| 443 | + { | ||
| 444 | + long hi = 1L << (digits * 4); | ||
| 445 | + return Long.toHexString(hi | (val & (hi - 1))).substring(1); | ||
| 446 | + } | ||
| 447 | + | ||
| 448 | + /** | ||
| 449 | + * 检查是否为time-based版本UUID | ||
| 450 | + */ | ||
| 451 | + private void checkTimeBase() | ||
| 452 | + { | ||
| 453 | + if (version() != 1) | ||
| 454 | + { | ||
| 455 | + throw new UnsupportedOperationException("Not a time-based UUID"); | ||
| 456 | + } | ||
| 457 | + } | ||
| 458 | + | ||
| 459 | + /** | ||
| 460 | + * 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG) | ||
| 461 | + * | ||
| 462 | + * @return {@link SecureRandom} | ||
| 463 | + */ | ||
| 464 | + public static SecureRandom getSecureRandom() | ||
| 465 | + { | ||
| 466 | + try | ||
| 467 | + { | ||
| 468 | + return SecureRandom.getInstance("SHA1PRNG"); | ||
| 469 | + } | ||
| 470 | + catch (NoSuchAlgorithmException e) | ||
| 471 | + { | ||
| 472 | + throw new UtilException(e); | ||
| 473 | + } | ||
| 474 | + } | ||
| 475 | + | ||
| 476 | + /** | ||
| 477 | + * 获取随机数生成器对象<br> | ||
| 478 | + * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。 | ||
| 479 | + * | ||
| 480 | + * @return {@link ThreadLocalRandom} | ||
| 481 | + */ | ||
| 482 | + public static ThreadLocalRandom getRandom() | ||
| 483 | + { | ||
| 484 | + return ThreadLocalRandom.current(); | ||
| 485 | + } | ||
| 486 | +} |
| 1 | +package com.zhonglai.luhui.util.xss; | ||
| 2 | + | ||
| 3 | +import javax.validation.Constraint; | ||
| 4 | +import javax.validation.Payload; | ||
| 5 | +import java.lang.annotation.ElementType; | ||
| 6 | +import java.lang.annotation.Retention; | ||
| 7 | +import java.lang.annotation.RetentionPolicy; | ||
| 8 | +import java.lang.annotation.Target; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 自定义xss校验注解 | ||
| 12 | + * | ||
| 13 | + * @author ruoyi | ||
| 14 | + */ | ||
| 15 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 16 | +@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER }) | ||
| 17 | +@Constraint(validatedBy = { XssValidator.class }) | ||
| 18 | +public @interface Xss | ||
| 19 | +{ | ||
| 20 | + String message() | ||
| 21 | + | ||
| 22 | + default "不允许任何脚本运行"; | ||
| 23 | + | ||
| 24 | + Class<?>[] groups() default {}; | ||
| 25 | + | ||
| 26 | + Class<? extends Payload>[] payload() default {}; | ||
| 27 | +} |
| 1 | +package com.zhonglai.luhui.util.xss; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import org.apache.commons.lang3.StringUtils; | ||
| 5 | + | ||
| 6 | +import javax.validation.ConstraintValidator; | ||
| 7 | +import javax.validation.ConstraintValidatorContext; | ||
| 8 | +import java.util.regex.Matcher; | ||
| 9 | +import java.util.regex.Pattern; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 自定义xss校验注解实现 | ||
| 13 | + * | ||
| 14 | + * @author ruoyi | ||
| 15 | + */ | ||
| 16 | +public class XssValidator implements ConstraintValidator<Xss, String> | ||
| 17 | +{ | ||
| 18 | + private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />"; | ||
| 19 | + | ||
| 20 | + @Override | ||
| 21 | + public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) | ||
| 22 | + { | ||
| 23 | + if (StringUtils.isBlank(value)) | ||
| 24 | + { | ||
| 25 | + return true; | ||
| 26 | + } | ||
| 27 | + return !containsHtml(value); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + public static boolean containsHtml(String value) | ||
| 31 | + { | ||
| 32 | + Pattern pattern = Pattern.compile(HTML_PATTERN); | ||
| 33 | + Matcher matcher = pattern.matcher(value); | ||
| 34 | + return matcher.matches(); | ||
| 35 | + } | ||
| 36 | +} |
lh-common/lh-domain/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 5 | + <modelVersion>4.0.0</modelVersion> | ||
| 6 | + <parent> | ||
| 7 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 8 | + <artifactId>lh-common</artifactId> | ||
| 9 | + <version>1.0.0</version> | ||
| 10 | + </parent> | ||
| 11 | + | ||
| 12 | + <artifactId>lh-domain</artifactId> | ||
| 13 | + <description>数据库表实体类</description> | ||
| 14 | + | ||
| 15 | + <properties> | ||
| 16 | + <maven.compiler.source>8</maven.compiler.source> | ||
| 17 | + <maven.compiler.target>8</maven.compiler.target> | ||
| 18 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| 19 | + </properties> | ||
| 20 | + | ||
| 21 | + <dependencies> | ||
| 22 | + <!-- 文档 --> | ||
| 23 | + <dependency > | ||
| 24 | + <groupId>io.springfox</groupId> | ||
| 25 | + <artifactId>springfox-swagger2</artifactId> | ||
| 26 | + <version>${swagger.version}</version> | ||
| 27 | + <exclusions> | ||
| 28 | + <exclusion> | ||
| 29 | + <groupId>io.swagger</groupId> | ||
| 30 | + <artifactId>swagger-models</artifactId> | ||
| 31 | + </exclusion> | ||
| 32 | + <exclusion> | ||
| 33 | + <groupId>com.google.guava</groupId> | ||
| 34 | + <artifactId>guava</artifactId> | ||
| 35 | + </exclusion> | ||
| 36 | + </exclusions> | ||
| 37 | + </dependency> | ||
| 38 | + <!--常用工具类 --> | ||
| 39 | + <dependency> | ||
| 40 | + <groupId>org.apache.commons</groupId> | ||
| 41 | + <artifactId>commons-lang3</artifactId> | ||
| 42 | + </dependency> | ||
| 43 | + <dependency> | ||
| 44 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 45 | + <artifactId>lh-common-util</artifactId> | ||
| 46 | + </dependency> | ||
| 47 | + </dependencies> | ||
| 48 | +</project> |
| 1 | +package com.zhonglai.luhui.domain.cb; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import com.zhonglai.luhui.util.sql.BaseEntity; | ||
| 5 | +import io.swagger.annotations.ApiModel; | ||
| 6 | +import io.swagger.annotations.ApiModelProperty; | ||
| 7 | +import org.apache.commons.lang3.builder.ToStringBuilder; | ||
| 8 | +import org.apache.commons.lang3.builder.ToStringStyle; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 标粗结转成本表对象 cb_bold_closing_cost | ||
| 12 | + * | ||
| 13 | + * @author 钟来 | ||
| 14 | + * @date 2024-04-11 | ||
| 15 | + */ | ||
| 16 | +@ApiModel("标粗结转成本表") | ||
| 17 | +public class CbBoldClosingCost extends BaseEntity | ||
| 18 | +{ | ||
| 19 | + private static final long serialVersionUID = 1L; | ||
| 20 | + | ||
| 21 | + /** 主键ID,自增长 */ | ||
| 22 | + @ApiModelProperty("主键ID,自增长") | ||
| 23 | + private Integer id; | ||
| 24 | + | ||
| 25 | + /** 养殖场 */ | ||
| 26 | + @ApiModelProperty("养殖场") | ||
| 27 | + private String farm_name; | ||
| 28 | + | ||
| 29 | + /** 养殖造次 */ | ||
| 30 | + @ApiModelProperty("养殖造次") | ||
| 31 | + private String breeding_round; | ||
| 32 | + | ||
| 33 | + /** 养殖区域 */ | ||
| 34 | + @ApiModelProperty("养殖区域") | ||
| 35 | + private String breeding_area; | ||
| 36 | + | ||
| 37 | + /** 塘口/箱号 */ | ||
| 38 | + @ApiModelProperty("塘口/箱号") | ||
| 39 | + private String pond_or_box; | ||
| 40 | + | ||
| 41 | + /** 养殖品种 */ | ||
| 42 | + @ApiModelProperty("养殖品种") | ||
| 43 | + private String breeding_species; | ||
| 44 | + | ||
| 45 | + /** 分苗日期 */ | ||
| 46 | + @ApiModelProperty("分苗日期") | ||
| 47 | + private java.util.Date seedling_info_date; | ||
| 48 | + | ||
| 49 | + /** 分苗数量 */ | ||
| 50 | + @ApiModelProperty("分苗数量") | ||
| 51 | + private java.math.BigDecimal seedling_quantity; | ||
| 52 | + | ||
| 53 | + /** 分苗重量 */ | ||
| 54 | + @ApiModelProperty("分苗重量") | ||
| 55 | + private java.math.BigDecimal seedling_weight; | ||
| 56 | + | ||
| 57 | + /** 分苗规格 */ | ||
| 58 | + @ApiModelProperty("分苗规格") | ||
| 59 | + private String seedling_specification; | ||
| 60 | + | ||
| 61 | + /** 变动成本 */ | ||
| 62 | + @ApiModelProperty("变动成本") | ||
| 63 | + private java.math.BigDecimal variable_costs; | ||
| 64 | + | ||
| 65 | + /** 种苗成本 */ | ||
| 66 | + @ApiModelProperty("种苗成本") | ||
| 67 | + private java.math.BigDecimal seedling_cost; | ||
| 68 | + | ||
| 69 | + /** 饲料数量(kg) */ | ||
| 70 | + @ApiModelProperty("饲料数量(kg)") | ||
| 71 | + private java.math.BigDecimal feed_quantity; | ||
| 72 | + | ||
| 73 | + /** 饲料金额 */ | ||
| 74 | + @ApiModelProperty("饲料金额") | ||
| 75 | + private java.math.BigDecimal feed_amount; | ||
| 76 | + | ||
| 77 | + /** 动保 */ | ||
| 78 | + @ApiModelProperty("动保") | ||
| 79 | + private java.math.BigDecimal animal_health_protection; | ||
| 80 | + | ||
| 81 | + /** 电费 */ | ||
| 82 | + @ApiModelProperty("电费") | ||
| 83 | + private java.math.BigDecimal electricity_fee; | ||
| 84 | + | ||
| 85 | + /** 人工 */ | ||
| 86 | + @ApiModelProperty("人工") | ||
| 87 | + private java.math.BigDecimal labor_cost; | ||
| 88 | + | ||
| 89 | + /** 低值易耗品 */ | ||
| 90 | + @ApiModelProperty("低值易耗品") | ||
| 91 | + private java.math.BigDecimal consumables_cost; | ||
| 92 | + | ||
| 93 | + /** 拉网费 */ | ||
| 94 | + @ApiModelProperty("拉网费") | ||
| 95 | + private java.math.BigDecimal netting_fee; | ||
| 96 | + | ||
| 97 | + /** 折旧与摊销 */ | ||
| 98 | + @ApiModelProperty("折旧与摊销") | ||
| 99 | + private java.math.BigDecimal depreciation_and_amortization; | ||
| 100 | + | ||
| 101 | + /** 修理费 */ | ||
| 102 | + @ApiModelProperty("修理费") | ||
| 103 | + private java.math.BigDecimal repair_fee; | ||
| 104 | + | ||
| 105 | + /** 燃料费 */ | ||
| 106 | + @ApiModelProperty("燃料费") | ||
| 107 | + private java.math.BigDecimal fuel_fee; | ||
| 108 | + | ||
| 109 | + /** 租赁费 */ | ||
| 110 | + @ApiModelProperty("租赁费") | ||
| 111 | + private java.math.BigDecimal lease_fee; | ||
| 112 | + | ||
| 113 | + /** 其他公摊 */ | ||
| 114 | + @ApiModelProperty("其他公摊") | ||
| 115 | + private java.math.BigDecimal other_shared_costs; | ||
| 116 | + | ||
| 117 | + /** 定额费用 */ | ||
| 118 | + @ApiModelProperty("定额费用") | ||
| 119 | + private java.math.BigDecimal fixed_costs; | ||
| 120 | + | ||
| 121 | + /** 网箱折旧费 */ | ||
| 122 | + @ApiModelProperty("网箱折旧费") | ||
| 123 | + private java.math.BigDecimal cage_depreciation_fee; | ||
| 124 | + | ||
| 125 | + /** 网箱管理费 */ | ||
| 126 | + @ApiModelProperty("网箱管理费") | ||
| 127 | + private java.math.BigDecimal cage_management_fee; | ||
| 128 | + | ||
| 129 | + /** 海域费 */ | ||
| 130 | + @ApiModelProperty("海域费") | ||
| 131 | + private java.math.BigDecimal sea_area_fee; | ||
| 132 | + | ||
| 133 | + /** 塘租 */ | ||
| 134 | + @ApiModelProperty("塘租") | ||
| 135 | + private java.math.BigDecimal pond_rent; | ||
| 136 | + | ||
| 137 | + /** 合计 */ | ||
| 138 | + @ApiModelProperty("合计") | ||
| 139 | + private java.math.BigDecimal total_cost; | ||
| 140 | + | ||
| 141 | + public void setId(Integer id) | ||
| 142 | + { | ||
| 143 | + this.id = id; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + public Integer getId() | ||
| 147 | + { | ||
| 148 | + return id; | ||
| 149 | + } | ||
| 150 | + public void setFarm_name(String farm_name) | ||
| 151 | + { | ||
| 152 | + this.farm_name = farm_name; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + public String getFarm_name() | ||
| 156 | + { | ||
| 157 | + return farm_name; | ||
| 158 | + } | ||
| 159 | + public void setBreeding_round(String breeding_round) | ||
| 160 | + { | ||
| 161 | + this.breeding_round = breeding_round; | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + public String getBreeding_round() | ||
| 165 | + { | ||
| 166 | + return breeding_round; | ||
| 167 | + } | ||
| 168 | + public void setBreeding_area(String breeding_area) | ||
| 169 | + { | ||
| 170 | + this.breeding_area = breeding_area; | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + public String getBreeding_area() | ||
| 174 | + { | ||
| 175 | + return breeding_area; | ||
| 176 | + } | ||
| 177 | + public void setPond_or_box(String pond_or_box) | ||
| 178 | + { | ||
| 179 | + this.pond_or_box = pond_or_box; | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + public String getPond_or_box() | ||
| 183 | + { | ||
| 184 | + return pond_or_box; | ||
| 185 | + } | ||
| 186 | + public void setBreeding_species(String breeding_species) | ||
| 187 | + { | ||
| 188 | + this.breeding_species = breeding_species; | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + public String getBreeding_species() | ||
| 192 | + { | ||
| 193 | + return breeding_species; | ||
| 194 | + } | ||
| 195 | + public void setSeedling_info_date(java.util.Date seedling_info_date) | ||
| 196 | + { | ||
| 197 | + this.seedling_info_date = seedling_info_date; | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + public java.util.Date getSeedling_info_date() | ||
| 201 | + { | ||
| 202 | + return seedling_info_date; | ||
| 203 | + } | ||
| 204 | + public void setSeedling_quantity(java.math.BigDecimal seedling_quantity) | ||
| 205 | + { | ||
| 206 | + this.seedling_quantity = seedling_quantity; | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + public java.math.BigDecimal getSeedling_quantity() | ||
| 210 | + { | ||
| 211 | + return seedling_quantity; | ||
| 212 | + } | ||
| 213 | + public void setSeedling_weight(java.math.BigDecimal seedling_weight) | ||
| 214 | + { | ||
| 215 | + this.seedling_weight = seedling_weight; | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + public java.math.BigDecimal getSeedling_weight() | ||
| 219 | + { | ||
| 220 | + return seedling_weight; | ||
| 221 | + } | ||
| 222 | + public void setSeedling_specification(String seedling_specification) | ||
| 223 | + { | ||
| 224 | + this.seedling_specification = seedling_specification; | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + public String getSeedling_specification() | ||
| 228 | + { | ||
| 229 | + return seedling_specification; | ||
| 230 | + } | ||
| 231 | + public void setVariable_costs(java.math.BigDecimal variable_costs) | ||
| 232 | + { | ||
| 233 | + this.variable_costs = variable_costs; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + public java.math.BigDecimal getVariable_costs() | ||
| 237 | + { | ||
| 238 | + return variable_costs; | ||
| 239 | + } | ||
| 240 | + public void setSeedling_cost(java.math.BigDecimal seedling_cost) | ||
| 241 | + { | ||
| 242 | + this.seedling_cost = seedling_cost; | ||
| 243 | + } | ||
| 244 | + | ||
| 245 | + public java.math.BigDecimal getSeedling_cost() | ||
| 246 | + { | ||
| 247 | + return seedling_cost; | ||
| 248 | + } | ||
| 249 | + public void setFeed_quantity(java.math.BigDecimal feed_quantity) | ||
| 250 | + { | ||
| 251 | + this.feed_quantity = feed_quantity; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + public java.math.BigDecimal getFeed_quantity() | ||
| 255 | + { | ||
| 256 | + return feed_quantity; | ||
| 257 | + } | ||
| 258 | + public void setFeed_amount(java.math.BigDecimal feed_amount) | ||
| 259 | + { | ||
| 260 | + this.feed_amount = feed_amount; | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + public java.math.BigDecimal getFeed_amount() | ||
| 264 | + { | ||
| 265 | + return feed_amount; | ||
| 266 | + } | ||
| 267 | + public void setAnimal_health_protection(java.math.BigDecimal animal_health_protection) | ||
| 268 | + { | ||
| 269 | + this.animal_health_protection = animal_health_protection; | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + public java.math.BigDecimal getAnimal_health_protection() | ||
| 273 | + { | ||
| 274 | + return animal_health_protection; | ||
| 275 | + } | ||
| 276 | + public void setElectricity_fee(java.math.BigDecimal electricity_fee) | ||
| 277 | + { | ||
| 278 | + this.electricity_fee = electricity_fee; | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + public java.math.BigDecimal getElectricity_fee() | ||
| 282 | + { | ||
| 283 | + return electricity_fee; | ||
| 284 | + } | ||
| 285 | + public void setLabor_cost(java.math.BigDecimal labor_cost) | ||
| 286 | + { | ||
| 287 | + this.labor_cost = labor_cost; | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + public java.math.BigDecimal getLabor_cost() | ||
| 291 | + { | ||
| 292 | + return labor_cost; | ||
| 293 | + } | ||
| 294 | + public void setConsumables_cost(java.math.BigDecimal consumables_cost) | ||
| 295 | + { | ||
| 296 | + this.consumables_cost = consumables_cost; | ||
| 297 | + } | ||
| 298 | + | ||
| 299 | + public java.math.BigDecimal getConsumables_cost() | ||
| 300 | + { | ||
| 301 | + return consumables_cost; | ||
| 302 | + } | ||
| 303 | + public void setNetting_fee(java.math.BigDecimal netting_fee) | ||
| 304 | + { | ||
| 305 | + this.netting_fee = netting_fee; | ||
| 306 | + } | ||
| 307 | + | ||
| 308 | + public java.math.BigDecimal getNetting_fee() | ||
| 309 | + { | ||
| 310 | + return netting_fee; | ||
| 311 | + } | ||
| 312 | + public void setDepreciation_and_amortization(java.math.BigDecimal depreciation_and_amortization) | ||
| 313 | + { | ||
| 314 | + this.depreciation_and_amortization = depreciation_and_amortization; | ||
| 315 | + } | ||
| 316 | + | ||
| 317 | + public java.math.BigDecimal getDepreciation_and_amortization() | ||
| 318 | + { | ||
| 319 | + return depreciation_and_amortization; | ||
| 320 | + } | ||
| 321 | + public void setRepair_fee(java.math.BigDecimal repair_fee) | ||
| 322 | + { | ||
| 323 | + this.repair_fee = repair_fee; | ||
| 324 | + } | ||
| 325 | + | ||
| 326 | + public java.math.BigDecimal getRepair_fee() | ||
| 327 | + { | ||
| 328 | + return repair_fee; | ||
| 329 | + } | ||
| 330 | + public void setFuel_fee(java.math.BigDecimal fuel_fee) | ||
| 331 | + { | ||
| 332 | + this.fuel_fee = fuel_fee; | ||
| 333 | + } | ||
| 334 | + | ||
| 335 | + public java.math.BigDecimal getFuel_fee() | ||
| 336 | + { | ||
| 337 | + return fuel_fee; | ||
| 338 | + } | ||
| 339 | + public void setLease_fee(java.math.BigDecimal lease_fee) | ||
| 340 | + { | ||
| 341 | + this.lease_fee = lease_fee; | ||
| 342 | + } | ||
| 343 | + | ||
| 344 | + public java.math.BigDecimal getLease_fee() | ||
| 345 | + { | ||
| 346 | + return lease_fee; | ||
| 347 | + } | ||
| 348 | + public void setOther_shared_costs(java.math.BigDecimal other_shared_costs) | ||
| 349 | + { | ||
| 350 | + this.other_shared_costs = other_shared_costs; | ||
| 351 | + } | ||
| 352 | + | ||
| 353 | + public java.math.BigDecimal getOther_shared_costs() | ||
| 354 | + { | ||
| 355 | + return other_shared_costs; | ||
| 356 | + } | ||
| 357 | + public void setFixed_costs(java.math.BigDecimal fixed_costs) | ||
| 358 | + { | ||
| 359 | + this.fixed_costs = fixed_costs; | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + public java.math.BigDecimal getFixed_costs() | ||
| 363 | + { | ||
| 364 | + return fixed_costs; | ||
| 365 | + } | ||
| 366 | + public void setCage_depreciation_fee(java.math.BigDecimal cage_depreciation_fee) | ||
| 367 | + { | ||
| 368 | + this.cage_depreciation_fee = cage_depreciation_fee; | ||
| 369 | + } | ||
| 370 | + | ||
| 371 | + public java.math.BigDecimal getCage_depreciation_fee() | ||
| 372 | + { | ||
| 373 | + return cage_depreciation_fee; | ||
| 374 | + } | ||
| 375 | + public void setCage_management_fee(java.math.BigDecimal cage_management_fee) | ||
| 376 | + { | ||
| 377 | + this.cage_management_fee = cage_management_fee; | ||
| 378 | + } | ||
| 379 | + | ||
| 380 | + public java.math.BigDecimal getCage_management_fee() | ||
| 381 | + { | ||
| 382 | + return cage_management_fee; | ||
| 383 | + } | ||
| 384 | + public void setSea_area_fee(java.math.BigDecimal sea_area_fee) | ||
| 385 | + { | ||
| 386 | + this.sea_area_fee = sea_area_fee; | ||
| 387 | + } | ||
| 388 | + | ||
| 389 | + public java.math.BigDecimal getSea_area_fee() | ||
| 390 | + { | ||
| 391 | + return sea_area_fee; | ||
| 392 | + } | ||
| 393 | + public void setPond_rent(java.math.BigDecimal pond_rent) | ||
| 394 | + { | ||
| 395 | + this.pond_rent = pond_rent; | ||
| 396 | + } | ||
| 397 | + | ||
| 398 | + public java.math.BigDecimal getPond_rent() | ||
| 399 | + { | ||
| 400 | + return pond_rent; | ||
| 401 | + } | ||
| 402 | + public void setTotal_cost(java.math.BigDecimal total_cost) | ||
| 403 | + { | ||
| 404 | + this.total_cost = total_cost; | ||
| 405 | + } | ||
| 406 | + | ||
| 407 | + public java.math.BigDecimal getTotal_cost() | ||
| 408 | + { | ||
| 409 | + return total_cost; | ||
| 410 | + } | ||
| 411 | + | ||
| 412 | + @Override | ||
| 413 | + public String toString() { | ||
| 414 | + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) | ||
| 415 | + .append("id", getId()) | ||
| 416 | + .append("farm_name", getFarm_name()) | ||
| 417 | + .append("breeding_round", getBreeding_round()) | ||
| 418 | + .append("breeding_area", getBreeding_area()) | ||
| 419 | + .append("pond_or_box", getPond_or_box()) | ||
| 420 | + .append("breeding_species", getBreeding_species()) | ||
| 421 | + .append("seedling_info_date", getSeedling_info_date()) | ||
| 422 | + .append("seedling_quantity", getSeedling_quantity()) | ||
| 423 | + .append("seedling_weight", getSeedling_weight()) | ||
| 424 | + .append("seedling_specification", getSeedling_specification()) | ||
| 425 | + .append("variable_costs", getVariable_costs()) | ||
| 426 | + .append("seedling_cost", getSeedling_cost()) | ||
| 427 | + .append("feed_quantity", getFeed_quantity()) | ||
| 428 | + .append("feed_amount", getFeed_amount()) | ||
| 429 | + .append("animal_health_protection", getAnimal_health_protection()) | ||
| 430 | + .append("electricity_fee", getElectricity_fee()) | ||
| 431 | + .append("labor_cost", getLabor_cost()) | ||
| 432 | + .append("consumables_cost", getConsumables_cost()) | ||
| 433 | + .append("netting_fee", getNetting_fee()) | ||
| 434 | + .append("depreciation_and_amortization", getDepreciation_and_amortization()) | ||
| 435 | + .append("repair_fee", getRepair_fee()) | ||
| 436 | + .append("fuel_fee", getFuel_fee()) | ||
| 437 | + .append("lease_fee", getLease_fee()) | ||
| 438 | + .append("other_shared_costs", getOther_shared_costs()) | ||
| 439 | + .append("fixed_costs", getFixed_costs()) | ||
| 440 | + .append("cage_depreciation_fee", getCage_depreciation_fee()) | ||
| 441 | + .append("cage_management_fee", getCage_management_fee()) | ||
| 442 | + .append("sea_area_fee", getSea_area_fee()) | ||
| 443 | + .append("pond_rent", getPond_rent()) | ||
| 444 | + .append("total_cost", getTotal_cost()) | ||
| 445 | + .toString(); | ||
| 446 | + } | ||
| 447 | +} |
lh-common/lh-jedis-redis/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 5 | + <modelVersion>4.0.0</modelVersion> | ||
| 6 | + <parent> | ||
| 7 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 8 | + <artifactId>lh-common</artifactId> | ||
| 9 | + <version>1.0.0</version> | ||
| 10 | + </parent> | ||
| 11 | + | ||
| 12 | + <artifactId>lh-jedis-redis</artifactId> | ||
| 13 | + <description>redis连接池操作</description> | ||
| 14 | + | ||
| 15 | + <properties> | ||
| 16 | + <maven.compiler.source>8</maven.compiler.source> | ||
| 17 | + <maven.compiler.target>8</maven.compiler.target> | ||
| 18 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| 19 | + </properties> | ||
| 20 | + | ||
| 21 | + <dependencies> | ||
| 22 | + <dependency> | ||
| 23 | + <groupId>redis.clients</groupId> | ||
| 24 | + <artifactId>jedis</artifactId> | ||
| 25 | + </dependency> | ||
| 26 | + </dependencies> | ||
| 27 | + | ||
| 28 | +</project> |
| 1 | +package com.zhonglai.luhui.redis.config; | ||
| 2 | + | ||
| 3 | +import com.zhonglai.luhui.redis.service.RedisService; | ||
| 4 | +import redis.clients.jedis.JedisPoolConfig; | ||
| 5 | + | ||
| 6 | +import java.io.File; | ||
| 7 | +import java.io.FileInputStream; | ||
| 8 | +import java.io.IOException; | ||
| 9 | +import java.io.InputStream; | ||
| 10 | +import java.util.Properties; | ||
| 11 | + | ||
| 12 | +public class RedisConfig { | ||
| 13 | + private String host = "127.0.0.1"; | ||
| 14 | + private Integer port = 6379; | ||
| 15 | + | ||
| 16 | + private String user; | ||
| 17 | + private String password; | ||
| 18 | + | ||
| 19 | + private Integer timeout; | ||
| 20 | + | ||
| 21 | + private Integer database; | ||
| 22 | + | ||
| 23 | + private JedisPoolConfig poolConfig; | ||
| 24 | + | ||
| 25 | + private String propertiesPath; | ||
| 26 | + | ||
| 27 | + public RedisConfig() | ||
| 28 | + { | ||
| 29 | + init(); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + public RedisConfig(String propertiesPath) | ||
| 33 | + { | ||
| 34 | + this.propertiesPath = propertiesPath; | ||
| 35 | + init(); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + public void init(Properties properties) | ||
| 39 | + { | ||
| 40 | + poolConfig = new JedisPoolConfig(); | ||
| 41 | + // 设置连接池参数 | ||
| 42 | + poolConfig.setMaxTotal(Integer.parseInt(properties.getProperty("jedis.pool.maxTotal"))); // 最多的连接个数 | ||
| 43 | + poolConfig.setMaxIdle(Integer.parseInt(properties.getProperty("jedis.pool.maxIdle"))); // 最多空闲的连接个数 | ||
| 44 | + poolConfig.setMinIdle(Integer.parseInt(properties.getProperty("jedis.pool.minIdle"))); // 最小空闲的连接个数 | ||
| 45 | + poolConfig.setTestOnBorrow(Boolean.parseBoolean(properties.getProperty("jedis.pool.testOnBorrow"))); // 在获取连接对象时是否验证该连接对象的连通性 | ||
| 46 | + poolConfig.setTestOnReturn(Boolean.parseBoolean(properties.getProperty("jedis.pool.testOnReturn"))); | ||
| 47 | + poolConfig.setTestWhileIdle(Boolean.parseBoolean(properties.getProperty("jedis.pool.testWhileIdle"))); | ||
| 48 | + poolConfig.setMinEvictableIdleTimeMillis(Long.parseLong(properties.getProperty("jedis.pool.minEvictableIdleTimeMillis"))); | ||
| 49 | + poolConfig.setTimeBetweenEvictionRunsMillis(Long.parseLong(properties.getProperty("jedis.pool.timeBetweenEvictionRunsMillis"))); | ||
| 50 | + poolConfig.setNumTestsPerEvictionRun(Integer.parseInt(properties.getProperty("jedis.pool.numTestsPerEvictionRun"))); | ||
| 51 | + poolConfig.setBlockWhenExhausted(Boolean.parseBoolean(properties.getProperty("jedis.pool.blockWhenExhausted"))); | ||
| 52 | + | ||
| 53 | + host = properties.getProperty("jedis.host"); | ||
| 54 | + port = Integer.parseInt(properties.getProperty("jedis.port")); | ||
| 55 | + timeout = Integer.parseInt(properties.getProperty("jedis.timeout")); | ||
| 56 | + password = properties.getProperty("jedis.password"); | ||
| 57 | + user = properties.getProperty("jedis.user"); | ||
| 58 | + database = Integer.parseInt(null!=properties.getProperty("jedis.database")?properties.getProperty("jedis.database"):"0"); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + public void init() | ||
| 62 | + { | ||
| 63 | + Properties properties = loadProperties(); | ||
| 64 | + init(properties); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + private Properties loadProperties() | ||
| 68 | + { | ||
| 69 | + if(null != propertiesPath && !"".equals(propertiesPath)) | ||
| 70 | + { | ||
| 71 | + Properties properties = new Properties(); | ||
| 72 | + try { | ||
| 73 | + properties.load(new FileInputStream(propertiesPath)); | ||
| 74 | + return properties; | ||
| 75 | + } catch (IOException e) { | ||
| 76 | + throw new RuntimeException(e); | ||
| 77 | + } | ||
| 78 | + } | ||
| 79 | + return loadDefaultProperties(); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + | ||
| 83 | + | ||
| 84 | + private Properties loadDefaultProperties() | ||
| 85 | + { | ||
| 86 | + // 加载属性文件 | ||
| 87 | + Properties properties = new Properties(); | ||
| 88 | + try (InputStream input = RedisService.class.getClassLoader().getResourceAsStream("jedis.properties")) { | ||
| 89 | + if (input == null) { | ||
| 90 | + System.out.println("Cannot find jedis.properties file in the classpath"); | ||
| 91 | + return properties; | ||
| 92 | + } | ||
| 93 | + properties.load(input); | ||
| 94 | + } catch (IOException ex) { | ||
| 95 | + ex.printStackTrace(); | ||
| 96 | + } | ||
| 97 | + return properties; | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + public String getHost() { | ||
| 101 | + return host; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + public void setHost(String host) { | ||
| 105 | + this.host = host; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + public Integer getPort() { | ||
| 109 | + return port; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + public void setPort(Integer port) { | ||
| 113 | + this.port = port; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + public String getPassword() { | ||
| 117 | + return password; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + public void setPassword(String password) { | ||
| 121 | + this.password = password; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + public Integer getTimeout() { | ||
| 125 | + return timeout; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + public void setTimeout(Integer timeout) { | ||
| 129 | + this.timeout = timeout; | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + public JedisPoolConfig getPoolConfig() { | ||
| 133 | + return poolConfig; | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + public void setPoolConfig(JedisPoolConfig poolConfig) { | ||
| 137 | + this.poolConfig = poolConfig; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + public Integer getDatabase() { | ||
| 141 | + return database; | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + public void setDatabase(Integer database) { | ||
| 145 | + this.database = database; | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + public String getUser() { | ||
| 149 | + return user; | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + public void setUser(String user) { | ||
| 153 | + this.user = user; | ||
| 154 | + } | ||
| 155 | +} |
lh-common/lh-jedis-redis/src/main/java/com/zhonglai/luhui/redis/service/RedisService.java
0 → 100644
| 1 | +package com.zhonglai.luhui.redis.service; | ||
| 2 | + | ||
| 3 | +import com.zhonglai.luhui.redis.config.RedisConfig; | ||
| 4 | +import redis.clients.jedis.Jedis; | ||
| 5 | +import redis.clients.jedis.JedisPool; | ||
| 6 | + | ||
| 7 | +public class RedisService { | ||
| 8 | + | ||
| 9 | + private JedisPool jedisPool; | ||
| 10 | + | ||
| 11 | + public RedisService(RedisConfig redisConfig) | ||
| 12 | + { | ||
| 13 | + // 创建JedisPool实例,并传入密码 | ||
| 14 | + jedisPool = new JedisPool(redisConfig.getPoolConfig(), redisConfig.getHost(), redisConfig.getPort(), redisConfig.getTimeout(),redisConfig.getUser(), redisConfig.getPassword(),redisConfig.getDatabase()); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + public Jedis getJedis() | ||
| 18 | + { | ||
| 19 | + return jedisPool.getResource(); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + public void exeJedis(RedisServiceExe redisServiceExe) | ||
| 23 | + { | ||
| 24 | + Jedis jedis = getJedis(); | ||
| 25 | + redisServiceExe.exe(jedis); | ||
| 26 | + jedis.close();//归还连接池 | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | +} |
| 1 | +# jedis.properties | ||
| 2 | +jedis.pool.maxTotal=100 | ||
| 3 | +jedis.pool.maxIdle=50 | ||
| 4 | +jedis.pool.minIdle=10 | ||
| 5 | +jedis.pool.testOnBorrow=true | ||
| 6 | +jedis.pool.testOnReturn=true | ||
| 7 | +jedis.pool.testWhileIdle=true | ||
| 8 | +jedis.pool.minEvictableIdleTimeMillis=60000 | ||
| 9 | +jedis.pool.timeBetweenEvictionRunsMillis=30000 | ||
| 10 | +jedis.pool.numTestsPerEvictionRun=3 | ||
| 11 | +jedis.pool.blockWhenExhausted=true | ||
| 12 | +jedis.host=47.112.163.61 | ||
| 13 | +jedis.port=9527 | ||
| 14 | +jedis.timeout=2000 | ||
| 15 | +jedis.password=Luhui586 | ||
| 16 | +jedis.database=3 |
| 1 | +import com.zhonglai.luhui.redis.config.RedisConfig; | ||
| 2 | +import com.zhonglai.luhui.redis.service.RedisService; | ||
| 3 | + | ||
| 4 | +import java.util.concurrent.atomic.AtomicReference; | ||
| 5 | + | ||
| 6 | +public class Test { | ||
| 7 | + public static void main(String[] args) { | ||
| 8 | + RedisService redisService = new RedisService(new RedisConfig()); | ||
| 9 | + | ||
| 10 | + AtomicReference<String> str = new AtomicReference<>(""); | ||
| 11 | + redisService.exeJedis(jedis -> { | ||
| 12 | + str.set(jedis.set("myKey", "myValue")); | ||
| 13 | + long seconds = 10; | ||
| 14 | + jedis.expire("myKey", seconds); | ||
| 15 | + }); | ||
| 16 | + | ||
| 17 | + System.out.println(str); | ||
| 18 | + } | ||
| 19 | +} |
lh-common/lh-public-dao/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 5 | + <modelVersion>4.0.0</modelVersion> | ||
| 6 | + <parent> | ||
| 7 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 8 | + <artifactId>lh-common</artifactId> | ||
| 9 | + <version>1.0.0</version> | ||
| 10 | + </parent> | ||
| 11 | + | ||
| 12 | + <artifactId>lh-public-dao</artifactId> | ||
| 13 | + <description>数据库操作</description> | ||
| 14 | + | ||
| 15 | + <properties> | ||
| 16 | + <maven.compiler.source>8</maven.compiler.source> | ||
| 17 | + <maven.compiler.target>8</maven.compiler.target> | ||
| 18 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| 19 | + </properties> | ||
| 20 | + | ||
| 21 | + <dependencies> | ||
| 22 | + <dependency> | ||
| 23 | + <groupId>com.zhonglai.luhui</groupId> | ||
| 24 | + <artifactId>lh-common-util</artifactId> | ||
| 25 | + </dependency> | ||
| 26 | + <dependency> | ||
| 27 | + <groupId>tk.mybatis</groupId> | ||
| 28 | + <artifactId>mapper</artifactId> | ||
| 29 | + <!-- 建议使用最新版本,最新版本请从项目首页查找 --> | ||
| 30 | + </dependency> | ||
| 31 | + <dependency> | ||
| 32 | + <groupId>tk.mybatis</groupId> | ||
| 33 | + <artifactId>mapper-spring-boot-starter</artifactId> | ||
| 34 | + </dependency> | ||
| 35 | +<!-- <dependency>--> | ||
| 36 | +<!-- <groupId>org.mybatis.spring.boot</groupId>--> | ||
| 37 | +<!-- <artifactId>mybatis-spring-boot-starter</artifactId>--> | ||
| 38 | +<!-- </dependency>--> | ||
| 39 | + <!--常用工具类 --> | ||
| 40 | + <dependency> | ||
| 41 | + <groupId>org.apache.commons</groupId> | ||
| 42 | + <artifactId>commons-lang3</artifactId> | ||
| 43 | + </dependency> | ||
| 44 | + | ||
| 45 | + </dependencies> | ||
| 46 | +</project> |
lh-common/lh-public-dao/src/main/java/com/zhonglai/luhui/dao/annotation/PublicSQLConfig.java
0 → 100644
| 1 | +package com.zhonglai.luhui.dao.annotation; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import java.lang.annotation.ElementType; | ||
| 5 | +import java.lang.annotation.Retention; | ||
| 6 | +import java.lang.annotation.RetentionPolicy; | ||
| 7 | +import java.lang.annotation.Target; | ||
| 8 | + | ||
| 9 | +@Target(ElementType.FIELD) | ||
| 10 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 11 | +public @interface PublicSQLConfig { | ||
| 12 | + boolean isSelect() default true; | ||
| 13 | + boolean isPrimarykey() default false; | ||
| 14 | +} |
-
请 注册 或 登录 后发表评论