SpringBoot-Actuator健康检查-打印日志改造应用策略模式+简单工厂

news2025/1/24 11:29:00

类图

image-20230610223626690

包结构

image-20230610222129347

代码实例

  1. pom

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.22.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>xxjob-actouor</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>xxjob-actouor</name>
        <description>xxjob-actouor</description>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
                <version>1.5.22.RELEASE</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <repositories>
            <repository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
            <repository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/snapshot</url>
                <releases>
                    <enabled>false</enabled>
                </releases>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </pluginRepository>
            <pluginRepository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/snapshot</url>
                <releases>
                    <enabled>false</enabled>
                </releases>
            </pluginRepository>
        </pluginRepositories>
    
    </project>
    
    
  2. yml

    server.port=9000
    # 控制是否打印日志  false 不打印日志 true 打印日志
    health.flag=true
    # 日志策类配置  default 默认日志类  caChe 添加缓存的日志类
    health.strategy=default
    # 健康检查结果缓存超时时间,只有 health.strategy=caChe 这项配置才有意义
    health.timeOut=10
    
    
  3. code

    1. Strategy

      HealthLogsSuper

      package com.example.xxjobactouor.Strategy;
      
      import org.aspectj.lang.ProceedingJoinPoint;
      
      /**
       * @Description 健康检查日志策略父类
       * @ClassName HealthSuper
       * @Author 康世行
       * @Date 21:23 2023/6/7
       * @Version 1.0
       **/
      public abstract class HealthLogsSuper {
      
          //获取健康检查结果
          public abstract Object getHealthLogs( ProceedingJoinPoint joinPoint );
      }
      
      

      DefaultHealthLogs

      package com.example.xxjobactouor.Strategy;
      
      import com.example.xxjobactouor.Strategy.common.HealthCommonPrint;
      import lombok.extern.slf4j.Slf4j;
      import org.aspectj.lang.ProceedingJoinPoint;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      /**
       * @Description 默认日志策略-控制日志是否打印
       * @ClassName DefaultHealth
       * @Author 康世行
       * @Date 21:34 2023/6/7
       * @Version 1.0
       **/
      @Service
      @Slf4j
      public  class DefaultHealthLogs extends HealthLogsSuper {
      
          @Autowired
          private HealthCommonPrint healthPrintLogs;
      
          @Override
          public Object getHealthLogs(ProceedingJoinPoint joinPoint) {
              Object proceed=null;
              //目标类
              Object target = joinPoint.getTarget();
              //接口请求开始时间
              long start=System.currentTimeMillis();
              try {
                  //进入类之前打印日志
                  healthPrintLogs.printPreHealthLogs(target);
                  proceed=joinPoint.proceed();
                  //进入类之后的日志
                  healthPrintLogs.printAftHealthLogs(target,start);
              } catch (Throwable e) {
                  throw new RuntimeException(e);
              }
              return proceed;
          }
      }
      
      

      CacheHealthLogs

      package com.example.xxjobactouor.Strategy;
      
      import com.example.xxjobactouor.Strategy.common.CacheHealth;
      import com.example.xxjobactouor.Strategy.common.HealthCommonPrint;
      import lombok.extern.slf4j.Slf4j;
      import org.aspectj.lang.ProceedingJoinPoint;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.stereotype.Service;
      
      import java.util.concurrent.TimeUnit;
      
      /**
       * @Description 对结果进行缓存的日志策略
       * @ClassName LogsAndCacheHealth
       * @Author 康世行
       * @Date 21:38 2023/6/7
       * @Version 1.0
       **/
      @Service
      @Slf4j
      public class CacheHealthLogs extends HealthLogsSuper {
      
          @Autowired
          private CacheHealth cacheHealth;
          @Value("${health.timeOut:5}")
          private long timeOut;
      
          //缓存key
          private final static String cacheKey="healthInfo";
          //打印日志
          @Autowired
          private HealthCommonPrint healthPrintLogs;
          @Override
          public Object getHealthLogs(ProceedingJoinPoint joinPoint) {
              Object proceed=null;
              //目标类
              Object target = joinPoint.getTarget();
              //接口请求开始时间
              long start=System.currentTimeMillis();
              try {
                  //进入类之前打印日志
                  healthPrintLogs.printPreHealthLogs(target);
                  //从缓存获取健康检查信息
                  proceed= cacheHealth.get(cacheKey);
                  if (proceed==null){
                      //再次获取健康检查的信息并保存到缓存,用于下次使用提高接口查询效率
                      proceed=joinPoint.proceed();
                      cacheHealth.put(cacheKey,proceed,timeOut, TimeUnit.SECONDS);
                  }
                  //进入类之后的日志
                  healthPrintLogs.printAftHealthLogs(target,start);
              } catch (Throwable e) {
                  throw new RuntimeException(e);
              }
      
              return proceed;
          }
      }
      
      

      HealthLogsContext

      package com.example.xxjobactouor.Strategy;
      
      import org.aspectj.lang.ProceedingJoinPoint;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      /**
       * @Description
       * 健康检查日志策略上下文类-用于维护 具体使用的那个策略对象 结合简单工厂使用
       * @ClassName HealthLogsContext
       * @Author 康世行
       * @Date 21:46 2023/6/7
       * @Version 1.0
       **/
      @Service
      public class HealthLogsContext {
      
          HealthLogsSuper logsSuper;
      
          @Autowired
          private DefaultHealthLogs defaultHealthLogs;
      
          @Autowired
          private CacheHealthLogs cacheHealthlogs;
      
          //设置具体策略
          public void setStrategy(String strategy){
              switch (strategy){
                  case "default":
                      logsSuper=defaultHealthLogs;
                      break;
                  case "caChe":
                      logsSuper=cacheHealthlogs;
                      break;
              }
          }
      
          //执行具体策略
          public Object getResult(ProceedingJoinPoint joinPoint ){
              Object healthLogs = logsSuper.getHealthLogs(joinPoint);
              return healthLogs;
          }
      }
      
      

      HealthLogs

      package com.example.xxjobactouor;
      
      import com.example.xxjobactouor.Strategy.HealthLogsContext;
      import lombok.extern.slf4j.Slf4j;
      import org.aspectj.lang.JoinPoint;
      import org.aspectj.lang.ProceedingJoinPoint;
      import org.aspectj.lang.annotation.Around;
      import org.aspectj.lang.annotation.Aspect;
      import org.aspectj.lang.annotation.Pointcut;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.context.annotation.EnableAspectJAutoProxy;
      import org.springframework.stereotype.Component;
      
      import java.util.concurrent.TimeUnit;
      
      /**
       * @Description 记录监控检查-日志
       * @ClassName HealthLogs
       * @Author 康世行
       * @Date 20:15 2023/6/7
       * @Version 1.0
       **/
      @Aspect
      @Component
      @Slf4j
      public class HealthLogs {
      
      
          @Pointcut("execution(public * com.example.xxjobactouor.Healthimpl.health())")
          public void logs(){};
      
          @Autowired
          private HealthLogsContext context;
      
      
          @Value("${health.strategy:default}")
          private String strategy;
      
          @Around("logs()")
          public Object log(ProceedingJoinPoint joinPoint){
              Object proceed=null;
              //设置使用那个日志策略
              context.setStrategy(strategy);
              // 获取健康检查返回值
              proceed= context.getResult(joinPoint);
              return proceed;
          }
      }
      
      
    2. common

    CacheHealth

    package com.example.xxjobactouor.Strategy.common;
    
    import org.springframework.stereotype.Component;
    
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @Description TODO
     * @ClassName CacheHealth
     * @Author 康世行
     * @Date 20:50 2023/6/7
     * @Version 1.0
     **/
    @Component
    public class CacheHealth {
    
        private  final Map<String,Object> cacheHealth=new ConcurrentHashMap<>();
    
        public void put(String key, Object value, long ttl, TimeUnit timeUnit) {
            cacheHealth.put(key, value);
            Executors.newSingleThreadScheduledExecutor().schedule(() -> cacheHealth.remove(key,value), ttl, timeUnit);
        }
    
        public Object get(String key) {
            return cacheHealth.get(key);
        }
    }
    
    

    HealthCommonPrint

    package com.example.xxjobactouor.Strategy.common;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    
    /**
     * @Description 日志打印类-所有日志策略公共类
     * @ClassName HealthPrintLogs
     * @Author 康世行
     * @Date 22:30 2023/6/7
     * @Version 1.0
     **/
    @Service
    @Slf4j
    public class HealthCommonPrint {
        @Value("${health.flag:false}")
        private boolean flag;
    
        //打印执行前健康检查日志
        public void printPreHealthLogs(Object joinPoint) {
            if (flag){
                log.info("进入"+joinPoint.getClass().getName()+"类之前");
            }
        }
    
    
    
        //打印执行后健康检查日志
        public void printAftHealthLogs(Object joinPoint,long start) {
    
            if (flag){
                log.info("进入"+joinPoint.getClass().getName()+"类之后");
            }
    
            if (flag){
                long end=System.currentTimeMillis()-start;
                log.info("耗时"+end);
            }
    
        }
    }
    
    

功能演示

image-20230610224814443

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/632324.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL 数据库】10、MySQL 的触发器

MySQL 的触发器 零、存储函数一、触发器二、触发器的使用和语法 零、存储函数 存储函数是有返回值的存储过程存储函数的参数只能是 IN 类型 characteristic 说明&#xff1a; ① DETERMINISTIC&#xff1a;相同的输入参数总是产生相同的结果 ② NO SQL &#xff1a;不包含 SQL…

【PCB专题】案例:绕等长怎么直接以颜色区分看出是否绕好

PCB上对于时序的处理,在板卡上实际我们是通过绕等长的手段。做为一个合格的Layout工程师,等长的处理是不可或缺的技能。 一般来说,在绕等长的时候我们可以使用Delay Tune命令来改变走线的长度,然后通过规则管理器中分析看看哪根线长哪根线短。 但是在实际工作中,很可能绕着…

【AI绘画】为小白准备的最简单本地部署安装使用教程——webui启动器

什么是AI绘画&#xff1f; ai绘画&#xff0c;也叫“ai作画”、“人工智能绘画”&#xff0c;即通过 AI 生成技术得到画作或图片。ai作画由来已久&#xff0c;有许多创作ai绘画作品的方式&#xff0c;包括基于规则的图像生成算法、深度学习算法。最近火爆全网的是通过文本描述…

悟道3.0全面开源!LeCun VS Max 智源大会最新演讲

夕小瑶科技说 原创 作者 | 小戏 2023 年智源大会如期召开&#xff01; 这场汇集了 Geoffery Hinton、Yann LeCun、姚期智、Joseph Sifakis、Sam Altman、Russell 等一众几乎是 AI 领域学界业界“半壁江山”的大佬们的学术盛会&#xff0c;聚焦 AI 领域的前沿问题&#xff0c…

【EasyX】实时时钟

目录 实时时钟1. 绘制静态秒针2. 秒针的转动3. 根据实际时间转动4. 添加时针和分针5. 添加表盘刻度 实时时钟 本博客介绍利用EasyX实现一个实时钟表的小程序&#xff0c;同时学习时间函数的使用。 本文源码可从github获取 1. 绘制静态秒针 第一步定义钟表的中心坐标center&a…

使用Python绘制粽子消消乐,素描图(优化版,正常/漫画/写实风格),词云图,字符画图及提取轮廓

使用Python绘制粽子消消乐&#xff0c;素描图&#xff08;优化版&#xff0c;正常/漫画/写实风格&#xff09;&#xff0c;词云图&#xff0c;字符画图及提取轮廓 1. 效果图2. 源码2.1 素描图源码2.2 [优化版&#xff1a;制作不同风格的素描图&#xff08;正常&#xff0c;漫画…

String的理解

1.号 1. 1 号连接符的实现原理 StringBuilder&#xff08;或者StringBuffer&#xff09;的apend方法拼接&#xff0c;然后toString方法返回新的字符串 1.2 号的特殊情况 1.2.1 当""两端均为编译期确定的字符串常量时&#xff0c;编译器会进行相应的优化&#xf…

springboot项目外卖管理 day05-新增与删除套餐

文章目录 一、新增菜品1.1、需求分析1.2、数据模型setmealsetmeal_dish 1.3、代码开发-梳理交互过程1.3.1、下拉框展示1.3.2、菜品窗口展示1.3.3、新增套餐 2、套餐分页查询 一、新增菜品 1.1、需求分析 套餐就是菜品的集合。 后台系统中可以管理套餐信息&#xff0c;通过新…

solr快速上手:常用查询语法(八)

0. 引言 solr作为搜索引擎&#xff0c;就像我们使用mysql一样&#xff0c;在日常业务中&#xff0c;更多接触的则是各类操作语法&#xff0c;所以今天&#xff0c;我们再来学习solr的常用查询语法&#xff0c;为大家在工作中最基本的solr查询打下基础。 solr快速上手&#xff…

ia write 自定义 导出模板

https://github.com/yangyang5214/github-plus.iatemplate 使用了点个 star 吧&#xff09; 在原有的 GitHub 模板基础上&#xff0c;增加了 封面页面和页脚。 封面页面 展示文章标题 作者 时间。高端大气&#xff5e; 增加页脚&#xff0c;显示 page/pageCount 加载 通过…

做策划有这些特质才能成为行业大咖,看看你符合几个

这个问题确实很重要&#xff0c;策划也不是职业也不是适合所有人的&#xff01; 首先&#xff0c;从性格方面来说吧。 有些人就是适合说话&#xff0c;有些人就是适合埋头苦干&#xff0c;还有一些人有强大的学习能力和逻辑思维。所以就是适合做创意类、创作类、策划类、统筹…

百度翻译API使用教程(前端+后端)

1.资格获取 首先我们需要登录百度翻译开放平台&#xff0c;获取开发者资格&#xff1a; 访问 百度翻译开放平台 然后进行注册&#xff08;如果有百度账号的话可以直接登录&#xff09; 注册成功后点击“产品服务”&#xff1a; 跳转到通用文本API界面&#xff1a; 在页面底…

怎么自学电脑编程

首要之首&#xff1a;不要急于选择一种语言 新手们有一个常见的错误就是犹豫于判断哪种编程语言是做好的、最该先学的。 我们有很多的选择&#xff0c;但你不能说那种语言最好。 我们应该理解&#xff1a;说到底&#xff0c;什么语言并不重要。 重要的是理解数据结构、控制逻辑…

C语言——修改控制台背景色和字体颜色

C语言——修改控制台背景色和字体颜色 方法一&#xff1a;system(“color NUM1NUM2”) system("color NUM1NUM2");可以用库函数system(“color NUM1NUM2”)实现 需要头文件 <stdlib.h> NUM1,NUM2均为16进制数 NUM1控制控制台背景色&#xff0c;NUM2控制前…

大数据驱动的实时文本情感分析系统:构建高效准确的情感洞察【上进小菜猪大数据】

上进小菜猪&#xff0c;沈工大软件工程专业&#xff0c;爱好敲代码&#xff0c;持续输出干货。 随着互联网的快速发展和大数据技术的不断成熟&#xff0c;用户推荐系统在各个应用领域变得越来越重要。本文将介绍如何利用大数据技术构建一个实时用户推荐系统。我们将通过结合Ap…

基本算法温习:打印金字塔

最终结果图如下&#xff1a; 想达到这个结果&#xff0c;通常的做法是通过拼结两个三角型达到&#xff0c;但是实际上还有最右边的第三个三角型没有处理&#xff0c;这个拼结的方法总让人看起来有一点不完美的感觉&#xff0c;于是我自创了一个思路&#xff0c;一气合成&#x…

【数据结构】七大排序算法(超详细)

欢迎来到南方有乔木的博客&#xff01;&#xff01;&#xff01; 博主主页&#xff1a;点击点击&#xff01;戳一戳&#xff01;&#xff01; 博主名:南方有乔木 博主简介&#xff1a; 一名在校大学生&#xff0c;正在努力学习Java语言编程。穷且意坚&#xff0c;不坠青云之志&…

uniapp和springboot微信小程序开发实战:后端架构搭建之封装WEB接口返回对象

文章目录 前言本节所需依赖工具类实现测试代码运行结果总结前言 作为开发者,开发的接口请求返回数据类型有很多种。比如返回字符串,返回对象,返回集合数组等情况,每个人开发者都有自己喜欢的方式或风格。所以在一个项目开发的时候架构师会定义好返回对象,给前端返回数据格…

redis基本数据类型001String

String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象 一个Redis中字符串value最多可以是512M 应用场景 需要存储常规数据的场景 缓存 session、token、图片地址、序列化后的对象(相比较于 Hash 存储更节省内存)。 需要计数的场景 举…

Singer混沌映射与莱维飞行改进灰狼算法

目录 一、灰狼算法 二、改进策略 2.1 混沌初始化种群 2.2 非线性收敛因子 三、引入莱维飞行 四、运行结果 从改进运行结果来看&#xff0c;效果非常好&#xff0c;在、、等极易陷入局部最优的测试函数上都取到了最优值&#xff0c;收敛速度也得到极大提升。 一、灰狼算法…