আজাক্স ব্যবহার করে একটি স্প্রিং এমভিসি নিয়ামককে @RequestBody এ একাধিক ভেরিয়েবল পাস করা


112

ব্যাকিং অবজেক্টে মোড়ানো কি দরকার? আমি এটা করতে চাই:

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

এবং এর মতো একটি জেএসএন ব্যবহার করুন:

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

উত্তর:


92

আপনি সঠিক, @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)

এখন একটি কাস্টম হ্যান্ডলারমিথডআর্গমেন্ট রিসোলভার লিখুন যা আসল যুক্তি সমাধানের জন্য উপরে সংজ্ঞায়িত জসনপথ ব্যবহার করে :

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

    }
}

এখন এটি স্প্রিং এমভিসির সাথে নিবন্ধন করুন। কিছুটা জড়িত, তবে এটি পরিষ্কারভাবে কাজ করা উচিত।


2
আমি কীভাবে কাস্টম টীকা তৈরি করব, দয়া করে @ জসনআরগ বলুন?
সুরেন্দ্র জানওয়ালি

কেন? এখন আমাকে ব্যাকএন্ডে অনেকগুলি বিভিন্ন র‍্যাপার ক্লাস তৈরি করতে হবে। আমি একটি স্ট্রুটস 2 অ্যাপ্লিকেশনটি স্প্রিংবুটে স্থানান্তরিত করছি এবং এর অনেকগুলি ক্ষেত্রেই দেখা গেছে যে জেএসএন অজ্যাক্স ব্যবহার করে পাঠানো বস্তুগুলি আসলে মডেলের দুটি বা ততোধিক বস্তু: যেমন একটি ব্যবহারকারী এবং একটি ক্রিয়াকলাপ
জোস ওসপিনা

এই লিঙ্কে আপনি "কিভাবে এই স্প্রিং MVC সাথে নিবন্ধন করতে" দেন geekabyte.blogspot.sg/2014/08/...
Bodil

3
এখনও এই বিকল্পটি বসন্তে যুক্ত করা হচ্ছে না কেন তা আন্তরিকভাবে আলোচনা করে। এটি আপনার একটি লজিকাল বিকল্পের মতো বলে মনে হয় যখন আপনি 2 টি দীর্ঘায়ু পছন্দ করেন এবং এটির জন্য একটি মোড়কের জিনিস তৈরি করতে চান না
tibi

@ সুরেন্দ্রজনাওয়ালি আপনি এটি এর মতো করতে পারেন@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface JsonArg { String value() default ""; }
এপোনো

87

যদিও এটি সত্য যে @RequestBodyকোনও একক অবজেক্টে ম্যাপ করতে হবে, সেই বস্তুটি একটি হতে পারে Map, সুতরাং আপনি যা অর্জন করার চেষ্টা করছেন তার এটি একটি ভাল উপায় পায় (কোনও ব্যাকিং অবজেক্ট লিখতে হবে না):

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

আপনি যদি জেএসনের একটি সম্পূর্ণ জাসন গাছ চান তবে আপনি জ্যাকসনের অবজেক্টনোডকেও আবদ্ধ করতে পারেন:

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

@ জোসঅস্পিনা কেন এটি করতে পারে না। অনুরোধের সাথে মানচিত্র <স্ট্রিং, অবজেক্ট> এর সাথে সম্পর্কিত কোনও ঝুঁকি
বেন চেং

@ এর অর্থ আমার অর্থ আপনি এর মধ্যে যে Mapকোনও সংখ্যক বস্তু সংরক্ষণের জন্য একটি একক অবজেক্ট ব্যবহার করতে পারেন , তবে শীর্ষ স্তরের অবজেক্টটি এখনও কেবল একটি হতে পারে, সেখানে দুটি শীর্ষ স্তরের বস্তু থাকতে পারে।
জোসে অস্পিনা

1
আমি মনে করি ডায়নামিক পদ্ধতির ডাউনসাইড Map<String, String>যেমন: এপিআই ডকুমেন্টেশন লাইব্রেরি (সোয়াগার / স্প্রিংফক্স ইত্যাদি) সম্ভবত আপনার উত্স কোড থেকে আপনার অনুরোধ / প্রতিক্রিয়া স্কিমাকে পার্স করতে সক্ষম হবে না।
স্ট্রোটোরিয়াস

10

আপনি সহজ ডেটা ধরণের জন্য বডি এবং পাথ ভেরিয়েবল ব্যবহার করে পোস্ট যুক্তিটি মিশ্রণ করতে পারেন:

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

10

একাধিক অবজেক্ট, প্যারাম, ভেরিয়েবল এবং এই জাতীয় পাস করার জন্য। আপনি জ্যাকসন লাইব্রেরি থেকে আপনার পরম হিসাবে অবজেক্টনোডটি গতিশীলভাবে এটি করতে পারেন। আপনি এটি এইভাবে করতে পারেন:

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

আমি এই সাহায্য আশা করি।


2

@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/firm যেখানে ফার্ম এবং ব্যবহারকারী হিসাবে ব্যবহৃত হয় Pathvariable


এটি প্রশ্নের উত্তর দেয় না এবং ভুল, আপনি পোষ্ট অনুরোধগুলির সাথে কোয়েরি স্ট্রিং ব্যবহার করবেন না
নিমচিম্পস্কি

1
@ নিমচিম্পস্কি: নিশ্চয়ই আপনি পারবেন। একটি পোস্ট অনুরোধ এখনও ইউআরএল মধ্যে পরামিতি অন্তর্ভুক্ত করতে পারে।
মার্টিজন পিটারস

2

সহজ সমাধানটি হ'ল একটি পেডলোড শ্রেণি তৈরি করা যা এতে 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"
}

1
এই টীকাগুলির প্যাকেজটি কী? অটোপোর্ট কেবলমাত্র আমদানির প্রস্তাব দেয় jdk.nashorn.intern.objects.annotations.Setter; সম্পাদনা করুন। আমি ধরে নিলাম এটি লম্বোক প্রজেক্টলম্বোক.অর্গ / ফিচারস / গেটারসেটর । আমি ভুল হলে দয়া করে আমাকে সংশোধন করুন
গ্লাইচমুট

@ গ্লাইচমুট আপনি আপনার ভেরিয়েবলগুলির জন্য সহজ গেটার এবং সেটার ব্যবহার করতে পারেন। এটি আপনার প্রত্যাশা মতো কাজ করবে।
গিমনাথ

1

জসন ব্যবহারের পরিবর্তে, আপনি সাধারণ জিনিস করতে পারেন।

$.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.>
                });

এখন নিয়ামকটিতে আপনাকে নীচে অজেক্স অনুরোধটি ম্যাপ করতে হবে:

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

আশা করি এটি আপনাকে সহায়তা করবে।


1
এটি জসন, এবং এটি কাজ করে না। আপনি পদ্ধতিতে রিকোয়েটারপ্যাম নির্দিষ্ট করে দিচ্ছেন, তবে এজ্যাক্স পোস্টের অনুরোধে জেসন সহ অশ্বস্তরকে সংজ্ঞায়িত করছেন।
নিমচিম্পস্কি

দেখুন আমি আজাদ কলটিতে JSON ফর্ম্যাটটি ব্যবহার করি নি। আমি কেবলমাত্র দুটি অনুরোধের প্যারাম ব্যবহার করেছি এবং নিয়ামকটিতে আমরা টীকা @RequestParam সহ সেইগুলি প্যারামগুলি পেতে পারি। এটা কাজ করছে। আমি এটি ব্যবহার করি শুধু এটা ব্যবহার করে দেখুন।
জাপান ত্রিবেদী

আমি এটি চেষ্টা করেছি, এটি কোয়েস্টটনের মূল বিষয়। এটি এর মতো কাজ করে না।
নিমচিম্পস্কি

আপনি ঠিক কী চেষ্টা করেছেন তা উল্লেখ করুন। আপনার প্রশ্নে এটি দেখান। আমি যেটা বুঝেছি তার চেয়ে আপনার আলাদা প্রয়োজন আছে বলে আমি মনে করি
জাপান ত্রিবেদী

1
প্রথম চেষ্টা করে আমার জন্য কাজ করেছেন। ধন্যবাদ!
হাম্পাকারিজিট

1

আমি বিজুর সমাধানটি মানিয়ে নিয়েছি:

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;

    }

}

ভিন্ন কি:

  • আমি জ্যাকসনকে জসন রূপান্তর করতে ব্যবহার করছি
  • টীকাতে আমার কোনও মান দরকার নেই, আপনি মেথডপ্যারামিটারের বাইরে প্যারামিটারের নামটি পড়তে পারেন
  • আমি মেথডাপারমিটার =>> এর বাইরে প্যারামিটারের ধরণটিও পড়েছি তাই সমাধানটি জেনেরিক হওয়া উচিত (আমি এটি স্ট্রিং এবং ডিটিও দিয়ে পরীক্ষা করেছি)

বিআর


0

জিইটি এবং পোষ্ট উভয়ের জন্যই অনুরোধ প্যারামিটার বিদ্যমান, এটি পেতে URL এর ক্যোয়ারী স্ট্রিং হিসাবে সংযুক্ত হবে তবে পোস্টের জন্য এটি অনুরোধ সংস্থার মধ্যে রয়েছে


0

আপনি কোথায় জসন যুক্ত করবেন তা নিশ্চিত নই তবে আমি যদি এটি কৌনিক দিয়ে এটি করি তবে এটি অনুরোধ ছাড়াই কাজ করে ody

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

0

ভাল. আমি একটি মান অবজেক্ট (Vo) তৈরি করার পরামর্শ দিচ্ছি যাতে আপনার প্রয়োজনীয় ক্ষেত্রগুলি রয়েছে। কোডটি সহজ, আমরা জ্যাকসনের কার্যকারিতা পরিবর্তন করি না এবং এটি বুঝতে আরও সহজ। শুভেচ্ছা সহ!


0

আপনি যা ব্যবহার করতে চান তা অর্জন করতে পারেন @RequestParam। এর জন্য আপনার নিম্নলিখিতগুলি করা উচিত:

  1. অনুরোধপ্যারামগুলি প্যারামিটারগুলি ঘোষণা করুন যা আপনার অবজেক্টগুলিকে প্রতিনিধিত্ব করে এবং requiredযদি আপনি নাল মান প্রেরণ করতে সক্ষম হতে চান তবে বিকল্পটিকে মিথ্যাতে সেট করে ।
  2. অগ্রভাগে, আপনি যে জিনিসগুলি প্রেরণ করতে চান সেগুলি স্ট্রাইফাই করুন এবং তাদের অনুরোধের পরামিতি হিসাবে অন্তর্ভুক্ত করুন।
  3. ব্যাকএন্ডে জ্যাকসন অবজেক্টম্যাপার বা এমন কিছু ব্যবহার করে এবং ভয়েলা ব্যবহার করে তারা প্রতিনিধিত্ব করে এমন জেএসএন স্ট্রিংগুলিকে ফেরত দিন!

আমি জানি, এটি একটি হ্যাক কিছুটা কিন্তু এটি কাজ করে! ;)


0

আপনি ব্যবহারকারী করতে পারেন @RequestBody Map<String, String> params, তার পরে params.get("key")পরামিতিটির মান পেতে ব্যবহার করুন


0

আপনি অনুরোধবডিটি ধারণ করতে একটি মাল্টিভ্যালু মানচিত্রও ব্যবহার করতে পারেন here এর উদাহরণ এখানে।

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

অনুরোধের অংশটি ধরে রাখার জন্য মানচিত্র ব্যবহার করার সময় @RequestBody টীকাটির বিপরীতে আমাদের @RequestParam এর সাথে মন্তব্য করতে হবে

এবং ব্যবহারকারীকে জসন রিকোস্টবডিতে প্রেরণ করুন

  @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");
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.