美文网首页
SpringBoot 异常处理

SpringBoot 异常处理

作者: SlowGO | 来源:发表于2019-01-16 12:19 被阅读7次

    下面的示例中对请求进行验证,并添加自定义的错误信息处理。

    1. 创建 rest api 和模型类

    EmployeeRESTController.java

    import javax.validation.Valid;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class EmployeeRESTController {
        @PostMapping(value = "/employees")
        public ResponseEntity<EmployeeVO> addEmployee (@Valid @RequestBody EmployeeVO employee)
        {
            return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK);
        }
         
        @GetMapping(value = "/employees/{id}")
        public ResponseEntity<EmployeeVO> getEmployeeById (@PathVariable("id") int id)
        {
            EmployeeVO employee = null;
             
            if(employee == null) {
                 throw new RecordNotFoundException("Invalid employee id : " + id);
            }
            return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK);
        }
    }
    

    EmployeeVO.java

    import java.io.Serializable;
    
    import javax.validation.constraints.Email;
    import javax.validation.constraints.NotEmpty;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement(name = "employee")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class EmployeeVO implements Serializable
    {
        private Integer employeeId;
        private String firstName;
        private String lastName;
        private String email;
     
        public EmployeeVO(Integer id, String firstName, String lastName, String email) {
            super();
            this.employeeId = id;
            this.firstName = firstName;
            this.lastName = lastName;
            this.email = email;
        }
     
        public EmployeeVO() {
        }
         
        //Removed setter/getter for readability
    }
    

    2. Spring boot 异常处理 - rest 请求验证

    2.1 spring 默认验证支持

    修改模型类,添加验证。

    EmployeeVO.java

    package com.example.demoasync.valid;
    
    import java.io.Serializable;
    
    import javax.validation.constraints.Email;
    import javax.validation.constraints.NotEmpty;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement(name = "employee")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class EmployeeVO implements Serializable
    {
        private static final long serialVersionUID = 1L;
         
        public EmployeeVO(Integer id, String firstName, String lastName, String email) {
            super();
            this.employeeId = id;
            this.firstName = firstName;
            this.lastName = lastName;
            this.email = email;
        }
     
        public EmployeeVO() {
        }
     
        private Integer employeeId;
     
        @NotEmpty(message = "first name must not be empty")
        private String firstName;
     
        @NotEmpty(message = "last name must not be empty")
        private String lastName;
     
        @NotEmpty(message = "email must not be empty")
        @Email(message = "email should be a valid email")
        private String email;
         
        //Removed setter/getter for readability
        
    }
    

    通过 @Valid 注解开启验证:

    @PostMapping(value = "/employees")
    public ResponseEntity<EmployeeVO> addEmployee (@Valid @RequestBody EmployeeVO employee)
    {
        EmployeeDB.addEmployee(employee);
        return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK);
    }
    

    2.2 异常模型类

    RecordNotFoundException.java

    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.ResponseStatus;
     
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public class RecordNotFoundException extends RuntimeException
    {
        public RecordNotFoundException(String exception) {
            super(exception);
        }
    }
    

    ErrorResponse.java

    import java.util.List;
    import javax.xml.bind.annotation.XmlRootElement;
     
    @XmlRootElement(name = "error")
    public class ErrorResponse
    {
        public ErrorResponse(String message, List<String> details) {
            super();
            this.message = message;
            this.details = details;
        }
     
        //General error message about nature of error
        private String message;
     
        //Specific errors in API request processing
        private List<String> details;
     
        //Getter and setters
    }
    

    2.3 自定义 ExceptionHandler

    CustomExceptionHandler.java

    import java.util.ArrayList;
    import java.util.List;
     
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.validation.ObjectError;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.context.request.WebRequest;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
     
    @SuppressWarnings({"unchecked","rawtypes"})
    @ControllerAdvice
    public class CustomExceptionHandler extends ResponseEntityExceptionHandler
    {
        @ExceptionHandler(Exception.class)
        public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
            List<String> details = new ArrayList<>();
            details.add(ex.getLocalizedMessage());
            ErrorResponse error = new ErrorResponse("Server Error", details);
            return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR);
        }
     
        @ExceptionHandler(RecordNotFoundException.class)
        public final ResponseEntity<Object> handleUserNotFoundException(RecordNotFoundException ex, WebRequest request) {
            List<String> details = new ArrayList<>();
            details.add(ex.getLocalizedMessage());
            ErrorResponse error = new ErrorResponse("Record Not Found", details);
            return new ResponseEntity(error, HttpStatus.NOT_FOUND);
        }
     
        @Override
        protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
            List<String> details = new ArrayList<>();
            for(ObjectError error : ex.getBindingResult().getAllErrors()) {
                details.add(error.getDefaultMessage());
            }
            ErrorResponse error = new ErrorResponse("Validation Failed", details);
            return new ResponseEntity(error, HttpStatus.BAD_REQUEST);
        }
    }
    

    3. 测试

    1)HTTP GET /employees/23

    HTTP Status : 404
     
    {
        "message": "Record Not Found",
        "details": [
            "Invalid employee id : 23"
        ]
    }
    

    2)HTTP POST /employees

    请求:

    {
        "lastName": "Bill",
        "email": "ibill@gmail.com"
    }
    

    响应:

    HTTP Status : 400
     
    {
        "message": "Validation Failed",
        "details": [
            "first name must not be empty"
        ]
    }
    

    3)HTTP POST /employees

    请求:

    {
        "firstName":"Lokesh",
        "email": "ibill_gmail.com" //invalid email in request
    }
    

    响应:

    HTTP Status : 400
     
    {
        "message": "Validation Failed",
        "details": [
            "last name must not be empty",
            "email should be a valid email"
        ]
    }
    

    相关文章

      网友评论

          本文标题:SpringBoot 异常处理

          本文链接:https://www.haomeiwen.com/subject/cxxmdqtx.html