数据后台管理(五)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天学会 ...
随机推荐
- 蓝松短视频SDK基本功能免费列表
下载地址:https://github.com/LanSoSdk/LanSoEditor_common 功能免费. 个人和公司都可以商用,不需要和我们说明. 直接下载, 直接去用既可. 完全不需要和我 ...
- 大家久等了,改造版阿里巴巴 sentinel 控制台终于开源了
前言 最近几天,好几个小伙伴在后台询问,改造后的 sentinel-dashboard 什么时候开源.讲真,不是不想给大家放出来,是因为一些地方还没有完善好,怕误导了大家,在经过了一个星期业余时间的努 ...
- MongoDB 学习笔记之 索引选项和重建索引
索引选项: {background:true}在后台创建索引,索引在构建过程中,其他客户端仍然可以查询数据,不会阻塞. db.comments.createIndex({anonymous: 1},{ ...
- .NET斗鱼直播弹幕客户端(上)
现在直播平台由于弹幕的存在,主播与观众可以更轻松地进行互动,非常受年轻群众的欢迎.斗鱼TV就是一款非常流行的直播平台,弹幕更是非常火爆.看到有不少主播接入弹幕语音播报器.弹幕点歌等模块,这都需要首先连 ...
- python编程基础之三十
时间模块: 时间戳:就是当前是键距离1970年1月1日0:0:0的秒数,后面还带小数,可以说是非常精确 时间的表示形式: a.以整数或者浮点数表示一个以秒为单位的时间间隔,这个时间的基础值1970.1 ...
- Spring Cloud 入门系列(一)
前言 Spring Could作为目前最流行基于Java开发的构建微服务的完整框架.发现目前相关系列教程太少,本文是基于官网教程做的一套翻译. 何为Spring Cloud? Spring Cloud ...
- 多线程EventWaitHandle -戈多编程
在.NET的System.Threading命名空间中有一个名叫WaitHandler的类,这是一个抽象类(abstract),我们无法手动去创建它,但是WaitHandler有三个子类,这三个子类分 ...
- python程序编译成exe文件
最近越来越喜欢使用python写工具.使用的时候,发现程序内部成员python安装目录常常不同,如果用bat双击执行,常常需要修改从svn上down下来的bat文件中python.exe的路径.而给策 ...
- TCP Traffic Analyzer
TCP Traffic Analyzer 工具yahoo 发布的一款开源网络分析工具,可以分析网络应用在服务器端与客户端之间的运行状态Yconalyzer保持与tcpdump兼容,两者生成的抓取文件能 ...
- win10系统 plsql developer启动慢
win10系统plsql启动慢一般原因是plsql打印设置的问题,若默认打印机设置为网络上某一位置的打印机,则plsql启动时会去寻找该打印机,导致启动很慢. 解决办法1 直接禁止print spoo ...