programing

Ajax를 사용하여 @RequestBody의 여러 변수를 Spring MVC 컨트롤러로 전달

shortcode 2022. 12. 24. 21:59
반응형

Ajax를 사용하여 @RequestBody의 여러 변수를 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

while while while while while while while while while@RequestBody객체에 . 이는 "이러한 객체"일 수 있습니다.이 객체는Map이를 통해 달성하려는 목표를 달성할 수 있습니다(원오프백오브젝트를 쓸 필요가 없습니다).

@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody Map<String, String> json) {
   //json.get("str1") == "test one"
}

완전한 JSON 트리를 원하는 경우 Jackson의 ObjectNode에 바인드할 수도 있습니다.

public boolean getTest(@RequestBody ObjectNode json) {
   //json.get("str1").asText() == "test one"

맞습니다. @RequestBody 주석이 달린 파라미터는 요청 본문 전체를 유지하고 하나의 오브젝트에 바인드하기 때문에 기본적으로 옵션을 사용해야 합니다.

꼭 필요한 경우 커스텀 구현이 가능합니다.

이게 네 아들이라고 해:

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

이 두 개의 파라미터에 바인드합니다.

@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를 사용하여 실제 인수를 해결하는 커스텀 핸들러 MethodArgumentResolver를 작성합니다.

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 "";

    }
}

이제 이걸 봄 MVC에 등록해 주세요. 조금 관련이 있지만, 이 작업은 깔끔하게 작동할 것입니다.

다중 객체, 매개 변수 등을 전달하기 위한 것입니다.Jackson 라이브러리의 ObjectNode를 파라미터로 사용하여 동적으로 수행할 수 있습니다.다음과 같이 할 수 있습니다.

@RequestMapping(value = "/Test", method = RequestMethod.POST)
@ResponseBody
public boolean getTest(@RequestBody ObjectNode objectNode) {
   // And then you can call parameters from objectNode
   String strOne = objectNode.get("str1").asText();
   String strTwo = objectNode.get("str2").asText();

   // When you using ObjectNode, you can pas other data such as:
   // instance object, array list, nested object, etc.
}

이게 도움이 됐으면 좋겠어요.

간단한 데이터 유형에 대해 body 변수와 path 변수를 사용하여 post 인수를 혼재시킬 수 있습니다.

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

간단한 해결책은 str1과 str2를 속성으로 하는 페이로드 클래스를 만드는 것입니다.

@Getter
@Setter
public class ObjHolder{

String str1;
String str2;

}

그리고 네가 합격하고 나면

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

요청 내용은 다음과 같습니다.

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

@RequestParam는 는 입니다.HTTP GET ★★★★★★★★★★★★★★★★★」POST클라이언트에 의해 송신된 파라미터, 요구 매핑은 가변적인 URL 세그먼트입니다.

http:/host/form_edit?param1=val1&param2=val2

var1&var2요청 매개 변수입니다.

http:/host/form/{params}

{params}하다, 이렇게 부를 수 요.http:/host/form/user ★★★★★★★★★★★★★★★★★」http:/host/form/firmfirm & 는 firm & user로 됩니다.Pathvariable.

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

도움이 되시길 바랍니다.

Biju의 솔루션을 개작했습니다.

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에서 파라미터의 이름을 읽을 수 있습니다.
  • Method parameter = >에서 파라미터의 타입도 읽어냈기 때문에 솔루션은 범용이어야 합니다(문자열과 DTO로 테스트했습니다).

BR

다중값 맵을 사용하여 requestBody를 유지할 수도 있습니다.여기에 그 예가 있다.

    foosId -> pathVariable
    user -> extracted from the Map of request Body 

맵을 사용하여 요청 본문을 유지할 때 @RequestBody 주석과는 달리 @RequestParam으로 주석을 달아야 합니다.

Json Request Body로 사용자를 전송합니다.

  @RequestMapping(value = "v1/test/foos/{foosId}", method = RequestMethod.POST, headers = "Accept=application"
            + "/json",
            consumes = MediaType.APPLICATION_JSON_UTF8_VALUE ,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public String postFoos(@PathVariable final Map<String, String> pathParam,
            @RequestParam final MultiValueMap<String, String> requestBody) {
        return "Post some Foos " + pathParam.get("foosId") + " " + requestBody.get("user");
    }

GET와 POST 모두에 대해 request 파라미터가 존재합니다.Get의 경우 URL에 쿼리 문자열로 추가되지만 POST의 경우 Request Body 내에 있습니다.

json을 어디에 추가할지는 모르겠지만, 각도로 이렇게 하면 요청 없이 작동합니다.본문: angluar:

    const params: HttpParams = new HttpParams().set('str1','val1').set('str2', ;val2;);
    return this.http.post<any>( this.urlMatch,  params , { observe: 'response' } );

자바:

@PostMapping(URL_MATCH)
public ResponseEntity<Void> match(Long str1, Long str2) {
  log.debug("found: {} and {}", str1, str2);
}

좋습니다. 필요한 필드를 포함하는 값 개체(Vo)를 만드는 것이 좋습니다.코드는 더 단순하고, 우리는 잭슨의 기능을 바꾸지 않으며, 더 쉽게 이해할 수 있습니다.안부 전해 주세요!

다음을 사용하여 원하는 것을 달성할 수 있습니다.@RequestParam이를 위해서는 다음 작업을 수행해야 합니다.

  1. 개체를 나타내는 RequestParams 파라미터를 선언하고requirednull 값을 송신할 수 있는 경우 옵션을 false로 설정합니다.
  2. 프런트 엔드에서는 송신할 오브젝트를 문자열화하여 요청 파라미터로 포함합니다.
  3. 백엔드에서 JSON 문자열은 Jackson Object Mapper 같은 것을 사용하여 나타내는 객체로 되돌리고 voila!

알아, 좀 엉터리지만 잘 돼!;)

사용자도 가능합니다.@RequestBody Map<String, String> params, 그 후 를 사용합니다.params.get("key")파라미터의 값을 취득하다

내부 클래스 사용

@RestController
public class MyController {

    @PutMapping("/do-thing")
    public void updateFindings(@RequestBody Bodies.DoThing body) {
        ...
    }


    private static class Bodies {
        public static class DoThing {
            public String name;
            public List<String> listOfThings;
        }
    }
}

Webflux 솔루션에 관심이 있는 경우 Biju의 답변을 바탕으로 한 반응형 버전을 아래에 나타냅니다.

본체가 두 번 이상 소비되지 않도록 보호하는 데 필요한 매우 작지만 동기화된 청크가 하나 있습니다.만약 당신이 완전 논블로킹 버전을 선호한다면, 나는 체크와 읽기를 순차적으로 하기 위해 같은 스케줄러에 json을 얻는 플럭스를 게시할 것을 제안한다.

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

@Slf4j
@RequiredArgsConstructor
public class JsonArgumentResolver implements HandlerMethodArgumentResolver {
    private static final String ATTRIBUTE_KEY = "BODY_TOSTRING_RESOLVER";
    private final ObjectMapper objectMapper;


    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(JsonArgument.class);
    }


    @Override
    public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext bindingContext,
                                        ServerWebExchange exchange) {
        String fieldName = parameter.getParameterName();
        Class<?> clz = parameter.getParameterType();

        return getRequestBody(exchange).map(body -> {
            try {
                JsonNode jsonNode = objectMapper.readTree(body).get(fieldName);
                String s = jsonNode.toString();
                return objectMapper.readValue(s, clz);
            } catch (JsonProcessingException e) {
                log.error(e.getMessage(), e);
                throw new RuntimeException(e);
            }
        });
    }


    private Mono<String> getRequestBody(ServerWebExchange exchange) {
        Mono<String> bodyReceiver;
        synchronized (exchange) {
            bodyReceiver = exchange.getAttribute(ATTRIBUTE_KEY);
            if (bodyReceiver == null) {
                bodyReceiver = exchange.getRequest().getBody()
                        .map(this::convertToString)
                        .single()
                        .cache();
                exchange.getAttributes().put(ATTRIBUTE_KEY, bodyReceiver);
            }
        }
        return bodyReceiver;
    }

    private String convertToString(DataBuffer dataBuffer) {
        byte[] bytes = new byte[dataBuffer.readableByteCount()];
        dataBuffer.read(bytes);
        DataBufferUtils.release(dataBuffer);
        return new String(bytes, StandardCharsets.UTF_8);
    }
}

언급URL : https://stackoverflow.com/questions/12893566/passing-multiple-variables-in-requestbody-to-a-spring-mvc-controller-using-ajax

반응형