1. ホーム
  2. java

[解決済み] Ajaxを使用してSpring MVCコントローラに@RequestBodyで複数の変数を渡す

2022-06-20 23:45:37

質問

バッキングオブジェクトでラップする必要があるのでしょうか?このようにしたいのですが。

@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody String str1, @RequestBody String str2) {}

そして、このようなJSONを使用します。

{
    "str1": "test one",
    "str2": "two test"
}

しかし、その代わりに

@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody Holder holder) {}

そして、このJSONを使う。

{
    "holder": {
        "str1": "test one",
        "str2": "two test"
    }
}

というのは正しいでしょうか?もう一つの選択肢は RequestMethodGET を使用し @RequestParam をクエリ文字列で使用するか @PathVariable のどちらかと RequestMethod .

どのように解決するのですか?

あなたの言うとおり、@RequestBody アノテーションされたパラメータは、リクエストのボディ全体を保持し、1 つのオブジェクトにバインドすることが期待されています。

どうしてもあなたのアプローチが欲しいのであれば、カスタム実装がありますが。

これがあなたのjsonだとします。

{
    "str1": "test one",
    "str2": "two test"
}

で、ここにある2つのパラメータにバインドしたいのです。

@RequestMapping(value = "/Test", method = RequestMethod.POST)
public boolean getTest(String str1, String str2)

まず、カスタムアノテーションを定義します。 @JsonArg のように、必要な情報へのパスのようなJSONパスを指定します。

public boolean getTest(@JsonArg("/str1") String str1, @JsonArg("/str2") String str2)

次に、カスタム ハンドラーメソッド引数リゾルバ を使う JsonPath を使用して、実際の引数を解決します。

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.jayway.jsonpath.JsonPath;

public class JsonPathArgumentResolver implements HandlerMethodArgumentResolver{

    private static final String JSONBODYATTRIBUTE = "JSON_REQUEST_BODY";
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(JsonArg.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        String body = getRequestBody(webRequest);
        String val = JsonPath.read(body, parameter.getMethodAnnotation(JsonArg.class).value());
        return val;
    }

    private String getRequestBody(NativeWebRequest webRequest){
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        String jsonBody = (String) servletRequest.getAttribute(JSONBODYATTRIBUTE);
        if (jsonBody==null){
            try {
                String body = IOUtils.toString(servletRequest.getInputStream());
                servletRequest.setAttribute(JSONBODYATTRIBUTE, body);
                return body;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return "";

    }
}

あとはこれをSpring MVCに登録するだけです。少し複雑ですが、これできれいに動作するはずです。