2014-10-21 31 views
11

भीतर स्प्रिंग बूट कस्टम अपवाद मैं अपने स्प्रिंग बूट आधारित रेस्ट सेवा में एक वैश्विक अपवाद संचालन को परिभाषित किया है:एक रेस्ट सेवा

@ControllerAdvice 
public class GlobalExceptionController { 

    private final Logger LOG = LoggerFactory.getLogger(getClass()); 

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR, reason = "Internal application error") 
    @ExceptionHandler({ServiceException.class}) 
    @ResponseBody 
    public ServiceException serviceError(ServiceException e) { 
     LOG.error("{}: {}", e.getErrorCode(), e.getMessage()); 
     return e; 
    } 
} 

और एक कस्टम ServiceException:

public class ServiceException extends RuntimeException { 

    private static final long serialVersionUID = -6502596312985405760L; 

    private String errorCode; 

    public ServiceException(String message, String errorCode, Throwable cause) { 
     super(message, cause); 
     this.errorCode = errorCode; 
    } 

    // other constructors, getter and setters omitted 
} 

अब तक तो अच्छा, जब एक अपवाद निकाल दिया जाता है तो नियंत्रक काम करता है और इसके साथ प्रतिक्रिया करता है:

{ 
    "timestamp": 1413883870237, 
    "status": 500, 
    "error": "Internal Server Error", 
    "exception": "org.example.ServiceException", 
    "message": "somthing goes wrong", 
    "path": "/index" 
} 

लेकिन वें ई फ़ील्ड त्रुटि कोड JSON प्रतिक्रिया में नहीं दिखाया गया है।

तो मैं अपने आवेदन में कस्टम अपवाद प्रतिक्रिया कैसे परिभाषित कर सकता हूं।

उत्तर

20

वसंत बूट ErrorAttributes के कार्यान्वयन का उपयोग करता है ताकि Map को जेएसओएन के रूप में प्रस्तुत किया जा सके। डिफ़ॉल्ट रूप से, DefaultErrorAttributes का एक उदाहरण उपयोग किया जाता है। अपने कस्टम errorCode को शामिल करने के लिए आपको एक कस्टम ErrorAttributes कार्यान्वयन प्रदान करना होगा जो ServiceException और उसके त्रुटि कोड के बारे में जानता है। यह कस्टम कार्यान्वयन आपकी कॉन्फ़िगरेशन में @Bean होना चाहिए।

एक दृष्टिकोण उप-वर्ग DefaultErrorAttributes होगा:

@Bean 
public ErrorAttributes errorAttributes() { 
    return new DefaultErrorAttributes() { 

     @Override 
     public Map<String, Object> getErrorAttributes(
       RequestAttributes requestAttributes, 
       boolean includeStackTrace) { 
      Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace); 
      Throwable error = getError(requestAttributes); 
      if (error instanceof ServiceException) { 
       errorAttributes.put("errorCode", ((ServiceException)error).getErrorCode()); 
      } 
      return errorAttributes; 
     } 

    }; 
} 
+0

हाय एंडी, कस्टम अपवाद वर्ग अपवाद या फेंकने योग्य तो त्रुटि उदाहरण के साथ फैली यहाँ हैं UnhandledThrowException क्यों हो रहा है होगा। – KSK

+0

@KSK यह मुझे स्पष्ट नहीं है कि यह इस प्रश्न से कैसे संबंधित है। मुझे लगता है कि आप कुछ और विवरण –

+0

महान के साथ एक नया प्रश्न पूछना बेहतर होगा, धन्यवाद एंडी –

3

@Alex आप विशिष्ट RestController में विशिष्ट अपवाद को संभालने के लिए एनोटेशन @ExceptionHandler (YourExceptionClass.class) उपयोग कर सकते हैं। मुझे लगता है कि यह व्यावसायिक अनुप्रयोगों में जटिल परिदृश्यों को संभालने का एक बेहतर तरीका है। इसके अलावा मैं आपको विभिन्न प्रकार के अपवादों से निपटने के लिए कस्टम अपवाद अनुवादक का उपयोग करने का सुझाव दूंगा। आप अपवाद अनुवादक के लिए संदर्भ कोड के रूप में spring oauth2 exception translator पर विचार कर सकते हैं।

नोट: निम्नलिखित कोड केवल इस समाधान की अवधारणा को समझने के लिए है। यह उत्पादन तैयार कोड नहीं है। इसके बारे में अधिक चर्चा करने के लिए स्वतंत्र महसूस करें।

import org.springframework.http.MediaType; 
import org.springframework.web.bind.annotation.*; 

/** 
* @author Harpreet 
* @since 16-Aug-17. 
*/ 
@RestController 
public class RestTestController { 

@RequestMapping(value = "name", method = RequestMethod.GET, 
     produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) 
public ResponseObject name(@RequestParam(value="name") String value){ 
    //your custom logic 
    if (value == null || value.length() < 2) { 
     //throwing exception to invoke customExceptionHandler 
     throw new NullPointerException("value of request_param:name is invalid"); 
    } 
    ResponseObject responseObject = new ResponseObject(); 
    responseObject.setMessage(value) 
      .setErrorCode(1); 
    return responseObject; 
} 

// to handle null pointer exception 
@ExceptionHandler(NullPointerException.class) 
public ResponseObject customExceptionHandler 
     (NullPointerException e) { 
    ResponseObject responseObject = new ResponseObject(); 
    responseObject.setMessage(e.getMessage()) 
      .setErrorCode(-1); 
    return responseObject; 
} 

// response data transfer class 
static class ResponseObject{ 
    String message; 
    Integer errorCode; 

    public String getMessage() { 
     return message; 
    } 

    public ResponseObject setMessage(String message) { 
     this.message = message; 
     return this; 
    } 

    public Integer getErrorCode() { 
     return errorCode; 
    } 

    public ResponseObject setErrorCode(Integer errorCode) { 
     this.errorCode = errorCode; 
     return this; 
    } 
    } 
} 
+0

मुझे लगता है कि मुझे वैश्विक स्तर पर 'त्रुटि एट्रिब्यूट' को फिर से परिभाषित करने से बेहतर दृष्टिकोण पसंद है। हालांकि मुझे लगता है कि इसे आदर्श गुणों को प्राप्त करने के लिए आदर्श रूप से वैश्विक 'ErrorAttributes' का उपयोग करना चाहिए, और फिर अतिरिक्त मान डाल दें। –

+0

@M। प्रोकोरोव सहमत हुए, इससे इसे अधिक शक्तिशाली दृष्टिकोण मिलेगा –

+0

@ हरप्रीतंधू-द कोडर जब मैं जावा प्रोग्राम से इसे एक्सेस करने का प्रयास करता हूं, तो यह त्रुटि कोड देता है, लेकिन त्रुटि संदेश नहीं। यानी, यह त्रुटि कोड 404 के रूप में देता है, लेकिन संदेश प्रतिक्रिया ऑब्जेक्ट में कहीं भी नहीं मिला है। – KingKari

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