Path Variables

在REST API 中 通过@PathVariable注释来指定要传入的参数,例子如下:

当前端访问url:/api/students/1的时候,就会返回studentId == 1的学生对象。

1
2
3
4
5
6
7
8
9
10
@RestController
@RequestMapping("/api")
public class StudentRestController {
@GetMapping("/students/{studentId}")
public Student getStudent(@PathVariable int studentId) {
List<Student> theStudents = new ArrayList<>();
...
return theStudents.get(studentId);
}
}

默认情况下 @GetMapping("/students/{studentId}") 中的 参数名字要和 @PathVariable int studentId 中的参数名一致。

Exception handling

构建一个处理不能找到学生id的错误处理的步骤包含以下4步(无法处理输入的id是string类型的错误):

  1. 构建一个自定义的错误消息类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // custome error class
    public class StudentErrorResponse() {
    private int status;
    private String message;
    private long timestamp;

    //constructor...
    //getter and setter...
    }
  2. 创建一个自定义的exception类
    1
    2
    3
    4
    5
    public class StudentNotFoundException extends RuntimeException() {

    //constructor from superclass

    }
  3. 在REST service如果遇到了错误则抛出这个exception
    1
    2
    3
    4
    5
    6
    7
    //....

    if ((studentId >= theStudents.size()) || (studentId < 0>)) {
    throw new StudentNotFoundException("Student id not found - " + studentId);
    }

    //...
  4. 使用@ExceptionHanlder添加一个exception hanlder
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @ExceptionHanlder
    //这个exception hanlder将会捕捉StudentNotFoundException类型的exception
    public ResponseEntity<StudentErrorResponse> handleException(StudentNotFoundException exc) {
    StudentErrorResponse error = new StudentErrorResponse();
    error.setStatus(HttpStatus.NOT_FOUND.value());
    error.setMessage(exc.getMessage());
    error.setTimeStamp(System.currentTimeMillis());

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

因为handleException(StudentNotFoundException exc)的参数是StudentNotFoundException,所以它只能捕捉这种类型的错误。如果我们想扩大捕捉的范围,就将参数换成Exception的类型,这样她就会捕捉所有的exception。然后修改相应的HttpStatues的类型

Golbal exception handler

上面的studentexception是在Controller里面的,如果有多个controller就要在每个里面编写对应的exception,这样明显是不合理的。所以我们可以通过使用@ControllerAdvice注释来创建全局的exception handle代码,这也是AOP的思想。

1
2
3
4
5
6
7
8
9
10
11
12
@ControllerAdvice
public class StudentRestExceptionHandler {
@ExceptionHanlder
public ResponseEntity<StudentErrorResponse> handleException(StudentNotFoundException exc) {
StudentErrorResponse error = new StudentErrorResponse();
error.setStatus(HttpStatus.NOT_FOUND.value());
error.setMessage(exc.getMessage());
error.setTimeStamp(System.currentTimeMillis());

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