protobuf接口调用报错:java.nio.charset.MalformedInputException: Input length = 1
使用protobuf定义的接口api发起http请求报错,日志如下:
[-- ::] 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: }
[-- ::] DEBUG EnvironmentInterceptor: - EnvironmentInterceptor.preHandle requesturl:http://127.0.0.1:8080/ms-search-war/ms.search.searchService/getSearchRank
[-- ::] DEBUG EnvironmentInterceptor: - RequestHeads,User-Agent=Apache-HttpClient/4.1. (java 1.5),X-Identity-ID=,X-Auth-Token=,X-Login-Type=
[-- ::] ERROR ServletRequestParser: - IOException: request=/ms-search-war/ms.search.searchService/getSearchRank, ex=java.nio.charset.MalformedInputException: Input length =
[-- ::] DEBUG EnvironmentInterceptor: - EnvironmentInterceptor completed, requesturl= http://127.0.0.1:8080/ms-search-war/ms.search.searchService/getSearchRank and server delayTime = 141
我们来看ServletRequestParser的报错代码行:
import java.io.IOException;
import java.math.BigDecimal;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import com.google.protobuf.ByteString;
import com.google.protobuf.Descriptors;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat;
public class ServletRequestParser {
private static final Logger logger = LoggerFactory.getLogger(ServletRequestParser.class); public static Message parse(HttpServletRequest request, Message prototype) {
String requestMethod = request.getMethod();
Descriptors.Descriptor inputType = prototype.getDescriptorForType();
Message.Builder builder = prototype.newBuilderForType();
if (HttpMethod.POST.matches(requestMethod)) {
MediaType contentType = ContentType.BINARY;
try {
contentType = MediaType.valueOf(request.getContentType());
} catch (Exception ex) {
}
try {
if (ContentType.isProtobuf(contentType) || ContentType.isBinary(contentType)) {
return builder.mergeFrom(request.getInputStream()).build();
} else if (ContentType.isJson(contentType)) {
request.setCharacterEncoding("utf-8");
JsonFormat.parser().merge(request.getReader(), builder);
return builder.build();
} else {
logger.error("invalid content-type: {}", contentType);
}
} catch (InvalidProtocolBufferException ex) {
logger.error("InvalidProtocolBuffer: request={}, ex={}", request.getRequestURI(), ex);
} catch (IOException ex) {
logger.error("IOException: request={}, ex={}", request.getRequestURI(), ex);
}
} else if (HttpMethod.GET.matches(requestMethod)) {
for (Descriptors.FieldDescriptor field : inputType.getFields()) {
String[] values = request.getParameterValues(field.getName());
if (null != values && values.length > 0) {
if (!field.isRepeated()) {
Object o = parseFieldValue(field, values[0], builder);
if (null != o) builder.setField(field, o);
} else {
for (String value : values) {
Object o = parseFieldValue(field, value, builder);
if (null != o) builder.addRepeatedField(field, o);
}
}
}
}
return builder.build();
}
return null;
}
这里调用了com.google.protobuf.util.JsonFormat的内部类Parser的merge方法进行转换时报错,因为异常只在这里抛出,所以只能怀疑获取Reader对象的这个request.getReader()方法,跟进代码:
/**
* Wrapper object for the Coyote request.
*
* @author Remy Maucherat
* @author Craig R. McClanahan
*/
public class Request implements org.apache.catalina.servlet4preview.http.HttpServletRequest {
/**
* Read the Reader wrapping the input stream for this Request. The
* default implementation wraps a <code>BufferedReader</code> around the
* servlet input stream returned by <code>createInputStream()</code>.
*
* @return a buffered reader for the request
* @exception IllegalStateException if <code>getInputStream()</code>
* has already been called for this request
* @exception IOException if an input/output error occurs
*/
@Override
public BufferedReader getReader() throws IOException { if (usingInputStream) {
throw new IllegalStateException
(sm.getString("coyoteRequest.getReader.ise"));
} usingReader = true;
inputBuffer.checkConverter();
if (reader == null) {
reader = new CoyoteReader(inputBuffer);
}
return reader; }
这里调用的是catalina的Requst对象的getReader方法,返回的是一个BufferedReader对象,这里最终实例化出了一个CoyoteReader对象。
/**
* Reader.
*/
protected CoyoteReader reader = new CoyoteReader(inputBuffer);
我们来看下CoyoteReader对象:
/**
* Coyote implementation of the buffered reader.
*
* @author Remy Maucherat
*/
public class CoyoteReader
extends BufferedReader { // -------------------------------------------------------------- Constants private static final char[] LINE_SEP = { '\r', '\n' };
private static final int MAX_LINE_LENGTH = 4096; // ----------------------------------------------------- Instance Variables protected InputBuffer ib; protected char[] lineBuffer = null; // ----------------------------------------------------------- Constructors public CoyoteReader(InputBuffer ib) {
super(ib, 1);
this.ib = ib;
} }
再看下它里面的InputBuffer对象:
/**
* The buffer used by Tomcat request. This is a derivative of the Tomcat 3.3
* OutputBuffer, adapted to handle input instead of output. This allows
* complete recycling of the facade objects (the ServletInputStream and the
* BufferedReader).
*
* @author Remy Maucherat
*/
public class InputBuffer extends Reader
implements ByteChunk.ByteInputChannel, ApplicationBufferHandler { /**
* The string manager for this package.
*/
protected static final StringManager sm = StringManager.getManager(InputBuffer.class); private static final Log log = LogFactory.getLog(InputBuffer.class); public static final int DEFAULT_BUFFER_SIZE = 8 * 1024; // The buffer can be used for byte[] and char[] reading
// ( this is needed to support ServletInputStream and BufferedReader )
public final int INITIAL_STATE = 0;
public final int CHAR_STATE = 1;
public final int BYTE_STATE = 2; /**
* Encoder cache.
*/
private static final ConcurrentMap<Charset, SynchronizedStack<B2CConverter>> encoders = new ConcurrentHashMap<>(); // ----------------------------------------------------- Instance Variables /**
* The byte buffer.
*/
private ByteBuffer bb; /**
* The char buffer.
*/
private CharBuffer cb; /**
* State of the output buffer.
*/
private int state = 0; /**
* Flag which indicates if the input buffer is closed.
*/
private boolean closed = false; /**
* Encoding to use.
*/
private String enc; /**
* Current byte to char converter.
*/
protected B2CConverter conv; /**
* Associated Coyote request.
*/
private Request coyoteRequest; /**
* Buffer position.
*/
private int markPos = -1; /**
* Char buffer limit.
*/
private int readLimit; /**
* Buffer size.
*/
private final int size; // ----------------------------------------------------------- Constructors /**
* Default constructor. Allocate the buffer with the default buffer size.
*/
public InputBuffer() { this(DEFAULT_BUFFER_SIZE); } /**
* Alternate constructor which allows specifying the initial buffer size.
*
* @param size Buffer size to use
*/
public InputBuffer(int size) { this.size = size;
bb = ByteBuffer.allocate(size);
clear(bb);
cb = CharBuffer.allocate(size);
clear(cb);
readLimit = size; } }
通过调试发现,当我的请求里没有中文时,CoyoteReader对象的InputBuffer属性的ByteBuffer的hb属性是能取到请求消息体的,而包含了中文则无法获取,protobuf直接转换报错了。
protobuf接口调用报错:java.nio.charset.MalformedInputException: Input length = 1的更多相关文章
- scala文件读取报错“java.nio.charset.MalformedInputException: Input length = 1”
今天写spark程序的时候遇到了一个问题就是,读取文件的时候报了一个错:“Exception in thread "main" java.nio.charset.Malformed ...
- windows中文编码报错 com.google.gson.JsonIOException: java.nio.charset.MalformedInputException: Input length = 1
昨天碰到一个问题:同一个请求页面,页面经过匹配后调用http的post协议接口,部署在linux环境的没问题,本地Eclipse启动的tomcat也没问题,直接启动本地tomcat却报错了: 18:4 ...
- 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 ...
- 我的Java开发学习之旅------>Java NIO 报java.nio.charset.MalformedInputException: Input length = 1异常
今天在使用Java NIO的Channel和Buffer进行文件操作时候,报了java.nio.charset.MalformedInputException: Input length = 1异常, ...
- Caused by: java.nio.charset.MalformedInputException: Input length = 1
java.lang.IllegalStateException: Failed to load property source from location 'classpath:/applicatio ...
- [bug] org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 2
原因 SpringBoot启动加载yml配置文件出现编码格式错误 参考 https://www.pianshen.com/article/2431144034/
- 转载:回编译APK出错:java.nio.char set.MalformedInputException: Input length = 1
使用APKtool回编译APK,出现错误如下: Exception in thread "main" org.yaml.snakeyaml.error.YAMLExcepti ...
- dubbo 使用zookeeper 出现 Dubbo客户端调用报错NullPointerException
现在将网上的方法总结一下 方法一:.https://blog.csdn.net/u011294519/article/details/81810631 dubbo-provider.xml:提供者先扫 ...
- 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 ...
随机推荐
- 移动端点击(click)事件延迟问题的产生与解决方法
http://blog.csdn.net/xjun0812/article/details/64919063 问题的发现 上班做项目的时候碰到一个移动端项目,其中有个小游戏,相当于天上掉馅饼,用户需要 ...
- laravel中Crypt加密方法
使用Crypt::encrypt对数据进行加密,要引入 use Illuminate\Support\Facades\Crypt;; 对使用Crypt::encrypt加密的数据进行解密的方法时:C ...
- Android_布局属性大全
RelativeLayout 第一类:属性值为true可false android:layout_centerHrizontal 水平居中 android:layout_centerVe ...
- SQL SERVER 算法执行效率
较差的性能 <---没有索引(为每个表执行表扫描) --->非聚集非覆盖索引(seek+局部有序扫描+lookups) ---> 聚集索引(seek+局部扫描) ---> 非聚 ...
- bootstrap 获得轮播中的索引 getActiveIndex
今天想用bootstrap做一个轮播,当轮播滚到每张图的时候,在页面下面就显示相对应的内容,那么问题来了:我肯定需要知道当前活动(显示图片)的索引号,那么bootstrap的轮播组件要怎么获得这个索引 ...
- React 与 可视化
一般会想到 canvas 和 svg ; svg更适合画图, 但由于cavans在移动端的良好兼容性, 使用的更广; 什么是svg, scalable vector graphics 全称 可缩放矢 ...
- three.js入门系列之光源
首先创建场景来试验各种光源带来的不同效果: 一.锥形光源(聚光灯) SpotLight 接下来缩小范围(π/7): 二.基础光源(环境光) AmbientLight 上例中没有添加环境光,使得周围黑漆 ...
- 【Keras学习】资源
Keras项目github源码(python):keras-team/keras: Deep Learning for humans 里面的docs包含说明文档 中文文档:Keras中文文档 预训练模 ...
- [Python] 跳过前几行快速读取文件内容:islice
from itertools import islice start = 1 # 跳过第一行idx=0,从idx=1开始读取文件 with codecs.open('data.json', encod ...
- C程序fork进程导致PHP执行不退出
/********************************************************************* * C程序fork进程导致PHP执行不退出 * 说明: * ...