SpringBoot 2 構建 REST 服務 - HTTP 平臺

要用 Web 層包裝存儲庫,必須使用 Spring MVC。多虧了 Spring Boot,幾乎沒有基礎代碼可以編寫。相反,我們可以專注於操作:

nonrest/src/main/java/payroll/EmployeeController.java

package payroll;

import java.util.List;

import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
class EmployeeController {

  private final EmployeeRepository repository;

  EmployeeController(EmployeeRepository repository) {
    this.repository = repository;
  }

  // Aggregate root

  @GetMapping("/employees")
  List<Employee> all() {
    return repository.findAll();
  }

  @PostMapping("/employees")
  Employee newEmployee(@RequestBody Employee newEmployee) {
    return repository.save(newEmployee);
  }

  // Single item

  @GetMapping("/employees/{id}")
  Employee one(@PathVariable Long id) {

    return repository.findById(id)
      .orElseThrow(() -> new EmployeeNotFoundException(id));
  }

  @PutMapping("/employees/{id}")
  Employee replaceEmployee(@RequestBody Employee newEmployee, @PathVariable Long id) {

    return repository.findById(id)
      .map(employee -> {
        employee.setName(newEmployee.getName());
        employee.setRole(newEmployee.getRole());
        return repository.save(employee);
      })
      .orElseGet(() -> {
        newEmployee.setId(id);
        return repository.save(newEmployee);
      });
  }

  @DeleteMapping("/employees/{id}")
  void deleteEmployee(@PathVariable Long id) {
    repository.deleteById(id);
  }
}
  • @RestController 表示每個方法返回的數據將直接寫入響應主體,而不是呈現模版;
  • EmployeeRepository 由構造函數注入到控制器中;
  • 我們爲每個操作提供路由(@GetMapping@PostMapping@PutMapping@DeleteMapping,對應於 HTTP 的 GETPOSTPUTDELETE 調用)。(注意:閱讀每種方法並瞭解他它們的作用非常有用。);
  • EmployeeNotFoundException 是一個異常,用於指示何時查找員工但找不到員工。

nonrest/src/main/java/payroll/EmployeeNotFoundException.java

package payroll;

class EmployeeNotFoundException extends RuntimeException {

  EmployeeNotFoundException(Long id) {
    super("Could not find employee " + id);
  }
}

當拋出 EmployeeNotFoundException 時,Spring MVC 配置的這個額外花絮用於呈現 HTTP 404

nonrest/src/main/java/payroll/EmployeeNotFoundAdvice.java

package payroll;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
class EmployeeNotFoundAdvice {

  @ResponseBody
  @ExceptionHandler(EmployeeNotFoundException.class)
  @ResponseStatus(HttpStatus.NOT_FOUND)
  String employeeNotFoundHandler(EmployeeNotFoundException ex) {
    return ex.getMessage();
  }
}
  • @ResponseBody 表示該建議直接呈現到響應主體中;
  • @ExceptionHandler 將建議配置爲僅在拋出 EmployeeNotFoundException 時才響應;
  • @ResponseStatus 說要發出 HttpStatus.NOT_FOUND,即 HTTP 404
  • 建議的主題生成內容。在這種情況下,它會給出異常消息。

要啓動要用,請右鍵單機 PayRollApplication 中的 public static void main,然後從 IDE 中選擇 Run,或者:

Spring Initializr 使用 Maven 包裝器,因此鍵入:

$ ./mvnw clean spring-boot:run

或者使用我們安裝的 Maven 版本鍵入以下命令:

$ mvn clean spring-boot:run

應用啓動後,我們可以立即對其進行查詢。

$ curl -v localhost:8080/employees

這將產生:

*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /employees HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Thu, 09 Aug 2018 17:58:00 GMT
<
* Connection #0 to host localhost left intact
[{"id":1,"name":"Bilbo Baggins","role":"burglar"},{"id":2,"name":"Frodo Baggins","role":"thief"}]

在這裏,我們可以查看壓縮格式的預加載數據。

如果我們嘗試查詢一個不存在的用戶…

$ curl -v localhost:8080/employees/99

我們將得到:

*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /employees/99 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 404
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 26
< Date: Thu, 09 Aug 2018 18:00:56 GMT
<
* Connection #0 to host localhost left intact
Could not find employee 99

該消息很好地顯示了 HTTP 404 錯誤和自定義消息找不到僱員 99

顯示當前編碼的交互並不困難…

$ curl -X POST localhost:8080/employees -H 'Content-type:application/json' -d '{"name": "Samwise Gamgee", "role": "gardener"}'

創建一個新的 Employee 記錄,然後將內容發送回給我們:

{"id":3,"name":"Samwise Gamgee","role":"gardener"}

我們可以更改用戶:

$ curl -X PUT localhost:8080/employees/3 -H 'Content-type:application/json' -d '{"name": "Samwise Gamgee", "role": "ring bearer"}'

更新用戶:

{"id":3,"name":"Samwise Gamgee","role":"ring bearer"}

根據我們構建服務的方式,可能會產生重大影響。在這種情況下,替換更新更好。例如,如果未提供名稱,則將其晴空。

我們可以刪除…

$ curl -X DELETE localhost:8080/employees/3
$ curl localhost:8080/employees/3
Could not find employee 3

這一切都很好,但是我們由 RESTful 服務嗎?(如果我們沒有受到提示,則答案爲否。)

缺少了什麼?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章