2012-06-28 10 views
23

मेरे पास एक स्प्रिंग एमवीसी एप्लीकेशन है जो फ्रीमार्कर को व्यू टेक्नोलॉजी के रूप में उपयोग करता है (लेकिन हो सकता है कि व्यू टेक्नोलॉजी वास्तव में मेरे प्रश्न के लिए कोई फर्क नहीं पड़ता)। मुझे अनुरोध के दौरान फेंकने वाले सभी अपवादों को रोकना होगा।स्प्रिंग एमवीसी में एक दृश्य प्रस्तुत करते समय अपवादों को कैसे संभाला जाए?

मैंने HandlerExceptionResolver लागू किया है लेकिन यह रिज़ॉल्यूशन केवल तब निष्पादित किया जाता है जब अपवाद नियंत्रक के भीतर होता है। लेकिन जब एक नियंत्रक मॉडल और दृश्य देता है और दृश्य को प्रस्तुत करते समय अपवाद होता है (क्योंकि एक चर नहीं मिला था या ऐसा कुछ) तो अपवाद रिज़ॉल्वर नहीं कहा जाता है और इसके बजाय मुझे ब्राउज़र विंडो में एक स्टैक ट्रेस मिलता है।

मैंने नियंत्रक के भीतर एक अपवाद हैंडलर विधि का उपयोग करने का भी प्रयास किया जो दृश्य को वापस करता है और इसे @ExceptionHandler के साथ टिप्पणी करता है लेकिन यह भी काम नहीं करता है (अधिकतर संभावना है क्योंकि अपवाद को नियंत्रक में नहीं फेंक दिया जाता है लेकिन दृश्य में) ।

तो क्या कुछ वसंत तंत्र है जहां मैं एक अपवाद हैंडलर पंजीकृत कर सकता हूं जो दृश्य त्रुटियों को कैप्चर करता है?

+0

क्या ऐसा [कॉन्फ़िगरेशन] (http://developingdeveloper.wordpress.com/2008/03/09/handling-exceptions-in-spring-mvc-part-2/) मदद करेगा? – nobeh

+0

@ नोबेह नोप, दुर्भाग्य से नहीं। यह आलेख बस हैंडलरएक्सप्शन रीसोल्वर सामान के उपयोग को समझाता है। यही वह है जो मैं पहले से ही उपयोग करता हूं लेकिन यह केवल नियंत्रकों में फेंकने वाले अपवादों को कैप्चर करता है, न कि विचारों में। – kayahr

उत्तर

21

एक शब्द अग्रिम: अगर आप सिर्फ ज्यादा तर्क और मॉडल तैयार करने के बिना एक "स्थिर" त्रुटि पृष्ठ की जरूरत है, यह आपके web.xml में एक <error-page> -Tag डाल करने के लिए (उदाहरण के लिए नीचे देखें) पर्याप्त होना चाहिए।

अन्यथा, वहाँ यह करने के लिए बेहतर तरीके हो सकते हैं, लेकिन यह हमारे लिए काम करता है:

हम web.xml कि सभी अपवाद लग जाती है और हमारे कस्टम ErrorHandler कॉल में एक सर्वलेट <filter> उपयोग करते हैं, एक ही हम वसंत के अंदर का उपयोग HandlerExceptionResolver।

<filter> 
    <filter-name>errorHandlerFilter</filter-name> 
    <filter-class>org.example.filter.ErrorHandlerFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>errorHandlerFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

क्रियान्वयन ऐसा अनिवार्य रूप से दिखता है:

public class ErrorHandlerFilter implements Filter { 

    ErrorHandler errorHandler; 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { 
    try { 
     filterChain.doFilter(request, response); 
    } catch (Exception ex) { 
     // call ErrorHandler and dispatch to error jsp 
     String errorMessage = errorHandler.handle(request, response, ex); 
     request.setAttribute("errorMessage", errorMessage); 
     request.getRequestDispatcher("/WEB-INF/jsp/error/dispatch-error.jsp").forward(request, response); 
    } 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
    errorHandler = (ErrorHandler) WebApplicationContextUtils 
     .getRequiredWebApplicationContext(filterConfig.getServletContext()) 
     .getBean("defaultErrorHandler"); 
    } 

    // ... 
} 

मेरा मानना ​​है कि यह काफी FreeMarker टेम्पलेट्स के लिए एक ही काम करना चाहिए। बेशक अगर आपका त्रुटि दृश्य एक त्रुटि फेंकता है, तो आप विकल्पों में से कम या कम हैं।

भी 404 की तरह त्रुटियों को पकड़ने और इसके लिए मॉडल तैयार करने के लिए, हम एक फिल्टर है कि ERROR डिस्पैचर के लिए मैप किया गया है का उपयोग करें:

@Override 
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 

    final HttpServletRequest request = (HttpServletRequest) servletRequest; 

    // handle code(s) 
    final int code = (Integer) request.getAttribute("javax.servlet.error.status_code"); 
    if (code == 404) { 
    final String uri = (String) request.getAttribute("javax.servlet.error.request_uri"); 
    request.setAttribute("errorMessage", "The requested page '" + uri + "' could not be found."); 
    } 

    // notify chain 
    filterChain.doFilter(servletRequest, servletResponse); 
} 
+0

मैंने कस्टम त्रुटि हैंडलर का उपयोग नहीं किया है। मैं बस इतना करना चाहता हूं - अगर टेम्पलेट प्रोसेसिंग विफल हो जाती है, तो उपयोगकर्ता को स्थिर त्रुटि पृष्ठ पर रीडायरेक्ट करें। ब्राउज़र त्रुटि पृष्ठ सामग्री दिखाता है लेकिन यह स्टैक ट्रेस भी दिखाता है। कोई सुराग? मैं वसंत का उपयोग कर रहा हूँ। विचारों के लिए freemarker के साथ बस सादे servlets। – sbidwai

+1

हैलो, इसके लिए धन्यवाद, मुझे 'org.springframework.beans.factory मिल रहा है। NoSuchBeanDefinitionException: init पर 'defaultErrorHandler' नामक कोई बीन परिभाषित नहीं किया गया है। क्या मुझे इसे servlet.xml में परिभाषित करने की ज़रूरत है? – Ernest

+0

क्या यह आगे करने का कोई तरीका है: 'request.getRequestDispatcher ("/WEB-INF/jsp/error/dispatch-error.jsp ")। आगे (अनुरोध, प्रतिक्रिया); 'मौजूदा व्यू रीसोलवर का उपयोग करना? – FelipeKunzler

0

यह सुनिश्चित नहीं है कि मेरा समाधान आपके द्वारा की जा रही समस्या के साथ काम करता है या नहीं। बीमार अभी जिस तरह मैं अपने अपवाद को पकड़ने के बाद यह सुनिश्चित करने के लिए कोई स्टैक ट्रेस ब्राउज़र के भीतर शो है:

public class AbstractController { 

    @ResponseStatus(HttpStatus.CONFLICT) 
    @ExceptionHandler({OptimisticLockingFailureException.class}) 
    @ResponseBody 
    public void handleConflict() { 
    //Do something extra if you want 
    } 
} 

इस तरह:

मैं एक विधि है कि इस तरह एक विशिष्ट संघर्ष संभाल लेंगे साथ एक AbstractController वर्ग बनाया जब भी कोई अपवाद होता है तो उपयोगकर्ता को डिफ़ॉल्ट HTTPResponse स्थिति दिखाई देगी। (उदाहरण के लिए 404 नहीं मिला आदि ..)

मैं इस वर्ग को अपने सभी नियंत्रक वर्गों पर विस्तारित करता हूं ताकि यह सुनिश्चित किया जा सके कि त्रुटियों को सार नियंत्रक पर रीडायरेक्ट किया गया हो। इस तरह मुझे एक विशिष्ट नियंत्रक पर अपवाद हैंडलर का उपयोग करने की आवश्यकता नहीं है, लेकिन मैं अपने सभी नियंत्रकों को वैश्विक स्तर पर जोड़ सकता हूं। (सार नियंत्रक वर्ग को विस्तारित करके)।

संपादित करें: आपके प्रश्न पर जाने के बाद, मैंने देखा कि आपको अपने विचार में त्रुटियां मिल रही हैं। सुनिश्चित नहीं है कि इस तरह से उस त्रुटि को पकड़ लिया जाएगा ..

आशा है कि इससे मदद मिलती है !!

+0

पहले से ही यह कोशिश की है। मैंने सीधे इस तरह की एक विधि को नियंत्रक में जोड़ा और इसके कुछ आधार वर्ग में नहीं, लेकिन इससे कोई फर्क नहीं पड़ता। इस अपवाद हैंडलर को तब कहा जाता है जब अपवाद को नियंत्रक विधि में फेंक दिया जाता है, लेकिन जब दृश्य में अपवाद फेंक दिया जाता है। – kayahr

+0

या यदि एक सर्वलेट फ़िल्टर में त्रुटि होती है। मुझे लगता है कि स्वीकृत उत्तर केवल एक ही है जो कहीं भी किसी भी त्रुटि को संभालता है। – ticktock

+0

यह काम नहीं करेगा। टेम्पलेट प्रसंस्करण होता है नियंत्रकों और नियंत्रक सलाह के बाद कहा जाता है। तो एकमात्र तरीका मैं सोच सकता हूं कि स्वीकृत उत्तर द्वारा सुझाए गए फ़िल्टर को हैंडलाइन जोड़ना है। सुंदर नहीं है लेकिन समझ में आता है। –

6
:

<filter> 
    <filter-name>errorDispatcherFilter</filter-name> 
    <filter-class>org.example.filter.ErrorDispatcherFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>errorDispatcherFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    <dispatcher>ERROR</dispatcher> 
</filter-mapping> 

<error-page> 
    <error-code>404</error-code> 
    <location>/WEB-INF/jsp/error/dispatch-error.jsp</location> 
</error-page> 
<error-page> 
    <exception-type>java.lang.Exception</exception-type> 
    <location>/WEB-INF/jsp/error/dispatch-error.jsp</location> 
</error-page> 

doFilter-कार्यान्वयन इस तरह दिखता है

आप डिस्पैचर सर्विलेट को बढ़ा सकते हैं।

अपने वेब.एक्सएमएल में अपनी खुद की कक्षा के लिए जेनेरिक डिस्पैचर सर्वलेट को प्रतिस्थापित करें।

<servlet> 
    <servlet-name>springmvc</servlet-name> 
    <servlet-class>com.controller.generic.DispatcherServletHandler</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

बाद में अपने स्वयं के वर्ग DispatcherServletHandler बना सकते हैं और DispatcherServlet से लागू होता है:

public class DispatcherServletHandler extends DispatcherServlet { 

    private static final String ERROR = "error"; 
    private static final String VIEW_ERROR_PAGE = "/WEB-INF/views/error/view-error.jsp"; 

    @Override 
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { 
     try{ 
      super.doService(request, response); 
     } catch(Exception ex) { 
      request.setAttribute(ERROR, ex); 
      request.getRequestDispatcher(VIEW_ERROR_PAGE).forward(request, response); 
     } 
    } 
} 

और उस पेज में हम केवल उपयोगकर्ता के लिए संदेश दिखाने के लिए।

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