• 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();
  • 相关阅读:
    oracle一次插入多条数据
    SQL在in中传入参数类型问题
    斗鱼刷弹幕定时
    在setTimeout 200ms后执行函数发生错误
    Java去除字符串中的空格
    同步与异步
    HTTP请求中GET和POST的区别
    SQL优化
    什么是死锁以及避免死锁
    常用快捷键
  • 原文地址:https://www.cnblogs.com/bozhengheng/p/12806107.html
Copyright © 2020-2023  润新知