一般来说项目中会碰到两个要求
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());
}
}