(十一)Springboot+ElasticSearch8整合

news2025/1/13 13:23:09

前言

在 Elasticsearch7.15版本之后,Elasticsearch官方将它的高级客户端 RestHighLevelClient标记为弃用状态。推出全新的 Java API客户端 Elasticsearch Java API Client,该客户端也将在 Elasticsearch8.0及以后版本中成为官方推荐使用的客户端。

1.导入ES依赖

        <!--es搜索-->
		<dependency>
			<groupId>co.elastic.clients</groupId>
			<artifactId>elasticsearch-java</artifactId>
			<version>8.1.3</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.13.3</version>
		</dependency>

出现报错 java.lang.NoClassDefFoundError: jakarta/json/JsonException导入下面依赖

    <dependency>
		<groupId>jakarta.json</groupId>
		<artifactId>jakarta.json-api</artifactId>
		<version>2.0.1</version>
	</dependency>

2.增加配置文件

// 配置的前缀
@ConfigurationProperties(prefix = "elasticsearch") 
@Configuration
public class ESClientConfig {

	/**
	 * 多个IP逗号隔开
	 */
	@Setter
	private String hosts;

	/**
	 * 同步方式
	 * 
	 * @return
	 */
	@Bean
	public ElasticsearchClient elasticsearchClient() {
		HttpHost[] httpHosts = toHttpHost();
		// Create the RestClient 
		RestClient restClient = RestClient.builder(httpHosts).build();
		// Create the transport with a Jackson mapper
		RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
		// create the API client
		return new ElasticsearchClient(transport);
	}

	/**
	 * 异步方式
	 * 
	 * @return
	 */
	@Bean
	public ElasticsearchAsyncClient elasticsearchAsyncClient() {
		HttpHost[] httpHosts = toHttpHost();
		RestClient restClient = RestClient.builder(httpHosts).build();
		RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
		return new ElasticsearchAsyncClient(transport);
	}

	/**
	 * 解析配置的字符串hosts,转为HttpHost对象数组
	 *
	 * @return
	 */
	private HttpHost[] toHttpHost() {
		if (!StringUtils.hasLength(hosts)) {
			throw new RuntimeException("invalid elasticsearch configuration. elasticsearch.hosts不能为空!");
		}

		// 多个IP逗号隔开
		String[] hostArray = hosts.split(",");
		HttpHost[] httpHosts = new HttpHost[hostArray.length];
		HttpHost httpHost;
		for (int i = 0; i < hostArray.length; i++) {
			String[] strings = hostArray[i].split(":");
			httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]), "http");
			httpHosts[i] = httpHost;
		}

		return httpHosts;
	}

}

增加配置文件配置es访问的地址和端口

elasticsearch:
  hosts: 172.16.5.10:9200

3.测试

注入 ElasticsearchClient添加studyes索引

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DatacenterApplication.class)
@Slf4j
public class ESTest {

    @Autowired
    private ElasticsearchClient client;

    @Test
    public void createidx() throws IOException {
        CreateIndexResponse response = client.indices().create(c -> c.index("studyes"));
        log.info("createIndex方法,acknowledged={}", response.acknowledged());
    }
}

可以看到 studyes 索引已经添加
在这里插入图片描述

索引操作

接口

public interface IndexService {

	/**
	 * 新建索引,指定索引名称
	 * 
	 * @param name
	 * @throws IOException
	 */
	void createIndex(String name) throws IOException;

	/**
	 * 创建索引,指定索引名称和setting和mapping
	 *
	 * @param name
	 *            - 索引名称
	 * @param settingFn
	 *            - 索引参数
	 * @param mappingFn
	 *            - 索引结构
	 * @throws IOException
	 */
	void createIndex(String name, Function<IndexSettings.Builder, ObjectBuilder<IndexSettings>> settingFn,
			Function<TypeMapping.Builder, ObjectBuilder<TypeMapping>> mappingFn) throws IOException;

	/**
	 * 删除索引
	 *
	 * @param name
	 * @throws IOException
	 */
	void deleteIndex(String name) throws IOException;

	/**
	 * 修改索引字段信息 <br/>
	 * 字段可以新增,已有的字段只能修改字段的 search_analyzer 属性。
	 * 
	 * @param name
	 *            - 索引名称
	 * @param propertyMap
	 *            - 索引字段,每个字段都有自己的property
	 * @throws IOException
	 */
	void updateIndexProperty(String name, HashMap<String, Property> propertyMap) throws IOException;

	/**
	 * 查询索引列表
	 * 
	 * @return
	 * @throws IOException
	 */
	GetIndexResponse getIndexList() throws IOException;

	/**
	 * 查询索引详情
	 *
	 * @param name
	 * @return
	 * @throws IOException
	 */
	GetIndexResponse getIndexDetail(String name) throws IOException;

	/**
	 * 检查指定名称的索引是否存在
	 * 
	 * @param name
	 * @return - true:存在
	 * @throws IOException
	 */
	boolean indexExists(String name) throws IOException;

}

实现类

@Service
@Slf4j
public class IndexServiceImpl implements IndexService {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Override
    public void createIndex(String name) throws IOException {
        //ApplicationContext applicationContext;
        CreateIndexResponse response = elasticsearchClient.indices().create(c -> c.index(name));
        log.info("createIndex方法,acknowledged={}", response.acknowledged());
    }

    @Override
    public void createIndex(String name,
                       Function<IndexSettings.Builder, ObjectBuilder<IndexSettings>> settingFn,
                       Function<TypeMapping.Builder, ObjectBuilder<TypeMapping>> mappingFn) throws IOException {
        CreateIndexResponse response = elasticsearchClient
                .indices()
                .create(c -> c
                        .index(name)
                        .settings(settingFn)
                        .mappings(mappingFn)
                );
        log.info("createIndex方法,acknowledged={}", response.acknowledged());
    }

    @Override
    public void deleteIndex(String name) throws IOException {
        DeleteIndexResponse response = elasticsearchClient.indices().delete(c -> c.index(name));
        log.info("deleteIndex方法,acknowledged={}", response.acknowledged());
    }

    @Override
    public void updateIndexProperty(String name, HashMap<String, Property> propertyMap) throws IOException {
        PutMappingResponse response = elasticsearchClient.indices()
                .putMapping(typeMappingBuilder ->
                                typeMappingBuilder
                                .index(name)
                                .properties(propertyMap)
        );
        log.info("updateIndexMapping方法,acknowledged={}", response.acknowledged());
    }

    @Override
    public GetIndexResponse getIndexList() throws IOException {
        //使用 * 或者 _all都可以
        GetIndexResponse response = elasticsearchClient.indices().get(builder -> builder.index("_all"));
        log.info("getIndexList方法,response.result()={}", response.result().toString());
        return response;
    }

    @Override
    public GetIndexResponse getIndexDetail(String name) throws IOException {
        GetIndexResponse response = elasticsearchClient.indices().get(builder -> builder.index(name));
        log.info("getIndexDetail方法,response.result()={}", response.result().toString());
        return response;
    }

    @Override
    public boolean indexExists(String name) throws IOException {
        return elasticsearchClient.indices().exists(b -> b.index(name)).value();
    }
  }

测试类

    @Autowired
    private IndexService indexService;

    @Test
    public void testCreateIndex() throws Exception {
        String indexName = "db_api_idx1";
        indexService.createIndex(indexName);

        //Assertions.assertTrue(indexService.indexExists(indexName));
        //indexService.createIndex(indexName);
        //Assertions.assertFalse(indexService.indexExists(indexName));
    }

    @Test
    public void testCreateIndex2() throws Exception {
        // 索引名
        String indexName = "db_api_idx2";

        // 构建setting
        Function<IndexSettings.Builder, ObjectBuilder<IndexSettings>> settingFn = sBuilder -> sBuilder
                .index(iBuilder -> iBuilder
                        // 三个分片
                        .numberOfShards("3")
                        // 一个副本
                        .numberOfReplicas("1")
                );



        // 索引字段,每个字段都有自己的property
        Property keywordProperty = Property.of(pBuilder -> pBuilder.keyword(keywordPropertyBuilder -> keywordPropertyBuilder.ignoreAbove(256)));
        Property integerProperty = Property.of(pBuilder -> pBuilder.integer(integerNumberPropertyBuilder -> integerNumberPropertyBuilder));
        Property textProperty = Property.of(pBuilder -> pBuilder.text(tBuilder -> tBuilder));

        // 构建mapping
        Function<TypeMapping.Builder, ObjectBuilder<TypeMapping>> mappingFn = mBuilder -> mBuilder
                .properties("name", keywordProperty)
                .properties("age", integerProperty)
                .properties("description", textProperty);

        // 创建索引,并指定setting和mapping
        indexService.createIndex(indexName, settingFn, mappingFn);
    }

    @Test
    public void testIndexExists() throws Exception {
        String indexName = "db_api_idx1";
        System.out.println(indexService.indexExists(indexName));
    }

    @Test
    public void testUpdateIndexProperty() throws Exception {
        String indexName = "db_api_idx2";

        // 索引字段,每个字段都有自己的property
        Property keywordProperty = Property.of(pBuilder -> pBuilder.keyword(keywordPropertyBuilder -> keywordPropertyBuilder.ignoreAbove(1024)));
        Property integerProperty = Property.of(pBuilder -> pBuilder.integer(integerNumberPropertyBuilder -> integerNumberPropertyBuilder));
        Property textProperty = Property.of(pBuilder -> pBuilder.text(tBuilder -> tBuilder));

        HashMap<String, Property> propertyMap = new HashMap<>();
        propertyMap.put("name", keywordProperty);
        propertyMap.put("description", textProperty);
        propertyMap.put("address", textProperty);

        // 构建mapping
        indexService.updateIndexProperty(indexName, propertyMap);
    }

    @Test
    public void testGetIndexList() throws Exception {
        indexService.getIndexList();
    }

    @Test
    public void testGetIndexDetail() throws Exception {
        String indexName = "db_api_idx2";
        indexService.getIndexDetail(indexName);
    }

    @Test
    public void testDeleteIndex() throws Exception {
        String indexName = "db_api_idx1";
        indexService.deleteIndex(indexName);
    }

文档操作

接口

public interface DocumentDemoService {

    /**
     * 新增一个文档
     * @param idxName 索引名
     * @param idxId 索引id
     * @param document 文档对象
     * @return
     */
    IndexResponse createByFluentDSL(String idxName, String idxId, Object document) throws Exception;

    /**
     * 新增一个文档
     * @param idxName 索引名
     * @param idxId 索引id
     * @param document 文档对象
     * @return
     */
    IndexResponse createByBuilderPattern(String idxName, String idxId, Object document) throws Exception;

    /**
     * 用JSON字符串创建文档
     * @param idxName 索引名
     * @param idxId 索引id
     * @param jsonContent
     * @return
     */
    IndexResponse createByJson(String idxName, String idxId, String jsonContent) throws Exception;


    /**
     * 异步新增文档
     * @param idxName 索引名
     * @param idxId 索引id
     * @param document
     * @param action
     */
    void createAsync(String idxName, String idxId, Object document, BiConsumer<IndexResponse, Throwable> action);

    /**
     * 批量增加文档
     * @param idxName 索引名
     * @param documents 要增加的对象集合
     * @return 批量操作的结果
     * @throws Exception
     */
    BulkResponse bulkCreate(String idxName, List<Object> documents) throws Exception;


    /**
     * 根据文档id查找文档
     * @param idxName 索引名
     * @param docId 文档id
     * @return Object类型的查找结果
     * @throws Exception
     */
    Object getById(String idxName, String docId) throws IOException;

    /**
     * 根据文档id查找文档,返回类型是ObjectNode
     * @param idxName 索引名
     * @param docId 文档id
     * @return ObjectNode类型的查找结果
     */
    ObjectNode getObjectNodeById(String idxName, String docId) throws IOException;

    /**
     * 根据文档id删除文档
     * @param idxName 索引名
     * @param docId 文档id
     * @return Object类型的查找结果
     * @throws Exception
     */
    Boolean deleteById(String idxName, String docId) throws IOException;

    /**
     * 批量删除文档
     * @param idxName 索引名
     * @param docIds 要删除的文档id集合
     * @return
     * @throws Exception
     */
    BulkResponse bulkDeleteByIds(String idxName, List<String> docIds) throws Exception;

}

实现类

@Slf4j
@Service
public class DocumentDemoServiceImpl implements DocumentDemoService {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private ElasticsearchAsyncClient elasticsearchAsyncClient;

    @Override
    public IndexResponse createByFluentDSL(String idxName, String idxId, Object document) throws Exception {
        IndexResponse response = elasticsearchClient.index(idx -> idx
                .index(idxName)
                .id(idxId)
                .document(document));
        return response;
    }

    @Override
    public IndexResponse createByBuilderPattern(String idxName, String idxId, Object document) throws Exception {
        IndexRequest.Builder<Object> indexReqBuilder = new IndexRequest.Builder<>();

        indexReqBuilder.index(idxName);
        indexReqBuilder.id(idxId);
        indexReqBuilder.document(document);
        return elasticsearchClient.index(indexReqBuilder.build());
    }

    @Override
    public IndexResponse createByJson(String idxName, String idxId, String jsonContent) throws Exception {
        return elasticsearchClient.index(i -> i
                .index(idxName)
                .id(idxId)
                .withJson(new StringReader(jsonContent))
        );
    }

    @Override
    public void createAsync(String idxName, String idxId, Object document, BiConsumer<IndexResponse, Throwable> action) {
        elasticsearchAsyncClient.index(idx -> idx
                .index(idxName)
                .id(idxId)
                .document(document)
        ).whenComplete(action);
    }

    @Override
    public BulkResponse bulkCreate(String idxName, List<Object> documents) throws Exception {
        BulkRequest.Builder br = new BulkRequest.Builder();

        // TODO 可以将 Object定义为一个文档基类。比如 ESDocument类

        // 将每一个product对象都放入builder中
        //documents.stream()
        //        .forEach(esDocument -> br
        //                .operations(op -> op
        //                        .index(idx -> idx
        //                                .index(idxName)
        //                                .id(esDocument.getId())
        //                                .document(esDocument))));

        return elasticsearchClient.bulk(br.build());
    }

    @Override
    public Object getById(String idxName, String docId) throws IOException {
        GetResponse<Object> response = elasticsearchClient.get(g -> g
                        .index(idxName)
                        .id(docId),
                Object.class);
        return response.found() ? response.source() : null;
    }

    @Override
    public ObjectNode getObjectNodeById(String idxName, String docId) throws IOException {
        GetResponse<ObjectNode> response = elasticsearchClient.get(g -> g
                        .index(idxName)
                        .id(docId),
                ObjectNode.class);

        return response.found() ? response.source() : null;
    }

    @Override
    public Boolean deleteById(String idxName, String docId) throws IOException {
        DeleteResponse delete = elasticsearchClient.delete(d -> d
                .index(idxName)
                .id(docId));
        return delete.forcedRefresh();
    }

    @Override
    public BulkResponse bulkDeleteByIds(String idxName, List<String> docIds) throws Exception {
        BulkRequest.Builder br = new BulkRequest.Builder();

        // 将每一个对象都放入builder中
        docIds.stream().forEach(id -> br
                        .operations(op -> op
                                .delete(d -> d
                                        .index(idxName)
                                        .id(id))));

        return elasticsearchClient.bulk(br.build());
    }
}

测试类

private final static String INDEX_NAME = "db_api_idx_uservo";

    @Autowired
    private DocumentDemoService documentDemoService;


    @Test
    public void testCreateByFluentDSL() throws Exception {
        // 构建文档数据
        UserVO userVO = new UserVO();
        userVO.setId(1L);
        userVO.setUserName("赵云2");
        userVO.setAge(11);
        userVO.setCreateTime(new Date());
        userVO.setUpdateTime(new Date());
        userVO.setEmail("ss.com");
        userVO.setVersion(1);
        userVO.setHeight(12D);

        // 新增一个文档
        IndexResponse response = documentDemoService.createByFluentDSL(INDEX_NAME, userVO.getId().toString(), userVO);

        System.out.println("response.forcedRefresh() -> " + response.forcedRefresh());
        System.out.println("response.toString() -> " + response.toString());
    }

    @Test
    public void testCreateByBuilderPattern() throws Exception {
        // 构建文档数据
        UserVO userVO = new UserVO();
        userVO.setId(2L);
        userVO.setUserName("赵云2");
        userVO.setAge(12);
        userVO.setCreateTime(new Date());
        userVO.setUpdateTime(new Date());
        userVO.setEmail("ss.com");
        userVO.setVersion(1);
        userVO.setHeight(12D);

        // 新增一个文档
        IndexResponse response = documentDemoService.createByBuilderPattern(INDEX_NAME, userVO.getId().toString(), userVO);

        System.out.println("response.toString() -> " + response.toString());
    }

    @Test
    public void testCreateByJSON() throws Exception {
        // 构建文档数据
        UserVO userVO = new UserVO();
        userVO.setId(3L);
        userVO.setUserName("赵云3");
        userVO.setAge(13);
        userVO.setCreateTime(new Date());
        userVO.setUpdateTime(new Date());
        userVO.setEmail("ss.com");
        userVO.setVersion(1);
        userVO.setHeight(12D);

        // 新增一个文档
        IndexResponse response = documentDemoService.createByJson(INDEX_NAME, userVO.getId().toString(), JSON.toJSONString(userVO));

        System.out.println("response.toString() -> " + response.toString());
    }

    @Test
    public void testCreateAsync() throws Exception {
        // 构建文档数据
        UserVO userVO = new UserVO();
        userVO.setId(4L);
        userVO.setUserName("赵云4");
        userVO.setAge(14);
        userVO.setCreateTime(new Date());
        userVO.setUpdateTime(new Date());
        userVO.setEmail("ss.com");
        userVO.setVersion(1);
        userVO.setHeight(12D);

        documentDemoService.createAsync(INDEX_NAME, userVO.getId().toString(), userVO, new BiConsumer<>() {
            @Override
            public void accept(IndexResponse indexResponse, Throwable throwable) {
                // throwable必须为空
                Assertions.assertNull(throwable);
                // 验证结果
                System.out.println("response.toString() -> " + indexResponse.toString());
            }
        });
    }

    @Test
    public void testBulkCreate() throws Exception {
        int start = 5;
        int end = 10;

        // 构造文档集合
        List<Object> list = new ArrayList<>();
        for (int i = 5; i <= 7; i++) {
            UserVO userVO = new UserVO();
            userVO.setId(Long.valueOf(i));
            userVO.setUserName("赵云batch" + i );
            userVO.setHeight(1.88D);
            userVO.setAge(10 + i);
            userVO.setCreateTime(new Date());
            list.add(userVO);
        }

        // 批量新增
        BulkResponse response = documentDemoService.bulkCreate(INDEX_NAME, list);
        List<BulkResponseItem> items = response.items();
        for (BulkResponseItem item : items) {
            System.out.println("BulkResponseItem.toString() -> " + item.toString());
        }
    }

    @Test
    public void testGetById() throws Exception {
        Long id = 1L;
        Object object = documentDemoService.getById(INDEX_NAME, id.toString());

        System.out.println("object ->" + object);
        // 无法直接强转,会报错
        //UserVO userVO = (UserVO) object;
        //System.out.println("userVO ->" + object);

    }

    @Test
    public void testGetObjectNode() throws Exception {
        Long id = 1L;
        ObjectNode objectNode = documentDemoService.getObjectNodeById(INDEX_NAME, id.toString());

        Assertions.assertNotNull(objectNode);
        System.out.println("id ->" + objectNode.get("id").asLong());
        System.out.println("userName ->" + objectNode.get("userName").asText());
    }

文章参考,出处 https://blog.csdn.net/qq_42402854/article/details/126686840

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

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

相关文章

【nosql】redis之高可用(主从复制、哨兵、集群)搭建

redis群集有三种模式 redis群集有三种模式&#xff0c;分别是主从同步/复制、哨兵模式、Cluster集群&#xff0c;下面会讲解一下三种模式的工作方式&#xff0c;以及如何搭建cluster群集 ●主从复制&#xff1a;主从复制是高可用Redis的基础&#xff0c;哨兵和集群都是在主从…

c#查看代码的执行耗时( Stopwatch )

我们如果需要看某段代码的执行耗时&#xff0c;会通过如下的方式进行查看 using System.Diagnostics; private void button1_Click(object sender, EventArgs e){Stopwatch sw Stopwatch.StartNew();//sw.Start();StringBuilder sb new StringBuilder();for(int i 0; i <…

云数据中心需要加密密钥的解决方案

云数据中心的加密密钥解决方案是确保数据的保密性和安全性的重要组成部分。以下是一些常见的加密密钥解决方案&#xff1a; 对称密钥加密&#xff1a;对称密钥加密是一种常见的加密方法&#xff0c;使用相同的密钥对数据进行加密和解密。在云数据中心中&#xff0c;可以使用对称…

Matlab进阶绘图第29期—三角热图

三角热图&#xff0c;顾名思义&#xff0c;就是仅保留热图数据矩阵的上三角或下三角部分。 三角热图简单明了&#xff0c;通过不同颜色表示数据的大小&#xff0c;可以更加直观地对矩阵数据进行可视化表达。 由于Matlab中未收录三角热图的绘制函数&#xff0c;因此需要大家自…

Python编程练习与解答 练习140:邮政编码

加拿大邮政编码的第一、三和五个字符是字母&#xff0c;第二四六个字符是数字。地址所在的省和地区可以根据邮政编码的第一个字符来确定&#xff0c;如下表所示。目前有效的邮政编码不以D、F、I、O、Q、U、W、Z开头&#xff0c; 邮政编码中第二个字符标识是农村还是城市。如果…

947. 移除最多的同行或同列石头

947. 移除最多的同行或同列石头 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 947. 移除最多的同行或同列石头 https://leetcode.cn/problems/most-stones-removed-with-same-row-or-column/description/ 完成…

基于Flask+websocket实现一个在线聊天室网站系统

在今天的互联网时代&#xff0c;实时通信成为了许多应用和服务的核心特色。从社交媒体到在线游戏&#xff0c;无处不在的即时互动为用户带来了难以置信的沉浸体验。有了这种背景&#xff0c;为何不深入了解如何构建自己的实时聊天应用呢&#xff1f;在本文中&#xff0c;我们将…

数字化转型对企业有哪些优势?

数字化转型为企业提供了众多优势&#xff0c;帮助他们在日益数字化的世界中保持竞争力、敏捷性和响应能力。以下是一些主要优势&#xff1a; 1.提高效率和生产力&#xff1a; 重复性任务和流程的自动化可以减少人为错误&#xff0c;并使员工能够专注于更具战略性的任务。简化…

管理类联考——数学——汇总篇——知识点突破——应用题——不定方程

&#x1f44a; 当方程或方程组种未知数较多&#xff0c;而无法通过解方程的角度来确定数值&#xff0c;这种方程称为不定方程。不定方程必须结合所给的一些性质&#xff0c;如整除、奇数偶数、质数合数、范围大小等特征才能确定答案。 ⛲️ 一、考点讲解 不定方程特征 在应…

CSS:隐藏移动端的滚动条的方式

目录 方式一&#xff1a;-webkit-scrollbar方式二&#xff1a;overflow方式三&#xff1a;clip-path方式四&#xff1a;mask 遮罩总结参考 移动端开发中&#xff0c;有一个横向滚动元素&#xff0c;产品告诉我不需要滚动条&#xff0c;我说这个简单&#xff0c;隐藏一下不就行了…

Latex多行合并/多列合并详解

1、宏包 在\begin{document}前加入宏包 \usepackage{multirow} 2、多行合并 代码 三行合并 \multirow{3}{*}{a}例子 \begin{center}\tabcaption{表}\label{tab:2}\renewcommand\tabcolsep{1pt}%调整表格长度\begin{tabular} {cccccc}\toprule名称&名称&名称&名…

粉底液、口红、睫毛膏,眼膜等护肤品和彩妆上架亚马逊需要做什么认证?HRIPT/RIPT测试,斑贴测试,COA认证和BCOP认证办理

亚马逊要求化妆、美容类睫毛膏、眼膜、足贴、假睫毛、洗发水、美甲套装等HRIPT / RIPTCOA测试&#xff0c;如果是眼睛这个部位使用的话 还需要出示BCOP认证 为了确保在使用产品或原料后不会产生潜在的刺激或过敏。亚马逊要求化妆品&#xff0c;美容产品&#xff0c;指甲胶等需…

终于搞懂了线程的状态以及状态转换

1 线程的状态 线程的状态是一个枚举类型 Thread.State public class ThreadState {public static void main(String[] args) {for (Thread.State state : Thread.State.values()) {System.out.println(state);}} }新建&#xff08;New&#xff09;&#xff1a; 意义&#xff1…

安卓绘制原理之 MeasureCache优化了什么?

安卓绘制原理概览_油炸板蓝根的博客-CSDN博客 搜了一下&#xff0c;全网居然没有人提过 measureCache。 在前文中提到过&#xff0c;measure的时候&#xff0c;如果命中了 measureCache&#xff0c;会跳过 onMeasure&#xff0c;同时会设置 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOU…

Mysql树形表的两种查询方案(递归与自连接)

你有没有遇到过这样一种情况&#xff1a; 一张表就实现了一对多的关系&#xff0c;并且表中每一行数据都存在“爷爷-父亲-儿子-…”的联系&#xff0c;这也就是所谓的树形结构 对于这样的表很显然想要通过查询来实现价值绝对是不能只靠select * from table 来实现的&#xff0…

微服务·数据一致-事务与分布式事务

微服务数据一致-事务与分布式事务 概述 事务是计算机科学和数据库管理中的一个关键概念&#xff0c;用于确保数据的一致性和可靠想。事务管理是大多数应用程序和数据库系统中不可或缺的一部分。分布式事务扩展了事务的概念&#xff0c;用于多个分布式系统和服务的数据一致性管…

1、java基本语法

1.、标识符、关键字、注释 标识符&#xff1a;对类、对象、变量、方法、数组等起个名字。 合法的标识符&#xff1a; 由字母、数字、下划线“_”组成&#xff0c;并且首字符不能是数字。不能把java关键字和保留字作为标识符。标识符区分大小写字母。 理论上只要满足上面三个…

Vuex -访问(modules)模块中的 state mutations actions getters

文章目录 四大核心复习一、获取模块内的state数据1.目标&#xff1a;2.使用模块中的数据3.代码示例 二、获取模块内的getters数据1.目标&#xff1a;2.语法&#xff1a;3.代码演示 三、获取模块内的mutations方法1.目标&#xff1a;2.注意&#xff1a;3.调用方式&#xff1a;4.…

LRTA*(Learning-RTA*)

1、基本概念 LRTA* 算法是对RTA* 算法的改进&#xff0c;在RTA* 的原论文中&#xff0c;提到了&#xff1a; Unfortunately, while RTA* as described above is ideally suited to single problem solving trials, it must be modified to accommodate multi-trial learning.…

集成学习-树模型

可以分为三部分学习树模型&#xff1a; 基本树&#xff08;包括 ID3、C4.5、CART&#xff09;.Random Forest、Adaboost、GBDTXgboost 和 LightGBM。 基本树 选择特征的准则 ID3&#xff1a;信息增益max C4.5&#xff1a;信息增益比max CART&#xff1a;基尼指数min 优缺…