2014-10-21 29 views
11

tôi đã xác định một xử lý ngoại lệ toàn cầu phục vụ nghỉ ngơi mùa xuân Boot dựa của tôi:Xuân Boot tùy chỉnh ngoại lệ trong một dịch vụ nghỉ ngơi

@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; 
    } 
} 

và ServiceException tùy chỉnh:

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 
} 

cho đến nay rất tốt, khi một ngoại lệ được kích hoạt, trình điều khiển hoạt động như bình thường và phản hồi với:

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

nhưng thứ e trường errorCode không được hiển thị trong phản hồi JSON.

Vậy làm cách nào tôi có thể xác định phản hồi ngoại lệ tùy chỉnh trong ứng dụng của mình.

Trả lời

20

Khởi động mùa xuân sử dụng triển khai ErrorAttributes để điền Map được hiển thị dưới dạng JSON. Theo mặc định, một thể hiện của DefaultErrorAttributes được sử dụng. Để bao gồm tùy chỉnh errorCode bạn cần phải cung cấp triển khai ErrorAttributes tùy chỉnh biết về mã ServiceException và mã lỗi của nó. Triển khai tùy chỉnh này phải là một @Bean trong cấu hình của bạn.

Một cách tiếp cận sẽ được sub-class 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

Hi Andy, đây Nếu lớp ngoại lệ tùy chỉnh mở rộng với ngoại lệ hoặc Throwable sau đó lỗi dụ sẽ UnhandledThrowException tại sao nó đang xảy ra. – KSK

+0

@KSK Nó không rõ ràng với tôi như thế nào đó là liên quan đến câu hỏi này một câu trả lời. Tôi nghĩ bạn nên hỏi một câu hỏi mới với một số chi tiết hơn –

+0

tuyệt vời, cảm ơn bạn Andy –

3

@ Alex Bạn có thể sử dụng chú thích @ExceptionHandler (YourExceptionClass.class) để xử lý các ngoại lệ cụ thể trong RestController cụ thể. Tôi nghĩ đó là cách tốt hơn để xử lý các tình huống phức tạp trong các ứng dụng kinh doanh. Hơn nữa tôi sẽ đề nghị bạn sử dụng dịch ngoại lệ tùy chỉnh để đối phó với các loại ngoại lệ khác nhau. Bạn có thể xem xét spring oauth2 exception translator làm mã tham chiếu cho trình dịch ngoại lệ.

Lưu ý: Mã sau chỉ hiểu khái niệm về giải pháp này. Nó không phải là mã sản xuất sẵn sàng. Hãy thảo luận thêm về nó.

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

Tôi nghĩ rằng tôi thích cách tiếp cận này tốt hơn so với xác định lại 'ErrorAttributes' trên toàn cầu. Mặc dù tôi nghĩ rằng nó lý tưởng vẫn nên sử dụng 'ErrorAttributes' toàn cầu để có được các thuộc tính mặc định, và sau đó đặt thêm các giá trị trong. –

+0

@M. Prokhorov đồng ý, điều đó sẽ làm cho nó tiếp cận mạnh mẽ hơn –

+0

@ HarpreetSandhu-TheCoder khi tôi cố gắng truy cập điều này từ một chương trình java, nó trả về mã lỗi, nhưng không phải là thông báo lỗi. tức là, nó trả về mã lỗi là 404, nhưng thông báo không tìm thấy ở bất kỳ đâu trong đối tượng phản hồi. – KingKari

Các vấn đề liên quan