Solr 6.0 學習(十)QueryResponseWriter 源碼解析

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)]);
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章