旅游后台项目——SSMAOP日志

该博客介绍了如何使用Spring AOP实现一个日志系统。通过在切面类中定义`@Before`和`@After`注解,分别在方法执行前后记录日志信息,包括访问时间、执行类、方法、参数、执行时间、IP地址和用户名。日志信息最终存储在SysLog表中,由SysLogService和SysLogMapper处理。
摘要由CSDN通过智能技术生成

SSMAOP日志

数据库与表结构

日志表信息描述sysLog

在这里插入图片描述

基于AOP日志处理

创建切面类处理日志

package com.sibd.travel.controller;

import com.sibd.travel.controller.SyslogController;
import com.sibd.travel.pojo.SysLog;
import com.sibd.travel.pojo.Users;
import com.sibd.travel.service.SyslogService;
import com.sibd.travel.util.UuidUtil;
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 SyslogService sysLogService;

    @Autowired
    private HttpServletRequest request;

    private Date startTime; // 访问时间
    private Class executionClass;// 访问的类
    private Method executionMethod; // 访问的方法

    @Before("execution(* com.sibd.travel.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException, SecurityException {
        // 访问时间
        startTime=new Date();

        // 获取访问的类字节码文件
        executionClass = jp.getTarget().getClass();
        // 获取访问的方法
        String methodName = jp.getSignature().getName();// 获取访问的方法的名称
        Object[] args = jp.getArgs();// 获取访问的方法的参数
        if (args == null || args.length == 0) {// 无参数
            executionMethod = executionClass.getMethod(methodName); // 只能获取无参数方法
        } else {
            // 有参数,就将args中所有元素遍历,获取对应的Class,装入到一个Class[]
            Class[] classArgs = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                classArgs[i] = args[i].getClass();
            }
            executionMethod = executionClass.getMethod(methodName, classArgs);// 获取有参数方法
        }


    }

    // 主要获取日志中其它信息,时长、ip、url...
    @After("execution(* com.sibd.travel.controller.*.*(..))")
    public void doAfter(JoinPoint jp) throws Exception {
        // 获取类上的@RequestMapping对象
        if (executionClass != SyslogController.class) {
            RequestMapping classAnnotation = (RequestMapping) executionClass.getAnnotation(RequestMapping.class);
            if (classAnnotation != null) {
                // 获取方法上的@RequestMapping对象
                RequestMapping methodAnnotation = executionMethod.getAnnotation(RequestMapping.class);
                if (methodAnnotation != null) {
                    String url = ""; // 它的值应该是类上的@RequestMapping的value+方法上的@RequestMapping的value
                    url = classAnnotation.value()[0] + methodAnnotation.value()[0];

                    SysLog sysLog = new SysLog();
                    sysLog.setId(UuidUtil.getId());

                    // 获取访问时长
                    Long executionTime = new Date().getTime() - startTime.getTime();
                    // 将sysLog对象属性封装
                    sysLog.setExecutionTime(executionTime);
                    // 获取ip
                    String ip = request.getRemoteAddr();
                    sysLog.setIp(ip);
                    sysLog.setMethod("[类名]" + executionClass.getName() + "[方法名]" + executionMethod.getName());
                    // 可以通过securityContext获取,也可以从request.getSession中获取
                    SecurityContext context = SecurityContextHolder.getContext();
                    //request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
                    String username = ((User)
                            (context.getAuthentication().getPrincipal())).getUsername();
                    sysLog.setUsername(username);

                    sysLog.setUrl(url);
                    sysLog.setVisitTime(startTime);
                    // 调用Service,调用dao将sysLog insert数据库
                    sysLogService.save(sysLog);
                }

            }
        }
    }
}

在切面类中我们需要获取登录用户的username,还需要获取ip地址,我们怎么处理?

  • username获取

    SecurityContextHolder获取

  • ip地址获取

    ip地址的获取我们可以通过request.getRemoteAddr()方法获取到。

    在Spring中可以通过RequestContextListener来获取request或session对象。

@Aspect:作用是把当前类标识为一个切面供容器读取
 
@Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: final增强,不管是抛出异常或者正常退出都会执行

SysLogController

package com.sibd.travel.controller;

import com.sibd.travel.pojo.SysLog;
import com.sibd.travel.service.SyslogService;
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 SyslogService syslogService;
    @RequestMapping("findAll.do")
    public ModelAndView findAll(){
        ModelAndView mv = new ModelAndView();
        List<SysLog> sysLogs = syslogService.findAll();
        mv.setViewName("syslog-list");
        mv.addObject("sysLogs",sysLogs);
        return mv;
    }
}

Service

package com.sibd.travel.service.impl;

import com.sibd.travel.mapper.SysLogMapper;
import com.sibd.travel.pojo.SysLog;
import com.sibd.travel.service.SyslogService;
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 SyslogService {
    @Autowired
    private SysLogMapper sysLogMapper;
    @Override
    public List<SysLog> findAll() {
        return sysLogMapper.findAll();
    }

    @Override
    public void save(SysLog sysLog) {
        sysLogMapper.save(sysLog);
    }
}

Dao

package com.sibd.travel.mapper;

import com.sibd.travel.pojo.SysLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface SysLogMapper {

    @Select("select * from syslog")
    List<SysLog> findAll();

    @Insert("insert into syslog(id,visitTime,username,ip,url,executionTime,method) values(#{id},#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})")
    void save(SysLog sysLog);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值