为了增加数据的安全性,在数据管理的过程中,我们需要将操作者访问时间,操作者的名称,访问的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;
}
}

最新文章

  1. &lt;HTML&gt;菜鸟入门基础须知
  2. SQL Server 2008 修改表所有者,架构
  3. css浏览器窗口大小
  4. Java设计模式之简单工厂设计模式
  5. [HDU 4585] Shaolin (map应用)
  6. idea maven添加jar包
  7. Mysql表操作
  8. http2.0 相对于 http1.1的优势
  9. LeetCode——Reverse Words in a String
  10. 利用js_API 运行对html文档元素的属性的CRUD操作
  11. 【Error】JavaWeb: 严重: Failed to initialize end point associated with ProtocolHandler [&amp;quot;http-bio-8080&amp;quot;]
  12. POJ 3414--Pots(BFS+回溯路径)
  13. [其他]win7下chrome浏览器插件导出与导入
  14. php-fpm 与 fastCgi的浅谈
  15. bootstrap fileinput上传返回400,404,500 等错误替换
  16. windows 子系统 linux wsl 开启ssh 服务
  17. 四则运算 C 语言
  18. Linux(CentOS7.0)下 C访问MySQL (转)
  19. 廖雪峰Java2面向对象编程-6Java核心类-1字符串和编码
  20. 字符、字符串和文本的处理之String类型

热门文章

  1. cmd控制台 wrapper | OpenSCManager failed - 拒绝访问。 (0x5)解决
  2. Python列表的深度排序
  3. 不吹不黑,今天我们来聊一聊 Kubernetes 落地的三种方式
  4. 为什么要学习go语言
  5. 【maven的使用】1maven的概念与配置
  6. 为什么用Markdown,而不用Word?
  7. 实战SpringCloud响应式微服务系列教程(第七章)
  8. 那些初学python犯过的小白错误(学习笔记1)
  9. restTemplate getForObject中map传参问题
  10. postman常用断言