操作日誌小框架
阿新 • • 發佈:2018-12-10
一般來說專案中會碰到兩個要求
1 打日誌不能影響主要的業務邏輯
2 打日誌要比較前後兩個物件的差異
為了滿足這樣的要求 我曾在好幾個大公司都接到過這樣的需求,那麼怎麼操作呢
一 首先先弄一個判空的工具類
public static boolean isBlank(Object str) {
return (str == null || (str+"").trim().length() == 0);
}
二 其次就是日誌的主體類的
/** * @Title: DealerLoggerService.java * @Package cn.pconline.dealer.service * @Description: TODO(用一句話描述該檔案做什麼) * @date: 2018年11月6日 下午6:06:17 * @version V1.0 */ package cn.pconline.dealer.service; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.servlet.ServletContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.gelivable.dao.SqlBuilder; import org.gelivable.web.EnvUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.ContextLoader; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import cn.pconline.dealer.entity.DealerLogger; import cn.pconline.dealer.util.Pager; import cn.pconline.dealer.util.T; import cn.pconline.extend.util.StringUtils; /** * @author pc * */ @Service public class DealerLoggerService extends DealerAbstractService<DealerLogger>{ private static final Log logger = LogFactory.getLog(DealerLoggerService.class); private ExecutorService service=Executors.newCachedThreadPool(); protected DealerLoggerService() { super(DealerLogger.class); } /** * @Title: instance * @Description: ${todo}(建立例項) * @param: ${tags} * @return: ${return_type} * @throws */ public static DealerLoggerService instance() { try { return EnvUtils.getEnv().getBean(DealerLoggerService.class); } catch (Exception e) { ServletContext servletContext = ContextLoader.getCurrentWebApplicationContext().getServletContext(); WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext); return ctx.getBean(DealerLoggerService.class); } } /** * @Title: findByOperatorId * @Description: TODO(這裡用一句話描述這個方法的作用) * @param: @param pageNum * @param: @param numPerPage * @param: @param operatorId * @param: @return * @return: Pager<DealerLogger> * @throws */ public Pager<DealerLogger> findByOperatorId(int pageNum, int numPerPage, long operatorId) { SqlBuilder sql = new SqlBuilder(); sql.appendSql("select ").appendSql(this.getKeyColumn()).appendSql(" from ").appendSql(this.getTableName(operatorId)); sql.appendSql(" where operator_id = ").appendValue(operatorId); sql.appendSql(" order by log_id desc"); List<DealerLogger> list = geliDao.list(DealerLogger.class,operatorId,sql.getSql(), sql.getValues()); Pager<DealerLogger> pagers=new Pager<DealerLogger>(list); pagers.setPageNo(pageNum); pagers.setPageSize(numPerPage); return pagers; } /** * * @Title: printLog * @Description: TODO(這裡用一句話描述這個方法的作用) * @param operatorId * @param username * @param action * @param newObj 修改前 * @param oldObj 修改後 * @param ip * @param classs * @param method * @param status * @throws */ public void printLog(long operatorId, String username, String action, Object newObj,Object oldObj, String ip, String classs, String method,int status) { try { Class<? extends Object> cls = newObj.getClass(); List<String> fileds2 = getFileds(oldObj, newObj, cls); String detail = StringUtils.join(fileds2,", "); this.printLog(operatorId, username, action, detail, ip, classs, method, status); } catch (Exception e) { logger.error("作業系統日誌列印失敗....."+e.getMessage());; } } private static List<String> getFileds(Object be, Object af,Class<? extends Object> cls) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { List<String> result=new ArrayList<String>(); Field[] filed = cls.getDeclaredFields(); List<Field> asList = Arrays.asList(filed); for(Field field:asList) { String upperCase = field.getName().substring(0, 1).toUpperCase(); String substring = field.getName().substring(1); int modifiers = field.getModifiers(); String modifier= Modifier.toString(modifiers); if(modifier.contains("static"))continue; String meth="get"+upperCase+substring; Method method2 = cls.getMethod(meth, null); if(null!=method2) { Object newValue = method2.invoke(af, null); Object oldValue = method2.invoke(be, null); if(T.isBlank(newValue)&&T.isBlank(oldValue)) { continue; } if(T.isBlank(newValue)&&!T.isBlank(oldValue)) { if(!oldValue.equals(newValue)) { result.add(String.format("%s[%s => %s] ", field, newValue, oldValue)); } } if(T.isBlank(oldValue)&&!T.isBlank(newValue)) { if(!newValue.equals(oldValue)) { result.add(String.format("%s[%s => %s] ", field, newValue, oldValue)); } } if(!T.isBlank(oldValue)&&!T.isBlank(newValue)) { if(!newValue.equals(oldValue)) { result.add(String.format("%s[%s => %s] ", field, newValue, oldValue)); } } } } Class<?> superclass = cls.getSuperclass(); if(superclass!=null) { List<String> fileds = getFileds(be,af,superclass); result.addAll(fileds); } return result; } /** * * @Title: printLog * @Description: TODO(打日誌) * @param operatorId * @param username * @param action * @param detail * @param ip * @param classs * @param method * @param status * @throws */ public void printLog(long operatorId, String username, String action, String detail, String ip, String classs, String method,int status) { final DealerLogger logger = new DealerLogger(); logger.setLogId(T.getNow().getTime()); logger.setOperatorId(operatorId); logger.setAction(action); logger.setDetail(detail); logger.setIp(ip); logger.setOperatorName(username); logger.setStatus(status); logger.setOperateClass(classs); logger.setOperateMethod(method); service.execute(new Runnable() { @Override public void run() { try { DealerLoggerService.instance().create(logger); } catch (Exception e) { Log logger = LogFactory.getLog(DealerLoggerService.class); logger.error("作業系統日誌列印失敗....."+e.getMessage());; } } }); } /** * * @Title: findLogger * @Description: (這裡用一句話描述這個方法的作用) * @param: @param pageNum * @param: @param numPerPage * @param: @param orderField * @param: @param orderDirection * @param: @return * @return: List<Log> * @author xiaozhengwen * @throws */ public List<DealerLogger> findLogger(Map qparam,int pageNum, int numPerPage, String orderField, String orderDirection) { long operatorId =(long) qparam.get("operatorId"); String names = (String) qparam.get("name"); long start=(pageNum-1)*numPerPage; SqlBuilder sql = new SqlBuilder(); sql.appendSql("select ").appendSql(this.getKeyColumn()).appendSql(" from ").appendSql(this.getTableName()); sql.appendSql(" where 1=1 "); if(operatorId!=0) { sql.appendSql(" and operator_id = ").appendValue(operatorId); } if(!T.isBlank(names)) { sql.appendSql(" and operator_name like '%"+names+"%'"); } sql.appendSql(" order by "); sql.appendSql(orderField + " " + orderDirection); sql.appendSql(" limit "+start+","+numPerPage); List<DealerLogger> list = geliDao.list(DealerLogger.class,sql.getSql(), sql.getValues()); return list; } /** * * @Title: findLoggerTotal * @Description: (查詢總的日誌條數) * @param: @return * @return: long * @author xiaozhengwen * @throws */ public long findLoggerTotal(Map qparam) { long operatorId = (long) qparam.get("operatorId"); String name = (String) qparam.get("name"); SqlBuilder sql = new SqlBuilder(); sql.appendSql(" 1=1 "); if(operatorId!=0) { sql.appendSql(" and operator_id = ").appendValue(operatorId); } if(!T.isBlank(name)) { sql.appendSql(" and operator_name like '%"+name+"%'"); } sql.appendSql(" order by log_id desc"); return geliDao.count(DealerLogger.class, sql.getSql(), sql.getValues()); } /* * @Title: handleOperatorLogByDateTime * @Description: 歸檔操作日誌資料,刪除歸檔表delDateTime前的資料,將操作日誌insertDateTime前的資料插入歸檔表並且刪除這些資料 * @param: insertDateTime 需要插入歸檔表的最小log_id * @param: delDateTime 需要刪除歸檔表資料的最小log_id * @return: void * @throws: Exception */ @Transactional public void handleOperatorLogByDateTime(long insertDateTime, long delDateTime) throws Exception { //先刪除歸檔表的舊資料 SqlBuilder sqlBuilder = new SqlBuilder(); sqlBuilder.appendSql("DELETE FROM genactivity_dealer_log_h"); sqlBuilder.appendSql(" WHERE log_id<=" + delDateTime); geliDao.getJdbcTemplate().execute(sqlBuilder.getSql()); logger.info("async-handleOperatorLogByDateTime SQL-->" + sqlBuilder.getSql()); //將操作日誌表的資料歸檔 SqlBuilder insertSQL = new SqlBuilder(); insertSQL.appendSql("INSERT INTO genactivity_dealer_log_h(log_id,operator_id,operator_name,action,detail,ip,status,operate_class,operate_method)"); insertSQL.appendSql(" SELECT gOther.log_id,gOther.operator_id,gOther.operator_name,gOther.action,gOther.detail" + ",gOther.ip,gOther.status,gOther.operate_class,gOther.operate_method FROM genactivity_dealer_log gOther"); insertSQL.appendSql(" WHERE not EXISTS("); insertSQL.appendSql("SELECT g.log_id,g.operator_id,g.operator_name,g.action,g.detail,g.ip,g.status,g.operate_class" + ",g.operate_method From genactivity_dealer_log_h g"); insertSQL.appendSql(" WHERE g.log_id = gOther.log_id ) AND gOther.log_id<=" + insertDateTime); geliDao.getJdbcTemplate().execute(insertSQL.getSql()); logger.info("async-handleOperatorLogByDateTime SQL-->" + insertSQL.getSql()); //清空日誌表中已經歸檔的資料 SqlBuilder delSQL = new SqlBuilder(); delSQL.appendSql("DELETE FROM genactivity_dealer_log"); delSQL.appendSql(" WHERE log_id<=" + insertDateTime); geliDao.getJdbcTemplate().execute(delSQL.getSql()); logger.info("async-handleOperatorLogByDateTime SQL-->" + sqlBuilder.getSql()); } }