1.Java aop面向切面编程访问日志
1.1需要使用的jar包
aspect包或者aspectjweaver包
1.2需要配置spring文件
在spring-jdbc.xml中
<!-- 设置扫描目录 -->
<context:component-scan base-package="com.ssm" />
<aop:aspectj-autoproxy proxy-target-class="true" />
1.3配置aop日志的相关文件
1.3.1注解类
@Target({ElementType.METHOD,ElementType.PARAMETER})
public @interface SysServiceAop {
String sysAopType() default "";
String sysAopRemark()default "";
}
1.3.2注解实现类
/**
* @Auther: cpb
* @Date: 2018/6/11 14:48
* @Description:日志操作。可以直接使用Service保存
*/
@Aspect // 该注解标示该类为切面类
@Component // 注入依赖
public class SysServiceAopAspect {
private static String restUrl;
private static final Logger logger = LoggerFactory.getLogger(SysServiceAop.class);
private static String[] types = { "java.lang.Integer", "java.lang.Double",
"java.lang.Float", "java.lang.Long", "java.lang.Short",
"java.lang.Byte", "java.lang.Boolean", "java.lang.Char",
"java.lang.String", "int", "double", "long", "short", "byte",
"boolean", "char", "float" };
//定义切点位置这种定位方式需要在spring中配置位置需要在spring中配置
/**
*
<aop:config>
<aop:pointcut id="serviceMethods" expression="execution(* com.ssm.web.service..*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>
*/
@Pointcut("@annotation(SysServiceAop)")
public void serviceAop(){
}
@AfterReturning(value="serviceAop()",returning="object")
public void doAfterReturning(JoinPoint joinPoint,Object object){
SysOprlog sysOprlog = getSysOprlogInfo(joinPoint);
sysOprlog.setOprlogStatus("1");
saveSysOprlog(sysOprlog);
}
/**
* 异常通知 用于拦截service层记录异常日志
* @param joinPoint
* @param e
*/
@AfterThrowing(pointcut = "serviceAop()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
String className = joinPoint.getTarget().getClass().getName();// 获取所在实体类
String methodName = joinPoint.getSignature().getName();// 获取方法名
logger.error("执行失败!"+className+"->"+methodName+"失败原因:" + e.getMessage());
SysOprlog sysOprlog = getSysOprlogInfo(joinPoint);
sysOprlog.setOprlogRemark("异常方法:"+className+"->"+methodName+",原因:"+e.getMessage());
sysOprlog.setOprlogStatus("0");
saveSysOprlog(sysOprlog);
}
/**
* 获取SysOprlog的属性内容
* @param joinPoint
* @return
*/
private SysOprlog getSysOprlogInfo(JoinPoint joinPoint){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
// 读取session中的用户
SysUserEntity user = (SysUserEntity) session.getAttribute("user");
// 请求的IP
//String ip = request.getRemoteAddr();
String className = joinPoint.getTarget().getClass().getName();// 获取所在实体类
String methodName = joinPoint.getSignature().getName();// 获取方法名
SysOprlog sysOprlog = new SysOprlog();
try {
String paramContent = getLogParamContent(getFieldsName(this.getClass(), className, methodName), joinPoint);
//获取注解描述
SysServiceAop systemServiceLog = getServiceMethodDescription(joinPoint);
sysOprlog.setOprlogId(UUID.randomUUID().toString());
sysOprlog.setOprlogParam(paramContent);
sysOprlog.setOprlogRemark(systemServiceLog.sysAopType());
sysOprlog.setOprlogTime(new Date());
sysOprlog.setOprlogType(systemServiceLog.sysAopRemark());
sysOprlog.setOprlogUserId(user.getUserId().toString());
sysOprlog.setOprlogUserName(user.getUsername());
} catch (Exception e) {
// 记录本地异常日志
logger.error("获取失败!失败原因:" + e.getMessage());
}
return sysOprlog;
}
/**
* 获取注解中对方法的描述信息,用于service层注解
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
*/
@SuppressWarnings("rawtypes")
private SysServiceAop getServiceMethodDescription(JoinPoint joinPoint) throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
SysServiceAop systemServiceLog = null;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
systemServiceLog = method.getAnnotation(SysServiceAop.class);
break;
}
}
}
return systemServiceLog;
}
/**
* 获取调用方法参数的名称
* @param cls
* @param clazzName
* @param methodName
* @return
* @throws NotFoundException
*/
@SuppressWarnings("rawtypes")
private String[] getFieldsName(Class cls, String clazzName, String methodName) throws NotFoundException{
ClassPool pool = ClassPool.getDefault();
ClassClassPath classPath = new ClassClassPath(cls);
pool.insertClassPath(classPath);
CtClass cc = pool.get(clazzName);
CtMethod cm = cc.getDeclaredMethod(methodName);
MethodInfo methodInfo = cm.getMethodInfo();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
if (attr == null) {
// exception
}
String[] paramNames = new String[cm.getParameterTypes().length];
int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
for (int i = 0; i < paramNames.length; i++){
paramNames[i] = attr.variableName(i + pos); //paramNames即参数名
}
return paramNames;
}
/**
* 获取日志参数内容。格式:参数名+参数内容
* @param paramNames
* @param joinPoint
* @return
*/
private String getLogParamContent(String[] paramNames, JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
StringBuilder sb = new StringBuilder();
boolean clazzFlag = true;
for(int k=0; k<args.length; k++){
Object arg = args[k];
sb.append(paramNames[k]);
// 获取对象类型
String typeName = arg.getClass().getName();
for (String t : types) {
if (t.equals(typeName)) {
sb.append("=" + arg+";");
}
}
if (clazzFlag) {
sb.append(getFieldsValue(arg));
}
}
return sb.toString();
}
/**
* 得到参数的值
* @param obj
*/
private String getFieldsValue(Object obj) {
Field[] fields = obj.getClass().getDeclaredFields();
String typeName = obj.getClass().getName();
for (String t : types) {
if(t.equals(typeName))
return "";
}
StringBuilder sb = new StringBuilder();
sb.append("[");
for (Field f : fields) {
f.setAccessible(true);
try {
for (String str : types) {
if (f.getType().getName().equals(str)){
sb.append(f.getName() + " = " + f.get(obj)+"; ");
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
sb.append("]");
return sb.toString();
}
/**
* rest请求存储操作日志在这里可以直接调用日志dao直接保存
* @param sysOprlog
*/
private void saveSysOprlog(SysOprlog sysOprlog){
AjaxResponse response = new AjaxResponse();
response.setSuccess(false);
response.setMessage("保存操作日志失败!");
Map<String, String> map = ConvertUtils.convertModelToMapWithDateFormat(sysOprlog, false, null);
HttpResponseResult responseResult = HttpClientUtils.post( restUrl+ "/sysOprLog/saveOprLog", map);
if(responseResult.getCode() == 200) {
String msg = responseResult.getMsg();
try {
response = JSON.parseObject(msg, AjaxResponse.class);
} catch (Exception e) {
logger.error("保存操作日志失败!rest调用返回的结果转换为实体失败,失败原因:" + e.getMessage());
}
}else{
logger.error("保存操作日志失败!失败原因:" + responseResult.getMsg());
}
}
}