import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qihangedu.tms.annotation.TMSProperty;
import com.qihangedu.tms.common.web.TMSMessageException;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.service.spi.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*; @Service
public class Util {
private static Logger logger = LoggerFactory.getLogger(TMSUtil.class); public static final long DEFAULT_SCALE = 100000000L; public static final SimpleDateFormat DATA_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
public static final SimpleDateFormat DATA_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /**
* 字符串类型(YYYY-MM-DD,YYYY/MM/DD)转换成 DATE 类型
* 新增对英文日期格式支持,如: Wed Oct 10 00:00:00 CST 2012 (excel数据导入运用)
*
* @param dateString YYYY-MM-DD,YYYY/MM/DD格式
* @return date对象
*/
public static synchronized Date string2Date(String dateString){
return string2Date(dateString, null);
} public static synchronized Date string2Date(String dateString, String defaultString){
if(StringUtils.isBlank(defaultString) && StringUtils.isBlank(dateString)){
return null;
} String ds = dateString;
if (StringUtils.isBlank(dateString)) {
ds = defaultString;
}
Date date = null;
try {
date = DateUtils.parseDate(ds, "yyyy-MM-dd","yyyy/MM/dd");
} catch (ParseException e) {
try {
date = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US).parse(ds);
}catch (Exception e1) {
logger.warn("转化日期格式错误: {}, format:yyyy-MM-dd 或 yyyy/MM/dd", ds);
}
}
return date;
} /**
* 格式化日期
* @param date
* @return
*/
public static String formatDate(Date date) {
if (date == null) {
return "";
}
return DATA_FORMAT.format(date);
} /**
* 格式化时间
* @param date
* @return
*/
public static String formatDateTime(Date date) {
if (date == null) {
return "";
}
return DATA_TIME_FORMAT.format(date);
} /**
* 将数字按缺省ModelEntity.SCORE_SCALE的倍数进行放大,用于内部保存.
* @param srcNumber 需要放大的输入源,字符串类型,可以携带小数
* @return 放大后的数字,长整型.
*/
public static synchronized long numberZoomIn(String srcNumber) {
return srcNumber == null ? 0 : numberZoomIn(srcNumber, DEFAULT_SCALE);
} /**
* 将数字按照传入的倍数进行放大,用于内部保存.
* @param srcNumber 需要放大的输入源,字符串类型,可以携带小数
* @param scale 放大的倍数
* @return 放大后的数字,长整型.
*/
public static synchronized long numberZoomIn(String srcNumber, long scale) {
double srcDouble = NumberUtils.toDouble(srcNumber, 0);
BigDecimal bigDecimal = new BigDecimal(srcDouble * 10000).multiply(new BigDecimal(scale)).divide(new BigDecimal(10000));
String string=bigDecimal.toString();
if(bigDecimal.toString().indexOf(".")>0){
//防止 越界
string=bigDecimal.toString().substring(0,bigDecimal.toString().indexOf("."));
}
long result = Long.valueOf(string);
if(logger.isDebugEnabled()) {
logger.debug("scale {}*{} is from {} to {}", srcNumber, scale, srcDouble, result);
}
return result;
} /**
* 将数值转换为百分比
*
* @param value
* @return
*/
public static String digitalToPercent(String value){
try {
if(StringUtils.isBlank(value)){
return null;
} if(StringUtils.indexOf(value, "%") != -1){
return value;
}
BigDecimal bigDecimal = new BigDecimal(value).multiply(new BigDecimal(100));
return bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP) + "%";
}catch (Exception e){
logger.error(e.getMessage(), e);
}
return value;
} /**
* 将百分比转换为数值
*
* @param value
* @return
*/
public static String percentToDigital(String value){
try {
if(StringUtils.isBlank(value)){
return null;
}
if(!StringUtils.endsWith(value, "%")){
return value;
}else{
value = value.replace("%", "");
}
BigDecimal bigDecimal = new BigDecimal(value).divide(new BigDecimal(100));
return bigDecimal.toPlainString();
}catch (Exception e){
logger.error(e.getMessage(), e);
}
return value;
} public static void main(String[] args) {
numberZoomIn("76.6",100000000);
} // /**
// * 根据小数点保留位数,计算出需要保存的整型。小数点以外的数字就不需要了。
// * @param srcStringDigital 字符串形式的源数据,可能是整型,可能是浮点,若是null表示为0
// * @return 扩大了小数点保留位后的整型
// */
// public static synchronized int scaleFromDoubleToInt(String srcStringDigital) {
// return scaleFromDoubleToInt(srcStringDigital, 8);
// }
//
// public static synchronized int scaleFromDoubleToInt(String srcStringDigital, int digitalPlace) {
// double sourceDouble = NumberUtils.toDouble(srcStringDigital);
// return scaleFromDoubleToInt(sourceDouble, digitalPlace);
//
// }
//
// /**
// * 根据小数点保留位数,计算出需要保存的整型。小数点以外的数字就不需要了。
// * @param srcDouble double类型的源数据
// * @param digitalPlace 小数点保留位数,0即不保留,直接取整
// * @return 扩大了小数点保留位后的整型
// */
// public static synchronized int scaleFromDoubleToInt(double srcDouble, int digitalPlace) {
// int result = (int) (srcDouble * Math.pow(10, digitalPlace));
// logger.debug("Math.pow(10, 8) = {}", Math.pow(10, digitalPlace));
// logger.debug("convert {} with digital place {}, result is {}", srcDouble, digitalPlace, result);
// return result;
// }
//
// /**
// * 将整形缩小小数点位数后返回字符串
// * @param srcValue 整型,数据源
// * @param digitalPlace 需要缩小的小数点位数
// * @param isTrimZero 是否裁剪掉末尾的不用的0
// * @return 格式化输出的字符串
// */
// public static synchronized String scaleFromLongToString(long srcValue, int digitalPlace, boolean isTrimZero){
// if(srcValue == 0L){
// return "0";
// }
//
// BigDecimal bd = new BigDecimal(srcValue);
//// bd = bd.setScale(digitalPlace);
// bd = bd.movePointLeft(digitalPlace);
//
// if(isTrimZero){
// return subZeroAndDot(bd.toString());
// }
// else{
// return bd.toString();
// }
//
// } // /**
// * 将整形缩小小数点位数后返回字符串
// * @param srcValue 整型,数据源
// * @param digitalPlace 需要缩小的小数点位数
// * @param isTrimZero 是否裁剪掉末尾的不用的0
// * @return 格式化输出的字符串
// */ /**
* 将内部保存的数字(长整型)缩小或扩大ModelEntity.SCORE_SCALE倍后返回字符串
* @param srcLong 长整型,数据源
* @return 格式化输出的字符串,小数点后面不再带"0"
*/
public static synchronized String numberZoomOutAndToString(long srcLong) {
return numberZoomOutAndToString(srcLong, DEFAULT_SCALE);
} /**
* 将内部保存的数字(长整型)缩小或扩大多少倍后返回字符串
* @param srcLong 长整型,数据源
* @param scale 需要缩小或扩大的倍数
* @return 格式化输出的字符串,小数点后面不再带"0"
*/
public static synchronized String numberZoomOutAndToString(long srcLong, long scale) {
BigDecimal bdLong = new BigDecimal(srcLong);
BigDecimal bdScale = new BigDecimal(scale);
BigDecimal result = bdLong.divide(bdScale, 2, BigDecimal.ROUND_HALF_UP); String str = subZeroAndDot(result.toString()); // if(logger.isDebugEnabled()) {
// logger.debug("input {} scale {} and result is {} to String is {}", srcLong, scale, result, str);
// } return str;
} /**
* 使用java正则表达式去掉多余的.与0
* <code>
Float f = 1f;
System.out.println(f.toString());//1.0
System.out.println(subZeroAndDot("1"));; // 转换后为1
System.out.println(subZeroAndDot("10"));; // 转换后为10
System.out.println(subZeroAndDot("1.0"));; // 转换后为1
System.out.println(subZeroAndDot("1.010"));; // 转换后为1.01
System.out.println(subZeroAndDot("1.01"));; // 转换后为1.01
</code>
* @param s 数字字符串
* @return 不带0和小数点(若是最后一位)
*/
public static synchronized String subZeroAndDot(String s) {
if (s.indexOf(".") > 0) {
s = s.replaceAll("0+?$", "");//去掉多余的0
s = s.replaceAll("[.]$", "");//如最后一位是.则去掉
}
return s;
} /**
* 字符串,拼装list 例"a,b,c"转换为list
* @param info 字符串
* @param regex 分隔符
* @return list
*/
public static synchronized List<String> str2List(String info, String regex) {
List<String> lst = new ArrayList<String>();
if (info != null) {
String infoArr[] = info.split(regex);
for (String str : infoArr) {
if (StringUtils.isNotBlank(str)) {
lst.add(str);
}
}
}
return lst;
} /**
* 获得两个日期之间的年份差额。
*
* 满12个月的为1年,不足12个月的为0年。规则调整为:取年份的差值,并向上进位(不
* 满一年的算一年)。
* @param startDate 开始日期
* @param currentDate 当前日期
* @return 差额年份,不足一年的为0.
*/
public static synchronized int getYearsOfAge(Date startDate, Date currentDate) {
Calendar startCal = Calendar.getInstance();
startCal.setTime(startDate); Calendar currentCal = Calendar.getInstance();
currentCal.setTime(currentDate); // int startMonths = startCal.get(Calendar.YEAR) * 12 + startCal.get(Calendar.MONTH);
// int currentMonths = currentCal.get(Calendar.YEAR) * 12 + currentCal.get(Calendar.MONTH);
//
// int months = currentMonths - startMonths;
//
// return months / 12;
// 根据启东的工作年限的计算规则,调整为向上取整
// 2013.12.30~2014.10.1,为两年
int startYear = startCal.get(Calendar.YEAR);
int currentYear = currentCal.get(Calendar.YEAR); return currentYear - startYear + 1;
} /**
* 从requst中获取json数据
*
* @param request
* @return json格式数据
* @throws java.io.IOException
*/
public static String getJsonBody(HttpServletRequest request) {
String body = null;
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
logger.warn("从request里读取数据流错误", ex.toString());
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
logger.warn("关闭request读取数据流错误", ex.toString());
}
}
} request.setAttribute(REQUEST_BODY, stringBuilder.toString());
//解决表情符号字符的问题,将他们先都过滤掉。
//by tanliang
//2015-10-22
String str = filterOffUtf8Mb4(stringBuilder.toString());
return str;
// try {
// return new String(stringBuilder.toString().getBytes("gbk"));
// } catch (UnsupportedEncodingException e) {
// logger.error(e.getMessage(), e);
// return "";
// }
} public static <T> T getJsonBody2Object(HttpServletRequest request, Class<T> clazz){
String jsonString = getJsonBody(request);
return JSON.parseObject(jsonString, clazz);
} public static JSONObject getJsonObject(HttpServletRequest request){
String jsonString = getJsonBody(request);
return JSON.parseObject(jsonString);
} // private static boolean isEmojiCharacter(char codePoint) {
// return (codePoint == 0x0) ||
// (codePoint == 0x9) ||
// (codePoint == 0xA) ||
// (codePoint == 0xD) ||
// ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
// ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||
// ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
// }
//
//
// /**
// * 检测是否有emoji字符
// *
// * @param source
// * @return 一旦含有就抛出
// */
// public static boolean containsEmoji(String source) {
// if (StringUtils.isBlank(source)) {
// return false;
// }
//
// int len = source.length();
// for (int i = 0; i < len; i++) {
// char codePoint = source.charAt(i);
// if (isEmojiCharacter(codePoint)) {
// //do nothing,判断到了这里表明,确认有表情字符
// return true;
// }
// }
// return false;
// }
//
//
// /**
// * 过滤emoji 或者 其他非文字类型的字符
// *
// * @param source
// * @return
// */
// public static String filterEmoji(String source) {
//
// if (!containsEmoji(source)) {
// return source;//如果不包含,直接返回
// }
// //到这里铁定包含
// StringBuilder buf = null;
//
// int len = source.length();
//
// for (int i = 0; i < len; i++) {
// char codePoint = source.charAt(i);
//
// if (isEmojiCharacter(codePoint)) {
// if (buf == null) {
// buf = new StringBuilder(source.length());
// }
//
// buf.append(codePoint);
// } else {
// }
// }
//
// if (buf == null) {
// return source;//如果没有找到 emoji表情,则返回源字符串
// } else {
// if (buf.length() == len) {//这里的意义在于尽可能少的toString,因为会重新生成字符串
// buf = null;
// return source;
// } else {
// return buf.toString();
// }
// }
// } /**
* 过滤掉超过3个字节的UTF8字符
* @param text
* @return
*/
public static String filterOffUtf8Mb4(String text) {
try {
if(text == null)
return null;
byte[] bytes = text.getBytes("utf-8");
if(!hasOffUtf8Mb4(bytes))
return text; ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
int i = 0;
while (i < bytes.length) {
short b = bytes[i];
if (b > 0) {
buffer.put(bytes[i++]);
continue;
} b += 256; // 去掉符号位 if (((b >> 5) ^ 0x6) == 0) {
buffer.put(bytes, i, 2);
i += 2;
} else if (((b >> 4) ^ 0xE) == 0) {
buffer.put(bytes, i, 3);
i += 3;
} else if (((b >> 3) ^ 0x1E) == 0) {
i += 4;
} else if (((b >> 2) ^ 0x3E) == 0) {
i += 5;
} else if (((b >> 1) ^ 0x7E) == 0) {
i += 6;
} else {
buffer.put(bytes[i++]);
}
}
buffer.flip();
return new String(buffer.array(), 0, buffer.limit(), "utf-8");
} catch (UnsupportedEncodingException e) {
logger.error(e.getMessage(), e);
return text;
}
} private static boolean hasOffUtf8Mb4(byte[] bytes) {
int i = 0;
while (i < bytes.length) {
short b = bytes[i];
if (b > 0) {
i++;
continue;
} b += 256; // 去掉符号位 if (((b >> 5) ^ 0x6) == 0) {
i += 2;
} else if (((b >> 4) ^ 0xE) == 0) {
i += 3;
} else if (((b >> 3) ^ 0x1E) == 0) {
return true;
} else if (((b >> 2) ^ 0x3E) == 0) {
return true;
} else if (((b >> 1) ^ 0x7E) == 0) {
return true;
} else {
// buffer.put(bytes[i++]);
i++;
}
}
return false;
} //首字母转小写
public static String toLowerCaseFirstOne(String s) {
if (Character.isLowerCase(s.charAt(0)))
return s;
else
return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
} //首字母转大写
public static String toUpperCaseFirstOne(String s) {
if (Character.isUpperCase(s.charAt(0)))
return s;
else
return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
} /**
* 判断文件后缀是否合法
* @param fileName
* @param suffix
* @return
*/
public static boolean isFileSuffix(String fileName, String...suffix){
for(String suf : suffix){
if(fileName.endsWith(suf)){
return true;
}
}
return false;
} /**
* 将list<Object> 对象转换为map对象.
*
* @param objs
* @param propName 对象属性名称,值对应map中key
* @return map key --> propName对应属性的值
* value --> object
*/
public static <T> Map<String, T> toMap(final List<T> objs, final String propName){
Map<String, T> results = new HashMap<>();
if(objs == null) return results;
for(T obj : objs){
try {
String propObj = PropertyUtils.getProperty(obj, propName) + "";
results.put(propObj, obj);
} catch (Exception e) {
logger.info("未知属性名称,{}", propName);
throw new ServiceException(e.getMessage());
}
}
return results;
} public static String toString(Collection<? extends Object> objects,String spilt){ StringBuffer sb = new StringBuffer(); if (objects != null && objects.size()>0) {
for (Object object : objects) {
sb.append(object.toString()+spilt) ;
}
}
return sb.toString();
} //==================================================================================================================
// 合并方法
//==================================================================================================================
public static final int MERGE_FLAG_NORMAL = 0;
public static final int MERGE_FLAG_ADD_NEW = 1;
public static final int MERGE_FLAG_REMOVE_OLD = 2;
public static final int MERGE_FLAG_COMBINE = 3; /**
* 合并对象的属性值。
*
* 利用属性上的@TMSProperty(merge=false)注解,则不需要复制该属性上的值。
* @param currentCollection 需要合并的对象集合
* @param postCollection 提交数据的对象集合
* @param flag 0,默认,不允许针对当前集合新增和删除对象;
* 1,仅新增在当前集合中不存在的对象;对于新增的对象,完全复制,不考虑合并(否则key值也会失效)。
* 2、仅删除在当前集合中多余的对象;
* 3、同时可以新增和删除当前集合中的对象。相当于完全依赖postCollection中的对象情况
* @param <T> 泛型。注:对于对象唯一性的判断,主要依赖T的hashCode()方法。
*/
public static <T> void mergeCollection(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
// Map<Integer, T> currentMap = collectionToMap(currentCollection);
// Map<Integer, T> postMap = collectionToMap(postCollection);
// mergeCore(currentMap, postMap, flag);
// currentCollection.clear();
// currentCollection.addAll(currentMap.values());
mergeCore(currentCollection, postCollection, flag);
} // /**
// * 合并对象V上的属性值。K只是索引值。适用于Map<String, EmployeeEntity>,其中key为empId
// *
// * 利用属性上的@TMSProperty(merge=false)注解,则不需要复制该属性上的值。
// * @param currentMap 需要合并的对象集合
// * @param postMap 提交数据的对象集合
// * @param flag 0,默认,不允许针对当前集合新增和删除对象;
// * 1,仅新增在当前集合中不存在的对象;
// * 2、仅删除在当前集合中多余的对象;
// * 3、同时可以新增和删除当前集合中的对象。相当于完全依赖postCollection中的对象情况
// * @param <K> 泛型。注:对于对象唯一性的判断,主要依赖K的hashCode()方法。
// * @param <V> 泛型。目前暂不支持V为Collection和Map。
// *
// */
// protected <K, V> void mergeMap(Map<K, V> currentMap, Map<K, V> postMap, int flag) {
// } // public static <V> void mergeCore(Map<Integer, V> currentMap, Map<Integer, V> postMap, int flag) {
// switch (flag) {
// case MERGE_FLAG_NORMAL:
// mergeCoreNormal(currentMap, postMap, flag);
// break;
// case MERGE_FLAG_ADD_NEW:
// mergeCoreAdd(currentMap, postMap, flag);
// break;
// case MERGE_FLAG_REMOVE_OLD:
// mergeCoreRemove(currentMap, postMap, flag);
// break;
// case MERGE_FLAG_COMBINE:
// mergeCoreRemove(currentMap, postMap, flag);
// mergeCoreAdd(currentMap, postMap, flag);
// break;
// }
//
// } public static <T> void mergeCore(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
switch (flag) {
case MERGE_FLAG_NORMAL:
mergeCoreNormal(currentCollection, postCollection, flag);
break;
case MERGE_FLAG_ADD_NEW:
mergeCoreAdd(currentCollection, postCollection, flag);
break;
case MERGE_FLAG_REMOVE_OLD:
mergeCoreRemove(currentCollection, postCollection, flag);
break;
case MERGE_FLAG_COMBINE:
mergeCoreRemove(currentCollection, postCollection, flag);
mergeCoreAdd(currentCollection, postCollection, flag);
break;
} } //内部实现方法
// protected static <V> void mergeCoreNormal(Map<Integer, V> currentMap, Map<Integer, V> postMap, int flag) {
// for (Map.Entry<Integer, V> postEntry : postMap.entrySet()) {
// if (currentMap.containsKey(postEntry.getKey())) {
// merge(currentMap.get(postEntry.getKey()), postEntry.getValue(), flag);
// }
// }
// }
protected static <T> void mergeCoreNormal(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
for (T ct : currentCollection) {
// if(!isComplexClass(ct)) continue;
T pt = findT(postCollection, ct);
if(pt != null && isComplexClass(ct)) {
merge(ct, pt, flag);
}
}
} protected static <T> T findT(Collection<T> collection, T t) {
for(T ct:collection) {
if(ct != null && ct.equals(t))
return ct;
}
return null;
} protected static <T> boolean isComplexClass(T t) {
if(t.getClass().isPrimitive() || t instanceof String || t instanceof Date) {
logger.warn("can not merge primitive/String/Date class object. Ony replace can do.");
return false;
}
return true;
} //内部实现方法
// @SuppressWarnings("unchecked")
// protected static <V> void mergeCoreAdd(Map<Integer, V> currentMap, Map<Integer, V> postMap, int flag) {
// for (Map.Entry<Integer, V> postEntry : postMap.entrySet()) {
// if (currentMap.containsKey(postEntry.getKey())) {
// merge(currentMap.get(postEntry.getKey()), postEntry.getValue(), flag);
// } else {
// try {
// V v = (V) postEntry.getValue().getClass().newInstance();
// //需要复制一下hashCode的值
// copyPrimaryKey(v, postEntry.getValue());
// merge(v, postEntry.getValue(), flag);
// currentMap.put(postEntry.getKey(), v);
// } catch (InstantiationException | IllegalAccessException e) {
// logger.error(e.getMessage(), e);
// }
// }
// }
// } @SuppressWarnings("unchecked")
protected static <T> void mergeCoreAdd(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
for(T pt : postCollection) {
// if(!isComplexClass(pt)) continue;
T ct = findT(currentCollection, pt);
if(ct != null && isComplexClass(pt)) {
merge(ct, pt, flag);
}
else if(isComplexClass(pt)){
try {
T t = (T) pt.getClass().newInstance();
//需要复制一下hashCode的值
copyPrimaryKey(t, pt);
merge(t, pt, flag);
currentCollection.add(t);
} catch (InstantiationException | IllegalAccessException e) {
logger.error(e.getMessage(), e);
}
}
else {
currentCollection.add(pt);
}
}
} protected static <T> void copyPrimaryKey(T currentObj, T postObj) {
if(currentObj == null || postObj == null) {
return;
} Collection<Field> fields = getAllDeclaredField(postObj.getClass());
for(Field field : fields) {
TMSProperty tmsProperty = field.getAnnotation(TMSProperty.class);
if(tmsProperty!=null && !tmsProperty.isPrimaryKey()) {
logger.trace("pass {}-{}", field.getDeclaringClass(), field.getName());
continue;
} try {
logger.debug("copy {}-{}", field.getDeclaringClass(), field.getName());
PropertyUtils.setProperty(currentObj, field.getName(), PropertyUtils.getProperty(postObj, field.getName()));
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
logger.error(e.getMessage(), e);
}
} } //内部实现方法
protected static <T> void mergeCoreRemove(Collection<T> currentCollection, Collection<T> postCollection, int flag) {
Collection<Integer> removeCollection = new ArrayList<>();
Iterator<T> iterator = currentCollection.iterator();
while(iterator.hasNext()) {
T ct = iterator.next();
// if(!isComplexClass(ct))
// continue; T pt = findT(postCollection, ct);
if(pt != null && isComplexClass(ct)) {
merge(ct, pt, flag);
}
else {
iterator.remove();
}
}
}
// protected static <V> void mergeCoreRemove(Map<Integer, V> currentMap, Map<Integer, V> postMap, int flag) {
// Collection<Integer> removeCollection = new ArrayList<>();
// for (Map.Entry<Integer, V> currentEntry : currentMap.entrySet()) {
// if (postMap.containsKey(currentEntry.getKey())) {
// merge(currentEntry.getValue(), postMap.get(currentEntry.getKey()), flag);
// } else {
// removeCollection.add(currentEntry.getKey());
// }
// }
//
// for(int key : removeCollection) {
// currentMap.remove(key);
// }
// } /**
* 合并对象的属性值。如果属性为集合,则会递归合并。
*
* 利用属性上的@TMSProperty(merge=false)注解,则不需要复制该属性上的值。如果这两个对象的hashCode值不一致,则不会进行合并,并且
* 抛出异常。
*
* @param currentObj 需要合并的对象
* @param postObj 提交数据的对象
* @param flag 仅针对属性为集合时有效
* 0,默认,不允许针对当前集合新增和删除对象;
* 1,仅新增在当前集合中不存在的对象;
* 2、仅删除在当前集合中多余的对象;
* 3、同时可以新增和删除当前集合中的对象。相当于完全依赖集合中的对象情况
* @param <T> 泛型。注:对于对象唯一性的判断,主要依赖T的hashCode()方法。
*/
@SuppressWarnings("unchecked")
public static <T> void merge(T currentObj, T postObj, int flag) {
if(currentObj == null || postObj == null) {
return;
} if(!currentObj.getClass().equals(postObj.getClass())) {
return;
} if(currentObj.getClass().isPrimitive() || currentObj instanceof String) {
return;
} if(currentObj.hashCode() != postObj.hashCode() && !currentObj.equals(postObj)) {
return;
} // Field fields[] = postObj.getClass().getDeclaredFields();
Collection<Field> fields = getAllDeclaredField(postObj.getClass());
for(Field field : fields) {
//静态的就不复制了,add by tanliang, 2015-12-15
if(Modifier.isStatic(field.getModifiers()))
continue;
TMSProperty tmsProperty = field.getAnnotation(TMSProperty.class);
if(tmsProperty!=null && !tmsProperty.merge()) {
logger.trace("pass {}-{}", field.getDeclaringClass(), field.getName());
continue;
} // //对于field为primary key,只有在新增模式下是需要复制的。否则忽略。
// if(tmsProperty != null && tmsProperty.isPrimaryKey() ) {
// if (flag != MERGE_FLAG_ADD_NEW && flag != MERGE_FLAG_COMBINE) {
// continue;
// }
// logger.debug("is primary key but need copy.");
// }
try {
//assertTrue(Collection.class.isAssignableFrom(List.class));
if(Collection.class.isAssignableFrom(field.getType())) {
//获取集合的泛型类型:
// Class cls = getGenericClass(field);
//
// if(cls.isPrimitive() || Date.class.isAssignableFrom(cls) || String.class.isAssignableFrom(cls)) {
// //如果是简单对象,则直接根据flag进行合并
//
// Collection<T> currentCollection = (Collection<T>)PropertyUtils.getProperty(currentObj, field.getName());
// Collection<T> postCollection = (Collection<T>)PropertyUtils.getProperty(postObj, field.getName());
//
// switch (flag) {
// case MERGE_FLAG_NORMAL:
// mergeCoreNormal(currentCollection, postCollection, flag);
// break;
// case MERGE_FLAG_ADD_NEW:
// mergeCoreAdd(currentCollection, postCollection, flag);
// break;
// case MERGE_FLAG_REMOVE_OLD:
// mergeCoreRemove(currentCollection, postCollection, flag);
// break;
// case MERGE_FLAG_COMBINE:
// mergeCoreRemove(currentCollection, postCollection, flag);
// mergeCoreAdd(currentCollection, postCollection, flag);
// break;
// }
// }
// else {
//递归
mergeCollection((Collection<T>) PropertyUtils.getProperty(currentObj, field.getName()), (Collection<T>) PropertyUtils.getProperty(postObj, field.getName()), flag);
// }
}
// else if(field.getDeclaringClass().isAssignableFrom(Map.class)) {
// //暂不支持递归,直接复制即可。.
// }
else {
logger.debug("copy {}-{}", field.getDeclaringClass(), field.getName());
PropertyUtils.setProperty(currentObj, field.getName(), PropertyUtils.getProperty(postObj, field.getName()));
}
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
logger.error(e.getMessage(), e);
}
}
} /**
* 通用的获取到指定类所有类属性字段的方法,包括继承而来的属性字段。一般Class中的getDeclaredFields()方法是不包括继承属性的。
* @param clazz 类
* @return 所有字段对象的集合
*/
public static Collection<Field> getAllDeclaredField(Class<?> clazz) {
Class<?> lastClazz = clazz; Collection<Field> allFields = new ArrayList<>();
for (; lastClazz != Object.class; lastClazz = lastClazz.getSuperclass()) {
Field fields[] = lastClazz.getDeclaredFields();
for(Field field : fields) {
if(findField(allFields, field.getName()) == null) {
allFields.add(field);
}
}
// CollectionUtils.addAll(fields, lastClazz.getDeclaredFields());
} return allFields;
} //
private static Field findField(Collection<Field> fields, String name) {
for(Field field : fields) {
if(field.getName().equals(name)) {
return field;
}
}
return null; //没有找到
} /**
* 简单的将集合对象hashCode后形成map,方便后面定位查找。
* @param c 对象的集合
* @param <T> 可被正确hashCode的类
* @return key为hashCode值,value为对象本身的map。
*/
public static <T> Map<Integer, T> collectionToMap(Collection<T> c) {
Map<Integer, T> map = new HashMap<>();
for(T t : c) {
map.put(t.hashCode(), t);
}
return map;
} public static Class getGenericClass(Field field) {
if(Collection.class.isAssignableFrom(field.getType())) {
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
//目前只取第一个泛型
return (Class) parameterizedType.getActualTypeArguments()[0];
}
}
return Object.class;
} /**
* 合并两个id集合
* @param managedIds 管理范围的id集合,也就是标准
* @param queryIds 业务查询出来的id集合,也就是目标
* @param pageSize 分页的页行数
* @param pageNo 分页的页码,从1开始
* @return 如果业务id在管理范围内,就保留下来,最后按分页的要求组合成新的集合。
*/
public static Collection<String> mergeIds(Collection<String> managedIds, Collection<String> queryIds, int pageSize, int pageNo) {
long offset = (pageNo - 1) * pageSize;
long limit = pageNo * pageSize;
long fetchPoint = 0; Collection<String> result = new ArrayList<>(pageSize);
for(String id : queryIds) {
if(managedIds != null && !managedIds.contains(id)) {
continue;
} if(fetchPoint < offset)
continue; if(fetchPoint > limit)
break; result.add(id);
fetchPoint++;
}
return result;
} /**
* 获取List中第一个元素的Field
* @param list
* @param fieldName
* @param <T>
* @return
*/
private static <T> Field getFirstElementField(List<T> list,String fieldName){ if (list == null || list.isEmpty()) {
return null;
} Class<? extends Object> clazz = list.get(0).getClass();
Class<? extends Object> clazz0 = clazz;
int count = 0;
while (clazz != Object.class && count < 20) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
}
if (field != null) {
field.setAccessible(true);
return field;
}
clazz = clazz.getSuperclass();
count++;
} logger.error("{}没有此属性{}", clazz0.getName(), fieldName); return null;
} /**
* 查找或排除集合中的元素,私有方法以供reject和find调用
* @param list
* @param fieldName
* @param fieldValue
* @param isReject
* @param <T>
* @return
*/
private static <T> List<T> findOrReject(List<T> list,String fieldName,Object fieldValue,boolean isReject){ Field field = getFirstElementField(list, fieldName); if (field == null) {
return list;
} Set<Object> targets = new HashSet<>(); if (fieldValue instanceof Collection){
targets.addAll((Collection)fieldValue);
}else {
targets.add(fieldValue);
} List<T> result = new ArrayList<>(); for (T object : list) {
try {
Object value = field.get(object); if (isReject) { if(!targets.contains(value)){
result.add(object);
} } else {
if(targets.contains(value)){
result.add(object);
}
} } catch (IllegalAccessException e) {
e.printStackTrace();
}
} return result;
} /**
* 从list中过滤掉指定属性指定值的元素
* @param list
* @param fieldName
* @param fieldValue
* @param <T>
* @return
*/
public static <T> List<T> reject(List<T> list,String fieldName,Object fieldValue){
return findOrReject(list,fieldName,fieldValue,true);
} /**
* 从list中过滤掉指定属性指定值的元素
* @param list
* @param fieldName
* @param fieldValue
* @param <T>
* @return
*/
public static <T> Object findOne(List<T> list,String fieldName,Object fieldValue){
List<T> list2 = findOrReject(list, fieldName, fieldValue, false);
if (isEmpty(list2)){
return null;
}
return list2.get(0);
} /**
* 从list中过滤掉指定属性指定值的元素
* @param list
* @param fieldName
* @param fieldValue
* @param <T>
* @return
*/
public static <T> List<T> find(List<T> list,String fieldName,Object fieldValue){
return findOrReject(list,fieldName,fieldValue,false);
} /**
* 模仿underscore的pluck函数
* var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
* _.pluck(stooges, 'name'); => ["moe", "larry", "curly"]
* @param list
* @param fieldName
* @return
*/
public static <T> List pluck(List<T> list,String fieldName){
Field field = getFirstElementField(list, fieldName); if (field == null) {
return new ArrayList<>();
} List<Object> result = new ArrayList<>(); for (T object : list) {
try {
Object value = field.get(object);
if (value != null) {
result.add(value);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return result;
} /**
* 判断对象是否为空
* @param object
* @return
* @throws TMSMessageException
*/
public static boolean isEmpty(Object object) {
if (object == null) {
return true;
} if (object.getClass().isArray()) {
Object[] arr = (Object[]) object;
return arr.length == 0;
} if (object instanceof Map) {
Map m = (Map) object;
return m.isEmpty();
} if (object instanceof Collection) {
Collection c = (Collection) object;
return c.isEmpty();
} if (object instanceof String) {
String s = (String) object;
s = s.trim();
return s.isEmpty();
} logger.error("只能判断数组,Map,Collection,String"); return false;
} public static String encodeHtml(String str){
if (str != null) {
str = str.replaceAll("<", "<");
str = str.replaceAll(">", ">");
}
return str;
} /**
* 求两个集合的差集
* @param list1
* @param list2
* @param fieldName
* @return
*/
public static List<Object> differenceByKey(List<Object> list1,List<Object> list2,String fieldName) throws IllegalAccessException {
Field field = getFirstElementField(list1, fieldName);
Map<String,Object> map2 = TMSUtil.toMap(list2,fieldName);
List<Object> result = new ArrayList<>();
for (Object object : list1){
Object filedValue = field.get(object);
if (!map2.containsKey(fieldName)){
result.add(object);
}
}
return result;
} /**
* 求两个集合的差集
* @param list1
* @param list2
* @return
*/
public static List<Object> difference(List list1,List list2){
List<Object> result = new ArrayList<>(); for (Object object:list1){
if (object!=null){
result.add(object);
}
} result.removeAll(list2);
return result;
} /**
* 检查是否是合法的邮箱地址
*
* @param mailAddress 待检验的邮箱地址
* @return 如果是空字符串,或者不包含@符号,就是一个非法邮箱地址,返回false,否则返回true
*/
public static boolean isValidMailAddress(String mailAddress) {
if(StringUtils.isBlank(mailAddress))
return false; String m = mailAddress.trim();
int pos = m.indexOf("@"); //找到@,且不是第一个,也不是最后一个
return !(pos == -1 || pos == 0 || pos == m.length()-1);
} /**
* 获取参数中第一个不为空的字符串,如果返回空字符串,说明获取失败
* @param args
* @return
*/
public static String getNotBlank(String ...args) { if (args == null) {
return "";
} for (String s : args) {
if (StringUtils.isNotBlank(s)) {
return s;
}
} return ""; } }

  

java Util的更多相关文章

  1. 【转】java.util.Arrays.asList 的用法

    DK 1.4对java.util.Arrays.asList的定义,函数参数是Object[].所以,在1.4中asList()并不支持基本类型的数组作参数. JDK 1.5中,java.util.A ...

  2. Java程序日志:java.util.logging.Logger类

    一.Logger 的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面.各级别按降序排列如下:SEVERE(最高值)WARNINGINFOCONFIGFINEF ...

  3. Android中使用java.util.Properties犯的错

    今天尝试使用java.util.Properties来保存应用配置,然而遇到了好几个问题,对于熟悉此内容的来说可能都是猪一样的错误,但难免有像我一样的新手再次遇到,希望此文能有所帮助. 错误1 jav ...

  4. java.util.ConcurrentModificationException 解决办法(转载)

    今天在项目的中有一个需求,需要在一个Set类型的集合中删除满足条件的对象,这时想当然地想到直接调用Set的remove(Object o)方法将指定的对象删除即可,测试代码:   public cla ...

  5. java util 下的concurrent包

    ------------------------------------------java util 下的concurrent包--------并发包--------------------.jav ...

  6. 原子类java.util.concurrent.atomic.*原理分析

    原子类java.util.concurrent.atomic.*原理分析 在并发编程下,原子操作类的应用可以说是无处不在的.为解决线程安全的读写提供了很大的便利. 原子类保证原子的两个关键的点就是:可 ...

  7. 错误:java.util.Map is an interface, and JAXB can't handle interfaces.

    问题: 在整合spring+cxf时报错java.util.Map is an interface, and JAXB can't handle interfaces. 解决方法: 将服务端的serv ...

  8. 解决springmvc报No converter found for return value of type: class java.util.ArrayList问题

    一.背景 最近闲来无事,想自己搭建一套Spring+SpringMVC+Mybatis+Mysql的环境(搭建步骤会在以后博客中给出),结果运行程序时,适用@ResponseBody注解进行返回Lis ...

  9. Java源码之 java.util.concurrent 学习笔记01

    准备花点时间看看 java.util.concurrent这个包的源代码,来提高自己对Java的认识,努力~~~ 参阅了@梧留柒的博客!边看源码,边通过前辈的博客学习! 包下的代码结构分类: 1.ja ...

  10. java:警告:[unchecked] 对作为普通类型 java.util.HashMap 的成员的put(K,V) 的调用未经检查

    java:警告:[unchecked] 对作为普通类型 java.util.HashMap 的成员的put(K,V) 的调用未经检查 一.问题:学习HashMap时候,我做了这样一个程序: impor ...

随机推荐

  1. apache下自定义404错误页面

    404页面的目的是:告诉浏览者其所请求的页面不存在或链接错误,同时引导用户使用网站其他页面而不是关闭窗口离开. 很多开源系统包括CMS系统.Blog系统等不提供404页面或提供的404页面并未达到SE ...

  2. [强连通分量] POJ 1236 Network of Schools

    Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16803   Accepted: 66 ...

  3. 支持Android iOS,firefox(其它未测)的图片上传客户端预览、缩放、裁切。

    var version = '007'; var host = window.location.host; function $$(id){return document.getElementById ...

  4. ubuntu arm妙算加载cp210x驱动

    在妙算TK1上安装ros后,插上usb串口竟然没有驱动 无奈装 从http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers. ...

  5. SSH(2)

    1.用户登录 index页面跳转到登录页面 <% String path = request.getContextPath(); String basePath = request.getSch ...

  6. Servlet里面url-pattern的通配符*的使用规则

    简单来说: 以”/’开头和以”/*”结尾的是用来做路径映射的. 以前缀”*.”开头的是用来做扩展映射的. “/” 是用来定义default servlet映射的. 剩下的都是用来定义详细映射的.比如: ...

  7. select document library from certain list 分类: Sharepoint 2015-07-05 07:52 6人阅读 评论(0) 收藏

    S using System; using Microsoft.SharePoint; namespace Test { class ConsoleApp { static void Main(str ...

  8. php字符串中单引号''和双引号“”的区别

    (1)双引号可以解析字符串中的变量,单引号不能 $a = 10; $str = "this a var $a"; //输出this a var 10 (2)在双引号中可以使用转义字 ...

  9. Jmeter—4 添加断言 判断响应数据是否符合预期

    发出请求之后,通过添加断言可以判断响应数据是否是我们的预期结果. 1 在Jmeter中发送一个登录的http请求(参数故意输入错误).结果肯定是登陆失败啦. 但结果树中http请求的图标显示‘绿色’表 ...

  10. Jmeter—1 安装

    1  Jmeter运行需要java环境.首先需要安装JDK. 图标是这样的:  2 下载apache-jmeter包. jmeter官网:http://jmeter.apache.org/ 3  解压 ...