为了增加数据的安全性,在数据管理的过程中,我们需要将操作者访问时间,操作者的名称,访问的IP,访问资源的URL,执行时长,访问方法记录下来存储到数据库中,并可以通过页面查看。

1.将日志信息存储到数据库中

1.1根据需要记录的日志内容在数据库中创建表syslog和对应的实体类SysLog

日志表syslog

SysLog类

 package club.nipengfei.ssm.domain;

 import java.util.Date;

 public class SysLog {
private String id;
private Date visitTime;
private String visitTimeStr;
private String username;
private String ip;
private String url;
private Long executionTime;
private String method; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public Date getVisitTime() {
return visitTime;
} public void setVisitTime(Date visitTime) {
this.visitTime = visitTime;
} public String getVisitTimeStr() {
return visitTimeStr;
} public void setVisitTimeStr(String visitTimeStr) {
this.visitTimeStr = visitTimeStr;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getIp() {
return ip;
} public void setIp(String ip) {
this.ip = ip;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
} public Long getExecutionTime() {
return executionTime;
} public void setExecutionTime(Long executionTime) {
this.executionTime = executionTime;
} public String getMethod() {
return method;
} public void setMethod(String method) {
this.method = method;
}
}

SysLog

1.2在controller包下新建一个切面类LogAop来获取需要记录日志内容

注意该类作为切面类需要注解@Aspect

在该切面类内创建一个前置通知@Before("execution(* club.nipengfei.ssm.controller.*.*(..))"),一个后置通知@After("execution(* club.nipengfei.ssm.controller.*.*(..))"),注解内的属性表示切入点表达式,在这里表示controller包下的所有类。

1.2.1获取操作者的访问时间

直接在前置通知内new一个Date()

1.2.2获取操作者名称

 // 获取当前操作的用户
SecurityContext context = SecurityContextHolder.getContext();
User user =(User) context.getAuthentication().getPrincipal();
String username = user.getUsername();

1.2.3获取访问IP

先在web.xml中新增一个监听器

   <listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

通过getRemoteAddr()方法获取IP

 // 获取IP地址
String ip = request.getRemoteAddr();

1.2.4获取访问资源的URL

思路:获取类上注解的@RequestMapping的属性值和方法上注解@RequestMapping的属性值,并将两者拼接。

获取类上注解属性值:通过反射获取操作的类,使用getAnnotation(RequestMapping.class)方法获取@RequestMapping注解,使用value()获取属性

获取方法上注解属性值:通过反射获取操作的类,使用getMethod()方法获取方法,使用getAnnotation(RequestMapping.class)方法获取@RequestMapping注解,使用value()获取属性

具体代码放下面。

1.2.5获取执行时长

在后置通知内new一个Date()减去前置通知的Date()。

 // 获取访问时长
long time = new Date().getTime()-visitTime.getTime();

1.2.6获取访问方法

通过类的getMethod()方法获取方法。

注意:有些方法含参,有些不含参需要分开处理。

     @Before("execution(* club.nipengfei.ssm.controller.*.*(..))")
public void doBefore(JoinPoint jp) throws NoSuchMethodException {
visitTime = new Date(); // 当前时间就是开始访问的类
clazz = jp.getTarget().getClass(); // 具体访问的类
String methodName = jp.getSignature().getName(); // 获取访问方法名称
Object[] args = jp.getArgs(); // 获取访问方法参数 // 获取具体执行方法Method对象
if (args==null || args.length==0){
method = clazz.getMethod(methodName);
} else {
Class[] classArgs = new Class[args.length];
for (int i=0;i<args.length;i++){
classArgs[i] = args[i].getClass();
}
method = clazz.getMethod(methodName,classArgs);
}
}

LogAop类的代码:

 package club.nipengfei.ssm.controller;

 import club.nipengfei.ssm.domain.SysLog;
import club.nipengfei.ssm.service.ISysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date; @Component
@Aspect
public class LogAop { @Autowired
private HttpServletRequest request; @Autowired
private ISysLogService sysLogService; private Date visitTime; // 开始时间
private Class clazz; // 访问的类
private Method method; // 访问的方法 // 前置通知 主要获取开始时间,执行的类哪一个,执行的哪一个方法
@Before("execution(* club.nipengfei.ssm.controller.*.*(..))")
public void doBefore(JoinPoint jp) throws NoSuchMethodException {
visitTime = new Date(); // 当前时间就是开始访问的类
clazz = jp.getTarget().getClass(); // 具体访问的类
String methodName = jp.getSignature().getName(); // 获取访问方法名称
Object[] args = jp.getArgs(); // 获取访问方法参数 // 获取具体执行方法Method对象
if (args==null || args.length==0){
method = clazz.getMethod(methodName);
} else {
Class[] classArgs = new Class[args.length];
for (int i=0;i<args.length;i++){
classArgs[i] = args[i].getClass();
}
method = clazz.getMethod(methodName,classArgs);
}
} // 后置通知
@After("execution(* club.nipengfei.ssm.controller.*.*(..))")
public void doAfter(JoinPoint jp) throws Exception { // 获取访问时长
long time = new Date().getTime()-visitTime.getTime(); String url = "";
// 获取url
if (clazz != null && method !=null && clazz!=LogAop.class){
// 获取类的@RequestMapping("/orders")
RequestMapping clazzAnnotation =(RequestMapping) clazz.getAnnotation(RequestMapping.class);
if (clazzAnnotation != null){
String[] classValue = clazzAnnotation.value();
// 获取方法上的@RequestMapping("xxx")
RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
if (methodAnnotation != null){
String[] methodValue = methodAnnotation.value();
url=classValue[0]+methodValue[0]; // 获取IP地址
String ip = request.getRemoteAddr(); // 获取当前操作的用户
SecurityContext context = SecurityContextHolder.getContext();
User user =(User) context.getAuthentication().getPrincipal();
String username = user.getUsername(); // 将日志相关信息封装到SysLog对象
SysLog sysLog = new SysLog();
sysLog.setExecutionTime(time);
sysLog.setIp(ip);
sysLog.setMethod("[类名] "+clazz.getName()+"[方法名] "+method.getName());
sysLog.setUrl(url);
sysLog.setUsername(username);
sysLog.setVisitTime(visitTime); // 调用service完成操作
sysLogService.save(sysLog);
}
} }
}
}

1.3在service.impl包下新建一个SysLogServiceImpl类,生成一个save方法将SysLog类对象放到数据表中

 package club.nipengfei.ssm.service.impl;

 import club.nipengfei.ssm.dao.ISysLogDao;
import club.nipengfei.ssm.domain.SysLog;
import club.nipengfei.ssm.service.ISysLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service
@Transactional
public class SysLogServiceImpl implements ISysLogService { @Autowired
private ISysLogDao sysLogDao; @Override
public void save(SysLog sysLog) throws Exception {
sysLogDao.save(sysLog);
} }

1.4在dao包下新建ISysLogDao接口

 package club.nipengfei.ssm.dao;

 import club.nipengfei.ssm.domain.SysLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select; import java.util.List; public interface ISysLogDao { @Insert("insert into syslog(visitTime,username,ip,url,executionTime,method) values(#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})")
public void save(SysLog sysLog) throws Exception; }

1.5存在的问题

当点击订单管理时发现,不能正常访问

查看资料发现因为该findAll方法传入的形参是int类型,而我们的切面类通过反射获取该类的方法时传入的参数Integer类型。将findAll方法的int改为Integer,发现能正常访问了。

2.将日志信息展示到页面上

流程分析图:

2.1在ISysLogDao接口中生成一个findAll方法

 package club.nipengfei.ssm.dao;

 import club.nipengfei.ssm.domain.SysLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select; import java.util.List; public interface ISysLogDao { @Insert("insert into syslog(visitTime,username,ip,url,executionTime,method) values(#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})")
public void save(SysLog sysLog) throws Exception; @Select("select * from sysLog")
List<SysLog> findAll() throws Exception;
}

2.2在SysLogServiceImpl类内调用上面方法

 package club.nipengfei.ssm.service.impl;

 import club.nipengfei.ssm.dao.ISysLogDao;
import club.nipengfei.ssm.domain.SysLog;
import club.nipengfei.ssm.service.ISysLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service
@Transactional
public class SysLogServiceImpl implements ISysLogService { @Autowired
private ISysLogDao sysLogDao; @Override
public void save(SysLog sysLog) throws Exception {
sysLogDao.save(sysLog);
} @Override
public List<SysLog> findAll() throws Exception {
return sysLogDao.findAll();
}
}

2.3在controller包下新建一个SysLogController类

 package club.nipengfei.ssm.controller;

 import club.nipengfei.ssm.domain.SysLog;
import club.nipengfei.ssm.service.ISysLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import java.util.List; @Controller
@RequestMapping("/sysLog")
public class SysLogController { @Autowired
private ISysLogService sysLogService; @RequestMapping("/findAll.do")
public ModelAndView findAll() throws Exception {
ModelAndView mv = new ModelAndView();
List<SysLog> sysLogList = sysLogService.findAll();
mv.addObject("sysLogs",sysLogList);
mv.setViewName("syslog-list");
return mv;
}
}

数据后台管理(五)AOP日志的更多相关文章

  1. Django:(博客系统)使用使用mysql数据->后台管理tag/post/category的配置

    Django后台一般是不需要人为的去开发的,因为django已经通过配置实现哪些模块是后台需要管理,如何排序,列表展示哪些列,列显示名称,是否为空(默认值),过滤条件,分页页数,列表中哪些项可编辑等等 ...

  2. 【Java EE 学习 76 下】【数据采集系统第八天】【通过AOP实现日志管理】【日志管理功能分析和初步实现】

    一.日志管理相关分析 1.日志管理是一种典型的系统级别的应用,非常适合使用spring AOP实现. 2.使用日志管理的目的:对系统修改的动作进行记录,比如对权限.角色.用户的写操作.修改操作.删除操 ...

  3. 在django中进行后台管理时插入外键数据时不显示值的问题

    在django的后台管理站点插入数据时,发现需要添加外键时,下拉框中不显示值 按照显示内容中的object,考虑这里应该是调用的模型类的objects对象方法,那么去models.py中对模型类添加一 ...

  4. Django -->admin后台(后台管理可以直接往数据库添加数据)

    一.使用pymysql时,必须加这两行(#如果使用mysql的数据库,请进行伪装 pymysql伪装为MySQLdb) import pymysqlpymysql.install_as_MySQLdb ...

  5. 033 SSM综合练习09--数据后台管理系统--基于AOP的日志处理

    1.数据库与表结构 (1)日志表信息描述sysLog (2)Sql语句 CREATE TABLE sysLog ( id ) DEFAULT SYS_GUID () PRIMARY KEY, visi ...

  6. Laravel-Easy-Admin 快速搭建数据后台 web管理后台

    基于PHP + Laravel + element-admin-ui 搭建的快速数据后台,只在解决系列后台增删改查等日常操作.快速搭建,在生成业务的同时可以花更多的时间关注技术本身,提高程序员自身进阶 ...

  7. 我的MYSQL学习心得(十五) 日志

    我的MYSQL学习心得(十五) 日志 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  8. 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现

    本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站.本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用.本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采 ...

  9. 10天学会phpWeChat——第六天:实现新闻的后台管理

    通过前面五讲的系列教程,我们完成了一个简单模块的前端发布.列表展示.详情展示.实际生产环境中,所有前台的数据都会有对应的后台操作进行统筹管理.我们称之为后台管理系统. 今天,我们开始<10天学会 ...

随机推荐

  1. Java 文章链接

    Java表单验证封装类 https://www.cnblogs.com/linjiqin/archive/2013/11/18/3429424.html 微信企业号接入JDK6和JDK7及JDK8加解 ...

  2. JS/JQuery 禁用超链接a

    JS // 禁用超链接元素elem ; document.getElementById(elemID).setAttribute('disabled', 'disabled'); // 启用超链接元素 ...

  3. 并发编程之多线程(Java)

    一.线程与进程区别 每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程.线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行.也可以把它理解为代码运行的上下文.所以线程基本上是 ...

  4. MapReduce与Yarn 的详细工作流程分析

    MapReduce详细工作流程之Map阶段 如上图所示 首先有一个200M的待处理文件 切片:在客户端提交之前,根据参数配置,进行任务规划,将文件按128M每块进行切片 提交:提交可以提交到本地工作环 ...

  5. 分享8点超级有用的Python编程建议

    我们在用Python进行机器学习建模项目的时候,每个人都会有自己的一套项目文件管理的习惯,我自己也有一套方法,是自己曾经踩过的坑总结出来的,现在在这里分享一下给大家,希望多少有些地方可以给大家借鉴.

  6. 软件开发工具(第12章: CVS的安装及使用)

    一.CVS介绍 并发版本系统(Concurrent Versions System——CVS)是一个常用 的代码版本控制系统. 使用CVS可以对代码进行集中管理,记录代码所有的更改历史,提供 协作开发 ...

  7. 版本控制之Git小结

    一.版本控制 1.1 什么是版本控制 版本控制是一种记录一个或若干个文件内容变化,以便将来查阅特定版本修订情况的系统.可以对任何类型的文件进行版本控制. 1.2 为什么需要版本控制 有了版本控制就可以 ...

  8. springmvc处理局部异常和全局异常

    springmvc通过HandlerExceptionResolver(是一个接口,在spring-webmvc依赖下)处理程序异常,包括处理器异常.数据绑定异常以及处理器执行时发生的异常.Handl ...

  9. Web Storage和cookie的区别——每日一题20190629

    Web Storage? 使用HTML5可以在本地存储用户的浏览数据. 使用的主要目的是为了克服Cookie带来的一些限制,当数据需要被严格控制在客户端上时,无需持续的将数据发回服务器 主要目标: 1 ...

  10. 通过实例理解Java网络IO模型

    网络IO模型及分类 网络IO模型是一个经常被提到的问题,不同的书或者博客说法可能都不一样,所以没必要死抠字眼,关键在于理解. Socket连接 不管是什么模型,所使用的socket连接都是一样的. 以 ...