首页 技术 正文
技术 2022年11月18日
0 收藏 877 点赞 3,730 浏览 8472 个字

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

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

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

日志表syslog

数据后台管理(五)AOP日志

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存在的问题

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

数据后台管理(五)AOP日志

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

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

流程分析图:

数据后台管理(五)AOP日志

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;
}
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,103
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,579
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,427
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,199
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,834
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,917