我使用ExtJS 4前端和Spring 3作为后端创建文件上传。文件上传有效,但服务器的响应内容类型错误。当我使用杰克逊序列化的{success:true}
发送Map<String, Object>
时,ExtJS会返回错误
Uncaught Ext.Error: You're trying to decode an invalid JSON String: <pre style="word-wrap: break-word; white-space: pre-wrap;">{"success":true}</pre>
为什么我的回复包含<pre>
标记?我已经搜索并found out我应该将响应类型更改为text/html
。但changing content type in servlet response没有帮助
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public @ResponseBody Map<String, Object> upload(
FileUpload uploadItem, BindingResult result, HttpServletResponse response) {
response.setContentType("text/html");
// File processing
Map<String, Object> jsonResult = new HashMap<String, Object>();
jsonResult.put("success", Boolean.TRUE);
return jsonResult;
}
当我将upload
方法的返回值更改为String
时,一切正常,但我想返回Map
并将其序列化为杰克逊
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public @ResponseBody String upload(
FileUpload uploadItem, BindingResult result, HttpServletResponse response) {
// File processing
return "{success:true}";
}
我的Spring配置
<bean
id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter">
</bean>
<bean
id="jacksonMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
<ref bean="stringHttpMessageConverter" />
</list>
</property>
</bean>
如何告诉Spring返回正确的内容类型?当正确解释其他方法的响应时,为什么此方法的响应不正确?
答案 0 :(得分:2)
您需要将响应的内容类型设置为“text / html”。 如果内容类型是“application / json”则会出现此问题。这很奇怪。
答案 1 :(得分:1)
如果只需要返回成功值,则可以返回布尔值:
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public @ResponseBody boolean upload(
FileUpload uploadItem, BindingResult result, HttpServletResponse response) {
return true; //or false
}
答案 2 :(得分:0)
嗯,这不是最好的解决方案,但它解决了这个问题。我创建了一个类,里面有Map
,以及将参数添加到Map
的方法。还实现了方法toString()
。
public class ExtJSJsonResponse {
/** Parameters to serialize to JSON */
private Map<String, Object> params = new HashMap<String, Object>();
/**
* Add arbitrary parameter for JSON serialization.
* Parameter will be serialized as {"key":"value"};
* @param key name of parameter
* @param value content of parameter
*/
@JsonIgnore
public void addParam(String key, Object value) {
params.put(key, value);
}
/**
* Gets all parameters. Also is annotated with <code>@JsonValue</code>.
* @return all params with keys as map
*/
@JsonValue
public Map<String, Object> getParams() {
return params;
}
/**
* Returns specified parameter by <code>key</code> as string "key":"value"
* @param key parameter key
* @return "key":"value" string or empty string when there is no parameter
* with specified key
*/
private String paramToString(String key) {
return params.containsKey(key)
? "\"" + key + "\":\"" + params.get(key) + "\""
: "";
}
/**
* Manually transforms map parameters to JSON string. Used when ExtJS fails
* to decode Jackson response. i.e. when uploading file.
* @return
*/
@Override
@JsonIgnore
public String toString() {
StringBuilder sb = new StringBuilder("{");
String delimiter = "";
for (String key : params.keySet()) {
sb.append(delimiter);
sb.append(paramToString(key));
delimiter = ",";
}
sb.append("}");
return sb.toString();
}
}
因此,当Uncaught Ext.Error: You're trying to decode an invalid JSON String
出现时,您只需执行此操作
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public @ResponseBody String upload(
FileUpload uploadItem, BindingResult result, HttpServletResponse response) {
ExtJSJsonResponse response = new ExtJSJsonResponse();
// File processing
response.addParam("success", true);
response.addParam("message", "All OK");
return response.toString();
}
在其他没有序列化问题的方法中,您只需调用return response;
即可自动序列化。
方法toString()
仅适用于简单类,如String。对于更复杂的课程,您必须更改它。
答案 3 :(得分:0)
我认为你可以使用Spring的@RequestMapping注释的“produce”属性:
@RequestMapping(value = "/upload", method = RequestMethod.POST, produces = MediaType.TEXT_HTML_VALUE)
public @ResponseBody Map<String, Object> upload(
FileUpload uploadItem, BindingResult result, HttpServletResponse response) {
// File processing
Map<String, Object> jsonResult = new HashMap<String, Object>();
jsonResult.put("success", Boolean.TRUE);
return jsonResult;
}
在配置文件中,您应该使此Content-Type可用:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<array>
<value>text/html</value>
<value>application/json</value>
</array>
</property>
</bean>
这在Spring 3.1.1.RELEASE中可用,可能在旧版本中它不起作用。