1. RESTfuldesignprinciples
REST (Representational State Transfer) is a软件architecture风格, 用于designnetworkapplication程序. RESTful API is 遵循RESTprinciples APIdesign方式.
1.1 RESTfuldesign coreprinciples
- resource (Resources) : 将一切视 for resource, usingURI (统一resource标识符) 标识resource
- 表现层 (Representation) : resource 表现形式, such asJSON, XMLetc.
- status转移 (State Transfer) : throughHTTPmethodimplementationresourcestatus 转移
- 无status (Stateless) : server不保存客户端status, 每次request都package含完整information
- 客户端-server (Client-Server) : 客户端 and server分离, 独立演进
- cache (Cache) : supportcache, improvingperformance
- 分层system (Layered System) : system可以分层deployment, 客户端不需要知道system in 部structure
1.2 HTTPmethod and resourceoperation
RESTful APIusingHTTPmethod来表示 for resource operation:
| HTTPmethod | operationclass型 | exampleURI | describes |
|---|---|---|---|
| GET | 读取 | /api/users | 获取所 has user |
| GET | 读取 | /api/users/1 | 获取ID for 1 user |
| POST | creation | /api/users | creation new user |
| PUT | update | /api/users/1 | updateID for 1 user |
| PATCH | 部分update | /api/users/1 | 部分updateID for 1 user |
| DELETE | delete | /api/users/1 | deleteID for 1 user |
1.3 RESTful API best practices
- using名词而不 is 动词来命名resource
- using复数形式命名resourcecollection
- usingHTTPstatus码表示response结果
- using一致 命名规则
- providing适当 errorinformation
- supportfilter, sort and 分页
- usingversion控制
2. creationREST API控制器
in Spring Bootin, 我们using@RestController注解creationREST API控制器. @RestController is @Controller and @ResponseBody 组合, 用于返回JSON or XMLetc.response体.
2.1 creation第一个REST控制器
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/api/hello")
public String hello() {
return "Hello, REST API!";
}
}
2.2 控制器class层次structure
for 于 complex API, 我们可以creation控制器层次structure, using@RequestMapping注解指定Basicspath:
package com.example.demo.controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public List getAllUsers() {
// 返回所 has user
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
// 返回指定ID user
}
@PostMapping
public User createUser(@RequestBody User user) {
// creation new user
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
// updateuser
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
// deleteuser
}
}
3. requestmap
Spring Bootproviding了 many 种注解用于requestmap:
3.1 pathmap注解
@GetMapping: processingGETrequest@PostMapping: processingPOSTrequest@PutMapping: processingPUTrequest@DeleteMapping: processingDELETErequest@PatchMapping: processingPATCHrequest@RequestMapping: commonrequestmap, 可以指定 many 种HTTPmethod
3.2 pathvariable
using@PathVariable注解获取URLin pathvariable:
@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
// usingidparameter
}
// 可以指定variable名
@GetMapping("/users/{user_id}")
public User getUserById(@PathVariable("user_id") Long id) {
// usingidparameter
}
// 可选pathvariable
@GetMapping("/users/{id?}")
public List getUsers(@PathVariable(required = false) Long id) {
// such as果providing了id, 则返回指定user, 否则返回所 has user
}
3.3 requestparameter
using@RequestParam注解获取requestparameter:
@GetMapping("/users")
public List getUsers(
@RequestParam(required = false) String name,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
// usingrequestparameterforfilter, 分页etc.operation
}
3.4 request头
using@RequestHeader注解获取request头information:
@GetMapping("/users")
public List getUsers(@RequestHeader("Authorization") String authorization) {
// usingauthorization头information
}
3.5 Cookie
using@CookieValue注解获取Cookie值:
@GetMapping("/users")
public List getUsers(@CookieValue("sessionId") String sessionId) {
// usingsessionIdforsessionmanagement
}
4. request体processing
using@RequestBody注解将request体转换 for Javaobject:
4.1 creation实体class
package com.example.demo.model;
public class User {
private Long id;
private String name;
private String email;
// getter and settermethod
}
4.2 接收request体
@PostMapping("/users")
public User createUser(@RequestBody User user) {
// processingusercreationrequest
return userService.save(user);
}
4.3 verificationrequest体
可以usingBean Validation API (JSR-380) for request体forverification:
package com.example.demo.model;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
public class User {
private Long id;
@NotBlank(message = "姓名不能 for 空")
@Size(min = 2, max = 50, message = "姓名 long 度必须 in 2 to 50个字符之间")
private String name;
@NotBlank(message = "邮箱不能 for 空")
@Email(message = "邮箱格式不正确")
private String email;
// getter and settermethod
}
in 控制器in添加@Valid注解:
@PostMapping("/users")
public ResponseEntity createUser(@Valid @RequestBody User user, BindingResult result) {
if (result.hasErrors()) {
// processingverificationerror
return ResponseEntity.badRequest().build();
}
// processingusercreationrequest
return ResponseEntity.ok(userService.save(user));
}
5. responseprocessing
Spring Bootproviding了 many 种方式processingresponse:
5.1 返回 simple class型
@GetMapping("/hello")
public String hello() {
return "Hello, REST API!";
}
@GetMapping("/count")
public int getCount() {
return 100;
}
5.2 返回object or collection
@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
return userService.findById(id);
}
@GetMapping("/users")
public List getAllUsers() {
return userService.findAll();
}
5.3 usingResponseEntity
ResponseEntityclass允许我们完全控制response, includingstatus码, response头 and response体:
@GetMapping("/users/{id}")
public ResponseEntity getUserById(@PathVariable Long id) {
User user = userService.findById(id);
if (user == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(user);
}
@PostMapping("/users")
public ResponseEntity createUser(@Valid @RequestBody User user) {
User savedUser = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED)
.header("Location", "/api/users/" + savedUser.getId())
.body(savedUser);
}
5.4 自定义responsestructure
可以creation统一 responsestructure, package含status码, message and data:
package com.example.demo.dto;
public class ApiResponse {
private int status;
private String message;
private T data;
// constructmethod, getter and setter
public static ApiResponse success(T data) {
return new ApiResponse<>(200, "success", data);
}
public static ApiResponse error(int status, String message) {
return new ApiResponse<>(status, message, null);
}
}
in 控制器inusing:
@GetMapping("/users/{id}")
public ApiResponse getUserById(@PathVariable Long id) {
User user = userService.findById(id);
if (user == null) {
return ApiResponse.error(404, "user不存 in ");
}
return ApiResponse.success(user);
}
6. exceptionprocessing
Spring Bootproviding了 many 种方式processingexception:
6.1 全局exceptionprocessing
using@RestControllerAdvice注解creation全局exceptionprocessing器:
@RestControllerAdvice
public class GlobalExceptionprocessingr {
@Exceptionprocessingr(ResourceNotFoundException.class)
public ResponseEntity> handleResourceNotFoundException(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ApiResponse.error(404, ex.getMessage()));
}
@Exceptionprocessingr(MethodArgumentNotValidException.class)
public ResponseEntity> handleValidationException(MethodArgumentNotValidException ex) {
// processingverificationexception
}
@Exceptionprocessingr(Exception.class)
public ResponseEntity> handleGenericException(Exception ex) {
// processingotherexception
}
}
6.2 自定义exception
creation自定义exceptionclass:
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
in service层抛出exception:
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("user不存 in , ID: " + id));
}
7. APIdocumentation
for REST API生成documentation is 非常 important , Spring Bootsupport many 种APIdocumentationtool:
7.1 SpringDoc OpenAPI
SpringDoc OpenAPI is a 用于生成OpenAPIdocumentation library, supportSpring Boot 3.0+.
7.1.1 添加依赖
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
7.1.2 configurationSpringDoc
in application.propertiesinconfiguration:
# APIdocumentation标题
springdoc.api-docs.title=Spring Boot REST API
# APIdocumentationdescribes
springdoc.api-docs.description=Spring Boot REST API Documentation
# APIversion
springdoc.api-docs.version=v1
# 启用APIdocumentation
springdoc.api-docs.enabled=true
# Swagger UIpath
springdoc.swagger-ui.path=/swagger-ui.html
7.1.3 访问APIdocumentation
- Swagger UI: http://localhost:8080/swagger-ui.html
- OpenAPI JSON: http://localhost:8080/v3/api-docs
7.2 using注解增强documentation
可以usingOpenAPI注解增强APIdocumentation:
@RestController
@RequestMapping("/api/users")
@Tag(name = "usermanagement", description = "user相关operation")
public class UserController {
@GetMapping
@Operation(summary = "获取所 has user", description = "返回systemin所 has user list")
public List getAllUsers() {
// implementation
}
@GetMapping("/{id}")
@Operation(summary = "根据ID获取user", description = "根据userID返回userinformation")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "成功获取user",
content = @Content(schema = @Schema(implementation = User.class))),
@ApiResponse(responseCode = "404", description = "user不存 in ")
})
public ResponseEntity getUserById(@PathVariable Long id) {
// implementation
}
// othermethod
}
练习 1: creationREST API控制器
- creation一个Spring Bootproject, 添加Spring Web依赖
- creation一个User实体class, package含id, name, email字段
- creation一个UserController, implementation以 under API:
- GET /api/users - 获取所 has user
- GET /api/users/{id} - 获取指定ID user
- POST /api/users - creation new user
- PUT /api/users/{id} - updateuser
- DELETE /api/users/{id} - deleteuser
- usingPostman or curltestAPI
练习 2: implementationrequestverification and exceptionprocessing
- for User实体class添加verification注解 (@NotBlank, @Emailetc.)
- in 控制器in添加verification逻辑
- creation自定义exceptionclassResourceNotFoundException
- creation全局exceptionprocessing器, processingResourceNotFoundException and verificationexception
- testverification and exceptionprocessingfunctions
练习 3: 集成APIdocumentation
- 添加SpringDoc OpenAPI依赖
- configurationAPIdocumentationbasicinformation
- usingOpenAPI注解增强APIdocumentation
- 访问Swagger UI, 查看生成 APIdocumentation