In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "how to write API interface". The content of the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "how to write API interface".
Thinking
Business interfaces usually contain the most basic CRUD operations, how to unify these interfaces as much as possible?
API interface part will use the data in HttpServletRequest and HttpServletResponse, how to easily get these two objects?
The parameters of the interface are sometimes passed through a single parameter and sometimes through an object. How to easily test these parameters without frequently using if judgment to identify the critical value or null?
With these questions, we solve them step by step.
Overall class diagram
Unified basic interface path
As mentioned in the previous article, how to use different protocols in the correct posture. GET,POST,PUT,PATCH,DELETE these five protocols are commonly used in daily CRUD development. Different businesses basically list these API interfaces, so can we try to extract them into interfaces, and then let different business control layers to implement this interface, so as to standardize the basic interface path? Theory exists and practice begins.
Practice v1 version
First define a common java interface class, write four methods, corresponding to add, delete, query and modify four operations. Note: PATCH API modifies a single attribute value, because there are too many differences in fields in different businesses, so it is more suitable for separate implementation. This interface is not covered in this interface.
Public interface BaseCrud {R selectList (@ ModelAttribute Map s); R selectOne (@ PathVariable String id); R add (@ RequestBody Map t); R upp (@ PathVariable String id, @ RequestBody Map t); R del (@ PathVariable String id);}
I believe you see these five interfaces at a glance, this is not add, delete, query and modify plus a paging interface. With this interface, it is easy for us to write the control layer of a business, directly implement it, and then achieve different logic, perfect.
/ / take user-related business and User user-related business as an example / / teacher business control layer @ Controller@RequestMapping ("user") public class UserController implements BaseCrud {@ Override @ GetMapping @ ResponseBody public R selectList (Map s) {return null;} @ Override @ GetMapping ("{id}") @ ResponseBody public R selectOne (String id) {return null } @ Override @ PostMapping @ ResponseBody public R add (Map t) {return null;} @ Override @ PutMapping ("{id}") @ ResponseBody public R upp (String id, Map t) {return null;} @ Override @ DeleteMapping ("{id}") @ ResponseBody public R del (String id) {return null }} / / teacher business control layer, the same operation as above, save space here, omit first.
Through the postMan test, the interfaces of their respective services can be called with teacher and user prefixes respectively, and a simple unified path for adding, deleting, querying and modifying is realized. But this will also have a defect, because we all use Map to receive, map key value pair because uncertain fields, later if not debug is very difficult to maintain, or even the field can be adjusted, not easy to troubleshoot, secondly, if we use Mybatis operation, but also need to convert to objects, although the unified interface path, but the back of the operation is still very cumbersome, so we still have to further optimize.
V2 version
I believe everyone is no stranger to generics. We can also use generics to optimize here. Because search paging needs to carry page numbers, sorting, and so on, we implement it as two generics.
/ / you need to pay attention to a little detail, because the path protocols of these five interfaces can be unified, so when we define the interface, we write the concatenated path in the interface. Public interface BaseCrud {/ * * @ description: paging query interface * @ author: chenyunxuan * @ updateTime: 11:40 on 2020-12-18 * / @ GetMapping R selectList (@ ModelAttribute S s) / * * @ description: query single data according to id * @ author: chenyunxuan * @ updateTime: 11:44 on 2020-12-18 * / @ GetMapping ("{id}") R selectOne (@ PathVariable String id) / * * @ description: add a single data * @ author: chenyunxuan * @ updateTime: 1:39 p.m., 2020-12-18 * / @ PostMapping R add (@ RequestBody T t) / * * @ description: modify a single data * @ author: chenyunxuan * @ updateTime: 1:39 on 2020-12-18 * / @ PutMapping ("{id}") R upp (@ PathVariable String id, @ RequestBody T t) / * * @ description: delete a single data * @ author: chenyunxuan * @ updateTime: 1:40 on 2020-12-18 * / @ DeleteMapping ("{id}") R del (@ PathVariable String id);}
Define two different business entity classes. Used for paging and new modifications respectively.
@ Data// corresponds to generic T, which is used to add and modify public class User {private String mobile; private String name; private String email; private Integer age; private LocalDateTime birthday;} @ Data// corresponding to generic S, and to search for public class UserSearch {private Integer pageNum; private String mobile; private String name; private String email;}.
Next is the implementation of the business control layer.
RestController @ RequestMapping ("teacher") public class UserController implements BaseCrud {@ Override public R selectList (UserSearch userSearch) {return null;} @ Override public R selectOne (String id) {return null;} @ Override public R add (User user) {return null;} @ Override public R upp (String id, User user) {return null } @ Override public R del (String id) {return null;}}
You can see that this version is much more convenient than the V1 version, optimizes the transfer object, and different businesses can create different objects for transmission. There is one small detail, the @ ResponseBody on the method has been omitted because @ RestController already contains the @ ResponseBody annotation. So far a general API interface unified demo has been completed.
Unified practice of parameter validation
People always pursue perfection, and I am no exception. Although the above v2 version unifies all the basic interfaces, I can't love to see that so many fields need to be validated. For example, when adding, the user's nickname cannot be empty. The user's age should be at least one year old and so on. Once again, my code is full of if judgment. I have to find a way to optimize it.
V3 version
We first introduce a parameter checking component validation of spring, which can easily verify the input parameters with annotations, and if an exception can be thrown directly by capturing the corresponding exception information.
Org.springframework.boot spring-boot-starter-validation
Here are some commonly used validation constraint annotations
@ Null the annotated element must be null
@ NotNull the annotated element must not be null
@ AssertTure the annotated element must be ture
@ AssertFalse the annotated element must be false
@ Min (value) the annotated element must be numeric and must be greater than or equal to the specified value
@ Max (value) the annotated element must be numeric and must be less than or equal to the specified value
@ DecimalMin (value) the annotated element must be numeric and must be greater than or equal to the specified value
@ DecimalMax (value) the annotated element must be numeric and must be less than or equal to the specified value
@ Size (max, min) the annotated element must be within the specified range
@ Digits (integer, fraction) the annotated element must be a number and its value must be within the given range
@ Past the annotated element must be a past date
@ Future the annotated element must be a future date
@ Pattern (value) the annotated element must conform to the given regular expression
@ Email the annotated element must be an Email address
@ Length (min, max) the annotated element length must be within the specified range
@ NotEmpty the annotated element must not be empty, nor can an empty string
@ Range the annotated element (which can be a number or a string representing a number) must be within the given range
@ URL the annotated element must be URL
@ Valid verifies entity classes
Next, we start to modify our interface, and you can add notes where entities are used in BaseCrud.
/ * @ description: paging query interface * @ author: chenyunxuan * @ updateTime: 11:40 on 2020-12-18 * / @ GetMapping R selectList (@ Validated @ ModelAttribute S s); / * @ description: add a single data * @ author: chenyunxuan * @ updateTime: 1:39 afternoon on 2020-12-18 * / @ PostMapping R add (@ Validated @ RequestBody T t) / * * @ description: modify a single data * @ author: chenyunxuan * @ updateTime: 1:39 on 2020-12-18 * / @ PutMapping ("{id}") R upp (@ PathVariable String id, @ Validated @ RequestBody T t)
At the same time, our entity class should also be modified accordingly, adding the verification annotations you want.
Public class User {/ * @ description: custom parameter validation (phone number verification) * @ author: chenyunxuan * @ updateTime: 2019-12-18 17:30 * / @ MobileVail (groups = {Add.class}) private String mobile / / the user name is a minimum of two digits and a maximum of 30 digits / / the group grouping here will describe its function @ Size (min = 2, max = 30, groups = {Upp.class}) private String name / * * @ description: custom error message * @ author: chenyunxuan * @ updateTime: 2019-12-18 17:30 * / check notes can be customized message, and return message @ NotEmpty (message = "Custom error message, Email cannot be empty") @ Email private String email with exception interception @ NotNull @ Min @ Max @ DateTimeFormat (pattern = "MM/dd/yyyy") / / cannot be empty and must be before system time @ NotNull @ Past private LocalDateTime birthday;}
From the above code, we can draw the following conclusion
Check annotations can be superimposed
You can customize the annotation when the preset check annotation is not satisfied.
Grouping can be used to achieve different business requirements and different verification methods.
The check information thrown can be set by yourself.
Custom check comment
Sometimes the preset check can not meet the business verification requirements, such as phone number check, ID card check and so on. Fortunately, validation also thought of this part of the requirement, providing ConstraintValidator interface to customize matching rules.
First we have to customize an annotation and a verification rule class
@ Documented// specifies the class @ Constraint (validatedBy = MobileValidator.class) @ Target ({ElementType.METHOD, ElementType.FIELD}) @ Retention (RetentionPolicy.RUNTIME) public @ interface MobileVail {String message () default that actually implements the verification rule; Class [] groups () default {}; Class
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.