使用protobuf定义的接口api发起http请求报错,日志如下:

  1. [-- ::] DEBUG AbstractPool: - server updated, node=10.211.95.79:, server={ node: 10.211.95.79:, hostname: 10.211.95.79, port: , status: , weight: , capacity: , breaker: { state :CLOSED, working: , delay: , failureThreshold: [/, 0.8], successThreshold: [/, 0.75]}, version: }
  2. [-- ::] DEBUG EnvironmentInterceptor: - EnvironmentInterceptor.preHandle requesturl:http://127.0.0.1:8080/ms-search-war/ms.search.searchService/getSearchRank
  3. [-- ::] DEBUG EnvironmentInterceptor: - RequestHeads,User-Agent=Apache-HttpClient/4.1. (java 1.5),X-Identity-ID=,X-Auth-Token=,X-Login-Type=
  4. [-- ::] ERROR ServletRequestParser: - IOException: request=/ms-search-war/ms.search.searchService/getSearchRank, ex=java.nio.charset.MalformedInputException: Input length =
  5. [-- ::] DEBUG EnvironmentInterceptor: - EnvironmentInterceptor completed, requesturl= http://127.0.0.1:8080/ms-search-war/ms.search.searchService/getSearchRank and server delayTime = 141

  我们来看ServletRequestParser的报错代码行:

  1. import java.io.IOException;
  2. import java.math.BigDecimal;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.xml.bind.DatatypeConverter;
  5.  
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import org.springframework.http.HttpMethod;
  9. import org.springframework.http.MediaType;
  10. import com.google.protobuf.ByteString;
  11. import com.google.protobuf.Descriptors;
  12. import com.google.protobuf.InvalidProtocolBufferException;
  13. import com.google.protobuf.Message;
  14. import com.google.protobuf.util.JsonFormat;
  15. public class ServletRequestParser {
  16. private static final Logger logger = LoggerFactory.getLogger(ServletRequestParser.class);
  17.  
  18. public static Message parse(HttpServletRequest request, Message prototype) {
  19. String requestMethod = request.getMethod();
  20. Descriptors.Descriptor inputType = prototype.getDescriptorForType();
  21. Message.Builder builder = prototype.newBuilderForType();
  22. if (HttpMethod.POST.matches(requestMethod)) {
  23. MediaType contentType = ContentType.BINARY;
  24. try {
  25. contentType = MediaType.valueOf(request.getContentType());
  26. } catch (Exception ex) {
  27. }
  28. try {
  29. if (ContentType.isProtobuf(contentType) || ContentType.isBinary(contentType)) {
  30. return builder.mergeFrom(request.getInputStream()).build();
  31. } else if (ContentType.isJson(contentType)) {
  32. request.setCharacterEncoding("utf-8");
  33. JsonFormat.parser().merge(request.getReader(), builder);
  34. return builder.build();
  35. } else {
  36. logger.error("invalid content-type: {}", contentType);
  37. }
  38. } catch (InvalidProtocolBufferException ex) {
  39. logger.error("InvalidProtocolBuffer: request={}, ex={}", request.getRequestURI(), ex);
  40. } catch (IOException ex) {
  41. logger.error("IOException: request={}, ex={}", request.getRequestURI(), ex);
  42. }
  43. } else if (HttpMethod.GET.matches(requestMethod)) {
  44. for (Descriptors.FieldDescriptor field : inputType.getFields()) {
  45. String[] values = request.getParameterValues(field.getName());
  46. if (null != values && values.length > 0) {
  47. if (!field.isRepeated()) {
  48. Object o = parseFieldValue(field, values[0], builder);
  49. if (null != o) builder.setField(field, o);
  50. } else {
  51. for (String value : values) {
  52. Object o = parseFieldValue(field, value, builder);
  53. if (null != o) builder.addRepeatedField(field, o);
  54. }
  55. }
  56. }
  57. }
  58. return builder.build();
  59. }
  60. return null;
  61. }

  这里调用了com.google.protobuf.util.JsonFormat的内部类Parser的merge方法进行转换时报错,因为异常只在这里抛出,所以只能怀疑获取Reader对象的这个request.getReader()方法,跟进代码:

  1. /**
  2. * Wrapper object for the Coyote request.
  3. *
  4. * @author Remy Maucherat
  5. * @author Craig R. McClanahan
  6. */
  7. public class Request implements org.apache.catalina.servlet4preview.http.HttpServletRequest {
  8. /**
  9. * Read the Reader wrapping the input stream for this Request. The
  10. * default implementation wraps a <code>BufferedReader</code> around the
  11. * servlet input stream returned by <code>createInputStream()</code>.
  12. *
  13. * @return a buffered reader for the request
  14. * @exception IllegalStateException if <code>getInputStream()</code>
  15. * has already been called for this request
  16. * @exception IOException if an input/output error occurs
  17. */
  18. @Override
  19. public BufferedReader getReader() throws IOException {
  20.  
  21. if (usingInputStream) {
  22. throw new IllegalStateException
  23. (sm.getString("coyoteRequest.getReader.ise"));
  24. }
  25.  
  26. usingReader = true;
  27. inputBuffer.checkConverter();
  28. if (reader == null) {
  29. reader = new CoyoteReader(inputBuffer);
  30. }
  31. return reader;
  32.  
  33. }

  这里调用的是catalina的Requst对象的getReader方法,返回的是一个BufferedReader对象,这里最终实例化出了一个CoyoteReader对象。

  1.     /**
         * Reader.
         */
        protected CoyoteReader reader = new CoyoteReader(inputBuffer);

  我们来看下CoyoteReader对象:  

  1. /**
  2. * Coyote implementation of the buffered reader.
  3. *
  4. * @author Remy Maucherat
  5. */
  6. public class CoyoteReader
  7. extends BufferedReader {
  8.  
  9. // -------------------------------------------------------------- Constants
  10.  
  11. private static final char[] LINE_SEP = { '\r', '\n' };
  12. private static final int MAX_LINE_LENGTH = 4096;
  13.  
  14. // ----------------------------------------------------- Instance Variables
  15.  
  16. protected InputBuffer ib;
  17.  
  18. protected char[] lineBuffer = null;
  19.  
  20. // ----------------------------------------------------------- Constructors
  21.  
  22. public CoyoteReader(InputBuffer ib) {
  23. super(ib, 1);
  24. this.ib = ib;
  25. }
  26.  
  27. }

  再看下它里面的InputBuffer对象:

  1. /**
  2. * The buffer used by Tomcat request. This is a derivative of the Tomcat 3.3
  3. * OutputBuffer, adapted to handle input instead of output. This allows
  4. * complete recycling of the facade objects (the ServletInputStream and the
  5. * BufferedReader).
  6. *
  7. * @author Remy Maucherat
  8. */
  9. public class InputBuffer extends Reader
  10. implements ByteChunk.ByteInputChannel, ApplicationBufferHandler {
  11.  
  12. /**
  13. * The string manager for this package.
  14. */
  15. protected static final StringManager sm = StringManager.getManager(InputBuffer.class);
  16.  
  17. private static final Log log = LogFactory.getLog(InputBuffer.class);
  18.  
  19. public static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
  20.  
  21. // The buffer can be used for byte[] and char[] reading
  22. // ( this is needed to support ServletInputStream and BufferedReader )
  23. public final int INITIAL_STATE = 0;
  24. public final int CHAR_STATE = 1;
  25. public final int BYTE_STATE = 2;
  26.  
  27. /**
  28. * Encoder cache.
  29. */
  30. private static final ConcurrentMap<Charset, SynchronizedStack<B2CConverter>> encoders = new ConcurrentHashMap<>();
  31.  
  32. // ----------------------------------------------------- Instance Variables
  33.  
  34. /**
  35. * The byte buffer.
  36. */
  37. private ByteBuffer bb;
  38.  
  39. /**
  40. * The char buffer.
  41. */
  42. private CharBuffer cb;
  43.  
  44. /**
  45. * State of the output buffer.
  46. */
  47. private int state = 0;
  48.  
  49. /**
  50. * Flag which indicates if the input buffer is closed.
  51. */
  52. private boolean closed = false;
  53.  
  54. /**
  55. * Encoding to use.
  56. */
  57. private String enc;
  58.  
  59. /**
  60. * Current byte to char converter.
  61. */
  62. protected B2CConverter conv;
  63.  
  64. /**
  65. * Associated Coyote request.
  66. */
  67. private Request coyoteRequest;
  68.  
  69. /**
  70. * Buffer position.
  71. */
  72. private int markPos = -1;
  73.  
  74. /**
  75. * Char buffer limit.
  76. */
  77. private int readLimit;
  78.  
  79. /**
  80. * Buffer size.
  81. */
  82. private final int size;
  83.  
  84. // ----------------------------------------------------------- Constructors
  85.  
  86. /**
  87. * Default constructor. Allocate the buffer with the default buffer size.
  88. */
  89. public InputBuffer() {
  90.  
  91. this(DEFAULT_BUFFER_SIZE);
  92.  
  93. }
  94.  
  95. /**
  96. * Alternate constructor which allows specifying the initial buffer size.
  97. *
  98. * @param size Buffer size to use
  99. */
  100. public InputBuffer(int size) {
  101.  
  102. this.size = size;
  103. bb = ByteBuffer.allocate(size);
  104. clear(bb);
  105. cb = CharBuffer.allocate(size);
  106. clear(cb);
  107. readLimit = size;
  108.  
  109. }
  110.  
  111. }

  通过调试发现,当我的请求里没有中文时,CoyoteReader对象的InputBuffer属性的ByteBuffer的hb属性是能取到请求消息体的,而包含了中文则无法获取,protobuf直接转换报错了。

protobuf接口调用报错:java.nio.charset.MalformedInputException: Input length = 1的更多相关文章

  1. scala文件读取报错“java.nio.charset.MalformedInputException: Input length = 1”

    今天写spark程序的时候遇到了一个问题就是,读取文件的时候报了一个错:“Exception in thread "main" java.nio.charset.Malformed ...

  2. windows中文编码报错 com.google.gson.JsonIOException: java.nio.charset.MalformedInputException: Input length = 1

    昨天碰到一个问题:同一个请求页面,页面经过匹配后调用http的post协议接口,部署在linux环境的没问题,本地Eclipse启动的tomcat也没问题,直接启动本地tomcat却报错了: 18:4 ...

  3. org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1

    项目启动报错2018-12-21 14:06:24.917 INFO 23472 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refr ...

  4. 我的Java开发学习之旅------>Java NIO 报java.nio.charset.MalformedInputException: Input length = 1异常

    今天在使用Java NIO的Channel和Buffer进行文件操作时候,报了java.nio.charset.MalformedInputException: Input length = 1异常, ...

  5. Caused by: java.nio.charset.MalformedInputException: Input length = 1

    java.lang.IllegalStateException: Failed to load property source from location 'classpath:/applicatio ...

  6. [bug] org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 2

    原因 SpringBoot启动加载yml配置文件出现编码格式错误 参考 https://www.pianshen.com/article/2431144034/

  7. 转载:回编译APK出错:java.nio.char set.MalformedInputException: Input length = 1

    使用APKtool回编译APK,出现错误如下:    Exception in thread "main" org.yaml.snakeyaml.error.YAMLExcepti ...

  8. dubbo 使用zookeeper 出现 Dubbo客户端调用报错NullPointerException

    现在将网上的方法总结一下 方法一:.https://blog.csdn.net/u011294519/article/details/81810631 dubbo-provider.xml:提供者先扫 ...

  9. springcloud采坑--Zuul上传文件报java.nio.charset.IllegalCharsetNameException: UTF-8;boundary=sqgzzmMxl1UPdIp0IAYnQgUIAr9yNewVAzKIX

    报错日志: 2018-12-17 10:01:19,688 ERROR [io.undertow.request] (default task-3) UT005023: Exception handl ...

随机推荐

  1. Xcode各版本

    官方下载, 用开发者账户登录,建议用Safari浏览器下载. 官方下载地址: https://developer.apple.com/xcode/downloads/ Xcode 7 beta 3:h ...

  2. 015PHP基础知识——流程控制(三)

    <?php /** *流程控制(三) */ /* 循环结构: while(){ } */ //设置脚本最长执行时间:100秒 //set_time_limit(100); $lantian = ...

  3. 模式窗体中调用父页面js与非模式化调用非父页面的js方法

    最近项目中使用模式窗体,遇到以下问题记录一下: 模式窗体:你必须关闭该窗体,才能操作其它窗体:比如说,必须按确定或取消,或者按关闭. 非模式窗体:不必关闭该窗体,就可转换到其它窗体上进行操作. 一:非 ...

  4. WIFI 基础知识

    转载自:wifi基本知识 如侵犯您的版权,请联系:2378264731@qq.com 1. IE802.11简介 标准号 IEEE 802.11b IEEE 802.11a IEEE 802.11g ...

  5. Python中注释的添加

    1.Python中注释,有助于我们对程序的理解:但注释不需要每行都写,可以在方法前面注释该方法的功能 或重要的一行进行注释. 2.单行注释,使用#号: 3.多行注释,使用""&qu ...

  6. functools 和 itertools

    functools 补充 1 wraps 在编写装饰器时,在实现前加入 @functools.wraps(func) 可以保证装饰器不会对被装饰函数造成影响.wraps 保存被装饰函数的原信息 def ...

  7. ICE实现服务器客户端

    本文将结合实际项目,做一个基于ice的实际项目实例应用,该实例完成客户端调用服务端接口完成消息发送,计算的功能.1,创建java项目ICEServer,导入ice.jar. 2,在项目下创建slice ...

  8. js之留言字数限制

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  9. a链接嵌套无效,嵌套链接最优解决办法

    <a>不支持嵌套.例如: <a href="#1">11111111111<a href="#2">22222222222& ...

  10. POJ3068 "Shortest" pair of paths 【费用流】

    POJ3068 "Shortest" pair of paths Description A chemical company has an unusual shortest pa ...