springBoot集成es有三种方法:java api、rest client、data-es,主流的是第三种方法,下面分别介绍下:
一、java api:这种方式,官方已经明确表示在ES 7.0版本中将弃用TransportClient
客户端,且在8.0版本中完全移除它。下面以SpringBoot 2.0.5,ES 5.5.0搭配看下集成方法:
1、依赖:
4.0.0
com.glodon
elasticsearch_data
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
1.5.6.RELEASE
1.8
5.5.0
org.springframework.boot
spring-boot-starter-test
org.springframework.boot
spring-boot-starter-web
org.elasticsearch.client
transport
${elasticsearch.version}
org.apache.logging.log4j
log4j-core
2.7
org.apache.commons
commons-lang3
3.8
org.springframework.boot
spring-boot-maven-plugin
2、配置文件:
@Configuration
public class MyConfig {
@Bean
public TransportClient client() throws UnknownHostException {
// 指定集群名,默认为elasticsearch,如果改了集群名,这里一定要加
Settings settings = Settings.builder()
.put("cluster.name", "elasticsearch")
.build();
TransportClient client = new PreBuiltTransportClient(settings);
/*
这里只配置了一个节点的地址然添加进去,也可以配置多个从节点添加进去再返回
*/
InetSocketTransportAddress node = new InetSocketTransportAddress(
InetAddress.getByName("localhost"),
9300
);
client.addTransportAddress(node);
return client;
}
}
3、controller:
@RestController
@RequestMapping("/es")
public class BookController {
@Autowired
private TransportClient client;
@RequestMapping(value = "/go")
public String go() {
return "go1";
}
/**
* 根据id查询
*
* @param id book id
*/
@RequestMapping(value = "/book", method = RequestMethod.GET)
public ResponseEntity> get(@RequestParam("id") String id) {
GetResponse result = client.prepareGet("book", "novel", id).get();
return new ResponseEntity<>(result.getSource(), HttpStatus.OK);
}
/**
* 添加文档
*
* @param id book id
* @param name book name
*/
@RequestMapping(value = "/book", method = RequestMethod.POST)
public ResponseEntity add(@RequestParam("id") String id, @RequestParam("name") String name) {
try {
// 构造ES的文档,这里注意startObject()开始构造,结束构造一定要加上endObject()
XContentBuilder content = XContentFactory.jsonBuilder().startObject().
field("id", id)
.field("name", name)
.endObject();
IndexResponse result = client.prepareIndex("book", "novel")
.setSource(content).get();
return new ResponseEntity<>(result.getId(), HttpStatus.OK);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据id删除book
*
* @param id book id
*/
@RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE)
public ResponseEntity delete(@PathVariable(value = "id") String id) {
DeleteResponse result = client.prepareDelete("book", "novel", id).get();
return new ResponseEntity<>(result.getResult().toString(), HttpStatus.OK);
}
/**
* 更新文档,这里的Book可以不管他,这样做是为了解决PUT请求的问题,随便搞
*/
@RequestMapping(value = "/book", method = RequestMethod.PUT)
public ResponseEntity update(@RequestBody Book book) {
System.out.println(book);
// 根据id查询
UpdateRequest updateRequest = new UpdateRequest("book", "novel", book.getId().toString());
try {
XContentBuilder contentBuilder = XContentFactory.jsonBuilder().startObject();
if (StringUtils.isNotBlank(book.getName())) {
contentBuilder.field("name", book.getName());
}
contentBuilder.endObject();
updateRequest.doc(contentBuilder);
} catch (IOException e) {
e.printStackTrace();
}
// 进行更新
UpdateResponse updateResponse = new UpdateResponse();
try {
updateResponse = client.update(updateRequest).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return new ResponseEntity<>(updateResponse.getResult().toString(), HttpStatus.OK);
}
}
二、rest client:
官方给出来的REST Client有Java Low Level REST Client和Java Hight Level REST Client两个,前者兼容所有版本的ES,后者是基于前者开发出来的,只暴露了部分API,待完善。这种方法是基于HTTP端口去通信的,便于操作,而且跟ES版本几乎没有关系。这个案例中使用Java Low Level REST Client,有如下的一些特点:
最小化依赖;持久连接;跟踪请求和响应的日志记录;可选的集群节点自动发现功能;提供跨所有可用节点的负载平衡;提供节点故障和特定响应代码时的故障转移;提供失败重连的惩罚机制(是否对一个连接失败的节点尝试重连,取决于它连续失败的次数,尝试重连且失败的次数越多,客户端在再次尝试重连这个节点时等的时间就越长。说那么多,太复杂了,其实给一个场景就是:我找你玩儿,你不答应,我伤自尊了,下次去找你我隔了一个星期再去找你,你又不答应,我又伤自尊了,下次再找你的话,那我就隔两个星期,依次类推);下面以es6.4.0为例看下集成方法:
1、依赖:
elasticsearch_data
com.glodon
1.0-SNAPSHOT
4.0.0
es_java_rest
org.elasticsearch.client
elasticsearch-rest-client
6.4.0
org.json
json
20160810
org.apache.maven.plugins
maven-shade-plugin
3.1.0
package
shade
org.apache.http
hidden.org.apache.http
org.apache.logging
hidden.org.apache.logging
org.apache.commons.codec
hidden.org.apache.commons.codec
org.apache.commons.logging
hidden.org.apache.commons.logging
2、配置文件:
@Configuration
public class RestConfig {
@Bean
public RestClient getClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// 如果有多个从节点可以持续在内部new多个HttpHost,参数1是ip,参数2是HTTP端口,参数3是通信协议
RestClientBuilder clientBuilder = RestClient.builder(new HttpHost("localhost", 9200, "http"));
// 添加其他配置,返回来的还是RestClientBuilder对象,这些配置都是可选的
// clientBuilder.setXX()...
// 最后配置好的clientBuilder再build一下即可得到真正的Client
return clientBuilder.build();
}
}
3、controller:
@RestController
@RequestMapping("/rest/book")
public class BookController {
@Autowired
private RestClient client;
// // RequestOptions类保存应在同一应用程序中的多个请求之间共享的部分请求
// private static final RequestOptions COMMON_OPTIONS;
//
// static {
// RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// // 添加所有请求所需的任何标头。
// builder.addHeader("Authorization", "Bearer " + TOKEN);
// // 自定义响应使用者
// builder.setHttpAsyncResponseConsumerFactory(
// new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
// COMMON_OPTIONS = builder.build();
// }
@RequestMapping(value = "/go", method = RequestMethod.GET)
public ResponseEntity go() {
return new ResponseEntity<>("go", HttpStatus.OK);
}
/**
* 同步执行HTTP请求
* @return
* @throws IOException
*/
@RequestMapping(value = "/es", method = RequestMethod.GET)
public ResponseEntity getEsInfo() throws IOException {
// 构造HTTP请求,第一个参数是请求方法,第二个参数是服务器的端点,host默认是http://localhost:9200
Request request = new Request("GET", "/");
// // 设置其他一些参数比如美化json
// request.addParameter("pretty", "true");
// // 设置请求体
// request.setEntity(new NStringEntity("{\"json\":\"text\"}", ContentType.APPLICATION_JSON));
// // 还可以将其设置为String,默认为ContentType为application/json
// request.setJsonEntity("{\"json\":\"text\"}");
/*
performRequest是同步的,将阻塞调用线程并在请求成功时返回Response,如果失败则抛出异常
内部属性可以取出来通过下面的方法
*/
Response response = client.performRequest(request);
// // 获取请求行
// RequestLine requestLine = response.getRequestLine();
// // 获取host
// HttpHost host = response.getHost();
// // 获取状态码
// int statusCode = response.getStatusLine().getStatusCode();
// // 获取响应头
// Header[] headers = response.getHeaders();
// 获取响应体
String responseBody = EntityUtils.toString(response.getEntity());
return new ResponseEntity<>(responseBody, HttpStatus.OK);
}
/**
* 异步执行HTTP请求
* @return
*/
@RequestMapping(value = "/es/asyn", method = RequestMethod.GET)
public ResponseEntity asynchronous() {
Request request = new Request(
"GET",
"/");
client.performRequestAsync(request, new ResponseListener() {
@Override
public void onSuccess(Response response) {
System.out.println("异步执行HTTP请求并成功");
}
@Override
public void onFailure(Exception exception) {
System.out.println("异步执行HTTP请求并失败");
}
});
return null;
}
/**
* 并行异步执行HTTP请求
*/
@RequestMapping(value = "/ps", method = RequestMethod.POST)
public void parallAsyn(@RequestBody Book[] documents) {
// final CountDownLatch latch = new CountDownLatch(documents.length);
// for (int i = 0; i < documents.length; i++) {
// Request request = new Request("PUT", "/posts/doc/" + i);
// //let's assume that the documents are stored in an HttpEntity array
// request.setEntity(documents[i]);
// client.performRequestAsync(
// request,
// new ResponseListener() {
// @Override
// public void onSuccess(Response response) {
//
// latch.countDown();
// }
//
// @Override
// public void onFailure(Exception exception) {
//
// latch.countDown();
// }
// }
// );
// }
// latch.await();
}
/**
* 添加ES对象, Book的ID就是ES中存储的document的ID,所以最好不要为空,自定义生成的ID太浮夸
*
* @return ResponseEntity
* @throws IOException
*/
@RequestMapping(value = "/", method = RequestMethod.POST)
public ResponseEntity add(@RequestBody Book book) throws IOException {
// 构造HTTP请求,第一个参数是请求方法,第二个参数是服务器的端点,host默认是http://localhost:9200,
// endpoint直接指定为index/type的形式
Request request = new Request("POST", new StringBuilder("/book/book/").
append(book.getId()).toString());
// 设置其他一些参数比如美化json
request.addParameter("pretty", "true");
JSONObject jsonObject = new JSONObject(book);
System.out.println(jsonObject.toString());
// 设置请求体并指定ContentType,如果不指定默认为APPLICATION_JSON
request.setEntity(new NStringEntity(jsonObject.toString()));
// 发送HTTP请求
Response response = client.performRequest(request);
// 获取响应体, id: AWXvzZYWXWr3RnGSLyhH
String responseBody = EntityUtils.toString(response.getEntity());
return new ResponseEntity<>(responseBody, HttpStatus.OK);
}
/**
* 根据id获取ES对象
*
* @param id
* @return
* @throws IOException
*/
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ResponseEntity getBookById(@PathVariable("id") String id) {
Request request = new Request("GET", new StringBuilder("/book/book/").
append(id).toString());
// 添加json返回优化
request.addParameter("pretty", "true");
Response response = null;
String responseBody = null;
try {
// 执行HHTP请求
response = client.performRequest(request);
responseBody = EntityUtils.toString(response.getEntity());
} catch (IOException e) {
return new ResponseEntity<>("can not found the book by your id", HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(responseBody, HttpStatus.OK);
}
/**
* 根据id更新Book
*
* @param id
* @param book
* @return
*/
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public ResponseEntity updateBook(@PathVariable("id") String id, @RequestBody Book book) throws IOException {
// 构造HTTP请求
Request request = new Request("POST", new StringBuilder("/book/book/").
append(id).append("/_update").toString());
request.addParameter("pretty", "true");
// 将数据丢进去,这里一定要外包一层“doc”,否则内部不能识别
JSONObject jsonObject = new JSONObject();
jsonObject.put("doc", new JSONObject(book));
request.setEntity(new NStringEntity(jsonObject.toString()));
// 执行HTTP请求
Response response = client.performRequest(request);
// 获取返回的内容
String responseBody = EntityUtils.toString(response.getEntity());
return new ResponseEntity<>(responseBody, HttpStatus.OK);
}
/**
* 使用脚本更新Book
* @param id
* @param
* @return
* @throws IOException
*/
@RequestMapping(value = "/update2/{id}", method = RequestMethod.PUT)
public ResponseEntity updateBook2(@PathVariable("id") String id, @RequestParam("name") String name) throws IOException {
// 构造HTTP请求
Request request = new Request("POST", new StringBuilder("/book/book/").
append(id).append("/_update").toString());
request.addParameter("pretty", "true");
JSONObject jsonObject = new JSONObject();
// 创建脚本语言,如果是字符变量,必须加单引号
StringBuilder op1 = new StringBuilder("ctx._source.name=").append("'" + name + "'");
jsonObject.put("script", op1);
request.setEntity(new NStringEntity(jsonObject.toString(), ContentType.APPLICATION_JSON));
// 执行HTTP请求
Response response = client.performRequest(request);
// 获取返回的内容
String responseBody = EntityUtils.toString(response.getEntity());
return new ResponseEntity<>(responseBody, HttpStatus.OK);
}
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public ResponseEntity deleteById(@PathVariable("id") String id) throws IOException {
Request request = new Request("DELETE", new StringBuilder("/book/book/").append(id).toString());
request.addParameter("pretty", "true");
// 执行HTTP请求
Response response = client.performRequest(request);
// 获取结果
String responseBody = EntityUtils.toString(response.getEntity());
return new ResponseEntity<>(responseBody, HttpStatus.OK);
}
}
三、spring-data-es:Spring提供了本身基于SpringData实现的一套方案spring-data-elasticsearch
,还有后来衍生的spring-boot-data-elasticsearch
,都是一样的,版本之间的搭配建议为:
spring data elasticsearch | elasticsearch |
---|---|
3.1.x | 6.2.2 |
3.0.x | 5.5.0 |
2.1.x | 2.4.0 |
2.0.x | 2.2.0 |
1.3.x | 1.5.2 |
集成方法见下一篇博客:https://blog.csdn.net/w_t_y_y/article/details/109472658