问题:

  系统需要记录用户的关键操作日志,以便后期的系统维护,方便的查看问题,及时排除

分析:

  (1)保存字段:作为一个日志记录功能,首先数据库新建一张表保存用户的操作关键字段,

          用户名,ip,操作描述,时间,日志id

  (2)采用技术:

      第一种:新建一个日志业务实现,在操作发生时进行联动

          缺点是耦合太紧密,无用代码增多,后期代码臃肿,改动时地方分散,不利于维护

      第二种:使用spring 的 aop 技术进行切面切入

          由于本身系统结构不规范,参数,方法名没有一致的样式,使用正则匹配方法名不是很方便

          本身日志记录也只是记录关键操作,api全部切入的话,就不需要这个功能了

          必须有针对性的记录关键操作日志

      第三种:使用spring 的 aop 技术切到自定义注解上,针对不同注解标志进行参数解析,记录日志

          缺点是要针对每个不同的注解标志进行分别取注解标志,获取参数进行日志记录输出

         

解决:

  由于本身系统的不规范,个人技术能力的欠缺,目前采用第三种办法进行关键日志的记录

  (1)首先新建 注解类【MethodLog】

package org.triber.portal.service.logAop;

import java.lang.annotation.*;

/**
* 日志切面注解
*/ @Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodLog { String remark() default "";
String operType() default "0";
// String desc() default "";
}

  (2)新建切面实现类【LogService】

package org.triber.portal.service.logAop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
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 org.triber.common.helper.StringUtil;
import org.triber.common.helper.UserUtil;
import org.triber.common.model.menu.MenuModel;
import org.triber.common.model.user.User;
import org.triber.portal.dao.mapper.operateLog.OperateLogMapper;
import org.triber.portal.model.area.Area; import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Calendar; /**
* 日志切面实现
*/ @Component
@Aspect
public class LogService { @Autowired
private OperateLogMapper dao; public LogService() {
System.out.println("Aop");
} /**
* 切点
*/
@Pointcut("@annotation(org.triber.portal.service.logAop.MethodLog)")
public void methodCachePointcut() { } /**
* 切面
*
* @param point
* @return
* @throws Throwable
*/
@Around("methodCachePointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
Calendar ca = Calendar.getInstance();
String operDate = df.format(ca.getTime());
String ip = getIp(request);
User user = UserUtil.getCurrentUser(request);
String loginName;
String name;
if (user != null) {
loginName = user.getLoginName();
} else {
loginName = "匿名用户";
}
String methodRemark = getMthodRemark(point);
String methodName = point.getSignature().getName();
String packages = point.getThis().getClass().getName();
if (packages.indexOf("$$EnhancerByCGLIB$$") > -1) { // 如果是CGLIB动态生成的类
try {
packages = packages.substring(0, packages.indexOf("$$"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
String operatingcontent = "";
Object[] method_param = null; Object object;
try {
method_param = point.getArgs(); //获取方法参数
// String param=(String) point.proceed(point.getArgs());
object = point.proceed();
} catch (Exception e) {
// 异常处理记录日志..log.error(e);
throw e;
}
Syslog sysLog = new Syslog();
sysLog.setOptId(org.triber.common.util.StringUtil.getRandNum(11));
sysLog.setLoginId(user.getLoginId());
sysLog.setLoginName(loginName);
sysLog.setIpAddress(ip);
sysLog.setMethodName(packages + "." + methodName);
sysLog.setMethodRemark(methodRemark);
sysLog.setOptDate(operDate); /**
* 用户操作
*/
if("新增用户".equals(methodRemark)){
HttpServletRequest req = (HttpServletRequest) method_param[0];
sysLog.setOperatingcontent("新增用户: 用户名为 " + req.getParameter("userName")); }
if("删除用户".equals(methodRemark)){
String loginId = (String) method_param[1];
sysLog.setOperatingcontent("删除用户: 用户id为 " + loginId);
}
if("修改用户".equals(methodRemark)){
HttpServletRequest req = (HttpServletRequest) method_param[0];
sysLog.setOperatingcontent("修改用户: 用户名为 " + req.getParameter("loginName"));
} /**
* 角色操作
*/
if("新增角色".equals(methodRemark)){
HttpServletRequest req = (HttpServletRequest) method_param[0];
sysLog.setOperatingcontent("新增角色: 角色名为 " + req.getParameter("roleDesc"));
}
if("删除角色".equals(methodRemark)){
String roleId = (String) method_param[1];
sysLog.setOperatingcontent("新增角色: 角色id为 " + roleId);
}
if("修改角色".equals(methodRemark)){
HttpServletRequest req = (HttpServletRequest) method_param[0];
sysLog.setOperatingcontent("修改角色: 角色名为 " + req.getParameter("roleDesc"));
} /**
* 菜单操作
*/
if("新增菜单".equals(methodRemark)){
MenuModel menuModel = (MenuModel) method_param[0];
sysLog.setOperatingcontent("新增菜单: 菜单名为 " + menuModel.getMenuName());
}
if("删除菜单".equals(methodRemark)){
String menuId = (String) method_param[0];
sysLog.setOperatingcontent("删除菜单: 菜单id为 " + menuId);
}
if("修改菜单".equals(methodRemark)){
MenuModel menuModel = (MenuModel) method_param[0];
sysLog.setOperatingcontent("修改菜单: 菜单名为 " + menuModel.getMenuName());
} /**
* 部门操作
*/
if("新增部门".equals(methodRemark)){
String deptDesc = (String) method_param[1];
sysLog.setOperatingcontent("新增部门: 部门名为 " + deptDesc); }
if("修改部门".equals(methodRemark)){
String deptDesc = (String) method_param[2];
sysLog.setOperatingcontent("修改部门: 部门名为 " + deptDesc);
} /**
* 地区操作
*/
if("新增地区".equals(methodRemark)){
Area area = (Area) method_param[0];
sysLog.setOperatingcontent("新增地区: 地区名为 " + area.getAreaDscr().trim());
}
if("删除地区".equals(methodRemark)){
String areaId = (String) method_param[0];
sysLog.setOperatingcontent("删除地区: 地区id为 " + areaId);
}
if("修改地区".equals(methodRemark)){
Area area = (Area) method_param[0];
sysLog.setOperatingcontent("修改地区: 地区名为 " + area.getAreaDscr().trim());
} /**
* 机构操作
*/
if("新增机构".equals(methodRemark)){
String isAdd = (String) method_param[1];
if(isAdd.equals("1")){
String addOrgDscrPancy = (String) method_param[5];
sysLog.setOperatingcontent("新增机构: 机构名为 " + addOrgDscrPancy);
}else{
String addOrgDscrPancy = (String) method_param[5];
sysLog.setOperatingcontent("修改机构: 机构名为 " + addOrgDscrPancy);
} }
if("删除机构".equals(methodRemark)){
String orgId = (String) method_param[3];
sysLog.setOperatingcontent("删除机构: 机构id为 " + orgId);
} /**
* 空参数
*/
if("".equals(methodRemark) || null == methodRemark){
sysLog.setOperatingcontent("操作参数: " + method_param[0]);
} dao.saveSysLog(sysLog);
// System.out.println("日志实体:"+sysLog.getLoginName()+sysLog.getMethodRemark()+sysLog.getOperatingcontent());
return object; } /**
* 方法异常时调用
*
* @param ex
*/
public void afterThrowing(Exception ex) {
System.out.println("afterThrowing");
System.out.println(ex);
} /**
* 获取方法中的中文备注
*
* @param joinPoint
* @return
* @throws Exception
*/
public static String getMthodRemark(ProceedingJoinPoint joinPoint) throws Exception { String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs(); Class targetClass = Class.forName(targetName);
Method[] method = targetClass.getMethods();
String methode = "";
for (Method m : method) {
if (m.getName().equals(methodName)) {
Class[] tmpCs = m.getParameterTypes();
if (tmpCs.length == arguments.length) {
MethodLog methodCache = m.getAnnotation(MethodLog.class);
if (methodCache != null) {
methode = methodCache.remark();
}
break;
}
}
}
return methode;
} /**
* 获取请求ip
*
* @param request
* @return
*/
public static String getIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
int index = ip.indexOf(",");
if (index != -1) {
return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip.substring(0, index);
} else {
return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
}
}
ip = request.getHeader("X-Real-IP");
if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
return ip;
}
return request.getRemoteAddr().equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
} }

  (3)新建日志实体【Syslog】

package org.triber.portal.service.logAop;

import lombok.Getter;
import lombok.Setter; import java.io.Serializable; /**
* 操作日志实体类
*/
public class Syslog implements Serializable{ @Setter@Getter private String optId;
@Setter@Getter private String loginId;
@Setter@Getter private String loginName;
@Setter@Getter private String ipAddress;
@Setter@Getter private String methodName;
@Setter@Getter private String methodRemark;
@Setter@Getter private String operatingcontent;
@Setter@Getter private String optDate;
//模糊条件
@Setter@Getter private String serchCondition;
}

  (4)日志切入【添加注解标志即可】

 /**
* 删除金融机构
* @param request
* @param response
* @param operateVersionId 机构版本
* @param orgId 机构iD
* @param orgLvl 机构层级
* @return
* @throws Exception
*/
@RequestMapping(value = "delOrgByFlagAndOrgId", method = RequestMethod.POST, produces = {"application/json"})
@MethodLog(remark = "删除机构")
public String delOrgByFlagAndOrgId(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value = "operateVersionId", required = false) String operateVersionId,
@RequestParam(value = "orgId", required = false) String orgId,
@RequestParam(value = "orgLvl", required = false) String orgLvl) throws Exception{
orgService.delOrgByFlagAndOrgId(areaIdPrefix,orgId, orgLvl, operateVersionId);
return "0";
}

  (5)maven注入aop依赖

<!--spring切面aop依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency> 在application.properties文件里加这样一条配置
spring.aop.auto=true 在springboot项目里加这两条配置即可,就可以开启aop功能

总结:

  至此,大功告成,可以开始加注解标志,获取参数,记录关键信息,输出日志了。。。

  

Spring_AOP 记录系统关键操作日志用法的更多相关文章

  1. Struts2拦截器记录系统操作日志

    前言 最近开发了一个项目,由于项目在整个开发过程中处于赶时间状态(每个项目都差不多如此)所以项目在收尾阶段发现缺少记录系统日志功能,以前系统都是直接写在每个模块的代码中,然后存入表单,在页面可以查看部 ...

  2. 【开源】OSharp3.0框架解说系列(6.2):操作日志与数据日志

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  3. linux查看ssh用户登录日志与操作日志

    linux查看ssh用户登录日志与操作日志 2013-11-01转载   ssh用户登录日志 linux下登录日志在下面的目录里:  代码如下 复制代码 cd /var/log 查看ssh用户的登录日 ...

  4. Winform开发框架之权限管理系统改进的经验总结(4)-一行代码实现表操作日志记录

    在前面介绍了几篇关于我的权限系统改进的一些经验总结,本篇继续这一系列主体,介绍如何一行代码实现重要表的操作日志记录.我们知道,在很多业务系统里面,数据是很敏感的,特别对于一些增加.修改.删除等关键的操 ...

  5. 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

    在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...

  6. Jeecg中通过Spring_AOP+注解方式实现日志的管理

    转载;https://blog.csdn.net/ma451152002/article/details/77234236 Jeecg中通过Spring_AOP+注解方式实现日志的管理 一.设计思路 ...

  7. [从源码学设计]蚂蚁金服SOFARegistry 之 服务注册和操作日志

    [从源码学设计]蚂蚁金服SOFARegistry之服务注册和操作日志 目录 [从源码学设计]蚂蚁金服SOFARegistry之服务注册和操作日志 0x00 摘要 0x01 整体业务流程 1.1 服务注 ...

  8. Appfuse:记录操作日志

    appfuse的数据维护操作都发生在***form页面,与之对应的是***FormController,在Controller中处理数据的操作是onSubmit方法,既然所有的操作都通过onSubmi ...

  9. C#操作日志

    首先引用NLog的dll文件 using System.IO; using NLog; -------------------------------------------------------- ...

随机推荐

  1. 对YUV数据进行裁剪

    项目中用到,用来对YUV数据(图片的yuv或者视频单帧yuv数据)进行裁剪. 格式介绍:http://blog.csdn.net/vblittleboy/article/details/1094514 ...

  2. 排错-Loadrunner录制打不开浏览器解决方法

    排错-Loadrunner录制打不开浏览器解决方法 by:授客 QQ:1033553122 问题描述: 采用自带的web测试站点http://127.0.0.1:1080/WebTours/,进行录制 ...

  3. Android 与Java 进程退出 killProcess与System.exit

    android所有activity都在主进程中,在清单文件Androidmanifest.xml中可以设置启动不同进程,Service需要指定运行在单独进程?主进程中的主线程?还是主进程中的其他线程? ...

  4. (后端)sql手工注入语句&SQL手工注入大全(转)

    转自脚本之家: 看看下面的1.判断是否有注入;and 1=1;and 1=2 2.初步判断是否是mssql;and user>0 3.判断数据库系统;and (select count(*) f ...

  5. Javascript数组系列四之数组的转换与排序Sort方法

    今天我们继续来介绍 Javascirpt 数组中的方法,也是数组系列的第四篇文章,因为数组的方法众多,每篇文章我们都对数组的每个方法都有比较细致的描述,只要你能够从中成长一点点,那我们的目的就达到了, ...

  6. 关于PID的如何修改的FAQ

    1.如何查询支付宝账号对应的PID: 2.意外绑错或者想修改PID流程: (1)和业务联系拿到商家平台支付宝变更协议书填写(模版如下,可在附件中下载) 致:杭州银盒宝成科技有限公司 本人因      ...

  7. OPPO A57 刷机(官方安装包)+完美Root+ 破解主题+屏蔽Root顶部红色框+NV修复

    朋友说她的手机被被人刷后,有许多预装的软件问我能不能处理下,让我装个纯净版. 开机可以看到预装了许多软件,通常想要删除预装软件就必须Root,于是下载刷机精灵,360刷机大师,线刷包之类的软件Root ...

  8. 前后端分离djangorestframework——视图组件

    CBV与FBV CBV之前说过就是在view.py里写视图类,在序列化时用过,FBV就是常用的视图函数,两者的功能都可以实现功能,但是在restful规范方面的话,CBV更方便,FBV还要用reque ...

  9. 【ABAP CDS系列】ABAP CDS中的系统信息

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP CDS系列]ABAP CDS中的系统 ...

  10. Tomcat优化配置

    1.环境: 系统:Windows.Linux Tomcat版本:9 2.编码与性能调优 server.xml文件: <Connector port="8080" connec ...