我正在使用Spring MVC 4.1.5,它的REST支持試圖獲得使用google協議緩衝區消息格式的web服務。我看到很多帖子都提到這個問題與JSON格式,但沒有與谷歌協議緩衝區格式。 我也沒有看到Spring框架文檔有protobufs(低於更多),我的代碼在這裏張貼在githubspring mvc rest protocol buffers http 406不可接受的錯誤
這裏是我的控制器代碼(使用或不使用的MediaType產生=「應用xprotobuf」不做區別 - 這裏同樣406不接受錯誤)
@RestController
@RequestMapping("/ws")
@EnableWebMvc
public class CustomerRestController {
@Autowired
private CustomerRepository customerRepository;
//@RequestMapping(value="/customers/{id}", method = RequestMethod.GET, produces="application/x-protobuf")
@RequestMapping(value="/customers/{id}", method = RequestMethod.GET)
public CustomerProtos.Customer customer(@PathVariable Integer id) {
return this.customerRepository.findById(id);
}
@Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
private CustomerProtos.Customer customer(int id, String f, String l, Collection<String> emails) {
String emailAddressString = "[email protected]";
for (String email : emails) {
emailAddressString = email;
break;
}
EmailAddress emailAddress = CustomerProtos.Customer.EmailAddress.newBuilder()
.setType(CustomerProtos.Customer.EmailType.PROFESSIONAL).setEmail(emailAddressString).build();
return CustomerProtos.Customer.newBuilder().setFirstName(f).setLastName(l).setId(id).addEmail(emailAddress)
// .addAllEmail(emailAddresses)
.build();
}
@Bean
CustomerRepository customerRepository() {
return new CustomerRepositoryImpl();
}
}
是我的web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>demo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/rest-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
,這裏是我的pom.xml,請注意,我確實有谷歌的protobuf libaries添加在這裏和他們的最終WEB-INF/lib目錄部署的.war文件的文件夾。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.0.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.DemoApplication</start-class>
<java.version>1.8</java.version>
<jackson.version>2.5.3</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.protobuf-java-format</groupId>
<artifactId>protobuf-java-format</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-legacy</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
這裏是我的測試客戶端
package demo;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class DemoApplicationTests {
@Configuration
public static class RestClientConfiguration {
@Bean
RestTemplate restTemplate(ProtobufHttpMessageConverter hmc) {
return new RestTemplate(Arrays.asList(hmc));
}
@Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
}
@Autowired
private RestTemplate restTemplate;
@Test
public void contextLoaded() {
ResponseEntity<CustomerProtos.Customer> customer = restTemplate.getForEntity(
"http://localhost:7001/demo-0.0.1-SNAPSHOT/ws/customers/2", CustomerProtos.Customer.class);
System.out.println("customer retrieved: " + customer.toString());
}
}
當我使用MVN測試 從命令行運行客戶端,我得到以下錯誤
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.697 sec <<< FAILURE! - in demo.DemoApplicationTests
contextLoaded(demo.DemoApplicationTests) Time elapsed: 0.037 sec <<< ERROR!
org.springframework.web.client.HttpClientErrorException: 406 Not Acceptable
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:641)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:597)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557)
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:289)
at demo.DemoApplicationTests.contextLoaded(DemoApplicationTests.java:42)
我看到人們使用contentNegotiationManager
提示在我的rest-servlet.xml中我有mvc:anno塔季翁驅動標籤
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="demo" />
<mvc:annotation-driven />
</beans>
而且我在webConfig.java已經下降在演示包
package demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
/**
* Total customization - see below for explanation.
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false).
favorParameter(true).
parameterName("mediaType").
ignoreAcceptHeader(true).
useJaf(false).
defaultContentType(MediaType.TEXT_PLAIN).
mediaType("xml", MediaType.APPLICATION_XML).
mediaType("json", MediaType.APPLICATION_JSON).
mediaType("x-protobuf", MediaType.ALL)
;
}
}
我得到的406不接受錯誤與不webconfig.java(這是做的工作contentNegotationManager)。
我一直無法在Spring 4.1.3或甚至4.2.3 jars中找到MediaType.APPLICATION_XPROTOBUF。
所以我已經離開該值MediaType.ALL(我認爲這應該工作?)
當我運行測試客戶端我實際運行測試之前得到這個消息..
09:27:26.198 [main] DEBUG o.s.web.client.RestTemplate - Created GET request for "http://localhost:7001/demo-0.0.1-SNAPSHOT/ws/customers/2"
09:27:26.199 [main] DEBUG o.s.web.client.RestTemplate - Setting request Accept header to [application/x-protobuf, text/plain, application/xml, application/json]
09:27:26.245 [main] DEBUG o.s.web.client.RestTemplate - GET request for "http://localhost:7001/demo-0.0.1-SNAPSHOT/ws/customers/2" resulted in 406 (Not Acceptable); invoking error
handler
它清楚地顯示了它將accept頭設置爲包含「application-xprotobuf」值。 不知道我在這種情況下缺少什麼。
你可以再試一次適當的Spring Boot應用程序(嘗試使用start.spring.io)。我可以在這裏看到多種氣味,這可能會導致很多問題:1)您不需要自己添加spring-mvc作爲依賴項,也不需要自己指定spring版本2)不應該有BootWebMvc註釋,因爲它是由Boot完成的。 3)web.xml和rest-servlet.xml文件不應該在那裏4)你應該刪除儘可能多的噪音,這裏不涉及你的問題 –
我可以做的那些步驟,除了我需要保持網頁。 xml和rest-servlet.xml,因爲我試圖讓它在支持Java6的servlet 2.5容器上工作。我見過Spring啓動文檔提到如果我在一個servlet 2.5容器中運行,我將需要該web.xml ..將讓你張貼。 thx的迴應。 –
預定義的MediaType常量只是一個便利功能。你可以創建你想要的媒體類型! 只需創建您自己的實例是這樣的: 新的MediaType(「應用程序/ x-protobuf的」) 還有一些其他的構造函數亞型,提供的字符集等。 –