Spring Boot整合ElasticSearch

2023-11-20

一、ES客户端

ES提供多种不同的客户端:

1、TransportClient

ES提供的传统客户端,官方计划8.0版本删除此客户端。

2、RestClient

RestClient是官方推荐使用的,它包括两种:REST Low Level Client和 REST High Level Client。ES在6.0之后提供REST High Level Client, 两种客户端官方更推荐使用 REST High Level Client,不过当前它还处于完善中,有些功能还没有。

二、搭建工程

1.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.2.RELEASE</version>
    </parent>

    <groupId>com.bjpowernode</groupId>
    <artifactId>springboot_elasticsearch</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <!-- 修改elasticsearch的版本 -->
    <properties>
        <elasticsearch.version>6.2.3</elasticsearch.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
</project>

2.application.yml

spring:
  elasticsearch:
    rest:
      uris:
        - http://192.168.204.132:9200

3.app

 

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ElasticsearchApp {

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

三、索引管理

1.创建索引库

   1.api

创建索引库:
PUT /java06
{
  "settings":{
       "number_of_shards" : 2,
       "number_of_replicas" : 0
  }
}


创建映射:
POST /java06/course/_mapping
{
  "_source": {
    "excludes":["description"]
  }, 
 	"properties": {
      "name": {
          "type": "text",
          "analyzer":"ik_max_word",
          "search_analyzer":"ik_smart"
      },
      "description": {
          "type": "text",
          "analyzer":"ik_max_word",
          "search_analyzer":"ik_smart"
       },
       "studymodel": {
          "type": "keyword"
       },
       "price": {
          "type": "float"
       },
       "pic":{
		   "type":"text",
		   "index":false
	    }
  }
}

   2.Java Client

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {ElasticsearchApp.class})
public class IndexWriterTest {
	@Autowired
    private RestHighLevelClient restHighLevelClient;

   //创建索引库
    @Test
    public void testCreateIndex() throws IOException {
        //创建“创建索引请求”对象,并设置索引名称
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("java06");
        //设置索引参数
        createIndexRequest.settings("{\n" +
                "       \"number_of_shards\" : 2,\n" +
                "       \"number_of_replicas\" : 0\n" +
                "  }", XContentType.JSON);
        createIndexRequest.mapping("course", "{\r\n" + 
        		"  \"_source\": {\r\n" + 
        		"    \"excludes\":[\"description\"]\r\n" + 
        		"  }, \r\n" + 
        		" 	\"properties\": {\r\n" + 
        		"           \"name\": {\r\n" + 
        		"              \"type\": \"text\",\r\n" + 
        		"              \"analyzer\":\"ik_max_word\",\r\n" + 
        		"              \"search_analyzer\":\"ik_smart\"\r\n" + 
        		"           },\r\n" + 
        		"           \"description\": {\r\n" + 
        		"              \"type\": \"text\",\r\n" + 
        		"              \"analyzer\":\"ik_max_word\",\r\n" + 
        		"              \"search_analyzer\":\"ik_smart\"\r\n" + 
        		"           },\r\n" + 
        		"           \"studymodel\": {\r\n" + 
        		"              \"type\": \"keyword\"\r\n" + 
        		"           },\r\n" + 
        		"           \"price\": {\r\n" + 
        		"              \"type\": \"float\"\r\n" + 
        		"           },\r\n" + 
        		"  }\r\n" + 
        		"}", XContentType.JSON);
        //创建索引操作客户端
        IndicesClient indices = restHighLevelClient.indices();

        //创建响应对象
        CreateIndexResponse createIndexResponse = 
            indices.create(createIndexRequest);
        //得到响应结果
        boolean acknowledged = createIndexResponse.isAcknowledged();
        System.out.println(acknowledged);
    } 
  }

2.删除索引库

   1.api

DELETE /java06

   2.java client

	//删除索引库
	@Test
	public void testDeleteIndex() throws IOException {
		//创建“删除索引请求”对象
		DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("java06");
		//创建索引操作客户端
		IndicesClient indices = restHighLevelClient.indices();
		//创建响应对象
		DeleteIndexResponse deleteIndexResponse = 
            indices.delete(deleteIndexRequest);
		//得到响应结果
		boolean acknowledged = deleteIndexResponse.isAcknowledged();
		System.out.println(acknowledged);
	}

3.添加文档

   1.api

POST /java06/course/1
{
 "name":"spring cloud实战",
 "description":"本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud 基础入门 3.实战Spring Boot 4.注册中心eureka。",
 "studymodel":"201001",
 "price":5.6
}

   2.java client

	//添加文档
	@Test
	public void testAddDocument() throws IOException {
		//创建“索引请求”对象:索引当动词
		IndexRequest indexRequest = new IndexRequest("java06", "course", "1");
		indexRequest.source("{\n" +
				" \"name\":\"spring cloud实战\",\n" +
				" \"description\":\"本课程主要从四个章节进行讲解: 1.微服务架构入门 " +
				"2.spring cloud 基础入门 3.实战Spring Boot 4.注册中心nacos。\",\n" +
				" \"studymodel\":\"201001\",\n" +
				" \"price\":5.6\n" +
				"}", XContentType.JSON);
		IndexResponse indexResponse = 
            restHighLevelClient.index(indexRequest);
		System.out.println(indexResponse.toString());
	}

4.批量添加文档

支持在一次API调用中,对不同的索引进行操作。支持四种类型的操作:index、create、update、delete。

   语法:

POST /_bulk
{ action: { metadata }} 
{ requestbody }\n
{ action: { metadata }} 
{ requestbody }\n
...

   1.api

POST /_bulk
{"index":{"_index":"java06","_type":"course"}}
{"name":"php实战","description":"php谁都不服","studymodel":"201001","price":"5.6"}
{"index":{"_index":"java06","_type":"course"}}
{"name":"net实战","description":"net从入门到放弃","studymodel":"201001","price":"7.6"}

   2.java client

@Test
public void testBulkAddDocument() throws IOException {
    BulkRequest bulkRequest = new BulkRequest();
    bulkRequest.add(new IndexRequest("java06", "course").source("{...}",
                                                                  XContentType.JSON));
    bulkRequest.add(new IndexRequest("java06", "course").source("{...}",
                                                                  XContentType.JSON));
    BulkResponse bulkResponse = 
                   restHighLevelClient.bulk(bulkRequest);
    System.out.println(bulkResponse.hasFailures());
}

5.修改文档

   1.api

PUT /java06/course/1
{
 "price":66.6
}

   2.java client

//更新文档
@Test
public void testUpdateDocument() throws IOException {
    UpdateRequest updateRequest = new UpdateRequest("java06", "course", "1");
    updateRequest.doc("{\n" +
            "  \"price\":7.6\n" +
            "}", XContentType.JSON);
    UpdateResponse updateResponse = 
                   restHighLevelClient.update(updateRequest);
    System.out.println(updateResponse.getResult());
}

6.删除文档

   1.api

DELETE /java06/coures/1

   2.java client

 //根据id删除文档
    @Test
    public void testDelDocument() throws IOException {
        //删除请求对象
        DeleteRequest deleteRequest = new DeleteRequest("java06","course","1");
        //响应对象
        DeleteResponse deleteResponse = 
            restHighLevelClient.delete(deleteRequest);
        System.out.println(deleteResponse.getResult());
    }

四、文档搜索

1.准备环境

   向索引库中多添加一些数据:

PUT /java06/course/1
{
  "name": "Bootstrap开发",
  "description": "Bootstrap是由Twitter推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个css,不受浏览器限制的精美界面css效果。",
  "studymodel": "201002",
  "price":38.6,
  "pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

PUT /java06/course/2
{
  "name": "java编程基础",
  "description": "java语言是世界第一编程语言,在软件开发领域使用人数最多。",
  "studymodel": "201001",
  "price":68.6,
  "pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

PUT /java06/course/3
{
  "name": "spring开发基础",
  "description": "spring 在java领域非常流行,java程序员都在用。",
  "studymodel": "201001",
  "price":88.6,
  "pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

2.简单搜索

简单搜索就是通过url进行查询,以get方式请求ES。

语法:

GET /index_name/type_name/doc_id
GET [/index_name/type_name/]_search[?parameter_name=parameter_value&...]

例如:

GET /java06/course/_search?q=name:spring&sort=price:desc

注意:

如果查询条件复杂,很难构建搜索条件 ,生产环境中很少使用。 例如:要求搜索条件为商品名称包含手机,价格在 1000~5000之间,销量在每月 500 以上,根据价格升序排列,分页查询第二页,每页 40 条数据:?q=xxxx:xxx&range=xxx:xxx:xxx&aggs&sort&from&size

   1.api

GET /java06/course/1

   2.java client

//查询文档
    @Test
    public void getDoc() throws IOException {
        GetRequest getRequest = new GetRequest("java06","course","1");
        GetResponse getResponse = restHighLevelClient.get(getRequest);
        boolean exists = getResponse.isExists();
        System.out.println(exists);
		String source = getResponse.getSourceAsString();
		System.out.println(source);
    }

3.DSL搜索

DSL(Domain Specific Language)是ES提出的基于json的搜索方式,在搜索时传入特定的json格式的数据来完成不同的搜索需求,DSL比URI搜索方式功能强大,在项目中建议使用DSL方式来完成搜索。

语法:

	GET /index_name/type_name/_search
​	{
​		"commond":{
​			"parameter_name" : "parameter_value"
​		}
​	}

   1.match_all查询

        1.api

GET /java06/course/_search
{
  "query" : { 
    "match_all" : {}
  }
}

        2.java client

import com.bjpowernode.ElasticsearchApp;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.io.IOException;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {ElasticsearchApp.class})
public class IndexReaderTest {
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    private SearchRequest searchRequest;
    private SearchResponse searchResponse;

    @Before
    public void init(){
        searchRequest = new SearchRequest();
        searchRequest.indices("java06");
        searchRequest.types("course");
    }

    @Test
    public void testMatchAll() throws IOException {
        //2、创建 search请求对象
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("java06");
        searchRequest.types("course");

        //3、创建 参数构造器
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());

        //4、设置请求参数
        searchRequest.source(searchSourceBuilder);

        //1、调用search方法
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest);

        SearchHits searchHits = searchResponse.getHits();
        
        long totalHits = searchHits.getTotalHits();
        System.out.println("共搜索到"+totalHits+"条文档");

        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
    }

    @After
    public void show(){
        SearchHits searchHits = searchResponse.getHits();
        long totalHits = searchHits.getTotalHits();
        System.out.println("共搜索到"+totalHits+"条文档");

        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
    }
}

   2.分页查询

        1.api

GET /java06/course/_search
{
  "query" : { "match_all" : {} },
  "from" : 1, # 从第几条数据开始查询,从0开始计数
  "size" : 3, # 查询多少数据
  "sort" : [
    { "price" : "asc" }
  ]
}

        2.java client

//分页查询
@Test
public void testSearchPage() throws Exception {
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.matchAllQuery());
    searchSourceBuilder.from(1);
    searchSourceBuilder.size(5);
    searchSourceBuilder.sort("price", SortOrder.ASC);

    // 设置搜索源
    searchRequest.source(searchSourceBuilder);
    // 执行搜索
    searchResponse = restHighLevelClient.search(searchRequest);
}

   2.match查询

        match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。

        1.api

        query:搜索的关键字

        operator:or 表示 只要有一个词在文档中出现则就符合条件,and表示每个词都在文档中出现则才符合条件。

        1、基本使用:

GET /java06/course/_search
{
  "query" : {
    "match" : {
      "name": {
        "query": "spring开发"
      }
    }
  }
}

        2、operator:

GET /java06/course/_search
{
  "query" : {
    "match" : {
      "name": {
        "query": "spring开发",
        "operator": "and"
      }
    }
  }
}

        上边的搜索的执行过程是:

                        1、将“spring开发”分词,分为spring、开发两个词

                        2、再使用spring和开发两个词去匹配索引中搜索。

                        3、由于设置了operator为and,必须匹配两个词成功时才返回该文档。

        2. java client

@Test
public void testMatchQuery() throws Exception {
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.matchQuery("name", "spring开
                                                       发").operator(Operator.AND));
		
    // 设置搜索源
    searchRequest.source(searchSourceBuilder);
    // 执行搜索
    searchResponse = restHighLevelClient.search(searchRequest);
 }

   3.multi_match查询

matchQuery是在一个field中去匹配,multiQuery是拿关键字去多个Field中匹配。

        1.api

           1、基本使用 例子:关键字 “开发”去匹配name 和description字段

GET /java06/course/_search
{
  "query": {
    "multi_match": {
      "query": "开发",
      "fields": ["name","description"]
    }
  }
}

 注意:此搜索操作适合构建复杂查询条件,生产环境常用。

        2.java client

@Test
public void testMultiMatchQuery() throws Exception {
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.multiMatchQuery("开发","name","description"));
		
    // 设置搜索源
    searchRequest.source(searchSourceBuilder);
    // 执行搜索
    searchResponse = restHighLevelClient.search(searchRequest);
}

   4.bool查询

        布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来。

        参数:

        must:表示必须,多个查询条件必须都满足。(通常使用must)

        should:表示或者,多个查询条件只要有一个满足即可。 must_not:表示非。

        1.api

           例如:查询name包括“开发”并且价格区间是1-100的文档

GET /java06/course/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "开发"
          }
        },
        {
          "range": {
            "price": {
              "gte": 50,
              "lte": 100
            }
          }
        }
      ]
    }
  }
}

        2.java client


    @Test
    public void testBooleanMatch() throws IOException {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //json条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchQuery("name","开发"));
        boolQueryBuilder.must(QueryBuilders.rangeQuery("price").gte("50").lte(100));
        searchSourceBuilder.query(boolQueryBuilder);

        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
    }

   6.filter查询

         过滤查询。此操作实际上就是 query DSL 的补充语法。过滤的时候,不进行任何的匹配分数计算,相对于 query 来说,filter 相对效率较高。Query 要计算搜索匹配相关度分数。Query更加适合复杂的条件搜索。

        1.api

        如:使用bool查询,搜索 name中包含 "开发"的数据,且price在 10~100 之间

        1、不使用 filter, name和price需要计算相关度分数

GET /java06/course/_search
{
  "query": {
     "bool" : {
        "must":[
            {
               "match": {
                 "name": "开发"
               }
            },
            {
              "range": {# 范围, 字段的数据必须满足某范围才有结果。
                "price": {
                  "gte": 10, # 比较符号 lt gt lte gte
                  "lte": 100
                }
              }
            }
        ]
     }
  }
}

        2、使用 filter, price不需要计算相关度分数:

GET /java06/course/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "开发"
          }
        }
      ],
      "filter": {# 过滤,在已有的搜索结果中进行过滤,满足条件的返回。
        "range": {
          "price": {
            "gte": 1,
            "lte": 100
          }
        }
      }
    }
  }
}

        2.java client

@Test
public void testFilterQuery() throws IOException {
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    boolQueryBuilder.must(QueryBuilders.matchQuery("name","开发"));
    boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(10).lte(100))
    searchSourceBuilder.query(boolQueryBuilder);
    searchRequest.source(searchSourceBuilder);
    searchResponse = restHighLevelClient.search(searchRequest);
}

   6.highlight查询

        高亮显示:

        高亮不是搜索条件,是显示逻辑,在搜索的时候,经常需要对搜索关键字实现高亮显示。

        1.api

         例如:

GET /java06/course/_search
{
  "query": {
    "match": {
      "name": "开发"
    }
  },
  "highlight": {
      "pre_tags": ["<font color='red'>"],
      "post_tags": ["</font>"],
      "fields": {"name": {}}
  }
}

        2.java clent

        1、查询:

 @Test
  public void testHighLightQuery() throws Exception {
      SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
      searchSourceBuilder.query(QueryBuilders.matchQuery("name", "spring"));
      //设置高亮
      HighlightBuilder highlightBuilder = new HighlightBuilder();
      highlightBuilder.preTags("<font color='red'>");
      highlightBuilder.postTags("</font>");
      highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
      searchSourceBuilder.highlighter(highlightBuilder);

      searchRequest.source(searchSourceBuilder);
      searchResponse = restHighLevelClient.search(searchRequest);
}

        2、遍历:

 @After
public void displayDoc() {
    SearchHits searchHits = searchResponse.getHits();
    long totalHits = searchHits.getTotalHits();
    System.out.println("共搜索到" + totalHits + "条文档");

    SearchHit[] hits = searchHits.getHits();
    for (int i = 0; i < hits.length; i++) {
        SearchHit hit = hits[i];
        String id = hit.getId();
        System.out.println("id:" + id);
        String source = hit.getSourceAsString();
        System.out.println(source);

        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        if (highlightFields != null) {
            HighlightField highlightField = highlightFields.get("name");
            Text[] fragments = highlightField.getFragments();
            System.out.println("高亮字段:" + fragments[0].toString());
        }
    }

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Boot整合ElasticSearch 的相关文章

  • 在 mvn 命令中指定 pom.xml 并混合其他项目的目标

    我有多个问题 我可以在 mvn 命令中指定 pom xml 吗 在当前项目上执行 mvn 命令时 我可以混合另一个项目的目标吗 例如 mvn clean otherproject comple otherproject install ot
  • 从 java sdk 向对等方发送提案时出现访问被拒绝错误

    我正在尝试使用以下代码查询区块链并收到访问被拒绝错误 我也遇到同样的错误sendTransactionProposal方法也是如此 UserContext adminUserContext RegisterEnrollUser regist
  • 如何在 Firebase 远程配置中从 JSON 获取值

    我是 Android 应用开发和 Firebase 的新手 我想知道如何获取存储在 Firebase 远程配置中的 JSONArray 文件中的值 String 和 Int 我使用 Firebase Remote Config 的最终目标是
  • 使用 GWT 读取非常大的本地 XML 文件

    我正在使用 GWT 构建我的第一个 Java 应用程序 它必须从一个非常大的 XML 文件中读取数据 当我尝试发送对文件中信息的请求时遇到问题 并且我不太确定它是否与文件的大小或我的语义有关 在我的程序中 我有以下内容 static fin
  • 打印星号的 ASCII 菱形

    我的程序打印出这样的钻石 但只有当参数或菱形的每一面为4 例如如果我输入6 底部三角形的间距是错误的 我一直在试图找出答案 当参数改变时 底部的三角形不会改变 只有顶部的三角形会改变 它只适用于输入4 public static void
  • GWT - 如何组织项目以拥有多个网页以及它们之间的导航

    我是 GET 的新手 顺便说一句 它给我留下了深刻的印象 并且发现它对于像我这样熟悉 C NET 桌面技术并愿意编写 Web 应用程序的人来说非常有吸引力 我根据 GWT Eclipse 向导生成的示例启动了自己的项目 该项目生成带有面板的
  • Spring RestTemplate 使用 cookie 遵循重定向

    最近我遇到了一个问题 我需要做一个GET请求远程服务 我假设使用一个简单的 servlet 并且 RestTemplate 返回Too many redirects 经过一番调查 似乎对指定远程服务发出的第一个请求实际上只是一个 302 重
  • 通往楼梯顶部的可能路径

    这是一个非常经典的问题 我听说谷歌在他们的面试中使用过这个问题 问题 制定一个递归方法 打印从楼梯底部到楼梯顶部的所有可能的独特路径 有 n 个楼梯 您一次只能走 1 步或 2 步 示例输出 如果它是一个有 3 级楼梯的楼梯 1 1 1 2
  • 在 Wildfly 中与 war 部署共享 util jar 文件

    假设我有一个名为 util jar 的 jar 文件 该 jar 文件主要包含 JPA 实体和一些 util 类 无 EJB 如何使这个 jar 可用于 Wildfly 中部署的所有 war 无需将 jar 放置在 war 的 WEB IN
  • 需要使用 joda 进行灵活的日期时间转换

    我想使用 joda 解析电子邮件中的日期时间字符串 不幸的是我得到了各种不同的格式 例如 Wed 19 Jan 2011 12 52 31 0600 Wed 19 Jan 2011 10 15 34 0800 PST Wed 19 Jan
  • 读取电子邮件的文本文件转换为 Javamail MimeMessage

    我有一个电子邮件原始来源的文本文件 直接从 gmail 复制 如果您单击 查看原始文件 您就会看到它 我想读入该文件并将其转换为 MimeMessage 如果您好奇为什么 我设置了 JavaMaildir 并且需要用电子邮件填充它的收件箱以
  • Java实现累加器类,提供Collector

    A Collector具有三种通用类型 public interface Collector
  • 使用架构注册表对 avro 消息进行 Spring 云合约测试

    我正在查看 spring 文档和 spring github 我可以看到一些非常基本的内容examples https github com spring cloud samples spring cloud contract sample
  • Docker 和 Eureka 与 Spring Boot 无法注册客户端

    我有一个使用 Spring Boot Docker Compose Eureka 的非常简单的演示 我的服务器在端口 8671 上运行 具有以下应用程序属性 server port 8761 eureka instance prefer i
  • java库维护数据库结构

    我的应用程序一直在开发 所以偶尔 当版本升级时 需要创建 更改 删除一些表 修改一些数据等 通常需要执行一些sql代码 是否有一个 Java 库可用于使我的数据库结构保持最新 通过分析类似 db structure version 信息并执
  • 使用布尔值进行冒泡排序以确定数组是否已排序

    我有以下用于冒泡排序的代码 但它根本不排序 如果我删除布尔值那么它工作正常 我知道 由于我的 a 0 小于所有其他元素 因此没有执行交换 任何人都可以帮助我解决这个问题 package com sample public class Bub
  • Resteasy 可以查看 JAX-RS 方法的参数类型吗?

    我们使用 Resteasy 3 0 9 作为 JAX RS Web 服务 最近切换到 3 0 19 我们开始看到很多RESTEASY002142 Multiple resource methods match request警告 例如 我们
  • Java中HashMap和ArrayList的区别?

    在爪哇 ArrayList and HashMap被用作集合 但我不明白我们应该在哪些情况下使用ArrayList以及使用时间HashMap 他们两者之间的主要区别是什么 您具体询问的是 ArrayList 和 HashMap 但我认为要完
  • org.apache.commons.net.io.CopyStreamException:复制时捕获 IOException

    我正在尝试使用以下方法中的代码将在我的服务器中创建的一些文件复制到 FTP 但奇怪的是我随机地低于错误 我无法弄清楚发生了什么 Exception org apache commons net io CopyStreamException
  • Java EE 目录结构

    我对以下教程有疑问 http www mkyong com jsf2 jsf 2 internationalization example http www mkyong com jsf2 jsf 2 internationalizatio

随机推荐

  • 手把手教你通过端口映射,轻松搭建Windows远程桌面

    市面上有很多的远程桌面软件 如TeamViewer 向日葵等 但无一例外 它们提供的免费服务连接质量普遍不高 而付费服务价格又偏高 并不能使人满意 但众所周知 微软自带的Windows远程桌面其实在连接质量和稳定性方面一点都不输给第三方软件
  • jquery中$()的使用

    在jquery中最常使用的就是 这个符号了 在我没有系统的学习jquery之前 我用到的 都是用于对元素的选择 而这只是 的很简单的用法 在jquery 函数一共有三种用法 selector context 在这个方法中selector是选
  • error: GLES2/gl2.h: No such file or directory

    最近一个朋友让帮忙编译android程序 中间遇到了很多问题 大概都解决了 最后又遇到了一个问题 GLES2 gl2 h No such file or directory 这个问题 我大概知道是怎么回事 关键是没有指定ndk的编译版本号
  • 公司刚上市就来了个从字节拿28K的人,让我见识到了什么才是测试天花板···

    5年测试 应该是能达到资深测试的水准 即不仅能熟练地开发业务 而且还能熟悉项目开发 测试 调试和发布的流程 而且还应该能全面掌握数据库等方面的技能 如果技能再高些的话 甚至熟悉分布式组件等高级技能 或者说 做个项目小组长 管个3 4号人 应
  • router-link 和 router-view 的 关系

  • vue整合ueditor

    一 前端代码 Ueditor官网地址为 http ueditor baidu com website download html ueditor 下载好之后 将Jsp版本解压 解压后文件夹改名为ueditor 将文件夹中的jsp目录删掉 之
  • Elasticsearch7 清空指定Index 相关数据

    注意 Elasticsearch7 起 Index索引已经不支持创建指定Type 类型 默认取值为 doc Elasticsearch7 清空指定Index 语法 POST 请求 http es 服务器地址 索引名称 delete by q
  • go 进阶 gin实战相关: 五. gin_scaffold 企业脚手架

    目录 一 gin scaffold 企业级脚手架 二 gin scaffold 脚手架安装及使用演示 文件分层解释 开始使用 1 配置开启go mod 功能 2 下载 安装 gin scaffold 3 整合 golang common 4
  • 原生js php ajax,原生Ajax怎么写

    写原生Ajax的方法 首先创建XMLHttpRequest对象 然后编写回调函数onreadystatechange 接着配置请求信息 最后发送请求即可 Ajax Asynchronous JavaScript and XML的缩写 是一种
  • C#使用NuGet包播放视频之二————读取RTSP流

    RTSP流的读取 上篇文章做到读取本地摄像头 基本事都做完了 这篇文章将RTSP流加进去 双击窗体中ToolStrip的RTSP 为之添加事件 事件中编写代码如下
  • Yii2框架(一)安装及目录结构

    如题 对 你要相信自己的眼睛 你没看错确实是Yii2框架 现在都2020年了 刚刚开始折腾Yii2框架难免有些过时 但是没办法 公司目前的项目是基于Yii2开发的 嘿 你说怎么这么巧 我还没用过Yii2框架 没办法 看手册呗 这玩意 万变不
  • Vue2运行报错SyntaxError: Cannot use import statement outside a module

    问题描述 像配置vue3那样配置vue config js的路径代理 代替src后 报错 语法错误 不能在模块外部使用导入语句 原因 模块语法一个是CommonJS module 一个是 ES6 module vue config js里的
  • Google Voice账号的具体保号教程

    Google Voice 官方号码回收规则 https www google com intl zh CN googlevoice program policies html 在9个月内你的Google Voice没拔打电话或接收短信 你的
  • Hbase使用shell命令报错大集锦:

    一 Hbase使用shell命令出现报错 PleaseHoldException Master is initializing 解决办法 0 保证hbase运行着的 1 删除HDFS里hbase文件夹 hdfs dfs rm r hbase
  • 蓝牙BLE连接设备报错onClientConnectionState() - status=133解决方法

    S905平台 Android 5 1 1 WIFI 蓝牙芯片AP6255 客户某蓝牙设备使用他们专用的APK连接不上 查logcat信息如下 D BluetoothAdapter 5097 stopLeScan D BluetoothAda
  • Arduino智能小车随笔(一)

    Arduino智能小车随笔 一 看到小孩的各种STEM课程很火 收费又老贵 就想着不如自己和小孩一起学着做个arduino智能小车 即能让女儿学点编程 又能省了智商税 一举两得 然而到了后面女儿基本上只帮我接线 arduBlock实在无法支
  • ZooKeeper踩坑

    一 下载安装包时要下载文件名中带有bin的安装包 否则会报错 找不到或无法加载主类 org apache zookeeper server quorum QuorumPeerMain Error contacting service 这是由
  • Alluxio集群环境搭建,救救孩子!

    写在前面 最近的一段时间内我会做HDFS Alluxio HBase相关的开发工作 我会继续学习并分享不限于这些组件的知识 正常来说 搭建个集群环境根本不需要专门写个文章 但是这次我必须写 顺带必须小吐槽一下 Alluxio官方文档搭建集群
  • python程序填空题 快乐的数字_Python习题之快乐的数字

    快乐的数字 描述 编写一个算法来确定一个数字是否 快乐 快乐的数字按照如下方式确定 从一个正整数开始 用其每位数的平方之和取代该数 并重复这个过程 直到最后数字要么收敛等于1且一直等于1 要么将无休止地循环下去且最终不会收敛等于1 能够最终
  • Spring Boot整合ElasticSearch

    一 ES客户端 ES提供多种不同的客户端 1 TransportClient ES提供的传统客户端 官方计划8 0版本删除此客户端 2 RestClient RestClient是官方推荐使用的 它包括两种 REST Low Level C