0

我需要你们帮助我,拜托!

当我使用重复、fixed64 或 int64 时,我的应用程序会生成以下错误。

com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field.  This could mean either that the input has been truncated or that an embedded message misreported its own length.
at com.google.protobuf.InvalidProtocolBufferException.truncatedMessage(InvalidProtocolBufferException.java:86)
at com.google.protobuf.CodedInputStream$ArrayDecoder.pushLimit(CodedInputStream.java:1224)
at com.google.protobuf.CodedInputStream$ArrayDecoder.readMessage(CodedInputStream.java:921)
at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:163)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:197)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:209)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:214)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:49)
at ...

**项目 1 **

我的 Protobuf 文件

syntax = "proto3";

option java_package = "br.com.my.project.view";
option java_outer_classname = "CompanyProtos";

message CompanyResponse {
  repeated Company companies = 1;
}
message Company {
  string name = 1;
  fixed32 id = 2;
  fixed64 systemId = 3;
  string aliasName = 4;
  message Address {
    fixed32 addressTypeId = 1;
    string streetType = 2;
    string streetName = 3;
    string streetNumber = 4;
    string streetComplement = 5;
    string neighborhood = 6;
    string city = 7;
    string state = 8;
    string country = 9;
    string zipcode = 10;
  }
  Address address = 5;
  message Phone {
    string name = 1;
    fixed64 number = 2;
  }
  repeated Phone phones = 6;
}

Spring 配置类

@Configuration
public class SpringConfig extends WebMvcConfigurationSupport {

@Bean
public ViewResolver internalResourceViewResolver() {
    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    viewResolver.setViewClass(JstlView.class);
    viewResolver.setPrefix("/WEB-INF/views/");
    viewResolver.setSuffix(".jsp");
    return viewResolver;
}

@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(protobufJsonFormatHttpMessageConverter());
    super.configureMessageConverters(converters);
}

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/index.jsp");
}

@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

@Bean
public ProtobufJsonFormatHttpMessageConverter protobufJsonFormatHttpMessageConverter() {
    return new ProtobufJsonFormatHttpMessageConverter();
}
}

控制器类

@RestController
@RequestMapping("company")
public class CompanyController {

   @Autowired
   private ICompanyBusinessService companyBusinessService;

   @GetMapping(value = {"/name/{name}"},produces = {MediaType.APPLICATION_JSON_UTF8_VALUE,"application/x-protobuf;charset=UTF-8" })
   public CompanyProtos.CompanyResponse getProtobufCompany(
        @RequestHeader(value = "messageId", required = false) String tid,
        @PathVariable(value = "name", required = false) String name) {

    List<Company> companies = companyBusinessService.getCompanies(name);
    CompanyProtos.CompanyResponse.Builder builder = CompanyProtos.CompanyResponse.newBuilder();
    for(Company c : companies) {
        CompanyProtos.Company.Builder companyBuilder = CompanyProtos.Company.newBuilder();
        companyBuilder.setName(c.getName());
        companyBuilder.setId(c.getId());
        companyBuilder.setSystemId(c.getSystemId());
        companyBuilder.setAliasName(c.getAliasName());

        CompanyProtos.Company.Address.Builder addressBuilder = CompanyProtos.Company.Address.newBuilder();
        addressBuilder.setAddressTypeId(c.getAddress().getAddressTypeId());
        addressBuilder.setStreetType(c.getAddress().getStreetType());
        addressBuilder.setStreetName(c.getAddress().getStreetName());
        addressBuilder.setStreetNumber(c.getAddress().getStreetNumber());
        addressBuilder.setStreetComplement(c.getAddress().getStreetComplement());
        addressBuilder.setNeighborhood(c.getAddress().getNeighborhood());
        addressBuilder.setCity(c.getAddress().getCity());
        addressBuilder.setState(c.getAddress().getState());
        addressBuilder.setCountry(c.getAddress().getCountry());
        addressBuilder.setZipcode(c.getAddress().getZipcode());
        addressBuilder.setMailbox(c.getAddress().getMailbox());
        companyBuilder.setAddress(addressBuilder.build()); 

        for(Phone p : c.getPhones()) {
            CompanyProtos.Company.Phone.Builder phoneBuilder = CompanyProtos.Company.Phone.newBuilder();
            phoneBuilder.setName(p.getName());
            phoneBuilder.setNumber(p.getNumber());
            companyBuilder.addPhones(phoneBuilder.build());
        }

        builder.addCompanies(companyBuilder.build());
    }
    return builder.build();
 }
}

**项目 2 **

我的另一个项目。接受者。

....

private ResponseEntity<byte[]> performCall(URI uri, HttpHeaders headers, HttpMethod method) throws Exception {
    RestTemplate rest = new RestTemplate();
    rest.getMessageConverters().add(new ProtobufHttpMessageConverter());
    rest.getMessageConverters().add(new StringHttpMessageConverter());
    rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
    rest.getMessageConverters().add(new ByteArrayHttpMessageConverter());
    HttpEntity<String> request = new HttpEntity<>(headers);
    ResponseEntity<byte[]> response = rest.exchange(uri, method, request, byte[].class);
    return response;
}

public byte[] perform() throws Exception {
    UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://localhost:8080/company/name/MyCompany")
    HttpHeaders headers = new HttpHeaders();
    headers.set("Accept","application/x-protobuf;charset=UTF-8");
    ResponseEntity<byte[]> response = this.performCall(uri, headers, HttpMethod.GET);
    return response.getBody();
}

private convertProtobufToObject(){
try {
        byte[] result = perform();
        CompanyProtos.CompanyResponse companies = CompanyProtos.CompanyResponse.parseFrom(result);
        System.out.println();
    } catch (Exception e) {
        e.printStrackTrace();
    }
}

....

我正在使用 Spring 5.1.4、protobuf-java 3.6.1、protobuf-java-util 3.6.1、protobuf-java-format 1.4、Tomcat 9 和 spring-boot-dependencies 2.1.2.RELEASE 和 .proto 文件是相同的对于这两个项目。

当我在项目 1 中使用 parseFrom 时,它可以工作,但是当我在项目 2 中使用时,它不起作用!

**更新**

好吧,经过几次测试,我找到了答案。问题是 Windows (CP1252) 的编码。我需要在启动tomcat9时添加这个配置:

-Dfile.encoding = CP1252

这可行,但不适用于 UTF-8

你能帮助我吗?

谢谢

4

1 回答 1

0

解决了

我需要创建一个 AbstractHttpMessageConverter 类并实现 writeInternal,我将一个字节数组转换为 Base64。然后我只是在 readInternal 中颠倒了这个过程

于 2019-04-23T16:07:52.060 回答