注: 該集成方式,對Elasticsearch無版本限制,但是需要自行封裝請求,解析結果等。
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>7.3.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency>
客戶端配置RestConfig
@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("134.175.237.32", 9200, "http")); // 添加其他配置,返回來的還是RestClientBuilder對象,這些配置都是可選的 //【1. 設置請求頭】 設置請求頭,每個請求都會帶上這個請求頭 //Header[] defaultHeaders = {new BasicHeader("header", "value")}; //clientBuilder.setDefaultHeaders(defaultHeaders); Header[] defaultHeaders = {new BasicHeader("charset", "utf-8"), new BasicHeader("content-type", "application/json")}; clientBuilder.setDefaultHeaders(defaultHeaders); //【2. 設置超時時間】 設置超時時間,多次嘗試同一請求時應該遵守的超時。默認值為30秒,與默認套接字超時相同。若自定義套接字超時,則應相應地調整最大重試超時 //clientBuilder.setMaxRetryTimeoutMillis(60000); //【3. 設置節點失敗監聽器】設置監聽器,每次節點失敗都可以監聽到,可以作額外處理 /*clientBuilder.setFailureListener(new RestClient.FailureListener() { @Override public void onFailure(Node node) { super.onFailure(node); System.out.println(node.getName() + "==節點失敗了"); } });*/ /*【4. 設置節點選擇器】 配置節點選擇器,客戶端以循環方式將每個請求發送到每一個配置的節點上, 發送請求的節點,用於過濾客戶端,將請求發送到這些客戶端節點,默認向每個配置節點發送, 這個配置通常是用戶在啟用嗅探時向專用主節點發送請求(即只有專用的主節點應該被HTTP請求命中) */ // clientBuilder.setNodeSelector(NodeSelector.SKIP_DEDICATED_MASTERS); // 進行詳細的配置 /* clientBuilder.setNodeSelector(new NodeSelector() { // 設置分配感知節點選擇器,允許選擇本地機架中的節點(如果有),否則轉到任何機架中的任何其他節點。 @Override public void select(Iterable<Node> nodes) { boolean foundOne = false; for (Node node: nodes) { String rackId = node.getAttributes().get("rack_id").get(0); if ("rack_one".equals(rackId)) { foundOne = true; break; } } if (foundOne) { Iterator<Node> nodesIt = nodes.iterator(); while (nodesIt.hasNext()) { Node node = nodesIt.next(); String rackId = node.getAttributes().get("rack_id").get(0); if ("rack_one".equals(rackId) == false) { nodesIt.remove(); } } } } });*/ /* 【5. 配置HTTP異步請求ES的線程數】 配置異步請求的線程數量,Apache Http Async Client默認啟動一個調度程序線程,以及由連接管理器使用的許多工作線程 (與本地檢測到的處理器數量一樣多,取決於Runtime.getRuntime().availableProcessors()返回的數量)。線程數可以修改如下, 這里是修改為1個線程,即默認情況 */ /*clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) { return httpAsyncClientBuilder.setDefaultIOReactorConfig( IOReactorConfig.custom().setIoThreadCount(1).build() ); } });*/ /*【6. 配置連接超時和套接字超時】 配置請求超時,將連接超時(默認為1秒)和套接字超時(默認為30秒)增加, 這里配置完應該相應地調整最大重試超時(默認為30秒),即上面的setMaxRetryTimeoutMillis,一般於最大的那個值一致即60000 */ /* clientBuilder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() { @Override public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) { // 連接5秒超時,套接字連接60s超時 return requestConfigBuilder.setConnectTimeout(5000).setSocketTimeout(60000); } });*/ /*【7. 配置ES安全認證】 如果ES設置了密碼,那這里也提供了一個基本的認證機制,下面設置了ES需要基本身份驗證的默認憑據提供程序 */ /*final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("user", "password")); clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); } });*/ /* 上面采用異步機制實現搶先認證,這個功能也可以禁用,這意味着每個請求都將在沒有授權標頭的情況下發送,然后查看它是否被接受, 並且在收到HTTP 401響應后,它再使用基本認證頭重新發送完全相同的請求,這個可能是基於安全、性能的考慮 */ /*clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { // 禁用搶先認證的方式 httpClientBuilder.disableAuthCaching(); return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); } });*/ /* 【8. 配置通信加密】 配置通信加密,有多種方式:setSSLContext、setSSLSessionStrategy和setConnectionManager(它們的重要性逐漸遞增) */ /*KeyStore truststore = KeyStore.getInstance("jks"); try (InputStream is = Files.newInputStream(keyStorePath)) { truststore.load(is, keyStorePass.toCharArray()); } SSLContextBuilder sslBuilder = SSLContexts.custom().loadTrustMaterial(truststore, null); final SSLContext sslContext = sslBuilder.build(); clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { return httpClientBuilder.setSSLContext(sslContext); } });*/ // 最后配置好的clientBuilder再build一下即可得到真正的Client return clientBuilder.build(); } }
實體類:
public class Book { private String id; private String name; private String author; public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Book{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
Rest Controller:
@RestController @RequestMapping("/book") public class BookController { @Autowired private RestClient client; /**新增 * 添加ES對象, Book的ID就是ES中存儲的document的ID,所以最好不要為空,自定義生成的ID太浮誇 * * @return ResponseEntity * @throws IOException */ @PostMapping("/add") public ResponseEntity<String> add(Book book) throws IOException { // 構造HTTP請求,第一個參數是請求方法,第二個參數是服務器的端點,host默認是http://localhost:9200, // endpoint直接指定為index/type的形式 Request request = new Request("POST", new StringBuilder("/test_db/book/"). append(book.getId()).toString()); // 設置其他一些參數比如美化json request.addParameter("pretty", "true"); String bookString=JSON.toJSONString(book); System.out.println(bookString); // 設置請求體並指定ContentType,如果不指定默認為APPLICATION_JSON request.setEntity(new NStringEntity(bookString, ContentType.APPLICATION_JSON)); // 發送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 */ @GetMapping("/getBookById/{id}") public ResponseEntity<String> getBookById(@PathVariable("id") String id) { Request request = new Request("GET", new StringBuilder("/test_db/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 */ @PostMapping("/updateBook/{id}") public ResponseEntity<String> updateBook(@PathVariable("id") String id, Book book) throws IOException { // 構造HTTP請求 Request request = new Request("POST", new StringBuilder("/test_db/book/"). append(id).append("/_update").toString()); request.addParameter("pretty", "true"); // 將數據丟進去,這里一定要外包一層“doc”,否則內部不能識別 JSONObject jsonObject = new JSONObject(); jsonObject.put("doc", book); 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); } /** * 使用腳本更新Book * @param id * @param * @return * @throws IOException */ @PostMapping("/update2/{id}") public ResponseEntity<String> updateBook2(@PathVariable("id") String id, @RequestParam("name") String name) throws IOException { // 構造HTTP請求 Request request = new Request("POST", new StringBuilder("/test_db/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); } @PostMapping("/deleteById/{id}") public ResponseEntity<String> deleteById(@PathVariable("id") String id) throws IOException { Request request = new Request("DELETE", new StringBuilder("/test_db/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); } /** * 獲取ES對象列表 * * @return * @throws IOException */ @GetMapping("/getBookList") public ResponseEntity<Object> getBookList(@RequestParam("author") String author) { // 構造HTTP請求 Request request = new Request("POST", new StringBuilder("/test_db/book/_search").toString()); // 添加json返回優化 request.addParameter("pretty", "true"); StringBuilder requestBody = new StringBuilder(); requestBody.append("{\"size\":10,\"query\":{\"match\":{\"author\":\""+author+"\"}},\"from\": 0,\"_source\": [\"id\", \"name\", \"author\"]}"); //JSONObject jsonObject = new JSONObject(); // jsonObject.put("doc", requestBody.toString()); request.setEntity(new NStringEntity(requestBody.toString(), ContentType.APPLICATION_JSON)); Response response = null; String responseBody = null; Object result=null; try{ // 執行HTTP請求 response = client.performRequest(request); // 獲取返回的內容 responseBody = EntityUtils.toString(response.getEntity()); Map jsonObject = JSON.parseObject(responseBody); result =jsonObject.get("hits"); System.out.println(result); } catch (IOException e) { e.printStackTrace(); return new ResponseEntity<>("can not found the book by your id", HttpStatus.NOT_FOUND); } return new ResponseEntity<>(result, HttpStatus.OK); }
