7

私の春のWebアプリには、jsonに応答するajaxサーブレットがあります(jacksonを使用):

<?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>

次の ajax サービスがあります。

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

ユーザーがログインすると、次のようなものが返されます。

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

ユーザーがログインしていない場合、予期される動作は戻ることです

null

しかし、有効な JSON 応答ではない空の応答を返します (さらに、Content-type ヘッダーが正しくありません)。

なぜこうなった ?
期待される動作を得るための解決策はありますか?

4

2 に答える 2

7

ユーザーがログインしていない場合、予想される動作は null を返すことです

Java と Javascript/JSON の両方で、 nullは有効な値であり、何もない、空、またはエラー/例外とは異なる意味を持つため、これは私の予想される動作です。

Spring は、null 応答を具体的に処理するのではなく、null 応答に応答することを期待しています。その場合、null (Java) の予想される変換は null (JSON) になります
私の予想される変換テーブル:

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


なぜこうなった ?

Spring の場合、null を返すコントローラーは「応答なし」を意味し、「値が null の応答」ではありません。このルールは、@ResponseBody アノテーションを含むすべてのコントローラー メソッドに適用されます。
これにより、後で応答に何かを追加することなく、手動で応答に書き込むことができます。

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

したがって、null を返す場合、Spring はレスポンスにも Content-type ヘッダーにも本文にも何も書き込みません。

期待される動作を得るための解決策はありますか?

私は次の汚いハックを行いました: 応答がコミットされていない場合に応答に null を書き込むフィルタを ajax パスに追加します。

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();
        }
    }

}

このソリューションは、null に応答するメソッドと何も応答しない (void) メソッドを同じ方法で処理します。

于 2013-02-08T08:56:08.317 に答える
0

セッションフィルターはありますか?

エラーに対してグローバルな ajax イベントをバインドし、そこでそれぞれの検証を行うことができると思います。

同様のケースの例を次に示します: spring-security と jQuery を使用して期限切れのセッションを処理する方法は?

于 2013-02-06T23:15:57.300 に答える