作者:高元_G·Marshal于 2018年04月13日 发布在分类 / 开发技术 / SpringCloud 下,并于 2018年04月13日 编辑
    基于服务发现的操作日志服务 foruo-sc-log

       425

       0


    基于服务发现的操作日志服务 foruo-sc-log

    客户端利用spring切面获取注解内容
    发送至消息服务器(rabbitmq)
    服务端监听消息服务器,并存储至数据库

    日志存储流程如下:

    1、业务端依赖引用log-client 
    2、业务端编写或修改切面内容,以获取日志注解内容(@ApiLogger(value = "操作内容")) 
    3、将日志内容格式化,并发送至消息中间件 
    4、日志服务端独立部署,实时监听消息中间件,消费消息后存入数据库。 
    5、由于整个架构是基于微服务,所以需要将日志服务端也接入注册中心,接受健康监测

    部分代码如下:

    sc-log-server

    服务端主要分为两个部分

    rabbitmq(获取日志)
    mysql(入库)

    [RabbitMQ]

    RabbitServerConfig.java (rabbitmq自定义配置)


    /**
     * rabbit配置
     * @author GaoYuan
     * @date 2018/4/9 下午3:55
     */
    @Configuration
    public class RabbitServerConfig {

        /** 队列名称 */
       
    public final static String queueName = "sc-log";

        @Bean
        Queue queue() {
            return new Queue(queueName, false);
        }

        /** 指定消息按什么规则,路由到哪个Queue,Message消息先要到达Exchange,在Server中承担着从Produce接收Message的责任 */
       
    @Bean
        TopicExchange exchange() {
            return new TopicExchange("sc-log-exchange");
        }

        /** 绑定queue与exchange */
       
    @Bean
        Binding binding(Queue queue, TopicExchange exchange) {
            return BindingBuilder.bind(queue).to(exchange).with(queueName);
        }

        @Bean
        SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
                                                 MessageListenerAdapter listenerAdapter) {
            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
            container.setQueueNames(queueName);
            container.setMessageListener(listenerAdapter);
            return container;
        }

        @Bean
        MessageListenerAdapter listenerAdapter(Receive receiver) {
            return new MessageListenerAdapter(receiver, "receiveMessage");
        }

    Receiver.java (消息接收方法)

    @Component 
    public class Receive {
        private CountDownLatch latch = new CountDownLatch(1);
        @Autowired
        ApiLogServerService apiLogService;
        /** 这里的方法在RabbitServerConfig里被调用 (见 listenerAdapter 方法)  */
        public void receiveMessage(String message) {
            System.out.println( message );
            ApiLog apiLog=  JSON.parseObject(message,ApiLog.class);
            apiLogService.saveLogger(apiLog);
            latch.countDown();
        }
    }

    [Mysql]

    入库部分不详细讲解,底部提供源码链接

    sc-log-client

    日志客户端主要提供

    自定义注解(通过此注解获取日志内容)
    RabbitMQ配置
    日志提交API

    ApiLogger.java (日志注解)

    package com.foruo.sc.log.client.annotation;
    import java.lang.annotation.*;
    /** 

    * 操作记录注解 

    * @author GaoYuan 

    * @date 2018/4/11 上午11:03 

    *
    @Target(ElementType.METHOD) 
    @Retention(RetentionPolicy.RUNTIME) 
    @Documented 
    public @interface ApiLogger { 
       /** 操作说明 */
       String value() default "";
       /** 参数 */
       String params() default "";
    }

    ApiLogClientService.java (日志发送)

     /** 

    * 日志服务层 

     * 保存日志或者存储至消息中间件 

     * @author GaoYuan 

     * @date 2018/4/9 下午3:48 */

     * 日志服务层
     * 保存日志或者存储至消息中间件
     * @author GaoYuan
     * @date 2018/4/9 下午3:48
     */ 

    @Service 

    public class ApiLogClientService {
         @Autowired 

         private AmqpTemplate rabbitTemplate; 

         public void log(ApiLog sysLog){
              rabbitTemplate.convertAndSend(RabbitClientConfig.queueName, JSON.toJSONString(sysLog));
         }
    }

    sc-log-example (业务层demo)

    引入客户端依赖
    <!--日志客户端(已包含amqp) @author gaoyuan--> 
    <dependency> 
    <groupId>com.foruo.module</groupId> 
    <artifactId>sc-log-client</artifactId> 
    <version>1.0</version> 
    </dependency> 
    编写自定义切面

    ApiLoggerAspect.java


    /**
     * api日志切面 

     * @author GaoYuan
     * @date 2018/4/9 下午3:44
     */ 

    @Aspect
    @Component 

    public class ApiLoggerAspect {
        @Autowired
        private ApiLogClientService loggerService;
        /** 定义切点 */
        @Pointcut("@annotation(com.foruo.sc.log.client.annotation.ApiLogger)")
        public void loggerPointCut() {
        }
        /** before - 顾名思义 */
        @Before("loggerPointCut()")
        public void saveSysLog(JoinPoint joinPoint) {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            ApiLog sysLog = new ApiLog();
            ApiLogger sysLogger = method.getAnnotation(ApiLogger.class);
            if(sysLogger != null){
                //注解上的描述             

                sysLog.setOperation(sysLogger.value());
            }
            //请求的方法名         

            String className = joinPoint.getTarget().getClass().getName();
            String methodName = signature.getName();
            sysLog.setMethod(className + "." + methodName + "()");
            //请求的参数         

            Object[] args = joinPoint.getArgs();
            String params="";
            for(Object o:args){
                params += JSON.toJSONString(o);
            }
            if(!StringUtils.isEmpty(params)) {
                sysLog.setParams(params);
            }
            //设置IP地址         

            sysLog.setIp(HttpUtils.getIpAddress());
            /** 在这里编写获取用户名 */
            String username = UserUtils.getCurrentPrinciple();
            if(!StringUtils.isEmpty(username)) {
                sysLog.setUsername(username);
            }
            sysLog.setCreateDate(new Date());
            //保存系统日志         

            loggerService.log(sysLog);
        }
    }

    webcontroller使用日志注解

    DemoController.java

    /**
    * 案例控制层
    * @author GaoYuan
    * @date 2018/4/9 下午3:43
    */ 
    @RestController 

    @RequestMapping("/demo")
    public class DemoController
                  @ApiLogger("执行某某操作") 
                  @PostMapping
                  @GetMapping
                  public void demo()
                         System.out.println("执行某某操作");
                  }
    }


    先运行服务端,再运行业务模块端,访问/demo,发现日志成功入库。

    期间发现使用 swagger 时也是要求写一些操作内容,其实也可以通过自定义切面获取 swagger 注解中填写的操作内容,这样就不需要单独写一个@ApiLogger了


    码云地址 : https://gitee.com/gmarshal/foruo-sc-log






    访问权限

    创建人 高元_G·Marshal
    文档编辑权限 创建者私有
    文档阅读权限 来自分类
    分类阅读权限 所有人
    分类编辑权限 所有人
    分类审核权限
    标签

    日志
    历史版本

    修改日期 修改人 备注
    2018-04-13 09:35:48[当前版本] 高元_G·Marshal CREAT
    附件

    PNG

    同类知识
    相关知识

    睿恒知识库-V3.2.0