zoukankan      html  css  js  c++  java
  • 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();
  • 相关阅读:
    盒子垂直水平居中
    Sahi (2) —— https/SSL配置(102 Tutorial)
    Sahi (1) —— 快速入门(101 Tutorial)
    组织分析(1)——介绍
    Java Servlet (1) —— Filter过滤请求与响应
    CAS (8) —— Mac下配置CAS到JBoss EAP 6.4(6.x)的Standalone模式(服务端)
    JBoss Wildfly (1) —— 7.2.0.Final编译
    CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服务端)
    CAS (6) —— Nginx代理模式下浏览器访问CAS服务器网络顺序图详解
    CAS (5) —— Nginx代理模式下浏览器访问CAS服务器配置详解
  • 原文地址:https://www.cnblogs.com/bozhengheng/p/12806107.html
Copyright © 2011-2022 走看看