requestmapping 参数没设置好 导致返回的protobuf解析报错

背景:使用protobuf2做与前端的数据交互,自己用junit测试的时候没问题,但是前端人员访问接口,总是报错:
com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag.

刚开始以为是protobuf jar包版本不一致导致的问题,后来自己用不同版本的protobuf访问接口也没问题。找啊找都没找到问题出在哪儿,后来前端的同学说正常应该返回二进制数据,但是我们返回的是个string,根据这个点找到了问题。

结果就是:接口没指定返回的数据类型,

RequestMapping("api/getC")改成  @RequestMapping(value = "api/getC", produces = "application/x-protobuf").

问题解决后,回去看为什么自己写的junitTest没问题,然后发现有指定accept,如图153行代码:

requestmapping 参数没设置好 导致返回的protobuf解析报错_第1张图片

,当我删掉produces配置再把153行删掉,果然报错了。

后记1:

produces :指定返回值类型,还设定返回值的字符编码;对应header里面的Accept;

consumes:指定处理请求的提交内容类型;对应header里面的Content-Type);

后记2: 查询资料过程中,又在思考,框架是怎么根据这些参数去返回数据的呢。这里是spring的HttpMessageConverter这个类起作用的,springmvc默认会加载StringHttpMessageConverter、ByteArrayHttpMessageConverter等,配置如图。


@Configuration
public class SpringMVCConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters(List> converters) {
        StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
        stringConverter.setDefaultCharset(Charsets.UTF_8);
        stringConverter.setSupportedMediaTypes(Arrays.asList(MediaType.parseMediaType("text/plain;charset=UTF-8")));
        converters.add(stringConverter);

        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        fastConverter.setSupportedMediaTypes(Lists.newArrayList(MediaType.APPLICATION_JSON_UTF8));
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        converters.add(fastConverter);

        converters.add(new ProtobufHttpMessageConverter());
    }

    @Override
    public void addArgumentResolvers(List argumentResolvers) {
        argumentResolvers.add(new HeaderArgumentResolver());
    }
}

mvc会根据request中的content-type,遍历messageConverters中的converter,如果(targetClass != null && converter.canRead(targetClass, contentType))==true 说明找到了对应的转换器,如果debug模式可以看到如下日志:

Read [class com.cc.apply.QueryRequest] as "application/x-protobuf;charset=UTF-8" with [org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter@20413045]

canRead方法调用的其实是 AbstractHttpMessageConverter的canRead方法:

public boolean canRead(Class clazz, MediaType mediaType) {
    return this.supports(clazz) && this.canRead(mediaType);
}

返回的时候调用AbstractHttpMessageConverter的canWrite方法,确定适用的转换器为protobuf,writeIternal()

requestmapping 参数没设置好 导致返回的protobuf解析报错_第2张图片

找到一篇把整个流程写的比较清楚的:https://blog.csdn.net/everyok/article/details/81350894 留看

你可能感兴趣的:(springMVC)