Last active
July 10, 2017 08:26
-
-
Save JunqiangYang/4394eacb629d244cdfd6f549c25cbc5a to your computer and use it in GitHub Desktop.
Utils
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Calendar; | |
import java.util.Date; | |
public class CalendarUtil { | |
public enum RepayPeriodType{ | |
Positive,//正推 | |
Reverse//倒退 | |
} | |
/** | |
* 获得当月最后一天 | |
* @param cal | |
* @return | |
*/ | |
public static Calendar getLastDayThisMonth(Calendar cal) { | |
Calendar c = Calendar.getInstance(); | |
c.setTime(cal.getTime()); | |
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH)); | |
return c; | |
} | |
/** | |
* 获得当月最后一天 | |
* @param cal | |
* @return | |
*/ | |
public static Calendar getLastDayThisMonth(long time) { | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(time); | |
return getLastDayThisMonth(c); | |
} | |
/** | |
* 获得time对应天的0点0分0秒的时间ms值 | |
* | |
* @param time | |
* @return | |
*/ | |
public static long getDayMilliStart(long time) { | |
Calendar cal = Calendar.getInstance(); | |
cal.setTimeInMillis(time); | |
cal.set(Calendar.HOUR_OF_DAY, 0); | |
cal.set(Calendar.MINUTE, 0); | |
cal.set(Calendar.SECOND, 0); | |
cal.set(Calendar.MILLISECOND, 0); | |
return cal.getTimeInMillis(); | |
} | |
/** | |
* 获得time对应天的23点59分59秒的时间ms值 | |
* | |
* @param end | |
* @return | |
*/ | |
public static long getDayMilliEnd(long end) { | |
return getDayMilliStart(end) + 86400 * 1000 - 1; | |
} | |
/** | |
* 计算2个时间的间隔天数 | |
* @param from | |
* @param to | |
* @param includeFromTo to的时间是否作为1天 | |
* @return | |
*/ | |
public static int computeDayInterval(long fromTimeMill, long toTimeMill, boolean includeTo) { | |
long max = Math.max(fromTimeMill, toTimeMill); | |
long min = Math.min(fromTimeMill, toTimeMill); | |
int dayInterval = (int)((getDayMilliStart(max)-getDayMilliStart(min))/(86400*1000)); | |
return includeTo?dayInterval:(dayInterval-1); | |
} | |
/** | |
* | |
* @param fromYmd 起始ymd时间 | |
* @param toYmd 截至ymd时间 | |
* @param includeTo to的时间是否作为1天 | |
* @return | |
*/ | |
public static int computeDayInterval(int fromYmd, int toYmd, boolean includeTo) { | |
long fromTimeMill = getDayMilliStart(Utils.fromYYYYMMDDToMills(fromYmd)); | |
long toTimeMill = getDayMilliStart(Utils.fromYYYYMMDDToMills(toYmd)); | |
return computeDayInterval(fromTimeMill, toTimeMill, includeTo); | |
} | |
/** | |
* 正向计算用户还款日 | |
* @param time | |
* @return | |
*/ | |
public static long computeMonthRepayTimePositive(long time, int periodInMonth) { | |
time = getDayMilliStart(time); | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(time); | |
c.add(Calendar.MONTH, periodInMonth); | |
return c.getTimeInMillis(); | |
} | |
public static long computeMonthRepayTime(long time, int periodInMonth, RepayPeriodType type) { | |
switch(type) { | |
case Positive: | |
return computeMonthRepayTimePositive(time, periodInMonth); | |
default: | |
return computeMonthRepayTimeReverse(time, periodInMonth); | |
} | |
} | |
public static int computePeriod(int ymd, int periods, long preloanTime, RepayPeriodType type) { | |
long[] repayTimes = computeMonthRepayTimes(preloanTime, periods, type); | |
int [] ymds = new int[repayTimes.length]; | |
for(int i=0;i<repayTimes.length;i++) { | |
ymds[i] = Utils.fromMillsToYYYYMMDD(repayTimes[i]); | |
} | |
for(int i=0;i<repayTimes.length-1;i++) { | |
if(ymds[i] <= ymd&&ymds[i+1] >= ymd) { | |
//还款日优先被前一个周期选中 | |
return i+1; | |
} | |
} | |
return -1; | |
} | |
/** | |
* 反向计算用户还款时间 | |
* | |
* @param pre_loan_time | |
* 起息日期 | |
* @param period | |
* 期号 | |
* @return | |
*/ | |
public static long computeNextMonthRepayTimeReverse(long pre_loan_time, int n) { | |
Calendar preLoanTime = Calendar.getInstance(); | |
preLoanTime.setTimeInMillis(pre_loan_time); | |
Calendar nextMonthPreLoanTime = Calendar.getInstance(); | |
nextMonthPreLoanTime.setTimeInMillis(pre_loan_time); | |
nextMonthPreLoanTime.add(Calendar.MONTH, n); | |
if(nextMonthPreLoanTime.get(Calendar.DAY_OF_MONTH) == preLoanTime.get(Calendar.DAY_OF_MONTH)) { | |
return nextMonthPreLoanTime.getTimeInMillis(); | |
} | |
else { | |
int days = computeDayInterval(preLoanTime.getTimeInMillis(), getLastDayThisMonth(preLoanTime).getTimeInMillis(), true); | |
preLoanTime.add(Calendar.MONTH, n); | |
return getLastDayThisMonth(preLoanTime).getTimeInMillis()-days*86400*1000; | |
} | |
} | |
/** | |
* 按起息日计算第几期的还款时间 | |
* @param pre_loan_time 放款时间 | |
* @param period 第几期 | |
* @return | |
*/ | |
public static long computeMonthRepayTimeReverse(long pre_loan_time, int period) { | |
long begin = getDayMilliStart(pre_loan_time);; | |
begin = computeNextMonthRepayTimeReverse(begin, period); | |
return begin; | |
} | |
/** | |
* 按反向方式计算标的的所有还款日 | |
* @param pre_loan_time 起息时间 | |
* @param period 期数 | |
* @return | |
*/ | |
public static long[] computeMonthRepayTimesReverse(long pre_loan_time, int periods) { | |
pre_loan_time = Utils.getDayMilliStart(pre_loan_time); | |
long[] rets = new long[periods+1]; | |
rets[0] = pre_loan_time; | |
for(int i=1;i<=periods;i++) { | |
rets[i] = computeNextMonthRepayTimeReverse(pre_loan_time, i); | |
} | |
return rets; | |
} | |
/** | |
* 按正向方式计算标的的所有还款日 | |
* @param pre_loan_time 起息时间 | |
* @param periods 期数 | |
* @return | |
*/ | |
public static long[] computeMonthRepayTimesPositive(long pre_loan_time, int periods) { | |
pre_loan_time = Utils.getDayMilliStart(pre_loan_time); | |
long[] rets = new long[periods+1]; | |
rets[0] = pre_loan_time; | |
for(int i=1;i<=periods;i++) { | |
rets[i] = computeMonthRepayTimePositive(pre_loan_time, i); | |
} | |
return rets; | |
} | |
public static long[] computeMonthRepayTimes(long pre_loan_time, int periods, RepayPeriodType type) { | |
switch(type) { | |
case Positive: | |
return computeMonthRepayTimesPositive(pre_loan_time, periods); | |
default: | |
return computeMonthRepayTimesReverse(pre_loan_time, periods); | |
} | |
} | |
public static int addDays(int ymd, int days) { | |
long t = Utils.fromYYYYMMDDToMills(ymd) + 1L*days*86400*1000; | |
return Utils.fromMillsToYYYYMMDD(t); | |
} | |
public static void main(String ...args) throws Throwable { | |
Date d = Utils.DATE_SIMPLE_SDF.parse("20160130"); | |
// System.out.println(new Date(computeNextMonthRepayTimeReverse(d.getTime()))); | |
// System.out.println(CalendarUtil.computeDayInterval(1475550197385L, 1478228597385L, true)); | |
System.out.println(CalendarUtil.computePeriod(20160229, 12, d.getTime(), RepayPeriodType.Reverse)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.security.MessageDigest; | |
public class Crypto { | |
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", | |
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; | |
public static String encryptBySHA1(String src, String charset) throws Throwable { | |
byte[] bytes; | |
StringBuilder result = new StringBuilder(); | |
try { | |
MessageDigest md = MessageDigest.getInstance("SHA-1"); | |
md.update(src.getBytes(charset)); | |
bytes = md.digest(); | |
for (int i = 0; i < bytes.length; i++) { | |
result.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16) | |
.substring(1)); | |
} | |
} catch (Throwable ex) { | |
throw ex; | |
} | |
return result.toString(); | |
} | |
private static String byteArrayToHexString(byte b[]) { | |
StringBuffer resultSb = new StringBuffer(); | |
for (int i = 0; i < b.length; i++) | |
resultSb.append(byteToHexString(b[i])); | |
return resultSb.toString(); | |
} | |
private static String byteToHexString(byte b) { | |
int n = b; | |
if (n < 0) | |
n += 256; | |
int d1 = n / 16; | |
int d2 = n % 16; | |
return hexDigits[d1] + hexDigits[d2]; | |
} | |
public static String MD5Encode(String origin, String charsetname) { | |
String resultString = null; | |
try { | |
resultString = new String(origin); | |
MessageDigest md = MessageDigest.getInstance("MD5"); | |
if (charsetname == null || "".equals(charsetname)) | |
resultString = byteArrayToHexString(md.digest(resultString | |
.getBytes())); | |
else | |
resultString = byteArrayToHexString(md.digest(resultString | |
.getBytes(charsetname))); | |
} catch (Exception exception) { | |
} | |
return resultString; | |
} | |
public static byte[] MD5Encode(byte[] origin) { | |
try { | |
MessageDigest md = MessageDigest.getInstance("MD5"); | |
return md.digest(origin); | |
} catch (Exception exception) { | |
} | |
return null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class DateUtil { | |
public static void sleep(int milliseconds){ | |
try{ | |
Thread.sleep(milliseconds); | |
}catch(Throwable e){} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.net.InetAddress; | |
import java.net.UnknownHostException; | |
public class GrayUtil { | |
private static String localIP = ""; | |
static{ | |
try { | |
localIP = InetAddress.getLocalHost().getHostAddress(); | |
} catch (UnknownHostException e) { | |
BizLogger.error(e, "GrayUtil.localIP"); | |
} | |
} | |
public static boolean isTestEnv(){ | |
if("test".equals(AppConfig.get("app.env", "formal"))){ | |
return true; | |
} | |
return false; | |
} | |
/** | |
* | |
* | |
* | |
* @param bid_id | |
* @return true 标识从Rsmq发送短信 false 标识不从Rsmq发送短信 | |
*/ | |
public static boolean isSendMsgformRsmq(long bid_id){ | |
String allow_bids = AppConfig.get("app.allow_sendMsgformRsmq_bids", ""); | |
// 自有账户 | |
if (allow_bids.contains("*")) { | |
BizLogger.info("allow_sendMsgformRsmq_bids * 全量 , bid = "+bid_id); | |
return true; | |
} | |
if(allow_bids.contains(bid_id + "")){ | |
BizLogger.info("allow_sendMsgformRsmq_bids bid灰度 ", bid_id,allow_bids); | |
return true; | |
} | |
String bidId = String.valueOf(bid_id); | |
if (allow_bids.contains(","+bidId.substring(bidId.length()-1)+",")) { | |
BizLogger.info("allow_sendMsgformRsmq_bids 尾号灰度 , bid = "+bid_id); | |
return true; | |
} | |
return false; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class HexUtil { | |
private static final char[] digits = new char[] { '0', '1', '2', '3', '4',// | |
'5', '6', '7', '8', '9',// | |
'A', 'B', 'C', 'D', 'E',// | |
'F' }; | |
public static final byte[] emptybytes = new byte[0]; | |
/** | |
* 将单个字节转成Hex String | |
* @param b 字节 | |
* @return String Hex String | |
*/ | |
public static String byte2HexStr(byte b) | |
{ | |
char[] buf = new char[2]; | |
buf[1] = digits[b & 0xF]; | |
b = (byte) (b >>> 4); | |
buf[0] = digits[b & 0xF]; | |
return new String(buf); | |
} | |
/** | |
* 将字节数组转成Hex String | |
* @param b | |
* @return String | |
*/ | |
public static String bytes2HexStr(byte[] bytes) | |
{ | |
if (bytes == null || bytes.length == 0) | |
{ | |
return null; | |
} | |
char[] buf = new char[2 * bytes.length]; | |
for (int i = 0; i < bytes.length; i++) | |
{ | |
byte b = bytes[i]; | |
buf[2 * i + 1] = digits[b & 0xF]; | |
b = (byte) (b >>> 4); | |
buf[2 * i + 0] = digits[b & 0xF]; | |
} | |
return new String(buf); | |
} | |
/** | |
* 将单个hex Str转换成字节 | |
* @param str | |
* @return byte | |
*/ | |
public static byte hexStr2Byte(String str) | |
{ | |
if (str != null && str.length() == 1) | |
{ | |
return char2Byte(str.charAt(0)); | |
} | |
else | |
{ | |
return 0; | |
} | |
} | |
/** | |
* 字符到字节 | |
* @param ch | |
* @return byte | |
*/ | |
public static byte char2Byte(char ch) | |
{ | |
if (ch >= '0' && ch <= '9') | |
{ | |
return (byte) (ch - '0'); | |
} | |
else if (ch >= 'a' && ch <= 'f') | |
{ | |
return (byte) (ch - 'a' + 10); | |
} | |
else if (ch >= 'A' && ch <= 'F') | |
{ | |
return (byte) (ch - 'A' + 10); | |
} | |
else | |
{ | |
return 0; | |
} | |
} | |
public static byte[] hexStr2Bytes(String str) | |
{ | |
if (str == null || str.equals("")) | |
{ | |
return emptybytes; | |
} | |
byte[] bytes = new byte[str.length() / 2]; | |
for (int i = 0; i < bytes.length; i++) | |
{ | |
char high = str.charAt(i * 2); | |
char low = str.charAt(i * 2 + 1); | |
bytes[i] = (byte) (char2Byte(high) * 16 + char2Byte(low)); | |
} | |
return bytes; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import java.util.Calendar; | |
import java.util.Date; | |
import java.util.HashMap; | |
import java.util.Map; | |
import org.apache.commons.lang.StringUtils; | |
/** | |
* 身份证工具类 | |
* | |
*/ | |
public class IdcardUtils extends StringUtils { | |
/** 中国公民身份证号码最小长度。 */ | |
public static final int CHINA_ID_MIN_LENGTH = 15; | |
/** 中国公民身份证号码最大长度。 */ | |
public static final int CHINA_ID_MAX_LENGTH = 18; | |
/** 省、直辖市代码表 */ | |
public static final String cityCode[] = { | |
"11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36", "37", "41", | |
"42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65", "71", | |
"81", "82", "91" | |
}; | |
/** 每位加权因子 */ | |
public static final int power[] = { | |
7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 | |
}; | |
/** 第18位校检码 */ | |
public static final String verifyCode[] = { | |
"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" | |
}; | |
/** 最低年限 */ | |
public static final int MIN = 1930; | |
public static Map<String, String> cityCodes = new HashMap<String, String>(); | |
/** 台湾身份首字母对应数字 */ | |
public static Map<String, Integer> twFirstCode = new HashMap<String, Integer>(); | |
/** 香港身份首字母对应数字 */ | |
public static Map<String, Integer> hkFirstCode = new HashMap<String, Integer>(); | |
static { | |
cityCodes.put("11", "北京"); | |
cityCodes.put("12", "天津"); | |
cityCodes.put("13", "河北"); | |
cityCodes.put("14", "山西"); | |
cityCodes.put("15", "内蒙古"); | |
cityCodes.put("21", "辽宁"); | |
cityCodes.put("22", "吉林"); | |
cityCodes.put("23", "黑龙江"); | |
cityCodes.put("31", "上海"); | |
cityCodes.put("32", "江苏"); | |
cityCodes.put("33", "浙江"); | |
cityCodes.put("34", "安徽"); | |
cityCodes.put("35", "福建"); | |
cityCodes.put("36", "江西"); | |
cityCodes.put("37", "山东"); | |
cityCodes.put("41", "河南"); | |
cityCodes.put("42", "湖北"); | |
cityCodes.put("43", "湖南"); | |
cityCodes.put("44", "广东"); | |
cityCodes.put("45", "广西"); | |
cityCodes.put("46", "海南"); | |
cityCodes.put("50", "重庆"); | |
cityCodes.put("51", "四川"); | |
cityCodes.put("52", "贵州"); | |
cityCodes.put("53", "云南"); | |
cityCodes.put("54", "西藏"); | |
cityCodes.put("61", "陕西"); | |
cityCodes.put("62", "甘肃"); | |
cityCodes.put("63", "青海"); | |
cityCodes.put("64", "宁夏"); | |
cityCodes.put("65", "新疆"); | |
cityCodes.put("71", "台湾"); | |
cityCodes.put("81", "香港"); | |
cityCodes.put("82", "澳门"); | |
cityCodes.put("91", "国外"); | |
twFirstCode.put("A", 10); | |
twFirstCode.put("B", 11); | |
twFirstCode.put("C", 12); | |
twFirstCode.put("D", 13); | |
twFirstCode.put("E", 14); | |
twFirstCode.put("F", 15); | |
twFirstCode.put("G", 16); | |
twFirstCode.put("H", 17); | |
twFirstCode.put("J", 18); | |
twFirstCode.put("K", 19); | |
twFirstCode.put("L", 20); | |
twFirstCode.put("M", 21); | |
twFirstCode.put("N", 22); | |
twFirstCode.put("P", 23); | |
twFirstCode.put("Q", 24); | |
twFirstCode.put("R", 25); | |
twFirstCode.put("S", 26); | |
twFirstCode.put("T", 27); | |
twFirstCode.put("U", 28); | |
twFirstCode.put("V", 29); | |
twFirstCode.put("X", 30); | |
twFirstCode.put("Y", 31); | |
twFirstCode.put("W", 32); | |
twFirstCode.put("Z", 33); | |
twFirstCode.put("I", 34); | |
twFirstCode.put("O", 35); | |
hkFirstCode.put("A", 1); | |
hkFirstCode.put("B", 2); | |
hkFirstCode.put("C", 3); | |
hkFirstCode.put("R", 18); | |
hkFirstCode.put("U", 21); | |
hkFirstCode.put("Z", 26); | |
hkFirstCode.put("X", 24); | |
hkFirstCode.put("W", 23); | |
hkFirstCode.put("O", 15); | |
hkFirstCode.put("N", 14); | |
} | |
/** | |
* 将15位身份证号码转换为18位 | |
* | |
* @param idCard | |
* 15位身份编码 | |
* @return 18位身份编码 | |
*/ | |
public static String conver15CardTo18(String idCard) { | |
String idCard18 = ""; | |
if (idCard.length() != CHINA_ID_MIN_LENGTH) { | |
return null; | |
} | |
if (isNum(idCard)) { | |
// 获取出生年月日 | |
String birthday = idCard.substring(6, 12); | |
Date birthDate = null; | |
try { | |
birthDate = new SimpleDateFormat("yyMMdd").parse(birthday); | |
} catch (ParseException e) { | |
e.printStackTrace(); | |
} | |
Calendar cal = Calendar.getInstance(); | |
if (birthDate != null) | |
cal.setTime(birthDate); | |
// 获取出生年(完全表现形式,如:2010) | |
String sYear = String.valueOf(cal.get(Calendar.YEAR)); | |
idCard18 = idCard.substring(0, 6) + sYear + idCard.substring(8); | |
// 转换字符数组 | |
char[] cArr = idCard18.toCharArray(); | |
if (cArr != null) { | |
int[] iCard = converCharToInt(cArr); | |
int iSum17 = getPowerSum(iCard); | |
// 获取校验位 | |
String sVal = getCheckCode18(iSum17); | |
if (sVal.length() > 0) { | |
idCard18 += sVal; | |
} else { | |
return null; | |
} | |
} | |
} else { | |
return null; | |
} | |
return idCard18; | |
} | |
/** | |
* 验证身份证是否合法 | |
*/ | |
public static boolean validateCard(String idCard) { | |
String card = idCard.trim(); | |
if (validateIdCard18(card)) { | |
return true; | |
} | |
if (validateIdCard15(card)) { | |
return true; | |
} | |
String[] cardval = validateIdCard10(card); | |
if (cardval != null) { | |
if (cardval[2].equals("true")) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* 验证18位身份编码是否合法 | |
* | |
* @param idCard 身份编码 | |
* @return 是否合法 | |
*/ | |
public static boolean validateIdCard18(String idCard) { | |
boolean bTrue = false; | |
if (idCard.length() == CHINA_ID_MAX_LENGTH) { | |
// 前17位 | |
String code17 = idCard.substring(0, 17); | |
// 第18位 | |
String code18 = idCard.substring(17, CHINA_ID_MAX_LENGTH); | |
if (isNum(code17)) { | |
String proCode = idCard.substring(0, 2); | |
if (cityCodes.get(proCode) == null) { | |
return false; | |
} | |
char[] cArr = code17.toCharArray(); | |
if (cArr != null) { | |
int[] iCard = converCharToInt(cArr); | |
int iSum17 = getPowerSum(iCard); | |
// 获取校验位 | |
String val = getCheckCode18(iSum17); | |
if (val.length() > 0) { | |
if (val.equalsIgnoreCase(code18)) { | |
bTrue = true; | |
} | |
} | |
} | |
} | |
} | |
return bTrue; | |
} | |
/** | |
* 验证15位身份编码是否合法 | |
* | |
* @param idCard | |
* 身份编码 | |
* @return 是否合法 | |
*/ | |
public static boolean validateIdCard15(String idCard) { | |
if (idCard.length() != CHINA_ID_MIN_LENGTH) { | |
return false; | |
} | |
if (isNum(idCard)) { | |
String proCode = idCard.substring(0, 2); | |
if (cityCodes.get(proCode) == null) { | |
return false; | |
} | |
String birthCode = idCard.substring(6, 12); | |
Date birthDate = null; | |
try { | |
birthDate = new SimpleDateFormat("yy").parse(birthCode.substring(0, 2)); | |
} catch (ParseException e) { | |
e.printStackTrace(); | |
} | |
Calendar cal = Calendar.getInstance(); | |
if (birthDate != null) | |
cal.setTime(birthDate); | |
if (!valiDate(cal.get(Calendar.YEAR), Integer.valueOf(birthCode.substring(2, 4)), | |
Integer.valueOf(birthCode.substring(4, 6)))) { | |
return false; | |
} | |
} else { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* 验证10位身份编码是否合法 | |
* | |
* @param idCard 身份编码 | |
* @return 身份证信息数组 | |
* <p> | |
* [0] - 台湾、澳门、香港 [1] - 性别(男M,女F,未知N) [2] - 是否合法(合法true,不合法false) | |
* 若不是身份证件号码则返回null | |
* </p> | |
*/ | |
public static String[] validateIdCard10(String idCard) { | |
String[] info = new String[3]; | |
String card = idCard.replaceAll("[\\(|\\)]", ""); | |
if (card.length() != 8 && card.length() != 9 && idCard.length() != 10) { | |
return null; | |
} | |
if (idCard.matches("^[a-zA-Z][0-9]{9}$")) { // 台湾 | |
info[0] = "台湾"; | |
System.out.println("11111"); | |
String char2 = idCard.substring(1, 2); | |
if (char2.equals("1")) { | |
info[1] = "M"; | |
System.out.println("MMMMMMM"); | |
} else if (char2.equals("2")) { | |
info[1] = "F"; | |
System.out.println("FFFFFFF"); | |
} else { | |
info[1] = "N"; | |
info[2] = "false"; | |
System.out.println("NNNN"); | |
return info; | |
} | |
info[2] = validateTWCard(idCard) ? "true" : "false"; | |
} else if (idCard.matches("^[1|5|7][0-9]{6}\\(?[0-9A-Z]\\)?$")) { // 澳门 | |
info[0] = "澳门"; | |
info[1] = "N"; | |
// TODO | |
} else if (idCard.matches("^[A-Z]{1,2}[0-9]{6}\\(?[0-9A]\\)?$")) { // 香港 | |
info[0] = "香港"; | |
info[1] = "N"; | |
info[2] = validateHKCard(idCard) ? "true" : "false"; | |
} else { | |
return null; | |
} | |
return info; | |
} | |
/** | |
* 验证台湾身份证号码 | |
* | |
* @param idCard | |
* 身份证号码 | |
* @return 验证码是否符合 | |
*/ | |
public static boolean validateTWCard(String idCard) { | |
String start = idCard.substring(0, 1); | |
String mid = idCard.substring(1, 9); | |
String end = idCard.substring(9, 10); | |
Integer iStart = twFirstCode.get(start); | |
Integer sum = iStart / 10 + (iStart % 10) * 9; | |
char[] chars = mid.toCharArray(); | |
Integer iflag = 8; | |
for (char c : chars) { | |
sum = sum + Integer.valueOf(c + "") * iflag; | |
iflag--; | |
} | |
return (sum % 10 == 0 ? 0 : (10 - sum % 10)) == Integer.valueOf(end) ? true : false; | |
} | |
/** | |
* 验证香港身份证号码(存在Bug,部份特殊身份证无法检查) | |
* <p> | |
* 身份证前2位为英文字符,如果只出现一个英文字符则表示第一位是空格,对应数字58 前2位英文字符A-Z分别对应数字10-35 | |
* 最后一位校验码为0-9的数字加上字符"A","A"代表10 | |
* </p> | |
* <p> | |
* 将身份证号码全部转换为数字,分别对应乘9-1相加的总和,整除11则证件号码有效 | |
* </p> | |
* | |
* @param idCard 身份证号码 | |
* @return 验证码是否符合 | |
*/ | |
public static boolean validateHKCard(String idCard) { | |
String card = idCard.replaceAll("[\\(|\\)]", ""); | |
Integer sum = 0; | |
if (card.length() == 9) { | |
sum = (Integer.valueOf(card.substring(0, 1).toUpperCase().toCharArray()[0]) - 55) * 9 | |
+ (Integer.valueOf(card.substring(1, 2).toUpperCase().toCharArray()[0]) - 55) * 8; | |
card = card.substring(1, 9); | |
} else { | |
sum = 522 + (Integer.valueOf(card.substring(0, 1).toUpperCase().toCharArray()[0]) - 55) * 8; | |
} | |
String mid = card.substring(1, 7); | |
String end = card.substring(7, 8); | |
char[] chars = mid.toCharArray(); | |
Integer iflag = 7; | |
for (char c : chars) { | |
sum = sum + Integer.valueOf(c + "") * iflag; | |
iflag--; | |
} | |
if (end.toUpperCase().equals("A")) { | |
sum = sum + 10; | |
} else { | |
sum = sum + Integer.valueOf(end); | |
} | |
return (sum % 11 == 0) ? true : false; | |
} | |
/** | |
* 将字符数组转换成数字数组 | |
* | |
* @param ca | |
* 字符数组 | |
* @return 数字数组 | |
*/ | |
public static int[] converCharToInt(char[] ca) { | |
int len = ca.length; | |
int[] iArr = new int[len]; | |
try { | |
for (int i = 0; i < len; i++) { | |
iArr[i] = Integer.parseInt(String.valueOf(ca[i])); | |
} | |
} catch (NumberFormatException e) { | |
e.printStackTrace(); | |
} | |
return iArr; | |
} | |
/** | |
* 将身份证的每位和对应位的加权因子相乘之后,再得到和值 | |
* | |
* @param iArr | |
* @return 身份证编码。 | |
*/ | |
public static int getPowerSum(int[] iArr) { | |
int iSum = 0; | |
if (power.length == iArr.length) { | |
for (int i = 0; i < iArr.length; i++) { | |
for (int j = 0; j < power.length; j++) { | |
if (i == j) { | |
iSum = iSum + iArr[i] * power[j]; | |
} | |
} | |
} | |
} | |
return iSum; | |
} | |
/** | |
* 将power和值与11取模获得余数进行校验码判断 | |
* | |
* @param iSum | |
* @return 校验位 | |
*/ | |
public static String getCheckCode18(int iSum) { | |
String sCode = ""; | |
switch (iSum % 11) { | |
case 10: | |
sCode = "2"; | |
break; | |
case 9: | |
sCode = "3"; | |
break; | |
case 8: | |
sCode = "4"; | |
break; | |
case 7: | |
sCode = "5"; | |
break; | |
case 6: | |
sCode = "6"; | |
break; | |
case 5: | |
sCode = "7"; | |
break; | |
case 4: | |
sCode = "8"; | |
break; | |
case 3: | |
sCode = "9"; | |
break; | |
case 2: | |
sCode = "x"; | |
break; | |
case 1: | |
sCode = "0"; | |
break; | |
case 0: | |
sCode = "1"; | |
break; | |
} | |
return sCode; | |
} | |
/** | |
* 根据身份编号获取年龄 | |
* | |
* @param idCard | |
* 身份编号 | |
* @return 年龄 | |
*/ | |
public static int getAgeByIdCard(String idCard) { | |
int iAge = 0; | |
if (idCard.length() == CHINA_ID_MIN_LENGTH) { | |
idCard = conver15CardTo18(idCard); | |
} | |
String year = idCard.substring(6, 10); | |
Calendar cal = Calendar.getInstance(); | |
int iCurrYear = cal.get(Calendar.YEAR); | |
iAge = iCurrYear - Integer.valueOf(year); | |
return iAge; | |
} | |
/** | |
* 根据身份编号获取生日 | |
* | |
* @param idCard 身份编号 | |
* @return 生日(yyyyMMdd) | |
*/ | |
public static String getBirthByIdCard(String idCard) { | |
Integer len = idCard.length(); | |
if (len < CHINA_ID_MIN_LENGTH) { | |
return null; | |
} else if (len == CHINA_ID_MIN_LENGTH) { | |
idCard = conver15CardTo18(idCard); | |
} | |
return idCard.substring(6, 14); | |
} | |
/** | |
* 根据身份编号获取生日年 | |
* | |
* @param idCard 身份编号 | |
* @return 生日(yyyy) | |
*/ | |
public static Short getYearByIdCard(String idCard) { | |
Integer len = idCard.length(); | |
if (len < CHINA_ID_MIN_LENGTH) { | |
return null; | |
} else if (len == CHINA_ID_MIN_LENGTH) { | |
idCard = conver15CardTo18(idCard); | |
} | |
return Short.valueOf(idCard.substring(6, 10)); | |
} | |
/** | |
* 根据身份编号获取生日月 | |
* | |
* @param idCard | |
* 身份编号 | |
* @return 生日(MM) | |
*/ | |
public static Short getMonthByIdCard(String idCard) { | |
Integer len = idCard.length(); | |
if (len < CHINA_ID_MIN_LENGTH) { | |
return null; | |
} else if (len == CHINA_ID_MIN_LENGTH) { | |
idCard = conver15CardTo18(idCard); | |
} | |
return Short.valueOf(idCard.substring(10, 12)); | |
} | |
/** | |
* 根据身份编号获取生日天 | |
* | |
* @param idCard | |
* 身份编号 | |
* @return 生日(dd) | |
*/ | |
public static Short getDateByIdCard(String idCard) { | |
Integer len = idCard.length(); | |
if (len < CHINA_ID_MIN_LENGTH) { | |
return null; | |
} else if (len == CHINA_ID_MIN_LENGTH) { | |
idCard = conver15CardTo18(idCard); | |
} | |
return Short.valueOf(idCard.substring(12, 14)); | |
} | |
/** | |
* 根据身份编号获取性别 | |
* | |
* @param idCard 身份编号 | |
* @return 性别(M-男,F-女,N-未知) | |
*/ | |
public static String getGenderByIdCard(String idCard) { | |
String sGender = "N"; | |
if (idCard.length() == CHINA_ID_MIN_LENGTH) { | |
idCard = conver15CardTo18(idCard); | |
} | |
String sCardNum = idCard.substring(16, 17); | |
if (Integer.parseInt(sCardNum) % 2 != 0) { | |
sGender = "M"; | |
} else { | |
sGender = "F"; | |
} | |
return sGender; | |
} | |
/** | |
* 根据身份编号获取户籍省份 | |
* | |
* @param idCard 身份编码 | |
* @return 省级编码。 | |
*/ | |
public static String getProvinceByIdCard(String idCard) { | |
int len = idCard.length(); | |
String sProvince = null; | |
String sProvinNum = ""; | |
if (len == CHINA_ID_MIN_LENGTH || len == CHINA_ID_MAX_LENGTH) { | |
sProvinNum = idCard.substring(0, 2); | |
} | |
sProvince = cityCodes.get(sProvinNum); | |
return sProvince; | |
} | |
/** | |
* 数字验证 | |
* | |
* @param val | |
* @return 提取的数字。 | |
*/ | |
public static boolean isNum(String val) { | |
return val == null || "".equals(val) ? false : val.matches("^[0-9]*$"); | |
} | |
/** | |
* 验证小于当前日期 是否有效 | |
* | |
* @param iYear | |
* 待验证日期(年) | |
* @param iMonth | |
* 待验证日期(月 1-12) | |
* @param iDate | |
* 待验证日期(日) | |
* @return 是否有效 | |
*/ | |
public static boolean valiDate(int iYear, int iMonth, int iDate) { | |
Calendar cal = Calendar.getInstance(); | |
int year = cal.get(Calendar.YEAR); | |
int datePerMonth; | |
if (iYear < MIN || iYear >= year) { | |
return false; | |
} | |
if (iMonth < 1 || iMonth > 12) { | |
return false; | |
} | |
switch (iMonth) { | |
case 4: | |
case 6: | |
case 9: | |
case 11: | |
datePerMonth = 30; | |
break; | |
case 2: | |
boolean dm = ((iYear % 4 == 0 && iYear % 100 != 0) || (iYear % 400 == 0)) | |
&& (iYear > MIN && iYear < year); | |
datePerMonth = dm ? 29 : 28; | |
break; | |
default: | |
datePerMonth = 31; | |
} | |
return (iDate >= 1) && (iDate <= datePerMonth); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class IntHolder { | |
public int value; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.Map; | |
public class JsonHolder { | |
private int code = 0; | |
private String msg = ""; | |
private Map<String, Object> json; | |
public JsonHolder() { | |
json = new HashMap<String, Object>(); | |
} | |
public JsonHolder(Map<String, Object> map) { | |
this(); | |
for(String key : map.keySet()) { | |
if(key.equals("code")) { | |
this.setCode(StringUtil.convertInt(String.valueOf(map.get(key)), ReturnValue.SYS_ERR)); | |
} | |
else if(key.equals("msg")) { | |
this.setMsg(String.valueOf(map.get(key))); | |
} | |
else { | |
this.addValue(key, map.get(key)); | |
} | |
} | |
} | |
public void setCode(int code) { | |
this.code = code; | |
} | |
public int getCode(){ | |
return this.code; | |
} | |
public void addValue(String key, Object value) { | |
json.put(key, value); | |
} | |
public void addMap(Map<String,Object> m) { | |
if(m==null) return; | |
Iterator<String> its = m.keySet().iterator(); | |
while(its.hasNext()){ | |
String key = its.next(); | |
json.put(key, m.get(key)); | |
} | |
} | |
public Object queryValue(String key) { | |
if(StringUtil.isEmpty(key) || json == null) return null; | |
return json.get(key); | |
} | |
public void setMsg(String msg) { | |
this.msg = msg; | |
} | |
public String toString() { | |
json.put("code", code); | |
json.put("msg", msg); | |
return JsonUtil.toJson(json); | |
//return JSON.toJSONString(json); | |
} | |
public String toAppString(){ | |
json.put("code", code); | |
json.put("msg", msg); | |
return ComplexPropertyPreFilter.getJsonStringByClient(json); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Set; | |
import java.util.concurrent.ConcurrentHashMap; | |
import com.alibaba.fastjson.JSON; | |
import com.alibaba.fastjson.serializer.ValueFilter; | |
import com.google.protobuf.Descriptors.Descriptor; | |
import com.google.protobuf.Descriptors.FieldDescriptor; | |
import com.google.protobuf.GeneratedMessage; | |
/** | |
* 对json做简单封装 | |
* @author user | |
* | |
*/ | |
public class JsonUtil { | |
private static ConcurrentHashMap<String, Set<String>> PbFields = new ConcurrentHashMap<String, Set<String>>(); | |
private static ValueFilter NullValueFilter = new ValueFilter() { | |
@Override | |
public Object process(Object obj, String s, Object v) { | |
if(v==null) | |
return ""; | |
return v; | |
} | |
}; | |
private static Set<String> parsePbObject(GeneratedMessage msg) { | |
String clzName = msg.getClass().getCanonicalName(); | |
Set<String> set = null; | |
if((set = PbFields.get(clzName))!=null) { | |
return set; | |
} | |
Descriptor d = msg.getDescriptorForType(); | |
List<FieldDescriptor> fileds = d.getFields(); | |
set = new HashSet<String>(); | |
for(FieldDescriptor fd : fileds) { | |
set.add(fd.getName()); | |
} | |
PbFields.putIfAbsent(msg.getClass().getCanonicalName(), set); | |
return set; | |
} | |
private static ValueFilter PbValueFilter = new ValueFilter() { | |
@Override | |
public Object process(Object obj, String s, Object v) { | |
if(obj instanceof GeneratedMessage) { | |
Set<String> fieldNames= parsePbObject((GeneratedMessage)obj); | |
if(fieldNames.contains(s)) { | |
return v; | |
} | |
} | |
return null; | |
} | |
}; | |
public static String toJson(Object o) { | |
if(o instanceof GeneratedMessage) { | |
return JSON.toJSONString(o, PbValueFilter); | |
} | |
return JSON.toJSONString(o); | |
} | |
public static <T> T fromJson(String json, Class<T> c) { | |
return JSON.parseObject(json, c); | |
} | |
public static Object toJsonObject(Object o) { | |
return JSON.toJSON(o); | |
} | |
public static <T> List<T> fromJsonArray(String json, Class<T> c) { | |
return JSON.parseArray(json, c); | |
} | |
public static String toJson(Object o, boolean forseNull) { | |
if(forseNull) { | |
return JSON.toJSONString(o, NullValueFilter); | |
} | |
return toJson(o); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.HashSet; | |
import java.util.concurrent.atomic.AtomicInteger; | |
/** | |
* 1百ms产生1M数量随机不重复long值 | |
* @author Administrator | |
* | |
*/ | |
public class LongUUid { | |
private static int randomSeed = 1024; | |
private static AtomicInteger adder = new AtomicInteger(0); | |
private static volatile int nextSeed = RandomUtil.nextInt(randomSeed); | |
public static long uuid() { | |
long low = MilliSecClock.currentTimeMillis()/1000; | |
if(adder.compareAndSet(1024*1024-2, nextSeed)) { | |
nextSeed = RandomUtil.nextInt(randomSeed); | |
} | |
long high = adder.getAndIncrement(); | |
long mid = RandomUtil.nextInt(randomSeed); | |
return low +(mid<<32)+(high<<42); | |
} | |
public static void main(String ...args) { | |
long begin = System.currentTimeMillis(); | |
HashSet<Long> set = new HashSet<Long>(3*1024*1024); | |
long v = 0; | |
for(int i=0;i<10;i++) { | |
v = LongUUid.uuid(); | |
System.out.println(v); | |
if(v < 0) { | |
System.out.println("bad"); | |
System.exit(0); | |
} | |
if(set.contains(v)) { | |
System.out.println("same key "+v); | |
System.exit(0); | |
} | |
set.add(v); | |
} | |
System.out.println("cost "+(System.currentTimeMillis()-begin)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MilliSecClock { | |
private static volatile long now; | |
private MilliSecClock() { | |
} | |
static { | |
now = System.currentTimeMillis(); | |
Thread t = new Thread() { | |
public void run() { | |
while(true) { | |
try { | |
now = System.currentTimeMillis(); | |
Thread.sleep(1); | |
} | |
catch(Throwable t){} | |
} | |
} | |
}; | |
t.setName("MilliSecClock-Task"); | |
t.start(); | |
} | |
public static long currentTimeMillis() { | |
return now; | |
} | |
public static void main(String ...args) { | |
System.out.println(MilliSecClock.currentTimeMillis()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Null { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ObjectHolder<T> { | |
public T value; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.Serializable; | |
import java.util.List; | |
public class Page <T> implements Serializable{ | |
private static final long serialVersionUID = 1L; | |
private List<T> record; | |
private int total; | |
private int pn; | |
private int psize; | |
private boolean hasNext; | |
private boolean hasPrev; | |
private int nextPn; | |
private int prevPn; | |
private int totalPage; | |
public Page() {} | |
public Page(List<T> record, int total, int pn, int psize) { | |
this.record = record; | |
this.total = total; | |
this.pn = pn; | |
this.psize = psize; | |
this.hasNext = total > pn*psize; | |
this.hasPrev = this.pn >1; | |
this.nextPn = this.hasNext ? (this.pn+1):0; | |
this.prevPn = this.hasPrev ? (this.pn-1):0; | |
this.totalPage = total%psize==0?total/psize:total/psize+1; | |
} | |
public Page<T> clone() { | |
Page<T> newp = new Page<T>(this.record, this.total, this.pn, this.psize); | |
return newp; | |
} | |
public Page<T> delRecord() { | |
this.record = null; | |
return this; | |
} | |
public int getTotalPage() { | |
return totalPage; | |
} | |
public void setTotalPage(int totalPage) { | |
this.totalPage = totalPage; | |
} | |
public int getNextPn() { | |
return nextPn; | |
} | |
public int getPrevPn() { | |
return prevPn; | |
} | |
public List<T> getRecord() { | |
return record; | |
} | |
public int getTotal() { | |
return total; | |
} | |
public int getPn() { | |
return pn; | |
} | |
public int getPsize() { | |
return psize; | |
} | |
public boolean isHasNext() { | |
return hasNext; | |
} | |
public boolean isHasPrev() { | |
return hasPrev; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 分页处理 | |
* @author jake | |
*/ | |
public class PageUtil { | |
// /** | |
// * 分页码显示 | |
// * @param m | |
// * @param p | |
// * @param pn 当前页 | |
// * @param url 请求url | |
// */ | |
// public static <T> void splitPage(ModelMap m , Page<T> p, int pn, String url){ | |
// if(p==null || p.getRecord().size()==0) return ; | |
// // 翻页参数设置,前台直接读取; 目前按显示5页码处理。 | |
// m.put("pn", pn); | |
// int start = 1; | |
// if(pn<=3) {start=1;} | |
// else if(pn>p.getTotalPage()) {start=p.getTotalPage()-4;} | |
// else {start=pn-2;} | |
// m.put("startno", start);// 跳页起始页码 | |
// m.put("endno",Math.min(p.getTotalPage(), start+4));// (含) 跳页结束页码 | |
// m.put("total", p.getTotalPage()); // 总页数 | |
// m.put("url",url); // action | |
// } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Pair<F, S> { | |
private F first; | |
private S second; | |
public Pair() { | |
super(); | |
} | |
public Pair(F first, S second) { | |
super(); | |
this.first = first; | |
this.second = second; | |
} | |
public F getFirst() { | |
return first; | |
} | |
public void setFirst(F first) { | |
this.first = first; | |
} | |
public S getSecond() { | |
return second; | |
} | |
public void setSecond(S second) { | |
this.second = second; | |
} | |
public String toString() { | |
return String.valueOf(first)+"|"+String.valueOf(second); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.security.NoSuchAlgorithmException; | |
/* | |
* Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm). | |
* Copyright (c) 2013, Taylor Hornby | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* 1. Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the following disclaimer. | |
* | |
* 2. Redistributions in binary form must reproduce the above copyright notice, | |
* this list of conditions and the following disclaimer in the documentation | |
* and/or other materials provided with the distribution. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
* POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
import java.security.SecureRandom; | |
import java.security.spec.InvalidKeySpecException; | |
import javax.crypto.SecretKeyFactory; | |
import javax.crypto.spec.PBEKeySpec; | |
/* | |
* PBKDF2 salted password hashing. | |
* Author: havoc AT defuse.ca | |
* www: http://crackstation.net/hashing-security.htm | |
*/ | |
public class PasswordHash { | |
private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1"; | |
// The following constants may be changed without breaking existing hashes. | |
public static final int SALT_BYTE_SIZE = 24; | |
public static final int HASH_BYTE_SIZE = 24; | |
public static final int PBKDF2_ITERATIONS = 64; | |
public static final int ITERATION_INDEX = 0; | |
public static final int SALT_INDEX = 1; | |
public static final int PBKDF2_INDEX = 2; | |
private static SecureRandom random = new SecureRandom(); | |
/** | |
* Returns a salted PBKDF2 hash of the password. | |
* | |
* @param password | |
* the password to hash | |
* @return a salted PBKDF2 hash of the password | |
*/ | |
public static Pair<String, String> createHash(String password) | |
throws NoSuchAlgorithmException, InvalidKeySpecException { | |
return createHash(password.toCharArray()); | |
} | |
/** | |
* Returns a salted PBKDF2 hash of the password. | |
* | |
* @param password | |
* the password to hash | |
* @return a salt and a salted PBKDF2 hash of the password | |
*/ | |
public static Pair<String, String> createHash(char[] password) | |
throws NoSuchAlgorithmException, InvalidKeySpecException { | |
// Generate a random salt | |
byte[] salt = new byte[SALT_BYTE_SIZE]; | |
random.nextBytes(salt); | |
// Hash the password | |
byte[] hash = pbkdf2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE); | |
return new Pair<String, String>(toHex(salt), toHex(hash)); | |
} | |
/** | |
* Validates a password using a hash. | |
* | |
* @param password | |
* the password to check | |
* @param correctHash | |
* the hash of the valid password | |
* @return true if the password is correct, false if not | |
*/ | |
public static boolean validatePassword(String password, String correctHash) | |
throws NoSuchAlgorithmException, InvalidKeySpecException { | |
return validatePassword(password.toCharArray(), correctHash); | |
} | |
/** | |
* Validates a password using a hash. | |
* | |
* @param password | |
* the password to check | |
* @param correctHash | |
* the hash of the valid password | |
* @return true if the password is correct, false if not | |
*/ | |
public static boolean validatePassword(char[] password, String correctHash) | |
throws NoSuchAlgorithmException, InvalidKeySpecException { | |
// Decode the hash into its parameters | |
String[] params = correctHash.split(":"); | |
int iterations = Integer.parseInt(params[ITERATION_INDEX]); | |
byte[] salt = fromHex(params[SALT_INDEX]); | |
byte[] hash = fromHex(params[PBKDF2_INDEX]); | |
// Compute the hash of the provided password, using the same salt, | |
// iteration count, and hash length | |
byte[] testHash = pbkdf2(password, salt, iterations, hash.length); | |
// Compare the hashes in constant time. The password is correct if | |
// both hashes match. | |
return slowEquals(hash, testHash); | |
} | |
public static boolean validatePassword(String password, String salt, String correctHash) | |
throws NoSuchAlgorithmException, InvalidKeySpecException { | |
// Decode the hash into its parameters | |
byte[] saltbytes = fromHex(salt); | |
byte[] hash = fromHex(correctHash); | |
// Compute the hash of the provided password, using the same salt, | |
// iteration count, and hash length | |
byte[] testHash = pbkdf2(password.toCharArray(), saltbytes, PBKDF2_ITERATIONS, hash.length); | |
// Compare the hashes in constant time. The password is correct if | |
// both hashes match. | |
return slowEquals(hash, testHash); | |
} | |
/** | |
* Compares two byte arrays in length-constant time. This comparison method | |
* is used so that password hashes cannot be extracted from an on-line | |
* system using a timing attack and then attacked off-line. | |
* | |
* @param a | |
* the first byte array | |
* @param b | |
* the second byte array | |
* @return true if both byte arrays are the same, false if not | |
*/ | |
private static boolean slowEquals(byte[] a, byte[] b) { | |
int diff = a.length ^ b.length; | |
for (int i = 0; i < a.length && i < b.length; i++) | |
diff |= a[i] ^ b[i]; | |
return diff == 0; | |
} | |
/** | |
* Computes the PBKDF2 hash of a password. | |
* | |
* @param password | |
* the password to hash. | |
* @param salt | |
* the salt | |
* @param iterations | |
* the iteration count (slowness factor) | |
* @param bytes | |
* the length of the hash to compute in bytes | |
* @return the PBDKF2 hash of the password | |
*/ | |
private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, | |
int bytes) throws NoSuchAlgorithmException, InvalidKeySpecException { | |
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8); | |
SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM); | |
return skf.generateSecret(spec).getEncoded(); | |
} | |
/** | |
* Converts a string of hexadecimal characters into a byte array. | |
* | |
* @param hex | |
* the hex string | |
* @return the hex string decoded into a byte array | |
*/ | |
private static byte[] fromHex(String hex) { | |
return ByteUtil.fromHex(hex); | |
} | |
/** | |
* Converts a byte array into a hexadecimal string. | |
* | |
* @param array | |
* the byte array to convert | |
* @return a length*2 character string encoding the byte array | |
*/ | |
private static String toHex(byte[] array) { | |
return ByteUtil.toHex(array); | |
} | |
/** | |
* Tests the basic functionality of the PasswordHash class | |
* | |
* @param args | |
* ignored | |
*/ | |
public static void main(String[] args) { | |
try { | |
Pair<String, String> hash = createHash("abc"); | |
System.out.println(validatePassword("abc", hash.getFirst(), hash.getSecond())); | |
} catch (Exception ex) { | |
System.out.println("ERROR: " + ex); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class ProPertyClone { | |
private Map<String, Object> mapProterty = new HashMap<String, Object>(); //对象属性列表 | |
private Map<String, String> mapSetMethod = new HashMap<String, String>(); //对象set方法列表 | |
private Map<String, String> mapGetMethod = new HashMap<String, String>(); //对象get方法列表 | |
public Map<String, String> getMapGetMethod() | |
{ | |
return mapGetMethod; | |
} | |
public Map<String, String> getSetMapMethod() | |
{ | |
return mapSetMethod; | |
} | |
//通过对象获得方法列表 | |
public void GetMathodFromObject(Object args, String mtype ) { | |
String cls = args.getClass().toString(); | |
String b[] = cls.split(" "); | |
Class cla=null; | |
try { | |
cla=Class.forName(b[1]); | |
} catch (ClassNotFoundException e) { | |
e.printStackTrace(); | |
} | |
Field[] f=cla.getDeclaredFields(); | |
//获取字段名 | |
for(int i=0;i<f.length;i++){ | |
String name = f[i].getName(); | |
name = mtype + name.substring(0, 1).toUpperCase() + name.substring(1); | |
mapProterty.put( name, "1" ); | |
} | |
try | |
{ | |
//获取方法名 | |
Class<?> clazz = Class.forName( b[1] ); | |
Method methlist[] = clazz.getDeclaredMethods(); | |
for (int i = 0; i < methlist.length; i++) { | |
Method m = methlist[i]; | |
String parameterName = null; | |
Class<?>[] parameterTypes = m.getParameterTypes(); | |
for (Class<?> clas : parameterTypes) { | |
parameterName = clas.getName(); | |
//System.out.println("参数名称:" + parameterName+":"+ parameterTypes.length ); | |
break; | |
} | |
if( mapProterty.get( m.getName() ) != null ) | |
{ | |
if( parameterName!=null) | |
{ | |
mapSetMethod.put( m.getName(), parameterName ); | |
} | |
else | |
{ | |
mapGetMethod.put( m.getName(), "1" ); | |
} | |
} | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
public static Class getParamType( String pname ) | |
{ | |
if( pname.equalsIgnoreCase("long")) | |
{ | |
return long.class; | |
} | |
if( pname.equalsIgnoreCase("int")) | |
{ | |
return int.class; | |
} | |
if( pname.equalsIgnoreCase("short")) | |
{ | |
return short.class; | |
} | |
if( pname.equalsIgnoreCase("byte")) | |
{ | |
return byte.class; | |
} | |
if( pname.equalsIgnoreCase("double")) | |
{ | |
return double.class; | |
} | |
if( pname.equalsIgnoreCase("boolean")) | |
{ | |
return boolean.class; | |
} | |
if( pname.equalsIgnoreCase("float")) | |
{ | |
return float.class; | |
} | |
if( pname.equalsIgnoreCase("char")) | |
{ | |
return char.class; | |
} | |
if( pname.equalsIgnoreCase("java.lang.String")) | |
{ | |
return java.lang.String.class; | |
} | |
if( pname.equalsIgnoreCase("java.util.List")) | |
{ | |
return java.util.List.class; | |
} | |
if( pname.equalsIgnoreCase("java.util.Map")) | |
{ | |
return java.util.Map.class; | |
} | |
else | |
{ | |
System.err.println("not identification--------------"+ pname ); | |
} | |
return null; | |
} | |
public static Class getObjectType( String pname ) | |
{ | |
Class clazz=null; | |
try | |
{ | |
clazz = Class.forName( pname ); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return clazz; | |
} | |
public static Object getObject( String pname ) | |
{ | |
Object object=null; | |
try | |
{ | |
Class clazz = Class.forName( pname ); | |
object=clazz.newInstance(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return object; | |
} | |
//对象属性克隆 | |
/* | |
* objectsrc 原始对象,被克隆对象 | |
* objecttag 目标对象,克隆对象 | |
*/ | |
public static int Clone( Object objectsrc, Object objecttag ) | |
{ | |
try | |
{ | |
String cls = objecttag.getClass().toString(); | |
String ctag[] = cls.split(" "); | |
Class tagclazz = Class.forName( ctag[1] ); | |
cls = objectsrc.getClass().toString(); | |
String csrc[] = cls.split(" "); | |
Class srcclazz = Class.forName( csrc[1] ); | |
//获取原始对象的get set 方法 | |
ProPertyClone src = new ProPertyClone(); | |
src.GetMathodFromObject( objectsrc, "get" ); | |
Map<String, String> mSetMethod = src.getSetMapMethod(); | |
src.GetMathodFromObject( objectsrc, "set" ); | |
Map<String, String> mGetMethod = src.getMapGetMethod(); | |
//获取目标对象的get set 方法 | |
ProPertyClone tag = new ProPertyClone(); | |
tag.GetMathodFromObject( objecttag, "set" ); | |
Map<String, String> tagmapMethod = tag.getSetMapMethod(); | |
for (Map.Entry<String, String> entry : tagmapMethod.entrySet()) { | |
String name = "get" + entry.getKey().substring(3); | |
if ( src.getMapGetMethod().get( name )==null) | |
{ | |
continue; | |
} | |
Method tagmethod = null; | |
Class tagPara = ProPertyClone.getParamType( entry.getValue() ); | |
if( tagPara == null ) | |
{ | |
tagmethod = tagclazz.getMethod( name ); | |
Object params = tagmethod.invoke( objecttag ); | |
if( params == null ) | |
{ | |
tagPara = getObjectType( entry.getValue() ); | |
params = getObject( entry.getValue() ); | |
Object[] arguments = new Object[] { params }; | |
tagmethod = tagclazz.getMethod( entry.getKey(), new Class[] { tagPara } ); | |
tagmethod.invoke( objecttag , arguments); | |
//System.err.println( name + " return null "); | |
} | |
/* | |
//is object exist | |
tagmethod = tagclazz.getMethod( name ); | |
params = tagmethod.invoke( objecttag ); | |
if( params == null ) | |
{ | |
System.err.println( name + " return null "); | |
} | |
*/ | |
} | |
else | |
{ | |
Method srcmethod = srcclazz.getMethod( name ); | |
Object params = srcmethod.invoke( objectsrc ); | |
Object[] arguments = new Object[] { params }; | |
tagmethod = tagclazz.getMethod( entry.getKey(), new Class[] { tagPara } ); | |
tagmethod.invoke( objecttag , arguments); | |
} | |
} | |
return 0; | |
} | |
catch( Exception e) | |
{ | |
e.printStackTrace(); | |
} | |
return -1; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Random; | |
public class RandomUtil { | |
private static ThreadLocal<Random> randoms = new ThreadLocal<Random>(){ | |
@Override | |
protected Random initialValue() { | |
return new Random(); | |
} | |
}; | |
public static int nextInt(int high) { | |
return randoms.get().nextInt(high); | |
} | |
public static long nextLong() { | |
return randoms.get().nextLong(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.apache.commons.lang.StringUtils; | |
public class RegexUtils { | |
/** | |
* 用户名是否符合规范(^[\u4E00-\u9FA5A-Za-z0-9_]+$) | |
* @return | |
*/ | |
public static boolean isValidUsername(String username) { | |
if (StringUtils.isBlank(username)) { | |
return false; | |
} | |
return username.matches("^[\u4E00-\u9FA5A-Za-z0-9_]{3,10}$"); | |
} | |
/** | |
* 密码是否符合规范([a-zA-Z\d]{6,20}) | |
* @return | |
*/ | |
public static boolean isValidPassword(String password) { | |
if (null == password) { | |
return false; | |
} | |
return password.matches("^([^\\s'‘’]{6,20})$"); | |
} | |
/** | |
* 是否有效手机号码 | |
* @param mobileNum | |
* @return | |
*/ | |
public static boolean isMobileNum(String mobileNum) { | |
if (null == mobileNum) { | |
return false; | |
} | |
return mobileNum.matches("^((13[0-9])|(14[4,7])|(15[^4,\\D])|(17[0-9])|(18[0-9]))(\\d{8})$"); | |
} | |
/** | |
* 是否有效邮箱 | |
* @param email | |
* @return | |
*/ | |
public static boolean isEmail(String email) { | |
if (null == email) { | |
return false; | |
} | |
return email.matches("^([a-zA-Z0-9])+([a-zA-Z0-9_.-])+@([a-zA-Z0-9_-])+((\\.[a-zA-Z0-9_-]{2,3}){1,2})$"); | |
} | |
/** | |
* 是否是QQ邮箱 | |
*/ | |
public static boolean isQQEmail(String email){ | |
if(null == email) | |
return false; | |
return email.matches("^[\\s\\S]*@qq.com$"); | |
} | |
/** | |
* 是否数字(小数||整数) | |
* @param number | |
* @return | |
*/ | |
public static boolean isNumber(String number) { | |
if (null == number) { | |
return false; | |
} | |
return number.matches("^[+-]?(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d)+)?$"); | |
} | |
/** | |
* 是否整数 | |
* @param number | |
* @return | |
*/ | |
public static boolean isInt(String number) { | |
if (null == number) { | |
return false; | |
} | |
return number.matches("^[+-]?(([1-9]{1}\\d*)|([0]{1}))$"); | |
} | |
public static boolean isMoney(String number) { | |
if (null == number) { | |
return false; | |
} | |
return number.matches("^(([1-9]\\d*)(\\.\\d{1,2})?)$|(0\\.0?([1-9]\\d?))$"); | |
} | |
/** | |
* 是否正整数 | |
* @param number | |
* @return | |
*/ | |
public static boolean isPositiveInt(String number) { | |
if (null == number) { | |
return false; | |
} | |
return number.matches("^[+-]?(([1-9]{1}\\d*)|([0]{1}))$"); | |
} | |
/** | |
* 是否日期yyyy-mm-dd(yyyy/mm/dd) | |
* @param date | |
* @return | |
*/ | |
public static boolean isDate(String date) { | |
if (null == date) { | |
return false; | |
} | |
return date.matches("^([1-2]\\d{3})[\\/|\\-](0?[1-9]|10|11|12)[\\/|\\-]([1-2]?[0-9]|0[1-9]|30|31)$"); | |
} | |
/** | |
* 逗号分隔的正则表达式 | |
* @param str | |
* @return | |
*/ | |
public static String getCommaSparatedRegex(String str) { | |
if (str == null) { | |
return null; | |
} | |
return "^("+str+")|([\\s\\S]*,"+str+")|("+str+",[\\s\\S]*)|([\\s\\S]*,"+str+",[\\s\\S]*)$"; | |
} | |
/** | |
* 字符串包含 | |
* @return | |
*/ | |
public static boolean contains(String str, String regex) { | |
if (str == null || regex == null) { | |
return false; | |
} | |
return str.matches(regex); | |
} | |
/** | |
* 是否为16-22位银行账号 | |
* @param bankAccount | |
* @return | |
*/ | |
public static boolean isBankAccount(String bankAccount){ | |
if (null == bankAccount) { | |
return false; | |
} | |
return bankAccount.matches("^\\d{12,22}$"); | |
} | |
public static void main(String ...args) { | |
System.out.println(isMoney("100.001")); | |
System.out.println(isMoney("1.")); | |
System.out.println(isMoney("0.11")); | |
System.out.println(isMoney("1.1.001")); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.HashMap; | |
import java.util.Map; | |
import javax.servlet.http.Cookie; | |
import javax.servlet.http.HttpServletRequest; | |
import org.springframework.ui.ModelMap; | |
import org.springframework.web.bind.ServletRequestBindingException; | |
import org.springframework.web.bind.ServletRequestUtils; | |
public class RequestUtil { | |
public static String getCookie(HttpServletRequest request, String name) { | |
Cookie[] cookies = request.getCookies(); | |
if (cookies == null) | |
return null; | |
for (Cookie cookie : cookies) { | |
if (cookie.getName().equals(name)) { | |
return cookie.getValue(); | |
} | |
} | |
return null; | |
} | |
public static String getParameter(HttpServletRequest request, String name, | |
String def) { | |
return ServletRequestUtils.getStringParameter(request, name, def); | |
} | |
public static int getIntParameter(HttpServletRequest request, String name, | |
int def) { | |
String value = null; | |
try { | |
value = ServletRequestUtils.getStringParameter(request, name); | |
} catch (ServletRequestBindingException e) { | |
} | |
return StringUtil.convertInt(value, def); | |
} | |
public static long getLongParameter(HttpServletRequest request, | |
String name, long def) { | |
String value = null; | |
try { | |
value = ServletRequestUtils.getStringParameter(request, name); | |
} catch (ServletRequestBindingException e) { | |
} | |
return StringUtil.convertLong(value, def); | |
} | |
/** | |
* 获得当前的服务器路径 | |
* | |
* @param request | |
* @return | |
*/ | |
public static String getMainPath(HttpServletRequest request) { | |
return Utils.getMainPath(); | |
} | |
/** | |
* 统一返回错误页 | |
* @param mm | |
* @param msg | |
* @param code | |
*/ | |
public static void addErrorMsg(ModelMap mm, String msg, int code) { | |
Map<String,String> common_error = new HashMap<String, String>(3); | |
common_error.put("code", String.valueOf(code)); | |
common_error.put("msg", msg); | |
mm.addAttribute("common_error", common_error); | |
} | |
/** | |
* 获取远程地址 | |
*/ | |
public static String getRemoteIp(HttpServletRequest req) { | |
String ip = req.getHeader("X-Forwarded-For"); | |
if(StringUtil.isEmpty(ip)) { | |
ip = req.getRemoteHost(); | |
} | |
return ip; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.OutputStream; | |
import javax.servlet.http.Cookie; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
public class ResponseUtil { | |
public static void addCookie(HttpServletResponse resp, String name, String value, int expire) { | |
Cookie cookie = new Cookie(name, value); | |
cookie.setMaxAge(expire); | |
resp.addCookie(cookie); | |
} | |
public static void writeJson(HttpServletResponse resp, JsonHolder jo) throws IOException { | |
writeJson(resp, jo, 0); | |
} | |
public static void writeJsonP(HttpServletResponse resp, JsonHolder jo, String callback, int cachetime) throws IOException { | |
if(cachetime == 0 ) { | |
resp.setHeader("Cache-Control", "no-cache"); | |
resp.setHeader("Pragma", "no-cache"); | |
} | |
else { | |
resp.setHeader("Cache-Control", "max-age="+cachetime); | |
} | |
resp.setContentType("text/javascript;charset=utf-8"); | |
resp.getWriter().write(filterCallbackName(callback)+"("+jo.toString()+")"); | |
} | |
public static void writeAppJson(HttpServletResponse resp, JsonHolder jo) throws IOException { | |
jo.addValue("sys_time", MilliSecClock.currentTimeMillis()); | |
writeAppJson(resp, jo, 0); | |
} | |
private static String filterCallbackName(String cb) { | |
StringBuilder sb = new StringBuilder(); | |
char ch; | |
for(int i=0;i<cb.length();i++) { | |
ch = cb.charAt(i); | |
if((ch>='0' && ch <='9') || (ch>='a'&&ch<='z') ||(ch>='A'&&ch<='Z') || ch=='_') { | |
sb.append(ch); | |
} | |
} | |
return sb.toString(); | |
} | |
public static void writeJsonP(HttpServletResponse resp, HttpServletRequest req, JsonHolder jo) throws IOException { | |
writeJsonP( resp, jo, filterCallbackName(RequestUtil.getParameter(req, "callback", "callback")), 0); | |
} | |
public static void writeJson(HttpServletResponse resp, JsonHolder jo, int cachetime) throws IOException { | |
resp.setHeader("Access-Control-Allow-Origin", "*"); | |
if(cachetime == 0 ) { | |
resp.setHeader("Cache-Control", "no-cache"); | |
resp.setHeader("Pragma", "no-cache"); | |
} | |
else { | |
resp.setHeader("Cache-Control", "max-age="+cachetime); | |
} | |
resp.setContentType("application/json;charset=utf-8"); | |
resp.getWriter().write(jo.toString()); | |
} | |
public static void writeAppJson(HttpServletResponse resp, JsonHolder jo, int cachetime) throws IOException { | |
resp.setHeader("Access-Control-Allow-Origin", "*"); | |
if(cachetime == 0 ) { | |
resp.setHeader("Cache-Control", "no-cache"); | |
resp.setHeader("Pragma", "no-cache"); | |
} | |
else { | |
resp.setHeader("Cache-Control", "max-age="+cachetime); | |
} | |
resp.setContentType("application/json;charset=utf-8"); | |
resp.getWriter().write(jo.toAppString()); | |
} | |
public static void writeText(HttpServletResponse resp, String text) throws IOException { | |
writeText(resp, text, 0); | |
} | |
public static void writeText(HttpServletResponse resp, String text, int cachetime) throws IOException { | |
resp.setContentType("application/text;charset=utf-8"); | |
resp.setHeader("Access-Control-Allow-Origin", "*"); | |
if(cachetime == 0 ) { | |
resp.setHeader("Cache-Control", "no-cache"); | |
resp.setHeader("Pragma", "no-cache"); | |
} | |
else { | |
resp.setHeader("Cache-Control", "max-age="+cachetime); | |
} | |
resp.getWriter().write(text); | |
} | |
public static void writeInputStream(HttpServletResponse resp, InputStream in, String type) { | |
try { | |
resp.setContentType(type); | |
byte[] bs = new byte[1024]; | |
OutputStream out = resp.getOutputStream(); | |
int len = 0; | |
while((len=in.read(bs)) >= 0) { | |
out.write(bs, 0, len); | |
} | |
in.close(); | |
} | |
catch(Throwable th) { | |
BizLogger.error(th, "writeInputStream"); | |
} | |
} | |
public static void writeCaptcha(HttpServletResponse resp, InputStream in) { | |
writeInputStream(resp, in, "image/png"); | |
} | |
public static void addCookie(HttpServletResponse resp, HttpServletRequest req, String key, String value, int maxAgeInSec, boolean httpOnly) { | |
Cookie cookie = new Cookie(key, value); | |
cookie.setHttpOnly(httpOnly); | |
cookie.setMaxAge(maxAgeInSec); | |
String domain = AppConfig.get("app.backendhostname", ""); | |
if(!StringUtil.isEmpty(domain)) { | |
cookie.setDomain(domain); | |
cookie.setPath("/"); | |
} | |
else { | |
cookie.setPath(req.getContextPath()); | |
} | |
resp.addCookie(cookie); | |
} | |
public static void addCookie(HttpServletResponse resp, HttpServletRequest req, String key, String value, boolean httpOnly) { | |
Cookie cookie = new Cookie(key, value); | |
cookie.setHttpOnly(httpOnly); | |
String domain = AppConfig.get("app.backendhostname", ""); | |
if(!StringUtil.isEmpty(domain)) { | |
cookie.setDomain(domain); | |
cookie.setPath("/"); | |
} | |
else { | |
cookie.setPath(req.getContextPath()); | |
} | |
cookie.setMaxAge(-1); | |
resp.addCookie(cookie); | |
} | |
public static void delCookie(HttpServletResponse resp, HttpServletRequest req, String key) { | |
Cookie cookie = new Cookie(key, ""); | |
String domain = AppConfig.get("app.backendhostname", ""); | |
if(!StringUtil.isEmpty(domain)) { | |
cookie.setDomain(domain); | |
cookie.setPath("/"); | |
} | |
else { | |
cookie.setPath(req.getContextPath()); | |
} | |
cookie.setMaxAge(0); | |
resp.addCookie(cookie); | |
} | |
public static void main(String ...args) { | |
Cookie cookie = new Cookie("key", "value"); | |
cookie.setHttpOnly(false); | |
cookie.setMaxAge(-1); | |
cookie.setPath("/"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import java.util.Date; | |
public class SafeSimpleDateFormat { | |
private ThreadLocal<SimpleDateFormat> localSimpleDateFormat; | |
public SafeSimpleDateFormat(SimpleDateFormat sdf) { | |
final SimpleDateFormat simpleDateFormat=sdf; | |
localSimpleDateFormat=new ThreadLocal<SimpleDateFormat>() { | |
@Override | |
protected SimpleDateFormat initialValue() { | |
return (SimpleDateFormat)simpleDateFormat.clone(); | |
} | |
}; | |
} | |
public SafeSimpleDateFormat(String format) { | |
final String fformat=format; | |
localSimpleDateFormat=new ThreadLocal<SimpleDateFormat>() { | |
@Override | |
protected SimpleDateFormat initialValue() { | |
return new SimpleDateFormat(fformat); | |
} | |
}; | |
} | |
public String format(Date date) { | |
return localSimpleDateFormat.get().format(date); | |
} | |
public String format(long time) { | |
return localSimpleDateFormat.get().format(time); | |
} | |
public Date parse(String time) throws ParseException { | |
return localSimpleDateFormat.get().parse(time); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.security.MessageDigest; | |
import java.security.SecureRandom; | |
public class SaltGenerator { | |
public static byte[] doGen(int len) { | |
SecureRandom random = new SecureRandom(); | |
byte bytes[] = new byte[len]; | |
random.nextBytes(bytes); | |
return bytes; | |
} | |
public static String doGenHex(int len) { | |
return HexUtil.bytes2HexStr(doGen(len)); | |
} | |
public static byte[] addSalt(String hexSalt, byte[] plain) { | |
byte[] saltBytes = HexUtil.hexStr2Bytes(hexSalt); | |
return addSalt(saltBytes, plain); | |
} | |
public static byte[] addSalt(byte[] salt, byte[] plain) { | |
byte[] saltBytes = salt; | |
byte[] rets = new byte[plain.length+saltBytes.length]; | |
System.arraycopy(plain, 0, rets, 0, plain.length); | |
System.arraycopy(saltBytes, 0, rets, plain.length, saltBytes.length); | |
return rets; | |
} | |
public static String addSalt2Hex(byte[] salt, byte[] plain) { | |
return HexUtil.bytes2HexStr(addSalt(salt, plain)); | |
} | |
public static String saltPwd(String pwd, byte [] salt) { | |
try { | |
byte[] bs = addSalt(salt, pwd.getBytes("utf-8")); | |
MessageDigest md = MessageDigest.getInstance("MD5"); | |
md.update(bs); | |
return HexUtil.bytes2HexStr(md.digest()); | |
} | |
catch(Throwable th) { | |
th.printStackTrace(); | |
} | |
return null; | |
} | |
public static void main(String ...args) throws Throwable { | |
String pwd = "123456"; | |
byte[] bytes = addSalt(HexUtil.hexStr2Bytes("385B732EEEB4DA100F6A4E2B790567DE"), pwd.getBytes()); | |
MessageDigest md = MessageDigest.getInstance("MD5"); | |
md.update(bytes); | |
System.out.println(HexUtil.bytes2HexStr(md.digest())); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.springframework.beans.BeansException; | |
import org.springframework.context.ApplicationContext; | |
import org.springframework.context.ApplicationContextAware; | |
import org.springframework.stereotype.Component; | |
@Component | |
public class SpringContextUtil implements ApplicationContextAware { | |
private static ApplicationContext applicationContext; // Spring应用上下文环境 | |
/* | |
* 实现了ApplicationContextAware 接口,必须实现该方法; | |
* 通过传递applicationContext参数初始化成员变量applicationContext | |
*/ | |
public void setApplicationContext(ApplicationContext applicationContext) | |
throws BeansException { | |
SpringContextUtil.applicationContext = applicationContext; | |
} | |
public static ApplicationContext getApplicationContext() { | |
return applicationContext; | |
} | |
@SuppressWarnings("unchecked") | |
public static <T> T getBean(String name) throws BeansException { | |
return (T) applicationContext.getBean(name); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class StringHolder { | |
public String value; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.net.URLDecoder; | |
import java.net.URLEncoder; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
public class StringUtil { | |
public static String encodeUrl(String url) { | |
String encodedUrl=""; | |
try { | |
encodedUrl=URLEncoder.encode(url, "utf-8"); | |
} catch(Throwable t) { | |
} | |
return encodedUrl; | |
} | |
public static String encodeUrl(String url, String charset) { | |
String encodedUrl=""; | |
try { | |
encodedUrl=URLEncoder.encode(url,charset).replace("+", "%20"); | |
} catch(Throwable t) { | |
} | |
return encodedUrl; | |
} | |
public static String decodeUrl(String url) { | |
String decodedUrl=""; | |
try { | |
decodedUrl=URLDecoder.decode(url,"utf-8"); | |
} catch(Throwable t) { | |
} | |
return decodedUrl; | |
} | |
public static String decodeUrl(String url, String charset) { | |
String decodedUrl=""; | |
try { | |
decodedUrl=URLDecoder.decode(url,charset); | |
} catch(Throwable t) { | |
} | |
return decodedUrl; | |
} | |
public static String join(Object[] objs, String seperator) { | |
if(objs == null) return ""; | |
StringBuilder sb = new StringBuilder(); | |
for(int i=0;i<objs.length;i++) { | |
sb.append(objs[i]); | |
if(i<objs.length-1) { | |
sb.append(seperator); | |
} | |
} | |
return sb.toString(); | |
} | |
public static String join(Collection<?> objs, String seperator) { | |
StringBuilder sb = new StringBuilder(); | |
int count = objs.size(); | |
for(Object obj:objs) { | |
sb.append(obj); | |
--count; | |
if(count>0) { | |
sb.append(seperator); | |
} | |
} | |
return sb.toString(); | |
} | |
public static String join(Object[] objs) { | |
return join(objs, "|"); | |
} | |
public static String join(Object obj, int count, String seperator) { | |
StringBuilder sb = new StringBuilder(); | |
for(int i=0;i<count;i++) { | |
sb.append(String.valueOf(obj)); | |
if(i<count-1) { | |
sb.append(seperator); | |
} | |
} | |
return sb.toString(); | |
} | |
public static boolean isEmpty(String str) { | |
return str == null || str.isEmpty() || str.trim().length()==0; | |
} | |
public static int convertInt(String str, int def) { | |
try { | |
if(str == null) return def; | |
return Integer.valueOf(str); | |
} | |
catch(NumberFormatException th) { | |
return def; | |
} | |
} | |
public static boolean convertBoolean(String str, boolean def) { | |
try { | |
if(str == null) return def; | |
return Boolean.valueOf(str); | |
} | |
catch(NumberFormatException th) { | |
return def; | |
} | |
} | |
public static String encodeSQL(String sql) { | |
if (sql == null) | |
{ | |
return ""; | |
} | |
StringBuilder sb = new StringBuilder(); | |
for(int i = 0; i < sql.length(); ++i) | |
{ | |
char c = sql.charAt(i); | |
switch(c) | |
{ | |
case '\\': | |
sb.append("\\\\"); | |
break; | |
case '\r': | |
sb.append("\\r"); | |
break; | |
case '\n': | |
sb.append("\\n"); | |
break; | |
case '\t': | |
sb.append("\\t"); | |
break; | |
case '\b': | |
sb.append("\\b"); | |
break; | |
case '\'': | |
sb.append("\'\'"); | |
break; | |
case '\"': | |
sb.append("\\\""); | |
break; | |
case '\u200B': | |
case '\uFEFF': | |
break; | |
default: | |
sb.append(c); | |
} | |
} | |
return sb.toString(); | |
} | |
public static double convertDouble(String str, double def) { | |
try { | |
if(str == null) return def; | |
return Double.valueOf(str); | |
} | |
catch(NumberFormatException th) { | |
return def; | |
} | |
} | |
public static long convertLong(String str, long def) { | |
try { | |
if(str == null) return def; | |
return Long.valueOf(str); | |
} | |
catch(NumberFormatException th) { | |
return def; | |
} | |
} | |
public static boolean converBool(String str, boolean def) { | |
try { | |
return Boolean.parseBoolean(str); | |
} | |
catch(Exception e) { | |
return def; | |
} | |
} | |
public static boolean equals(String str1, String str2) { | |
if(str1 == null && str2 == null) return false; | |
if(str1 == str2) return true; | |
if(str1 != null) return str1.equals(str2); | |
else if(str2 != null) return str2.equals(str1); | |
return false; | |
} | |
public static boolean equalsIgnoreCase(String str1, String str2) { | |
return equals(str1, str2) || (str1!=null && str2!=null && str1.equalsIgnoreCase(str2)); | |
} | |
public static String toString(String str) { | |
if(str == null) return ""; | |
else { | |
return str; | |
} | |
} | |
public static byte[] toUtf8Bytes(String str) { | |
try { | |
return String.valueOf(isEmpty(str)?"":str).getBytes(Charsets.UTF8); | |
} | |
catch(Throwable th) { | |
return null; | |
} | |
} | |
public static String fromUtf8Bytes(byte[] bytes) { | |
try { | |
return new String(bytes, Charsets.UTF8); | |
} | |
catch(Throwable th) { | |
return ""; | |
} | |
} | |
/** | |
* 分割字符串 | |
* @param line 原始字符串 | |
* @param seperator 分隔符 | |
* @return 分割结果 | |
*/ | |
public static String[] split(String line, String seperator) | |
{ | |
if(line == null || seperator == null || seperator.length() == 0) | |
return null; | |
ArrayList<String> list = new ArrayList<String>(); | |
int pos1 = 0; | |
int pos2; | |
for(; ; ) | |
{ | |
pos2 = line.indexOf(seperator, pos1); | |
if(pos2 < 0) | |
{ | |
list.add(line.substring(pos1)); | |
break; | |
} | |
list.add(line.substring(pos1, pos2)); | |
pos1 = pos2 + seperator.length(); | |
} | |
// 去掉末尾的空串,和String.split行为保持一致 | |
for(int i = list.size() - 1; i >= 0 && list.get(i).length() == 0; --i) | |
{ | |
list.remove(i); | |
} | |
return list.toArray(new String[0]); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Triple<F, S, T> { | |
private F first; | |
private S second; | |
private T third; | |
public Triple() { | |
super(); | |
} | |
public Triple(F first, S second, T third) { | |
super(); | |
this.first = first; | |
this.second = second; | |
this.third = third; | |
} | |
public F getFirst() { | |
return first; | |
} | |
public void setFirst(F first) { | |
this.first = first; | |
} | |
public S getSecond() { | |
return second; | |
} | |
public void setSecond(S second) { | |
this.second = second; | |
} | |
public T getThird() { | |
return third; | |
} | |
public void setThird(T third) { | |
this.third = third; | |
} | |
public String toString() { | |
return String.valueOf(first)+"|"+String.valueOf(second)+"|"+String.valueOf(third); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import java.util.ArrayList; | |
import java.util.Calendar; | |
import java.util.Collection; | |
import java.util.Date; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.TimeZone; | |
import java.util.UUID; | |
import java.util.regex.Matcher; | |
import java.util.regex.Pattern; | |
import org.apache.commons.lang.StringUtils; | |
/** | |
* 大杂烩工具类 | |
* | |
* @author user | |
* | |
*/ | |
public class Utils { | |
public static final SafeSimpleDateFormat DATE_NORMAL_SDF = new SafeSimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
public static final SafeSimpleDateFormat DATE_SIMPLE_SDF = new SafeSimpleDateFormat("yyyyMMdd"); | |
public static final SafeSimpleDateFormat YYYY_MM_DD_HH = new SafeSimpleDateFormat("yyyyMMddHH"); | |
public static final SafeSimpleDateFormat YYYY_MM_DD_SDF = new SafeSimpleDateFormat("yyyy-MM-dd"); | |
public static final SafeSimpleDateFormat YYYYMMDD_SLASH = new SafeSimpleDateFormat("yyyy/MM/dd"); | |
public static final SafeSimpleDateFormat YYYY_MM_DD_HH_mm_HZ_SDF = new SafeSimpleDateFormat("yyyy年MM月dd日HH点mm分"); | |
public static final SafeSimpleDateFormat YYYY_MM_DD_HZ_SDF = new SafeSimpleDateFormat("yyyy年MM月dd日"); | |
public static final SafeSimpleDateFormat HH_mm_ss_HZ_SDF = new SafeSimpleDateFormat("H点m分"); | |
public static final SafeSimpleDateFormat MM_DD_HH_mm_HZ_SDF = new SafeSimpleDateFormat("MM月dd日HH点mm分"); | |
public static final String DATE_NORMAL = "yyyy-MM-dd HH:mm:ss"; | |
public static final String DATE_SIMPLE = "yyyyMMdd"; | |
public static final int MILLIS_PER_SECOND = 1000; //一秒的毫秒数 | |
public static final int MILLIS_PER_MINUTE = MILLIS_PER_SECOND * 60; //一分钟的毫秒数 | |
public static final int MILLIS_PER_HOUR = MILLIS_PER_MINUTE * 60; //一小时的毫秒数 | |
public static final int MILLIS_PER_DAY = MILLIS_PER_HOUR * 24; //一天的毫秒数 | |
public static final int TIME_STAMP_LENGTH = 24; //最多保存连续24个月的记录 | |
public static final long TIME_OFFSET = TimeZone.getDefault().getRawOffset(); | |
public static boolean isVipAccount(long uid) { | |
return BidComposateAccount.isBidVip(uid) | |
|| PackComposateAccountManager.INSTANCE.isVip(uid); | |
} | |
public static String uuid() { | |
return UUID.randomUUID().toString(); | |
} | |
/** | |
* 将分为单位的金额取整百 | |
* @param money | |
* @return | |
*/ | |
public static long formatHandredMoney(long money){ | |
return money-money%10000; | |
} | |
/** | |
* 将一个以分为单位的amt格式化成#####.## | |
* | |
* @param amt | |
* @return | |
*/ | |
public static String formatMoney(long amt) { | |
return amt / 100 + "." + String.format("%02d", amt % 100); | |
} | |
/** | |
* 将一个以分为单位的amt格式化成###,###.## | |
* | |
* @param amt | |
* @return | |
*/ | |
public static String formatCNMoney(long amt){ | |
return formatCNMoney(amt,false); | |
} | |
public static String formatCNMoney(long amt,boolean isHandred) { | |
StringBuilder sb = new StringBuilder(); | |
if (amt < 0) { | |
amt = -amt; | |
sb.append("-"); | |
} | |
List<String> strs = new ArrayList<String>(5); | |
long dots = isHandred?0:(amt % 100); | |
amt /= 100; | |
long tmp = 0; | |
if(isHandred){ | |
amt -= amt%100; | |
} | |
if (amt == 0) { | |
sb.append("0"); | |
} else { | |
while (amt > 0) { | |
tmp = amt % 1000; | |
amt -= tmp; | |
amt /= 1000; | |
if (amt == 0) { | |
strs.add(String.valueOf(tmp)); | |
} else { | |
strs.add(String.format("%03d", tmp)); | |
} | |
} | |
for (int i = strs.size() - 1; i >= 0; i--) { | |
sb.append(strs.get(i)); | |
if (i > 0) { | |
sb.append(","); | |
} | |
} | |
} | |
sb.append("."); | |
sb.append(String.format("%02d", dots)); | |
return sb.toString(); | |
} | |
public static String format(Date date) { | |
return DATE_NORMAL_SDF.format(date); | |
} | |
public static String format(long time) { | |
return DATE_NORMAL_SDF.format(time); | |
} | |
public static String formatDate(long time) { | |
return YYYY_MM_DD_SDF.format(time); | |
} | |
public static String YYYYMMDD_SLASH(long time) { | |
return YYYYMMDD_SLASH.format(time); | |
} | |
public static String formatYMD(long time) { | |
return YYYY_MM_DD_SDF.format(time); | |
} | |
public static int formatYMD_INT(long time) { | |
String ymds = DATE_SIMPLE_SDF.format(time); | |
int ymd = Integer.valueOf(ymds); | |
return ymd; | |
} | |
/** 获得time 对应昨天 0时0分0秒0毫秒 时间 */ | |
public static long getYestodayMilliStart(long time){ | |
return getDayMilliStart(time)-86400 * 1000; | |
} | |
public static Long parse(String ymdHMS) { | |
try { | |
return DATE_NORMAL_SDF.parse(ymdHMS).getTime(); | |
}catch(Throwable th) { | |
return 0L; | |
} | |
} | |
public static long formatString(String times, SafeSimpleDateFormat perten) throws ParseException { | |
return perten.parse(times).getTime(); | |
} | |
public static long formatString(String times) throws ParseException { | |
SimpleDateFormat sdf = new SimpleDateFormat(DATE_NORMAL); | |
Date date = sdf.parse(times); | |
return date.getTime(); | |
} | |
public static String format(long date, SafeSimpleDateFormat f) { | |
if (f == null) { | |
return DATE_NORMAL_SDF.format(date); | |
} | |
return f.format(date); | |
} | |
public static String format(Date date, SafeSimpleDateFormat f) { | |
if (f == null) { | |
return format(date); | |
} | |
return f.format(date); | |
} | |
public static String getTmpPwd(String moblieNo, String idCardNo) | |
throws Throwable { | |
return MobileCodeVerifyer.genRandomPsw(); | |
} | |
/** | |
* 判断空集合 | |
* | |
* @param c | |
* @return | |
*/ | |
public static boolean isEmpty(Collection<?> c) { | |
return c == null || c.isEmpty(); | |
} | |
/** | |
* 判断空map | |
* @param m | |
* @return | |
*/ | |
public static boolean isEmpty(Map<?, ?> m) { | |
return m == null || m.isEmpty(); | |
} | |
/** | |
* 将****.**格式格式化成分为单位的金额 | |
* | |
* @param amt | |
* @return | |
*/ | |
public static long parseMoney(String amt) { | |
String[] strs = amt.split("\\."); | |
long result = Long.parseLong(strs[0]) * 100; | |
if (strs.length > 1) { | |
String point = strs[1].length()>2?strs[1].substring(0,2):strs[1]; | |
result += Long.parseLong(point) | |
* (point.length() <= 1 ? 10 : 1); | |
} | |
return result; | |
} | |
/** | |
* 获得time对应天的0点0分0秒的时间ms值 | |
* | |
* @param time | |
* @return | |
*/ | |
public static long getDayMilliStart(long time) { | |
Calendar cal = Calendar.getInstance(); | |
cal.setTimeInMillis(time); | |
cal.set(Calendar.HOUR_OF_DAY, 0); | |
cal.set(Calendar.MINUTE, 0); | |
cal.set(Calendar.SECOND, 0); | |
cal.set(Calendar.MILLISECOND, 0); | |
return cal.getTimeInMillis(); | |
} | |
/** | |
* 获得time对应天的23点59分59秒的时间ms值 | |
* | |
* @param end | |
* @return | |
*/ | |
public static long getDayMilliEnd(long end) { | |
return getDayMilliStart(end) + 86400 * 1000 -1; | |
} | |
/** | |
* 判断两个时间戳是否是1天内 | |
* @param d1 | |
* @param d2 | |
* @return | |
*/ | |
public static boolean isSameDay(long d1, long d2) { | |
return Math.abs(getDayMilliStart(d1)-d2) < 86400*1000; | |
} | |
/** | |
* 根据身份证获得年龄 | |
* | |
* @param idCardNo | |
* @return | |
*/ | |
public static int age(String idCardNo) { | |
return Calendar.getInstance().get(Calendar.YEAR) | |
- Integer.valueOf(idCardNo.substring(6, 10)); | |
} | |
public static Date birthday(String idCardNo) { | |
try { | |
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); | |
return sdf.parse(idCardNo.substring(6, 14)); | |
} catch (Throwable th) { | |
return null; | |
} | |
} | |
public static boolean isMale(String idCardNo) { | |
return Integer.valueOf(idCardNo.substring(16, 17)) == 1; | |
} | |
/** | |
* 按万分比计算金额 | |
* | |
* @param money | |
* 金额 | |
* @param rate | |
* 万分比 | |
* @return | |
*/ | |
public static long rateMoney(long money, int rate) { | |
return money * rate / 10000; | |
} | |
/** | |
* 将一个万分比的利率转换成##.##的形式,若小数位为00,则舍去小数位 | |
* | |
* @param rate | |
* @return | |
*/ | |
public static String formatRate(long rate) { | |
return rate % 100 == 0 ? rate / 100 + "" : rate / 100 + "." | |
+ String.format("%02d", rate % 100); | |
} | |
/** | |
* 预期收益 | |
* | |
* @param bid_corpus | |
* 借款本金 | |
* @param bid_apr | |
* 年利率 | |
* @param bid_period | |
* 期限,单位月 | |
* @param real_invest_expire_time | |
* 放款时间 | |
* @param cur_time | |
* 参照时间 | |
* @return null为异常,[当期还款时间,当期的剩余日息和] | |
*/ | |
public static Pair<Long, Long> getProfit(long bid_corpus, long bid_apr, | |
int bid_period, long real_invest_expire_time, long cur_time) { | |
if (cur_time < real_invest_expire_time || bid_period < 1 || bid_apr < 1) { | |
return null; | |
} | |
try { | |
Map<Integer, Date> repayment_times = getRepaymentTimeByPeriod( | |
real_invest_expire_time, bid_period); | |
int cur_period = 0; | |
long last_time = 0; // 上一次还款日 | |
long next_time = 0; // 最近的还款日 | |
long left_days_interest = 0;// 当期剩余天数的利息,包括当日 | |
for (int i = 1; i <= bid_period; i++) { | |
long t = repayment_times.get(i).getTime(); | |
if (cur_time > t) { | |
last_time = t; | |
} | |
if (next_time == 0 && cur_time <= t) { | |
next_time = t; | |
cur_period = i; | |
} | |
} | |
if (last_time == 0) { | |
last_time = real_invest_expire_time; | |
} | |
DEBX aount = getAmountInfo(bid_corpus, bid_apr, bid_period); | |
Map<Integer, DEBXPeriod> map = aount.getPeriods(); | |
long cur_interest = (long) map.get(cur_period).getMonPayInterest(); // 当期的应得利息 | |
int left_days = (int) Math.ceil((next_time - cur_time) | |
/ (24L * 60 * 60 * 1000.0)); | |
int cur_days = (int) Math.ceil((next_time - last_time) | |
/ (24L * 60 * 60 * 1000.0));// 当期一共多少天 | |
left_days_interest = left_days * cur_interest / cur_days;// 当天的利息要算给承接人 | |
return new Pair<Long, Long>(next_time, left_days_interest); | |
} catch (Exception e) { | |
BizLogger.error(e, "Utils.getProfit", bid_corpus, bid_apr, | |
bid_period, real_invest_expire_time, cur_time); | |
} | |
return null; | |
} | |
/** | |
* 等额本息算法 | |
* | |
* @param bid_corpus | |
* 总借款金额(本金) | |
* @param bid_apr | |
* 年利率 | |
* @param bid_period | |
* 期限,单位:月 | |
* @return | |
*/ | |
public static DEBX getAmountInfo(long bid_corpus, long bid_apr, | |
int bid_period) { | |
DEBX info = new DEBX(); | |
double monthRate = bid_apr / 10000.0 / 12;// 月利率 | |
double monPay = 0;// 每个月要还的金额 | |
double borrowSum = bid_corpus;// 本金总额 | |
double amount = bid_corpus; | |
double monPayInterest = 0;// 每个月利息(如果是天标的话,就是所有的利息) | |
double monPayAmount = 0;// 每个月本金 | |
double totalAmount = 0;// 总共要还的金额 | |
double payRemain = 0;// 剩余要还的金额 | |
double payAmount = 0;// 应付本金 | |
double payInterest = 0;// 应付利息 | |
// | |
monPay = Double.valueOf((amount * monthRate) | |
* Math.pow((1 + monthRate), bid_period)) | |
/ Double.valueOf(Math.pow((1 + monthRate), bid_period) - 1);// 每个月要还的本金和利息 | |
totalAmount = monPay * bid_period;// 总共要还的金额 | |
payRemain = totalAmount; | |
Map<Integer, DEBXPeriod> periods = new HashMap<Integer, DEBXPeriod>(); | |
for (int n = 1; n <= bid_period; n++) { | |
DEBXPeriod p = new DEBXPeriod(); | |
monPayInterest = Math.round(borrowSum * monthRate);// 每个月利息 | |
monPayAmount = Math.round((monPay - monPayInterest));// 每个月本金 | |
amount = amount - monPayAmount; | |
payRemain = totalAmount; | |
if (n == bid_period) { | |
monPay = payRemain; | |
monPayAmount = Math.round((borrowSum - payAmount)); | |
monPayInterest = Math.round(totalAmount - payAmount | |
- payInterest - monPayAmount); | |
} | |
p.setPeriod(n); | |
p.setMonPayAmount(monPayAmount); | |
p.setMonPayInterest(monPayInterest); | |
periods.put(n, p); | |
// | |
payAmount += monPayAmount; | |
payInterest += monPayInterest; | |
payRemain = payRemain - monPay; | |
} | |
info.setPeriods(periods); | |
info.setPayAmount(payAmount); | |
info.setPayInterest(payInterest); | |
info.setTotalAmount(Math.round(totalAmount)); | |
return info; | |
} | |
/** | |
* 线下等额本息算法 | |
* | |
* @param bid_amount | |
* 借款总额 | |
* @param bid_apr | |
* 年利率 | |
* @param bid_all_rate | |
* 总费率,不同标的的费率不同 | |
* @param period_payment | |
* 月还款金额 | |
* @param bid_period | |
* 期限 | |
* @return | |
* @throws Throwable | |
*/ | |
public static DEBX getAmountInfoOffLine(long bid_amount, | |
long bid_sign_amount, long bid_apr, long bid_all_rate, | |
long period_payment, int bid_period) throws Throwable { | |
long bid_corpus = Math.round(bid_amount | |
/ (1 + (bid_all_rate / 10000.0) * bid_period)); // 借款人到手金额 | |
double monPay = bid_corpus / bid_period + bid_corpus * bid_all_rate | |
/ 10000.0;// 月还款额 | |
double totalAmount = monPay * bid_period;// 总共要还的金额 | |
// | |
if (period_payment != Math.round(monPay)) {// 月还款额的核实 | |
throw new Throwable("period_repaymen is error"); | |
} | |
if (bid_amount != Math.round(totalAmount)) { | |
throw new Throwable("bid_amount is error"); | |
} | |
return getAmountInfoOffLineWithoutCheck(bid_sign_amount, bid_apr, period_payment, bid_period); | |
} | |
/** | |
* 不验证数据,专提供理财人计算当前费率 | |
* | |
* @param bid_sign_amount | |
* @param bid_apr | |
* @param bid_all_rate | |
* @param period_payment | |
* @param bid_period | |
* @return | |
*/ | |
public static DEBX getAmountInfoOffLineWithoutCheck(long bid_sign_amount, long bid_apr, | |
long period_payment, int bid_period){ | |
DEBX info = new DEBX(); | |
double monthRate = bid_apr / 10000.0 / 12;// 月利率 | |
double totalAmount = period_payment * bid_period ;// 总共要还的金额 | |
double payInterest = 0;// 应付利息 | |
double left_amount = bid_sign_amount;// 签约金额,剩余本金 | |
double payAmount = 0;//应付本金 | |
Map<Integer, DEBXPeriod> periods = new HashMap<Integer, DEBXPeriod>(); | |
for (int i = 1; i <= bid_period; i++) { | |
DEBXPeriod p = new DEBXPeriod(); | |
long cur_mon_interest = Math.round(left_amount * monthRate);// 当月利息 | |
long cur_mon_amount = period_payment - cur_mon_interest;// 当月本金 | |
if(i == bid_period){ | |
cur_mon_amount = Math.round(bid_sign_amount - payAmount); | |
cur_mon_interest = Math.round(period_payment - cur_mon_amount); | |
} | |
p.setPeriod(i); | |
p.setMonPayAmount(cur_mon_amount); | |
p.setMonPayInterest(cur_mon_interest); | |
periods.put(i, p); | |
left_amount = left_amount - cur_mon_amount; | |
payInterest += cur_mon_interest; | |
payAmount += cur_mon_amount; | |
} | |
info.setPeriods(periods); | |
info.setPayAmount(payAmount); | |
info.setPayInterest(payInterest); | |
info.setTotalAmount(totalAmount); | |
info.setPeriodRepayment(period_payment); | |
return info; | |
} | |
/** | |
* 获取每个月借款人的账单,按月还息到期还本算法 | |
* @param bid_sign_amount 借款金额 | |
* @param bid_apr 借款利率 | |
* @param bid_period 借款期数 | |
* @return | |
*/ | |
public static Map<Integer, DEBXPeriod> getPeriodAmountInfo(long bid_sign_amount, long bid_apr, int bid_period) { | |
Map<Integer, DEBXPeriod> periods = new HashMap<Integer, DEBXPeriod>(); | |
// 按月还息到期还本,所以每个月的利息是相同的 | |
double mon_interest = bid_sign_amount * bid_apr / 10000.0 / 12 ; | |
double mon_amount = 0l;//只有最后一期才还本金 | |
for (int i = 1; i <= bid_period; i++) { | |
DEBXPeriod p = new DEBXPeriod(); | |
if (i == bid_period) { | |
mon_amount = bid_sign_amount; | |
} | |
p.setPeriod(i); | |
p.setMonPayAmount(mon_amount); | |
p.setMonPayInterest(mon_interest); | |
periods.put(i, p); | |
} | |
return periods; | |
} | |
/** | |
* 获取抵押宝出借人的账单,按月还息,到期还本算法 | |
* | |
* @param bid_sign_amount | |
* 出借人出借的金额 | |
* @param bid_apr | |
* 理财利率 | |
* @param bid_period | |
* 出借期数 | |
* @param actual_hold_days | |
* 首期持有的天数 | |
* @param pre_loan_time | |
* 起息时间 | |
* @return | |
*/ | |
public static DEBX getDYBAmountInfoInvest(long bid_sign_amount, long bid_apr, int bid_period, int actual_hold_days, | |
long pre_loan_time) { | |
DEBX info = new DEBX(); | |
Map<Integer, DEBXPeriod> periods = new HashMap<Integer, DEBXPeriod>(); | |
// double invest_monthRate = bid_apr / 12;// 用于账单计算 | |
for (int i = 1; i <= bid_period; i++) { | |
DEBXPeriod p = new DEBXPeriod(); | |
long cur_mon_interest = 0; | |
long cur_mon_amount = 0; | |
if (i == 1) { // 第一期需要计算实际持有天数的利息 | |
cur_mon_interest = getFirstAmountInfoOfPledge(bid_sign_amount, bid_apr, actual_hold_days, | |
pre_loan_time); | |
} else if (i > 1 && i < bid_period) {// 中间期数的利息计算方式相同 | |
cur_mon_interest = Math.round(bid_sign_amount * bid_apr / 12 / 10000.0); | |
} else if (i == bid_period) { // 最后一期需要计算本金 | |
cur_mon_interest = Math.round(bid_sign_amount * bid_apr / 12 / 10000.0); | |
cur_mon_amount = bid_sign_amount; | |
} | |
if(bid_period == 1){ | |
cur_mon_amount = bid_sign_amount; | |
} | |
p.setPeriod(i); | |
p.setMonPayAmount(cur_mon_amount); | |
p.setMonPayInterest(cur_mon_interest); | |
periods.put(i, p); | |
} | |
info.setPeriods(periods); | |
return info; | |
} | |
/** | |
* 获取第一期抵押宝利息 | |
* | |
* @param bid_sign_amount | |
* 出借人借款金额 | |
* @param bid_apr | |
* 理财利率 | |
* @param actual_hold_days | |
* 首期持有天数 | |
* @param pre_loan_time | |
* 起息时间 | |
* @return | |
*/ | |
public static long getFirstAmountInfoOfPledge(long bid_sign_amount, long bid_apr, int actual_hold_days, | |
long pre_loan_time) { | |
long nextReaymentDate = getNextRepaymentDate(pre_loan_time, 1).getTime(); | |
// 获取首期月份天数 | |
long cur_month_day = betweenDays(nextReaymentDate, pre_loan_time); | |
// 防止出现当月天数为0的情况 | |
if (cur_month_day == 0) { | |
cur_month_day = getCurMonthOfDay(pre_loan_time); | |
} | |
long cur_mon_interest = Math.round((bid_sign_amount * bid_apr / 120000.0 ) / cur_month_day * actual_hold_days); | |
return cur_mon_interest; | |
} | |
public static DEBX getAmountInfoInvest(long bid_sign_amount, long bid_apr, | |
int bid_period){ | |
DEBX info = new DEBX(); | |
double monthRate = bid_apr / 10000.0 / 12;// 月利率,用于月应收金额 | |
double invest_monthRate = bid_apr / 12;//用于账单计算 | |
double payInterest = 0;// 应付利息 | |
double left_amount = bid_sign_amount;// 签约金额,剩余本金 | |
//[贷款本金×月利率×(1+月利率)^还款月数]÷[(1+月利率)^还款月数-1] | |
double period_payment =Math.floor((bid_sign_amount*monthRate*Math.pow((1+monthRate), bid_period))/(Math.pow((1+monthRate),bid_period)-1)); | |
double totalAmount = period_payment * bid_period; | |
Map<Integer, DEBXPeriod> periods = new HashMap<Integer, DEBXPeriod>(); | |
long payAmount = 0;//累计本金 | |
for (int i = 1; i <= bid_period; i++) { | |
DEBXPeriod p = new DEBXPeriod(); | |
long cur_mon_interest = (long)(left_amount * invest_monthRate) / 10000;// 当月利息 | |
long cur_mon_amount = (long)(period_payment - cur_mon_interest);// 当月本金 | |
if(i == bid_period){ | |
cur_mon_amount = bid_sign_amount - payAmount; | |
cur_mon_interest = Math.max((long) (period_payment - cur_mon_amount), 0);//最后一期利息可能不足减,差额通过同期其他理财账单进行平账 | |
} | |
p.setPeriod(i); | |
p.setMonPayAmount(cur_mon_amount); | |
p.setMonPayInterest(cur_mon_interest); | |
periods.put(i, p); | |
left_amount = left_amount - cur_mon_amount; | |
payInterest += cur_mon_interest; | |
payAmount +=cur_mon_amount; | |
} | |
info.setPeriods(periods); | |
info.setPayAmount(bid_sign_amount); | |
info.setPayInterest(payInterest); | |
info.setTotalAmount(totalAmount); | |
info.setPeriodRepayment(period_payment); | |
return info; | |
} | |
/** | |
* 根据借款期限获得每月还款日期 | |
* | |
* @param begin_time 起息日期 | |
* @param period 期数 | |
* @return | |
*/ | |
public static Map<Integer, Date> getRepaymentTimeByPeriod(long begin_time, | |
int period) { | |
Map<Integer, Date> map = new HashMap<Integer, Date>(); | |
for (int i = 1; i < period + 1; i++) { | |
map.put(i, getNextRepaymentDate(begin_time, i)); | |
} | |
return map; | |
} | |
public static Map<Integer, Date> getRepaymentTimeByPeriod(long begin_time, | |
int period,int type) { | |
Map<Integer, Date> map = new HashMap<Integer, Date>(); | |
if(type == 1) { | |
for (int i = 1; i < period + 1; i++) { | |
map.put(i, getNextRepaymentDateNew(begin_time, i));//非倒推逻辑 | |
} | |
}else{ | |
for (int i = 1; i < period + 1; i++) { | |
map.put(i, getNextRepaymentDate(begin_time, i));//倒推逻辑 | |
} | |
} | |
return map; | |
} | |
//根据起息日计算当期的还款日 非倒推逻辑 | |
public static Date getNextRepaymentDateNew(long pre_loan_time, int period){ | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(pre_loan_time); | |
c.add(Calendar.MONTH, period); | |
return c.getTime(); | |
} | |
/** | |
* 根据借款期限获得每月还款日期 | |
* | |
* @param begin_time 起息日期 | |
* @param period 期数 | |
* @return | |
*/ | |
public static Map<Integer, Date> getDYBRepaymentTimeByPeriod(long begin_time, | |
int period) { | |
Map<Integer, Date> map = new HashMap<Integer, Date>(); | |
for (int i = 1; i < period + 1; i++) { | |
map.put(i, getDYBNextRepaymentDate(begin_time, i)); | |
} | |
return map; | |
} | |
/** | |
* | |
* | |
* @param begin_time 实际起息日期 | |
* @param platform_begin_time 平台起息日期 | |
* @param period 天数 | |
* @return | |
*/ | |
public static Map<Integer, Date> getRepaymentTimeByDays(long begin_time,int days) { | |
Map<Integer, Date> map = new HashMap<Integer, Date>(); | |
int period = getMonthSpace(begin_time + days * 86400000, begin_time); | |
for (int i = 1; i < period + 1; i++) { | |
map.put(i, getNextRepaymentDate(begin_time, i)); | |
} | |
return map; | |
} | |
/** | |
* 获取两个日期相差的天数 | |
* | |
* @param mills1 | |
* @param mills2 | |
* @return | |
*/ | |
public static long betweenDays(long mills1, long mills2) { | |
return getTimeZoneDay(mills1) - getTimeZoneDay(mills2); | |
} | |
/** | |
* 默认时区下,获取指定时间的天数 | |
* | |
* @param time | |
* @return | |
*/ | |
public static long getTimeZoneDay(long time) { | |
return (time + TIME_OFFSET) / MILLIS_PER_DAY; | |
} | |
public static int getCurMonthOfDay(long time){ | |
Calendar calendar = Calendar.getInstance(); | |
calendar.setTimeInMillis(time); | |
calendar.set(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),1); | |
calendar.roll(Calendar.DATE, false); | |
return calendar.get(Calendar.DATE); | |
} | |
/** | |
* 根据时间差算出共有多少期 | |
* @param date1 <String> | |
* @param date2 <String> | |
* @return int | |
* @throws ParseException | |
*/ | |
public static int getMonthSpace(Long date1, Long date2){ | |
int result = 0; | |
Calendar c1 = Calendar.getInstance(); | |
Calendar c2 = Calendar.getInstance(); | |
c1.setTimeInMillis(date1); | |
c2.setTimeInMillis(date2); | |
result = c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH); | |
return result == 0 ? 1 : Math.abs(result); | |
} | |
/** | |
* 根据起息日计算当期的还款日 | |
* | |
* @param pre_loan_time 起息日期 | |
* @param period 期号 | |
* @return | |
*/ | |
public static Date getNextRepaymentDate(long pre_loan_time, int period){ | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(pre_loan_time); | |
int f = c.get(Calendar.DATE);//起息日:当月第几天 | |
c.add(Calendar.MONTH, 1); | |
c.set(Calendar.DATE, 1); | |
c.add(Calendar.DATE, -1); | |
int l = c.get(Calendar.DATE); | |
int sub = l - f + 1; // 起息日:当月倒数第几天 | |
c = Calendar.getInstance(); | |
c.setTimeInMillis(pre_loan_time); | |
c.add(Calendar.MONTH, period); | |
int r = c.get(Calendar.DATE);//当期:预期还款日 | |
if(r < f){ | |
c = Calendar.getInstance(); | |
c.setTimeInMillis(pre_loan_time); | |
c.add(Calendar.MONTH, period + 1); | |
c.set(Calendar.DATE, 1); | |
c.add(Calendar.DATE, -sub); | |
} | |
return c.getTime(); | |
} | |
/** | |
* 根据起息日计算当期的还款日 | |
* | |
* @param pre_loan_time 起息日期 | |
* @param period 期号 | |
* @return | |
*/ | |
public static Date getDYBNextRepaymentDate(long pre_loan_time, int period){ | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(pre_loan_time); | |
int f = c.get(Calendar.DATE);//起息日:当月第几天 | |
c.add(Calendar.MONTH, 1); | |
c.set(Calendar.DATE, 1); | |
c.add(Calendar.DATE, -1); | |
c = Calendar.getInstance(); | |
c.setTimeInMillis(pre_loan_time); | |
c.add(Calendar.MONTH, period); | |
int r = c.get(Calendar.DATE);//当期:预期还款日 | |
if(r < f){ | |
c = Calendar.getInstance(); | |
c.setTimeInMillis(pre_loan_time); | |
c.add(Calendar.MONTH, period + 1); | |
c.set(Calendar.DATE, 1); | |
c.add(Calendar.DATE, -1); | |
} | |
return c.getTime(); | |
} | |
/** | |
* 返回Pair<下次还款时间,剩余期数> | |
* 下次还款时间(如果已结清返回最后一次还款时间) | |
*/ | |
public static Pair<Long,Integer> getNextPayTime_LeftPeriod(long pre_loan_time, int bid_period){ | |
long cur_time = MilliSecClock.currentTimeMillis(); | |
long t = 0; | |
for (int i = 1; i < bid_period + 1; i++) { | |
t= getDayMilliStart(getNextRepaymentDate(pre_loan_time, i).getTime()); | |
if(cur_time < t){ | |
return new Pair<Long,Integer>(t,bid_period+1-i); // 还款中,返回下次还款时间 | |
} | |
} | |
return new Pair<Long,Integer>(t,0); // 已结清,返回最后一次还款时间 | |
} | |
public static long addDay(long setTime, int dayCount){ | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(setTime); | |
c.add(Calendar.DAY_OF_YEAR, dayCount); | |
return c.getTimeInMillis(); | |
} | |
public static String dealRealname(String realName) { | |
if(StringUtil.isEmpty(realName)) return ""; | |
StringBuilder sb = new StringBuilder(); | |
sb.append(realName.charAt(0)); | |
for(int i=0;i<realName.length()-1;i++) { | |
sb.append("*"); | |
} | |
return sb.toString(); | |
} | |
/** | |
* 求数组元素和 | |
* @param values | |
* @return | |
*/ | |
public static int sum(int[] values){ | |
if(values == null) return 0; | |
else { | |
int sum = 0; | |
for(int i: values) { | |
sum += i; | |
} | |
return sum; | |
} | |
} | |
/** | |
* 隐去手机号码4-7位 | |
* @param mobile | |
* @return | |
*/ | |
public static String dealMobile(String mobile) { | |
if(StringUtil.isEmpty(mobile)) return ""; | |
if(mobile.length()==11) { | |
return mobile.substring(0, 3)+"****"+mobile.substring(7); | |
} | |
return ""; | |
} | |
public static String formatRate(int rate){ | |
return String.format("%.2f", rate / 100.00); | |
} | |
public static double getInvestRepaymentPeriod(long bid_sign_amount, int bid_apr, int period){ | |
double monthRate = getMonRate(bid_apr); | |
return (bid_sign_amount*monthRate*Math.pow((1+monthRate), period))/(Math.pow((1+monthRate),period)-1); | |
} | |
public static double getMonRate(int bid_apr){ | |
return bid_apr / 10000.0 / 12;// 月利率 | |
} | |
public static double formatRateToDouble(int bid_apr){ | |
return bid_apr / 10000.0;// 年利率 | |
} | |
public static String getMainPath(){ | |
String host = AppConfig.get("app.app_host", "nyonline.cn"); | |
String port = AppConfig.get("app.app_port", ""); | |
String pro = AppConfig.get("app.app_pro", "https"); | |
return pro + "://" + host + (StringUtil.isEmpty(port)? "" : (":" + port)) + AppConfig.get("app.app_context_path", ""); | |
} | |
/** | |
* 过滤特殊字符 | |
* <p> | |
* 融宝接口出现特殊字符有异常 | |
* @param str | |
* @return | |
*/ | |
public static String escape(String str){ | |
String regEx="[`~!@#$%^&*()+-=|{}':;',//[//].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]"; | |
Pattern p= Pattern.compile(regEx); | |
Matcher m = p.matcher(str); | |
return m.replaceAll("").trim(); | |
} | |
/** | |
* 隐藏身份证中间部分 | |
* @param old | |
* @return | |
*/ | |
public static String dealIdCard(String old){ | |
return old.replace(old.substring(6, 12),"######"); | |
} | |
/** 返回 当前时间 , 格式:2015 年 10 月 23 日 */ | |
public static String getYMD(long time){ | |
Calendar cal = Calendar.getInstance(); | |
cal.setTimeInMillis(time); | |
return cal.get(Calendar.YEAR)+" 年 "+ (cal.get(Calendar.MONTH)+1) + " 月 "+cal.get(Calendar.DAY_OF_MONTH) +" 日"; | |
} | |
public static long toFen(String yuan) { | |
try { | |
return Math.round(Double.valueOf(yuan) * 100); | |
} catch (Exception e) { | |
return 0; | |
} | |
} | |
public static int toRate(String rate) { | |
return Math.round(Float.valueOf(rate) * 10000); | |
} | |
public static int DJBHash(String str) | |
{ | |
int hash = 5381; | |
for(int i = 0; i < str.length(); i++) | |
{ | |
hash = ((hash << 5) + hash) + str.charAt(i); | |
} | |
return (hash & 0x7FFFFFFF); | |
} | |
@SuppressWarnings("unchecked") | |
public static <T> T[] asArray(Collection<T> col) { | |
if(Utils.isEmpty(col)) return (T[])(new Object[0]); | |
else { | |
int s = col.size(); | |
Object[] objs = new Object[s]; | |
int i = 0; | |
for(T t : col) { | |
objs[i++] = t; | |
} | |
return (T[])objs; | |
} | |
} | |
public static byte[][] asBytesArray(Collection<byte[]> col) { | |
if(Utils.isEmpty(col)) return new byte[][]{new byte[0]}; | |
else { | |
int s = col.size(); | |
byte[][] objs = new byte[s][]; | |
int i = 0; | |
for(byte[] t : col) { | |
objs[i++] = t; | |
} | |
return objs; | |
} | |
} | |
public static boolean isEmpty(Object[] array) { | |
return array == null || array.length == 0; | |
} | |
/** | |
* 计算2个绝对时间之间相差的天数 | |
* @param d1 | |
* @param d2 | |
* @return | |
*/ | |
public static long getDayInterval(long d1, long d2) { | |
long max = Utils.getDayMilliStart(Math.max(d1, d2)); | |
long min = Utils.getDayMilliStart(Math.min(d1, d2)); | |
return (max-min)/86400/1000; | |
} | |
public static int getCurDay(long time){ | |
Calendar cal = Calendar.getInstance(); | |
cal.setTimeInMillis(time); | |
return cal.get(Calendar.DAY_OF_MONTH); | |
} | |
/** | |
* 获取n小时前的时间 | |
* @param time | |
* @param hours | |
* @return | |
*/ | |
public static long getNHourBefore(long time, int hours){ | |
Calendar cal = Calendar.getInstance(); | |
cal.setTimeInMillis(time); | |
cal.add(Calendar.HOUR_OF_DAY,-hours); | |
return cal.getTimeInMillis(); | |
} | |
/** | |
* 返回时间戳N天后的日期 | |
* | |
*/ | |
public static String getNdaysafter(long timestamp,int days){ | |
Calendar cal = Calendar.getInstance(); | |
cal.setTimeInMillis(timestamp); | |
cal.add(Calendar.DAY_OF_YEAR,days); | |
return YYYY_MM_DD_SDF.format(cal.getTime()); | |
} | |
public static long getNdaysafterTime(long timestamp,int days){ | |
Calendar cal = Calendar.getInstance(); | |
cal.setTimeInMillis(timestamp); | |
cal.add(Calendar.DAY_OF_YEAR,days); | |
return getDayMilliStart(cal.getTimeInMillis()); | |
} | |
/** | |
* 将yyyymmdd格式的时间格式化成ms | |
* @param day yyyymmdd的整数 | |
* @return | |
*/ | |
public static long fromYYYYMMDDToMills(int day) { | |
try { | |
return DATE_SIMPLE_SDF.parse(String.valueOf(day)).getTime(); | |
} | |
catch(Throwable th) { | |
BizLogger.error(th); | |
} | |
return 0; | |
} | |
/** | |
* 将毫秒时间格式化为YYYYMMDD的整数 | |
* @param time | |
* @return | |
*/ | |
public static int fromMillsToYYYYMMDD(long time) { | |
return Integer.valueOf(DATE_SIMPLE_SDF.format(time)); | |
} | |
public static String fromMillsToYYYYMMDDHH(long time) { | |
return YYYY_MM_DD_HH.format(time); | |
} | |
/** | |
* 计算债权包结算时候的分成比例 | |
* @param bidApr | |
* @param packApr | |
* @param month | |
* @return | |
*/ | |
public static double computePackBalanceRate(int bidApr, int packApr, int month) { | |
double ret = (1+packApr*1.0/10000/12*month)/Math.pow(1+bidApr*1.0/10000/12, month); | |
if(ret >= 1) { | |
BizLogger.error(null, "computePackBalanceRate>1", ret); | |
} | |
return ret; | |
} | |
/** | |
* 多期债权包结算计算分成比例 | |
* @param bidApr | |
* @param packApr | |
* @param month 共参与几个月 | |
* @param totalMonth 包的总月份 | |
* @return | |
*/ | |
public static double computePackBalanceRate(int bidApr, int packApr, int month, int totalMonth) { | |
double ret = (1+packApr*1.0/10000/12*month*month/totalMonth)/Math.pow(1+bidApr*1.0/10000/12, month); | |
if(ret >= 1) { | |
BizLogger.error(null, "computePackBalanceRate >1", ret); | |
} | |
return ret; | |
} | |
/** | |
* 计算当前是第几期 | |
* | |
* @param begin_time | |
* @param period | |
* @return 默认第一期 | |
*/ | |
public static int getCurPeriod(long begin_time, long pre_loan_time, int period) { | |
for (int i = 1; i < period + 1; i++) { | |
long r = getDayMilliStart(getNextRepaymentDate(pre_loan_time, i).getTime()); | |
if(begin_time < r){ | |
return i; | |
} | |
} | |
return 1; | |
} | |
/** | |
* 根据打包起始期数计算当前债权期数 | |
* <p> | |
* 以债权的回款时间为准(包与债权的回款时间不一定一致) | |
* @param from_period | |
* @param pre_loan_time | |
* @param period | |
* @return | |
*/ | |
public static int getCurPeriodByFromPeriod(int curyyyyMMDD, long pre_loan_time, int period) { | |
long begin = Utils.fromYYYYMMDDToMills(curyyyyMMDD); | |
for (int i = 1; i < period + 1; i++) { | |
long r = getDayMilliStart(getNextRepaymentDate(pre_loan_time, i).getTime()); | |
if(begin < r){ | |
return i; | |
} | |
} | |
return 1; | |
} | |
/** | |
* 开始投标时间(平台上线日期),2015-11-11 00:00:00 | |
*/ | |
private static final long START = 1447171200000L; | |
/** | |
* 正推方式,根据还款时间获得历史起息日 | |
* | |
* @param repayment_time | |
* @return | |
*/ | |
public static List<Date> getPreLoanDates(long repayment_time) { | |
int period = 0; | |
List<Date> list = new ArrayList<Date>(); | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(repayment_time); | |
int r_y = c.get(Calendar.YEAR); | |
int r_m = c.get(Calendar.MONTH); | |
int r = c.get(Calendar.DATE);// 还款日:当月第几天 | |
c = Calendar.getInstance(); | |
c.setTimeInMillis(START); | |
int b_y = c.get(Calendar.YEAR); | |
int b_m = c.get(Calendar.MONTH); | |
period = (r_y - b_y) * 12 + (r_m - b_m);// 时隔几期(月) | |
for (int i = 1; i < period + 1; i++) { | |
c = Calendar.getInstance(); | |
c.setTimeInMillis(repayment_time); | |
c.add(Calendar.MONTH, -i); | |
int p = c.get(Calendar.DATE);// 推算起息日日期 | |
if (p < r) { | |
continue; | |
} | |
list.add(c.getTime()); | |
} | |
return list; | |
} | |
/** | |
* 倒推方式 ,根据还款时间获得历史起息日 | |
* <p> | |
* 目前只支持到倒数不大于3天,且日期不大于29 | |
* <p> | |
* 当月倒数第几天>>历史月倒数第几天&&历史月倒数第几天的日期大于当月最后一天日期 | |
* <p> | |
* | |
* | |
* @param repayment_time | |
* @return | |
*/ | |
public static List<Date> getPreLoanDatesReverse(long repayment_time) { | |
List<Date> list = new ArrayList<Date>(); | |
int d_positive = getPositiveDaysOfMonth(repayment_time);//当月第几天 | |
int d_reverse = getReverseDaysOfMonth(repayment_time);//当月倒数第几天 | |
Calendar last_c = getDateByfReverseDays(repayment_time, 1);//当月最后一天的日期 | |
if(d_reverse > 3 || d_positive > 29){ | |
return list; | |
} | |
int period = getPeriodsByRepaymentTime(repayment_time); | |
for (int i = 1; i < period + 1; i++) { | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(repayment_time); | |
c.add(Calendar.MONTH, -i); | |
Calendar his_reverse_c = getDateByfReverseDays(c.getTimeInMillis(), d_reverse);//历史月倒数第几天的日期 | |
if (his_reverse_c.get(Calendar.DATE) <= last_c.get(Calendar.DATE)) { | |
continue; | |
} | |
list.add(his_reverse_c.getTime()); | |
} | |
return list; | |
} | |
public static List<Integer> getPreLoanIntDates(long repayment_time) { | |
List<Date> dates = getPreLoanDates(repayment_time); | |
List<Integer> retList = new ArrayList<Integer>(); | |
for(Date d : dates) { | |
retList.add(Utils.fromMillsToYYYYMMDD(d.getTime())); | |
} | |
return retList; | |
} | |
/** | |
* 计算包用户收益率 | |
* | |
* @param packApr | |
* @param month | |
* @param totalMonth 初始包的期数 | |
* @return | |
*/ | |
public static double computePackIncomeRate(int packApr, int month, int totalMonth) { | |
return (packApr*1.0/10000/12*month*month/totalMonth); | |
} | |
public static long computePackInterest(long invest_amount, int apr, int periods){ | |
return (long)((double)invest_amount*((double)apr/12.00/10000.00*(double)periods)); | |
} | |
/** | |
* P2C账单计划 | |
* | |
* @param amount | |
* @param apr | |
* @param period | |
* @return | |
*/ | |
public static Map<Integer, Pair<Long, Long>> getComTenderBills(long amount, int apr, int period){ | |
Map<Integer, Pair<Long, Long>> bills = new HashMap<Integer, Pair<Long,Long>>(); | |
long period_interest = amount * apr / 12 / 10000; | |
for(int p = 1; p < period + 1; p++){ | |
bills.put(p, new Pair<Long, Long>(0L, period_interest)); | |
if(p == period){ | |
bills.put(p, new Pair<Long, Long>(amount, period_interest)); | |
} | |
} | |
return bills; | |
} | |
/** | |
* 多月期P2C账单计划 | |
* <p> | |
* 一次性还本付息 | |
* @param amount | |
* @param apr | |
* @param period | |
* @return | |
*/ | |
public static Pair<Long, Long> getMultComTenderBills(long amount, int apr, int period){ | |
long period_interest = amount * apr / 12 / 10000 * period; | |
return new Pair<Long, Long>(amount, period_interest); | |
} | |
/** | |
* 债赢宝账单计划 | |
* | |
* @param amount | |
* @param apr | |
* @param period | |
* @return | |
*/ | |
public static Pair<Long, Long> getZYBTenderBills(long amount, int apr, int period){ | |
long period_interest = period * amount * apr / 12 / 10000; | |
return new Pair<Long, Long>(amount, period_interest); | |
} | |
public static double computeComPackBalanceRate(int bidApr, int packApr, int month) { | |
double ret = (1+packApr*1.0/10000/12*month)/(1+bidApr*1.0/10000/12*month); | |
if(ret >= 1) { | |
BizLogger.error(null, "computeComPackBalanceRate>1", ret); | |
} | |
return ret; | |
} | |
/** | |
* 获取等额本息每期还款额 | |
* | |
* @param sign_amount 签约金额 | |
* @param bid_apr 年利率 | |
* @param period 期数 | |
* @return | |
*/ | |
public static long getPeriodRepaymentDRBX(long sign_amount, int bid_apr, int period){ | |
double monthRate = getMonRate(bid_apr); | |
return (long)(Double.valueOf((sign_amount * monthRate) | |
* Math.pow((1 + monthRate), period)) | |
/ Double.valueOf(Math.pow((1 + monthRate), period) - 1)); | |
} | |
/** | |
* 获得时间是所属月份的第几天 | |
* @return | |
*/ | |
private static int getPositiveDaysOfMonth(long time){ | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(time); | |
return c.get(Calendar.DATE); | |
} | |
/** | |
* 获得时间是所属月份的倒数第几天 | |
* @return | |
*/ | |
private static int getReverseDaysOfMonth(long time){ | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(time); | |
int f = c.get(Calendar.DATE);//当月第几天 | |
c.add(Calendar.MONTH, 1); | |
c.set(Calendar.DATE, 1); | |
c.add(Calendar.DATE, -1); | |
int l = c.get(Calendar.DATE); | |
return (l - f + 1); // 起息日:当月倒数第几天 | |
} | |
/** | |
* 根据还款日获取当前应处第几期 | |
* | |
* @param time | |
* @return | |
*/ | |
private static int getPeriodsByRepaymentTime(long time){ | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(time); | |
int r_y = c.get(Calendar.YEAR); | |
int r_m = c.get(Calendar.MONTH); | |
c = Calendar.getInstance(); | |
c.setTimeInMillis(START); | |
int b_y = c.get(Calendar.YEAR); | |
int b_m = c.get(Calendar.MONTH); | |
return ((r_y - b_y) * 12 + (r_m - b_m));// 时隔几期(月) | |
} | |
/** | |
* 当月倒数第几天的日期 | |
* | |
* @param days | |
* @return | |
*/ | |
private static Calendar getDateByfReverseDays(long time, int days){ | |
Calendar c = Calendar.getInstance(); | |
c.setTimeInMillis(time); | |
c.add(Calendar.MONTH, 1); | |
c.set(Calendar.DATE, 1); | |
c.add(Calendar.DATE, -days); | |
return c; | |
} | |
public static String getCardEnd(String card) { | |
if (StringUtils.isNotBlank(card) && card.length() > 4) { | |
return card.substring(card.length() - 4); | |
} | |
return card; | |
} | |
/** | |
* getAddress:(通过city id 获取县\市\省). | |
* @author yuejichun | |
* @param cityId | |
* @return | |
* @since JDK 1.7 | |
*/ | |
public static Triple<String, String, String> getAddress(int cityId, String cityName) { | |
Triple<String, String, String> triple = new Triple<String, String, String>(); | |
String first = cityName; | |
String second = cityName; | |
String third = cityName; | |
Dictionary dict = DictionaryCache.getById(cityId); | |
if (dict != null) { | |
String cityCode = dict.getSourcecode(); | |
if (cityCode != null && cityCode.length() == 6) { | |
first = dict.getSourcename()==null?cityName:dict.getSourcename(); | |
triple.setFirst(first); | |
Dictionary dictCity = DictionaryCache.getByCode(cityCode.substring(0, 4) + "00"); | |
second = dictCity != null && dictCity.getSourcename() != null ? dictCity.getSourcename() : second; | |
triple.setSecond(second); | |
Dictionary dictPro = DictionaryCache.getByCode(cityCode.substring(0, 2) + "0000"); | |
third = dictPro != null && dictPro.getSourcename() != null ? dictPro.getSourcename() : third; | |
triple.setThird(third); | |
} | |
} | |
return new Triple<String, String, String>(first, second, third); | |
} | |
public static void main(String[] args) throws Throwable { | |
DictionaryCache.reload(); | |
System.out.println(Utils.getAddress(StringUtil.convertInt("205", 0) , "abc")); | |
// System.out.println(fromMillsToYYYYMMDDHH(1495123200000L)); | |
// int curyyyyMMDD = 20170117; | |
// int curPeriods = Utils.getCurPeriodByFromPeriod(curyyyyMMDD, 1481108971000L, 3); | |
// System.out.println(curPeriods); | |
// List<Date> l = getPreLoanDatesReverse(Utils.fromYYYYMMDDToMills(20200229)); | |
// List<Date> l = getPreLoanDates(Utils.fromYYYYMMDDToMills(20200229)); | |
// for(Date d : l){ | |
// System.out.println(Utils.fromMillsToYYYYMMDD(d.getTime())); | |
// } | |
// System.out.println(getCurPeriod(fromYYYYMMDDToMills(20160730), 1451491200000L, 24)); | |
// System.out.println(betweenDays(1461513600000l,1458835200000l)); | |
// System.out.println(getZYBTenderBills(10000000, 850, 6)); | |
// System.out.println(computePackIncomeRate(550,1,1)); | |
// System.out.println(computePackBalanceRate(1268,900,1)); | |
// System.out.println(computePackBalanceRate(1268,900,2)); | |
// System.out.println(computePackBalanceRate(1268,900,3)); | |
// System.out.println(computePackIncomeRate(900, 3)); | |
// long pack_pre_loan_time = Utils.fromYYYYMMDDToMills(20160815); | |
// int cur_pack_period = Utils.getCurPeriod(Utils.fromYYYYMMDDToMills(20170215), | |
// pack_pre_loan_time, 7); | |
// long time = getNextRepaymentDate(1472572800000L,1).getTime(); | |
// System.out.println(time); | |
// if(MilliSecClock.currentTimeMillis() < Utils.getDayMilliEnd(time)){ | |
// System.out.println("00"); | |
// }else{ | |
// System.out.println("01"); | |
// } | |
// System.out.println(MilliSecClock.currentTimeMillis()); | |
// System.out.println(Utils.getDayMilliEnd(time)); | |
// getAmountInfoInvest(5628, 1268, 36); | |
// DEBX d= getAmountInfoOffLineWithoutCheck(1235133, 1268, 268, | |
// 110133, 12); | |
/* | |
* System.out.println(getAmountInfoOffLine(4713600, 4144189, 1268, 238, | |
* 196400, 24)); // System.out.println(Math.pow(2, 12)); // Calendar c = | |
* Calendar.getInstance(); // Calendar c2 = Calendar.getInstance(); // | |
* c2.add(Calendar.MONTH, -1); // c2.set(Calendar.HOUR_OF_DAY, 0); // | |
* System.out.println(Utils.format(c2.getTime())); // getProfit(1000000, | |
* 1200, 12, c2.getTimeInMillis(), c.getTimeInMillis()); | |
* | |
* long now = System.currentTimeMillis(); | |
* System.out.println(format(getDayMilliStart(now))); | |
* System.out.println(format(getDayMilliEnd(now))); | |
* System.out.println(format(new Date().getTime())); try { | |
* System.out.println(getTmpPwd("15298654586", "232102352698545625")); } | |
* catch (Throwable e) { e.printStackTrace(); } | |
*/ | |
// System.out.println(Math.abs(-100)); | |
//System.out.println(Utils.fromYYYYMMDDToMills(20151112)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static org.springframework.beans.BeanUtils.getPropertyDescriptor; | |
import static org.springframework.beans.BeanUtils.getPropertyDescriptors; | |
import java.beans.PropertyDescriptor; | |
import java.lang.reflect.Method; | |
import java.lang.reflect.Modifier; | |
import org.springframework.beans.BeansException; | |
public class verifyUtil { | |
public static boolean VerifyModel(Object source, Object target) throws BeansException { | |
return VerifyProperties(source, target); | |
} | |
private static boolean VerifyProperties(Object source, Object target) throws BeansException { | |
PropertyDescriptor[] targetPds = getPropertyDescriptors(target.getClass()); //读取对象2的所有属性 | |
PropertyDescriptor[] vartarget = targetPds; //将目标对象赋给vartarget | |
int varLenht = targetPds.length;//获取对象属性的长度 | |
for(int variate = 0; variate < varLenht; ++variate) { | |
PropertyDescriptor targetPd = vartarget[variate];//获取对象2的属性名称 | |
if(targetPd.getReadMethod()!= null && (!targetPd.getName().equals("class"))&&(!(targetPd.getName().equals("payInfos")))) { | |
//定义一个属性对象,接收 在源目标类中是否有目标对象的属性。但是当对象属性为status时,name等于bid_status | |
String name=targetPd.getName().equals("status")?"bid_status":targetPd.getName(); | |
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), name); | |
if(sourcePd != null && sourcePd.getReadMethod() != null) { | |
try { | |
Method source_ex = sourcePd.getReadMethod(); | |
//忽略访问权限,直接调用 | |
if(!Modifier.isPublic(source_ex.getDeclaringClass().getModifiers())) { | |
source_ex.setAccessible(true); | |
} | |
Object source_value = source_ex.invoke(source, new Object[0]);//委托一个Object | |
Method target_ex = targetPd.getReadMethod(); | |
//忽略访问权限,直接调用 | |
if(!Modifier.isPublic(target_ex.getDeclaringClass().getModifiers())) { | |
target_ex.setAccessible(true); | |
} | |
Object target_value = target_ex.invoke(target, new Object[0]);//委托一个Object | |
if(source_value == null && target_value == null) { | |
continue; | |
} | |
if(source_value == null || !source_value.equals(target_value)){ | |
BizLogger.info("VerifyProperties error",name,source_value,target_value); | |
return false; | |
} | |
} catch (Throwable th) { | |
BizLogger.error(th,"verifyUtil.VerifyProperties",name); | |
return false; | |
} | |
} | |
} | |
} | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment