当前位置: 首页 > article >正文

从零搭建微服务项目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/SpringCloudBase5https://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使用)

前言&#xff1a; 本章主要在原有项目上添加了日志配置&#xff0c;对SpringBoot默认的logback的配置进行了自定义修改&#xff0c;并详细阐述了xml文件配置要点&#xff08;只对日志配置感兴趣的小伙伴可选择直接跳到第三节&#xff09;&#xff0c;并使用Feign代替原有RestT…...

数据结构《图》

数据结构《图论》 图的性质 一、无向图&#xff08;Undirected Graph&#xff09; 定义 由一组顶点&#xff08;Vertex&#xff09;和一组无向边&#xff08;Edge&#xff09;构成。 每条无向边用一条无方向的线段连接两个顶点&#xff0c;记为 ( (u, v) )&#xff0c;其中…...

【数据分析】通过个体和遗址层面的遗传相关性网络分析

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍原理应用场景加载R包数据下载函数个体层面的遗传相关性网络分析导入数据数据预处理构建遗传相关性的个体网络对个体网络Nij进行可视化评估和选择最佳模型评估和选择最佳模型最佳模型…...

在 macOS 的 ARM 架构上按住 Command (⌘) + Shift + .(点)。这将暂时显示隐藏文件和文件夹。

在 macOS 的 ARM 架构&#xff08;如 M1/M2 系列的 Mac&#xff09;上&#xff0c;设置 Finder&#xff08;访达&#xff09;来显示隐藏文件夹的步骤如下&#xff1a; 使用快捷键临时显示隐藏文件&#xff1a; 在Finder中按住 Command (⌘) Shift .&#xff08;点&#xff…...

【产品经理】需求分析方法论+实践

阐述了需求分析的基本认知&#xff0c;包括需求分析的定义、原则和内容。接着&#xff0c;文章详细介绍了需求分析的十个步骤&#xff0c;从收集需求到结果评审&#xff0c;为产品经理提供了清晰的操作指南。 作为产品经理&#xff0c;需求分析是一个最基本的工作&#xff0c;但…...

Windows平台的小工具,功能实用!

今天给大家分享一款超实用的Windows平台监控工具&#xff0c;堪称“桌面小管家”&#xff0c;能帮你轻松掌握电脑的各种运行状态&#xff0c;比如网速、下载速度、内存和CPU占用率等常用参数&#xff0c;让你的电脑运行情况一目了然。 TrafficMonitor 网速监控悬浮窗软件 这款…...

意图识别概述

在当今的人工智能领域&#xff0c;意图识别技术是自然语言处理&#xff08;NLP&#xff09;中的一个重要分支&#xff0c;它使得机器能够理解人类语言背后的目的或意图。对于鸿蒙操作系统而言&#xff0c;掌握意图识别技术可以极大地提升用户体验&#xff0c;使设备能更好地响应…...

54. c++类型转换

c是强类型语言&#xff0c;它有自己的类型系统&#xff0c;隐式类型转换是在类型转换时&#xff0c;自动转换且数据不丢失&#xff0c;显示类型转换是指定转换类型&#xff1b;在c风格的类型转换中 &#xff0c;如下代码进行转换 #include <iostream>int main(int argc,…...

SAP-工单技术性关闭操作手册

文章目录 单个工单批量处理TECO和CLSD标识的区别 单个工单 事务代码CO02&#xff0c;输入工单号后回车 功能-》限制处理-》技术性完成 工单状态更改 撤销TECO操作 CO02输入工单号&#xff0c;功能-》限制处理-》撤销技术性完成 批量处理 事务代码COHV&#xff0c;点击生…...

Aseprite绘画流程案例(1)——画相机图标

原图&#xff1a; 步骤一&#xff1a;打开需要参照的图标 步骤二&#xff1a;将参照的图片拖放到右边&#xff0c;作为参考 步骤三&#xff1a;新建24x24的画布&#xff0c;背景为白色的画布 步骤四&#xff1a;点击菜单栏——视图——显示——像素网格&#xff08;如果画布已经…...

RESTful 的特点与普通 Web API 的区别

RESTful 是一种设计风格&#xff0c;而不仅仅是普通的 Web API。它遵循一些特定的原则和约束&#xff0c;使得 API 更加简洁、可扩展和易于理解。以下是 RESTful 的特点&#xff0c;以及与普通 Web API 的区别&#xff1a; RESTful 的特点 1. 资源导向 RESTful API 的核心是资…...

安装海康威视相机SDK后,catkin_make其他项目时,出现“libusb_set_option”错误的解决方法

硬件&#xff1a;雷神MIX G139H047LD 工控机 系统&#xff1a;ubuntu20.04 之前运行某项目时&#xff0c;处于正常状态。后来由于要使用海康威视工业相机&#xff08;型号&#xff1a;MV-CA013-21UC&#xff09;&#xff0c;便下载了并安装了该相机的SDK&#xff0c;之后运行…...

云计算架构学习之Ansible-playbook实战、Ansible-流程控制、Ansible-字典循环-roles角色

一、Ansible-playbook实战 1.Ansible-playbook安装软件 bash #编写yml [rootansible ansible]# cat wget.yml - hosts: backup tasks: - name: Install wget yum: name: wget state: present #检查playbook的语法 [rootansible ansible]…...

常用安全哈希算法bcrypt

文章目录 常用安全哈希算法bcrypt背景什么是哈希算法bcrypt哈希值验证在线工具编程方式 Bcrypt的原理 常用安全哈希算法bcrypt 背景 在设计一个系统的时候&#xff0c;肯定都有会有用户身份认证的问题&#xff0c;一般对用户校验的时候&#xff0c;都是对用户存在数据库总的密…...

Docker 常用命令基础详解(一)

一、Docker 初相识 在当今数字化时代&#xff0c;软件开发和部署的效率与灵活性成为了关键因素。Docker&#xff0c;作为一款开源的应用容器引擎&#xff0c;犹如一颗璀璨的明星&#xff0c;照亮了软件开发与部署的道路&#xff0c;为开发者们带来了前所未有的便利。它就像是一…...

网络工程师 (47)QOS

一、概念与原理 QOS即服务质量&#xff08;Quality of Service&#xff09;是一种网络技术&#xff0c;用于管理和保证网络中不同类型的质量和性能。它通过设置优先级和带宽限制等策略&#xff0c;确保关键应用&#xff08;如视频会议、语音通信&#xff09;的数据包能够在网络…...

glob 用法技巧

目录 处理大量文件节省内存 匹配多个文件扩展名 遍历多种格式文件 遍历某一个文件&#xff1a; 查找当前目录和子目录 6. 排除特定文件 7. 大小写不敏感匹配 8. 获取绝对路径 9. 处理特殊字符 处理大量文件节省内存 技巧&#xff1a;用 iglob 替代 glob&#xff0c;逐…...

Vue3 前端路由配置 + .NET8 后端静态文件服务优化策略

目录 一、Vue 前端配置&#xff08;核心&#xff09; 1. 配置 Vue Router 的 base 路径 2. 配置 Vue 的 publicPath 二、.NET 后端配置&#xff08;关键&#xff09; 1. 启用默认文档中间件 2. 配置静态文件服务的默认文档 三、验证访问路径 四、原理解释 五、常见问题…...

风铃摇晃的弧度与不安等长

晴&#xff0c;2025年2月19日 的确是&#xff0c;有依靠又有谁会去自己打伞。是啊&#xff0c;有时候生活推着我们走的样子确实挺无力的。不过谁都愿意携手走的&#xff0c;希望有一天再也不用“抛头露面”了吧。 又下载回了 X &#xff0c;马上 Gork 3 可以使用&#xff0c…...

Linux部署DeepSeek r1 模型训练

之前写过一篇windows下部署deepseekR1的文章&#xff0c;有小伙伴反馈提供一篇linux下部署DeepSeek r1 模型训练教程&#xff0c;在 Linux 环境下&#xff0c;我找了足够的相关资料&#xff0c;花费了一些时间&#xff0c;我成功部署了 DeepSeek R1 模型训练任务&#xff0c;结…...

JetBrains 2024开发者生态报告 -你尝试过用VR头戴设备编程吗

JetBrains 2024开发者生态报告&#xff1a;核心洞察 方法论 覆盖 171 个国家/地区 的 23,262 名开发者 。数据按区域开发者数量和就业状态加权。 主要趋势 AI 整合 80% 的公司允许使用第三方 AI 工具&#xff08;如 ChatGPT、Copilot&#xff09;。18% 的开发者将 AI 集成到产…...

Spring Boot “约定大于配置”

什么是“约定大于配置”&#xff1f; “约定大于配置”是一种简化开发的设计理念。简单来说&#xff0c;就是框架默认提供了常见的配置和行为&#xff0c;开发者只需要按照约定来编写代码&#xff0c;避免了繁琐的配置&#xff0c;只在需要时进行定制和调整。这种理念在Spring…...

【大语言模型_3】ollama本地加载deepseek模型后回答混乱问题解决

背景&#xff1a; 本地下载了DeepSeek-R1-Distill-Qwen-7B模型后&#xff0c;通过ollama create DeepSeek-R1-Distill-Qwen-7B -f ds7b.mf加载模型启动后回答混乱&#xff0c;无法使用。 解决方法 重新下载模型&#xff0c;选择了DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf 重…...

汇能感知的光谱相机/模块产品有哪些?

CM020A 分辨率&#xff1a;1600H1200V 光谱范围&#xff1a;350~950nm 光谱分辨率&#xff1a;1nm 接口&#xff1a;USB2.0 帧率&#xff1a;16001200 (6帧) 输出格式&#xff1a;Raw 8bit FOV&#xff1a;D73.5H58.8V44.1 相机尺寸&#xff1a;505055mm VM02S10 分辨率…...

Spring中Bean的四种实例化方法

Bean的四种实例化方法 Bean是Spring核心的概念&#xff0c;另外一个核心的概念是AOP。官网上&#xff0c;Bean的解释是&#xff1a; In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans…...

Office word打开加载比较慢处理方法

1.添加safe参数 ,找到word启动项,右击word,选择属性 , 添加/safe , 应用并确定 2.取消加载项,点击文件,点击选项 ,点击加载项,点击转到,取消所有勾选,确定。...

一台服务器将docker image打包去另一天服务器安装这个镜像

一台服务器将docker image打到去另一天服务器安装这个镜像 1. 打包2.另一台服务器执行 1. 打包 docker save -o nebula-graph-studio.tar harbor1.vm.example.lan/dockerio/vesoft/nebula-graph-studioxxx.tar 是打包好的文件 后面的是 docker image 2.另一台服务器执行 docke…...

在局域网中连接Grafana数据源

目录 登录Grafana 添加数据源 配置数据源 保存并测试 使用数据源 注意事项 登录Grafana 打开浏览器&#xff0c;访问Grafana的地址&#xff0c;默认是http://localhost:3000。 使用默认用户名和密码登录&#xff08;通常是admin/admin&#xff09;&#xff0c;登录后建议…...

深入理解指针1

深入理解指针1 一.内存和地址以及指针间的关系 举一个生活中的例子&#xff0c;假如你去找你的朋友玩&#xff0c;你的朋友告诉了你酒店的名字&#xff0c;但是没有告诉告诉你他具体住哪一件房间&#xff0c;于是你为了找到你的朋友&#xff0c;只好一间房间一间房间的去找&am…...

使用 pjsua2 开发呼叫机器人,批量拨打号码并播放固定音频

如何使用 pjsua2 开发呼叫机器人,批量拨打号码并播放固定音频 声明 该播客仅提供实现思路,并非实际的方案记录,不要盲目照搬。 pjsua2库的安装会有较多问题,请参考本人之前的播客进行安装 pjsua2。 pjsua2 库具体的 api 说明请参考开源库内的 范例代码。 引言 在今天的…...