Spring Ajax - @ResponseBody -返回空响应

时间:2021-09-09 18:04:49

In my spring webapp, I have an ajax servlet that answer json (using jackson):

在我的spring webapp中,我有一个回答json(使用jackson)的ajax servlet:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <context:component-scan base-package="com.myapp.ajax" />

    <util:list id="messageConvertersList">
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>application/json;charset=UTF-8</value>
                </list>
            </property>
        </bean>
    </util:list>

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters" ref="messageConvertersList" />
    </bean>
    <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
                <property name="paramName" value="lang" />
            </bean>
        </mvc:interceptor>
    </mvc:interceptors>

    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />

    <bean id="handlerExceptionResolver" class="com.myapp.ajax.AjaxExceptionHandlerResolver">
        <property name="exceptionHandler">
            <bean class="com.myapp.ajax.AjaxExceptionHandler" />
        </property>
        <property name="messageConverters" ref="messageConvertersList" />
    </bean>

I have the following ajax service:

我有以下ajax服务:

@RequestMapping(value = "getLoggedUser")
@ResponseBody
public DtoUser getLoggedUser() {
    return authenticationService.getLoggedUser();
}

When the user is logged in it returns something like:

当用户登录时,返回如下内容:

{ userName : "jojo", email : "john.doe@email.com", firstName : "John", lastName : "Doe" }

When the user is not logged in, the expected behavior is to return

当用户没有登录时,预期的行为是返回

null

But it returns an empty response which is not a valid JSON response (and additionally with a bad Content-type header)

但是它返回一个空响应,这不是一个有效的JSON响应(另外还有一个糟糕的内容类型头)

Why is this happening ?
Do I have solutions to obtain the expected behaviour ?

为什么会这样?我是否有办法获得预期的行为?

2 个解决方案

#1


6  

When the user is not logged in, the expected behavior is to return null

当用户没有登录时,预期的行为是返回null

That's my expected behaviour because in both Java and Javascript/JSON, null is a valid value, which have a different mean than nothing, empty or error/exception.

这是我的预期行为,因为在Java和Javascript/JSON中,null都是一个有效值,它的均值不同于无、空或错误/异常。

I would expect that Spring answer the null response instead of handling it specifically. In that case, the expected convertion for null (Java) would be null (JSON)
My expected conversion table:

我希望Spring会回答空响应而不是专门处理它。在这种情况下,null (Java)的期望转换将是null (JSON)我的期望转换表:

Java Exception => HTTP Error Code
null => null
empty map / object => {}
void => no response


Why is this happening ?

为什么会这样?

For Spring, a controller returning null mean "No response" and not "a response which value is null". This rule applies to all controller methods including ones with @ResponseBody annotation.
This allow to write manually to the response without having something appended to the response later:

对于Spring,返回null的控制器表示“没有响应”,而不是“值为null的响应”。此规则适用于所有控制器方法,包括带有@ResponseBody注释的方法。这样就可以手工编写响应,而不必在以后的响应中添加一些内容:

if (mySpecialCase) {
    Writer writer = response.getWriter();
    writer.write("my custom response");
    return null;
} else {
     return myObject;
}

So when returning null Spring write nothing to the response, nor Content-type header nor body.

因此,当返回null Spring时,不向响应写任何内容类型的头或主体。

Do I have solutions to obtain the expected behaviour ?

我是否有办法获得预期的行为?

I made the following dirty hack: add a filter on my ajax path that write null to the response when no response have been commited.

我做了如下肮脏的修改:在ajax路径上添加一个过滤器,当没有响应被引用时,该过滤器将null写入响应。

public class AjaxEmptyResponseFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(request, response);
        if (!response.isCommitted()) {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            Writer writer = response.getWriter();
            writer.write("null");
            writer.close();
            response.flushBuffer();
        }
    }

}

This solution handle methods answering null and method answering nothing (void) the same way.

此解决方案以相同的方式处理回答null的方法和回答none (void)的方法。

#2


0  

Do you have a session filter?

你有会话过滤器吗?

I think, you can bind a global ajax event for errors and make your respective validation there.

我认为,您可以为错误绑定全局ajax事件,并在那里进行相应的验证。

here is a example on a similar case: How to handle expired session using spring-security and jQuery?

这里有一个类似的例子:如何使用spring-security和jQuery处理过期的会话?

#1


6  

When the user is not logged in, the expected behavior is to return null

当用户没有登录时,预期的行为是返回null

That's my expected behaviour because in both Java and Javascript/JSON, null is a valid value, which have a different mean than nothing, empty or error/exception.

这是我的预期行为,因为在Java和Javascript/JSON中,null都是一个有效值,它的均值不同于无、空或错误/异常。

I would expect that Spring answer the null response instead of handling it specifically. In that case, the expected convertion for null (Java) would be null (JSON)
My expected conversion table:

我希望Spring会回答空响应而不是专门处理它。在这种情况下,null (Java)的期望转换将是null (JSON)我的期望转换表:

Java Exception => HTTP Error Code
null => null
empty map / object => {}
void => no response


Why is this happening ?

为什么会这样?

For Spring, a controller returning null mean "No response" and not "a response which value is null". This rule applies to all controller methods including ones with @ResponseBody annotation.
This allow to write manually to the response without having something appended to the response later:

对于Spring,返回null的控制器表示“没有响应”,而不是“值为null的响应”。此规则适用于所有控制器方法,包括带有@ResponseBody注释的方法。这样就可以手工编写响应,而不必在以后的响应中添加一些内容:

if (mySpecialCase) {
    Writer writer = response.getWriter();
    writer.write("my custom response");
    return null;
} else {
     return myObject;
}

So when returning null Spring write nothing to the response, nor Content-type header nor body.

因此,当返回null Spring时,不向响应写任何内容类型的头或主体。

Do I have solutions to obtain the expected behaviour ?

我是否有办法获得预期的行为?

I made the following dirty hack: add a filter on my ajax path that write null to the response when no response have been commited.

我做了如下肮脏的修改:在ajax路径上添加一个过滤器,当没有响应被引用时,该过滤器将null写入响应。

public class AjaxEmptyResponseFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(request, response);
        if (!response.isCommitted()) {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            Writer writer = response.getWriter();
            writer.write("null");
            writer.close();
            response.flushBuffer();
        }
    }

}

This solution handle methods answering null and method answering nothing (void) the same way.

此解决方案以相同的方式处理回答null的方法和回答none (void)的方法。

#2


0  

Do you have a session filter?

你有会话过滤器吗?

I think, you can bind a global ajax event for errors and make your respective validation there.

我认为,您可以为错误绑定全局ajax事件,并在那里进行相应的验证。

here is a example on a similar case: How to handle expired session using spring-security and jQuery?

这里有一个类似的例子:如何使用spring-security和jQuery处理过期的会话?