QueryResponseWriter 源码解析
看到上一篇
中获取响应回写实例的时候返回类型为:QueryResponseWriter
public final QueryResponseWriter getQueryResponseWriter(String writerName)
QueryResponseWriter responseWriter = core.getQueryResponseWriter("upxiaofeng");
那我们看看QueryResponseWriter 源码
package org.apache.solr.response;
import java.io.IOException;
import java.io.Writer;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
public abstract interface QueryResponseWriter extends NamedListInitializedPlugin
{
public static final String CONTENT_TYPE_XML_UTF8 = "application/xml; charset=UTF-8";
public static final String CONTENT_TYPE_TEXT_UTF8 = "text/plain; charset=UTF-8";
public static final String CONTENT_TYPE_TEXT_ASCII = "text/plain; charset=US-ASCII";
//响应
public abstract void write(Writer paramWriter, SolrQueryRequest paramSolrQueryRequest, SolrQueryResponse paramSolrQueryResponse)
throws IOException;
//获取响应数据类型
public abstract String getContentType(SolrQueryRequest paramSolrQueryRequest, SolrQueryResponse paramSolrQueryResponse);
//初始化
public abstract void init(NamedList paramNamedList);
}
那该如何实现这个接口呢?我们找到solr6.0的包,在solr-6.0.0\solr-6.0.0\example\example-DIH\solr\solr\conf 找到solrconfig.xml
我们找到如下配置:
<queryResponseWriter name="json" class="solr.JSONResponseWriter">
<!-- For the purposes of the tutorial, JSON responses are written as
plain text so that they are easy to read in *any* browser.
If you expect a MIME type of "application/json" just remove this override.
-->
<str name="content-type">text/plain; charset=UTF-8</str>
</queryResponseWriter>
QueryResponseWriter实现之 JSONResponseWriter
那我们看下JSONResponseWriter又是如何实现的,可以参考。下面是JSONResponseWriter的源码。
package org.apache.solr.response;
import java.io.IOException;
import java.io.Writer;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
public class JSONResponseWriter
implements QueryResponseWriter
{
public static String CONTENT_TYPE_JSON_UTF8 = "application/json; charset=UTF-8";
private String contentType = CONTENT_TYPE_JSON_UTF8;
//初始化
//获取配置文件中配置的数据字符类型
//<str name="content-type">text/plain; charset=UTF-8</str>
public void init(NamedList namedList)
{
String contentType = (String)namedList.get("content-type");
if (contentType != null)
this.contentType = contentType;
}
public void write(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp)
throws IOException
{
JSONWriter w = new JSONWriter(writer, req, rsp);
try {
w.writeResponse();
} finally {
w.close();
}
}
public String getContentType(SolrQueryRequest request, SolrQueryResponse response)
{
return this.contentType;
}
}
如下是JSONWriter的源码
package org.apache.solr.response;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.ReturnFields;
import org.apache.solr.util.FastWriter;
//继承TextResponseWriter
class JSONWriter extends TextResponseWriter
{
private String namedListStyle;
private String wrapperFunction;
private static final String JSON_NL_STYLE = "json.nl";
private static final String JSON_NL_MAP = "map";
private static final String JSON_NL_FLAT = "flat";
private static final String JSON_NL_ARROFARR = "arrarr";
private static final String JSON_NL_ARROFMAP = "arrmap";
private static final String JSON_WRAPPER_FUNCTION = "json.wrf";
private static char[] hexdigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
public JSONWriter(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp)
{
super(writer, req, rsp);
this.namedListStyle = req.getParams().get("json.nl", "flat").intern();
this.wrapperFunction = req.getParams().get("json.wrf");
}
public void writeResponse() throws IOException {
if (this.wrapperFunction != null) {
this.writer.write(this.wrapperFunction + "(");
}
Boolean omitHeader = this.req.getParams().getBool("omitHeader");
if ((omitHeader != null) && (omitHeader.booleanValue())) this.rsp.removeResponseHeader();
//this.rsp.getValues()
//获取SolrQueryResponse返回的值
writeNamedList(null, this.rsp.getValues());
if (this.wrapperFunction != null) {
this.writer.write(')');
}
this.writer.write('\n');
}
protected void writeKey(String fname, boolean needsEscaping) throws IOException {
writeStr(null, fname, needsEscaping);
this.writer.write(':');
}
protected void writeNamedListAsMapMangled(String name, NamedList val)
throws IOException
{
//...
}
protected void writeNamedListAsMapWithDups(String name, NamedList val)
throws IOException
{
//...
}
//将返回值处理成json格式
protected void writeNamedListAsArrMap(String name, NamedList val)
throws IOException
{
int sz = val.size();
indent();
writeArrayOpener(sz);
incLevel();
boolean first = true;
for (int i = 0; i < sz; i++) {
String key = val.getName(i);
if (first)
first = false;
else {
writeArraySeparator();
}
indent();
if (key == null) {
writeVal(null, val.getVal(i));
} else {
writeMapOpener(1);
writeKey(key, true);
writeVal(key, val.getVal(i));
writeMapCloser();
}
}
decLevel();
writeArrayCloser();
}
protected void writeNamedListAsArrArr(String name, NamedList val)
throws IOException
{
//...
}
protected void writeNamedListAsFlat(String name, NamedList val)
throws IOException
{
//...
}
public void writeNamedList(String name, NamedList val)
throws IOException
{
if ((val instanceof SimpleOrderedMap))
writeNamedListAsMapWithDups(name, val);
else if (this.namedListStyle == "flat")
writeNamedListAsFlat(name, val);
else if (this.namedListStyle == "map")
writeNamedListAsMapWithDups(name, val);
else if (this.namedListStyle == "arrarr")
writeNamedListAsArrArr(name, val);
else if (this.namedListStyle == "arrmap")
writeNamedListAsArrMap(name, val);
}
public void writeSolrDocument(String name, SolrDocument doc, ReturnFields returnFields, int idx)
throws IOException
{
if (idx > 0) {
writeArraySeparator();
}
indent();
writeMapOpener(doc.size());
incLevel();
boolean first = true;
for (String fname : doc.getFieldNames()) {
if ((returnFields == null) || (returnFields.wantsField(fname)))
{
if (first) {
first = false;
}
else {
writeMapSeparator();
}
indent();
writeKey(fname, true);
Object val = doc.getFieldValue(fname);
if ((val instanceof List))
{
writeArray(name, ((Iterable)val).iterator());
}
else writeVal(fname, val);
}
}
if (doc.hasChildDocuments()) {
if (!first) {
writeMapSeparator();
indent();
}
writeKey("_childDocuments_", true);
writeArrayOpener(doc.getChildDocumentCount());
List childDocs = doc.getChildDocuments();
for (int i = 0; i < childDocs.size(); i++) {
writeSolrDocument(null, (SolrDocument)childDocs.get(i), null, i);
}
writeArrayCloser();
}
decLevel();
writeMapCloser();
}
public void writeStartDocumentList(String name, long start, int size, long numFound, Float maxScore)
throws IOException
{
writeMapOpener(maxScore == null ? 3 : 4);
incLevel();
writeKey("numFound", false);
writeLong(null, numFound);
writeMapSeparator();
writeKey("start", false);
writeLong(null, start);
if (maxScore != null) {
writeMapSeparator();
writeKey("maxScore", false);
writeFloat(null, maxScore.floatValue());
}
writeMapSeparator();
writeKey("docs", false);
writeArrayOpener(size);
incLevel();
}
public void writeEndDocumentList()
throws IOException
{
decLevel();
writeArrayCloser();
decLevel();
indent();
writeMapCloser();
}
public void writeMapOpener(int size)
throws IOException, IllegalArgumentException
{
this.writer.write('{');
}
public void writeMapSeparator() throws IOException {
this.writer.write(',');
}
public void writeMapCloser() throws IOException {
this.writer.write('}');
}
public void writeArrayOpener(int size) throws IOException, IllegalArgumentException {
this.writer.write('[');
}
public void writeArraySeparator() throws IOException {
this.writer.write(',');
}
public void writeArrayCloser() throws IOException {
this.writer.write(']');
}
public void writeStr(String name, String val, boolean needsEscaping)
throws IOException
{
if (needsEscaping)
{
this.writer.write('"');
for (int i = 0; i < val.length(); i++) {
char ch = val.charAt(i);
if (((ch > '#') && (ch != '\\') && (ch < '
')) || (ch == ' ')) {
this.writer.write(ch);
}
else {
switch (ch) {
case '"':
case '\\':
this.writer.write('\\');
this.writer.write(ch);
break;
case '\r':
this.writer.write('\\'); this.writer.write('r'); break;
case '\n':
this.writer.write('\\'); this.writer.write('n'); break;
case '\t':
this.writer.write('\\'); this.writer.write('t'); break;
case '\b':
this.writer.write('\\'); this.writer.write('b'); break;
case '\f':
this.writer.write('\\'); this.writer.write('f'); break;
case '
':
case '
':
unicodeEscape(this.writer, ch);
break;
default:
if (ch <= '\037')
unicodeEscape(this.writer, ch);
else {
this.writer.write(ch);
}
break;
}
}
}
this.writer.write('"');
} else {
this.writer.write('"');
this.writer.write(val);
this.writer.write('"');
}
}
public void writeMap(String name, Map val, boolean excludeOuter, boolean isFirstVal)
throws IOException
{
if (!excludeOuter) {
writeMapOpener(val.size());
incLevel();
isFirstVal = true;
}
boolean doIndent = (excludeOuter) || (val.size() > 1);
for (Map.Entry entry : val.entrySet()) {
Object e = entry.getKey();
String k = e == null ? "" : e.toString();
Object v = entry.getValue();
if (isFirstVal)
isFirstVal = false;
else {
writeMapSeparator();
}
if (doIndent) indent();
writeKey(k, true);
writeVal(k, v);
}
if (!excludeOuter) {
decLevel();
writeMapCloser();
}
}
public void writeArray(String name, Iterator val) throws IOException
{
writeArrayOpener(-1);
incLevel();
boolean first = true;
while (val.hasNext()) {
if (!first) indent();
writeVal(null, val.next());
if (val.hasNext()) {
writeArraySeparator();
}
first = false;
}
decLevel();
writeArrayCloser();
}
public void writeNull(String name)
throws IOException
{
this.writer.write("null");
}
public void writeInt(String name, String val) throws IOException
{
this.writer.write(val);
}
public void writeLong(String name, String val) throws IOException
{
this.writer.write(val);
}
public void writeBool(String name, String val) throws IOException
{
this.writer.write(val);
}
public void writeFloat(String name, String val) throws IOException
{
this.writer.write(val);
}
public void writeDouble(String name, String val) throws IOException
{
this.writer.write(val);
}
public void writeDate(String name, String val) throws IOException
{
writeStr(name, val, false);
}
protected static void unicodeEscape(Appendable out, int ch) throws IOException
{
out.append('\\');
out.append('u');
out.append(hexdigits[(ch >>> 12)]);
out.append(hexdigits[(ch >>> 8 & 0xF)]);
out.append(hexdigits[(ch >>> 4 & 0xF)]);
out.append(hexdigits[(ch & 0xF)]);
}
}