Spring + Boot + Cloud + JDK8 + Elasticsearch 单节点 模式下实现全文检索高亮-分页显示 快速入门案例

1. 安装elasticsearch+ik分词器插件

sudo wget https://release.infinilabs.com/analysis-ik/stable/elasticsearch-analysis-ik-8.13.4.zip
sudo mkdir -p ./es_plugins/analysis-ik
sudo mkdir ./es_data
sudo unzip elasticsearch-analysis-ik-8.13.4.zip -d ./es_plugins/analysis-ik
sudo chown liber:liber es_data/ es_plugins/

1.1 docker-compose

version: '3.8'
services:elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:8.13.4container_name: elasticsearchenvironment:- discovery.type=single-node- xpack.security.enabled=true - bootstrap.memory_lock=true- "ES_JAVA_OPTS=-Xms512m -Xmx512m"ulimits:memlock:soft: -1hard: -1mem_limit: 1g  ports:- "9200:9200"- "9300:9300"networks:- esnetvolumes:- ./es_data:/usr/share/elasticsearch/data- ./es_plugins:/usr/share/elasticsearch/plugins
networks:esnet:

启动容器命令:

docker-compose up -d

1.2 修改密码

进入容器

docker exec -it elasticsearch bash

验证分词器的安装:

bin/elasticsearch-plugin list

手动更改密码: 使用 Elasticsearch 提供的 elasticsearch-reset-password 工具重置 elastic 用户的密码:

bin/elasticsearch-reset-password -u elastic

1.3 可能会用到的指令

删除索引:

curl -u elastic:dxOHCIBIWu+2djY6qtF1 -X DELETE "http://127.0.0.1:9200/articles"

测试ik分词器:

 curl -X GET "http://127.0.0.1:9200/_analyze" -u elastic:dxOHCIBIWu+2djY6qtF1 -H 'Content-Type: application/json' -d'{"analyzer": "ik_max_word","text": "Spring Boot 使用入门"}'

说明:dxOHCIBIWu+2djY6qtF1是密码。

2. 项目结构

2.1 完整的项目

在这里插入图片描述

说明:全局控制版本的依赖可以参考上一篇文章,本文只介绍artice-service模块。

2.2 artice-service模块

在这里插入图片描述

3. 数据库操作

create database if not exists blog;
use blog;
CREATE TABLE if not exists users
(id         BIGINT AUTO_INCREMENT PRIMARY KEY,                                          -- 用户的唯一标识符,自动递增的主键email      VARCHAR(100) NOT NULL UNIQUE,                                               -- 电子邮件,不能为空且唯一,长度限制为100个字符username   VARCHAR(12)  NOT NULL UNIQUE,                                               -- 用户名,不能为空且唯一,长度限制为12个字符password   VARCHAR(255) NOT NULL,                                                      -- 用户密码,不能为空,存储为加密后的字符串name       VARCHAR(50),                                                                -- 用户显示名称,非必填,长度限制为50个字符avatar_url VARCHAR(255),                                                               -- 用户头像的URL或文件路径,非必填,长度限制为255个字符role       VARCHAR(20)  NOT NULL DEFAULT 'USER',                                       -- 用户角色,不能为空,默认值为 'USER'enabled    BOOLEAN      NOT NULL DEFAULT TRUE,                                         -- 账户启用状态,不能为空,默认值为TRUE(启用)created_at DATETIME              DEFAULT CURRENT_TIMESTAMP,                            -- 记录创建时间,默认值为当前时间戳updated_at DATETIME              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- 记录最后更新时间,自动更新为当前时间戳
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4COLLATE = utf8mb4_unicode_ci;CREATE TABLE articles
(id         BIGINT AUTO_INCREMENT PRIMARY KEY,                               -- 主键,自增IDtitle      VARCHAR(255) NOT NULL,                                           -- 文章标题,非空content    TEXT         NOT NULL,                                           -- 文章内容 (Markdown格式),非空author     VARCHAR(100) NOT NULL,                                           -- 作者名称,非空user_id    BIGINT       NOT NULL,                                           -- 关联用户ID,外键created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,                             -- 创建时间,默认当前时间updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 更新时间,默认当前时间,更新时自动更新FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE               -- 外键约束,用户删除时级联删除文章
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4COLLATE = utf8mb4_unicode_ci; -- 使用utf8mb4字符集和Unicode排序规则INSERT INTO articles (title, content, author, user_id)
VALUES ('Spring Boot 入门教程', '本文介绍如何使用 Spring Boot 快速创建一个应用程序。', '张三', 1),('MyBatis 使用指南', '这篇文章将讲解 MyBatis 的基本使用方法。', '李四', 1),('Elasticsearch 搜索引擎', '深入了解 Elasticsearch 的功能和用法。', '王五', 1),('Java 并发编程', '本文详细讨论了 Java 中的并发编程技术。', '赵六', 1),('Docker 容器化技术', '这篇文章介绍了如何使用 Docker 进行应用容器化。', '孙七', 1),('微服务架构设计', '讨论了微服务架构的设计原则与实践。', '周八', 1),('Redis 数据库应用', '本文详细介绍了 Redis 的常用操作与应用场景。', '吴九', 1),('Spring Cloud 微服务', '使用 Spring Cloud 构建分布式系统。', '郑十', 1),('RabbitMQ 消息队列', '探讨了 RabbitMQ 在消息队列中的应用。', '张三', 1),('Kubernetes 集群管理', '介绍 Kubernetes 的基本概念与使用。', '李四', 1),('RESTful API 设计', '探讨如何设计和实现 RESTful API。', '王五', 1),('CI/CD 持续集成与部署', '本文介绍了 CI/CD 的概念和工具。', '赵六', 1),('分布式系统概念', '讨论了分布式系统的核心概念。', '孙七', 1),('大数据处理技术', '探讨了 Hadoop 和 Spark 在大数据处理中的应用。', '周八', 1),('NoSQL 数据库应用', '介绍了 NoSQL 数据库的特点与应用场景。', '吴九', 1),('前端开发框架 React', '详细介绍了 React 的基本概念与用法。', '郑十', 1),('Vue.js 框架使用', '讨论了如何使用 Vue.js 构建用户界面。', '张三', 1),('Angular 开发指南', '本文讲解了如何使用 Angular 进行开发。', '李四', 1),('Git 版本控制系统', '介绍了 Git 的基本操作与分支管理。', '王五', 1)('Agile 敏捷开发实践', '探讨了敏捷开发的原则与实践。', '赵六', 1);

4. pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>info.liberx</groupId><artifactId>blog</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>article-service</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.17.2</version></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>2.17.2</version></dependency><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency></dependencies>
</project>

5. application.yml

spring:application:name: article-servicedatasource:url: jdbc:mysql://localhost:3306/blog?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf8username: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverdata:redis:port: 6379host: 192.168.186.77password: 123456timeout: 10000jackson:serialization:write-dates-as-timestamps: false
elasticsearch:url: 192.168.186.77  # Elasticsearch 地址port: 9200username: elastic  # 如果有设置认证,提供用户名password: dxOHCIBIWu+2djY6qtF1  # 如果有设置认证,提供密码
mybatis:configuration:map-underscore-to-camel-case: truecache-enabled: true
eureka:client:service-url:defaultZone: http://localhost:8761/eureka/register-with-eureka: truefetch-registry: true
server:port: 8002

说明:Eurka中心,Redis在本案例暂时没有演示,需要Eurka中心是为了注册到服务中心通过Gateway网关进行转发,读者可以自行去掉一些不必要的依赖项还有配置项。

6. ElasticsearchConfig.java

package info.liberx.articleservice.config;import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ElasticsearchConfig {@Value("${elasticsearch.url}")private String url;@Value("${elasticsearch.username}")private String username;@Value("${elasticsearch.password}")private String password;@Value("${elasticsearch.port}")private int port;@Beanpublic ElasticsearchClient elasticsearchClient() {// 配置 Jackson 的 ObjectMapper 并注册 JavaTimeModuleObjectMapper objectMapper = new ObjectMapper();objectMapper.registerModule(new JavaTimeModule());// 创建自定义的 JacksonJsonpMapperJacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper(objectMapper);// 配置身份验证final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username, password));// 配置 RestClientRestClientBuilder builder = RestClient.builder(new HttpHost(url, port)).setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));RestClient restClient = builder.build();// 使用 RestClientTransport 创建 ElasticsearchClientRestClientTransport transport = new RestClientTransport(restClient, jsonpMapper);return new ElasticsearchClient(transport);}
}

说明:注册了一个 JavaTimeModule,它使得 Jackson 能够正确处理 Java 8 的日期和时间 API。

7. ArticleController.java

package info.liberx.articleservice.controller;import com.github.pagehelper.PageInfo;
import info.liberx.articleservice.model.Article;
import info.liberx.articleservice.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.io.IOException;@RestController
@RequestMapping("/articles")
public class ArticleController {private final ArticleService articleService;@Autowiredpublic ArticleController(ArticleService articleService) {this.articleService = articleService;}// 搜索文章@GetMapping("/search")public ResponseEntity<Page<Article>> searchArticles(@RequestParam String keyword,@RequestParam(defaultValue = "0") int page,@RequestParam(defaultValue = "10") int size) {Pageable pageable = PageRequest.of(page, size);try {Page<Article> articles = articleService.searchArticles(keyword, pageable);return new ResponseEntity<>(articles, HttpStatus.OK);} catch (IOException e) {return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);}}// 创建新文章@PostMappingpublic ResponseEntity<Article> createArticle(@RequestBody Article article) {int result = articleService.createArticle(article);if (result > 0) {return new ResponseEntity<>(article, HttpStatus.CREATED);} else {return new ResponseEntity<>(HttpStatus.BAD_REQUEST);}}// 根据文章ID获取文章@GetMapping("/{id}")public ResponseEntity<Article> getArticleById(@PathVariable Long id) {Article article = articleService.getArticleById(id);if (article != null) {return new ResponseEntity<>(article, HttpStatus.OK);} else {return new ResponseEntity<>(HttpStatus.NOT_FOUND);}}// 更新文章@PutMapping("/{id}")public ResponseEntity<Article> updateArticle(@PathVariable Long id, @RequestBody Article article) {article.setId(id); // 确保更新的是指定ID的文章int result = articleService.updateArticle(article);if (result > 0) {return new ResponseEntity<>(article, HttpStatus.OK);} else {return new ResponseEntity<>(HttpStatus.BAD_REQUEST);}}// 删除文章@DeleteMapping("/{id}")public ResponseEntity<String> deleteArticle(@PathVariable Long id) {int result = articleService.deleteArticle(id);if (result > 0) {return new ResponseEntity<>("文章删除成功", HttpStatus.OK);} else {return new ResponseEntity<>("文章删除失败", HttpStatus.NOT_FOUND);}}// 获取所有文章// 获取所有文章,支持分页@GetMapping("/get/{userid}")public ResponseEntity<PageInfo<Article>> getAllArticles(@PathVariable Long userid,@RequestParam(defaultValue = "1") int page,  // 注意:PageHelper 的页码从1开始@RequestParam(defaultValue = "10") int size) {// 获取分页结果PageInfo<Article> articles = articleService.getArticlesByUserId(userid, page, size);return new ResponseEntity<>(articles, HttpStatus.OK);}
}

8. ArticleMapper.java

package info.liberx.articleservice.mapper;import info.liberx.articleservice.model.Article;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface ArticleMapper {@Insert("INSERT INTO articles(title, content, author, user_id) VALUES(#{title}, #{content}, #{author}, #{userId})")@Options(useGeneratedKeys = true, keyProperty = "id")int insertArticle(Article article);@Select("SELECT * FROM articles WHERE id = #{id}")Article findArticleById(Long id);@Select("SELECT * FROM articles WHERE user_id = #{userId}")List<Article> findArticlesByUserId(Long userId);@Update("UPDATE articles SET title = #{title}, content = #{content}, author = #{author} WHERE id = #{id}")int updateArticle(Article article);@Delete("DELETE FROM articles WHERE id = #{id}")int deleteArticle(Long id);@Select("SELECT * FROM articles")List<Article> findAllArticles();
}

9. Article.java

package info.liberx.articleservice.model;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;import java.time.OffsetDateTime;@Data
@Document(indexName = "articles")  // 定义为 Elasticsearch 索引
@JsonIgnoreProperties(ignoreUnknown = true)  // 忽略未识别的字
public class Article {@Id  // 标记为 Elasticsearch 的文档IDprivate Long id;@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")private String title;@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")private String content;  // Markdown 格式内容@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")private String author;  // 使用 IK 分词器进行分词和搜索@Field(type = FieldType.Long)private Long userId;  // 关联的用户ID@Field(type = FieldType.Date, format = {}, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")private OffsetDateTime createdAt;@Field(type = FieldType.Date, format = {}, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")private OffsetDateTime updatedAt;
}

10. ArticleRepository.java

package info.liberx.articleservice.repository;import info.liberx.articleservice.model.Article;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;@Repository
public interface ArticleRepository extends ElasticsearchRepository<Article, Long> {}

11. ArticleService.java

package info.liberx.articleservice.service;import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import info.liberx.articleservice.mapper.ArticleMapper;
import info.liberx.articleservice.model.Article;
import info.liberx.articleservice.repository.ArticleRepository;
import jakarta.annotation.PostConstruct;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;@Service
public class ArticleService {private final ArticleMapper articleMapper;private final ArticleRepository articleRepository;private final ElasticsearchClient elasticsearchClient;public ArticleService(ElasticsearchClient elasticsearchClient, ArticleMapper articleMapper, ArticleRepository articleRepository) {this.elasticsearchClient = elasticsearchClient;this.articleMapper = articleMapper;this.articleRepository = articleRepository;}@PostConstruct// 同步数据库中的所有文章到 Elasticsearchpublic void indexAllArticles() {List<Article> articles = articleMapper.findAllArticles();articleRepository.saveAll(articles);}public int createArticle(Article article) {int result = articleMapper.insertArticle(article);if (result > 0) {articleRepository.save(article);}return result;}public Article getArticleById(Long id) {return articleMapper.findArticleById(id);}// 分页查询文章public PageInfo<Article> getArticlesByUserId(Long userId, int page, int size) {// 使用 PageHelper 设置分页参数PageHelper.startPage(page, size);// 查询结果List<Article> articles = articleMapper.findArticlesByUserId(userId);// 包装查询结果为 PageInfo 对象return new PageInfo<>(articles);}public int updateArticle(Article article) {int result = articleMapper.updateArticle(article);if (result > 0) {articleRepository.save(article);}return result;}public int deleteArticle(Long id) {int result = articleMapper.deleteArticle(id);if (result > 0) {articleRepository.deleteById(id);}return result;}public Page<Article> searchArticles(String keyword, Pageable pageable) throws IOException {// 构建布尔查询,首先匹配完全符合的记录,然后匹配部分符合的记录Query query = QueryBuilders.bool().should(QueryBuilders.multiMatch().fields("title", "content", "author").query(keyword).type(co.elastic.clients.elasticsearch._types.query_dsl.TextQueryType.Phrase) // 完全匹配.boost(2.0f) // 提高完全匹配的权重.build()._toQuery()).should(QueryBuilders.multiMatch().fields("title", "content", "author").query(keyword).build()._toQuery()) // 部分匹配.build()._toQuery();// 构建搜索请求,设置索引、查询条件、高亮设置、分页参数SearchRequest searchRequest = new SearchRequest.Builder().index("articles").query(query).highlight(h -> h.fields("title", f -> f.preTags("<strong>").postTags("</strong>")).fields("content", f -> f.preTags("<strong>").postTags("</strong>")).fields("author", f -> f.preTags("<strong>").postTags("</strong>"))).from((int) pageable.getOffset()).size(pageable.getPageSize()).build();// 执行搜索请求SearchResponse<Article> searchResponse = elasticsearchClient.search(searchRequest, Article.class);HitsMetadata<Article> hitsMetadata = searchResponse.hits();// 处理搜索结果,提取高亮信息并设置到对应的Article对象中List<Article> articles = hitsMetadata.hits().stream().map(hit -> {Article article = hit.source();if (article != null && hit.highlight() != null) {hit.highlight().forEach((field, highlights) -> {switch (field) {case "title":article.setTitle(String.join(" ", highlights));break;case "content":article.setContent(String.join(" ", highlights));break;case "author":article.setAuthor(String.join(" ", highlights));break;}});}return article;}).collect(Collectors.toList());// 返回包含分页和高亮结果的Page对象return new PageImpl<>(articles, pageable, Objects.requireNonNull(hitsMetadata.total()).value());}}

12. ArticleServiceApplication.java

package info.liberx.articleservice;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration;
import org.springframework.data.web.config.EnableSpringDataWebSupport;@SpringBootApplication(exclude = {LoadBalancerAutoConfiguration.class, LoadBalancerBeanPostProcessorAutoConfiguration.class})
@EnableDiscoveryClient
@EnableSpringDataWebSupport(pageSerializationMode = EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO)
public class ArticleServiceApplication {public static void main(String[] args) {SpringApplication.run(ArticleServiceApplication.class, args);}
}

13. 测试接口(postman)

13.1 测试创建文章 (POST /articles)

POST http://localhost:8002/articles

Body:
选择 raw -> JSON 格式,示例如下:

{"title": "Spring Boot 保姆级教程","content": "本文介绍如何使用 Spring Boot 快速创建一个应用程序。","author": "张三","userId": 1
}

在这里插入图片描述

13.2 测试根据文章 ID 获取文章 (GET /articles/{id})

GET http://localhost:8002/articles/1

在这里插入图片描述

13.3 测试更新文章 (PUT /articles/{id})

PUT http://localhost:8002/articles/1

Body:
选择 raw -> JSON 格式:

{"title": "Spring Boot 入门教程 - 更新","content": "本文详细介绍了如何使用 Spring Boot 创建应用程序,并提供更新。","author": "张三","userId": 1
}

13.4 测试删除文章 (DELETE /articles/{id})

DELETE http://localhost:8002/articles/1

13.5 测试搜索文章 (GET /articles/search)

GET http://localhost:8002/articles/search?keyword=Spring&page=0&size=10

在这里插入图片描述

13.6 测试获取某用户的所有文章并分页 (GET /articles/get/{userid})

GET http://localhost:8002/articles/get/1?page=1&size=10

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/407668.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

市盈率的概念

写篇有关市盈率的【不务正业】的内容。 重要公式 市盈率 官方的定义 平均市盈率&#xff1d;∑(收盘价发行数量)/∑(每股收益发行数量)&#xff0c;统计时剔除亏损及暂停上市的上市公司。 静态市盈率 滚动市盈率&#xff08;TTM&#xff09; 股票市盈率的意义 如果某股票有较…

海运整箱成本与拼箱成本对比 | 国际贸易服务平台 | 箱讯科技

整箱和拼箱 在集装箱运输业务中&#xff0c;我们把一个集装箱、一个出口人、一个收货人、一个目的港&#xff0c;满足这“四个一”条件的货物叫做整箱货&#xff0c;而把一个集装箱、出口人、收货人和目的港这三项之中只要有一项是在两个或两个以上的出口运输货物&#xff0c;就…

Linux网络环境搭建,开发板网线直连电脑网口,电脑WIFI上网

开发板网线直连电脑网口&#xff08;电脑自带&#xff0c;一般有PCI&#xff0c;不是USB网卡&#xff09;&#xff0c;电脑WIFI上网 因为电脑是 WiFi 上网&#xff0c;所以需要添加一个网络适配器并设置成 NAT 模式&#xff0c;供虚拟机上网。 设置双网卡&#xff0c;注意双网卡…

蓝队技能-应急响应篇钓鱼攻击邮件与文件EML还原蠕虫分析线索定性

知识点&#xff1a; 1、应急响应-钓鱼邮件-定性&排查 2、应急响应-恶意文件-应急&分析一、演示案例-蓝队技能-钓鱼攻击-邮件&附件&分析&排查 如何分析邮件安全性&#xff1a; 1、看发信人地址 2、看发信内容信息 3、看发信内容附件 4、看邮件原文源码…

什么是营销自动化?营销自动化的优势?

在SaaS行业和软件行业中&#xff0c;营销自动化作为一种先进的营销手段&#xff0c;正逐渐受到企业的青睐。营销自动化基于大数据和人工智能技术&#xff0c;能够自动执行、管理和完成营销任务和流程&#xff0c;为企业带来诸多优势。 营销自动化是一种能够一体化执行、管理、…

静态代码分析工具介绍——Fortify SCA

今天为大家介绍的是静态代码分析工具&#xff0c;静态代码测试是很重要的&#xff0c;做应用安全最佳的切入点就是在开发阶段做代码的静态应用安全测试分析。这里给大家主要推荐的是Fortify&#xff0c;这是业界做应用安全测试最早的产品&#xff0c;甚至可以称之为应用安全测试…

c++链表(list)

前言 链表作为一个常见的数据结构&#xff0c;在高频插入删除的场景下有独特的优势&#xff0c;在内存的使用上也极少有浪费可以按需申请。今天我们就来简单的学习一下这种数据结构&#xff0c;链表也有很多不同的实现&#xff0c;我们这里和标准库保持一致&#xff0c;实现带…

CUDA指南-CUDA编程基础

CUDA编程基础是开始利用GPU进行并行计算的起点。以下是一些入门步骤和概念&#xff1a; Hello World&#xff1a;第一个CUDA程序 编写CUDA核函数&#xff1a; 创建一个简单的核函数&#xff0c;例如一个向量加法操作。核函数用 global 修饰&#xff0c;表示它将在GPU上执行。…

React 学习——useMemo

useMemo使用场景&#xff1a;消耗非常大的计算&#xff0c;例如递归 import { useMemo, useState } from react; // 缓存&#xff1a;消耗非常大的计算&#xff0c;例如递归 function fib(n){console.log(fib);if(n < 3)return 1;return fib(n-2) fib(n-1); }const App (…

Linux | 文件系统进阶:Inode与软硬链接艺术剖析

当时共我赏花人&#xff0c;点检如今无一半。 - 《木兰花》(晏殊) 2024.8.24 目录 1. 文件系统的基本概念 1.1 ls -l命令查看目录信息 1.2 stat命令查看具体文件的详细信息 1.3 inode ext2文件系统的主要组成部分&#xff1a; 例子&#xff1a;创建main.c文件 文件的创建步骤&a…

谷歌登录的时候,要求在手机的通知点是,并按数字来验证身份,但是手机通知栏没有收到通知和数字,原因是什么,怎么办?

前两天&#xff0c;有个朋友联系到GG账号服务&#xff0c;说他的一个谷歌账号在新设备登录的时候&#xff0c;提示说要在手机的通知栏点击谷歌发来的通知&#xff0c;点击是确认&#xff0c;并且要点按相应的数字。 但问题是他反复刷新手机的通知栏都没有看到谷歌发来的通知&a…

xml打印模板解析-SAAS本地化及未来之窗行业应用跨平台架构

一、为何要自己设置打印模板系统 1.确保自由知识产权 2.支持跨平台&#xff1a;物联网&#xff0c;自助终端&#xff0c;电脑&#xff0c;web&#xff0c;C#&#xff0c;jsp,android,java,php 等多种语言 二、xml 代码解析 package CyberWinPHP.Cyber_Plus;import java.io.…

区块链浪潮:Web3时代的数字经济新格局

随着科技的迅猛发展&#xff0c;全球经济正迎来一场前所未有的变革&#xff0c;区块链技术正在其中扮演着关键角色。Web3作为下一代互联网的核心&#xff0c;正在通过区块链技术重塑数字经济的格局&#xff0c;为全球市场带来新的机遇和挑战。这场以去中心化为特征的技术革命&a…

进阶岛 - MindSearch(CPU版)部署到github codespace

实践结论写在前面&#xff1a; github codespace很好用&#xff0c;丝滑、快速huggingface的space管理代码也很好用&#xff0c;自动编译、容器打包、发布一气呵成mindsearch很好用&#xff0c;效果超出预想。planner和searcher的交互丝滑、有效率。mindsearch内置搜索可解决很…

JAVA基础面试题总结(十四)——JVM(下)

类文件结构详解 什么是字节码&#xff1f; 在 Java 中&#xff0c;JVM 可以理解的代码就叫做字节码&#xff08;即扩展名为 .class 的文件&#xff09;&#xff0c;它不面向任何特定的处理器&#xff0c;只面向虚拟机。Java 语言通过字节码的方式&#xff0c;在一定程度上解决…

45.5【C语言】typedef

目录&#xff1a; *全称 *格式 一般指针 数组指针 函数指针 *细节 *全称 type define 类型&#xff08;重新&#xff09;定义&#xff08;或命名&#xff09;&#xff0c;可简化输入 *格式 1.非指针类型: typedef 类型 简化名称 typedef signed long long k; signed long …

WPF中的可视化树(VisualTree)和逻辑树(LogicalTree)

可视化树和逻辑树 我们先来理解一下什么是可视化树和逻辑树。 可视化树&#xff1a;包含最初指定的大多数元素&#xff08;在XAML或.cs中&#xff09;以及控件模板中的元素。 通俗点来讲&#xff0c;就是整个元素的构成树&#xff0c;从最上面的结点到最后一个结点&#xff…

SpringCache源码解析(一)

一、springCache如何实现自动装配 SpringBoot 确实是通过 spring.factories 文件实现自动配置的。Spring Cache 也是遵循这一机制来实现自动装配的。 具体来说,Spring Cache 的自动装配是通过 org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration 这个类来…

Maven的使用

Maven 是一个项目管理工具&#xff0c;它基于项目对象模型&#xff08;POM&#xff0c;Project Object Model&#xff09;的概念&#xff0c;通过一小段描述信息&#xff08;pom.xml&#xff09;来管理项目的构建、报告和文档。Maven 提供了一个标准化的方式来构建项目&#xf…

MyBatis-Plus 三、(进阶使用)

一、typeHandler 的使用 1、存储json格式字段 如果字段需要存储为json格式&#xff0c;可以使用JacksonTypeHandler处理器。使用方式非常简单&#xff0c;如下所示&#xff1a; 只需要加上两个注解即可&#xff1a; TableName(autoResultMap true) 表示自动…