SpringBoot2整合ElasticSearch(包含ElasticSearch入門+spring-boot-starter-data-elasticsearch)

前言

作爲互聯網熱點知識的ElasticSearch,怎能不學。如果你有空餘時間,歡迎入門;如果你沒空餘時間,也歡迎走馬觀花看一眼。走過如果不要錯過,這是一篇自我感覺相對對入門者來說比較全面的文章了,希望對大家有幫助,有什麼疑問或者建議歡迎留言討論。

Why&What Elasticsearch?

  • 概念Elasticsearch 是一個開源分佈式高擴展高實時的RESTful 搜索和分析引擎,基於Lucene
  • 背景Elasticsearch是與名爲Logstash的數據收集和日誌解析引擎以及名爲Kibana的分析和可視化平臺一起開發的。這三個產品被設計成一個集成解決方案,稱爲“Elastic Stack”(以前稱爲“ELK stack”)。
  • 價值Elasticsearch能很方便的使大量數據具有搜索分析探索的能力,能使數據在生產環境變得更有價值
  • 步驟:首先用戶將數據提交到Elastic Search 數據庫中,再通過分詞控制器去將對應的語句分詞,將其權重和分詞結果一併存入數據,當用戶搜索數據時候,再根據權重將結果排名打分,再將返回結果呈現給用戶。
  • 誰在用: 1. Wikipedia 使用 Elasticsearch 提供帶有高亮片段的全文搜索,還有 search-as-you-type 和 did-you-mean 的建議。2. Stack Overflow 將地理位置查詢融入全文檢索中去,並且使用 more-like-this 接口去查找相關的問題和回答。3. GitHub 使用 Elasticsearch 對1300億行代碼進行查詢。
  • 端口9200http協議的RESTful接口。9300tcp通訊端口,集羣間和TCPClient都走的它。

ElasticSearch&DB的區別

DB ES
`database`數據庫 `index`索引
`table`表 `type`類型
`row`行(一條數據) `document`文檔
`column`列(字段名) `field`字段

Download&Install Elasticsearch

  1. https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.1.zip下載6.8.1版本 如果從官網https://www.elastic.co/cn/downloads/elasticsearch下載Elasticsearch,下載到的版本太新,客戶端不支持
  2. 運行bin\elasticsearch.bat
  3. 訪問http://127.0.0.1:9200/ ,見到以下返回信息(目前推薦ES6.8.1的版本,比較靠譜,minimum_index_compatibility_version=5.X的,最新版ES7最低的client版本是6.X,會有兼容問題,請看末尾版本兼容問題部分)
{
    "name": "sUR4zrr",
    "cluster_name": "elasticsearch",
    "cluster_uuid": "ODsZw-P1QMe9CDeOqEQQvA",
    "version": {
        "number": "6.7.1",
        "build_flavor": "default",
        "build_type": "zip",
        "build_hash": "2f32220",
        "build_date": "2019-04-02T15:59:27.961366Z",
        "build_snapshot": false,
        "lucene_version": "7.7.0",
        "minimum_wire_compatibility_version": "5.6.0",
        "minimum_index_compatibility_version": "5.0.0"
    },
    "tagline": "You Know, for Search"
}
  1. 下載Chrome插件 elasticsearch-head https://www.chromefor.com/elasticsearch-head_v0-1-4/dejavu-elasticsearch-web-ui https://www.chromefor.com/dejavu-elasticsearch-web-ui_v3-4-0/

Elasticsearch REST API

這裏補充幾個常用的API,以便大家對ES的REST API有簡單的瞭解:

  1. curl -X PUT \ http://localhost:9200/blog ,PUT請求,後面的blog是要新建的index,也就是這個api相當於新建一個數據庫
  2. curl -X POST \ http://localhost:9200/blog/article \ -d ' { "author": "zhengkai.blog.csdn.net", "createtime": 1563689639575, "id": 2, "text": "Elasticsearch是一個開源的分佈式、高擴展、高實時的RESTful 搜索和分析引擎,基於Lucene......", "title": "SpringBoot整合ElasticSearch" }' ,POST請求,如果不存在叫article的type類型/table表,則新增,並插入記錄。
  3. curl -X GET \ 'http://localhost:9200/article_info/doc/61969/_termvectors?fields=title' 格式爲/${index}/${type}/${id}/_termvectors?fields=${fields_name} ,GET請求,查詢分詞結果。返回的JSON中term_vectors.field.terms裏面就是分詞結果。
  4. curl -X POST \http://localhost:9200/_search -d '{"query":{"bool":{"must":[{"wildcard":{"title.keyword":{"wildcard":"*SpringBoot*","boost":1}}}],"disable_coord":false,"adjust_pure_negative":true,"boost":1}}}' ,POST請求,進行搜索。

2019.7.23 補充。這個查詢情況比較複雜,補充一些**【ElasticSearch分詞和查詢相關】**東西:

  • 情況一:{"query":{"wildcard": { "title": "*springboot*" }}} 可以查詢到包含SpringBoot和springboot忽略大小寫的標題,走分詞,所以只能用小寫查。而{"query":{"wildcard": { "title": "*SpringBoot*" }}}什麼都查詢不出來。。。
  • 情況二:{"query":{"wildcard": { "title.keyword": "*SpringBoot*" }}} 可以查詢到包含SpringBoot的大小寫必須一致的標題,不走分詞。而{"query":{"wildcard": { "title.keyword": "*springboot*" }}} `什麼都查詢不出來。。。
  • 情況三:{"query":{"match": { "title": "bootelasticsearch" }}},可以查詢出來,而且無論bootelasticsearch中什麼字母是大寫或者小寫,忽略大小寫。。。
  • 情況四:{"query":{"term": { "title": "bootelasticsearch" }}},可以查詢出來,且必須小寫字母才能查詢出來,其他都不行。。。

以上情況很奇怪對吧,爲什麼呢,請看下文分解。。

  • bool(boolQuery)和must(boolQuery.must)的關係,就像sql的whereand一樣,作爲條件連接的橋樑來使用,多個條件的話,就使用多個must。
  • wildcard模糊查詢,跟SQL的LIKE查詢很類似,條件"*SpringBoot*"表示包含SpringBoot的文本。
  • wildcard的情況下,查詢字段是text類型的話(es5以後沒有string類型呢,分text和keyword,string數據put到es5中,默認是text。),直接title查詢是走分詞的,例如查詢springboot,將會查詢到Spring;用title.keyword的話這樣可以不走分詞,進行精準匹配。
  • es默認分詞器爲standard analyzer,大寫字母全部轉爲了小寫字母,並存入了倒排索引以供搜索。”SpringBootElasticSearch”會被分解成[bootelasticsearch]寫入倒排索引(使用3的分詞結果接口可以看到。坑啊!不是應[該spring,boot,elasticsearch]嗎!!!)。 所以term query 查詢的是倒排索引中確切的term,必須要匹配到大寫的BootElasticSearch;而match query 會對filed進行分詞操作,然後在查詢,忽略大小寫

項目實戰


前面都是基礎,下面纔是開始Coding。

開源項目

項目源碼已經上傳到github,有需要可以參考或者下載使用。

Maven依賴

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

Application配置

這裏是application.yml的配置

server:
  port: 9999
  servlet:
      context-path: /es
tomcat:
    remote-ip-header: x-forward-for
    uri-encoding: UTF-8
    max-threads: 10
    background-processor-delay: 30
spring:
    http:
      encoding:
        force: true
        charset: UTF-8
    application:
        name: spring-cloud-study-security-elasticsearch
        author: zhengkai.blog.csdn.net
    data:
        elasticsearch:
          cluster-nodes: 127.0.0.1:9300
          cluster-name: elasticsearch

Entity實體

import java.util.Date;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import lombok.Data;

@Data
@Document(indexName = "article_info", type = "doc")
public class Article {
	@Id
    private Integer id;

    private String title;

    private String text;

    private Date createtime;

    private String author;

}

ElasticsearchRepository

ArticleRepository 接口繼承ElasticsearchRepository來完成基本的CRUD分頁操作的,功能強大並且和普通JPA沒有什麼區別。保存的話直接用save就可以了,以下是search相關的方法:

  • Iterable search(QueryBuilder query);
  • Page search(QueryBuilder query, Pageable pageable);
  • Page search(SearchQuery searchQuery);
  • Page searchSimilar(T entity, String[] fields, Pageable pageable);
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
/**
 * ElasticsearchRepository --> ElasticsearchCrudRepository --> PagingAndSortingRepository --> CrudRepository
 * @author zhengkai.blog.csdn.net
 */
@Repository
public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> {

}

RestController

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.softdev.system.demo.entity.Article;
import com.softdev.system.demo.repository.ArticleRepository;
import com.softdev.system.demo.util.ApiReturnUtil;

import cn.hutool.core.util.RandomUtil;
/**
 *  ElasticSearch控制器
 * @author  zhengkai.blog.csdn.net
 * */
@RestController
public class ArticleController {

	@Autowired
	private ElasticsearchTemplate elasticsearchTemplate;
	
	@Autowired
	private ArticleRepository articleRepository;

	@GetMapping("new")
	public Object newArticle(@RequestParam(defaultValue = "SpringBootElasticSearch") String title, @RequestParam(defaultValue = "`Elasticsearch` 是一個`開源`的`分佈式`、`高擴展`、`高實時`的RESTful `搜索和分析引擎`,基於`Lucene`......") String text){
		//構建並保存Article
		Article article = new Article();
		article.setId(RandomUtil.randomInt(10000,99999));
		article.setTitle(title);
		article.setText(text);
		article.setCreatetime(new Date());
		article.setAuthor("zhengkai.blog.csdn.net");
		return ApiReturnUtil.success(article);
	}

	@GetMapping("save")
	public Object save(@RequestParam(defaultValue = "SpringBootElasticSearch") String title, @RequestParam(defaultValue = "`Elasticsearch` 是一個`開源`的`分佈式`、`高擴展`、`高實時`的RESTful `搜索和分析引擎`,基於`Lucene`......") String text){
		//構建並保存Article
		Article article = new Article();
		article.setId(RandomUtil.randomInt(10000,99999));
		article.setTitle(title);
		article.setText(text);
		article.setCreatetime(new Date());
		article.setAuthor("zhengkai.blog.csdn.net");
		articleRepository.save(article);
		return ApiReturnUtil.success(article);
	}

	/**
	 * ElasticSearch之Search封裝查詢
	 * @author  zhengkai.blog.csdn.net
	 * @param title   搜索標題
	 * @param pageable page = 第幾頁參數(第一頁是0), value = 每頁顯示條數
	 */
	@GetMapping("search")
	public Object search(@RequestParam(defaultValue = "SpringBoot") String title, @PageableDefault(page = 0, value = 10) Pageable pageable){
		//以下查詢等同於封裝了{"query":{"bool":{"must":[{"wildcard":{"title.keyword":{"wildcard":"*SpringBoot*","boost":1}}}],"disable_coord":false,"adjust_pure_negative":true,"boost":1}}}
		//按標題進行模糊查詢
		QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("title.keyword", "*SpringBoot*");
		//按照順序構建builder,bool->must->wildcard ,有了上文的JSON,順序就很好理解了
		BoolQueryBuilder must = QueryBuilders.boolQuery().must(queryBuilder);
		//封裝pageable分頁
		Page<Article> queryResult =  articleRepository.search(must,pageable);
		//返回
		return ApiReturnUtil.success(queryResult.getContent());
	}
	/**
	 * ElasticSearch之elasticsearchTemplate查詢
	 * @author  zhengkai.blog.csdn.net
	 * @param title   搜索標題
	 */
	@GetMapping("originSearch")
	public Object originSearch(@RequestParam(defaultValue = "SpringBoot") String title) {
		BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
		QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("title.keyword", "*SpringBoot*");
		BoolQueryBuilder must = boolQuery.must(queryBuilder);
		NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
		NativeSearchQuery build = nativeSearchQueryBuilder.withQuery(must).build();
		List<Article> queryForList = elasticsearchTemplate.queryForList(build, Article.class);
		
		return ApiReturnUtil.success(queryForList);
	}
}

Result效果演示

  1. 連續調用6次左右,http://localhost:9999/es/save進行保存(如果你想用API保存,可以http://localhost:9999/es/new訪問,得到一些JSON數據)
  2. 調用一次http://localhost:9999/es/save?title=ElasticSearch保存一條title不包含SpringBoot的數據(下文根據SpringBoot來檢索)
  3. 打開瀏覽器ElasticSearch HeadDejavu UI插件進行查看(前提是安裝好插件!!!否則請跳過。。。)
  • chrome-extension://ffmkiejjmecolpfloofpjologoblkegm/elasticsearch-head/index.html
  • chrome-extension://jopjeaiilkcibeohjdmejhoifenbnmlh/index.html?appname=article_info&url=http://localhost:9200&mode=edit在這裏插入圖片描述
  1. 在Header插件的Structured Query界面中選擇 must+doc.title.keyword+wildcard+*SpringBoot*的查詢條件,成功查詢到數據。在這裏插入圖片描述
    5.訪問http://localhost:9999/es/search
    在這裏插入圖片描述

或者用ES的RESTful API ,POST以下鏈接:

http://localhost:9200/_search
{“query”:{“bool”:{“must”:[{“wildcard”:{“title.keyword”:{“wildcard”:“SpringBoot”,“boost”:1}}}],“disable_coord”:false,“adjust_pure_negative”:true,“boost”:1}}}

在這裏插入圖片描述

榪滅▼涓繪満寮鴻揩鍏抽棴浜嗕竴涓幇鏈夌殑榪炴帴銆?

這個報錯轉換過來就是:遠程主機強迫關閉了一個現有的連接

exception caught on transport layer [Netty4TcpChannel{localAddress=/127.0.0.1:9300, remoteAddress=/127.0.0.1:53494}], closing connection
java.io.IOException: 榪滅▼涓繪満寮鴻揩鍏抽棴浜嗕竴涓幇鏈夌殑榪炴帴銆?
        at sun.nio.ch.SocketDispatcher.read0(Native Method) ~[?:?]
        at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43) ~[?:?]
        at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:276) ~[?:?]
        at sun.nio.ch.IOUtil.read(IOUtil.java:245) ~[?:?]
        at sun.nio.ch.IOUtil.read(IOUtil.java:223) ~[?:?]
        at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:358) ~[?:?]
        at io.netty.buffer.PooledHeapByteBuf.setBytes(PooledHeapByteBuf.java:261) ~[netty-buffer-4.1.32.Final.jar:4.1.32.Final]
        at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132) ~[netty-buffer-4.1.32.Final.jar:4.1.32.Final]
        at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:347) ~[netty-transport-4.1.32.Final.jar:4.1.32.Final]
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:656) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:556) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:510) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:470) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:909) [netty-common-4.1.32.Final.jar:4.1.32.Final]
        at java.lang.Thread.run(Thread.java:834) [?:?]

版本兼容問題

minimum_index_compatibility_version這裏定義的最低版本會受spring-boot-starter-data-elasticsearch的版本影響。

所以目前推薦ES6,6.8.1左右的版本,比較靠譜。我一開始就是到官網下載最新版本,就被坑了。

如果你看到JAVA控制檯有以下錯誤,基本就是版本兼容性問題了,直接訪問localhost:9200獲取版本信息。

org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available

推斷錯誤的話。可以從一下日誌查找思路,特別是看ES控制檯輸出的內容,可以清楚的看到

closing connection
java.lang.IllegalStateException: Received handshake message from unsupported version: [5.0.0] minimal compatible version is: [6.8.0]

{
  "name" : "WORKPC-MOSHOW",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "fDlrxuUcTjqgvfpWbl3Hcg",
  "version" : {
    "number" : "7.2.0",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "508c38a",
    "build_date" : "2019-06-20T15:54:18.811730Z",
    "build_snapshot" : false,
    "lucene_version" : "8.0.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
[/es] threw exception [Request processing failed; nested exception is NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{mQ1hg9-tT3mvRnfLIAaZHg}{127.0.0.1}{127.0.0.1:9300}]]] with root cause

org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{mQ1hg9-tT3mvRnfLIAaZHg}{127.0.0.1}{127.0.0.1:9300}]
	at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:347) ~[elasticsearch-5.6.11.jar:5.6.11]
	at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:245) ~[elasticsearch-5.6.11.jar:5.6.11]
	at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:59) ~[elasticsearch-5.6.11.jar:5.6.11]
	at org.elasticsearch.client.transport.TransportClient.doExecute(TransportClient.java:366) ~[elasticsearch-5.6.11.jar:5.6.11]
	at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:408) ~[elasticsearch-5.6.11.jar:5.6.11]
	at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:80) ~[elasticsearch-5.6.11.jar:5.6.11]
	at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:54) ~[elasticsearch-5.6.11.jar:5.6.11]
	at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.index(ElasticsearchTemplate.java:571) ~[spring-data-elasticsearch-3.0.10.RELEASE.jar:3.0.10.RELEASE]
	at org.springframework.data.elasticsearch.repository.support.AbstractElasticsearchRepository.save(AbstractElasticsearchRepository.java:156) ~[spring-data-elasticsearch-3.0.10.RELEASE.jar:3.0.10.RELEASE]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
	at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
	at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:641) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:590) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at com.sun.proxy.$Proxy88.save(Unknown Source) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
	at org.zeroturnaround.javarebel.integration.util.ReloadingProxyFactory$ReloadingMethodHandler.invoke(SourceFile:74) ~[na:201907051008]
	at com.sun.proxy.$Proxy88.save(Unknown Source) ~[na:na]
	at com.softdev.system.demo.controller.ArticleController.save(ArticleController.java:38) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:891) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:41002) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) [na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at java.base/java.lang.Thread.run(Thread.java:844) [na:na]
[WARN ][o.e.t.TcpTransport       ] [WORKPC-MOSHOW] exception caught on transport layer [Netty4TcpChannel{localAddress=/127.0.0.1:9300, remoteAddress=/127.0.0.1:64883}], closing connection
java.lang.IllegalStateException: Received handshake message from unsupported version: [5.0.0] minimal compatible version is: [6.8.0]
        at org.elasticsearch.transport.InboundMessage.ensureVersionCompatibility(InboundMessage.java:137) ~[elasticsearch-7.2.0.jar:7.2.0]
        at org.elasticsearch.transport.InboundMessage.access$000(InboundMessage.java:39) ~[elasticsearch-7.2.0.jar:7.2.0]
        at org.elasticsearch.transport.InboundMessage$Reader.deserialize(InboundMessage.java:76) ~[elasticsearch-7.2.0.jar:7.2.0]
        at org.elasticsearch.transport.InboundHandler.messageReceived(InboundHandler.java:116) ~[elasticsearch-7.2.0.jar:7.2.0]
        at org.elasticsearch.transport.InboundHandler.inboundMessage(InboundHandler.java:105) ~[elasticsearch-7.2.0.jar:7.2.0]
        at org.elasticsearch.transport.TcpTransport.inboundMessage(TcpTransport.java:660) [elasticsearch-7.2.0.jar:7.2.0]
        at org.elasticsearch.transport.netty4.Netty4MessageChannelHandler.channelRead(Netty4MessageChannelHandler.java:62) [transport-netty4-client-7.2.0.jar:7.2.0]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:297) [netty-codec-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:241) [netty-handler-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:682) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:582) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:536) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) [netty-transport-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906) [netty-common-4.1.35.Final.jar:4.1.35.Final]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.35.Final.jar:4.1.35.Final]
        at java.lang.Thread.run(Thread.java:834) [?:?]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章