Elastcsearch官方提供了一个elasticsearch-rest-high-level-client,作者在写bug的时候需要将其中的ActionRequest(子类包括SearchRequest、IndexRequest、UpdateRequest等)和SearchResponse类分别做序列化和反序列化。
首先,这两个类都没有实现Serializable接口也无法直接用Json工具序列化为Json字符串。但是官方给我们提供了其它方法,亲测有效,以下作为记录:
ActionRequest(使用SearchRequest作例子):
官方提供了readFrom(StreamInput in)和writeTo(StreamOutput out)方法供使用
public abstract class ActionRequest extends TransportRequest {
...
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
}
...
}
所以,我们实现序列化的核心代码如下:
BytesStreamOutput output = new BytesStreamOutput();
actionRequest.writeTo(output);
//用base64进行编码(如果没有这步,反序列化时会失败)
String s = BaseCoder.encryptBASE64(output.bytes().toBytesRef().bytes);
反序列化:
//base64解码
byte[] s1 = BaseCoder.decryptBASE64(s);
BytesStreamOutput bytesStreamOutput = new BytesStreamOutput();
bytesStreamOutput.write(s1);
//设置解析器
IndicesModule indicesModule = new IndicesModule(Collections.emptyList());
SearchModule searchModule = new SearchModule(Settings.EMPTY, false, Collections.emptyList());
List<NamedWriteableRegistry.Entry> entries = new ArrayList<>();
entries.addAll(indicesModule.getNamedWriteables());
entries.addAll(searchModule.getNamedWriteables());
NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry(entries);
//转换成输入流
StreamInput in= new
NamedWriteableAwareStreamInput(bytesStreamOutput.bytes().streamInput(), namedWriteableRegistry);
//还原
SearchRequest request = new SearchRequest();
actionRequest.readFrom(in);
SearchResponse:
作者在对SearchResponse进行序列化处理时发现上面的办法行不通,于是换了一个办法。es给我们提供了json的解决方式(XContent)。
序列化:
XContentBuilder builder = XContentFactory.jsonBuilder();
XContentBuilder xContent = searchResponse.toXContent(builder, ToXContent.EMPTY_PARAMS);
String jsonResponse = xContent.string();
反序列化:
NamedXContentRegistry namedXContentRegistry = new NamedXContentRegistry(getDefaultNamedXContents());
XContentParser parser = JsonXContent.jsonXContent.createParser(namedXContentRegistry, jsonResponse);
SearchResponse response= SearchResponse.fromXContent(parser);
private static List<NamedXContentRegistry.Entry> getDefaultNamedXContents() {
Map<String, ContextParser<Object, ? extends Aggregation>> map = new HashMap<>();
//这里设置统计字段(Aggregation)
map.put(TopHitsAggregationBuilder.NAME, (p, c) -> ParsedTopHits.fromXContent(p, (String) c));
map.put(DateRangeAggregationBuilder.NAME, (p, c) -> ParsedDateRange.fromXContent(p, (String) c));
map.put(FilterAggregationBuilder.NAME, (p, c) -> ParsedFilter.fromXContent(p, (String) c));
map.put(StringTerms.NAME, (p, c) -> ParsedStringTerms.fromXContent(p, (String) c));
map.put(LongTerms.NAME, (p, c) -> ParsedLongTerms.fromXContent(p, (String) c));
map.put(DoubleTerms.NAME, (p, c) -> ParsedDoubleTerms.fromXContent(p, (String) c));
List<NamedXContentRegistry.Entry> entries = map.entrySet().stream()
.map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue()))
.collect(Collectors.toList());
SearchModule searchModule = new SearchModule(Settings.EMPTY, false, Collections.EMPTY_LIST);
//普通字段
entries.addAll(searchModule.getNamedXContents());
return entries;
}