Introduction to best practices and best practices of REST interfaces for Spring Boot Development
This article introduces the best practices for developing REST interfaces in Spring Boot and shares them with you as follows:
HTTP verb corresponds to SQL command
GET
Obtain resources from the server. One or more resources are allowed. Corresponding to SELECTGET/users in the SQL command, obtain all user information on the server. GET/users/ID: 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. The client provides the complete changed resource. The UPDATEPUT/users/ID in the SQL command updates all information of the user with the specified ID.
DELETE
Deletes a resource from the server. The DELETEDELETE/users/ID in the SQL command deletes the user information of the specified ID.
PATCH
Update some attributes of a resource on the server. The UPDATEPATCH/users/ID in the SQL command updates a certain attribute of the user with the specified ID.
Conventions in URLs
The nouns in the URL are in the plural form.
The question of whether the URL name is singular or plural has been controversial for a long time. The nouns in URLs generally correspond to tables in the database. The tables store similar data. In practice, I use the plural form forcibly, which looks more comfortable.
/users/users/1/roles/roles/1
As for some irregular and unmeasurable terms, you can be wise.
/heroes/heroes/1/people/people/1/foots/foots/1/feet/feet/1
Version
The version number is added to the URL to cope with incompatible and destructive changes. When a new API is released, the client can freely migrate it to the new API, so it will not be in a dilemma because it calls completely different new APIs. The intuitive "V" prefix is used to indicate that the subsequent number is the version number. The minor version number is not required and the API version cannot be released frequently.
/edu/v1/users/edu/v1/roles
Use query strings for optional and complex parameters
To make the URL smaller and more concise, set a basic URL for the resource. Optional and complex parameters are represented by query strings.
/edu/v1/users?enabled=1&roleid=1
Provide paging information
Returning all the resources in the database at one time is not a good idea. Therefore, a paging mechanism is required. We usually use the well-known parameter offset and limit in the database.
/edu/v1/users?enabled=1&offset=1&limit=15
If the client does not pass these parameters, use the default value, usually offset = 0, limit = 10.
Non-resource request verb
Sometimes API calls do not involve resources. In this case, the server returns the result to the client after performing an operation.
/edu/v1/calc?p=100
Consider specific resources and cross-resource search
It is easy to search for a specific ending edge. You only need to use the corresponding resource set and append the search string to the query parameters.
/Edu/v1/users? Username = Li Qinghai
If you need to provide global search for all resources, you need to use other methods.
/Edu/v1/search? Key = Li Qinghai
Response Results
Use the small camper name method as the property identifier
Generally, RESTful Web services are used by clients written in JavaScript. The client converts the JSON response to a JavaScript Object and calls its attributes. Therefore, it is best to follow the general specification of JavaScript code.
Person. year_of_birth // not recommended. Violation of the general JavaScript code specification person. YearOfBirth // not recommended. The JavaScript constructor name is person. yearOfBirth // recommended.
Provide paging information
Paging information should be provided when many results are returned.
{ "page": 0, "size": 10, "total": 3465, "obj": [ ] }
Spring MVC development REST Interface
Common annotations
@ RestController
@ RestController is a combination of @ ResponseBody and @ Controller.
@ RequestMapping
This annotation can be applied to a controller method or to this controller class. When the Controller adds the @ RequestMapping annotation to the class level, this annotation will be applied to all the processor methods of the controller. The @ RequestMapping Annotation on the processor method supplements the @ RequestMapping declaration at the class level.
@ PostMapping
The combination annotation is the abbreviation of @ RequestMapping (method = RequestMethod. POST.
@ PutMapping
The combination annotation is the abbreviation of @ RequestMapping (method = RequestMethod. PUT.
@ PatchMapping
The combination annotation is the abbreviation of @ RequestMapping (method = RequestMethod. PATCH.
@ DeleteMapping
The combination annotation is the abbreviation of @ RequestMapping (method = RequestMethod. DELETE.
@ GetMapping
The combination annotation is the abbreviation of @ RequestMapping (method = RequestMethod. GET.
@ PathVariable
Obtain the data in the url.
@ RequestParam
Obtain the value of the request parameter.
Example of compiling API documentation for REST interface and Swagger
For more information about Swagger usage, see use Swagger2 in Spring Boot. The code in the method body is not important. What is important is the method signature and the ing with the HTTP verb.
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. apiOperation; 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 a user, register ** @ param loginName * Logon account * @ param userName * User name * @ param password * logon password * @ param roleId * User Role * @ return * @ throws ResourceExistsException */@ apiOperation (value = "Add User ") @ PostMapping ("/") public JsonResult create (@ ApiParam (name = "loginName", value = "Logon account", required = true) @ RequestParam (required = true) @ RequestBody String loginName, @ ApiParam (name = "userName", value = "User name", required = true) @ RequestParam (required = true) @ RequestBody String userName, @ ApiParam (name = "password", value = "Logon 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 User = userService. create (loginName, password, userName, roleId); return JsonResult. success (user );} /*** use the Logon account and password to log on. ** @ param loginName * Logon account * @ param password * logon password * @ throws EntityNotFoundException */@ ApiOperation (value =" query user information by user number ") @ GetMapping ("/login") public JsonResult login (@ ApiParam (name = "loginName", value = "Logon account", required = true) @ RequestParam (required = true) string loginName, @ ApiParam (name = "password", value = "Logon 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 by user number ** @ param id * user number * @ throws EntityNotFoundException */@ ApiOperation (value = "query user information by user number ") @ GetMapping ("/{id}") public JsonResult read (@ ApiParam (name = "id", value = "User id, primary key", required = true) @ PathVariable (required = true) String id) throws EntityNotFoundException {User user = this. userService. getOne (id); return JsonResult. success (user);}/*** deregister the account, do not delete user data ** @ param userId * User id * @ return */@ ApiOperation (value = "deregister account") @ PatchMapping ("/{id }") public JsonResult cancel (@ ApiParam (name = "id", value = "User id, primary key", required = true) @ PathVariable (required = true) String id) throws EntityNotFoundException {this. userService. cancel (id); return JsonResult. success ();} /***** Reset password ** @ param id * User id * @ param password * New logon password * @ return */@ ApiOperation (value = "Reset password ") @ PatchMapping ("/") public JsonResult updatePassword (@ ApiParam (name = "id", value = "User id, primary key", required = true) @ RequestParam (required = true) string id, @ ApiParam (name = "password", value = "New logon 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, start from 0 * @ param size * The number of lines per page. The default value is 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 ID", 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 = "page, page number, starting from 1", defaultValue = "1", required = true) @ RequestParam (defaultValue = "1", required = true) int page, @ ApiParam (name = "size", value = "number of lines 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
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.