带有null返回值的Spring Ajax @ResponseBody

时间:2014-09-03 17:30:57

标签: java ajax spring jackson

我有大约50个使用@ResponseBody注释的控制器。

像这样:

@RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET)
public @ResponseBody Object getObject(@RequestParam("id") Long id) {
    Object object = provider.getObject(id);
    return object;
}

有时候getObject方法返回null。问题是,在客户端,我得到空响应而不是null

在初始实现中,我们有自定义JsonView对象,它作为包装器而没有@ResponseBody注释。

像这样:

@RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET)
public JsonView<Object> getObject(@RequestParam("id") Long id) {
    Object object = provider.getObject(id);
    return new JsonView(object);
}

所以它工作正常。

我在How do you override the null serializer in Jackson 2.0?找到了一些解决方案但不幸的是它仅适用于POJO中的字段。

您有什么想法可以处理吗?

提前致谢!

3 个答案:

答案 0 :(得分:6)

这不是一个需要解决的小问题。

Spring有一个共同的模式,如果一个处理程序方法返回null,它意味着指示处理程序已经处理了生成和编写适当的响应内容,并且前面不需要进一步的操作

Spring已在其RequestResponseBodyMethodProcesserHandlerMethodReturnValueHandler的{​​{1}}实现)中应用此模式。它检查返回值是否为@ResponseBody。它将请求设置为已处理。如果返回值不是null,则会尝试使用适当的null对其进行序列化。

一种选择是创建自己的HttpMessageConverter注释和相应的@ResponseBodyNull,除了处理HandlerMethodReturnValueHandler外,它们也会相同。请注意,您无法重复使用null中的代码,因为有些RequestResponseBodyMethodProcess会尝试使用HttpMessageConverters失败。

另一个类似的选项是覆盖null以接受RequestResponseBodyMethodProcessor(具有上述限制),并使用null明确注册,覆盖默认RequestMappingHandlerMapping。你必须小心地这样做(即注册相同的),除非你想失去功能。

更好的解决方案IMO将不在响应机构中处理HandlerMethodReturnValueHandler。如果null没有返回任何内容,那对我来说就好像是404。设置适当的响应代码,瞧!

您始终可以将getObject注入到处理程序方法中并执行类似

的操作
HttpServletResponse

假设您知道必须将其序列化为JSON。

答案 1 :(得分:2)

当对象为空时,您可以返回ResponseEntity并将HTTP状态指定为错误:

@RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET)
public ResponseEntity<Object> getObject(@RequestParam("id") Long id) {
    Object object = provider.getObject(id);
    if (object == null ) {
        return new ResponseEntity<Object> (HttpStatus.BAD_REQUEST); // Or any other error status
    } else {
        return new ResponseEntity<Object> (object, HttpStatus.OK);
    }
}

通过这种方式,您的客户端将能够知道对象何时为空,检查响应状态。

如果您确实需要返回null值,可以将Jackson配置为序列化(来自tkuty的代码):

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                    <property name="serializationInclusion">
                        <value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
                    </property>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

我希望这对你有所帮助。

答案 2 :(得分:-3)

首先,我建议你不要这样写:

@RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET)
public @ResponseBody Object getObject(@RequestParam("id") Long id) {
    /*
    */
}

将其作为标准代码。试试这个:

@RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET)
@ResponseBody
public Object getObject(@RequestParam("id") Long id) {
    Object object = provider.getObject(id);
    return object;
}

我有高质量扫描仪的经验,这种方式可以帮助您避免扫描仪发现错误。关于您的问题,您可以尝试使用Transformer或addScala()来返回POJO。我遇到了这个麻烦,并达成了协议!祝你好运。