zoukankan      html  css  js  c++  java
  • 数据后台管理(五)AOP日志

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

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

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

    日志表syslog

    SysLog类

     1 package club.nipengfei.ssm.domain;
     2 
     3 import java.util.Date;
     4 
     5 public class SysLog {
     6     private String id;
     7     private Date visitTime;
     8     private String visitTimeStr;
     9     private String username;
    10     private String ip;
    11     private String url;
    12     private Long executionTime;
    13     private String method;
    14 
    15     public String getId() {
    16         return id;
    17     }
    18 
    19     public void setId(String id) {
    20         this.id = id;
    21     }
    22 
    23     public Date getVisitTime() {
    24         return visitTime;
    25     }
    26 
    27     public void setVisitTime(Date visitTime) {
    28         this.visitTime = visitTime;
    29     }
    30 
    31     public String getVisitTimeStr() {
    32         return visitTimeStr;
    33     }
    34 
    35     public void setVisitTimeStr(String visitTimeStr) {
    36         this.visitTimeStr = visitTimeStr;
    37     }
    38 
    39     public String getUsername() {
    40         return username;
    41     }
    42 
    43     public void setUsername(String username) {
    44         this.username = username;
    45     }
    46 
    47     public String getIp() {
    48         return ip;
    49     }
    50 
    51     public void setIp(String ip) {
    52         this.ip = ip;
    53     }
    54 
    55     public String getUrl() {
    56         return url;
    57     }
    58 
    59     public void setUrl(String url) {
    60         this.url = url;
    61     }
    62 
    63     public Long getExecutionTime() {
    64         return executionTime;
    65     }
    66 
    67     public void setExecutionTime(Long executionTime) {
    68         this.executionTime = executionTime;
    69     }
    70 
    71     public String getMethod() {
    72         return method;
    73     }
    74 
    75     public void setMethod(String method) {
    76         this.method = method;
    77     }
    78 }
    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获取操作者名称

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

    1.2.3获取访问IP

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

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

    通过getRemoteAddr()方法获取IP

    1 // 获取IP地址
    2 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()。

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

    1.2.6获取访问方法

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

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

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

     LogAop类的代码:

     1 package club.nipengfei.ssm.controller;
     2 
     3 import club.nipengfei.ssm.domain.SysLog;
     4 import club.nipengfei.ssm.service.ISysLogService;
     5 import org.aspectj.lang.JoinPoint;
     6 import org.aspectj.lang.annotation.After;
     7 import org.aspectj.lang.annotation.Aspect;
     8 import org.aspectj.lang.annotation.Before;
     9 import org.springframework.beans.factory.annotation.Autowired;
    10 import org.springframework.security.core.context.SecurityContext;
    11 import org.springframework.security.core.context.SecurityContextHolder;
    12 import org.springframework.security.core.userdetails.User;
    13 import org.springframework.stereotype.Component;
    14 import org.springframework.web.bind.annotation.RequestMapping;
    15 
    16 import javax.servlet.http.HttpServletRequest;
    17 import java.lang.reflect.Method;
    18 import java.util.Date;
    19 
    20 @Component
    21 @Aspect
    22 public class LogAop {
    23 
    24     @Autowired
    25     private HttpServletRequest request;
    26 
    27     @Autowired
    28     private ISysLogService sysLogService;
    29 
    30     private Date visitTime; // 开始时间
    31     private Class clazz;  // 访问的类
    32     private Method method; // 访问的方法
    33 
    34     // 前置通知 主要获取开始时间,执行的类哪一个,执行的哪一个方法
    35     @Before("execution(* club.nipengfei.ssm.controller.*.*(..))")
    36     public void doBefore(JoinPoint jp) throws NoSuchMethodException {
    37         visitTime = new Date();  // 当前时间就是开始访问的类
    38         clazz = jp.getTarget().getClass(); // 具体访问的类
    39         String methodName = jp.getSignature().getName();  // 获取访问方法名称
    40         Object[] args = jp.getArgs();  // 获取访问方法参数
    41 
    42         // 获取具体执行方法Method对象
    43         if (args==null || args.length==0){
    44             method =  clazz.getMethod(methodName);
    45         } else {
    46             Class[] classArgs = new Class[args.length];
    47             for (int i=0;i<args.length;i++){
    48                 classArgs[i] = args[i].getClass();
    49             }
    50             method = clazz.getMethod(methodName,classArgs);
    51         }
    52     }
    53 
    54     // 后置通知
    55     @After("execution(* club.nipengfei.ssm.controller.*.*(..))")
    56     public void doAfter(JoinPoint jp) throws Exception {
    57 
    58         // 获取访问时长
    59         long time = new Date().getTime()-visitTime.getTime();
    60 
    61         String url = "";
    62         // 获取url
    63         if (clazz != null && method !=null && clazz!=LogAop.class){
    64             // 获取类的@RequestMapping("/orders")
    65             RequestMapping clazzAnnotation =(RequestMapping) clazz.getAnnotation(RequestMapping.class);
    66             if (clazzAnnotation != null){
    67                 String[] classValue = clazzAnnotation.value();
    68                 // 获取方法上的@RequestMapping("xxx")
    69                 RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
    70                 if (methodAnnotation != null){
    71                     String[] methodValue = methodAnnotation.value();
    72                     url=classValue[0]+methodValue[0];
    73 
    74                     // 获取IP地址
    75                     String ip = request.getRemoteAddr();
    76 
    77                     // 获取当前操作的用户
    78                     SecurityContext context = SecurityContextHolder.getContext();
    79                     User user =(User) context.getAuthentication().getPrincipal();
    80                     String username = user.getUsername();
    81 
    82                     // 将日志相关信息封装到SysLog对象
    83                     SysLog sysLog = new SysLog();
    84                     sysLog.setExecutionTime(time);
    85                     sysLog.setIp(ip);
    86                     sysLog.setMethod("[类名] "+clazz.getName()+"[方法名] "+method.getName());
    87                     sysLog.setUrl(url);
    88                     sysLog.setUsername(username);
    89                     sysLog.setVisitTime(visitTime);
    90 
    91                     // 调用service完成操作
    92                     sysLogService.save(sysLog);
    93                 }
    94             }
    95 
    96         }
    97     }
    98 }

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

     1 package club.nipengfei.ssm.service.impl;
     2 
     3 import club.nipengfei.ssm.dao.ISysLogDao;
     4 import club.nipengfei.ssm.domain.SysLog;
     5 import club.nipengfei.ssm.service.ISysLogService;
     6 import org.springframework.beans.factory.annotation.Autowired;
     7 import org.springframework.stereotype.Service;
     8 import org.springframework.transaction.annotation.Transactional;
     9 
    10 import java.util.List;
    11 
    12 @Service
    13 @Transactional
    14 public class SysLogServiceImpl implements ISysLogService {
    15 
    16     @Autowired
    17     private ISysLogDao sysLogDao;
    18 
    19     @Override
    20     public void save(SysLog sysLog) throws Exception {
    21         sysLogDao.save(sysLog);
    22     }
    23 
    24 }

    1.4在dao包下新建ISysLogDao接口

     1 package club.nipengfei.ssm.dao;
     2 
     3 import club.nipengfei.ssm.domain.SysLog;
     4 import org.apache.ibatis.annotations.Insert;
     5 import org.apache.ibatis.annotations.Select;
     6 
     7 import java.util.List;
     8 
     9 public interface ISysLogDao {
    10 
    11     @Insert("insert into syslog(visitTime,username,ip,url,executionTime,method) values(#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})")
    12     public void save(SysLog sysLog) throws Exception;
    13 
    14 }

    1.5存在的问题

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

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

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

    流程分析图:

     

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

     1 package club.nipengfei.ssm.dao;
     2 
     3 import club.nipengfei.ssm.domain.SysLog;
     4 import org.apache.ibatis.annotations.Insert;
     5 import org.apache.ibatis.annotations.Select;
     6 
     7 import java.util.List;
     8 
     9 public interface ISysLogDao {
    10 
    11     @Insert("insert into syslog(visitTime,username,ip,url,executionTime,method) values(#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})")
    12     public void save(SysLog sysLog) throws Exception;
    13 
    14     @Select("select * from sysLog")
    15     List<SysLog> findAll() throws Exception;
    16 }

    2.2在SysLogServiceImpl类内调用上面方法

     1 package club.nipengfei.ssm.service.impl;
     2 
     3 import club.nipengfei.ssm.dao.ISysLogDao;
     4 import club.nipengfei.ssm.domain.SysLog;
     5 import club.nipengfei.ssm.service.ISysLogService;
     6 import org.springframework.beans.factory.annotation.Autowired;
     7 import org.springframework.stereotype.Service;
     8 import org.springframework.transaction.annotation.Transactional;
     9 
    10 import java.util.List;
    11 
    12 @Service
    13 @Transactional
    14 public class SysLogServiceImpl implements ISysLogService {
    15 
    16     @Autowired
    17     private ISysLogDao sysLogDao;
    18 
    19     @Override
    20     public void save(SysLog sysLog) throws Exception {
    21         sysLogDao.save(sysLog);
    22     }
    23 
    24     @Override
    25     public List<SysLog> findAll() throws Exception {
    26         return sysLogDao.findAll();
    27     }
    28 }

    2.3在controller包下新建一个SysLogController类

     1 package club.nipengfei.ssm.controller;
     2 
     3 import club.nipengfei.ssm.domain.SysLog;
     4 import club.nipengfei.ssm.service.ISysLogService;
     5 import org.springframework.beans.factory.annotation.Autowired;
     6 import org.springframework.stereotype.Controller;
     7 import org.springframework.web.bind.annotation.RequestMapping;
     8 import org.springframework.web.servlet.ModelAndView;
     9 
    10 import java.util.List;
    11 
    12 @Controller
    13 @RequestMapping("/sysLog")
    14 public class SysLogController {
    15 
    16     @Autowired
    17     private ISysLogService sysLogService;
    18 
    19     @RequestMapping("/findAll.do")
    20     public ModelAndView findAll() throws Exception {
    21         ModelAndView mv = new ModelAndView();
    22         List<SysLog> sysLogList = sysLogService.findAll();
    23         mv.addObject("sysLogs",sysLogList);
    24         mv.setViewName("syslog-list");
    25         return mv;
    26     }
    27 }
  • 相关阅读:
    递归的初步应用
    最大公约数与最小公倍数(低效)
    进制转换
    凸多边形的面积问题
    单词替换
    DNA排序
    字符串排序
    倒三角形
    韩信点兵
    oracle
  • 原文地址:https://www.cnblogs.com/qzwl/p/11792588.html
Copyright © 2011-2022 走看看