java شرح - تمرير متغيرات متعددة فيRequestBody إلى وحدة تحكم Spring MVC باستخدام Ajax




5 Answers

أنت على صواب ، من المتوقع أن تحمل المعلمة المشروحةRequestBody كامل الجسم للطلب وترتبط بواحد ، لذلك عليك أن تذهب بالخيارات المتاحة لك.

إذا كنت ترغب تمامًا في اتباع أسلوبك ، فهناك تطبيق مخصص يمكنك تنفيذه على الرغم من ذلك:

قل هذا هو json الخاص بك:

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

وتريد ربطه بالمطربين هنا:

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

حدد أولاً @JsonArg توضيحيًا مخصصًا ، قل @JsonArg ، مع مسار JSON مثل المسار إلى المعلومات التي تريدها:

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

اكتب الآن JsonPath مخصص يستخدم 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. تشارك قليلا ، ولكن هذا يجب أن يعمل بشكل نظيف.

موقع معنى

هل من الضروري الالتفاف في كائن دعم؟ اريد فعل هذا:

@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"
    }
}

هل هذا صحيح؟ سيكون الخيار الخاص بي الأخرى في تغيير RequestMethod إلى GET واستخدام @RequestParam في سلسلة الاستعلام أو استخدام @PathVariable مع RequestMethod .




يمكنك مزج وسيطة النشر باستخدام متغير المسار والجسم لأنواع البيانات البسيطة:

@RequestMapping(value = "new-trade/portfolio/{portfolioId}", method = RequestMethod.POST)
    public ResponseEntity<List<String>> newTrade(@RequestBody Trade trade, @PathVariable long portfolioId) {
...
}



بدلا من استخدام json ، يمكنك القيام بشيء بسيط.

$.post("${pageContext.servletContext.contextPath}/Test",
                {
                "str1": "test one",
                "str2": "two test",

                        <other form data>
                },
                function(j)
                {
                        <j is the string you will return from the controller function.>
                });

الآن في وحدة التحكم تحتاج إلى تعيين طلب ajax على النحو التالي:

 @RequestMapping(value="/Test", method=RequestMethod.POST)
    @ResponseBody
    public String calculateTestData(@RequestParam("str1") String str1, @RequestParam("str2") String str2, HttpServletRequest request, HttpServletResponse response){
            <perform the task here and return the String result.>

            return "xyz";
}

آمل أن يساعدك هذا.




لقد تكييفت حل بيجو:

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.springframework.core.MethodParameter;
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.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;


public class JsonPathArgumentResolver implements HandlerMethodArgumentResolver{

    private static final String JSONBODYATTRIBUTE = "JSON_REQUEST_BODY";

    private ObjectMapper om = new ObjectMapper();

    @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 jsonBody = getRequestBody(webRequest);

        JsonNode rootNode = om.readTree(jsonBody);
        JsonNode node = rootNode.path(parameter.getParameterName());    

        return om.readValue(node.toString(), parameter.getParameterType());
    }


    private String getRequestBody(NativeWebRequest webRequest){
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);

        String jsonBody = (String) webRequest.getAttribute(JSONBODYATTRIBUTE, NativeWebRequest.SCOPE_REQUEST);
        if (jsonBody==null){
            try {
                jsonBody = IOUtils.toString(servletRequest.getInputStream());
                webRequest.setAttribute(JSONBODYATTRIBUTE, jsonBody, NativeWebRequest.SCOPE_REQUEST);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return jsonBody;

    }

}

ما هو مختلف:

  • أنا أستخدم جاكسون لتحويل json
  • لا أحتاج إلى قيمة في التعليق التوضيحي ، يمكنك قراءة اسم المعلمة خارج MethodParameter
  • قرأت أيضًا نوع المعلمة خارج Methodparameter => لذا يجب أن يكون الحل عامًا (لقد اختبرت مع السلسلة و DTOs)

BR




جيد. أقترح إنشاء كائن قيمة (فو) يحتوي على الحقول التي تحتاجها. الرمز أبسط ، نحن لا نغير عمل جاكسون ، بل هو أسهل في الفهم. مع تحياتي!




Related

java spring http spring-mvc