数据后台管理(五)AOP日志
为了增加数据的安全性,在数据管理的过程中,我们需要将操作者访问时间,操作者的名称,访问的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日志的更多相关文章
- Django:(博客系统)使用使用mysql数据->后台管理tag/post/category的配置
Django后台一般是不需要人为的去开发的,因为django已经通过配置实现哪些模块是后台需要管理,如何排序,列表展示哪些列,列显示名称,是否为空(默认值),过滤条件,分页页数,列表中哪些项可编辑等等 ...
- 【Java EE 学习 76 下】【数据采集系统第八天】【通过AOP实现日志管理】【日志管理功能分析和初步实现】
一.日志管理相关分析 1.日志管理是一种典型的系统级别的应用,非常适合使用spring AOP实现. 2.使用日志管理的目的:对系统修改的动作进行记录,比如对权限.角色.用户的写操作.修改操作.删除操 ...
- 在django中进行后台管理时插入外键数据时不显示值的问题
在django的后台管理站点插入数据时,发现需要添加外键时,下拉框中不显示值 按照显示内容中的object,考虑这里应该是调用的模型类的objects对象方法,那么去models.py中对模型类添加一 ...
- Django -->admin后台(后台管理可以直接往数据库添加数据)
一.使用pymysql时,必须加这两行(#如果使用mysql的数据库,请进行伪装 pymysql伪装为MySQLdb) import pymysqlpymysql.install_as_MySQLdb ...
- 033 SSM综合练习09--数据后台管理系统--基于AOP的日志处理
1.数据库与表结构 (1)日志表信息描述sysLog (2)Sql语句 CREATE TABLE sysLog ( id ) DEFAULT SYS_GUID () PRIMARY KEY, visi ...
- Laravel-Easy-Admin 快速搭建数据后台 web管理后台
基于PHP + Laravel + element-admin-ui 搭建的快速数据后台,只在解决系列后台增删改查等日常操作.快速搭建,在生成业务的同时可以花更多的时间关注技术本身,提高程序员自身进阶 ...
- 我的MYSQL学习心得(十五) 日志
我的MYSQL学习心得(十五) 日志 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...
- 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现
本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站.本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用.本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采 ...
- 10天学会phpWeChat——第六天:实现新闻的后台管理
通过前面五讲的系列教程,我们完成了一个简单模块的前端发布.列表展示.详情展示.实际生产环境中,所有前台的数据都会有对应的后台操作进行统筹管理.我们称之为后台管理系统. 今天,我们开始<10天学会 ...
随机推荐
- Spring Security 梳理 - session
Spring Security默认的行为是每个登录成功的用户会新建一个Session.这也就是下面的配置的效果: <http create-session="ifRequired&qu ...
- Centos 6下使用cmake编译安装MariaDB
写在前面 最近在学习Maria DB,为了方便查阅,又为了将所学的知识重新的梳理,特作此随笔一篇,希望过后阅读时能有所感,也希望对大家能够有所帮助. 安装前的准备 大家都知道,在Linux上安装软件一 ...
- maven 打包构建相关命令
1.命令 mvn clean package 依次执行clean.resources.compile.testResources.testCompile.test.jar(打包)等7个阶段. mvn ...
- ps 将图片四角变成圆角
1.用PS打开一张图片,用矩形选框工具,选出你要保留的的那一部分,“选择→修改→平滑”.在弹出的选框里添入数值,值越大角就越圆. 2.选择“选择→反选”,再按delete删除就ok了.
- 使用.NET Core中创建Windows服务(一) - 使用官方推荐方式
原文:Creating Windows Services In .NET Core – Part 1 – The "Microsoft" Way 作者:Dotnet Core Tu ...
- 在 Cocos Creator 中使用 Protobufjs(一)
一. 环境准备 我一直在探索Cocos H5正确的开发姿势,目前做javascript项目已经离不开 nodejs.npm或grunt等脚手架工具了. 1.初始化package.json文件 npm ...
- Java 学习笔记之 Suspend和Resume
Suspend和Resume: Suspend和Resume使用方法: 以下例子证明了线程确实被暂停了,而且还可以恢复成运行状态. public class SuspendResumeThread e ...
- MongoDB 学习笔记之 分片和副本集混合运用
分片和副本集混合运用: 基本架构图: 搭建详细配置: 3个shard + 3个replicat set + 3个configserver + 3个Mongos shardrsname Primary ...
- F#周报2019年第41期
新闻 .NET架构指南 美妙的WebSharper:学术刊物 .NET Core 3.0中Blazor Server的方案与性能 Mono 6.4.0发布说明 CapitolFSharp召集发言人 视 ...
- python 中的一点新知识
逻辑行与物理行 所谓物理行(Physical Line)是你在编写程序时 你所看到 的内容.所谓逻辑行(Logical Line)是 Python 所看到 的单个语句.Python 会假定每一 物理行 ...