从零搭建微服务项目Base(第5章——SpringBoot项目LogBack日志配置+Feign使用)
前言:
本章主要在原有项目上添加了日志配置,对SpringBoot默认的logback的配置进行了自定义修改,并详细阐述了xml文件配置要点(只对日志配置感兴趣的小伙伴可选择直接跳到第三节),并使用Feign代替原有RestTemplate完成微服务间调用,以及通过修改Feign的日志输出介绍了Feign配置的修改。
本章代码基于第4章项目,前置源码可在第4章博客下载,博客链接如下:
从零搭建微服务项目(第4章——Nacos环境隔离和配置拉取)-CSDN博客
https://blog.csdn.net/wlf2030/article/details/145532798?sharetype=blogdetail&sharerId=145532798&sharerefer=PC&sharesource=wlf2030&spm=1011.2480.3001.8118简要介绍前置项目流程:order-service以及user-service两服务分别连接order-db以及user-db两数据库,order-db中仅有user-id,user-info存在user-db中,为提供完整order-info,order-service通过nacos发现user-service服务地址并使用RestTemplate调用其端口拿取user-info结合从order-db中拿取的信息返回给前端。
本项目源码链接如下:
wlf728050719/SpringCloudBase5
https://github.com/wlf728050719/SpringCloudBase5以及本专栏会持续更新微服务项目,每一章的项目都会基于前一章项目进行功能的完善,欢迎小伙伴们关注!同时如果只是对单章感兴趣也不用从头看,只需下载前一章项目即可,每一章都会有前置项目准备部分,跟着操作就能实现上一章的最终效果,当然如果是一直跟着做可以直接跳过这一部分。

一、前置项目准备
1.从github下载前一章的项目解压,重命名为Base5打开。
![]()
2.重命名模块为Base5

3.父工程pom.xml中<name>改成Base5,

4.选择环境为dev,并重新加载maven

5.启动nacos(安装和启动见第三章)

6.进入nacos网页 配置管理->配置列表确认有这些yaml文件
(如果不是一直跟着专栏做自然是没有的,需要看第四章的环境隔离和配置拉取,记得把父工程pom文件中namespace的值与nacos中命名空间生成的保持一致)


7.配置数据源,更换两服务的resources下yml文件的数据库配置,数据库sql见第一章数据库准备部分。

.测试数据库连接 属性->点击数据源->测试连接->输入用户名密码



8.添加运行配置 服务->加号->运行配置类型->spring boot

启动服务

测试order-service

测试user-service

二、Feign基本使用
1.order-service的pom中添加feign依赖(建议使用下面release版本)

版本不对,可能会在启动order-service时出现如下报错,即找不到org.springframework.cloud.openfeign.FeignClientFactory的Bean

2.order-service的application开启feign客户端注解,并删除掉原有RestTemplate的bean

替换后内容如下:
package cn.bit.orderservice;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@MapperScan("cn.bit.orderservice.mapper")
@EnableFeignClients
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class, args);}
}
3.创建client接口

接口内容如下:能够看出feign即通过把url封装为接口方便调用,可以理解为每个FeignClient即对应一个微服务,但通过封装让业务看起来像是服务的内部调用。
package cn.bit.orderservice.client;import cn.bit.orderservice.bean.dto.UserBaseInfoDTO;
import cn.bit.orderservice.bean.vo.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient("user-service")
public interface UserClient {@GetMapping("/user/baseInfo/{id}")R<UserBaseInfoDTO> getUserBaseInfo(@PathVariable("id") Integer id);
}
4.更改order-service的serviceImpl实现
原有调用方式如下:(通过url调用服务)

替换后内容如下:(通过定义好的feignclient调用服务)
package cn.bit.orderservice.service.impl;import cn.bit.orderservice.bean.dto.UserBaseInfoDTO;
import cn.bit.orderservice.bean.po.OrderPO;
import cn.bit.orderservice.bean.vo.OrderInfoVO;
import cn.bit.orderservice.client.UserClient;
import cn.bit.orderservice.mapper.OrderMapper;
import cn.bit.orderservice.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate UserClient userClient;@Overridepublic OrderInfoVO getOrderInfoById(int orderId) {OrderPO orderPO = orderMapper.getOrderPOById(orderId);if (orderPO == null)return null;OrderInfoVO orderInfoVO = new OrderInfoVO();orderInfoVO.setOrderId(orderPO.getId());orderInfoVO.setAmount(orderPO.getAmount());orderInfoVO.setCreateTime(orderPO.getCreateTime());orderInfoVO.setGetLocation(orderPO.getGetLocation());try {// 获取买家信息UserBaseInfoDTO userBaseInfo1 = userClient.getUserBaseInfo(orderPO.getBuyerId()).getData();orderInfoVO.setBuyerName(userBaseInfo1.getUsername());// 获取卖家信息UserBaseInfoDTO userBaseInfo2 = userClient.getUserBaseInfo(orderPO.getSellerId()).getData();orderInfoVO.setSellerName(userBaseInfo2.getUsername());} catch (Exception e) {System.out.println("user-service connect error");e.printStackTrace();}return orderInfoVO;}
}
5.启动服务后测试

关闭user-service,无法获取用户信息且控制台有异常输出。


三、日志配置
为体现feign配置需要引入日志输出,之前的控制台的彩色输出是因为Spring Cloud默认日志实现是LogBack,其自动引入了对应的依赖,并有一套默认的配置。
如果需要自行配置日志格式,操作如下:
在order-service的resources目录下创建 logback-spring.xml文件,内容如下:
(本节最后有更完善的配置xml,本xm仅用于了解日志配置相关知识)
<?xml version="1.0" encoding="UTF-8"?>
<configuration><property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${LOG_PATTERN}</pattern></encoder></appender><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>logs/order-service.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>logs/order-service.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><encoder><pattern>${LOG_PATTERN}</pattern></encoder></appender><root level="info"><appender-ref ref="CONSOLE"/><appender-ref ref="FILE"/></root><logger name="cn.bit.orderservice" level="debug" additivity="false"><appender-ref ref="CONSOLE"/></logger>
</configuration>
其中LOG_PATTERN属性定义一种日志输出的格式
(1)appender name=console指定控制台输出采用哪种格式,此处采用上述定义的格式。
(2)appender name=file 指定日志文件记录的目录以及输出的格式。
(3)appender的name的命名随意,只要对应即可,关键实现是其后面的class属性决定了功能
(4)root level=info指定了根日志级别是info级别,除了所有被指定设置的logger其他所有日志级别在info及以上的都会执行console以及file,即控制台打印加日志文件记录。
(5)logger通过name指定cn.bit.orderservice包下日志级别为debug即以上的日志语句会打印在控制台。且设置其不会传播到父logger,其父logger为根,因此debug日志只会被控制台输出而不会被记录在日志文件中。
日志严重等级从高到低如下:
OFF:关闭所有日志记录。
FATAL:记录严重错误事件,这些事件可能导致程序中断。
ERROR:记录错误事件,但不会导致程序中断。
WARN:记录潜在有害的情况。
INFO:记录一般信息,用于描述程序运行过程中的关键事件。
DEBUG:记录详细的调试信息,用于诊断问题。
TRACE:记录最详细的调试信息,用于跟踪程序执行过程。
### 验证开始(该部分可自行选择跳过)
1.在order-service上添加上述xml文件,user-service不添加即使用默认配置


2.在order-controller的接口添加一句log的各种输出;会自动添加@Slf4j注解

3.启动服务,并调用一次接口,能够看到user-service的输出为彩色,order-service的输出为白色。说明每个模块用不同的配置(按照项目目前结构需要每个模块单独写log配置文件,后续有网关模块即可统一配置)
![]()


4.根目录有生成的logs目录和对应日志文件,验证上述(2)。

5.对比控制台输出和日志文件末尾,只有控制台记录了debug,info,warning,验证上述(4)(5)。


这时候肯定就有小伙伴有疑问,既然cn.bit.orderservice包已经被设定了只输出不记录为什么log文件里还有那么多记录。这时就会发现我着重加粗的是日志语句,不是从这个包输出的日志信息被单独配置了,而是这个包定义的日志语句被单独配置。这么说似乎还是有点抽象,下面来用案例说明。
用ctrl+左键跳转到这个HikariDataSource类,这是导入的类,不是项目编写的。

其构造函数中有logger的输出语句,也对应了上述的控制台输出


这时后在logback的配置文件为该类单独配置,即这个日志什么也不干。

然后删除刚才生成的log目录,再重新启动调用接口。前后对比就会发现上面的日志在控制台和文件中都不见了。




我个人的理解是,在编译时,编译器根据配置文件中特殊配置的logger,找到对应的类,扫描其所有logger,然后或面向切面或代理模式对这些logger进行功能增强,其他未特殊配置的类的logger就是默认的功能。不过只是个人理解,具体实现还得扒源码。
6.把logback.xml替换成下面内容, 即console变成console1,格式变成年月日,然后日志路径改成log12345
<?xml version="1.0" encoding="UTF-8"?>
<configuration><property name="LOG_PATTERN" value="%d{yyyy年MM月dd日 HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/><appender name="CONSOLE1" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${LOG_PATTERN}</pattern></encoder></appender><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>logs12345/order-service.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>logs/order-service.%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>30</maxHistory></rollingPolicy><encoder><pattern>${LOG_PATTERN}</pattern></encoder></appender><root level="info"><appender-ref ref="CONSOLE1"/><appender-ref ref="FILE"/></root><logger name="cn.bit.orderservice" level="debug" additivity="false"><appender-ref ref="CONSOLE1"/></logger><logger name="com.zaxxer.hikari.HikariDataSource" level="info" additivity="false"></logger>
</configuration>
7.启动后输出,验证上述(1)(2)(3)。


### 验证结束
这时候会有人问,博主博主,你的日志xml讲解确实很多但还是太吃理解了,有没有更简单强势的xml推荐呢?
有的,兄弟!(bushi)
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false"><property name="logLevel" value="INFO"/><property name="logPath" value="logs/order-service"/><property name="maxHistory" value="60"/><property name="queueSize" value="512"/><!-- 彩色日志格式 --><property name="CONSOLE_LOG_PATTERN"value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/><conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/><conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/><conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/><!-- 控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern></encoder></appender><!-- DEBUG 日志文件输出 --><appender name="FILE_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${logPath}/debug.log</file><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>${logPath}/debug-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern><maxFileSize>128MB</maxFileSize><maxHistory>${maxHistory}</maxHistory><totalSizeCap>10GB</totalSizeCap></rollingPolicy><encoder><pattern>%date [%thread] %-5level [%logger{50}] - %msg%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>DEBUG</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- INFO 日志文件输出 --><appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${logPath}/info.log</file><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>${logPath}/info-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern><maxFileSize>128MB</maxFileSize><maxHistory>${maxHistory}</maxHistory><totalSizeCap>10GB</totalSizeCap></rollingPolicy><encoder><pattern>%date [%thread] %-5level [%logger{50}] - %msg%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- WARN 日志文件输出 --><appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${logPath}/warn.log</file><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>${logPath}/warn-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern><maxFileSize>128MB</maxFileSize><maxHistory>${maxHistory}</maxHistory><totalSizeCap>10GB</totalSizeCap></rollingPolicy><encoder><pattern>%date [%thread] %-5level [%logger{50}] - %msg%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>WARN</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- ERROR 日志文件输出 --><appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${logPath}/error.log</file><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>${logPath}/error-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern><maxFileSize>128MB</maxFileSize><maxHistory>${maxHistory}</maxHistory><totalSizeCap>10GB</totalSizeCap></rollingPolicy><encoder><pattern>%date [%thread] %-5level [%logger{50}] - %msg%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- 异步日志记录 --><appender name="ASYNC_LOG_DEBUG" class="ch.qos.logback.classic.AsyncAppender"><discardingThreshold>0</discardingThreshold><queueSize>${queueSize}</queueSize><neverBlock>true</neverBlock><appender-ref ref="FILE_DEBUG"/></appender><appender name="ASYNC_LOG_INFO" class="ch.qos.logback.classic.AsyncAppender"><discardingThreshold>0</discardingThreshold><queueSize>${queueSize}</queueSize><neverBlock>true</neverBlock><appender-ref ref="FILE_INFO"/></appender><appender name="ASYNC_LOG_WARN" class="ch.qos.logback.classic.AsyncAppender"><discardingThreshold>0</discardingThreshold><queueSize>${queueSize}</queueSize><neverBlock>true</neverBlock><appender-ref ref="FILE_WARN"/></appender><appender name="ASYNC_LOG_ERROR" class="ch.qos.logback.classic.AsyncAppender"><discardingThreshold>0</discardingThreshold><queueSize>${queueSize}</queueSize><neverBlock>true</neverBlock><appender-ref ref="FILE_ERROR"/></appender><root level="${logLevel}"><appender-ref ref="STDOUT"/><appender-ref ref="ASYNC_LOG_DEBUG"/><appender-ref ref="ASYNC_LOG_INFO"/><appender-ref ref="ASYNC_LOG_WARN"/><appender-ref ref="ASYNC_LOG_ERROR"/></root><logger name="cn.bit.orderservice" level="debug" additivity="false"><appender-ref ref="STDOUT"/><appender-ref ref="ASYNC_LOG_DEBUG"/><appender-ref ref="ASYNC_LOG_INFO"/><appender-ref ref="ASYNC_LOG_WARN"/><appender-ref ref="ASYNC_LOG_ERROR"/></logger></configuration>
使用时只需要注意下面两点:
全局日志等级,这里设置为info,在没有特殊指定的情况下会把info及以上等级日志输出和输出到文件中。

单独配置项目文件即cn.bit.orderservice包中的日志,这里相等于把等级下调到了debug。

这些在控制台和日志文件中就会有导入包的info及以上和项目中的debug及以上信息。
其实在nacos的yml或本地application.yml文件中也能使用logger.level对单独的包进行配置,但似乎并不能设置additivity属性阻止其传递给父logger.配置前缀如下:

四、Feign自定义配置
1.在order-service下创建配置类

类内容如下:(这里对feign的日志输出进行配置)
package cn.bit.orderservice.config;import org.springframework.context.annotation.Bean;
import feign.Logger;
public class FeignConfiguration {@Beanpublic Logger.Level feignLoggerLevel() {return Logger.Level.FULL;}
}
2.在order-service的application上启动配置(这种写法会使该模块下所有client都默认使用该配置)

或在UserClient上单独添加配置,具体如下:(因为后面会有多个client扩充,因此项目采用全局配置)

3.在前面日志配置好的情况下启动。
能够看到详细的feign信息。

换成basic

仅输出基本信息

最后:
很抱歉在第五章才加上日志配置的部分,这部分其实应该放在第0章,毕竟日志的重要性不言而喻。不过目前日志配置仍然是每个模块配置一个,实际在网关模块学习后只需要配置一个,并且能够通过使用@{project.artifactId}来使每个模块的日志输出到不同目录,目前仍然需要手动指定每个模块的输出路径。日志配置也会在后面的章节有所更改。
相关文章:
从零搭建微服务项目Base(第5章——SpringBoot项目LogBack日志配置+Feign使用)
前言: 本章主要在原有项目上添加了日志配置,对SpringBoot默认的logback的配置进行了自定义修改,并详细阐述了xml文件配置要点(只对日志配置感兴趣的小伙伴可选择直接跳到第三节),并使用Feign代替原有RestT…...
【深度学习】使用飞桨paddle实现波士顿房价预测任务
使用飞桨实现波士顿房价预测任务 由于开始学习深度学习,因此每次开始都熟悉一下深度学习模型的基本步骤: 在之前的学习中,我们学习了使用Python和NumPy实现波士顿房价预测任务的方法,本章我们将尝试使用飞桨paddle重写房价预测任…...
钉钉多维表:数据管理与协作的新篇章
在当今数字化时代,数据的高效管理和团队协作已成为企业竞争力的关键因素之一。钉钉多维表,作为一款基于钉钉平台的数据协作管理工具,正以其独特的功能和优势,引领着数据管理与协作的新潮流。本文将为您全面解析钉钉多维表的定义、特点、功能亮点、应用场景以及如何使用,让您轻松…...
高级推理的多样化推理与验证
25年2月来自波士顿大学、NotBadMath.AI、谷歌、哥伦比亚大学、MIT、Intuit公司和斯坦福大学的论文“Diverse Inference and Verification for Advanced Reasoning”。 OpenAI o1、o3 和 DeepSeek R1 等推理 LLM 在数学和编码方面取得重大进展,但仍发现 IMO 组合问题…...
深入理解 MySQL 8 C++ 源码:SELECT MOD(MONTH(NOW()), 2) 的函数执行过程
MySQL 作为最流行的关系型数据库之一,其内部实现机制一直是开发者探索的热点。本文将以一条简单的 SQL 查询 SELECT MOD(MONTH(NOW()), 2) 为例,深入分析 MySQL 8 源码中内置函数 MOD、MONTH 和 NOW 的执行过程,揭示其底层实现逻辑。 一、SQL…...
【算法系列】leetcode1419 数青蛙 --模拟
一、题目 二、思路 模拟⻘蛙的叫声。 当遇到 r o a k 这四个字符的时候,我们要去看看每⼀个字符对应的前驱字符,有没有⻘蛙叫出来。如果有⻘蛙叫出来,那就让这个⻘蛙接下来喊出来这个字符;如果没有则为异常字符串,直接…...
蓝桥杯 Java B 组之背包问题、最长递增子序列(LIS)
Day 4:背包问题、最长递增子序列(LIS) 📖 一、动态规划(Dynamic Programming)简介 动态规划是一种通过将复杂问题分解成更小的子问题来解决问题的算法设计思想。它主要用于解决具有最优子结构和重叠子问题…...
Git如何将一个分支的内容同步到另一个分支
在 Git 中,可以通过多种方法将一个分支的内容同步到另一个分支。以下是几种常用的方法: 1. 使用 merge 命令 这是最常见的方法,将一个分支的更改合并到另一个分支。 # 切换到目标分支 git checkout target-branch# 合并源分支的内容 git m…...
[C#]C# winform部署yolov12目标检测的onnx模型
yolov12官方框架:github.com/sunsmarterjie/yolov12 【测试环境】 vs2019 netframework4.7.2 opencvsharp4.8.0 onnxruntime1.16.3 【效果展示】 【调用代码】 using System; using System.Collections.Generic; using System.ComponentModel; using System.…...
51c大模型~合集69
我自己的原文哦~ https://blog.51cto.com/whaosoft/12221979 #7项基于SAM万物分割模型研究工作 1、CC-SAM: SAM with Cross-feature Attention and Context for Ultrasound Image Segmentation #ECCV2024 #SAM #图像分割 #医学图像 Segment Anything Model (SAM) 在自…...
2025寒假周报4
2025寒假天梯训练7-CSDN博客 眨眼间寒假训练就告一段落了,准备回校继续战斗了。这周练了3场OI赛制的篮球杯,感觉非常糟糕,不像天梯赛,天梯赛打起来非常舒适顺畅,一直都不喜欢OI赛制,打着非常不稳定..还需要…...
自学Java-AI结合GUI开发一个石头迷阵的游戏
自学Java-AI结合GUI开发一个石头迷阵的游戏 准备环节1、创建石头迷阵的界面2、打乱顺序3、控制上下左右移动4、判断是否通关5、统计移动步骤,重启游戏6、拓展问题 准备环节 技术: 1、GUI界面编程 2、二维数组 3、程序流程控制 4、面向对象编程 ∙ \bulle…...
buuctf-[极客大挑战 2019]Knife题解
一个很简单的web题,进入界面 网页名还加白给的shell,并且给的提示也很明显,给了一个一句话木马再加上菜刀,很怀疑是一个webshell题,那么直接打开蚁剑测试连接拿shell 用提示的一句话木马的密码,测试链接发现…...
Spring MVC 对象转换器:初级开发者入门指南
Spring MVC 对象转换器:初级开发者入门指南 为什么需要对象转换器? 在 Web 应用中,我们经常需要处理不同类型的对象。例如:前端数据到后端对象 :用户通过表单提交的数据通常是HttpServletRequest 对象,我们…...
语音直播交友app出海:语音直播交友系统软件源码搭建国际化发展技术层面分析
随着移动互联网的普及和全球社交需求的增长以及国内如火如荼的Ai大模型引起的全球发展热潮,语音直播软件出海成为了具有巨大发展潜力的业务领域。以下是一些关键的技术方向,将为语音直播软件在国际市场的成功推广及搭建合作奠定基础。 通信技术 实时语音…...
Web Scraper,强大的浏览器爬虫插件!
Web Scraper是一款功能丰富的浏览器扩展爬虫工具,有着直观的图形界面,无需编写代码即可自定义数据抓取规则,高效地从网页中提取结构化数据,而且它支持灵活的数据导出选项,广泛应用于电商监控、内容聚合、市场调研等多元…...
EasyRTC:基于WebRTC与P2P技术,开启智能硬件音视频交互的全新时代
在数字化浪潮的席卷下,智能硬件已成为我们日常生活的重要组成部分,从智能家居到智能穿戴,从工业物联网到远程协作,设备间的互联互通已成为不可或缺的趋势。然而,高效、低延迟且稳定的音视频交互一直是智能硬件领域亟待…...
go 定时任务 gocron timer
选型推荐(DeepSeek) 简单任务调度: 推荐使用 cron 或 gocron,它们轻量且易用。 复杂任务调度: 推荐使用 go-quartz,支持任务依赖和持久化。 分布式任务调度: 推荐使用 asynq,基于 Redis 实现,适合分布式…...
uniapp引入uview组件库(可以引用多个组件)
第一步安装 npm install uview-ui2.0.31 第二步更新uview npm update uview-ui 第三步在main.js中引入uview组件库 第四步在uni.scss中引入import "uview-ui/theme.scss"样式 第五步在文件中使用组件...
MySQL主从架构
MySQL主从架构 MySQL REPLICATION 在实际生产环境中,如果对数据库的读和写都在一个数据库服务器中操作。无论是在安全性、高可用性,还是高并发等各个方面都是完全不能满足实际需求的,因此,一般来说都是通过主从复制(…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
