前言:
通过自定义注解和AOP结合的方式,实现日志的记录功能
大致流程:项目运行->用户操作调用业务处理类->通过自定义的注解(我理解为一个切点)->进入到AOP切面类(在这里可以获得业务处理类的类名,方法名,通过request获取操作者ip,自定义的操作名,时间等)->把获取的信息记入数据库实现日志的记录->记录成功后返回业务处理类,下面是代码。
1.spring-mvc配置文件
<!-- 6.开启注解AOP (前提是引入aop命名空间和相关jar包) -->
<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"></aop:aspectj-autoproxy> <!-- 7.开启aop,对类代理强制使用cglib代理 -->
<aop:config proxy-target-class="true"></aop:config> <!-- 8.扫描 @Service @Component 注解-->
<context:component-scan base-package="com.bs" >
<!-- 不扫描 @Controller的类 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
2.自定义注解类
package com.bs.annotation; import java.lang.annotation.*; @Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SysLog { String value() default "";
}
3.AOP切面类
package com.bs.aop; import java.lang.reflect.Method;
import java.text.DateFormat;
import java.util.Date;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.bs.annotation.SysLog;
import com.bs.basic.service.BsSysLogService; @Aspect
@Component
public class LogAspect { private static final String LOG_CONTENT = "[类名]:%s <br/>[方法]:%s <br>[参数]:%s <br/>[IP]:%s"; @Autowired
public BsSysLogService logService; @Around("@annotation(com.bs.annotation.SysLog)")
public Object saveLog(ProceedingJoinPoint joinPoint) throws Throwable{ DateFormat ddtf = DateFormat.getDateTimeInstance();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Object result = null;
String methodName = joinPoint.getSignature().getName();
Method method = currentMethod(joinPoint, methodName);
SysLog log = method.getAnnotation(SysLog.class);
String content =buildeContent(joinPoint, methodName, request); logService.insert(content,ddtf.format(new Date()),"-",log.value());
try{
result=joinPoint.proceed();
}catch(Exception exception){ }finally{
}
return result;
} /**
* 获取当前方法
* @param joinPoint
* @param methodName
* @return
*/
public Method currentMethod(ProceedingJoinPoint joinPoint,String methodName){
Method[] methods = joinPoint.getTarget().getClass().getMethods();
Method resultMethod = null;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
resultMethod = method;
break;
}
}
return resultMethod;
} /**
* 日志内容
* @param joinPoint
* @param methodName
* @param request
* @return
*/
public String buildeContent(ProceedingJoinPoint joinPoint, String methodName, HttpServletRequest request) {
String className = joinPoint.getTarget().getClass().getName();
Object[] params = joinPoint.getArgs();
StringBuffer bf = new StringBuffer();
if (params != null && params.length > 0) {
Enumeration<String> paraNames = request.getParameterNames();
while (paraNames.hasMoreElements()) {
String key = paraNames.nextElement();
bf.append(key).append("=");
bf.append(request.getParameter(key)).append("&");
}
if (StringUtils.isBlank(bf.toString())) {
bf.append(request.getQueryString());
}
}
return String.format(LOG_CONTENT, className, methodName, bf.toString(),getRemoteAddress(request));
} /**
*
* 获取请求客户端ip
*
* @param request
*
* @return ip地址
*
*/
public static String getRemoteAddress(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {
ip = request.getRemoteAddr();
}
return ip;
}
}
4.自定义注解配置在需要记录的业务处理类
@SysLog("删除场景")
@Override
public String deleteScene(String cmdValues) {
//业务逻辑....
}
@SysLog("更新场景")
@Override
public String updateScene(String value) {
//业务处理...
}