1. 程式人生 > >操作日誌小框架

操作日誌小框架

一般來說專案中會碰到兩個要求

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());
	}

}