2013-02-05 11 views
12

(जैसे HTTP 404 के रूप में) संभाल त्रुटियों विश्व स्तर पर, मैं अपने web.xml में निम्न के समान प्रविष्टियाँ जो एक नियंत्रक के बाहर हो सकता है:वसंत एमवीसी 3.2 - त्रुटि पृष्ठों के लिए सामग्री बातचीत?

<error-page> 
    <error-code>404</error-code> 
    <location>/errors/404</location> 
</error-page> 

मेरी ErrorController में मैं के लिए इसी तरह इसी तरीकों निम्नलिखित:

@Controller 
@RequestMapping("/errors") 
public class ErrorController { 

    @RequestMapping(value = "/404", method = RequestMethod.GET) 
    @ResponseBody 
    public ResponseEntity<ErrorResponse> error404() { 

     ErrorResponse errorBody = new ErrorResponse(404, "Resource Not Found!"); 

     return new ResponseEntity<ErrorResponse>(errorBody, HttpStatus.NOT_FOUND); 
    } 
} 

मुद्दा मैं का सामना करना पड़ रहा है कि ContentNegotiationManager और संदेश कन्वर्टर्स मैं कॉन्फ़िगर किया है इस मामले में इस्तेमाल नहीं किया जा रहा है। मुझे संदेह है कि चूंकि अनुरोध को त्रुटि पृष्ठ पर रीडायरेक्ट किया जा रहा है, इसलिए सामग्री वार्ता में उपयोग किए गए मूल अनुरोध के गुण खो गए हैं और इसे पूरी तरह से अलग अनुरोध के रूप में माना जाता है। (यानी /mycontroller/badresource.json ->/त्रुटियों/404 (डब्ल्यू/नहीं फ़ाइल एक्सटेंशन) के लिए मूल अनुरोध)

क्या कोई त्रुटि हैडलर में कोई तरीका है जैसे उचित सामग्री प्रकार के निर्धारण और/या प्रतिक्रिया जैसा कि मूल अनुरोध में अनुरोध किया गया है?

उत्तर

3

मैं इसके लिए एक हैक के साथ आया लेकिन ऐसा लगता है कि यह काम करता है। मूल रूप से मूल अनुरोध के फ़ाइल एक्सटेंशन को निर्धारित करने के लिए यह मूल रूप से त्रुटि प्रबंधन में एक अतिरिक्त आगे शामिल है।

मेरे web.xml में मैं एक मध्यवर्ती कार्रवाई के लिए अग्रेषित त्रुटि है:

<error-page> 
    <error-code>404</error-code> 
    <location>/errors/redirect</location> 
</error-page> 

फिर, कार्रवाई है कि त्रुटि प्रतिसाद उत्पन्न होगा करने के लिए अग्रेषित करने से पहले, एक चेक अगर वहाँ था देखने के लिए किया जाता है एक मूल अनुरोध पर फ़ाइल एक्सटेंशन। यदि वहां था, तो यह सुनिश्चित करता है कि यह आगे यूआरआई में संलग्न है। HTTP शीर्षलेख स्वचालित रूप से अग्रेषित किए जाते हैं, इसलिए यदि आपके द्वारा सेटअप की गई सामग्री वार्ता में केवल फ़ाइल एक्सटेंशन या HTTP शीर्षलेख शामिल है, तो यह उचित रूप से "त्रुटि पृष्ठ" को उपयुक्त सामग्री प्रकार में त्रुटि वापस करने की अनुमति देगा।

@Controller 
@RequestMapping("/errors") 
public class ErrorController { 

    @RequestMapping(value = "/redirect", method = RequestMethod.GET) 
    public void errorRedirect(HttpServletRequest request, HttpServletResponse response) { 

     // Get original request URI 
     String uri = (String)request.getAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE); 

     // Try to determine file extension 
     String filename = WebUtils.extractFullFilenameFromUrlPath(uri); 
     String extension = StringUtils.getFilenameExtension(filename); 
     extension = StringUtils.hasText(extension) ? "." + extension : ""; 

     // Forward request to appropriate handler with original request's file extension (i.e. /errors/404.json) 
     String forwardUri = "/errors/404" + extension); 
     request.getRequestDispatcher(forwardUri).forward(request, response); 
    } 

    @RequestMapping(value = "/404", method = RequestMethod.GET) 
    @ResponseBody 
    public ResponseEntity<ErrorResponse> error404() { 

     ErrorResponse errorBody = new ErrorResponse(404, "Resource Not Found!"); 

     return new ResponseEntity<ErrorResponse>(errorBody, HttpStatus.NOT_FOUND); 
    } 
} 
2

हां वास्तव में, एप्लिकेशन अपवाद और HTTP प्रतिक्रिया त्रुटि कोड दो अलग-अलग चीजें हैं।

आप नीचे दिए गए कोड को अनुकूलित कर सकते हैं, ताकि आपके पास requestUri तक पहुंच हो। मुझे लगता है कि आप इसके आधार पर सामग्री प्रकार पा सकते हैं। मैं अपने कच्चे जानते हैं, लेकिन मुझे नहीं लगता कि हम वैकल्पिक समाधान है:

@RequestMapping(value = "/404", method = RequestMethod.GET) 
@ResponseBody 
public ResponseEntity<ErrorResponse> error404(HttpServletRequest request) { 

    ErrorResponse errorBody = new ErrorResponse(404, "Resource Not Found!"); 

    String requestUri = request.getRequestURI(); 

    return new ResponseEntity<ErrorResponse>(errorBody, HttpStatus.NOT_FOUND); 
} 

उदाहरण से मुझे लगता है आपके आवेदन बाकी सेवा है, तो शायद आप एक बाकी पूर्ण सेवा में this link on how 404 is handled की जानकारी दे सकती है।

+0

इनपुट के लिए धन्यवाद -

यहाँ कैसे मैं इसे सेट होता है। मैंने उस आलेख को देखा है, लेकिन जब तक कि मुझे कुछ याद नहीं आ रहा है, यह केवल नियंत्रकों से अपवादों को संभालता है, न कि सामान्य सर्वलेट त्रुटियों। साथ ही, इस संदर्भ में 'request.getRequestURI() 'आपको त्रुटि पृष्ठ का यूआरआई देता है। ऐसा लगता है कि आपको मूल अनुरोध के यूआरआई प्राप्त करने के लिए 'req.getAttribute (" javax.servlet.error.request_uri ") का उपयोग करना होगा।मैं सोच रहा हूं कि क्या ContentNegotiationManager उस जानकारी को ओवरराइड करने का कोई तरीका है जो त्रुटि पृष्ठ के बजाय मूल अनुरोध से जानकारी पर सेट करता है? – WayneC

2

वसंत MVC 3.2 अब @ControllerAdvice नामक एक उपयोगी एनोटेशन भी शामिल है। आप ExceptionHandler विधि जोड़ सकते हैं जो आपके द्वारा परिभाषित अपवाद को वैश्विक रूप से संभालेगा।

मेरे लिए, मुझे क्लाइंट में लौटने के लिए केवल दो संभावित सामग्री-प्रकारों की देखभाल है - application/json या text/html

@ControllerAdvice 
public class ExceptionControllerAdvice { 

    private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 
    private static final MediaType JSON_MEDIA_TYPE = new MediaType("application", "json", DEFAULT_CHARSET); 

    //I decided to handle all exceptions in this one method 
    @ExceptionHandler(Throwable.class) 
    public @ResponseBody String handleThrowable(HttpServletRequest request, HttpServletResponse response, Throwable ex) throws IOException { 

     ... 

     if(supportsJsonResponse(request.getHeader("Accept"))) { 

      //return response as JSON 
      response.setStatus(statusCode); 
      response.setContentType(JSON_MEDIA_TYPE.toString()); 

        //TODO serialize your error in a JSON format 
        //return ... 

     } else { 

      //return as HTML 
      response.setContentType("text/html"); 
      response.sendError(statusCode, exceptionMessage); 
      return null; 
     } 
    } 

    private boolean supportsJsonResponse(String acceptHeader) { 

     List<MediaType> mediaTypes = MediaType.parseMediaTypes(acceptHeader); 

     for(MediaType mediaType : mediaTypes) { 
      if(JSON_MEDIA_TYPE.includes(mediaType)) { 
       return true; 
      } 
     } 

     return false; 
    } 

} 
+0

स्ट्रिंग के बजाय ResponseEntity वापस करना बेहतर है। और क्या मेरे पास इस दृष्टिकोण के साथ web.xml में 404 त्रुटि-पृष्ठ होना चाहिए? कृपया मेरा प्रश्न जांचें: http://stackoverflow.com/questions/17322855/how-to-handle-404-exception-invoked-by-ajax-spring-mvc-3-2-controlleradvice – Alex

संबंधित मुद्दे