要用 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 的GET
、POST
、PUT
和DELETE
调用)。(注意:阅读每种方法并了解他它们的作用非常有用。); 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"}]
在这里,我们可以查看压缩格式的预加载数据。
扫描二维码关注公众号,回复:
10979116 查看本文章
如果我们尝试查询一个不存在的用户…
$ 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 服务吗?(如果我们没有受到提示,则答案为否。)
缺少了什么?