読者です 読者をやめる 読者になる 読者になる

( ꒪⌓꒪) ゆるよろ日記

( ゚∀゚)o彡°オパーイ!オパーイ! ( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

SAStruts + JQueryでのAjaxリクエスト判定の方法

はーい、元気ですかー?ロックンロール!


今現在、SAStrutsを使い始めて2つめのプロジェクトを荒々しくコーディング中なんですが、今回はJQueryを利用したAjax処理をあちこちで採用してます。
マスタ管理とかの一覧のページングとかはAjaxだし、追加・更新もajaxlightbox風な感じで表示してるし。


で、リクエストが正常に処理された場合はおkなんですが、入力エラーだったりセッションが切れてたり例外が出たときに、デフォルトのままエラー画面とかにforwardすると、ブラウザ側でエライことになっちまいますよね?
divの中にエラー画面がloadされたり、javascriptをevalしようとしたら実はHTMLだったぜ的な。


そこで、今回はRequestのヘッダーの中身によって、Ajaxでのリクエストなのか、クライアントはHTMLを期待しているのかそれともjavascriptやjsonを期待しているのかを判定して、forward先を変更する処理を実装しました。


例外処理の場合は、ExceptionHandlerの中で、こんな感じでAjaxか判定してますよ。

@Override
public ActionForward execute(Exception ex, ExceptionConfig ae,
    ActionMapping mapping, ActionForm formInstance,
    HttpServletRequest request, HttpServletResponse response)
    throws ServletException 
{

    if( isAjax( request ){
        if(isRequiredJs( request ) ){
           return new ActionForward( "/WEB-INF/view/ajaxErrorJs.jsp" , false);
        }
        
        return new ActionForward( "/WEB-INF/view/ajaxError.jsp" , false);
    }
    return super.execute(ex, ae, mapping, formInstance, request, response)
}

static boolean isAjax( HttpServletRequest request ){
    return StringUtil.equals("XMLHttpRequest", request.getHeader("X-Requested-With"));
}

static boolean isRequiredJs(HttpServletRequest request ){
    return ( StringUtil.contains(accept, "text/javascript") ||
             StringUtil.contains(accept, "application/javascript") );
}

えー、boolean isAjax( HttpServletRequest request )で、JQueryから$.ajax()や$(selector).load()などでリクエストすると、HTTPHeaderにX-Requested-With:XMLHttpRequestと設定されるのを利用して、ajaxのリクエストであるか判定してます。


ただ、このままでは、ブラウザがHTMLが欲しいのかjavascriptが欲しいのか分かりません。
HTMLが欲しい場合はエラーメッセージをdivの中に表示したいし、javascriptの場合はエラーメッセージをalertするなりdivにつっこむなりのスクリプトを返すようにしたいわけです。


そこで、boolean isRequiredJs(HttpServletRequest request )でHTTPHeaderのAcceptを見て、"text/javascript"や"application/javascript"が含まれていればjavascriptを要求しているものとして判定しています。


同様の対応で、セッションが切れいている場合や入力エラーの場合にも、forward先のjspを切り替えることで対応できると思います。


ただし、HTMLを要求する場合は$(selector).load()を利用し、javascriptを要求する場合は$.ajax()でdataType:'script'を指定してリクエストを送るということが前提条件となります。


とりあえず、Firefoxsafariではこの方法でうまくいってます。IEは試してません。
ってか、IE摘発しろ!