स्प्रिंग रेस्टफुल एप्लिकेशन के लिए ResponseEntity <T> और @RestController का उपयोग करें


163

मैं MVC और रेस्ट के साथ मिलकर स्प्रिंग फ्रेमवर्क 4.0.7 के साथ काम कर रहा हूं

मैं शांति के साथ काम कर सकता हूं:

  • @Controller
  • ResponseEntity<T>

उदाहरण के लिए:

@Controller
@RequestMapping("/person")
@Profile("responseentity")
public class PersonRestResponseEntityController {

विधि के साथ (बस बनाने के लिए)

@RequestMapping(value="/", method=RequestMethod.POST)
public ResponseEntity<Void> createPerson(@RequestBody Person person, UriComponentsBuilder ucb){
    logger.info("PersonRestResponseEntityController  - createPerson");
    if(person==null)
        logger.error("person is null!!!");
    else
        logger.info("{}", person.toString());

    personMapRepository.savePerson(person);
    HttpHeaders headers = new HttpHeaders();
    headers.add("1", "uno");
    //http://localhost:8080/spring-utility/person/1
    headers.setLocation(ucb.path("/person/{id}").buildAndExpand(person.getId()).toUri());

    return new ResponseEntity<>(headers, HttpStatus.CREATED);
}

कुछ वापस करने के लिए

@RequestMapping(value="/{id}", method=RequestMethod.GET)
public ResponseEntity<Person> getPerson(@PathVariable Integer id){
    logger.info("PersonRestResponseEntityController  - getPerson - id: {}", id);
    Person person = personMapRepository.findPerson(id);
    return new ResponseEntity<>(person, HttpStatus.FOUND);
}

ठीक काम करता है

मैं इसके साथ भी ऐसा कर सकता हूं :

  • @RestController(मुझे पता है कि यह @Controller+ से समान है @ResponseBody)
  • @ResponseStatus

उदाहरण के लिए:

@RestController
@RequestMapping("/person")
@Profile("restcontroller")
public class PersonRestController {

विधि के साथ (बस बनाने के लिए)

@RequestMapping(value="/", method=RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public void createPerson(@RequestBody Person person, HttpServletRequest request, HttpServletResponse response){
    logger.info("PersonRestController  - createPerson");
    if(person==null)
        logger.error("person is null!!!");
    else
        logger.info("{}", person.toString());

    personMapRepository.savePerson(person);
    response.setHeader("1", "uno");

    //http://localhost:8080/spring-utility/person/1
    response.setHeader("Location", request.getRequestURL().append(person.getId()).toString());
}

कुछ वापस करने के लिए

@RequestMapping(value="/{id}", method=RequestMethod.GET)
@ResponseStatus(HttpStatus.FOUND)
public Person getPerson(@PathVariable Integer id){
    logger.info("PersonRestController  - getPerson - id: {}", id);
    Person person = personMapRepository.findPerson(id);
    return person;
}

मेरे प्रश्न हैं:

  1. जब एक ठोस कारण या विशिष्ट परिदृश्य के लिए एक विकल्प को दूसरे पर अनिवार्य रूप से इस्तेमाल किया जाना चाहिए
  2. यदि (1) कोई फर्क नहीं पड़ता है, तो क्या दृष्टिकोण सुझाया गया है और क्यों।

जवाबों:


213

ResponseEntityसंपूर्ण HTTP प्रतिसाद का प्रतिनिधित्व करने के लिए है। आप इसमें जाने वाली किसी भी चीज़ को नियंत्रित कर सकते हैं: स्टेटस कोड, हेडर और बॉडी।

@ResponseBodyHTTP प्रतिक्रिया निकाय के लिए एक मार्कर है और HTTP प्रतिक्रिया @ResponseStatusकी स्थिति कोड घोषित करता है।

@ResponseStatusबहुत लचीला नहीं है। यह पूरी विधि को चिह्नित करता है इसलिए आपको यह सुनिश्चित करना होगा कि आपका हैंडलर तरीका हमेशा उसी तरह का व्यवहार करेगा। और आप अभी भी हेडर सेट नहीं कर सकते। आपको HttpServletResponseया एक HttpHeadersपैरामीटर की आवश्यकता होगी ।

असल में, ResponseEntityआप और अधिक करने की सुविधा देता है।


6
तीसरे अवलोकन के बारे में अच्छी बात। धन्यवाद ... और मैंने इसके बारे में ऐसा ही सोचा ResponseEntity, यह अधिक लचीला है। बस मैं संदेह के साथ था @RestController। धन्यवाद
मैनुअल जॉर्डन

55

Sotorios Delimanolis से जवाब पूरा करने के लिए।

यह सच है कि ResponseEntityआपको अधिक लचीलापन देता है, लेकिन ज्यादातर मामलों में आपको इसकी आवश्यकता नहीं होगी और आप ResponseEntityअपने नियंत्रक में हर जगह इन के साथ समाप्त हो जाएंगे और इस प्रकार इसे पढ़ना और समझना मुश्किल हो जाएगा।

यदि आप विशेष मामलों जैसे त्रुटियों (नहीं मिला, संघर्ष, आदि) को संभालना चाहते हैं, तो आप HandlerExceptionResolverअपने स्प्रिंग कॉन्फ़िगरेशन में जोड़ सकते हैं । इसलिए आपके कोड में, आप केवल एक विशिष्ट अपवाद ( NotFoundExceptionउदाहरण के लिए) को फेंक देते हैं और तय करते हैं कि आपके हैंडलर में क्या करना है (HTTP स्थिति 404 पर सेट करना), जिससे नियंत्रक कोड अधिक स्पष्ट हो।


5
आपका दृष्टिकोण (@) ExceptionHandler के साथ काम करने के लिए मान्य है। मुद्दा यह है: यदि आप चाहते हैं कि सभी एक विधि (ट्राइ / कैच) में संभाला जाए तो HttpEntity अच्छी तरह से फिट बैठता है, यदि आप अपवाद हैंडलिंग (@) एक्सेप्शनहैंडलर को कई (@) के लिए पुनः उपयोग करना चाहते हैं तो अच्छी तरह से फिट बैठता है। मुझे HttpEntity पसंद है क्योंकि मैं HttpHeaders के साथ भी काम करने में सक्षम हूं।
मैनुअल जॉर्डन

46

आधिकारिक दस्तावेज के अनुसार: @RestController एनोटेशन के साथ अन्य कंट्रोलर बनाना

@RestController एक स्टीरियोटाइप एनोटेशन है जो @ResponseBody और @Controller को जोड़ती है। इससे अधिक, यह आपके नियंत्रक को अधिक अर्थ देता है और फ्रेमवर्क के भविष्य के रिलीज में अतिरिक्त शब्दार्थ भी ले सकता है।

ऐसा लगता है कि यह @RestControllerस्पष्टता के लिए उपयोग करना सबसे अच्छा है , लेकिन आप इसे ज़रूरत पड़ने पर लचीलेपन के साथ भी जोड़ सकते हैं ResponseEntity( आधिकारिक ट्यूटोरियल के अनुसार और यहाँ कोड और मेरे सवाल की पुष्टि करने के लिए )।

उदाहरण के लिए:

@RestController
public class MyController {

    @GetMapping(path = "/test")
    @ResponseStatus(HttpStatus.OK)
    public User test() {
        User user = new User();
        user.setName("Name 1");

        return user;
    }

}

के समान है:

@RestController
public class MyController {

    @GetMapping(path = "/test")
    public ResponseEntity<User> test() {
        User user = new User();
        user.setName("Name 1");

        HttpHeaders responseHeaders = new HttpHeaders();
        // ...
        return new ResponseEntity<>(user, responseHeaders, HttpStatus.OK);
    }

}

इस तरह, आप ResponseEntityकेवल जरूरत पड़ने पर परिभाषित कर सकते हैं ।

अपडेट करें

आप इसका उपयोग कर सकते हैं:

    return ResponseEntity.ok().headers(responseHeaders).body(user);

यदि हमने विधि पर @ResponseStatus (HttpStatus.OK) जोड़ दिया है, लेकिन विधि नई प्रतिक्रिया देता है मैं सिर्फ यह सोच रहा हूं कि क्या @ResponseStatus आगे प्रतिक्रिया कोड को संशोधित करेगा।
प्रतापी हेमंत पटेल

4
@ हेमंत ऐसा लगता है कि @ResponseStatus(HttpStatus.OK)जब आप वापस लौटते हैं तो उसे अनदेखा कर दिया जाता है ResponseEntity<>(user, responseHeaders, HttpStatus.NOT_FOUND)। HTTP प्रतिसाद है404
Danail

ResponseStatus के JavaDocs से। स्थिति कोड HTTP प्रतिक्रिया पर लागू होता है जब हैंडलर विधि को लागू किया जाता है और {@code ResponseEntity} या {@code "पुनर्निर्देशित:"} जैसे अन्य साधनों द्वारा निर्धारित स्थिति की जानकारी को ओवरराइड करता है।
vzhemevko

14

प्रतिक्रिया में एक उचित रीस्ट एपीआई के घटक नीचे होने चाहिए

  1. स्थिति का कोड
  2. प्रतिक्रिया शरीर
  3. उस संसाधन का स्थान जो बदल दिया गया था (उदाहरण के लिए, यदि कोई संसाधन बनाया गया था, तो ग्राहक को उस स्थान के यूआरएल को जानने में रुचि होगी)

ResponseEntity का मुख्य उद्देश्य विकल्प 3 प्रदान करना था, ResponseEntity के बिना बाकी विकल्प प्राप्त किए जा सकते थे।

इसलिए यदि आप संसाधन का स्थान प्रदान करना चाहते हैं तो ResponseEntity का उपयोग करना बेहतर होगा अन्यथा इसे टाला जा सकता है।

एक उदाहरण पर विचार करें जहां उल्लिखित सभी विकल्पों को प्रदान करने के लिए एक एपीआई संशोधित किया गया है

// Step 1 - Without any options provided
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public @ResponseBody Spittle spittleById(@PathVariable long id) {
  return spittleRepository.findOne(id);
}

// Step 2- We need to handle exception scenarios, as step 1 only caters happy path.
@ExceptionHandler(SpittleNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public Error spittleNotFound(SpittleNotFoundException e) {
  long spittleId = e.getSpittleId();
  return new Error(4, "Spittle [" + spittleId + "] not found");
}

// Step 3 - Now we will alter the service method, **if you want to provide location**
@RequestMapping(
    method=RequestMethod.POST
    consumes="application/json")
public ResponseEntity<Spittle> saveSpittle(
    @RequestBody Spittle spittle,
    UriComponentsBuilder ucb) {

  Spittle spittle = spittleRepository.save(spittle);
  HttpHeaders headers = new HttpHeaders();
  URI locationUri =
  ucb.path("/spittles/")
      .path(String.valueOf(spittle.getId()))
      .build()
      .toUri();
  headers.setLocation(locationUri);
  ResponseEntity<Spittle> responseEntity =
      new ResponseEntity<Spittle>(
          spittle, headers, HttpStatus.CREATED)
  return responseEntity;
}

// Step4 - If you are not interested to provide the url location, you can omit ResponseEntity and go with
@RequestMapping(
    method=RequestMethod.POST
    consumes="application/json")
@ResponseStatus(HttpStatus.CREATED)
public Spittle saveSpittle(@RequestBody Spittle spittle) {
  return spittleRepository.save(spittle);
}

स्रोत - स्प्रिंग इन एक्शन

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.