LoginSignup
30
27

More than 1 year has passed since last update.

SAStrutsとJSON

Last updated at Posted at 2013-05-05

今更感がありますが、SAStrutsでJSONを処理できるようにしてみました。

JSONリクエスト

SAStrutsはS2RequestProcessor.javaでHTTPリクエストをアクションフォームにコピーしているので、JSONリクエストの処理はその直前で行います。
JSONデータの読み込みはJacksonを使いました。

S2JSONRequestProcessor.java
package sample.sastruts.json.action;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.seasar.framework.beans.util.Beans;
import org.seasar.framework.util.ReaderUtil;
import org.seasar.struts.action.S2RequestProcessor;
import org.seasar.struts.util.S2ActionMappingUtil;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

public class S2JSONRequestProcessor extends S2RequestProcessor {

    @Override
    protected void processPopulate(HttpServletRequest request,
            HttpServletResponse response, ActionForm form, ActionMapping mapping)
            throws ServletException {

        if (form == null) {
            return;
        }

        String contentType = request.getContentType();
        String method = request.getMethod();
        if (contentType != null && contentType.startsWith("application/json")
                && "POST".equalsIgnoreCase(method)) {

            form.setServlet(servlet);
            form.setMultipartRequestHandler(null);
            processExecuteConfig(request, response, mapping);
            form.reset(mapping, request);

            Object actionForm = S2ActionMappingUtil.getActionMapping()
                    .getActionForm();
            try {
                ObjectMapper  mapper = new ObjectMapper();
                mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

                String postBody = ReaderUtil.readText(request.getReader());
                Object value = mapper.readValue(postBody, actionForm.getClass());

                Beans.copy(value, actionForm).execute();

            } catch (IOException e) {
                log.error(e.getMessage(), e);
                throw new ServletException(e.getMessage(), e);
            }

        } else {

            super.processPopulate(request, response, form, mapping);

        }
    }

}

一番キモとなっているのは以下の部分です。
JSONリクエストをactionForm.getClass()型としてvalueに読み込んでいるので、actionFormに値をコピーできます。

ObjectMapper  mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

String postBody = ReaderUtil.readText(request.getReader());
Object value = mapper.readValue(postBody, actionForm.getClass());

Beans.copy(value, actionForm).execute();

このクラスをstruts-config.xmlprocessorClassに設定すると利用できます。

struts-config.xml
<controller
    maxFileSize="1024K"
    bufferSize="1024"
    processorClass="sample.sastruts.json.action.S2JSONRequestProcessor"
    multipartClass="org.seasar.struts.upload.S2MultipartRequestHandler"/>

JSONレスポンス

SAStrutsのアクションは遷移先のパスを戻り値に書いてJSP等と連携しますがnullを返却すると遷移しません。これを利用しつつアクションからHTTPレスポンスに直接JSONを書き出します。
JavaオブジェクトからJSONの変換もJacksonを使っています。

XXXAction.java
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.seasar.struts.annotation.Execute;
import org.seasar.struts.util.ResponseUtil;

public class XXXAction {
    @Execute(validator = false)
    public String xxx() throws JsonProcessingException {
        String[] result = {"foo", "bar"};
        ObjectMapper mapper = new ObjectMapper();
        ResponseUtil.write(mapper.writeValueAsString(result), "application/json", "UTF-8");

        return null;
    }
}

追記

スマートなJSONレスポンスの実装方法の解説がありましたので、そちらもご覧下さい。
SAStrutsでJSON形式のデータを返す(検証エラー込み)

JSONサンプルアプリ

SAStrutsの足し算チュートリアルでJSONを利用するように修正したサンプルアプリを作りました。
こちらでは更にBean Validationをバリデータに利用しています。

30
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
27