This article introduces the best practices for Spring Boot to develop REST interfaces and shares them with you, as follows:
HTTP verbs correspond to SQL commands
GET
Obtain resources from the server, you can obtain one or more resources, and obtain all user information on the server, GET /users/ID, the specified ID, and obtain user information of the specified ID.
POST
Create a new resource on the server, corresponding to CREATEPOST /users in the SQL command to create a new user
PUT
Update a resource on the server, and the client provides the changed complete resource, corresponding to the UPDATEPUT /users/ID in the SQL command to update all information of the user with the specified ID
DELETE
Delete a resource from the server, and delete the user information of the specified ID corresponding to the DELETEDELETE /users/ID in the SQL command
PATCH
Update some attributes of a resource on the server, corresponding to UPDATEPATCH /users/ID in the SQL command to update a certain attribute of the user with the specified ID
Conventions in URLs
Nouns in URLs use plural forms
The question of whether the name in a URL uses an singular or a plural has been controversial. The nouns in the URL generally correspond to tables in the database, and the tables store similar data. In practice, I force the use of plural forms, which looks more comfortable.
/users/users/1/roles/roles/roles/1
As for some irregular and uncountable nouns, it depends on your opinion.
/heroes/heroes/1/people/people/1/foots/foots/1/feet/feet/1/feet/feet/1
Version
Speak version numbers to be added to the URL to deal with incompatible and destructive changes. When releasing a new API, the client can move to the new API freely and will not be in trouble because of calling a completely different new API. Use an intuitive "V" prefix to indicate that the following number is the version number, no secondary version number is required, and API versions should not be released frequently.
/edu/v1/users/edu/v1/roles
Use query strings for optional, complex parameters
In order to make the URL smaller and more concise, set a basic URL for the resource, and optional and complex parameters are represented by query strings.
/edu/v1/users?enabled=1&roleid=1
Provide paging information
It is not a good idea to return all resources in the database at once, so a paging mechanism is required. Usually, the well-known parameters in the database are used to offset and limit
/edu/v1/users?enabled=1&offset=1&limit=15
If the client does not pass these parameters, the default value should be used, usually offset=0, limit=10.
Use verbs for non-resource requests
Sometimes API calls do not involve resources, in which case the server performs an operation and returns the result to the client.
/edu/v1/calc?p=100
Consider specific resources and cross-resource searches
It is easy to provide a search for a specific end-of-stay. You just need to use the corresponding resource collection and append the search string to the query parameters.
/edu/v1/users?username=Li Qinghai
If you need to provide a global search for all resources, you need to use another method.
/edu/v1/search?key=Li Qinghai
Response results
Use small camel nomenclature as attribute identifier
Typically, RESTful web services will be used by clients written in JavaScript. The client converts the JSON response to a JavaScript object and then calls its properties. Therefore, it is best to follow the JavaScript code common specification.
person.year_of_birth // Not recommended, violating the JavaScript code general specification person.YearOfBirth // Not recommended, JavaScript constructor named person.yearOfBirth // Recommended
Provide paging information
When there are many results returned, paging information should be provided.
{ "page": 0, "size": 10, "total": 3465, "obj": [ ] }Spring MVC development REST interface
Common annotations
@RestController
@RestController is a combination annotation of @ResponseBody and @Controller.
@RequestMapping
This annotation can be applied to a method of the controller or to this controller class. When the controller adds the @RequestMapping annotation at the class level, this annotation is applied to all processor methods of the controller. The @RequestMapping annotation on the processor method will supplement the declaration of @RequestMapping at the class level.
@PostMapping
Combination annotation is the abbreviation of @RequestMapping(method =RequestMethod.POST).
@PutMapping
Combination annotation is the abbreviation of @RequestMapping(method = RequestMethod.PUT).
@PatchMapping
Combination annotation is the abbreviation of @RequestMapping(method = RequestMethod.PATCH).
@DeleteMapping
Combination annotation is the abbreviation of @RequestMapping(method = RequestMethod.DELETE).
@GetMapping
Combination annotation is the abbreviation of @RequestMapping(method = RequestMethod.GET).
@PathVariable
Get the data in the url.
@RequestParam
Gets the value of the requested parameter.
REST interface and Swagger API documentation example
For the use of Swagger, please refer to the use of Swagger2 in the Spring Boot project. The code in the method body is not important, what is important is the signature of the method and the mapping with HTTP verbs.
import java.util.Date;import javax.persistence.EntityNotFoundException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PatchMapping;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.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import cn.com.infcn.jianshu.Service.UserService;import cn.com.infcn.jianshu.exception.BizException;import cn.com.infcn.jianshu.exception.LoginNameOrPasswordErrorException;import cn.com.infcn.jianshu.exception.ResourceExistsException;import cn.com.infcn.jianshu.model.User;import cn.com.infcn.jianshu.util.JsonResult;import io.swagger.annotations.Api;import io.swagger.annotations.ApiParam;/** * System User Controller * * @author Li Qinghai* */@Api(value = "System User Interface", tags = "System Management")@RestController@RequestMapping("/v3/edu/users")public class UserController { @Autowired private UserService userService; /** * Add user, register * * @param loginName * Login account* @param userName * User name* @param password * Login password* @param roleId * User role* @return * @throws ResourceExistsException */ @ApiOperation(value = "Add user") @PostMapping("/") public JsonResult create( @ApiParam(name = "loginName", value = "Login account", required = true) @RequestParam(required = true) @RequestBody String loginName, @ApiParam(name = "userName", value = "Username", required = true) @RequestParam(required = true) @RequestBody String userName, @ApiParam(name = "password", value = "Log in password", required = true) @RequestParam(required = true) @RequestBody String password, @ApiParam(name = "roleId", value = "User Role Number", required = true) @RequestParam(required = true) @RequestBody String roleId) throws ResourceExistsException { boolean exists = this.userService.exists(loginName); if (exists) { throw new ResourceExistsException(loginName); } User user = userService.create(loginName, password, userName, roleId); return JsonResult.success(user); } /** * User login with login account and login password* * @param loginName * Login account* @param password * Login password* @throws EntityNotFoundException */ @ApiOperation(value = "Query user information based on user number") @GetMapping("/login") public JsonResult login( @ApiParam(name = "loginName", value = "Login account", required = true) @RequestParam(required = true) String loginName, @ApiParam(name = "password", value = "Login Password", required = true) @RequestParam(required = true) String password) throws LoginNameOrPasswordErrorException { User user = this.userService.login(loginName, password); if (null == user) { throw new LoginNameOrPasswordErrorException(); } return JsonResult.success(user); } /** * Query user information based on user number* * @param id * User number* @throws EntityNotFoundException */ @ApiOperation(value = "Query user information based on user number") @GetMapping("/{id}") public JsonResult read( @ApiParam(name = "id", value = "User number, primary key", required = true) @PathVariable(required = true) String id) throws EntityNotFoundException { User user = this.userService.getOne(id); return JsonResult.success(user); } /** * Account is cancelled, and the user's data is not deleted* * @param userId * User number* @return */ @ApiOperation(value = "Carded out of account") @PatchMapping("/{id}") public JsonResult cancel( @ApiParam(name = "id", value = "User number, primary key", required = true) @PathVariable(required = true) String id) throws EntityNotFoundException { this.userService.cancel(id); return JsonResult.success(); } /** * Reset password* * @param id * User number* @param password * New login password* @return */ @ApiOperation(value = "Reset password") @PatchMapping("/") public JsonResult updatePassword( @ApiParam(name = "id", value = "User number, primary key", required = true) @RequestParam(required = true) String id, @ApiParam(name = "password", value = "New login password", required = true) @RequestParam(required = true) String password) { this.userService.updatePassword(id, password); return JsonResult.success(); } /** * Multi-condition combination query* * @param userName * User name* @param roleId * User role* @param start * Start date* @param end * End date* @param page * Pagination, starting from 0* @param size * Number of rows per page, default 10 * @return * @throws BizException */ @ApiOperation(value = "User information query") @GetMapping("/") public JsonResult query( @ApiParam(name = "userName", value = "User name, query keyword", required = false) @RequestParam(required = false) String userName, @ApiParam(name = "roleId", value = "User Role Number", required = false) @RequestParam(required = false) String roleId, @ApiParam(name = "start", value = "User Role Number", required = false) @RequestParam(required = false) Date start, @ApiParam(name = "end", value = "User Role Number", required = false) @RequestParam(required = false) Date end, @ApiParam(name = "page", value = "Pagination, which page, starting from 1", defaultValue = "1", required = true) @RequestParam(defaultValue = "1", required = true) int page, @ApiParam(name = "size", value = "Number of rows per page, positive integer", defaultValue = "10", required = true) @RequestParam(defaultValue = "10", required = true) int size) throws BizException { Page<User> datas = this.userService.findDatas(userName, roleId, start, end, page, size); if (null == datas || null == datas.getContent() || datas.getContent().isEmpty()) { throw new BizException("User does not exist"); } return JsonResult.success(datas); }}Swagger2 interface document rendering
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.