java_将数据存入elasticsearch进行高效搜索
使用技术简介:
(1) 使用Nginx实现反向代理,使前端可以调用多个微服务
(2) 使用nacos将多个服务管理关联起来
(3) 将数据存入elasticsearch进行高效搜索
(4) 使用消息队列rabbitmq进行消息的传递
(5) 使用 openfeign 进行多个服务之间的api调用
参考: 56 尚上优选项目-平台管理端-整合ES+MQ实现商品上下架-功能最终测试_哔哩哔哩_bilibili
1. 使用Nginx实现反向代理
使用Nginx实现反向代理,使前端可以通过一个端口,调用多个微服务(的端口)
前端中的配置的base api端口 9901:
反向代理逻辑图:
图示 /acl /sys 为两个服务的名称中的路径字符串。
在nginx中的配置如下:
2. 使用nacos将多个服务管理关联起来
通过nacos将多个服务关联起来,这里实现一个产品上架(存入elasticsearch仓库,简称es)下架(从es仓库删除)的功能.service-product提供商品的信息,service-search通过远程调用(FeignClient)调用service-product的接口,获取商品的具体信息,存入或者从es中删除。
service-product 和 service-search 两个服务通过消息队列进行通讯(rabbitmq消息队列, pom名称:spring-cloud-starter-bus-amqp)
nacos部分:pom依赖:
<!--服务注册 --> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
在各个服务中添加在naco的注册:示例 service-produce模块的application.yml中添加cloud.nacos.discovery.server-addr
在 main主程序中添加 启用Nacos服务发现注解:@EnableDiscoveryClient
同理在service-search模块中:
启动nacos服务,同时启动自己的服务,看自己的服务是否注册成功:
下载安装合适版本的nacos(版本不对应会出兼容性问题):
到nacos目录,执行:
.\bin\startup.cmd -m standalone
启动nacos后,启动自己的服务,如自己的服务注册成功,会在log中有如下提示:
在浏览器中输入: http://192.168.136.1:8848/nacos/index.html 也可看是否启动成功,若你的目标服务在“服务列表”中,说明服务注册成功,nacos正常运行,服务可以被关联起来,可以通过restful风格进行数据的传递了。
3. 使用消息队列rabbitmq进行消息的传递
在需要使用的服务service-search的pom.xml中添加依赖:
<!--rabbitmq消息队列--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
安装rabbitmq服务,示例在虚拟机docker中安装 rabbitmq:3.8-management:
#拉取镜像
docker pull rabbitmq:3.8-management
#创建容器启动
docker run -d --restart=always -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:3.8-management
查看安装rabbitmq的虚拟机ip地址:
docker中安装好后,可以在本机(win11)上测试下安装是否成功:浏览器中输入:http://192.168.68.132:15672/ (注意这里是自己虚拟机的ip地址)
根据自己虚拟机的地址,在需要使用的服务service-search 和 serivice-product 中配置ip地址和端口号等信息:
编写代码,使用 RabbitTemplate, 进行消息的发送:
进行消息发送:指定j交换机exchange 字符串(自定义一个),路由器routing, 发送内容 Object message (这里是 Long skuId)
为了让发送的消息能构正确解析,需要定义一个@Configuration, 使用Jackson2JsonMessageConverter,进行消息的类型转换,这里是将Long skuId 转换成Json格式:
package com.atguigu.ssyx.mq.config;import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MQConfig {@Beanpublic MessageConverter messageConverter() {return new Jackson2JsonMessageConverter();}
}
注意rabbit端还需要对 RabbitTemplate 做一些初始化操作,参考init():
package com.atguigu.ssyx.mq.config;import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;@Component
public class MQProducerAckConfig implements RabbitTemplate.ReturnCallback, RabbitTemplate.ConfirmCallback {// 我们发送消息使用的是 private RabbitTemplate rabbitTemplate; 对象// 如果不做设置的话 当前的rabbitTemplate 与当前的配置类没有任何关系!@Autowiredprivate RabbitTemplate rabbitTemplate;// 设置 表示修饰一个非静态的void方法,在服务器加载Servlet的时候运行。并且只执行一次!// PostConstruct注解的函数:在 Spring 容器创建并初始化 Bean 后自动调用,一个类中只能有一个 @PostConstruct 注解的方法@PostConstructpublic void init(){rabbitTemplate.setReturnCallback(this);rabbitTemplate.setConfirmCallback(this);}/*** 表示消息是否正确发送到了交换机上** @param correlationData 消息的载体* @param ack 判断是否发送到交换机上* @param cause 原因*/@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {if (ack) {System.out.println("消息发送成功!");} else {System.out.println("消息发送失败!" + cause);}}/*** 消息如果没有正确发送到队列中,则会走这个方法!如果消息被正常处理,则这个方法不会走!** @param message* @param replyCode* @param replyText* @param exchange* @param routingKey*/@Overridepublic void returnedMessage(Message message, int replyCode, String replyText,String exchange, String routingKey) {System.out.println("消息主体: " + new String(message.getBody()));System.out.println("应答码: " + replyCode);System.out.println("描述:" + replyText);System.out.println("消息使用的交换器 exchange : " + exchange);System.out.println("消息使用的路由键 routing : " + routingKey);}
}
消息的接收端(消费者) ,通过RabbitListener 定位到到发送者发送的消息队列上:
package com.atguigu.ssyx.receiver;
import com.atguigu.ssyx.mq.constant.MqConst;
import com.rabbitmq.client.Channel;
import com.atguigu.ssyx.search.service.SkuService;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
public class SkuReceiver {@Autowiredprivate SkuService skuService;/*** 商品上架* @param skuId* @param message* @param channel* @throws IOException*/@RabbitListener(bindings = @QueueBinding( //绑定接收什么消息 //消费者,接收消息value=@Queue(value = MqConst.QUEUE_GOODS_UPPER, durable = "true"), // durable 持久化exchange = @Exchange(value = MqConst.EXCHANGE_GOODS_DIRECT),key = {MqConst.ROUTING_GOODS_UPPER}))public void upperSku(Long skuId, Message message, Channel channel) throws IOException {// 发送者: rabbitService.sendMsg(MqConst.EXCHANGE_GOODS_DIRECT,// MqConst.ROUTING_GOODS_UPPER,// skuId);//:发送者函数原型:public boolean sendMsg(String exchange, String routingKey, Object message)// 这里的Object message使用 public MessageConverter messageConverter() 方法转成了json格式,// 确保了生产者和消费者之间的消息序列化与反序列化逻辑一致,// 所以 Object message 对应这里接收者的 Long skuId 形参,实现了参数传递的目的。try{if(skuId != null) {skuService.upperSku(skuId);}/*** 第一个参数:表示收到的消息的标号* 第二个参数:如果为true表示可以签收多个消息*///DeliveryTag 交货标签channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);} catch (IOException e) {System.out.print("john:IOException occurred while processing message");throw e; // 或者处理该异常}}/*** 商品下架* @param skuId*/@RabbitListener(bindings = @QueueBinding(value = @Queue(value = MqConst.QUEUE_GOODS_LOWER, durable = "true"),exchange = @Exchange(value = MqConst.EXCHANGE_GOODS_DIRECT), //交换器key = {MqConst.ROUTING_GOODS_LOWER} //路由器))public void lowerSku(Long skuId, Message message, Channel channel) throws IOException {try {if (skuId != null) {skuService.lowerSku(skuId);}channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);}catch (IOException e) {System.out.print("john:IOException occurred while processing message");throw e; // 或者处理该异常}}
}
注意着的对应关系:
public boolean sendMsg(String exchange, String routingKey, Object message)
sendMsg中的 Object message 被 public MessageConverter messageConverter() 正确解析成了 Long skuId
upperSku(Long skuId, Message message, Channel channel)
至此,rabbitmq完成了从service-product传递一个skuId到service-serach的动作。
若有消息发送送时,界面中会出翔对应的消息队列的名称:
4.将数据存入elasticsearch进行高效搜索
elasticsearch的配置
下载elasticsearch Past Releases of Elastic Stack Software | Elastic, elasticsearch-7.8.0-windows-x86_64.zip (注意版本不对,会有兼容性问题)
下载对应版本的分词器:elasticsearch-analysis-ik-7.8.0.zip
下载 kibana来进行客户端操作 kibana-7.8.0-windows-x86_64.zip
解压 elasticsearch-7.8.0-windows-x86_64文件,在
path\elasticsearch-7.8.0-windows-x86_64\elasticsearch-7.8.0\plugins\ 目录下新建文件夹,命名为ik,解压elasticsearch-analysis-ik-7.8.0,将内容所有内容copy到ik目录中:
在 es目录下运行 .\bin\elasticsearch.bat 启动es:
可以看到启动成功了:
浏览器界面看下 http://localhost:9200/ ,出现下面界面,说明启动成功
配置kibana
下载,解压,修改如下3个配置 (不同版本可能不一样,有增加或者删除项):
启动kibana:
.\bin\kibana.bat
浏览器访问看下:http://127.0.0.1:5601/
分词器的测试:
代码配置
首先定义一个存储仓库对应的类 SkuRepository, 继承自 ElasticsearchRepository:
package com.atguigu.ssyx.search.repository;
import com.atguigu.ssyx.model.search.SkuEs;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;public interface SkuRepository extends ElasticsearchRepository<SkuEs, Long> {
}
使用 skuRepository.save(skuEs) 方法,即可存入 es仓库中。
使用 skuRepository.deleteById(skuId); 即可从仓库中删除。
使用 ProductFeignClient 进行跨服务访问
因为service-serach要使用service-product的信息,但时两个服务,这是需要使用 ProductFeignClient 进行restful风格的api传递参数,进行远程调用。
首先需要pom中引入依赖:
<!-- 服务调用feign --> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><scope>provided </scope> </dependency>
在对应的 service-serach的application-dev.yml中进行配置:
在主程序中药加入远程调用注释: @EnableFeignClients
然后,定义service-product中的api,将参数传入到指定的api接口:
package com.atguigu.ssyx.product.api;import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.product.service.CategoryService;
import com.atguigu.ssyx.product.service.SkuInfoService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
// 内部调用,不是前端调用
@RequestMapping("/api/product") //该类是为了内部调用,供service-search使用,所以命名为内部inner
public class ProductInnerController {@Autowiredprivate CategoryService categoryService;@Autowiredprivate SkuInfoService skuInfoService;//根据categoryId获取商品的category信息@ApiOperation(value = "根据categoryId获取商品的category信息")@GetMapping("inner/getCategory/{categoryId}")public Category getCategoryById(@PathVariable("categoryId") Long categoryId) {return categoryService.getById(categoryId);}//根据skuId获取skuInfo@ApiOperation(value = "根据skuId获取skuInfo信息")@GetMapping("inner/getSkuInfo/{skuId}")public SkuInfo getSkuInfoById(@PathVariable("skuId") Long skuId) {return skuInfoService.getById(skuId);}}
定义使用该api的函数,并使用@FeignClient 注明从哪个模块进行api的对接:
package com.atguigu.ssyx.client.product;import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;//与service\service-product\src\main\resources\application.yml中的application。name名称一致
@FeignClient(value = "service-product")
public interface ProductFeignClient {//作为\service\service-product中的\product\api\ProductInnerController.java//中函数的接口定义文件//注意要使用完整的restful风格的路径//用于远程调用(service-search远程调用service-product)@GetMapping("/api/product/inner/getCategory/{categoryId}")public Category getCategoryById(@PathVariable("categoryId") Long categoryId);@GetMapping("/api/product/inner/getSkuInfo/{skuId}")public SkuInfo getSkuInfoById(@PathVariable("skuId") Long skuId);}
定义feign对象 productFeignClient,调用api对应的函数接口:
SkuInfo skuInfo = productFeignClient.getSkuInfoById(skuId); // ... Category category = productFeignClient.getCategoryById(skuInfo.getCategoryId());
package com.atguigu.ssyx.search.service.impl;import com.alibaba.fastjson.JSON;
import com.atguigu.ssyx.client.product.ProductFeignClient;
import com.atguigu.ssyx.enums.SkuType;
import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.model.search.SkuEs;
import com.atguigu.ssyx.search.repository.SkuRepository;
import com.atguigu.ssyx.search.service.SkuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;@Slf4j
@Service
public class SkuServiceImpl implements SkuService {//通过service-product-client中的feign远程调用service-product中的方法@Autowiredprivate ProductFeignClient productFeignClient;//写入ES,即ElasticsearchRepository的接口类@Autowiredprivate SkuRepository skuRepository;@Overridepublic void upperSku(Long skuId) {SkuEs skuEs = new SkuEs();//为skuEs一个一个属性赋值SkuInfo skuInfo = productFeignClient.getSkuInfoById(skuId);if (skuInfo == null) {return;}Category category = productFeignClient.getCategoryById(skuInfo.getCategoryId());if (category != null) {skuEs.setCategoryId(category.getId());skuEs.setCategoryName(category.getName());}skuEs.setId(skuInfo.getId());skuEs.setKeyword(skuInfo.getSkuName() + "," + skuEs.getCategoryName()); //keyword不分词查询skuEs.setWareId(skuInfo.getWareId());skuEs.setIsNewPerson(skuInfo.getIsNewPerson());skuEs.setImgUrl(skuInfo.getImgUrl());//分词查询的字段数据类型必须是 FieldType.TextskuEs.setTitle(skuInfo.getSkuName());if (skuInfo.getSkuType() == SkuType.COMMON.getCode()) //普通还是秒杀{skuEs.setSkuType(0);skuEs.setPrice(skuInfo.getPrice().doubleValue());skuEs.setStock(skuInfo.getStock()); //仓库数量skuEs.setSale(skuInfo.getSale());skuEs.setPerLimit(skuInfo.getPerLimit()); //每人限购数量} else {//TODO 待完善-秒杀商品}//使用 ElasticsearchRepository 提供的方法保存ES信息SkuEs save = skuRepository.save(skuEs);System.out.print("upperSku:" + JSON.toJSONString(save));}@Overridepublic void lowerSku(Long skuId) {//使用 ElasticsearchRepository 提供的方法删除ES信息skuRepository.deleteById(skuId);}
}
5. 效果验证
实验中的表的名称是skues:
对应
public interface SkuRepository extends ElasticsearchRepository<SkuEs, Long> {
}
对应代码中的名称:
当服务中的 public void upperSku(Long skuId) 被调用时,即 skuRepository.save(skuEs);被调用时,对应的数据就会写入 es中,可在 kibana中进行查看:
使用下面命令进行查看:
GET /_cat/indices?v
查看更多数据,(数据结构取决于自己数据库和代码中对数据的定义):
使用如下命令,其中skues为你的index (表名)名称
POST /skues/_search
{"query":{"match_all":{}}
}
结果有了:
相关文章:
java_将数据存入elasticsearch进行高效搜索
使用技术简介: (1) 使用Nginx实现反向代理,使前端可以调用多个微服务 (2) 使用nacos将多个服务管理关联起来 (3) 将数据存入elasticsearch进行高效搜索 (4) 使用消息队列rabbitmq进行消息的传递 (5) 使用 openfeign 进行多个服务之间的api调用 参…...
RAG中的文本切分策略详解
RAG中的文本切分策略详解 1. 选择RAG中的文本切分策略 1.1 不同的文本切分策略 1. CharacterTextSplitter - 这是最简单的方法。它默认基于字符(默认为"")来切割,并且通过字符的数量来衡量块的长度 2. RecursiveCharacterTextSplitter - 基于字符列表拆分文本。 …...
1-1 电场基本概念
目录: 目录 目录: 1.0 电荷守恒定律 2.0 互斥与相吸 3.0 电场的概念 4.0 库伦定律 5.0 矢量的概念 1.0 电荷守恒定律 电荷守恒定律是物理学中的一个基本原理,它指出在一个封闭系统内,电荷的总量是保持不变的。这意味着电荷既…...
SpringBoot初始化执行自定义接口
SpringBoot初始化执行自定义接口 直接加载接口的方法上即可 PostConstructpublic void init() {//加载初始化数据}PostConstruct是一个在Java EE 5规范中引入的注解,用于标记在依赖注入完成后需要执行的方法。这个注解定义在javax.annotation包中,而不…...
【Ubuntu与Linux操作系统:一、Ubuntu安装与基本使用】
第1章 Ubuntu安装与基本使用 1.1 Linux与Ubuntu Linux是一种开源、类Unix操作系统内核,拥有高稳定性和强大的网络功能。由于其开源性和灵活性,Linux被广泛应用于服务器、嵌入式设备以及桌面环境中。 Ubuntu是基于Debian的一个流行Linux发行版…...
C++大端小端判断方法
文章目录 大端小端定义判断方法方法一:利用联合体(Union)特性判断方法二:通过指针类型转换判断方法三:利用位运算与移位操作判断方法四:使用系统提供的字节序相关宏(特定平台支持) 联…...
【IO编程】标准IO和文件IO的对比
标准 I/O 和 文件 I/O 是两种常见的输入输出操作方式。它们的核心功能都是处理数据流,但使用场景和实现方式有所不同,适用于不同的需求。 标准 I/O 标准 I/O 是指与标准输入、标准输出和标准错误流(分别为 stdin、stdout 和 stderr…...
C#范围表达式,模式匹配,逆变和协变--11
目录 一.范围表达式 1.概述 2.语法 3.代码示例 4.实现原理 5.应用场景 二.模式匹配 1.概述 2.核心概念 3.常用模式类型 4.Switch表达式 5.使用示例 6.优势 三.逆变和协变 1.概述 2.泛型类型参数的变性 3.协变示例 4.逆变示例 5.注意事项 6.应用场景 总结 一…...
矩阵求逆的几种方式
矩阵求逆的几种方式(以二阶为例) 矩阵求逆的方法有多种,以下是常用的几种方式总结: 1. 行列式公式法 这是最常见的方法,适用于 2 2 2 \times 2 22矩阵。 对于矩阵: Φ [ a b c d ] , \Phi \begin{bma…...
全新市场阶段, Plume 生态不断壮大的 RWAfi 版图
加密市场在 2024 年迎来了新的里程碑。BTC 不仅成功推出 ETF,以 BTC 为代表的主流加密货币还在一系列传统金融机构的推动下逐步与主流金融市场接轨。与此同时,随着特朗普成功当选下一任美国总统,他承诺推出一系列友好的加密政策,并…...
HTTPS SSL/TLS 工作流程
目录 一、HTTP/HTTPS 简介1、HTTP协议相关内容2、HTTPS协议3、HTTP版本差异: 二、HTTPS 协议工作流程解析1. 客户端请求 SSL 握手2. 服务端接收 SSL 握手连接3. TLS 握手中的密钥协商4. HTTP 数据的加密与解密5. 安全性保障 三、HTTPS 协议的相关知识拓展1. TLS 与 …...
基于异步IO的io_uring
基于异步IO的io_uring 1. io_uring的实现原理 io_uring使用了一种异步IO机制,它通过一对环形缓冲区(ring buffer)实现用户态于内核态之间的高效通信,用户只需将IO请求放入提交队列,当内核完成IO请求时,会将结果放入完成队列&…...
【redis】centos7下安装redis7
在CentOS 7下安装Redis7可以通过以下两种方法实现:手动编译安装和使用YUM进行安装。 CentOS 7系统的环境和版本: $ cat /etc/centos-release CentOS Linux release 7.9.2009 (Core)手动编译安装 参考官方文档:https://redis.io/docs/lates…...
信息系统项目管理-采购管理-采购清单示例
序号类别产品/服务名称规格/功能描述数量备注1硬件服务器高性能处理器,大容量存储10HP、DELL2网络设备高速路由器和交换机10华为3工作站多核处理器,高分辨率显示器25国产设备4移动检查设备手持式移动检查仪,可连接云平台30国产设备5打印机和扫…...
python 代码使用 DeepXDE 库实现了一个求解二维非线性偏微分方程(PDE)的功能
import deepxde as dde import numpy as np import matplotlib.pyplot as plt import tensorflow as tf# 设置时空计算域 Lx 1 # x 范围从 0 到 1 Ly 1 # y 范围从 0 到 1 Lt 0.05 # t 范围从 0 到 0.05 geom dde.geometry.Rectangle([0, 0], [Lx, Ly]) # 空间域 timed…...
后端技术选型 sa-token校验学习 下 结合项目学习 后端鉴权
目录 后端注册拦截器 实现对 WebMvcConfigurer 接口的类实现 静态变量 方法重写 注册 Spring Framework拦截器 Sa-Token中SaServletFilter拦截器 思考 为什么使用两个拦截器 1. Spring Framework 拦截器 2. SaServletFilter 为什么要注册两个拦截器? 总结 …...
继承(8)
大家好,今天我们来学习一下继承方式相关的知识,有助于我们对java的继承有更深的了解,话不多说,来看。 1.10 继承方式 在现实生活中,事物之间的关系是非常复杂,灵活多样。 Java中支持以下几种继承方式: 单继承: 多层…...
深度学习-图神经网络-超图概念及在Hyper-YOLO的应用(小白也看懂)
为什么需要超图? 在一个复杂系统中,某些节点(实体)之间的互动可能不是仅限于两个节点之间的关系,而是多个节点同时参与的更复杂的关系(超边)。简单说就是为了更好的描述事物之间的关系…...
django基于Python的校园个人闲置物品换购平台
Django 基于 Python 的校园个人闲置物品换购平台 一、平台概述 Django 基于 Python 的校园个人闲置物品换购平台是专为校园师生打造的一个便捷、环保且充满活力的线上交易场所。它借助 Django 这一强大的 Python Web 开发框架,整合了校园内丰富的闲置物品资源&…...
opencv的NLM去噪算法
NLM(Non-Local Means)去噪算法是一种基于图像块(patch)相似性的去噪方法。其基本原理是: 图像块相似性:算法首先定义了一个搜索窗口(search window),然后在该窗口内寻找…...
嵌入式系统中的 OpenCV 与 OpenGLES 协同应用
🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 一、OpenCV 在嵌入式中的基石地位二、OpenGLES 为嵌入式图形渲染赋能三、二者协同的精妙之处四、面临的挑战与应对策略 在嵌入式开…...
第三十六章 Spring之假如让你来写MVC——拦截器篇
Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…...
DDD - 如何运用 DDD 进行数据库设计
文章目录 Pre概述领域对象持久化的思想领域模型的设计传统的 4 种关系1. 一对一关系2. 多对一关系3. 一对多关系4. 多对多关系 继承关系的 3 种设计1. 继承关系的第一种方案:整个父类与子类都写入一张表2. 继承关系的第二种方案:各子类各自对应各自的表3…...
OSPF - 特殊报文与ospf的机制
👠1 携带FA地址的5类LSA 除去7类转5类的LSA会携带FA地址,还有一种情况会有FA地址 FA地址:forwarding address 转发地址,解决次优路径,避免环路5类LSA FA地址不为0,则直接通过FA地址去往目标网段 FA地址为0,…...
VSCode 插件
VSCode 插件 1. GitHub Copilot - AI 代码助手 功能:根据上下文提供实时代码补全,支持自然语言转代码,提供符合现代编程规范的建议。进阶技巧: 使用快捷键 Alt ] 切换多个建议。写注释时,描述业务逻辑而不是具体实现…...
jQuery CSS 类
jQuery CSS 类 引言 在网页设计和开发中,CSS(层叠样式表)起着至关重要的作用,它负责定义网页的布局、颜色、字体等视觉效果。jQuery,作为一个快速、小巧且功能丰富的JavaScript库,极大地简化了HTML文档的…...
CentOS下安装Docker
Docker 必须要在Linux环境下才能运行,windows下运行也是安装虚拟机后才能下载安装运行,菜鸟教程 下载安装 linux 依次执行下边步骤 更新 yum yum update 卸载旧的Docker yum remove docker docker-client docker-client-latest docker-common doc…...
SQLAlchemy
https://docs.sqlalchemy.org.cn/en/20/orm/quickstart.htmlhttps://docs.sqlalchemy.org.cn/en/20/orm/quickstart.html 声明模型 在这里,我们定义模块级构造,这些构造将构成我们从数据库中查询的结构。这种结构被称为 声明式映射,它同时定…...
2025年第三届“华数杯”国际赛A题解题思路与代码(Python版)
游泳竞技策略优化模型代码详解 第一题:速度优化模型 在这一部分,我们将详细解析如何通过数学建模来优化游泳运动员在不同距离比赛中的速度分配策略。 1. 模型概述 我们的模型主要包含三个核心文件: speed_optimization.py: 速度优化的核…...
深入架构剖析 博客点赞逻辑 strategy 策略模式 策略接口 上下文 具体策略 项目实战
目录 点赞策略上下文 策略上下文代码详解 1. 策略模式概述 2. 核心组件 3. 代码解读 LikeStrategyContext 类 LikeTypeEnum 枚举 LikeStrategy 接口 具体策略类 4. 如何使用这个设计 5. 优点 6. 总结 具体代码实现 定义枚举类 从控制层传入参数到上下文 在策略上…...
嵌入式Linux之C语言开发基础
一、C 语言编译过程 Linux 的 C 语言开发,一般选择 GCC 工具链进行编译,示例: 1.mkdir helloworld 2.cd helloworld // 1.main.c #include "hello.h" int main() {say_hello();return 0; } // 2.hello.h #ifndef __HELLO_H__ #de…...
std::accumulate
std::accumulate 是 C 标准库中的一个算法,定义在 <numeric> 头文件中。它用于计算给定范围内元素的累积值(通常是一个和,但也可以是其他类型的累积操作)。 template< class InputIt, class T > T accumulate( Input…...
计算机网络 (33)传输控制协议TCP概述
一、定义与基本概念 TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。它工作在OSI模型的第四层,即传输层,为用户提供可靠的、有序的和无差错的数据传输服务。TCP协议与UDP协议是传输层的两大主要协议,但两者在设计上有明显的不同&…...
Gitee图形界面上传(详细步骤)
目录 1.软件安装 2.安装顺序 3.创建仓库 4.克隆远程仓库到本地电脑 提交代码的三板斧 1.软件安装 Git - Downloads (git-scm.com) Download – TortoiseGit – Windows Shell Interface to Git 2.安装顺序 1. 首先安装git-2.33.1-64-bit.exe,顺序不能搞错2. …...
【STM32-学习笔记-6-】DMA
文章目录 DMAⅠ、DMA框图Ⅱ、DMA基本结构Ⅲ、不同外设的DMA请求Ⅳ、DMA函数Ⅴ、DMA_InitTypeDef结构体参数①、DMA_PeripheralBaseAddr②、DMA_PeripheralDataSize③、DMA_PeripheralInc④、DMA_MemoryBaseAddr⑤、DMA_MemoryDataSize⑥、DMA_MemoryInc⑦、DMA_DIR⑧、DMA_Buff…...
苍穹外卖08——(涉及接收日期格式数据、ApachePOI导出报表、sql获取top10菜品数据)
营业额统计 service层 在需要处理空值、与数据库交互或使用集合时,Integer 、Double是更好的选择。 // 导入string工具类 import org.apache.commons.lang.StringUtils; Service // 标记该类为Spring的服务组件 Slf4j // 引入日志功能 public class Repor…...
Node.js——fs(文件系统)模块
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...
【Docker】入门教程
目录 一、Docker的安装 二、Docker的命令 Docker命令实验 1.下载镜像 2.启动容器 3.修改页面 4.保存镜像 5.分享社区 三、Docker存储 1.目录挂载 2.卷映射 四、Docker网络 1.容器间相互访问 2.Redis主从同步集群 3.启动MySQL 五、Docker Compose 1.命令式安装 …...
Ubuntu中使用miniconda安装R和R包devtools
安装devtools环境包 sudo apt-get install gfortran -y sudo apt-get install build-essential -y sudo apt-get install libxt-dev -y sudo apt-get install libcurl4-openssl-dev -y sudo apt-get install libxml2.6-dev -y sudo apt-get install libssl-dev -y sudo apt-g…...
大语言模型预训练、微调、RLHF
转发,如有侵权,请联系删除: 1.【LLM】3:从零开始训练大语言模型(预训练、微调、RLHF) 2.老婆饼里没有老婆,RLHF里也没有真正的RL 3.【大模型微调】一文掌握7种大模型微调的方法 4.基于 Qwen2.…...
啥!GitHub Copilot也免费使用了
文章目录 前言免费版直接修复代码多文件上下文Agent模式总结 前言 最近,GitHub 给开发者们带来了一个好消息:他们的 AI 编程助手 GitHub Copilot 现在可以免费使用了!以前,每个月要花 10 美元才能享受的服务,现在对所…...
【Ubuntu与Linux操作系统:五、文件与目录管理】
第5章 磁盘存储管理 5.1 Linux磁盘存储概述 磁盘存储是Linux系统存储数据的重要组件,它通过分区和文件系统组织和管理数据。Linux支持多种文件系统,如ext4、xfs和btrfs,并以块的形式管理存储设备。 1. 分区与文件系统: 分区&am…...
【PDF转Word】 PDF在线转word文档 好用!优质网站资源推荐
大家在工作与学习中,经常需要将PDF文件转换为Word格式以便进行编辑和修改。很多人都不知道怎么操作,今天我们介绍一个非常好用的工具:小白工具网,可以在线帮忙大家快速把PDF转换成word格式。 小白工具网提供的PDF转Word功能&…...
计算机网络 (38)TCP的拥塞控制
前言 TCP拥塞控制是传输控制协议(Transmission Control Protocol,TCP)避免网络拥塞的算法,是互联网上主要的一个拥塞控制措施。 一、目的 TCP拥塞控制的主要目的是防止过多的数据注入到网络中,使网络能够承受现有的网络…...
构造函数的原型原型链
代码示例 // 定义一个构造函数 Test function Test() {this.name 张三 }; //向构造函数的原型添加一个属性 age18 Test.prototype.age 18;//使用构造函数 Test 来实例化一个新对象 const test new Test();//向 Object.prototype 添加了一个名为 sex 的属性,其值…...
2025华数杯国际赛A题完整论文讲解(含每一问python代码+数据+可视化图)
大家好呀,从发布赛题一直到现在,总算完成了2025“华数杯”国际大学生数学建模竞赛A题Can He Swim Faster的完整的成品论文。 本论文可以保证原创,保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品论文…...
[RabbitMQ] RabbitMQ运维问题
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...
GenAIOps:生成式 AI 运维 - 实用指南
https://medium.com/google-cloud/genaiops-operationalize-generative-ai-a-practical-guide-d5bedaa59d78 作者:Dr Sokratis Kartakis 从创意到生产:使用生成式 AI 和运维 (GenAIOps) 概述 生成式 AI (GenAI) 的世界充满了令人兴奋的可…...
用户界面软件04
后果 使用这种架构很容易对两个层面的非功能性需求进行优化,但是你仍然需要小心不要将功能 需求重复实现。 现在,两个层面可能有完全不同的设计。比如,用户界面层可能使用配件模型(Widget Model), 以大量的…...
分布式系统设计:Java的秘密基地布局
分布式系统设计是Java企业级开发中的一个关键领域,它涉及到构建高可用、可扩展、高性能的系统。以下是分布式系统设计的一些核心概念和实践: 3.1 分布式系统的特点 分布式系统由多个独立的计算机节点组成,这些节点通过网络连接在一起&#x…...