(已于2018年01月04日更新了一个优化版,里面附带源码,地址为:http://www.cnblogs.com/leifei/p/8194644.html )
前几天做系统日志记录的功能,一个操作调一次记录方法,每次还得去收集参数等等,太尼玛烦了。在程序员的世界里,当你的一个功能重复出现多次,就应该想想肯定有更简单的实现方法。于是果断搜索各种资料,终于搞定了,现在上代码
环境: SpringMvc + myBatis
jar包 : aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMEAAAAUCAIAAAC7085XAAAFDklEQVRoge2a0WvbRhzH7w/YQ2HkZW+Fkjc9TQ/awwjsaeRlzA+lzaYXU8Ye2sK0bszNNjqRNURpQky87iFsawux89BNfljKkrWklGFUDIXgZuCQmDk2kd3KicCWRzwv3sNJp5PuTk6cgL2i40tRz3c/fe/uc787QcDwnc1spRkqVM8CkKGVXDm1tv7TstZVqbX1lVy5775DDY5shhYfPtvYLFiW9TdRGo0GerYsa2OzsPjwWd99hxoc2Qzdvr9Wq9Xa7fa/WGm3241Gw8z/0Wq1UE2tVrt9f63vvrOawgFB0vptIxwsYmgutWoYxj9YabVa9Xq99vstY1awLAvVG4Yxl1rtu+9BnlZVFjg5R9bHReAWMc3ono4A4O9+CoP1hU1HbB/ROGqTjDrm8HfRWnplMzR1d7larR5gxTTNF79Nvfx2eH9//+X6qmVZsL5arU7dXe7T8uQkHkSSfYOjuzSFAwCQEFSa2UozLnY3r8oCq/tJ5A2bk3gbiLiIaE5HeEWF7ZNRhxhqS79shuQFVdf1plPq9XrlUaL69Ru6rld+lV9MDNfrdfiTruvygtqnRRpwhnISDzg5Fxd7ZUhTOBCNMLr3roCwyShA6LhKR8i0R2/ZzCKGxhNL5XK57hTTNKvXX4f/wgfTNOFP5XJ5PLHEMGoXNFMQfywTQghQesTn1K2kpVzAyQp6BryiagoHovFKE1uwdAQFdAdMC+u3aq+965nZF/PPmNCsx5KfMO9sUBpEkrTuzmAZ8xzsih2WZdXNQ10HhTF0beZesVg0nWIYRlV5s1gsVj57zTAMwzBKpdLu7u7e3l6xWLw2c48yfpHIhPjIPfPoVLpecfBRsiFvBlgecoKrsmDn2GSU4+2LiDNgaliaVZc5/O20vjyLgCNNN2pALjY6LAIZopkPdEUP64BIyYuawuH1AS19DI1O/Ixre3u7UCiU5XN/pW8UCoVSqfT53OLUj7/s7OxsbW1dnlygxiKyDtzHeFb0HUbOf93bHLbvKcmTwlDWTUiCpMFDPSfxgqQxwjKtCpKGhaX39flHicqT+bsyRDkssMF2yUPM7E57UXBYgmZVFgDj8k7l3sPQmXfGcYlfff/xzR8+GP/u4vVE5/Cgs3Pp+fQQVCczculGggqvbdGffuAugc7YDJH+jsiQTQxGT1LhYEdqWIZVOMXuJxX9+D/ShexoDJFT5C342z0bhjTPctUtrJfmgFsznXsfQ2JsVkxFcT148vTBk6fpR5nO4cHz6aGWsdHJnOssDa1cGRJjswG8q7KAzjLJc2A7o3KMui3xq0ylGRfJyrTkSwPY8quywPH2iQafKTckFJZqFQbkoxEeTRPV0vEZcj/Lc6rmNrAngfbR7nZHv+LZkWL+mK40hcOXAAakXDwYLVkMnZcmwcQorgux+Yux+QuxeZKh89JkAPKcGMU3t11sKzmJBxERHROYadqVHKt0cbE3E3HNxNjCVoVxAyWt+vgO6NsrQ2nPN4H/16MxRDd/bFfEaUg5u2FASksWQ5lP3yKVz+fz+TzJ0HuXvwm2y9bpfZxT982rqsEerM3Q8tjZP2+N4loeO3t1Jnl1Jkky9O5HX/b6vlNjKCC1vnoa8ME6DI2eIaXruq7rJEPvf3Kz1/edBkN21h3cfXma+j8M1mYorj4e+2L67Q8lUp3Dg05mZOXKEFQnMxJXH/fdd6jBEQj/Bi3UCQWG72yGCnUSgU5YwnKy8h8i8f1ly/IrZAAAAABJRU5ErkJggg==" alt="" /> (aspect.jar也行,我原来项目中有,便没有替换了)
1.自定义注解类 ArchivesLog.java(获取Controller描述用的)
package com.noahwm.uomp.archives.common; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ArchivesLog { /** 要执行的操作类型比如:add操作 **/
public String operationType() default ""; /** 要执行的具体操作比如:添加用户 **/
public String operationName() default ""; }
2.日志处理类 ArchivesLogAspect.java(业务处理)
package com.noahwm.uomp.archives.common;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import com.noahwm.uomp.base.security.SecurityConstant;
import com.noahwm.uomp.system.bo.User; public class ArchivesLogAspect {
private final Logger logger = Logger.getLogger(this.getClass()); private String requestPath = null ; // 请求地址
private String userName = "" ; // 用户名
private Map<?,?> inputParamMap = null ; // 传入参数
private Map<String, Object> outputParamMap = null; // 存放输出结果
private long startTimeMillis = 0; // 开始时间
private long endTimeMillis = 0; // 结束时间
private User user = null;
private HttpServletRequest request = null; /**
*
* @Description: 方法调用前触发 记录开始时间
* @author fei.lei
* @date 2016年11月23日 下午5:10
* @param joinPoint
*/
public void before(JoinPoint joinPoint){
//System.out.println("被拦截方法调用之后调用此方法,输出此语句");
request = getHttpServletRequest();
//fileName 为例子
Object obj =request.getParameter("fileName");
System.out.println("方法调用前: " + obj);
user = (User)request.getSession().getAttribute(SecurityConstant.CURRENT_LOGIN_USER);
startTimeMillis = System.currentTimeMillis(); //记录方法开始执行的时间
} /**
*
* @Description: 方法调用后触发 记录结束时间
* @author fei.lei
* @date 2016年11月23日 下午5:10
* @param joinPoint
*/
public void after(JoinPoint joinPoint) {
request = getHttpServletRequest();
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = null;
try {
targetClass = Class.forName(targetName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method[] methods = targetClass.getMethods();
String operationName = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs!=null&&clazzs.length == arguments.length&&method.getAnnotation(ArchivesLog.class)!=null) {
operationName = method.getAnnotation(ArchivesLog.class).operationName();
break;
}
}
}
endTimeMillis = System.currentTimeMillis();
//格式化开始时间
String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTimeMillis);
//格式化结束时间
String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endTimeMillis); Object obj =request.getParameter("fileName");
System.out.println("方法调用后: " + obj);
System.out.println(" 操作人: "+user.getName()+" 操作方法: "+operationName+" 操作开始时间: "+startTime +" 操作结束时间: "+endTime); }
/**
* @Description: 获取request
* @author fei.lei
* @date 2016年11月23日 下午5:10
* @param
* @return HttpServletRequest
*/
public HttpServletRequest getHttpServletRequest(){
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes)ra;
HttpServletRequest request = sra.getRequest();
return request;
} /**
*
* @Title:around
* @Description: 环绕触发
* @author fei.lei
* @date 2016年11月23日 下午5:10
* @param joinPoint
* @return Object
* @throws Throwable
*/
public Object around(ProceedingJoinPoint joinPoint) throws Throwable { return null;
} /**
*
* @Title:printOptLog
* @Description: 输出日志
* @author fei.lei
* @date 2016年11月23日 下午5:10
*/
/*private void printOptLog() {
Gson gson = new Gson(); // 需要用到google的gson解析包
String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTimeMillis);
String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endTimeMillis);
logger.info("user :" +user.getName()+ " start_time: " + startTime +" end_time: "+endTime);
} */ }
3.spring 注入
<!--指定扫描目录-->
<context:component-scan base-package="com.noahwm" /> <aop:aspectj-autoproxy proxy-target-class="true" /> <!--将日志类注入到bean中。-->
<bean id="logAspect" class="com.noahwm.uomp.archives.common.ArchivesLogAspect"></bean> <aop:config>
<!--调用日志类-->
<aop:aspect id="LogAspect" ref="logAspect">
<!--配置在controller包下所有的类在调用之前都会被拦截-->
<aop:pointcut id="log" expression="execution(* com.noahwm.uomp.archives.controller.*.*(..))"/>
<!-- 方法前触发 --><aop:before pointcut-ref="log" method="before"/>
<!-- 方法后触发 --><aop:after pointcut-ref="log" method="after"/>
<!-- 环绕触发 <aop:around pointcut-ref="log" method="around"/> -->
</aop:aspect>
</aop:config>
3.调用(设置Controller描述)
@RequestMapping(value="/fileQuery")
@ArchivesLog(operationType="查询操作:",operationName="查询文件")
public ModelAndView fileQuery(HttpServletRequest request,HttpServletResponse response){ return new ModelAndView("archives/fileQuery");
}
4.结果
aaarticlea/png;base64,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" alt="" />
这样一来还可以记录操作前,操作后的值了