2015-05-30 16 views
15

Tôi có một bộ điều khiển ánh xạ với các chú thích như sau:Spring MVC 4: "application/json" Content Type không được đặt đúng

@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json") 
@ResponseBody 
public String bar() { 
    return "{\"test\": \"jsonResponseExample\"}"; 
} 

Tôi trả về một chuỗi JSON hợp lệ tuy nhiên, content-type khi tôi xem phản hồi trên Công cụ tìm kiếm Chrome trong trình duyệt không phải là application/json nhưng chỉ đơn giản là text/html. Tại sao loại nội dung không được đặt?

My web.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app metadata-complete="true" version="3.0" 
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 

    <display-name>Spring MVC Web Application</display-name> 

    <servlet> 
     <servlet-name>dispatcher</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

    <!-- static assets --> 
    <servlet-mapping> 
     <servlet-name>default</servlet-name> 
     <url-pattern>*.js</url-pattern> 
    </servlet-mapping> 
    <servlet-mapping> 
     <servlet-name>default</servlet-name> 
     <url-pattern>*.css</url-pattern> 
    </servlet-mapping> 

    <servlet-mapping> 
     <servlet-name>dispatcher</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 

    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/dispatcher-servlet.xml</param-value> 
    </context-param> 

    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
</web-app> 

dispatcher-servlet.xml của tôi:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" 
    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.1.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.1.xsd"> 


    <context:annotation-config /> 

    <context:component-scan base-package="com.mydomain.controllers" /> 

    <bean id="viewResolver" 
     class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="prefix" value="/WEB-INF/jsp/" /> 
     <property name="suffix" value=".jsp" /> 
    </bean> 
</beans> 

Sử dụng WildFly 8.1 như máy chủ ứng dụng của tôi.

+0

bạn có sử dụng @ResponseBody và acctualy có một số người lập bản đồ Json? – John

+1

Hãy xem phần còn lại của phương thức, tiêu đề yêu cầu và phản hồi đầy đủ của bạn. –

+0

@SotiriosDelimanolis Đã thêm tất cả. – user1757703

Trả lời

40

Điều đầu tiên phải hiểu là các yếu tố RequestMapping#produces() trong

@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json") 

chỉ phục vụ để hạn chế ánh xạ cho xử lý yêu cầu của bạn. Không có gì khác.

Sau đó, cho rằng phương pháp của bạn có một kiểu trả về của String và được chú thích với @ResponseBody, giá trị trả về sẽ được xử lý bởi StringHttpMessageConverter mà đặt Content-type tiêu đề để text/plain. Nếu bạn muốn tự trả lại chuỗi JSON và đặt tiêu đề thành application/json, hãy sử dụng loại trả lại là ResponseEntity (loại bỏ @ResponseBody) và thêm tiêu đề thích hợp vào nó.

@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json") 
public ResponseEntity<String> bar() { 
    final HttpHeaders httpHeaders= new HttpHeaders(); 
    httpHeaders.setContentType(MediaType.APPLICATION_JSON); 
    return new ResponseEntity<String>("{\"test\": \"jsonResponseExample\"}", httpHeaders, HttpStatus.OK); 
} 

Lưu ý rằng bạn có lẽ nên có

<mvc:annotation-driven /> 

trong cấu hình servlet context của bạn để thiết lập cấu hình MVC của bạn với giá trị mặc định phù hợp nhất.

+1

thư viện Jackson hoạt động hoàn hảo tốt với @ResponseBody – John

+2

@ user3360241 Jackson với '@ ResponseBody' được thực hiện với một' MappingJackson2HttpMessageConverter'. Nó được đăng ký sau một 'StringHttpMessageConverter' và do đó không đóng vai trò gì trong việc xử lý yêu cầu này. –

+0

Hm: http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/, đó cũng chỉ là ví dụ. Tôi sẽ nói rằng op cũng muốn trả về các đối tượng tùy chỉnh như Json. – John

3

Sử dụng thư viện jackson và @ResponseBody chú thích về kiểu trả về cho Bộ điều khiển.

Điều này có tác dụng nếu bạn muốn trả lại POJO được biểu thị dưới dạng JSon. Nếu bạn muốn trả lại String chứ không phải POJO như JSon, vui lòng tham khảo câu trả lời Sotirious.

+1

Tôi đã làm điều đó nhưng nó vẫn không hoạt động. Nó có thể là một cái gì đó để làm với các tập tin cấu hình XML của tôi? Được sử dụng Gson thay vì Jackson nhưng điều tương tự. – user1757703

+0

Thêm chi tiết khác, vui lòng cho chúng tôi thấy sự phụ thuộc và toàn bộ mã của bạn cho bộ điều khiển. – John

+0

Tôi không thể nói về Gson này, tôi đảm bảo với bạn rằng jackson hoạt động mặc dù. – John

1

Như những người khác đã nhận xét, bởi vì kiểu trả về của phương thức của bạn là String Mùa xuân sẽ không cảm thấy cần phải làm gì với kết quả.

Nếu bạn thay đổi chữ ký của bạn để các kiểu trả về là cái gì đó cần marshalling, mà sẽ giúp:

@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json") 
@ResponseBody 
public Map<String, Object> bar() { 
    HashMap<String, Object> map = new HashMap<String, Object>(); 
    map.put("test", "jsonRestExample"); 
    return map; 
} 
-1

Khi tôi nâng cấp để mùa xuân 4 tôi cần phải cập nhật các phụ thuộc jackson như sau:

<dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-core</artifactId> 
     <version>2.5.1</version> 
    </dependency> 
    <dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-databind</artifactId> 
     <version>2.5.1</version> 
    </dependency> 
    <dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-annotations</artifactId> 
     <version>2.5.1</version> 
    </dependency>   
-1

Tôi có các phụ thuộc như được chỉ định @Greg post.Tôi vẫn còn phải đối mặt với vấn đề này và có thể có thể giải quyết nó bằng cách thêm sau thêm phụ thuộc jackson:

<dependency> 
    <groupId>com.fasterxml.jackson.dataformat</groupId> 
    <artifactId>jackson-dataformat-xml</artifactId> 
    <version>2.7.4</version> 
</dependency> 
0

Không chính xác cho OP này, nhưng đối với những người gặp phải 404 và không thể thiết lập phản ứng content-type-"application/json" (bất kỳ content-type). Một khả năng là một máy chủ thực sự đáp ứng 406 nhưng nhà thám hiểm (ví dụ, chrome) in nó như là 404.

Nếu bạn không tùy chỉnh chuyển đổi tin nhắn, mùa xuân sẽ sử dụng AbstractMessageConverterMethodProcessor.java. Nó sẽ chạy:

List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(request); 
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType); 

và nếu họ không có bất kỳ chồng chéo (item giống nhau), nó sẽ ném HttpMediaTypeNotAcceptableException và điều này cuối cùng gây 406. Không có vấn đề nếu nó là một ajax, hoặc GET/POST, hoặc hình thức hành động, nếu yêu cầu uri kết thúc bằng một .html hoặc bất kỳ hậu tố, các requestedMediaTypes sẽ là "text/[suffix rằng]", và xung đột này với producibleMediaTypes, mà thường là:

"application/json" 
"application/xml" 
"text/xml"   
"application/*+xml" 
"application/json" 
"application/*+json" 
"application/json" 
"application/*+json" 
"application/xml" 
"text/xml"   
"application/*+xml" 
"application/xml" 
"text/xml"   
"application/*+xml" 
Các vấn đề liên quan