SpringBoot集成Solr全文检索

news2025/1/10 23:47:54

SrpingBoot 集成 Solr 实现全文检索

一、核心路线

  1. 使用 Docker 镜像部署 Solr 8.11.3 版本服务
  2. 使用 ik 分词器用于处理中文分词
  3. 使用 spring-boot-starter-data-solr 实现增删改查
  4. 配置用户名密码认证
  5. 使用 poi 和 pdfbox 组件进行文本内容读取
  6. 文章最上方有源码和 ik 分词器资源

二、Solr Docker 镜像制作

由于 Solr 官方镜像无法通过环境变量直接配置用户名密码认证,所以选用第三方的 bitnami/solr 镜像作为基础,将 ik 分词器插件封装后得到新的镜像。

  1. 拉取 bitnami/solr 镜像

    docker pull bitnami/solr:8.11.3
    
  2. 下载 ik 分词器 jar 包 ik-analyzer-8.5.0.jar

  3. 编写 Dockerfile 文件

    FROM  bitnami/solr:8.11.3
    
    COPY  ./ik-analyzer-8.5.0.jar  /opt/bitnami/solr/server/solr-webapp/webapp/WEB-INF/lib/
    
    CMD  ["/opt/bitnami/scripts/solr/run.sh"]
    
  4. 构建镜像

    docker build -t bitnami/solr:8.11.3-ik .
    

三、部署 Solr 服务

方式一:普通 docker 命令行部署
  1. 创建数据目录,例如 /home/solr-data

  2. 启动容器

    docker run -d -p 8983:8983 --name solr \
      -v /home/solr-data:/bitnami \
      -e SOLR_ENABLE_AUTHENTICATION=yes \
      -e SOLR_CORES=my_core \
      -e SOLR_ADMIN_USERNAME=admin \
      -e SOLR_ADMIN_PASSWORD=SolrPass \
      bitnami/solr:8.11.3-ik
    
方式二:Rancher 云平台部署

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

由于 solr 镜像默认使用 solr 用户启动容器,挂载的 pvc 没有写入权限,需要按照以下步骤进行:

  1. 以 UID=0 即 root 用户进行启动,并且入口 Entrypoint 使用 /bin/bash 覆盖默认启动命令,然后进入容器命令行

  2. 修改数据目录属主

    chown -R solr:solr /bitnami/
    
  3. 去掉入口(Entrypoint)命令,用户 UID 设置为 1000 即 solr,重启工作负载即可

四、配置 Solr 用户权限

  1. 访问 http://localhost:8983 即可打开 solr 控制台,输入账号密码 admin/SolrPass 登录认证

  2. 为了演示方便,直接给 admin 用户赋予全部权限

    在这里插入图片描述

    在这里插入图片描述

五、配置 my_core 的 ik 分词

编辑 /bitnami/solr/server/solr/my_core/conf/managed-schema 配置文件,追加以下配置内容:

  <!--ik 分词插件配置-->
  <fieldType name="text_ik" class="solr.TextField">
    <analyzer type="index">
      <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" conf="ik.conf" useSmart="false"/>
      <filter class="solr.LowerCaseFilterFactory"/>
    </analyzer>
    <analyzer type="query">
      <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" conf="ik.conf" useSmart="true"/>
      <filter class="solr.LowerCaseFilterFactory"/>
    </analyzer>
  </fieldType>

配置完成后重启 solr 容器。

六、创建 SpringBoot 工程

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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>solr-example</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Solr-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-solr</artifactId>
        </dependency>
        <!--Solr 认证-->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>
        <!--读取 docx 文档内容-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.2</version>
        </dependency>
        <!--读取 doc 文档内容-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>5.2.2</version>
        </dependency>
        <!--读取 PDF 文档内容-->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.26</version>
        </dependency>
        <!--Hutool 工具类-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.3.RELEASE</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

配置文件
server:
  port: 18888
spring:
  servlet:
    # 文件上传配置
    multipart:
      enabled: true
      max-file-size: 100MB
      max-request-size: 100MB
  data:
    solr:
      host: http://localhost:8983/solr # solr 服务地址
      username: admin # solr 用户名
      password: SolrPass # solr 密码
工程启动类
package com.example.solr;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.solr.repository.config.EnableSolrRepositories;

@EnableSolrRepositories // 启用 solr repository
@SpringBootApplication
public class SolrExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SolrExampleApplication.class, args);
    }
}

SolrConfig 配置类

该类用于配置 Solr 认证

import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpCoreContext;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.URI;

@Configuration
public class SolrConfig {

    @Value("${spring.data.solr.username}")
    private String username;

    @Value("${spring.data.solr.password}")
    private String password;

    @Value("${spring.data.solr.host}")
    private String uri;

    /***
     *  配置 solr 账号密码
     */
    @Bean
    public HttpSolrClient solrClient() {
        CredentialsProvider provider = new BasicCredentialsProvider();
        final URI uri = URI.create(this.uri);
        provider.setCredentials(new AuthScope(uri.getHost(), uri.getPort()),
                new UsernamePasswordCredentials(this.username, this.password));
        HttpClientBuilder builder = HttpClientBuilder.create();
        // 指定拦截器,用于设置认证信息
        builder.addInterceptorFirst(new SolrAuthInterceptor());
        builder.setDefaultCredentialsProvider(provider);
        CloseableHttpClient httpClient = builder.build();
        return new HttpSolrClient.Builder(this.uri).withHttpClient(httpClient).build();
    }

    public static class SolrAuthInterceptor implements HttpRequestInterceptor {
        @Override
        public void process(final HttpRequest request, final HttpContext context) {
            AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
            if (authState.getAuthScheme() == null) {
                CredentialsProvider provider =
                        (CredentialsProvider) context.getAttribute(HttpClientContext.CREDS_PROVIDER);
                HttpHost httpHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
                AuthScope scope = new AuthScope(httpHost.getHostName(), httpHost.getPort());
                Credentials credentials = provider.getCredentials(scope);
                authState.update(new BasicScheme(), credentials);
            }
        }
    }
}

MyDocument 实体类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.annotation.Id;
import org.springframework.data.solr.core.mapping.Indexed;
import org.springframework.data.solr.core.mapping.SolrDocument;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
@SolrDocument(collection = "my_core") // 此处配置 core 信息
public class MyDocument implements Serializable {

    @Id
    @Field
    private String id;

    // 使用 string 类型即不进行分词
    @Indexed(name = "type", type = "string")
    private String type;

    // 使用 text_ik 类型即使用 ik 分词器进行分词索引和查询
    @Indexed(name = "title", type = "text_ik")
    private String title;

    // 使用 text_ik 类型即使用 ik 分词器进行分词索引和查询
    @Indexed(name = "content", type = "text_ik")
    private String content;
}
MyDocumentRepository 类

该类用于和 solr 服务进行通信,实现增删改查操作。

import com.example.solr.entity.MyDocument;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.core.query.result.HighlightPage;
import org.springframework.data.solr.repository.Highlight;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.repository.SolrCrudRepository;

import java.util.List;

public interface MyDocumentRepository extends SolrCrudRepository<MyDocument, String> {

    /**
     * 按类型进行查询
     *
     * @param type 类型
     * @return 查询结果
     */
    @Query("type:?0")
    List<MyDocument> findAllByType(String type);

    /**
     * 按照标题或内容进行模糊查询,并且对关键词进行高亮标记
     * snipplets = 3 用于指定查询出符合条件的结果数,不指定则只能查出一条
     *
     * @param title    标题关键词
     * @param content  内容关键词
     * @param pageable 分页对象
     * @return 带有高亮标记的查询结果
     */
    @Highlight(snipplets = 3, fields = {"title", "content"}, prefix = "<span style='color:red'>", postfix = "</span>")
    HighlightPage<MyDocument> findAllByTitleOrContent(String title, String content, Pageable pageable);
}
MyDocumentService 类
import com.example.solr.entity.MyDocument;
import org.springframework.data.domain.Pageable;

import java.util.List;
import java.util.Map;

public interface MyDocumentService {

    MyDocument save(MyDocument document);

    void saveAll(List<MyDocument> documentList);

    void delete(String id);

    MyDocument findById(String id);

    List<MyDocument> findAllByType(String type);

    List<Map<String, Object>> findAllByTitleOrContent(String searchItem, Pageable pageable);
}

对应的实现类

import com.example.solr.entity.MyDocument;
import com.example.solr.repository.MyDocumentRepository;
import com.example.solr.service.MyDocumentService;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.core.query.result.HighlightEntry;
import org.springframework.data.solr.core.query.result.HighlightPage;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class MyDocumentServiceImpl implements MyDocumentService {

    @Resource
    private MyDocumentRepository repository;

    @Override
    public MyDocument save(MyDocument document) {
        return repository.save(document);
    }

    @Override
    public void saveAll(List<MyDocument> documentList) {
        repository.saveAll(documentList);
    }

    @Override
    public void delete(String id) {
        repository.delete(findById(id));
    }

    @Override
    public MyDocument findById(String id) {
        return repository.findById(id).orElse(null);
    }

    @Override
    public List<MyDocument> findAllByType(String type) {
        return repository.findAllByType(type);
    }

    @Override
    public List<Map<String, Object>> findAllByTitleOrContent(String searchItem, Pageable pageable) {

        // 查询分页结果
        HighlightPage<MyDocument> page = repository.findAllByTitleOrContent(searchItem, searchItem, pageable);

        List<Map<String, Object>> result = new ArrayList<>();
        // 处理查询结果高亮片段
        for (HighlightEntry<MyDocument> highlight : page.getHighlighted()) {
            // 每个 map 对应一个文档
            Map<String, Object> map = new HashMap<>();
            MyDocument doc = highlight.getEntity();
            map.put("id", doc.getId());
            map.put("type", doc.getType());
            map.put("title", doc.getTitle());
            for (HighlightEntry.Highlight hl : highlight.getHighlights()) {
                map.put(hl.getField().getName(), hl.getSnipplets());
            }
            result.add(map);
        }
        return result;
    }
}
FileUtil 文件内容处理类
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

@Slf4j
public class FileUtil {
    /**
     * 读取文档内容
     * 目前仅支持 txt, doc, docx, pdf 格式
     *
     * @param file 文件对象
     * @return 文档内容
     */
    public static String readFileContent(MultipartFile file) {

        String filename = file.getOriginalFilename();
        assert filename != null;
        String fileType = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
        switch (fileType) {
            case "TXT":
                return readTxtContent(file);
            case "DOC":
            case "DOCX":
                return readWordContent(file);
            case "PDF":
                return readPDFContent(file);
            default:
                return "";
        }
    }

    /**
     * 读取 txt 文档内容
     */
    private static String readTxtContent(MultipartFile file) {
        try {
            return StrUtil.utf8Str(file.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
            log.error("读取 txt 文件内容时发生 IO 异常");
            return "";
        }
    }

    /**
     * 读取 doc 和 docx 文档内容
     */
    private static String readWordContent(MultipartFile file) {

        String filename = file.getOriginalFilename();
        assert filename != null;
        String fileType = filename.substring(filename.lastIndexOf(".") + 1);
        return "doc".equals(fileType) ? readDocContent(file) : readDocxContent(file);
    }

    /**
     * 读取 .doc 格式的 word 文档
     *
     * @param file 文件对象
     * @return 文本内容
     */
    private static String readDocContent(MultipartFile file) {
        StringBuilder content = new StringBuilder();
        try (InputStream inputStream = file.getInputStream();
             HWPFDocument document = new HWPFDocument(inputStream)) {
            WordExtractor extractor = new WordExtractor(document);
            String[] paragraphs = extractor.getParagraphText();
            for (String paragraph : paragraphs) {
                content.append(paragraph);
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("读取文件内容时发生 IO 异常");
        }
        return content.toString();
    }

    /**
     * 读取 .docx 格式的 word 文档
     *
     * @param file 文件对象
     * @return 文本内容
     */
    private static String readDocxContent(MultipartFile file) {
        StringBuilder content = new StringBuilder();
        try (InputStream inputStream = file.getInputStream();
             XWPFDocument document = new XWPFDocument(inputStream)) {
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                for (XWPFRun run : paragraph.getRuns()) {
                    String runText = run.getText(0);
                    if (runText != null) {
                        content.append(runText);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("读取文件内容时发生 IO 异常");
        }
        return content.toString();
    }

    /**
     * 读取 pdf 文档内容
     */
    private static String readPDFContent(MultipartFile file) {

        StringBuilder content = new StringBuilder();
        try (InputStream inputStream = file.getInputStream();
             PDDocument document = PDDocument.load(inputStream)) {
            // 检查是否是由文档转换出的 pdf 文件
            if (!document.isEncrypted() && document.getNumberOfPages() > 0) {
                PDFTextStripper textStripper = new PDFTextStripper();
                content.append(textStripper.getText(document));
            } else {
                log.warn("PDF 已加密或不是由文档转换的 PDF 格式,无法读取内容!");
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("读取文件内容时发生 IO 异常");
        }
        return content.toString();
    }
}

MyDocumentController 控制器类
package com.example.solr.controller;

import com.example.solr.entity.MyDocument;
import com.example.solr.service.MyDocumentService;
import com.example.solr.util.FileUtil;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping("/solr")
public class MyDocumentController {

    @Resource
    private MyDocumentService documentService;

    /**
     * 上传文档文件,读取文档内容并写入 solr
     *
     * @param file 上传的文档文件,仅支持读取以下格式的文件内容 txt, doc, docx, pdf(由文档转换生成的)
     * @param type 文件分类
     * @return 处理结果
     */
    @PostMapping("/upload")
    public Map<String, Object> upload(@RequestPart("multipartFile") MultipartFile file, @RequestParam String type) {

        MyDocument doc = new MyDocument();
        doc.setId(UUID.randomUUID().toString());
        doc.setType(type);
        doc.setTitle(file.getOriginalFilename());
        doc.setContent(FileUtil.readFileContent(file));
        documentService.save(doc);

        Map<String, Object> result = new HashMap<>();
        result.put("result", true);
        result.put("data", doc);
        return result;
    }

    /**
     * 直接向 solr 添加内容
     *
     * @param type    类型
     * @param title   标题
     * @param content 内容
     * @return 处理结果
     */
    @PostMapping("/save")
    public Map<String, Object> save(@RequestParam String type, @RequestParam String title, @RequestParam String content) {

        MyDocument doc = new MyDocument();
        doc.setId(UUID.randomUUID().toString());
        doc.setType(type);
        doc.setTitle(title);
        doc.setContent(content);
        documentService.save(doc);

        Map<String, Object> result = new HashMap<>();
        result.put("result", true);
        result.put("data", doc);
        return result;
    }

    /**
     * 删除 solr 内容
     *
     * @param id 主键
     * @return 处理结果
     */
    @DeleteMapping("/delete")
    public Map<String, Object> delete(@RequestParam String id) {
        documentService.delete(id);

        Map<String, Object> result = new HashMap<>();
        result.put("result", true);
        result.put("data", null);
        return result;
    }

    /**
     * 根据标题或内容模糊搜索,并且高亮关键词
     *
     * @param searchItem 搜索关键词
     * @param page       页码
     * @param size       每页数量
     * @return 查询结果
     */
    @GetMapping("/searchTitleOrContent")
    public Map<String, Object> searchTitleOrContent(@RequestParam String searchItem, @RequestParam Integer page,
                                                    @RequestParam Integer size) {

        List<Map<String, Object>> data = documentService.findAllByTitleOrContent(searchItem, PageRequest.of(page, size));

        Map<String, Object> result = new HashMap<>();
        result.put("result", true);
        result.put("data", data);
        return result;
    }

    /**
     * 根据类型搜索
     *
     * @param type 类型
     * @return 查询结果
     */
    @GetMapping("/searchType")
    public Map<String, Object> searchType(@RequestParam String type) {

        List<MyDocument> data = documentService.findAllByType(type);

        Map<String, Object> result = new HashMap<>();
        result.put("result", true);
        result.put("data", data);
        return result;
    }
}

七、验证

启动服务,使用 postman 等工具进行接口请求。

1. 直接写入 solr 内容

在这里插入图片描述

2. 上传 word 文档读取内容写入 solr

在这里插入图片描述

3. 根据类型精确查询

在这里插入图片描述

4. 根据标题或内容模糊查询

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pe启动盘破解windows密码wins电脑登录密码修改重置

目录 1.进入电脑BIOS&#xff0c;设置电脑第一启动项为U盘启动2.进入微pe系统3.然后点击界面最左下方的Windows图标4.点击windows密码选择对应用户名称修改&#xff1b; 1.进入电脑BIOS&#xff0c;设置电脑第一启动项为U盘启动 把u盘插到要清除密码的电脑&#xff0c;然后开机…

面试八股——Redis——分布式锁——Redisson

1.看门狗机制 注意看门狗机制&#xff1a;redisson会监听持有锁的线程&#xff0c;并每隔一段时间(releaseTime/3&#xff0c;默认releaseTime为30s)&#xff0c;如果线程还未释放锁的话&#xff0c;会给锁做一次续期。 2. 主从一致性 实际开发中我们会搭建多台redis服务器&a…

【数据结构】非线性结构——二叉树

文章目录 前言1.树型结构1.1树的概念1.2树的特性1.3树的一些性质1.4树的一些表示形式1.5树的应用2.二叉树 2.1 概念2.2 两种特殊的二叉树2.3 二叉树的性质2.4 二叉树的存储2.5 二叉树的基本操作 前言 前面我们都是学的线性结构的数据结构&#xff0c;接下来我们就需要来学习非…

安防监控视频汇聚平台EasyCVR在银河麒麟V10系统中的启动异常及解决方法

安防监控视频平台EasyCVR具备较强的兼容性&#xff0c;它可以支持国标GB28181、RTSP/Onvif、RTMP&#xff0c;以及厂家的私有协议与SDK&#xff0c;如&#xff1a;海康ehome、海康sdk、大华sdk、宇视sdk、华为sdk、萤石云sdk、乐橙sdk等。平台兼容性强&#xff0c;支持Windows系…

密码学及其应用1 —— 密码学概述

1 密码学的基本概念 1.1 网络安全的定义 网络安全是网络领域的一个专业领域&#xff0c;它涵盖了在基础计算机网络基础设施中所采取的措施、网络管理员为保护网络及网络可访问资源免受未授权访问而采纳的政策&#xff0c;以及对其有效性&#xff08;或无效性&#xff09;的持续…

WSL2 设置桥接模式

文章目录 一、前言二、准备阶段三、环境配置3.1 Type-V管理器环境配置3.2 新增.wslconfig 文件 四、遇到的问题以及解决方案 一、前言 ​ 使用 wsl 的过程中&#xff0c;会出现 WSL 的IP地址 找不到&#xff0c;或者无法和计算机通讯&#xff0c;搞 嵌入式 的话&#xff0c;还…

基于nodejs+vue智能菜谱推荐系统python-flask-django-php

本文拟采用nodejs技术和express 搭建系统框架&#xff0c;后台使用MySQL数据库进行信息管理&#xff0c;设计开发的智能菜谱推荐系统。通过调研和分析&#xff0c;系统拥有管理员和用户两个角色&#xff0c;主要具备登录注册、个人信息修改、对用户管理、类型管理、菜谱信息管理…

力扣算题【第二期】

文章目录 1.反转链表1.1 算法题目1.2 算法思路1.3 代码实现 2.回文链表2.1 算法题目2.2 算法思路2.3 代码实现 1.反转链表 1.1 算法题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 1.2 算法思路 1.设置工作指针p,来遍历链表。 2.采…

常用中间件redis,kafka及其测试方法

常用消息中间件及其测试方法 一、中间件的使用场景引入中间件的目的一般有两个&#xff1a;1、提升性能常用的中间件&#xff1a;1) 高速缓存&#xff1a;redis2) 全文检索&#xff1a;ES3) 存日志&#xff1a;ELK架构4) 流量削峰&#xff1a;kafka 2、提升可用性产品架构中高可…

我在京东做数据分析,一位京东数据分析师的工作日常

有人说&#xff1a;“种下一棵树最好的时间是十年前&#xff0c;其次是现在”。任何时候&#xff0c;我们都应该抓住机遇&#xff0c;说不定就是改变你现状的一个机会。 2020年&#xff0c;我在疫情得到控制后&#xff0c;面试入职京东大数据组&#xff0c;截止目前&#xff0…

elasticsearch+kibana安装部分问题:

1.elasticsearch启动问题&#xff1a; 如果elasticsearch开启https登录则第一次启动的时候需要前台启动&#xff0c;前台启动的时候会自己创建相应的token等登录信息,如果是后台启动则没有这些登录信息&#xff1a; ./elasticsearch ━━━━━━━━━━━━━━━━━━━…

web前端之3D标签动画、指定范围的随机数、动态设置css变量、文档片段对象、反向动画

MENU 效果图htmlJavaScriptstyle 效果图 html <div class"container"></div>JavaScript // 祝词 var words [健康码常绿,股票飙红,生意兴隆,财源广进,心想事成,永远十八,身体健康,大富大贵,大吉大利,万事如意,美梦成真,吉祥如意,鸿运当头,五福临门,吉…

flask_restful规范返回值之类型设置

大型的互联网项目中&#xff0c;返回的数据格式&#xff0c;有时是比较复杂的结构。 如&#xff1a;豆瓣电影 https://movie.douban.com/j/chart/top_list?type24&interval_id 100%3A90&action&start20&limit20 返回的值里有 json 或者列表数据&#xff0c…

HC-RS04超声波模块测速

1.硬件接线 电源3.3v~5v; 一个触发信号&#xff0c;3.3伏20us的脉冲。 一个接收&#xff0c;为脉冲的宽度&#xff0c;也就是高电平时间。 2.距离计算 距离音速x时间/2&#xff1b; D340m/s *Th /2,Th:为高电平时间。 距离范围&#xff1a;2~400cm 代码比较简单&#xff0c;就…

第十二届蓝桥杯物联网试题(省赛)

思路&#xff1a; 这个考了一个RTC的配置&#xff0c;RTC我只配过一次&#xff0c;所以有些生疏&#xff0c;还是不能大意&#xff0c;一些偏僻的考点还是要多练&#xff0c;在获取RTC时间的时候也遇到一些bug,这个后续会用一篇博客将最近遇到的BUG都总结一下 主要的难点还是…

RPA-财务对账邮件应用自动化(客户对账机器人)

《财务对账邮件应用自动化》&#xff0c;将会使用邮箱的SMTP服务&#xff0c;小北把资源包绑定在这篇博客了 Uibot (RPA设计软件)———机器人的小项目友友们可以参考小北的课前材料五博客~ (本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff09; …

Knative 助力 XTransfer 加速应用云原生 Serverless 化

作者&#xff1a;元毅 公司介绍 XTransfer 是一站式外贸企业跨境金融和风控服务公司&#xff0c;致力于帮助中小微企业大幅降低全球展业的门槛和成本&#xff0c;提升全球竞争力。公司连续7年专注 B2B 外贸金融服务&#xff0c;已成为中国 B2B 外贸金融第一平台&#xff0c;目…

服务端应用多级缓存架构方案

服务端应用多级缓存架构方案 场景 20w的QPS的场景下&#xff0c;服务端架构应如何设计&#xff1f; 常规解决方案 可使用分布式缓存来抗&#xff0c;比如redis集群&#xff0c;6主6从&#xff0c;主提供读写&#xff0c;从作为备&#xff0c;不提供读写服务。1台平均抗3w并…

政安晨:【TensorFlow与Keras实战演绎机器学习】专栏 —— 目录

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎机器学习 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 本篇是作者政安晨的专栏《TensorFlow与Keras…

电源模块 YULIN俞霖科技DC/DC电源模块 直流升压 高压稳压

Features 最低工作电压&#xff1a;0.7V电压隔离&#xff1a;1000VDC /3000VDC 平均无故障时间&#xff1a; > 800,000 小时短路与电弧保护无最低负载要求&#xff1a;可空载工作输入电压&#xff1a;5、12、15、24VDCOutput 100,200、300、400、500 、600、800、 1000、1…