ES升级--04--SpringBoot整合Elasticsearch

news2024/11/17 7:48:33

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • SpringBoot整合Elasticsearch
    • 1.建立项目
    • 2.Maven 依赖
        • [ES 官方网站:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.8/index.html](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.8/index.html)
    • 3. pom配置
    • 4.证书文件elastic-certificates.p12 拷贝
        • 证书文件elastic-certificates.p12需拷贝到所有ES节点对应的目录下
    • 5.配置类 ElasticsearchConfig
    • 6.nacos配置参数
    • 7.测试
      • 1.TransportClient
      • 2.ElasticsearchTemplate
      • 3.RestHighLevelClient
      • 4.ElasticsearchRestTemplate


SpringBoot整合Elasticsearch

1.建立项目

在这里插入图片描述
在这里插入图片描述

2.Maven 依赖

进入到 ES 官方网站

ES 官方网站:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.8/index.html

在这里插入图片描述

  • 可以看到有低级和 高级的 Rest Client

在这里插入图片描述

3. pom配置

基于 springboot 2.1.7.RELEASE

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
 <!-- ES -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.8.23</version>
            <exclusions>
                <exclusion>
                    <groupId>org.elasticsearch.client</groupId>
                    <artifactId>transport</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.elasticsearch.client</groupId>
                    <artifactId>elasticsearch-rest-client</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.elasticsearch</groupId>
                    <artifactId>elasticsearch</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>transport</artifactId>
            <version>6.8.23</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.8.23</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>6.8.23</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.plugin</groupId>
            <artifactId>transport-netty4-client</artifactId>
            <version>6.8.23</version>
        </dependency>
        <!-- Elasticsearch客户端依赖版本升级到6.8.32 新增x-pack依赖-->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>x-pack-transport</artifactId>
            <version>6.8.23</version>
        </dependency>

4.证书文件elastic-certificates.p12 拷贝

证书文件elastic-certificates.p12需拷贝到所有ES节点对应的目录下
  • 注意:只需创建一次证书并将其复制到所有节点。

在这里插入图片描述

5.配置类 ElasticsearchConfig

支持x-pack 密码验证

/**
 * ES 配置 -----Elasticsearch 6.8.23
 * 通过实现配置配,初始化安全Elasticsearch客户端对象,包括ElasticsearchTemplate和RestHighLevelClient两者客户端类
 * 支持x-pack 密码验证
 */

@Slf4j
@Configuration
public class SecureElasticsearchConfig {


    //用户名 elastic
    @Value("${elasticsearch.xpack.username}")
    private String xpackUsername = "elastic";
    //用户密码
    @Value("${elasticsearch.xpack.password}")
    private String xpackrPassword;

    //证书路径  "/home/data/es"
    @Value("${elasticsearch.xpack.kspath}")
    private String certPath;
    //证书密码  ""
    @Value("${elasticsearch.xpack.kspwd}")
    private String certPassword;

    //集群名
    @Value("${elasticsearch.master.cluster-name}")
    private String masterClusterName;
    //节点名
    @Value("${elasticsearch.master.clusterNodes}")
    private String clusterNodes;
    //ip
    @Value("${elasticsearch.master.address}")
    private String masterAddress;
    //端口
    @Value("${elasticsearch.master.port}")
    private Integer masterPort;

//    // es 连接超时时间
//    private int connectTimeOut;
//    // es socket 连接超时时间
//    private int socketTimeOut;
//    // es 请求超时时间
//    private int connectionRequestTimeOut;
//    // es 最大连接数
//    private int maxConnectNum;
//    // es 每个路由的最大连接数
//    private int maxConnectNumPerRoute;



    /**
     *集群配置
     */
    private Settings settings() {
        Settings.Builder builder = Settings.builder();
        //基础配置
        builder.put("cluster.name", masterClusterName);
        builder.put("xpack.security.user", xpackUsername+ ":" + xpackrPassword);
        // Keystore 配置
        builder.put("xpack.security.transport.ssl.keystore.path", certPath);
        builder.put("xpack.security.transport.ssl.keystore.password", certPassword);
        // Truststore 配置
        builder.put("xpack.security.transport.ssl.truststore.path", certPath);
        builder.put("xpack.security.transport.ssl.truststore.password", certPassword);
        // 验证模式配置
        builder.put("xpack.security.transport.ssl.verification_mode", "certificate");
        // 启用 X-Pack 安全功能
        builder.put("xpack.security.enabled", true);
        builder.put("xpack.security.transport.ssl.enabled", true);
        return builder.build();
    }

    /**
     * 初始化安全TransportClient类
     */
    @Bean
    public TransportClient transportClient() throws Exception {

        //本地测试用
        certPath="D:\\cdms\\es\\elastic-certificates.p12";
        log.info(">>>>>>>>>>> SecureElasticsearchConfig PreBuiltXPackTransportClient 开始初始化");
        Settings settings = settings();
        PreBuiltXPackTransportClient client = new PreBuiltXPackTransportClient(settings);
        client.addTransportAddress(new TransportAddress(InetAddress.getByName(masterAddress), masterPort));
        return client;
    }

    /**
     *初始化安全ElasticsearchTemplate类
     * 基于 spring-boot-starter-data
     */
    @Bean
    public ElasticsearchTemplate elasticsearchTemplate(@Autowired TransportClient transportClient) throws Exception {
        log.info(">>>>>>>>>>> SecureElasticsearchConfig ElasticsearchTemplate 开始初始化");
        ElasticsearchTemplate secureElasticsearchTemplate;
        try {
            secureElasticsearchTemplate = new ElasticsearchTemplate(transportClient);
            return secureElasticsearchTemplate;
        } catch (Exception e) {
            log.error("SecureElasticsearchConfig  初始化ElasticsearchTemplate报错: ", e.getMessage());
            throw e;
        }
    }



    /**
     * 初始化安全RestHighLevelClient类
     * 只支持http  端口: 9200
     */
    @Bean
    public RestHighLevelClient restHighLevelClient() {
        log.info(">>>>>>>>>>> SecureElasticsearchConfig RestHighLevelClient 开始初始化");
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();

        credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(xpackUsername, xpackrPassword));

        RestClientBuilder builder = RestClient.builder(new HttpHost(masterAddress,9200))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
                        return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    }
                });
        RestHighLevelClient client = new RestHighLevelClient(builder);

//        // 连接延时配置
//        builder.setRequestConfigCallback(requestConfigBuilder -> {
//            requestConfigBuilder.setConnectTimeout(connectTimeOut);
//            requestConfigBuilder.setSocketTimeout(socketTimeOut);
//            requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
//            return requestConfigBuilder;
//        });
//        // 连接数配置
//        builder.setHttpClientConfigCallback(httpClientBuilder -> {
//                    httpClientBuilder.setMaxConnTotal(maxConnectNum);
//                    httpClientBuilder.setMaxConnPerRoute(maxConnectNumPerRoute);
//                    httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
//                    return httpClientBuilder;
//        });


        return client;
    }

    /**
     *初始化安全ElasticsearchRestTemplate类
     * 基于 spring-boot-starter-data
     */
    @Bean
    ElasticsearchRestTemplate elasticsearchRestTemplate(@Autowired RestHighLevelClient restHighLevelClient) {
        return new ElasticsearchRestTemplate(restHighLevelClient);
    }

}

6.nacos配置参数

elasticsearch:
  xpack:
    username: elastic
    password: escdms
    kspath: /home/data/es
    kspwd: 
  master:
    cluster-name: gz-java-test-laas
    clusterNodes: master-test-laas
    address: 192.168.2.89
    port: 9300

7.测试

1.TransportClient

 @Autowired
    private  TransportClient transportClient;


    @Test
    public void createIndex_transportClient() {
        String indexName="lass_test_transportclient";

        try {
            CreateIndexRequest request = new CreateIndexRequest(indexName);
            // 可以在此处添加更多设置,例如映射 (mapping) 和设置 (settings)

            CreateIndexResponse response = transportClient.admin().indices().create(request).actionGet();
            if (response.isAcknowledged()) {
                System.out.println("Index created successfully: " + indexName);
            } else {
                System.out.println("Index creation failed: " + indexName);
            }
        } catch (Exception e) {
            System.err.println("Error creating index: " + e.getMessage());
        }

    }



    @Test
    public void addDocuments_transportClient() {
        String indexName = "lass_test_transportclient";

        try {


            String json1 = "{" +
                    "\"user\":\"kimchy\"," +
                    "\"postDate\":\"2013-01-30\"," +
                    "\"message\":\"trying out Elasticsearch\"" +
                    "}";

            IndexResponse response1 = transportClient.prepareIndex(indexName, "_doc")
                    .setSource(json1, XContentType.JSON)
                    .get();


//            if (response1.status() == RestStatus.CREATED) {
//                System.out.println("Document 1 indexed successfully.");
//            } else {
//                System.out.println("Failed to index Document 1.");
//            }

            String json2 = "{" +
                    "\"user\":\"Tom\"," +
                    "\"postDate\":\"2024-01-30\"," +
                    "\"message\":\"lass升级 transportClient \"" +
                    "}";

            transportClient.prepareIndex(indexName, "_doc")
                    .setSource(json2, XContentType.JSON)
                    .get();

        } catch (Exception e) {
            System.err.println("Error adding documents: " + e.getMessage());
        }
    }





    @Test
    public void deleteIndex_transportClient() {
        String indexName = "lass_test_transportclient";

        try {
            DeleteIndexRequest request = new DeleteIndexRequest(indexName);
            AcknowledgedResponse response = transportClient.admin().indices().delete(request).actionGet();
            if (response.isAcknowledged()) {
                System.out.println("Index deleted successfully: " + indexName);
            } else {
                System.out.println("Failed to delete index: " + indexName);
            }
        } catch (Exception e) {
            System.err.println("Error deleting index: " + e.getMessage());
        }
    }
GET lass_test_transportclient/_search
{
  "query":{
    "match_all" : {}
  }
}

在这里插入图片描述

2.ElasticsearchTemplate

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Document(indexName = "lass_test_people",type = "_doc",shards = 1,replicas = 1)
public class People {
    @Id
    private String id;
    // 整个name不被分词,切不创建索引
    // Keyword表示不被分词
    @Field(type= FieldType.Keyword,index = false)
    private String name;
    // address被ik分词
    // Text类型的属性才能被分词
    @Field(type = FieldType.Text)
    private String address;

    @Field(type = FieldType.Long,index = false)
    private int age;

}
 @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Test
    public void createIndex_elasticsearchTemplate() {

        //根据实体类创建索引,
        boolean result1 = elasticsearchTemplate.createIndex(People.class);
        System.out.println(result1);
        //将索引放到软件里面
        boolean results = elasticsearchTemplate.putMapping(People.class);

    }




    @Test
    public void addDocuments_elasticsearchTemplate() {

        People peo = new People();
        peo.setId("123");
        peo.setName("张三");
        peo.setAddress("北京市海淀区回龙观东大街");
        peo.setAge(18);

        IndexQuery query = new IndexQuery();
        query.setObject(peo);

        String result = elasticsearchTemplate.index(query);
        System.out.println(result);
    }

    @Test
    public void bulk(){
        List<IndexQuery> list = new ArrayList<>();
        // IndexQuery多行写法
        IndexQuery indexQuery = new IndexQuery();
        indexQuery.setObject(new People("1", "王五", "北京东城", 12));
        list.add(indexQuery);
        // IndexQuery 连缀写法
        list.add(new IndexQueryBuilder().withObject(new People("2", "赵六", "北京西城", 13)).build());
        list.add(new IndexQueryBuilder().withObject(new People("3", "吴七", "北京昌平", 14)).build());
        elasticsearchTemplate.bulkIndex(list);
    }


    @Test
    public void deletee_elasticsearchTemplate() {
        boolean result = elasticsearchTemplate.deleteIndex(People.class);
        System.out.println(result);
    }

在这里插入图片描述

3.RestHighLevelClient

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Document(indexName = "lass_test_student",type = AudienceEsConst.DOC, createIndex = false, useServerConfiguration = true)
public class Student {
    @Id
    private String id;
    // 整个name不被分词,切不创建索引
    // Keyword表示不被分词
    @Field(type= FieldType.Keyword,index = false)
    private String name;
    // address被ik分词
    // Text类型的属性才能被分词
    @Field(type = FieldType.Text)
    private String address;

    @Field(type = FieldType.Long,index = false)
    private int age;

}
 @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void createIndex_restHighLevelClient() throws IOException {
        String indexName = "lass_test_resthighlevelclient";

        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.field("user", "zhangSan");
            builder.timeField("postDate", new Date());
            builder.field("message", "laas 升级 RestHighLevelClient ");
        }

        builder.endObject();
        IndexRequest request = new IndexRequest(indexName, "doc").source(builder);

        IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);

            if (indexResponse.status() == RestStatus.CREATED) {
                System.out.println("Document 1 indexed successfully.");
            } else {
                System.out.println("Failed to index Document 1.");
            }

    }



    @Test
    public void addDocuments_restHighLevelClient() {
        String indexName = "lass_test_resthighlevelclient";

        try {
            Map<String, Object> jsonMap = new HashMap<>();
            jsonMap.put("user", "李四");
            jsonMap.put("postDate", new Date());
            jsonMap.put("message", "laas 升级 RestHighLevelClient ");
            IndexRequest indexRequest = new IndexRequest(indexName,"doc").source(jsonMap);
            IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);

            if (indexResponse.status() == RestStatus.CREATED) {
                System.out.println("Document 1 indexed successfully.");
            } else {
                System.out.println("Failed to index Document 1.");
            }

        } catch (Exception e) {
            System.err.println("Error adding documents: " + e.getMessage());
        }
    }



    @Test
    public void deletee_restHighLevelClient() {
        String indexName = "lass_test_resthighlevelclient";
        boolean result = elasticsearchTemplate.deleteIndex(indexName);
        System.out.println(result);
    }

4.ElasticsearchRestTemplate

 @Autowired
    private  ElasticsearchRestTemplate  restTemplate;

    @Test
    public void createIndex_restTemplate() {

        //根据实体类创建索引,
        boolean result1 = restTemplate.createIndex(Student.class);
        System.out.println(result1);
        //将索引放到软件里面
        boolean results = restTemplate.putMapping(Student.class);

    }

    @Test
    public void addDocuments_restTemplate() {

        Student student = new Student();
        student.setId("123");
        student.setName("张三");
        student.setAddress("北京市海淀区回龙观东大街");
        student.setAge(18);

        IndexQuery query = new IndexQuery();
        query.setObject(student);

        String result = restTemplate.index(query);
        System.out.println(result);
    }

    @Test
    public void bulk_restTemplate(){
        List<IndexQuery> list = new ArrayList<>();
        // IndexQuery多行写法
        IndexQuery indexQuery = new IndexQuery();
        indexQuery.setObject(new Student("1", "王五", "北京东城", 12));
        list.add(indexQuery);
        // IndexQuery 连缀写法
        list.add(new IndexQueryBuilder().withObject(new Student("2", "赵六", "北京西城", 13)).build());
        list.add(new IndexQueryBuilder().withObject(new Student("3", "吴七", "北京昌平", 14)).build());
        restTemplate.bulkIndex(list);
    }


    @Test
    public void deletee_restTemplate() {
        boolean result = restTemplate.deleteIndex(Student.class);
        System.out.println(result);
    }

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

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

相关文章

C++ vector 模拟实现

vector的底层也是一个动态数组&#xff0c;他与 string 的区别就是&#xff0c;string 是专门用来存储字符类数据的&#xff0c;为了兼容C语言&#xff0c;使用C语言的接口&#xff0c;在string的动态数组内都会都开一块空间用来存 \0 &#xff0c;而vector则不会。 首先我们要…

水电收费远程抄表

1.前言&#xff1a;从传统到现代的改变 水电收费远程抄表&#xff0c;是科学技术在公共服务领域的一次重要运用&#xff0c;它改变了过去人力上门服务抄表的传统模式&#xff0c;提高了高效率&#xff0c;降低了偏差&#xff0c;为群众与企业带来了极大的便利。这种系统运用智…

富途面试题:用面向对象的思想设计人关门的场景

我工作两年后&#xff0c;有一次不成功的富途证券的面试&#xff0c;印象非常深刻&#xff0c;面试官提出了一个看似简单实则充满深意的问题&#xff1a;如何用面向对象的思想设计一个人关门的场景&#xff1f; 我当时是这样设计的&#xff0c;创建两个类&#xff1a;Person和D…

Linux命令那么多,先来一篇文件和目录管理命令!

&#x1f4a1;本文建议大家收藏&#xff01; 文件和目录管理命令 1. ls - 列出目录内容 ls命令是Linux中最常用的命令之一&#xff0c;用于列出目录中的文件和子目录。 ls显示当前目录下的所有文件和目录。 ls -l以长格式列出目录内容&#xff0c;显示文件权限、所有者、大…

云途探索——移动云云日志接入实践

目录 1 前言2 新手入门2.1 前置条件2.2. 配置采集对象及规则2.3 安装Agent2.4 日志管理 3 使用场景3.1 优势3.2 应用场景 4 总结 1 前言 随着人工智能、大数据、物联网以及云计算时代的到来&#xff0c;在日志数据量持续爆增、日志数据日益多样化的今天&#xff0c;传统日志服…

Java(六)——抽象类与接口

文章目录 抽象类和接口抽象类抽象类的概念抽象类的语法抽象类的特性抽象类的意义 接口接口的概念接口的语法接口的特性接口的使用实现多个接口接口与多态接口间的继承抽象类和接口的区别 抽象类和接口 抽象类 抽象类的概念 Java使用类实例化对象来描述现实生活中的实体&…

[数据集][图像分类]家庭场景下的家具分类数据集1010张101类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;1010 分类类别数&#xff1a;101 类别名称:[“bath_bath”,“bath_heated_t…

java版CRM客户关系管理系统源码-CRM客户关系管理系统的技术架构与功能实现

CRM客户关系管理系统的技术架构与功能实现 一、引言 随着市场竞争的日益激烈&#xff0c;客户关系管理&#xff08;CRM&#xff09;已成为企业赢得市场、提升客户满意度、促 进业务增长的关键手段。本文旨在介绍一款先进的CRM客户关系管理系统的技术架构与功能实现&#xff0…

C++:类的内存分布

类的成员变量和方法是分开存储的&#xff0c;内存给类实例化出的对象开辟空间时只开辟成员变量所占用的空间。类中的所有方法&#xff08;成员函数&#xff09;都会放在代码区&#xff0c;所以类的大小一般只计算类中成员变量的对齐之后大小的综合&#xff08;如果没有虚函数的…

Java设计模式 _行为型模式_观察者模式

一、观察者模式 1、观察者模式 观察者模式 ( Observer Pattern )是一种行为型模式。 常用于对象间存在一对多关系时&#xff0c;比如&#xff0c;当一个对象被修改时&#xff0c;需要自动通知它的依赖对象。 2、实现思路 &#xff08;1&#xff09;、定义被观察者的行为&…

ETLCloud中如何执行SQL脚本

SQL脚本 在数据库管理与数据分析的广阔领域中&#xff0c;SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;脚本扮演着举足轻重的角色。作为一门专为关系型数据库设计的编程语言&#xff0c;SQL不仅能够执行数据的检索、更新、插入及删除等基…

算法与数据结构:二叉排序树与AVL树

ACM大牛带你玩转算法与数据结构-课程资料 本笔记属于船说系列课程之一&#xff0c;课程链接&#xff1a; 哔哩哔哩_bilibilihttps://www.bilibili.com/cheese/play/ep66799?csourceprivate_space_class_null&spm_id_from333.999.0.0 你也可以选择购买『船说系列课程-年度会…

便携式应急气象站:应急气象监测装备

TH-BQX5便携式应急气象站&#xff0c;作为现代气象监测的重要装备&#xff0c;以其独特的便携性、高效性和灵活性&#xff0c;在应急气象监测领域发挥着至关重要的作用。这类气象站不仅为灾害预警、环境保护、农业生产等多个领域提供了实时、准确的气象数据&#xff0c;还在突发…

uniapp通过Canvas绘制网格(心电图,坐标纸等可用)

本篇文档是Canvas绘制心电图的第一个部分&#xff0c;想了解详情的可以关注后学习交流。 心电图的最底层需要一个网状底层&#xff0c;来方便进行数据的测量。 一、白底分大、中、小三个区域的网格 1、首先是HTML部分 <!DOCTYPE html> <html lang"en">…

DNS设置(linux)

1.配置dns需要现在/etc/sysconfig/network-scripts/目录下的ifcfg-ens33(后面数字也可能是其他的)中配置DNS 2.编辑/etc/resolv.conf文件&#xff0c;将上面网卡中加的dns服务器ip添加到此文件 vi /etc/resolv.conf重启网络配置 service network restart常用的dns的ip 国内…

qt中实现多语言功能

qt中实现多语言功能 原理&#xff1a; 其本质就是生成ts文件&#xff0c;然后使用Linguist软件手工翻译&#xff0c;再生成qm文件&#xff0c;最后在主程序的开始加载不同的qm文件&#xff0c;实现多语言。 步骤&#xff1a; 修改程序文件 在pro文件中加入说明 TRANSLATI…

通讯录恢复怎么办?保护珍贵联系信息的2个必备技能!

手机通讯录扮演着重要的角色&#xff0c;它不仅仅是一个简单的联系方式列表&#xff0c;更是我们与亲朋好友、同事、业务伙伴等之间关系的见证。万一不慎丢失或误删通讯录&#xff0c;学会通讯录恢复的技能变得非常重要。本文将为你介绍几种保护珍贵联系信息的必备技能&#xf…

这样写代码太优雅了吧

文章目录 优化案例初次优化再次优化看看Spring源码的处理 优化案例 假设一个场景&#xff0c; 开发代码时&#xff0c;需要对类中的方法进行遍历&#xff0c;判断有没有注解NotNull&#xff0c;暂时没有合适的工具类&#xff0c;需要自己手搓一个。 无须多想&#xff0c;分分钟…

从GPT-3.5到GPT-4O:探索AI的进化之旅,哪一版更懂你?

如何评价GPT-4o? 最新的GPT-4O&#xff0c;被誉为GPT-4的增强版。它在保持前代产品优秀性能的基础上&#xff0c;大幅降低了使用成本&#xff0c;使得更多的普通用户也能享受到顶尖AI的服务。GPT-4O在非英语语言处理上的强化&#xff0c;更是让其在全球范围内的适用性大大提高…

使用Java和XxlCrawler获取各城市月度天气情况实践

目录 前言 一、历史数据获取 1、关于天气后报 2、信息界面分析 二、数据的提取开发 1、PageVo的定义 2、属性定义 3、实际信息抓取 三、信息抓取调试以及可能的问题 1、信息获取成果 2、关于超时的问题 四、总结 前言 这篇文章主要来源于一个我们家小朋友的一个作业…