前言:
通过自定义注解和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) { //业务处理... }