尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Springboot-四-场景整合

Springboot-四-场景整合 环境准备购买云服务器安装docker,及相应的软件redis.mysql,等。NoSQL-Redis整合1.导入场景依赖包!-- redis场景 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency2.在application.properties配置redis#配置redis spring.data.redis.host localhost spring.data.redis.port 6379 spring.data.redis.password 1233.测试redis在这个配置类中给我们提供了两个组件操作redis数据RedisTemplateObject, Object //对象类型注意需要把对象实现序列化不然保存redis会报错RedisTemplateString, String //字符串类型注入 StringRedisTemplate 对象操作redisRestController public class RedisController { //操作redis需要注入操作RedisTemplate 对象 Autowired private StringRedisTemplate stringRedisTemplate; GetMapping(/redis) public String redis(){ Long count stringRedisTemplate.opsForValue().increment(count); return 访问本网页redis自动增加次数count 次; } }在redis中一般都是Map对象的形式存放KeyValueValue可以是很多种类型String: 字符串存放 ,stringRedisTemplate.opsForValue().set(name,haha); //设置值 stringRedisTemplate.opsForValue().get(name); //取值List: 列表stringRedisTemplate.opsForList().leftPush(list,haha);//添加 到list stringRedisTemplate.opsForList().rightPop(list); //从list中取出Set: 集合stringRedisTemplate.opsForSet().add(set,1,2,3); //添加到set stringRedisTemplate.opsForSet().size(set); //获取set的长度 stringRedisTemplate.opsForSet().remove(set,1); //删除set中的元素 stringRedisTemplate.opsForSet().isMember(set,1);//判断元素1是否在set中 stringRedisTemplate.opsForSet().pop(set);ZSet:有序集合stringRedisTemplate.opsForZSet().add( zset,1,1); stringRedisTemplate.opsForZSet().add(zset,2,2); stringRedisTemplate.opsForZSet().add(zset,3,3); stringRedisTemplate.opsForZSet().size(zset); stringRedisTemplate.opsForZSet().remove(zset,1);Hash: map结构mapk,vstringRedisTemplate.opsForHash().put(KEY1,name,王五); stringRedisTemplate.opsForHash().put(KEY1,age,18); stringRedisTemplate.opsForHash().get(KEY1,name);序列化器修改redis保存数据使用默认的序列化机制导致在redis中看到数据是乱码。在redis的自动配置类中redisTemplate这个方法上注解要求容器中没有RedisTemplate 这个组件才会自动给我添加这个组件如果我们自己写一个redisTemplate放入容器中那不就会使用我们放入哪一个了吗。自定义redisTemplate对象修改为json存储1.首先写一个配置类使用Bean注解 把组件注册到容器中springboot3 写法调用GenericJackson2JsonRedisSerializer 这个在springboot4中废弃Configuration public class AppRedisConfig { /** * 创建RedisTemplate对象 * param redisConnectionFactory // 注入RedisConnectionFactory,底层自动配置好了连接工厂所有连接都要从这个工厂获取 * return */ // 创建RedisTemplate对象, 并注入RedisConnectionFactory Bean public RedisTemplateObject, Object redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplateObject, Object template new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); //设置自己的默认序列化器调用GenericJackson2JsonRedisSerializer() 无参实现类 template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer()); return template; } }springboot4写法调用新版GenericJacksonJsonRedisSerializer方法Configuration public class AppRedisConfig { /** * 创建RedisTemplate对象 * param redisConnectionFactory // 注入RedisConnectionFactory,底层自动配置好了连接工厂所有连接都要从这个工厂获取 * return */ // 创建RedisTemplate对象, 并注入RedisConnectionFactory Bean public RedisTemplateObject, Object redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplateObject, Object template new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); // Jackson 3用 JsonMapper.builder() 构建ObjectMapper 已不可变 JsonMapper jsonMapper JsonMapper.builder() // 按需开启/关闭特性例如 .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) // .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) .build(); //设置自己的默认序列化器 template.setDefaultSerializer(new GenericJacksonJsonRedisSerializer(jsonMapper)); return template; } }注意对象一定要实现序列化SerializableData // getter setter toString AllArgsConstructor NoArgsConstructor public class User implements java.io.Serializable{ private int id; private String name; private int age; }Redis客户端连接方式切换RedisTemplate、 StringRedisTemplate: 操作redis的的工具类。它分别有两种连接方式LettuceConnection 默认JedisConnectionLettuce连接方式切换为Jedis 连接方式首先我们看到导入的依赖包中 spring-boot-starter-data-redis在 spring-boot-data-redis 依赖配置中给我们导入了Lettuce连接所以springboot4默认使用的是Lettuce连接方式。现在我们想要切换成Jedis 连接方式那我们必须先把Lettuce依赖导包排除在导入Jedis 依赖包dependency !-- jedis底层连接redis客户端-- groupIdredis.clients/groupId artifactIdjedis/artifactId /dependency配置文件设置相应的配置属性#客户端类型 spring.data.redis.client-typejedis #是否开启连接池 spring.data.redis.jedis.pool.enabledtrue #最大连接数 spring.data.redis.jedis.pool.max-active8小技巧IDEA中ctrl N 调出查询类或方法名称选中接口按ctrlH可以查看接口被实现的类有那些。接口文档openAPI与swagger蓝色线框是传统开发方式只要导入了webmvc-ui 下面几个包抖会被导入进来。红色线框是响应式编程也是同样的导入webflux-ui下面需要的包抖会被导入最终会得到可视化的swagger界面整合swaggerKnife4j 也是一种UI界面是swagger增强版本。1.导入swagger依赖包,springboot4以上需要2.8 以上版本dependency !-- swagger ui -- groupIdorg.springdoc/groupId artifactIdspringdoc-openapi-starter-webmvc-ui/artifactId version2.8.0/version /dependency如果想使用增强版的knife4j继续导入一下包!-- Knife4j Jakarta版 -- dependency groupIdcom.github.xiaoymin/groupId artifactIdknife4j-openapi3-jakarta-spring-boot-starter/artifactId version4.5.0/version /dependency2.访问页面swagger-ui访问首页http://localhost:8080/swagger-ui/index.htmlknife4j 访问首页http://localhost:8080/doc.html3.注解使用Tag 和Operation 使用效果swagger分组配置1.创建一个配置类创建两个方法返回值是GroupedOpenApi使用注解Bean 注册到容器中粉色部分还可以进行方法上的注解进行判断。比如方法上标注了某个注解才生成文档效果配置文件中添加下面这个方法可以对文档信息的描述设置效果远程调用轻量级客户端方式RestTemplate:普通开发WebClient:响应式编程开发Http Interface:声明式编程API/SDK的区别是什么?· api: (Application Programming Interface)远程提供功能;· sdk: 工具包 (Software Development Kit)导入jar包直接调用功能即可RestTemplate对象连接工具Spring 提供的 HTTP 客户端工具用来在 Java 后端发 HTTP 请求。访问接口说明例如请求https://wttr.in/重庆?formatj1langzhformat是 wttr.in 的输出格式控制参数j json返回结构化 JSON方便代码解析不再返回终端彩色 ASCII 天气图1 完整 JSON 规格包含实时天气 未来 3 天全天预报 逐小时数据 地区信息langzh天气描述中文不加默认英文 示例https://wttr.in/重庆?formatj1langzhm强制公制单位摄氏度、km/h、mm默认有时混英制0只返回实时天气不返回 3 天预报精简q安静模式去掉冗余附加信息formatj2极简 JSON只保留实时温度、地点format3单行文本重庆: ⛅ 26°Cformatp1Prometheus 监控指标格式RestController public class WttrWeatherController { private static final RestTemplate restTemplate new RestTemplate(); GetMapping(/weather) public String weather(RequestParam(city) String city) throws Exception{ // 手动拼接原始中文url字符串 String rawUrl https://wttr.in/ city ?formatj1langzh; // 构造URI对象注意这里直接使用原始url不要URLEncoder // java.net.URI uri new java.net.URI(rawUrl); ResponseEntityString resp restTemplate.exchange(rawUrl, HttpMethod.GET, null, String.class); String body resp.getBody(); JsonMapper jsonMapper new JsonMapper(); JsonNode jsonNode jsonMapper.readTree(body); System.out.println(天气数据); System.out.println(城市 jsonNode.get(nearest_area).get(0).get(areaName).get(0).get(value).asText()); //经纬度 System.out.println(经度 jsonNode.get(nearest_area).get(0).get(latitude).asText()); System.out.println(纬度 jsonNode.get(nearest_area).get(0).get(longitude).asText()); // 解析实时天气 current_condition JsonNode current jsonNode.get(current_condition).get(0); System.out.println(实时天气); System.out.println(温度℃ current.get(temp_C).asText()); System.out.println(体感温度℃ current.get(FeelsLikeC).asText()); System.out.println(湿度% current.get(humidity).asText()); System.out.println(天气描述 current.get(weatherDesc).get(0).get(value).asText()); System.out.println(风速km/h current.get(windspeedKmph).asText()); System.out.println(气压hPa current.get(pressure).asText()); System.out.println(降水量mm current.get(precipMM).asText()); // 解析今日预报 weather[0] JsonNode todayForecast jsonNode.get(weather).get(0); System.out.println(\n今日预报); System.out.println(日期 todayForecast.get(date).asText()); System.out.println(最高温度℃ todayForecast.get(maxtempC).asText()); System.out.println(最低温度℃ todayForecast.get(mintempC).asText()); //get(astronomy).get(0) 对象中的第一个数组 System.out.println(日出 todayForecast.get(astronomy).get(0).get(sunrise).asText()); System.out.println(日落 todayForecast.get(astronomy).get(0).get(sunset).asText()); return body; }WebClient对象连接工具WebClient是Spring‑WebFlux 提供的新一代 HTTP 客户端用来替代老旧的RestTemplate核心特点支持非阻塞响应式Reactor高并发场景性能更好不阻塞 Tomcat 业务线程同时支持同步写法像 RestTemplate 一样简单和异步响应式写法API 流式链式调用可读性强统一处理请求头、Cookie、超时、过滤器RestTemplate 底层基于HttpURLConnectionWebClient 底层可切换Reactor‑Netty、Jetty、Apache HttpClientSpringBoot 项目只要引入spring‑boot‑starter‑webflux依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring‑boot‑starter‑webflux/artifactId /dependency即使你的项目是普通 MVCtomcat只加这个依赖就可以使用 WebClient不用把容器改成 Netty。如果我们创建的是响应式项目springboot会自动帮我们导入webflux依赖包RestController public class WeatherController { GetMapping(/weather) public MonoString weather(RequestParam(city) String city){ // 临时快速测试不注入 WebClient webClient WebClient.create(); return webClient.get() .uri(https://wttr.in/{city}?format4, city) .accept(MediaType.APPLICATION_JSON) .retrieve() .bodyToMono(String.class); } }HTTP Interface1.导入依赖包dependency groupIdorg.springframework.boot/groupId artifactIdspring‑boot‑starter‑webflux/artifactId /dependency2.定义接口public interface WeatherInterface { // 定义接口方法 url请求的路径accept接受的类型json GetExchange(url /{city},accept application/json) // 定义方法参数表示路径参数 cityformat是请求参数 MonoString getWeather(PathVariable String city, RequestParam(defaultValue j1,name format) String format); }3.写一个配置类把代理工厂和定义的接口对象注册到容器中。3.1 创建客户端代理工厂并把代理工厂组件注册到容器中3.2通过代理工厂获得到客户端创建代理对象Configuration public class WeatherConfig { //把代理工厂对象创建好后放入到容器中 Bean HttpServiceProxyFactory factory(){ //创建WebClient客户端对象 //WebClient.builder() 上的 defaultHeader / defaultCookie / defaultRequest属于 WebClient 实例的全局默认配置对这个 WebClient 发出的每一次请求都生效 **可以被单次请求覆盖。 WebClient client WebClient.builder() .defaultHeader(Accept, application/json) // 添加默认请求头 .baseUrl(https://wttr.in)// 设置基础URL .build(); //2.创建代理工厂 return HttpServiceProxyFactory.builderFor(WebClientAdapter.create(client)).build(); } //把WeatherInterface接口对象创建好后放入到容器中 Bean public WeatherInterface weatherInterface(HttpServiceProxyFactory factory) { //3.创建代理对象 return factory.createClient(WeatherInterface.class); } }可以将上面代码有需要变化的抽取到配置文件例如url,请求参数Configuration public class WeatherConfig { //把代理工厂对象创建好后放入到容器中 Bean HttpServiceProxyFactory factory(Value(webclient.baseUrl)String url,Value(webclient.param)String param){ //创建WebClient客户端对象 //WebClient.builder() 上的 defaultHeader / defaultCookie / defaultRequest属于 WebClient 实例的全局默认配置对这个 WebClient 发出的每一次请求都生效 **可以被单次请求覆盖。 WebClient client WebClient.builder() .defaultHeader(Accept, application/json) // 添加默认请求头 .baseUrl(url)// 设置基础URL // 全局过滤器追加 formatj1 query参数兼容原生WebClient与HttpInterface .filter((request, next) - { URI origin request.url(); URI targetUri UriComponentsBuilder.fromUri(origin) .replaceQueryParam(format,param) .build(true) .toUri(); ClientRequest newReq ClientRequest.from(request) .url(targetUri) .build(); return next.exchange(newReq); }) .build(); //2.创建代理工厂 return HttpServiceProxyFactory.builderFor(WebClientAdapter.create(client)).build(); } //把WeatherInterface接口对象创建好后放入到容器中 Bean public WeatherInterface weatherInterface(HttpServiceProxyFactory factory) { //3.创建代理对象 return factory.createClient(WeatherInterface.class); } }4.控制器中注入接口调用接口方法RestController class WeatherController { Autowired WeatherInterface weatherService; GetMapping(/weather) public MonoString getWeather(RequestParam(city) String city) { //4.调用接口中的方法 return weatherService.getWeather(city, j1); } }5.如果我要增加业务例如查询快递业务只需要5.1写请求接口填写接口url请求参数等public interface ExprssInterface { /** * 获取快递信息 * param number // 快递单号 * return */ GetExchange(url https://v1.apizero.cn/api/express?comyto, accept application/json) // 访问接口地址 MonoString getExpress(RequestParam(name number) String number); }5.2写配置文件中的代理对象。Configuration public class ExpressConfig { /** * 创建HttpServiceProxyFactory对象 * return 返回代理接口对象 */ Bean public ExprssInterface exprssInterface(HttpServiceProxyFactory httpServiceProxyFactory){ return httpServiceProxyFactory.createClient(ExprssInterface.class); } }5.3 Controller控制器中注入接口对象 调用接口方法RestController public class WeatherController { Autowired ExprssInterface exprssInterface; GetMapping(/express) public MonoString express(RequestParam(number) String number){ return exprssInterface.getExpress(number); } }消息服务消息队列kafka消息队列kafka工作原理注意grop组与组之间是订阅关系组里面的每个消费者之间是竞争关系。kafka网页界面整合kafka1.创建一个项目导入需要的场景kafka的自动配置类中代码代码操作kafka1.配置kafka的服务器# 设置kafka的连接地址 spring.kafka.bootstrap-serverslocalhost:9092 # 设置消费组 spring.kafka.consumer.group-idkafkaDemo #设置从最开始消费 spring.kafka.consumer.auto-offset-resetearliest #设置自动提交 spring.kafka.consumer.enable-auto-committrue #设置自动提交的时间间隔 spring.kafka.consumer.auto-commit-interval1000 #设置消费者的key和value的反序列化方式默认是StringDeserializer spring.kafka.consumer.key-deserializerorg.apache.kafka.common.serialization.StringDeserializer #设置消费者value的反序列化方式 默认是StringDeserializer 设置为JacksonJsonDeserializer spring.kafka.consumer.value-deserializerorg.springframework.kafka.support.serializer.JacksonJsonDeserializer #设置生产者的key和value的序列化方式 spring.kafka.producer.key-serializerorg.apache.kafka.common.serialization.StringSerializer spring.kafka.producer.value-serializerorg.springframework.kafka.support.serializer.JsonSerializer #设置批量发送消息的大小 spring.kafka.producer.batch-size16384使用KafkaTemplate 发送消息SpringBootTest class KafkaDemoApplicationTests { Autowired KafkaTemplate kafkaTemplate; Test void contextLoads() { kafkaTemplate.send(主题,key,value); //如果发送的值是对象 需要早配置文件配置为JSON 序列化器 kafkaTemplate.send(主题,key,new User(1,王五,18)); } }查看提供了那些序列化类1.找到配置属性类 KafkaProperties.class2.进入到Producer类中,找到keySerializer 属性3.进入到 StringSerializer.class类中它实现了Serializer.class类4.在进入到Serializer.class类中按下 ctrlH 查看到这个接口全部的实现类操作kafka监听消息官方文档:Configuring Topics :: Spring Kafkahttps://docs.spring.io/spring-kafka/reference/kafka/configuring-topics.html参照文档我们可以在启动程序后创建主题分区备份首先写一个配置类Configuration public class kafkaConfig { // 创建一个名为topic1的Topic Bean public NewTopic topic1() { return TopicBuilder.name(主题名称) // 主题名称 .partitions(3) // 分区数 .replicas(2)// 副本数 .compact() // 压缩 .build(); } }在主函数类上使用开启kafka注解功能监听消息参照文档使用kafka注解监听指定主题获取key和value值Component // 声明为组件必须要把这个类放入到容器中 public class MyListenerMessage { // 监听器方法, 监听test主题, groupId为test-group KafkaListener(topics test,groupId test-group) public void onMessageListener(ConsumerRecord record) { Object key record.key(); Object message record.value(); System.out.println(接收到keykey接收到消息 message); } }获取所有的消息/** * 监听test主题指定分区0从0开始消费 * * kafka没有设置偏移时候默认是获取最新消息最后一个 */ KafkaListener(groupId test-group2,topicPartitions {TopicPartition(topic test, partitionOffsets { PartitionOffset(partition 0, initialOffset 0)})}) public void allMessageListener(ConsumerRecord record) { Object key record.key(); Object message record.value(); System.out.println(接收到keykey接收到消息 message); }Web安全安全框架有Apache ShiroSpring Securityl安全架构1.认证 Authentication2.授权Authorization3.防攻击安全框架就是一堆的过滤器Securityl简单功能测试创建一个项目引入需要的场景一般我们写的index.html是能被所有人访问的但是在我们使用了Securityl框架后访问主页也是需要登录的。如果实现主页能被所有人访问我们需要自己写一个配置类Configuration public class IndexViewConfig { Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { HttpSecurity httpSecurity http.authorizeHttpRequests( // 配置请求匹配器允许所有用户访问根路径 req - req.requestMatchers(/) .permitAll() .anyRequest()// 其他所有请求需要认证 .authenticated());// 认证 return httpSecurity.build(); } }配置自己的自定义表单登录页面所有人都能访问Configuration public class IndexViewConfig { Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { HttpSecurity httpSecurity http.authorizeHttpRequests( // 配置请求匹配器允许所有用户访问根路径 req - req.requestMatchers(/) .permitAll() .anyRequest()// 其他所有请求需要认证 .authenticated());// 认证 // 配置自己的表单登录页面permitAll所有人都能访问 http.formLogin(log-log.loginPage(/login).permitAll()); return httpSecurity.build(); } }在Controller中写一个login登录页面RestController public class LoginController { /** * 登录页面 * return */ RequestMapping(/login) public String login() { return login; } }登录login页面!DOCTYPE html html langen head meta charsetUTF-8 titleTitle/title /head body form th:action{/login} methodpost label forusernameUsername/label input typetext idusername nameusernamebrbr label forpasswordPassword/label input typepassword idpassword namepasswordbrbr button typesubmitLogin/button /form /body /html注意登录名称user 密码在启动的控制台在属性配置类中我们可以看到默认用户名称密码是生成的UUIDUserDetailsService组件注册到容器中用于获取所有的用户信息密码需要使用加密器后才能存入EnableMethodSecurity // 启用方法级别的安全控制 Configuration public class IndexViewConfig { Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { HttpSecurity httpSecurity http.authorizeHttpRequests( // 配置请求匹配器允许所有用户访问根路径 req - req.requestMatchers(/) .permitAll() .anyRequest()// 其他所有请求需要认证 .authenticated());// 认证 // 配置自己的表单登录页面 http.formLogin(log-log.loginPage(/login).permitAll()); return httpSecurity.build(); } Bean UserDetailsService userDetailsService(){ return new JdbcDaoImpl(); } // 配置密码编码器(加密器) Bean PasswordEncoder passwordEncoder(){ return new BcryptPassword4jPasswordEncoder(); } }如果精确控制可以使用 EnableMethodSecurity方法注解配合PreAuthorize等注解EnableMethodSecurity // 启用方法级别的安全控制PreAuthorize(hasAnyAuthority(logout)) // 需要有logout权限才能访问 PreAuthorize(hasAllRoles(admin))// 需要有admin角色才能访问可观测性SpringBoot Actuator依赖包!--可观测性 依赖包-- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-actuator/artifactId /dependency导入依赖包后就可以访问:http://localhost:8080/actuator暴露所有端点需要配置#暴露所有端点 management.endpoints.web.exposure.include*定制端点健康状态存活销毁指标次数效率是多少自定义健康监控端点需要满足以下条件1.写的类约定好的必须是以HealthIndicator 结尾以HealthIndicator结尾的类表示端点监控类。2.写的类必须实现HealthIndicator接口自己写健康状态进行返回3.或者是继承AbstractHealthIndicator编写健康检查4.编写的类也需要注册成为组件添加注解Component例如我想查看ExpressConfig 组件在容器中是否存活Configuration public class ExpressConfig { /** * 创建HttpServiceProxyFactory对象 * return 返回代理接口对象 */ Bean public ExprssInterface exprssInterface(HttpServiceProxyFactory httpServiceProxyFactory){ return httpServiceProxyFactory.createClient(ExprssInterface.class); } }重写抽象类中的方法Component //声明为组件 public class MyHealthIndicator extends AbstractHealthIndicator { //注入我们监控组件对象 Autowired ExpressConfig expressConfig; Override protected void doHealthCheck(Health.Builder builder) throws Exception { if (expressConfig.exprssInterface(null)!null){ builder.up()//设置健康状态为up .withDetail(name,张三) //添加详情 .withDetail(age,18) //添加详情 .build(); //构建健康对象 }else { builder.down() //设置健康状态为down .withDetail(name,张三) //添加详情 .withDetail(age,88) //添加详情 .build(); } } }需要看到详细信息需要开启配置#暴露健康检查端点 management.endpoint.health.enabledtrue #显示所有健康检查信息 management.endpoint.health.show-detailsalways访问结果自定义指标MeterRegistry在我们导入依赖包后程序自动帮我们在容器中添加了组件 MeterRegistry 对象使用 MeterRegistry 只需要在构造参数中传入即可。例如我需要统计setConfig 这个方法被调用了多少次。Component //声明为组件 public class MyHealthIndicator extends AbstractHealthIndicator { //注入我们监控组件对象 Autowired ExpressConfig expressConfig; Counter reqnull; public MyHealthIndicator(MeterRegistry meterRegistry) { req meterRegistry.counter(req);//创建计数器对象 } public void setConfig() { req.increment(); // 计数器加1 System.out.println(hello MeterRegistry); } }发请求访问这个方法访问到这个方法多少次会被统计到MeterRegistry对象中访问 http://localhost:8080/hh 就会去调用setConfig方法就会被统计访问次数RestController public class WeatherController { Autowired MyHealthIndicator myHealthIndicator; GetMapping(/hh) public String hh(){ myHealthIndicator.setConfig(); return ok; } }在访问http://localhost:8080/actuator/metrics会看到我们自己写的req 计数器对象最后访问http://localhost:8080/actuator/metrics/req可以看到我们访问的方法被调用的次数。整合Prometheus GrafanaPrometheus 时序数据库Grafana 展示看板原理图时序数据库通过定时抓取Actuator 中的内容存入数据库通过Grafana展示1.安装prometheus:时序数据库docker run -p 9090:9090 -d \ -v pc:/etc/prometheus \ prom/prometheus2.安装grafana;默认账号密码 admin:admindocker run -d - -namegrafana -p 3000:3000 grafana/grafana3.改造SpringBoot应用产生Prometheus需要的格式数据。导入依赖包dependency groupIdio.micrometer/groupId artifactIdmicrometer-registry-prometheus/artifactId /dependency就可以访问网页http:localhost:8080/actuator/prometheus 看到prometheus 需要的全部数据4.把应用程序上传到服务器运行。阿里云上传文件命令#安装上传工具 yum install lrzsz #上传文件 rz5.配置Prometheus 拉取数据,修改 prometheus.yml配置文件#修改 prometheus.yml配置文件 scrape_configs: - job_name: spring-boot-actuator-exporter metrics_path:‘/actuator/prometheus#指定抓取的路径 static_configs: - targets: [192.168.200.1:8001] #被访问的服务器地址 labels: nodename:app-demo6.配置好后重启一下访问prometheus端口就能看到拉取的数据7.使用Grafana展示prometheus拉取的数据Grafana应用市场挑选dashboardshttps://grafana.com/grafana/dashboards/?plcmtfooter选择喜欢的dashboards样式点进去复制 ID7.1进入自己的Grafana 网页新建一个dashboards看板粘贴刚刚的ID数据源的添加返回主页找到Connections
返回列表