AOP日志

在ssm框架中因为要记录使用者的访问信息,所以要使用日志系统;

首先定义一个类,用来保存访问的信息;

public class SysLog {
    private Integer id;
    private Date visitTime;//访问时间
    private String username;
    private String ip;
    private String url;
    private Long executionTime;//执行时长
    private String method;//访问的方法

然后定义一个切面方法。

@Component
@Aspect
public class LogAop {

使用@Component和@Aspect注解,因为这个类不是controller方法或者service方法,所以使用Component注解,Aspect是
@Aspect:作用是把当前类标识为一个切面供容器读取

定义两个方法

@Before("execution(* com.hengheng.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {





 @After("execution(* com.hengheng.controller.*.*(..))")
    public void doAfter(JoinPoint jp){

一个前置通知,一个后置通知,使用JoinPoint 获取

JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象. 
常用api:

方法名功能
Signature getSignature(); 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
Object[] getArgs(); 获取传入目标方法的参数对象
Object getTarget(); 获取被代理的对象
Object getThis(); 获取代理对象

首先在SysAop类中定义一些属性,用来接收访问信息,

private Date visitTime;//访问时间
    private Class clazz;//访问的类
    private Method method;//访问的方法

然后就可以开始获取自己需要的信息了

在前置方法中获取访问的时间,还有访问的类,和访问的方法

//前置通知  主要是获取开始时间 ,执行的是哪个类,执行的是哪个方法
    @Before("execution(* com.hengheng.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        visitTime = new Date();//访问的时间
        clazz = jp.getTarget().getClass();//jp.getTarget()获取被代理对象
        String methodName = jp.getSignature().getName();//获取访问的方法的名字.joinpoint.getSignature():(signature是信号,标识的意思):获取被增强的方法相关信息
        Object[] args = jp.getArgs();//获取访问方法的参数

        //获取具体的访问的方法
        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);//getMethod(String, Class<?>...)
        }


    }

在后置方法中可以获取总时长,访问的URL,访问的用户,访问的ip

 @After("execution(* com.hengheng.controller.*.*(..))")
    public void doAfter(JoinPoint jp){
        //访问的时长
        Long totalTime = new Date().getTime() - visitTime.getTime();

        String url = "";
        //clazz访问的类;method访问的方法;clazz != LogAop.class 访问的类不是LogAop
        if(clazz != null&&method != null&&clazz != LogAop.class){
            //获取类上的注解
            RequestMapping clazzAnnotation = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
            //获取注解中的值@RequestMapping("/findUserByIdAndAllRole.do")中的值
            String[] clazzUrl = clazzAnnotation.value();
            //获取方法上的注解
            RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
            String[] methodUrl = methodAnnotation.value();

            url = clazzUrl[0]+methodUrl[0];
        }

        //获取当前的访问用户,因我是用的是shiro所以在realm中曾经获取过用户,可以参考
        String username = (String) SecurityUtils.getSubject().getPrincipal();


        //获取访问的ip,要使用request对象,但是首先要在web.xml中配置request的过滤器RequestContextListener,这样在 本类中就可以注入一个 request的对象
        //@Autowired
        //    private HttpServletRequest request;
        //就可以使用request对象了
        String ip = request.getRemoteAddr();

        SysLog sysLog = new SysLog();
        sysLog.setExecutionTime(totalTime);
        sysLog.setIp(ip);
        sysLog.setMethod("[类名] "+clazz.getName()+"[方法名] "+method.getName());
        sysLog.setUrl(url);
        sysLog.setUsername(username);
        sysLog.setVisitTime(visitTime);
        System.out.println(sysLog);



    }

注意当需要使用request对象的时候要在web。xml中 配置request的listener监听器

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

这样就可以注入HttpServletRequest对象了,或者使用shiro获取也可以。

@Autowired
    private HttpServletRequest request;

//就可以使用request对象了
 String ip = request.getRemoteAddr();

使用shiro 获取用户名和ip(参考)

private String getUsername() {
        Object principal = SecurityUtils.getSubject().getPrincipal();
        return principal.toString();
    }

    private String getIp(){
        Subject subject = SecurityUtils.getSubject();
        String host = subject.getSession().getHost();
        return host;
    }

注意,获取用户时,因为使用的是shiro框架,所以要使用

//获取当前的访问用户,因我是用的是shiro所以在realm中曾经获取过用户,可以参考
        String username = (String) SecurityUtils.getSubject().getPrincipal();
SecurityUtils.getSubject(),获取shiro的Subject主体
SecurityUtils.getSubject().getPrincipal()这个方法获取的是在自定义的Realm中
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,credentialsSalt, getName());

标红的位置传的是什么,SecurityUtils.getSubject().getPrincipal()获取的就是什么,可以是User对象,或者用户名。

//获取当前的访问用户,因我是用的是shiro所以在realm中曾经获取过用户,可以参考
String username = (String) SecurityUtils.getSubject().getPrincipal();
原文地址:https://www.cnblogs.com/bozhengheng/p/12806107.html