जवाबों:
स्प्रिंग 3.0 के बाद से आप @ResponseStatus
एनोटेशन के साथ घोषित अपवाद भी फेंक सकते हैं :
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
...
}
@Controller
public class SomeController {
@RequestMapping.....
public void handleCall() {
if (isFound()) {
// whatever
}
else {
throw new ResourceNotFoundException();
}
}
}
@ResponseStatus
है कि आप सभी के साथ दृढ़ता से टाइप, अच्छी तरह से नामित अपवाद वर्गों के एक पूरे समूह को परिभाषित करते हैं @ResponseStatus
। इस तरह, आप अपने कंट्रोलर कोड को HTTP स्टेटस कोड के विस्तार से अलग कर लेते हैं।
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason="Your reason")
ResourceNotFound.fillInStackTrace()
खाली क्रियान्वयन के साथ ओवरराइड करना एक अच्छा विचार है ।
स्प्रिंग 5.0 से शुरू, आपको अतिरिक्त अपवाद बनाने की आवश्यकता नहीं है:
throw new ResponseStatusException(NOT_FOUND, "Unable to find resource");
इसके अलावा, आप एक, बिल्ट-इन अपवाद के साथ कई परिदृश्यों को कवर कर सकते हैं और आपके पास अधिक नियंत्रण है।
और देखें:
अपने विधि हस्ताक्षर को फिर से लिखें ताकि यह HttpServletResponse
एक पैरामीटर के रूप में स्वीकार हो , ताकि आप इस setStatus(int)
पर कॉल कर सकें।
setStatus(int)
javadoc में निम्नानुसार है: यदि इस पद्धति का उपयोग त्रुटि कोड सेट करने के लिए किया जाता है, तो कंटेनर का त्रुटि पृष्ठ तंत्र ट्रिगर नहीं होगा। यदि कोई त्रुटि है और फोन करने वाले को वेब एप्लिकेशन में परिभाषित त्रुटि पृष्ठ को आमंत्रित sendError
करना है , तो इसके बजाय इसका उपयोग किया जाना चाहिए।
मैं उल्लेख करना चाहूंगा कि स्प्रिंग द्वारा प्रदान की गई डिफ़ॉल्ट रूप से 404 के लिए अपवाद (न केवल) है। देखें स्प्रिंग प्रलेखन जानकारी के लिए। तो अगर आपको अपने स्वयं के अपवाद की आवश्यकता नहीं है, तो आप बस ऐसा कर सकते हैं:
@RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView show() throws NoSuchRequestHandlingMethodException {
if(something == null)
throw new NoSuchRequestHandlingMethodException("show", YourClass.class);
...
}
@PathVariable
, तो मेरे दृष्टिकोण से निपटने का कोई अनुरोध नहीं है। क्या आपको लगता है कि अपने स्वयं के अपवाद के साथ एनोटेट का उपयोग करना बेहतर / क्लीनर है @ResponseStatus(value = HttpStatus.NOT_FOUND)
?
स्प्रिंग 3.0.2 के बाद से आप रेस्पोंसेंटिटी <T> को नियंत्रक की विधि के परिणामस्वरूप वापस कर सकते हैं :
@RequestMapping.....
public ResponseEntity<Object> handleCall() {
if (isFound()) {
// do what you want
return new ResponseEntity<>(HttpStatus.OK);
}
else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
(ResponseEntity <T> @ResponseBody एनोटेशन की तुलना में अधिक लचीला है - एक और प्रश्न देखें )
आप @ControllerAdvice का उपयोग कर सकते हैं अपने अपवादों को संभालने के का , डिफ़ॉल्ट व्यवहार @ControllerAdvice एनोटेट वर्ग सभी ज्ञात नियंत्रकों की सहायता करेगा।
इसलिए यह तब कहा जाएगा जब आपके पास कोई नियंत्रक 404 त्रुटि है।
निम्नलिखित की तरह:
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.NOT_FOUND) // 404
@ExceptionHandler(Exception.class)
public void handleNoTFound() {
// Nothing to do
}
}
और अपने web.xml में इस 404 रिस्पॉन्स एरर को निम्न की तरह मैप करें:
<error-page>
<error-code>404</error-code>
<location>/Error404.html</location>
</error-page>
उम्मीद है की वो मदद करदे ।
यदि आपका नियंत्रक तरीका फ़ाइल संभालने जैसी किसी चीज़ के लिए है तो ResponseEntity
बहुत आसान है:
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity handleCall() {
if (isFound()) {
return new ResponseEntity(...);
}
else {
return new ResponseEntity(404);
}
}
}
जबकि चिह्नित उत्तर सही है, बिना अपवाद के इसे प्राप्त करने का एक तरीका है। सेवा Optional<T>
खोजी गई वस्तु पर वापस लौट रही है और HttpStatus.OK
यदि खाली है तो उसे 404 और यदि मिला तो मैप किया गया है।
@Controller
public class SomeController {
@RequestMapping.....
public ResponseEntity<Object> handleCall() {
return service.find(param).map(result -> new ResponseEntity<>(result, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
}
@Service
public class Service{
public Optional<Object> find(String param){
if(!found()){
return Optional.empty();
}
...
return Optional.of(data);
}
}
मैं इस तरह HttpClientErrorException को फेंकने की सलाह दूंगा
@RequestMapping(value = "/sample/")
public void sample() {
if (somethingIsWrong()) {
throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
}
}
आपको याद रखना चाहिए कि सर्वलेट आउटपुट स्ट्रीम में कुछ भी लिखे जाने से पहले ही ऐसा किया जा सकता है।
Whitelabel Error Page \n .... \n There was an unexpected error (type=Internal Server Error, status=500). \n 404 This is your not found error
यह थोड़ा लेट है, लेकिन यदि आप स्प्रिंग डेटा रीस्ट का उपयोग कर रहे हैं तो पहले से ही है। org.springframework.data.rest.webmvc.ResourceNotFoundException
यह @ResponseStatus
एनोटेशन का भी उपयोग करता है । अब कस्टम रनटाइम अपवाद बनाने की कोई आवश्यकता नहीं है।
इसके अलावा अगर आप अपने कंट्रोलर से 404 स्टेटस वापस करना चाहते हैं तो आपको बस यही करना है
@RequestMapping(value = "/somthing", method = RequestMethod.POST)
@ResponseBody
public HttpStatus doSomthing(@RequestBody String employeeId) {
try{
return HttpStatus.OK;
}
catch(Exception ex){
return HttpStatus.NOT_FOUND;
}
}
ऐसा करने पर आपको उस स्थिति में 404 त्रुटि मिलेगी जब आप अपने नियंत्रक से 404 वापस करना चाहते हैं।
बस आप त्रुटि कोड और 404 त्रुटि पेज जोड़ने के लिए web.xml का उपयोग कर सकते हैं। लेकिन सुनिश्चित करें कि 404 त्रुटि पेज को WEB-INF के तहत पता नहीं लगाना चाहिए।
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
यह इसे करने का सबसे सरल तरीका है लेकिन इसकी कुछ सीमा है। मान लीजिए अगर आप इस पेज के लिए वही स्टाइल जोड़ना चाहते हैं जो आपने अन्य पेज जोड़े हैं। इस तरह से आप ऐसा नहीं कर सकते। आपको उपयोग करना होगा@ResponseStatus(value = HttpStatus.NOT_FOUND)
HttpServletResponse#sendError(HttpServletResponse.SC_NOT_FOUND); return null;
नियंत्रक कोड से इसके साथ विचार करें । अब बाहर से प्रतिक्रिया सामान्य 404 से अलग नहीं दिखती है जो किसी भी नियंत्रक से नहीं टकराती है।
सेटिंग के साथ web.xml कॉन्फ़िगर करें
<error-page>
<error-code>500</error-code>
<location>/error/500</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404</location>
</error-page>
नया कंट्रोलर बनाएं
/**
* Error Controller. handles the calls for 404, 500 and 401 HTTP Status codes.
*/
@Controller
@RequestMapping(value = ErrorController.ERROR_URL, produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public class ErrorController {
/**
* The constant ERROR_URL.
*/
public static final String ERROR_URL = "/error";
/**
* The constant TILE_ERROR.
*/
public static final String TILE_ERROR = "error.page";
/**
* Page Not Found.
*
* @return Home Page
*/
@RequestMapping(value = "/404", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public ModelAndView notFound() {
ModelAndView model = new ModelAndView(TILE_ERROR);
model.addObject("message", "The page you requested could not be found. This location may not be current.");
return model;
}
/**
* Error page.
*
* @return the model and view
*/
@RequestMapping(value = "/500", produces = MediaType.APPLICATION_XHTML_XML_VALUE)
public ModelAndView errorPage() {
ModelAndView model = new ModelAndView(TILE_ERROR);
model.addObject("message", "The page you requested could not be found. This location may not be current, due to the recent site redesign.");
return model;
}
}
क्योंकि एक ही काम करने के कम से कम दस तरीके होना हमेशा अच्छा होता है:
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class Something {
@RequestMapping("/path")
public ModelAndView somethingPath() {
return new ModelAndView("/", HttpStatus.NOT_FOUND);
}
}