preface
For an interface provided by the back end, it is essential to have a unified response format to facilitate parameter verification and unified exception handling. Today, we integrate these three basic functions into the project to make the project closer to the actual development scenario.
Unified response
In project development, generally, what is returned to the front end will be a unified return response object. Therefore, the back end needs to encapsulate a generic class as the response object. The advantage of this is that the front and back ends can return through a unified interface and can do standardized response processing.
Implementation steps:
- Create mingx common microservices to handle public services, including unified response, unified exception interception, tool classes, etc.
- Create a new com.mingx.common package under src/mian/java, and create it under this package
The functions of appresult.java, appresultbuilder.java and resultcode.java files are as follows:
- AppResult.java: a class that specifies the format of the returned result
package com.mingx.common; public class AppResult<T> { private int code; private String msg; private T data;// data public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
- AppResultBuilder.java: a class that facilitates the return of format assembly
package com.mingx.common; public class AppResultBuilder { private static Integer successCode = ResultCode.SUCCESS.getCode(); private static String successMsg = ResultCode.SUCCESS.getMsg(); //Success, no specific data returned public static AppResult<String> success(){ AppResult<String> result = new AppResult<String>(); result.setCode(successCode); result.setMsg(successMsg); result.setData(""); return result; } //Success, return data public static <T> AppResult<T> success(T t){ AppResult<T> result = new AppResult<T>(); result.setCode(successCode); result.setMsg(successMsg); result.setData(t); return result; } //Failed, return failure information public static <T> AppResult<T> error(ResultCode code){ AppResult<T> result = new AppResult<T>(); result.setCode(code.getCode()); result.setMsg(code.getMsg()); return result; } //Failed, return failure information public static <T> AppResult<T> error(ResultCode code,String extraMsg){ AppResult<T> result = new AppResult<T>(); result.setCode(code.getCode()); result.setMsg(code.getMsg() + "," + extraMsg); return result; } //Failed, return failure information public static <T> AppResult<T> error(Integer code,String extraMsg){ AppResult<T> result = new AppResult<T>(); result.setCode(code); result.setMsg(extraMsg); return result; } }
- ResultCode.java: enumeration class that defines the return information
package com.mingx.common; public enum ResultCode { /* Success status code */ SUCCESS(10000, "success"), /* System error: */ SYSTEM_ERROR(10001, "The system is busy, please try again later"), /* Parameter error: */ PARAM_ERROR(10002, "Parameter error"), /* Illegal login:*/ ILLEGAL_ERROR(10003, "Illegal user login"), /* User module: 20001-29999*/ USER_NOT_LOGGED_IN(20001, "User not logged in"), USER_LOGIN_ERROR(20002, "The user name or password is incorrect. Please check and try again"), USER_ACCOUNT_FORBIDDEN(20003, "Account has been disabled"), USER_HAS_EXISTED(20004, "User already exists"); private Integer code; private String msg; ResultCode(Integer code, String msg) { this.code = code; this.msg = msg; } public Integer getCode() { return code; } public String getMsg() { return msg; } }
Input parameter verification
In normal projects, it is inevitable to check the correctness of some parameters. These checks appear in the business code, which makes our business code look bloated. Moreover, it is boring to write such parameter verification codes frequently. In view of this, I think the Hibernate Validator framework just solves these problems. It can implement parameter verification in an elegant way, separate business code from verification logic, and no longer write duplicate verification logic.
Hibernate Validator is the reference implementation of Bean Validation. Hibernate Validator provides the implementation of all built-in constraints in JSR 303 specification. In addition, there are some additional constraints.
Bean Validation defines the corresponding metadata model and API for JavaBean validation. The default metadata is Java Annotations. The original metadata information can be overwritten and extended by using XML. Bean Validation is a runtime data validation framework. After validation, the validation error information will be returned immediately.
Preparation steps:
- Add hibernate validator master version management in the parent pom
<hibernate-validator.version>6.0.14.Final</hibernate-validator.version> <!-- hibernate validator Master version management --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate-validator.version}</version> </dependency>
2. Create a new com.mingx.common package under src/mian/java. Under this package, create regexpcontainers interface for common regular expression management, and add it according to the actual situation of the project.
package com.mingx.common; /** * General regular expression * * @author Admin */ public interface RegexpContants { /** * Nullable tag */ String NULLFLAG = "^$|"; /** * Mobile phone regular expression */ String MOBIL_EREGEXP = "^(13|14|15|16|17|18|19)\\d{9}$"; /** * Mailbox regular expression */ String EMAIL_EREGEXP = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$"; /** * ID card regular expression */ String ID_CARD_EREGEXP = "(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)"; /** * Fixed line regular expression */ String TELEPHONE_EREGEXP = "^(0\\d{2,3}-)?\\d{7,8}(-\\d{3,4})?$"; /** * Web site regular expression */ String URL_EREGEXP = "(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]"; /** * 6 Bit SMS verification code */ String SIXNUMBER_EREGEXP = "^\\d{6}$"; /** * 4 Bit SMS verification code */ String FOURNUMBER_EREGEXP = "^\\d{4}$"; /** * Verification number */ String NUMBER_EREGEXP = "^\\d{1,}$"; /** * Age */ String AGE_EREGEXP = "^[0-9]{1,2}$"; /** * Password (6-12 letters or numbers) regular expression */ String PASSWORD_OR_EREGEXP = "^[0-9A-Za-z]{6,12}$"; /** * Password (6-12 letters and numbers) regular expression */ String PASSWORD_AND_EREGEXP = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,12}$"; /** * Chinese name regular expression */ String CHINESE_NAME_EREGEXP = "^[\u4e00-\u9fa5]+(\\·[\u4e00-\u9fa5]+)*$"; /** * Amount regular expression Positive integer, cannot be decimal or negative */ String MONEY_EREGEXP = "^([1-9]\\d*)*$"; /** * Only numbers can be entered 0 or one **/ String ZERO_OR_ONE_EREGEXP = "^[0-1]{1}$"; /** * positive integer */ String POSITIVE_NUMBER = "^[0-9]*[1-9][0-9]*$"; /** * Date mode */ String SIMPLE_DATE_PATTERN = "^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$"; /** * Mm / DD / yyyy date mode none- */ String SIMPLE_DATE_PATTERN_SIMPLE = "^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$"; /** * Date format validation */ String DATE_FORMATE_TEMPLATE1_EREGEXP = "^[1-2][0-9][0-9][0-9]-([1][0-2]|0?[1-9])-([12][0-9]|3[01]|0?[1-9]) ([01][0-9]|[2][0-3]):[0-5][0-9]$"; /** * Zip code format verification */ String POSTCODE_EREGEXP = "^[0-9]{6}$"; }
In the subsequent practical application, see how to use it.
Unified exception response
- Introducing spring boot starter web dependency into the pom of mingx common
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.mingx</groupId> <artifactId>mingx-demo</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>com.mingx.common</groupId> <artifactId>mingx-common</artifactId> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
2. Create a com.mingx.common, handler package under src/mian/java, and create SysExceptionHandler.java under this package
The ControllerAdvice annotation is used to realize global Exception handling. First, the Exception handling for input parameter verification will throw an Exception of MethodArgumentNotValidException. First, it will be caught and return a unified parameter error response. Next, catch all exceptions. The exceptions here can be refined. Now, for simulation, catch exceptions uniformly and return a unified [system busy, please try again later] response.
package com.mingx.common.hander; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import com.mingx.common.AppResult; import com.mingx.common.AppResultBuilder; import com.mingx.common.ResultCode; @ControllerAdvice @Component public class SysExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(SysExceptionHandler.class); /** * Input parameter verification * @param exception * @return */ @ResponseBody @ExceptionHandler(MethodArgumentNotValidException.class) public AppResult<String> handle(MethodArgumentNotValidException exception) { String message = exception.getBindingResult().getAllErrors().get(0).getDefaultMessage(); return AppResultBuilder.error(ResultCode.PARAM_ERROR,message); } /** * Global exception capture processing * @param ex * @return */ @ResponseBody @ExceptionHandler(value = Exception.class) public AppResult<String> errorHandler(Exception ex) { logger.error(ex.getMessage(),ex); return AppResultBuilder.error(ResultCode.SYSTEM_ERROR); } }
Comprehensive practice
After preparing for the implementation of the above three basic functions, now simulate and realize a function of saving user information. The steps are as follows:
- Introduce mingx common and Hibernate validator dependencies into the project pom
<dependency> <groupId>com.mingx.common</groupId> <artifactId>mingx-common</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> </dependency>
2. In the mingx user pojo project, create the com.mingx.user.bo package, which is specially used to put the pojo class of verification input parameters and create the SaveUserBO.java class. It is recommended that the name of the BO class be: corresponding method name + BO, and the specific code is as follows:
package com.mingx.user.bo; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; import org.hibernate.validator.constraints.Length; import com.mingx.common.RegexpContants; import lombok.Data; @Data public class SaveUserBO { @NotBlank(message = "User name cannot be empty") @Length(max = 10,message = "The length cannot exceed 10 characters") private String name; @NotBlank(message = "Gender cannot be empty") @Pattern(regexp = RegexpContants.ZERO_OR_ONE_EREGEXP,message = "Incorrect gender format") private String sex; @NotBlank(message = "Birth date cannot be blank") @Pattern(regexp = RegexpContants.SIMPLE_DATE_PATTERN_SIMPLE,message = "Birth date format is incorrect") private String birthday; }
@NotBank annotation is a non empty annotation, indicating that this field cannot be empty
@The Length annotation sets its field Length
@The Pattern annotation can be used for custom regular expression verification, and the relevant regular expressions can be extracted separately. The regexpcontainers.java interface created earlier can be used to define common regular expressions
For more comments on verification, please refer to the reference document officially given by hibernate Validator. Here is the simplest use.
3. Add the interface for saving user information in SysController.java of mingx user project:
Note: the interface input parameter needs to be annotated with @ Validated before parameter verification can be performed on the input parameter
@PostMapping("/saveUser") public AppResult<String> saveUser(@Validated @RequestBody SaveUserBO bo){ Integer count = sysUserService.count(new QueryWrapper<SysUser>().eq("name", bo.getName())); if(count > 0) { return AppResultBuilder.error(ResultCode.USER_HAS_EXISTED); } SysUser user = new SysUser(); user.setName(bo.getName()).setSex(Integer.valueOf(bo.getSex())) .setBirthday(LocalDate.parse(bo.getBirthday(),DateTimeFormatter.ofPattern("yyyy-MM-dd"))) .setCreateTime(LocalDateTime.now()); sysUserService.save(user); return AppResultBuilder.success(user.getId()); }
4. Start nacos, start mingx user, open postman, send post request and access http://localhost:7001/user/saveUser,
Add parameters in json format to the body, as follows:
If it is saved successfully, it will be displayed as follows:
If a field is empty or the format is incorrect, it will be displayed as follows:
Due to the addition of repeated logical judgment, if you save it again, you will return:
Conclusion
This chapter does not cover the knowledge points related to SpringClould, but as long as it is a qualified back-end interface, it must have the three most basic functions. It is simple to practice in the project and optimize and refine, which is helpful to improve the technical level. It can not be directly involved in business development and ignore the implementation process of these basic functions.