7 常用开发技术
约 6016 字大约 20 分钟
2025-06-18
导入坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
导入坐标后还需要在启动类上面添加EnableCaching注解表示这个程序启动要使用缓存技术 接着要在使用缓存技术的函数上加上Cacheable注解
@Cacheable(value="cacheSpace",key="#id")
public Book getById(Integer id){
return bookDao.selectById(id);
}
value表示存储的缓存命名空间,如果没有则创建,key表示存入缓存的键,#id表示将参数id作为键
SpringBoot提供的缓存技术除了提供默认的缓存方案,,还可以对其他缓存技术进行整合,统一接口,方便缓存技术的开发与管理
更改缓存技术
默认使用的simple可以进行更改
ehcache
导入坐标
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
更改配置
spring:
cache:
type: ehcache
ehcache:
config: ehcache
在需要使用缓存的函数上加上注解
@CachePut(value ="smsCode",key="#tele")
配置文件
ehcache要使用自己的配置文件ehcache.xml
<?xml version="1.o"encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updatecheck="false">
<!-- 缓存存放的位置 -->
<diskStore path="D:\ehcache"/>
<!-- 默认缓存策略 -->
<!--external:是否永久存在,设置为true则不会被清除,此时与timeout冲突,通常设置为faLse -->
<!--diskPersistent:是否启用磁盘持久化-->
<!--maxELementsInMemory:最大缓存数量-->
<!--overfLowToDisk:超过最大缓存数量是否持久化到磁盘-->
<!--timeToIdLeSeconds:最大不活动间隔,设置过长缓存容易溢出,设置过短无效果,可用于记录时效性数据,例如验证码-->
<!--timeToLiveSeconds:最大存活时间-->
<!--memoryStoreEvictionPoLicy:缓存清除策略-->
<defaultCache
eternal="false"
diskPersistent="false"
maxElementsInMemory="1000"
overflowToDisk="false"
timeToIdleSeconds="60"
timeToLiveSeconds="60"
memoryStoreEvictionPolicy="LRU"/>
<!-- 其他缓存配置 -->
<cache
name="smsCode"
eternal="false"
diskPersistent="false"
maxElementsInMemory="1000"
overflowToDisk="false"
timeToIdleSeconds="60"
timeToLiveSeconds="60"
memoryStoreEvictionPolicy="LRU"/>
除了默认缓存配置还有其他缓存配置需要指定出name属性表示缓存的命名空间
@CachePut(value ="smsCode",key="#tele")
中value指定的命名空间就是存储到配置的命名空间中
redis
导入坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置文件
spring
cache:
type: redis
redis:
host: localhost
port: 6379
use-key-prefix: false //是否使用前缀,如果使用,在CachePut注解中指定的value就是作为前缀值存入redis中,如果不指定则直接将值存入redis中
cache-null-values: false //是否允许空值,如果不允许则值为空时不存入
key-prefix: aa //键的前缀,需要use-key-prefix使用前缀开启,在前缀的键上拼接该字符串
time-to-live: 10s //超时时间
jetcache
以上缓存只能只使用本地缓存或者只使用远程缓存
jetCache对SpringCache进行了封装,在原有功能基础上实现了多级缓存、缓存统计、自动刷新、异步调用、数据报表等功能
jetCache设定了本地缓存与远程缓存的多级缓存解决方案 本地缓存(local)
- LinkedHashMap
- Caffeine 远程缓存(remote)
- Redis
- Tair
导入坐标
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.6.2</version>
</dependency>
远程方案
配置文件
jetcache:
remote: //使用本地还是远程,如果是远程就使用local
default: //默认空间,如果不指定缓存的命名空间默认使用该空间
type: redis
host: localhost
port: 6379
poolConfig:
maxTotal: 50 //最大连接数,必须指定
在能够被读取的配置类(或引导类)中加上注解@EnableCreateCacheAnnotation
在要使用缓存的类中添加操作对象 area表示命名空间,不指定默认使用default name表示缓存空间,expire过期时间,timeUnit时间单位默认是秒 cacheType表示使用的缓存方案,可以是远程或本地也可以都用
@CreateCache(area="sms",name="jetCache",expire =3600,timeUnit=TimeUnit.SECONDS,catcheType=CacheType.LOCAL)
private Cache<String,String> jetCache;
@Override
public String sendCodeToSMS(String tele){
String code = codeutils.generator(tele);
jetCache.put(tele,code); //指定存储的键值
return code;
}
@override
public boolean checkCode(SMSCode smsCode){
String code=jetCache.get(smsCode.getTele());
return smsCode.getCode().equals(code);
}
本地方案
远程方案和本地方案可以共存 keyConvertor用于转换键,通常键是使用字符串存储的,但也可以存储对象类型,如果是对象类型在比对的时候就会更加复杂,一般是将对象类型转换为字符串存储为key jetcache默认携带有fastjson,可以使用fastjson将对象类型转换为json字符串 valueEncode和valueDecode表示值编解码的对象是什么对象,由于使用的是java故为java对象
jetcache:
local:
default:
type: linkedhashmap
keyConvertor:fastjson
valueEncode: java
valueDecode: java
接着在需要缓存的java对象中还需要实现Serializable接口才能真正使用对象序列化,有默认的方法,不需要给出实现
@Data
public class Book implements Serializable{
private Integer id;
private String type;
private String name;
private String description;
}
方法缓存
要在配置类(启动类)上面加上enableMethodCache注解和EnableCreateCacheAnnotation注解搭配使用 要用basePackages指定出要作用的包名,可以以数组的形式指定多个
@EnableMethodCache(basePackages="com.itheima")
接着在指定的包中的方法上加上Cached注解并指定参数即可使用
缓存更新
如果一条数据进入缓存后又在磁盘中更改(或删除)了这个数据那么缓存中的数据就变成了脏数据,可以在更新操作中设置当调用该更新方法时就去缓存中查看是否有记录该数据,如果有就同步更新缓存中的数据
//更新
@override
@CacheUpdate(name="book_", key="#book.id", value="#book")
public boolean update(Book book){
return bookDao.updateById(book)>0;
}
//删除
@Override
@CacheInvalidate(name="book_",key ="#id")
public boolean delete(Integer id){
return bookDao.deleteById(id)>0;
}
如果有多个系统都可以更改数据库中的数据,此时有一个系统更改了这个数据,自己的缓存也更新 了,但其他的系统却不知道数据库更新了.这种情况可以使用缓存刷新来每隔一段时间查询一次以此更新数据
@CacheRefresh(refres=10)
该注解一般加在查询的方法上,这样就设定每隔一段时间查询数据保持数据更新
缓存统计
jetcache提供了缓存统计的功能,可以查看缓存效率 每隔指定的分钟数就在控制台中输出操作情况
jetcache:
statIntervalMinutes: 1
j2cache
导入坐标
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-core</artifactId>
<version>2.8.4-release</version>
</dependency>
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-spring-boot2-starter</artifactId>
<version>2.8.0-release</version>
</dependency>
配置文件 在spring的配置文件中只有一个配置选项指定配置文件路径 需要额外添加专门的配置文件
j2cache:
config-location: j2cache.properties
#1级缓存
j2cache.L1.provider_class = ehcache # 一级缓存供应商
ehcache.configXml =ehcache.xml # ehcache的配置文件
# 设置是否启用二级缓存
j2cache.l2-cache-open=false
#2级缓存
j2cache.L2.provider_class =net.oschina.j2cache.cache.support.redis.SpringRedisProvider # 二级缓存供应商为redis,redis要去springboot中找到服务的类的全类名
j2cache.L2.config_section = redis1 # 配置属性的前缀(在当前配置文件中)只要前缀匹配都是redis的配置属性
redis1.hosts =1ocalhost:6379 # 配置redis的地址与端口
#1级缓存中的数据如何到达二级缓存
j2cache.broadcast=net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy # 使用redis的订阅与发布机制
接着就可以在类中使用了,使用时需要创建一个CacheChannel类自动注入,然后使用其中的set和get方法
@Service
public class SMSCodeServiceImpl implements SMSCodeService{
@Autowired
private CodeUtils codeUtils;
@Autowired
private CacheChannel cacheChannel;
@Override
public String sendCodeToSMS(String tele){
String code = codeUtils.generator(tele);
cachechannel.set("sms",tele,code);
return code;
}
@Override
public boolean checkCode(SMSCode smsCode){
String code =cacheChanne.get("sms",smsCode.getTele()).asString();
return smsCode.getCode().equals(code);
}
}
定时任务
java中有自动任务的官方库,使用时需要重写run函数,和多线程一样,本质就是当到达指定时间时开启一个线程执行定时任务
Quartz
相关概念
- 工作(Job):用于定义具体执行的工作
- 工作明细(JobDetail):用于描述定时工作相关的信息
- 触发器(Trigger):用于描述触发工作的规则,通常使用cron表达式定义调度规则
- 调度器(Scheduler):描述了工作明细与触发器的对应关系
触发器绑定工作明细,工作明细指定工作
- 导入坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
<scope>test</scope>
</dependency>
- 指定工作 在使用时自定义的定时任务需要继承QuartzJobBean抽象类,并重写其中的executeInternal函数,这个函数就类似于run函数,定时任务就在其中执行 它有一个参数JobExecutionContext表示任务的上下文对象,可以获取许多信息
public classMyQuartzextends QuartzJobBean{
@Override
protected void executeInternal (JobExecutionContexttcontext) throws JobExecutionException {
System.out.println("quartz task run...");
}
}
- 工作配置 需要添加一个工作的配置类 使用JobBuilder构造器创建新的工作,将自己定义好的工作传入(工作种类) storeDurably表示当工作没有执行时是否要持久化下来下次再用
cronSchedule中需要指定时间表达式用来指明工作周期 绑定器中的forJob用来绑定自定义工作类中的什么工作 withSchedule绑定执行周期
@Configuration
public class QuartzConfig{
@Bean
public JobDetail printJobDetail(){
//绑定具体的工作
return JobBuilder.newJob(MyQuartz.class).storeDurably().build();
}
@Bean
public Trigger printJobTrigger(){
//绑定对应的工作明细
ScheduleBuilder schedBuilder=CronScheduleBuilder.cronSchedule("时间表达式")
return TriggerBuilder.newTrigger().forJob(printJobDetail().withSchedule(schedBuilder).build();
}
}
spring task
quartz太过繁琐,spring自己提供了任务框架
配置类 需要在配置类(或启动类)上添加EnableScheduling注解表示开启定时任务功能
创建工作类 创建的工作类需要添加@Component注解被ioc容器管控 在需要定时执行的任务上添加Scheduled注解,cron属性指定时间表达式
@Component
public class MyBean {
@Scheduled(cron="时间表达式")
public void print(){
System.out.println("spring task run...");
}
}
本质也是开启一个新线程执行定时任务,因此可以在任务函数中使用线程相关函数
- 定时任务相关配置
spring:
task:
scheduling:
#任务调度线程池大小默认1
pool:
size:1
#调度线程名称前缀默认scheduLing-
thread-name-prefix: ssm_
shutdown:
#线程池关闭时等待所有任务完成
await-termination: false
#调度线程关闭前最大等待时间,确保最后一定关闭
await-termination-period: 10s
邮件
- SMTP(Simple Mail Transfer Protocol):简单邮件传输协议,用于发送电子邮件的传输协议
- POP3(Post Office Protocol - Version 3):用于接收电子邮件的标准协议
- IMAP(Internet Mail Access Protocol):互联网消息协议,是POP3的替代协议
JavaMail
- 导入坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
- 配置
spring:
mail:
host: smtp.qq.com # 使用什么协议和哪个邮箱
username: [email protected] # 邮箱地址
password: ewlrengdrxfxhjde # 该邮箱对应协议的授权码
- 实现类 发送人的邮箱要在配置文件中
@Service
public class SendMailServiceImpl implements SendMailService{
@Autowired
private JavaMailSender javaMailSender;
//发送人
private String from ="[email protected]";
//接收人
private String to ="[email protected]";
//标题
private String subject="测试邮件";
//正文
private Stringcontext:"测试邮件正文内容";
@Override
public void sendMail(){
SimpleMailMessage message = new SimpleMailMessage(); //创建对象(简单邮件)
message.setFrom(from); //设置发送人
message.setTo(to); //设置接收人
message.setSubject(subject); //设置标题
message.setText(context); //设置正文
javaMailSender.send(message); //发送邮件
}
}
根据邮箱格式如果在发送人的邮箱后面加上括号备注,那么在接收方接收到的邮件中就不会显示邮箱地址而显示备注名了
private String from="[email protected](备注名)"
普通邮件 普通邮件比简单邮件的区别就是发送的正文可以是html的,这样就可以设置跳转链接了 或图片附件等
普通邮件发送需要创建一个MimeMessageHelper对象包装MimeMessage对象,在helper对象中设置发送信息 如果要发送的邮件支持html需要在setText设置正文的时候再传入一个布尔参数表示支持html否则发送过去的还只是一个文本
//发送人
private String from ="[email protected]";
//接收人
private String to ="[email protected]";
//标题
private String subject="测试邮件";
//正文
private Stringcontext:"<a href='https://www.baidu.com'>点击跳转到百度</a>";
@Override
public void sendMail(){
try{
MimeMessage message =javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
helper.setFrom(from+"(小甜甜)");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(context,true);
javaMailSender.send(message);
}catch(Exception e){
e.printStackTrace();
}
}
发送附件 要发送附件需要在创建helper对象时在第二个参数中传入布尔值表示开关多部件功能 再调用addAttachment函数设置给helper,第一个参数为文件名,第二个参数是文件本体 文件名需要带后缀
MimeMessageHelper helper=new MimeMessageHelper(message,true);
//添加附件
File f1=new File("path");
File f2=new File("path");
helper.addAttachment(f1.getName(),f1);
helper.addAttachment("文件名",f2);
消息
- 同步消息 : 发送方发送消息,当接收方回复消息后再继续发送
- 异步消息 : 发送方发送全部消息无论接收方是否回复
企业级应用中广泛使用的三种异步消息传递技术
- JMS
- AMQP
- MQTT
Kafka,一种高吞吐量的分布式发布订阅消息系统,提供实时消息功能。
JMS
JMS(JavaMessageService):一个规范,等同于JDBC规范,提供了与消息服务相关的APi接口
JMS消息模型
- peer-2-peer:点对点模型,消息发送到一个队列中,队列保存消息。队列的消息只能被一个消费者消费,或超时
- publish-subscribe:发布订阅模型,消息可以被多个消费者消费,生产者和消费者完全独立,不需要感知对方的存在
JMS消息种类
- TextMessage
- MapMessage
- BytesMessage
- StreamMessage
- ObjectMessage
- Message(只有消息头和属性)
JMS实现:ActiveMQ、Redis、HornetMQ、RabbitMQ、RocketMQ(没有完全遵守JMS规范)
ActiveMQ
下载并启动 默认端口是61616
导入坐标
<dependency>
<groupId>prg.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
- 配置
spring:
activemq:
broker-url: tcp://localhost:61616 # 配置消息队列地址
jms:
template:
default-destination: itheima # 指定消息发送和存储的空间名称
- 实现类 需要实现MessqgeService接口 并且使用的时候需要自动注入JmsMessagingTemplate
@Service
public class MessageServiceActivemqImpl implements MessageService{
@Autowired
private JmsMessagingTemplate messagingTemplate;
@Override
public void sendMessage(String id){
System.out.println("待发送短信的订单已纳入处理队列,id:"+id);
messagingTemplate.convertAndSend("order.queue.id",id); //将消息转换为可以被识别的类型并发送
}
@Override
public String doMessage(){
String id =messagingTemplate.receiveAndConvert("order.queue.id",String.class); //接收时需要转换为对应的数据类型
System.out.println("已完成短信发送业务,id:"+id);
return id;
}
}
监听消息 使用JmsListener注解监听指定目的地的消息,一旦该地方有消息进入立即取出消息执行下面的函数
@Component
public class MessageListener{
@JmsListener(destination="order.queue.id")
public void receive(String id){
System.out.println("已完成短信发送业务,id:"+id);
}
}
转发消息 在接收消息的执行函数上面添加SendTO("目的地")注解,可以在处理完消息后将函数的返回值作为消息发送到另一个目的地
发布-订阅模式 以上消息处理是点对点的模式,可以更改为发布-订阅的模式
spring:
jms:
pub-sub-domain: true # 切换为发布-订阅模式
AMQP
AMQP(advancedmessagequeuingprotocol):一种协议(高级消息队列协议,也是消息代理规范),规范了网络交换的数据格式,兼容JMS
优点:具有跨平台性,服务器供应商,生产者,消费者可以使用不同的语言来实现
AMQP消息模型
- direct exchange
- fanout exchange
- topic exchange
- headers exchange
- system exchange
AMQP消息种类:byte[] 只有一种字节型的消息,可以跨屏台
AMQP实现:RabbitMQ、StormMQ、RocketMQ
RabbitMQ
是使用Erlang语言开发的,使用时需要有Erlang环境 服务端口:5672,管理后台端口:15672 用户名&密码:guest 程序中使用的是5672,在浏览器中查看消息队列时使用的是15672
- 导入坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- 配置
rabbitmq:
host: localhost
port: 5672
- 配置类
先在配置类中创建好一个消息队列(以及交换机)
Queue创建消息队列 第一个参数是字符串类型,消息队列的名称 durable:是否持久化 exclusive:是否是当前连接专用,如果是,当前连接关闭消息队列也关闭 autoDelete:是否自动删除,当发送方和接收方都销毁时该消息队列也自动销毁
DirectExchange创建直连模式的交换机 第一个参数是交换机的名称
Binding绑定消息队列和交换机 将消息队列绑定到交换机上 with给绑定好的对象起名
@Configuration
public class RabbitConfigDirect{
@Bean
public Queue directQueue(){
return new Queue ("direct_queue",true,true,true);
}
@Bean
public DirectExchange directExchange(){
return new DirectExchange("directExchange");
}
@Bean
public Binding bindingDirect(){
return BindingBuilder.bind(directQueue()).to(directExchange()).with("direct");
}
}
- 实现类 发送消息发送到的对象交换机和绑定好的消息队列都使用起的名字传入
@Service
public class MessageServiceRabbitmqDirectImpl implements MessageService{
@Autowired
private AmqpTemplate amqpTemplate;
@Override
public void sendMessage(String id){
System.out.println("待发送短信的订单已纳入处理队列(rabbitmq direct),id:"+id);
amqpTemplate.convertAndSend("directExchange", "direct",id);
}
监听消息队列 和activeMQ类似只需要在接收消息的函数上方加上RabbitListener(queues="direct_queue")注解指明要监听的消息目的地即可
主题交换机 要使用主题模式和创建直连模式类似,只需要将直连模式的direct更改为topic代码就可复用 直连模式只能连接一个制定好的消息队列目的地 主题交换机可以根据匹配规则的不同连接不同的消息队列目的地
绑定键匹配规则
- (星号):用来表示一个单词,且该单词是必须出现的
- #(井号):用来表示任意数量
匹配键 | topic.*.* | topic.# |
---|---|---|
topic.order.id | true | true |
order.topic.id | false | false |
topic.sm.order.id | false | true |
topic.sm.id | false | true |
topic.id.order | true | true |
topic.id | false | true |
topic.order | false | true |
MQTT
MQTT(Message Queueing Telemetry Transport)消息队列遥测传输,专为小设备设计,是物联网(IOT)生态系统中主要成分之一
kafka
zookeeper默认端口为2181 kafka默认端口为9092
- 导入坐标
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
- 配置文件
spring:
kafka:
bootstrap-servers: localhost: 9092
consumer:
group-id: order
- 实现类
@Service
public class MessageServiceKafkaImpl implements MessageService{
@Autowired
private KafkaTemplate<String,String> kafkaTemplate;
@Override
public void sendMessage(String id){
System.out.println("待发送短信的订单已纳入处理队列(kafka),id:"+id);
kafkaTemplate.send("itheima2022",id);
}
@Override
public String doMessage(){
return null;
}
}
只需要使用KafkaTemplate类调用send函数即可,
监听消息队列 只需要在要监听的处理函数上添加KafkaListener注解指定topics即可,如果要监听多个队列可以使用KafkaListeners传入多个topics 从消息队列中获取到的消息存储在形参ConsumerRecord中
@Component
public class MessageListener{
@KafkaListener(topics="itheima2022")
public void onMessage(ConsumerRecord<String,String> record){
System.out.println("已完成短信发送业务(kafka),id:"+record.value());
}
}
监控
- 监控服务状态是否岩机
- 监控服务运行指标(内存、虚拟机、线程、请求等)
- 监控日志
- 管理服务(服务下线)
监控的方式有两种,一种是让被监控的应用程序主动发送信息给监控程序,一种是监控程序主动向被监控的应用程序查询 一般使用后者,当想要查询监控信息时前者无法实现
SpringBootAdmin,开源社区项目,用于管理和监控SpringBoot应用程序。客户端注册到服务端后,通过HTTP请求方式,服务端定期从客户端获取对应的信息,并通过UI界面展示对应信息。 并不是spring官方开发的
- 导入坐标 springbootadmin是有维护的,在创建spring项目时选择它就不用指定版本,有变量定义有版本,但如皋要手动导入坐标在指定版本时版本必须和springboot的版本一致
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.5.4</version>
</dependency>
添加注解 在配置类(启动类)上面添加EnableAdminServer注解表示开启springbootadmin服务
配置被监控的springboot程序
spring
boot:
admin:
client:
url: http://localhost:8080 # 表示可以被本地的8080程序监控
management: # 配置监控程序查看的信息
endpoint:
health:
show-details: always # 健康的信息总是可以被查看
endpoints: #开放多个信息给监控程序
web:
exposure:
include: "*" #开放所有
如果要开放多个断点,在endpoints的include的配置中使用逗号间隔
extend是排除某些端点 include表示包含某些端点
endpoint表示的是是否对外开放信息 endpoints表示是否在浏览器页面展示信息 如果endpoint对某个端点设置不对外开放信息,那么在endpoints中即使设置了显示在页面上也是看不到的
监控原理
Actuator提供了SpringBoot生产就绪功能,通过端点的配置与访问,获取端点信息 端点描述了一组监控信息,SpringBoot提供了多个内置端点,也可以根据需要自定义端点信息 访问当前应用所有端点信息:/actuator 访问端点详细信息:/actuator/端点名称
也可以不使用提供的网页的方式访问,可以使用jmx查看信息
信息端点
在提供的端点中有一个信息端点默认是没有数据的 这个信息端点是用来描述应用程序的信息的,是由程序员写在配置文件中的 在info属性中,里面都是以键值对方式配置的,键和值的取值不做限制
info:
appName: @project.artifactId@
version: @project.version@
company:传智教育
author: itheima
动态信息
在配置文件中无法显示动态信息
要实现动态信息需要创建一个类实现InfoContributor接口,并重写其中的contribute方法 withDetail是写入单条的键值对信息 withDetails是写入多个信息传入的map容器中的所有数据
public class InfoConfig implements InfoContributor{
@Override
public void contribute(Info.Builder builder){
builder.withDetail("runTime",System.currentTimeMillis());
}
}
健康端点
健康端点一般情况下不可以修改 但同样也可以使用配置类的方式动态添加
要创建一个类继承AbstractHealthIndicator抽象类或者实现InfoContributor接口两种方式 AbstractHealthIndicator本质上也是实现了InfoContributor接口 重写其中的doHealthCheck函数 此后的操作和动态实现信息端点的数据一样了
@Component
public class HealthConfigextends AbstractHealthIndicator{
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
boolean condition=true;
if(condition){
builder.withDetail("上线成功,运行时间:",System.currentTimeMiLLis());
builder.up();
}else{
Map infoMap =new HashMap();
infoMap.put("上线失败,错误:","2006");
builder.withDetails(infoMap);
builder.down();
}
}
}
但健康的信息有一个在线情况的属性,如果不指定默认添加的信息是unknow,可以使用builder中的函数进行修改,如: up , unknow , down 但通常使用status函数传入不同的枚举值进行修改: builder.status(Status.UP)
性能端点
metrics
通常在service的实现层添加 使用构造器注入 在该实现类中添加一个构造函数,参数是MeterRegistry 类型,接着就可以将其他的数据传入到MeterRegistry 中了 例如使用了一个计数器,将计数器的数据传入到了其中
private Conter conter;
public BookServiceImpl(MeterRegistry meterRegistry){
counter=meterRegistry.counter(name:"用户付费操作次数:");
}
自定义端点
在实现类上添加相应注解 在实现类上添加Endpoint注解表示该类是一个端点类 其中的id表示端点的名称,enableByDefault表示默认是否默认被控制,也可以在配置文件中像正常端点一样开启
在执行函数上添加注解 在执行函数上添加ReadOperation注解,该注解表示当前端点类的端点被调用时执行一次此函数 函数的返回值将会被传递到监控信息中
@Component
@Endpoint(id="pay")
public class PayEndPoint{
@ReadOperation
public Object getPay(){
//调用业务操作,获取支付相关信息结果,最终return出去
MappayMapp = new HashMap();
payMap.put("level 1",103);
payMap.put("level 2",315);
payMap.put("level 3",666);
return payMap;
}
}
贡献者
版权所有
版权归属:PinkDopeyBug