当前位置:网站首页>Elegant writing controller (parameter verification + unified exception handling)
Elegant writing controller (parameter verification + unified exception handling)
2022-06-29 18:19:00 【Li Nai - leemon】
Elegant writing Controller( Parameter validation + Unified exception handling )
List of articles
Recently, many interfaces have been developed , Because there is no reference case , So at the beginning, it was developed according to my understanding . After more development, I found that I wrote the same code for each result :try() {} catch() {}, And about parameter null determination :StringUtils.empty(xxx). With a warm and lustful attitude , After the development, I naturally want to develop more gracefully next time . therefore , Used springboot Parameter validation and unified exception handling .
One , Preliminary data and class preparation
1.1 Unified status code
For different return types , We should have different corresponding status codes . The return type of the interface must exist in the unified status code .
package com.lmc.common.enums;
/** * @author lmc * @Description: TODO Interface API Return status code enumeration * @Create 2022-06-26 13:16 * @version: 1.0 */
public enum ResultCodeEnum {
SUCCESS(1000, " The request is successful "),
FAILURE(1001, " request was aborted "),
VALIDATE_PARAMS_ERROR(1002, " Parameter verification failed ");
private int code;
private String msg;
ResultCodeEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
/** * obtain code * @return */
public int getCode() {
return code;
}
/** * pick up information * @return */
public String getMsg() {
return msg;
}
}
1.2 Uniform return format
After the unified status code is completed , You also need to define a uniform return format , For the convenience of the front end
package com.lmc.common.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.lmc.common.enums.ResultCodeEnum;
import lombok.Data;
import java.util.Date;
/** * @author lmc * @Description: TODO Interface returns the result type * @Create 2022-06-26 13:13 * @version: 1.0 */
@Data
public class ResultVo {
/** * Status code */
private int code;
/** * Status code information */
private String msg;
/** * Return description information ( Prepare to provide detailed failure reasons in case of call failure ) */
private String desc;
/** * Return the data */
private Object data;
/** * Interface call end time */
@JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
private Date searchTime;
public ResultVo(int code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
this.searchTime = new Date();
}
/** * Return when the call is successful * @param data * @return */
public static ResultVo success(Object data) {
return new ResultVo(ResultCodeEnum.SUCCESS.getCode(), ResultCodeEnum.SUCCESS.getMsg(), data);
}
/** * Return... When the call fails * @param data * @return */
public static ResultVo fail(Object data) {
return new ResultVo(ResultCodeEnum.FAILURE.getCode(), ResultCodeEnum.FAILURE.getMsg(), data);
}
/** * Specify the status code when calling * @param enums * @param data * @return */
public static ResultVo result(ResultCodeEnum enums, Object data) {
return new ResultVo(enums.getCode(), enums.getMsg(), data);
}
public ResultVo withDesc(String desc) {
this.desc = desc;
return this;
}
}
1.3 Custom interface API Exception class
Then customize the exception class of the interface , Of course, you don't have to , Depending on personal preference
package pers.lmc.tools2.provider.exception;
import com.lmc.common.enums.ResultCodeEnum;
/** * @author lmc * @Description: TODO API Exception class * @Create 2022-06-26 18:48 * @version: 1.0 */
public class ApiException extends RuntimeException{
private int code;
private String msg;
public ApiException(String msg) {
super(msg);
this.code = ResultCodeEnum.FAILURE.getCode();
this.msg = ResultCodeEnum.FAILURE.getMsg();
}
public ApiException(ResultCodeEnum enums, String msg) {
super(msg);
this.code = enums.getCode();
this.msg = enums.getMsg();
}
}
1.4 Parameter encapsulation class
To debug parameter validation , You also need to customize the encapsulation class of a parameter
package pers.lmc.tools2.provider.vo;
import lombok.Data;
/** * @author lmc * @Description: TODO * @Create 2022-06-26 13:43 * @version: 1.0 */
@Data
public class Param01Vo {
private String name;
private Integer age;
private Short sex;
}
Two , Parameter validation
Parameter validation requires springboot Of validation rely on
2.1 pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- About verification -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
2.2 Modify the parameter encapsulation class
package pers.lmc.tools2.provider.vo;
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/** * @author lmc * @Description: TODO * @Create 2022-06-26 13:43 * @version: 1.0 */
@Data
public class Param01Vo {
@NotNull(message = " Name cannot be empty ")
@Size(min = 1, max = 50, message = " name name The length must be 1-50 Characters ")
private String name;
@NotNull(message = " Age age Can't be empty ")
@Min(value = 10, message = " Age age Not lower than 10 year ")
@Max(value = 25, message = " Age age No more than 25 year ")
private Integer age;
@Min(value = 0, message = " Gender sex Can only be 0 and 1,0= Woman 1= male ")
@Max(value = 1, message = " Gender sex Can only be 0 and 1,0= Woman 1= male ")
private Short sex;
}
Here, the three parameters of the encapsulation class are restricted
2.3 controller
stay controller When validating parameters in , You need to use annotations on classes @Validated, At the same time, the parameter of the interface is also annotated @Valid
package pers.lmc.tools2.provider.controller;
import com.lmc.common.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
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.RestController;
import pers.lmc.tools2.provider.vo.Param01Vo;
import javax.validation.Valid;
/** * @author lmc * @Description: TODO * @Create 2022-06-26 17:10 * @version: 1.0 */
@RestController
@Validated
@RequestMapping("/valicate")
@Slf4j
public class ValicateController {
@PostMapping("/add")
public ResultVo addParam01(@Valid @RequestBody Param01Vo param01Vo) {
log.info(" perform add() Method , Parameters :" + param01Vo.toString());
return ResultVo.success(param01Vo);
}
}
2.4 test
Development complete , Prepare to test , To APIPost Visit http://localhost:9003/provider/valicate/add, Bring parameters :
{
"name":"lmc",
"age": 22,
"sex": 1
}
Successful visit , The results are as follows :
{
"code": 1000,
"msg": " The request is successful ",
"desc": null,
"data": {
"name": "lmc",
"age": 22,
"sex": 1
},
"searchTime": "2022-06-26 19:59:55"
}
If the parameter input is incorrect , for example :
{
"name":"",
"age": 220,
"sex": 2
}
The results are as follows :
{
"timestamp": "2022-06-26T12:02:21.748+00:00",
"status": 400,
"error": "Bad Request",
"message": "",
"path": "/provider/valicate/add"
}
The log is like this :
2022-06-26 20:02:21 [http-nio-9003-exec-1] WARN o.s.w.s.m.support.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.lmc.common.vo.ResultVo pers.lmc.tools2.provider.controller.ValicateController.addParam01(pers.lmc.tools2.provider.vo.Param01Vo) with 3 errors: [Field error in object 'param01Vo' on field 'sex': rejected value [2]; codes [Max.param01Vo.sex,Max.sex,Max.java.lang.Short,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [param01Vo.sex,sex]; arguments []; default message [sex],1]; default message [ Gender sex Can only be 0 and 1,0= Woman 1= male ]] [Field error in object 'param01Vo' on field 'age': rejected value [220]; codes [Max.param01Vo.age,Max.age,Max.java.lang.Integer,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [param01Vo.age,age]; arguments []; default message [age],25]; default message [ Age age No more than 25 year ]] [Field error in object 'param01Vo' on field 'name': rejected value []; codes [Size.param01Vo.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [param01Vo.name,name]; arguments []; default message [name],50,1]; default message [ name name The length must be 1-50 Characters ]] ]
Throw out MethodArgumentNotValidException abnormal .
Although it is intercepted when the parameter is wrong , But the format is not consistent with what we want to return . This is the time , You need to use unified exception handling .
3、 ... and , Unified exception handling
3.1 Method parameter validation exception handling
Through the above questions , We can set controller Unified exception handling , When a parameter validation error occurs , Just capture MethodArgumentNotValidException abnormal , Then we do it ourselves .
package pers.lmc.tools2.provider.aop;
import com.lmc.common.enums.ResultCodeEnum;
import com.lmc.common.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import pers.lmc.tools2.provider.exception.ApiException;
import java.util.List;
import java.util.stream.Collectors;
/** * @author lmc * @Description: TODO * @Create 2022-06-26 18:31 * @version: 1.0 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/** * Handle all exceptions that fail verification (MethodArgumentNotValidException abnormal ) * @param e * @return */
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public ResultVo handleBindGetException(MethodArgumentNotValidException e) {
// Get all exception parameters
List<String> errors = e.getBindingResult()
.getFieldErrors()
.stream()
.map(x -> x.getDefaultMessage())
.collect(Collectors.toList());
return ResultVo.result(ResultCodeEnum.VALIDATE_PARAMS_ERROR, null).withDesc(" Parameter verification failed :" + errors);
}
/** * Handle customization APIException abnormal * @param e * @return */
@ExceptionHandler(value = ApiException.class)
public ResultVo handleApiException(ApiException e) {
return ResultVo.fail(null).withDesc(e.getMessage());
}
/** * Handling other exceptions * @param e * @return */
@ExceptionHandler(value = Exception.class)
public ResultVo handleException(Exception e) {
log.info(" Implementation to unified processing method ...");
return ResultVo.fail(null).withDesc(e.getMessage());
}
}
Through the above configuration , When transmitting with illegal parameters again , The following errors will be reported :
{
"code": 1002,
"msg": " Parameter verification failed ",
"desc": " Parameter verification failed :[ Gender sex Can only be 0 and 1,0= Woman 1= male , name name The length must be 1-50 Characters , Age age No more than 25 year ]",
"data": null,
"searchTime": "2022-06-26 20:08:22"
}
At this time, the format is already the return format we want .
3.2 Other exception handling
We just tried to handle the parameter validation exception of the method , There may also be errors in the program , You do not need to use after configuring unified exception handling try{} catch() {}, Because we have already configured... In the global exception handling class :
/** * Handling other exceptions * @param e * @return */
@ExceptionHandler(value = Exception.class)
public ResultVo handleException(Exception e) {
log.info(" Implementation to unified processing method ...");
return ResultVo.fail(null).withDesc(e.getMessage());
}
At this time, other exceptions are thrown in the program , Will execute the code here , Also return the format we want . Examples are as follows
modify controller Interface :
@PostMapping("/add")
public ResultVo addParam01(@Valid @RequestBody Param01Vo param01Vo) {
log.info(" perform add() Method , Parameters :" + param01Vo.toString());
int k = 1/0; // An exception will be thrown when the interface is called
return ResultVo.success(param01Vo);
}
Call the interface and return the result :
{
"code": 1001,
"msg": " request was aborted ",
"desc": "/ by zero",
"data": null,
"searchTime": "2022-06-26 20:13:51"
}
边栏推荐
- 图像特征计算与表示——基于内容的图像检索
- 记录服务器被入侵病毒:ssh密码被更改登录失败、恶意程序跑满了cpu、jar包启动失败自动kill、一直弹出You have new mail in /var/spool/mail/root
- JWT登录验证
- Sd6.23 summary of intensive training
- 金鱼哥RHCA回忆录:DO447构建高级作业工作流--使用事实缓存提高性能
- 【TcaplusDB知识库】TcaplusDB系统用户组介绍
- VMware installation esxi
- Shell基本语法--流程控制
- 工作流模块Jar包启动报错:liquibase – Waiting for changelog lock….
- Adobe Premiere基础-声音调整(音量矫正,降噪,电话音,音高换挡器,参数均衡器)(十八)
猜你喜欢

小迈科技 X Hologres:高可用的百亿级广告实时数仓建设

Serial port experiment based on stm32f103zet6 library function

Wechat applet development reserve knowledge

js两个二维数组合并并去除相同项(整理)

【目标跟踪】|stark配置 win otb

Adobe Premiere Basics - common video effects (corner positioning, mosaic, blur, sharpen, handwriting tools, effect control hierarchy) (16)

Adobe Premiere基础-编辑素材文件常规操作(脱机文件,替换素材,素材标签和编组,素材启用,便捷调节不透明度,项目打包)(十七)

Adobe Premiere基础-批量素材导入序列-变速和倒放(回忆)-连续动作镜头切换-字幕要求(十三)

Request header field xxxx is not allowed by Access-Control-Allow-Headers in preflight response问题

Yolov6+tensorrt+onnx: deployment based on win10+tensorrt8+yolov6+onnx
随机推荐
Travel card "star picking" hot search first! Stimulate the search volume of tourism products to rise
Adobe Premiere Basics - general operations for editing material files (offline files, replacing materials, material labels and grouping, material enabling, convenient adjustment of opacity, project pa
Detailed analysis on the use of MySQL stored procedure loop
3H proficient in opencv (V) - perspective transformation
idea怎么使用?
牛客小Bai月赛52 D 环上食虫(尺取+st表)
Jar包后台启动并输出日志
工作流模块Jar包启动报错:liquibase – Waiting for changelog lock….
[tcapulusdb knowledge base] tcapulusdb operation and maintenance doc introduction
Maxcompute string replacement function -replace
等保测评结论为差,是不是表示等保工作白做了?
Jar package background startup and log output
When easycvr deploys a server cluster, what is the reason why one is online and the other is offline?
字典树(随学)
【目标跟踪】|stark配置 win otb
MySql存储过程循环的使用分析详解
[网鼎杯 2020 青龙组]AreUSerialz
PWM output experiment based on stm32f103zet6 library function
Adobe Premiere基础-常用的视频特效(边角定位,马赛克,模糊,锐化,手写工具,效果控件层级顺序)(十六)
Programmer Resource Recommendation Guide