一、业务需求

与第三方平台对接,第三方调用接口实现数据上报。由于接口传参较多,要对每一个参数做校验,如果写工具类对每个参数校验会很麻烦,因为,使用springboot自带的校验功能实现对参数的统一校验,大大减少代码量,通过注解的方式,使代码更加简洁。

二、具体实现

首先说明下传参的格式,因为传参的格式不同也会影响注解的使用。由于文档格式是之前的同事定好,所以不好随意更改,只能按照他这种格式写。

{"info": [{"param": "320106","param1":"11111","param2": "测试部门","param3": "测试单位","param4": "测试1213","param5": "17311111111"}]
}
  1. 参数封装类编写
    这是一个List集合,对于这种格式的参数校验,我采取的办法是使用@valid注解。需要注意的是,@Valid注解是可以加在属性上的,而@Validate注解是不能加载属性的。加在属性上,可以实现嵌套验证。
  • 定义传参结构和实体类
@Data
public class MsgSyncList<E>{// 属性添加Valid注解,支持该属性进行嵌套验证@ValidList<E> info;
}
  • 定义参数实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SyncDeptParam {@NotBlank(message = "区域编码不能为空")private String  regionCode;@NotBlank(message = "部门id不能为空")private String deptId;@NotBlank(message = "部门名称不能为空")private String groupName;private String superGroup;@NotBlank(message = "部门联系人不能为空")private String contactName;@NotBlank(message = "部门联系人手机号不能为空")@Length(min = 11, max = 11, message = "部门联系人手机号只能为11位")@Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "部门联系人手机号格式有误")private String contactPhone;}
  1. 封装返回信息
@Getter
public enum SyncMsgCode {/*** 成功*/SUCCESS(100, "成功"),/*** 失败*/FAILED(102, "失败"),/*** 推送的JSON格式有误*/ERR_JSON(103, "推送的JSON格式有误"),/*** 数据验证错误*/ERR_VALIDATE(104, "数据验证错误"),/*** 其他错误*/ERR_OTHER(105, "其他错误"),/*** 所属部门不存在*/DEPT_NOT_FOUND(106, "所属部门不存在"),/*** 区域编码不存在*/ERR_REGIONCODE(111, "区域编码不存在"),/*** 用户名或者密码不对*/ERR_USERNAME_PWD(112, "用户名或者密码不对");private int code;private String msg;SyncMsgCode(int code, String msg) {this.code = code;this.msg = msg;}
}
  1. 统一异常处理及参数加密处理

@RestControllerAdvice
@Slf4j
public class SyncRequestControllerAdvice implements RequestBodyAdvice {@Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {return methodParameter.getMethod().isAnnotationPresent(SecurityParam.class);}@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {if (parameter.getMethod().isAnnotationPresent(SecurityParam.class)) {SecurityParam secretAnnotation = parameter.getMethod().getAnnotation(SecurityParam.class);if (secretAnnotation.inDecode()) {return new HttpInputMessage() {@Overridepublic InputStream getBody() throws IOException {String bodyStr = IOUtils.toString(inputMessage.getBody(), "utf-8");MsgSyncList<Object> list = null;if(!JsonHelper.isJson(bodyStr)) {bodyStr = bodyStr.substring(1, bodyStr.lastIndexOf("\""));try {bodyStr = SM4Util.decodeSms4HexToString(bodyStr);list = JSONObject.parseObject(bodyStr, MsgSyncList.class);} catch (Exception e) {e.printStackTrace();}return IOUtils.toInputStream(JSONObject.toJSONString(list), "utf-8");}list = JSONObject.parseObject(bodyStr, MsgSyncList.class);return IOUtils.toInputStream(JSONObject.toJSONString(list), "utf-8");}@Overridepublic HttpHeaders getHeaders() {return inputMessage.getHeaders();}};}}return inputMessage;}@Overridepublic Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {return body;}@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {return body;}/*** 方法参数错误异常** @param e* @return*/@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public SyncReturnMsg methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {log.error("方法参数错误异常");Set<String> list = new HashSet<>();        // 从异常对象中拿到ObjectError对象List<ObjectError> objectErrorList = e.getBindingResult().getAllErrors();if (!objectErrorList.isEmpty()) {for (ObjectError error : objectErrorList) {list.add(error.getDefaultMessage());}}// 然后提取错误提示信息进行返回return new SyncReturnMsg(SyncMsgCode.ERR_VALIDATE, list);}/*** 集合校验异常处理** @param exception* @return*/@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(ConstraintViolationException.class)@ResponseBodypublic SyncReturnMsg handlerConstraintViolationException(ConstraintViolationException exception) {log.error("方法参数错误异常:{}", exception);Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations();List<String> list = new ArrayList<>();for (ConstraintViolation<?> constraintViolation : constraintViolations) {String index = constraintViolation.getPropertyPath() != null ?constraintViolation.getPropertyPath().toString() : "";list.add(index.substring((index.substring(0, index.indexOf(".")).length() + 1))+ ":" + constraintViolation.getMessage());}return new SyncReturnMsg(SyncMsgCode.ERR_VALIDATE, list);}
}

5.控制器添加注解实现参数校验

@Api(tags = "下级平台数据同步到省级平台")
@RestController
@RequestMapping("/api")
@Slf4j
public class GwcMsgSyncController {@Autowiredprivate SyncService syncService;@ApiOperation("部门基本信息同步")@SecurityParam@RequestMapping(value = "/editDept")public SyncReturnMsg editGroup(@RequestBody @Validated MsgSyncList<SyncDeptParam> deptSyncParamList) {log.info("部门信息同步入参:{}", JSONObject.toJSONString(deptSyncParamList));try {return syncService.editDept(deptSyncParamList);} catch (Exception e) {log.error("部门基本信息同步异常:{}", e);return new SyncReturnMsg(SyncMsgCode.FAILED, "部门信息同步失败");}}}
  1. 由于对接需要对参数进行加密,所以使用了自定义注解,对加了注解的请求进行参数解密。
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Mapping
@Documented
public @interface SecurityParam {/*** 入参是否解密,默认解密*/boolean inDecode() default true;/*** 出参是否加密,默认加密*/boolean outEncode() default true;
}

SpringBoot 实现统一参数校验相关推荐

  1. 校验json格式_不来学一下SpringBoot统一参数校验?

    微服务架构之春招总结:SpringCloud.Docker.Dubbo与SpringBoot 一个SpringBoot问题就干趴下了?我却凭着这份PDF文档吊打面试官. 金三银四第一天,啃透这些Spr ...

  2. SpringBoot 如何进行参数校验,老鸟们都这么玩的!

    大家好,我是飘渺. 前几天写了一篇 SpringBoot如何统一后端返回格式?老鸟们都是这样玩的! 阅读效果还不错,而且被很多号主都转载过,今天我们继续第二篇,来聊聊在SprinBoot中如何集成参数 ...

  3. boot spring 对参数检测_【springboot】@Valid参数校验

    转自: https://blog.csdn.net/cp026la/article/details/86495659 扯淡: 刚开始写代码的时候对参数的校验要么不做.要么写很多类似 if( xx == ...

  4. Springboot优雅的参数校验(一)

    目录 前言 1. 依赖引入 2. 参数形式 3. 常用到的约束注解 4. 参数基础校验 4.1 @RequestBody参数 4.2 @RequestParam参数/@PathVariable参数 4 ...

  5. Springboot中请求参数校验

    1.添加依赖 <!-- 参数校验 --> <dependency><groupId>org.springframework.boot</groupId> ...

  6. springboot 优雅的参数校验_SpringBoot 2.x 开发案例之优雅的校验参数

    前言 参数如何校验?撸主很久很久之前的项目都是在前端页面一个个 if else 的,后来就用了一系列的前端校验框架,比如 layui iview 等等,几个样式属性就可以轻松搞定,的确是美滋滋. 后端 ...

  7. 企业实战之Spring拦截器《统一参数校验》

    在前面的一些文章中我们有讲到,通过拦截器我们可以做很多的事情,包括接口统一的 参数校验. 登录校验.权限校验等,也可以做一些HTTP响应体写入逻辑,比如我们另一篇文章所说的<解决跨域问题> ...

  8. 中value大小_如何在Spring/SpringBoot 中做参数校验?你需要了解的都在这里!

    数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据. 本文结合自己在项目 ...

  9. Springboot 参数校验@Valid @Validated(最新最全)

    Springboot 参数校验@Valid @Validated(最新最全) 提示:统一参数校验,异常处理 文章目录 Springboot 参数校验@Valid @Validated(最新最全) 前言 ...

最新文章

  1. python程序的原理_Python程序的执行原理(转)
  2. 一种新的计算机视觉技术?将手机的摄像头变成了一个搜索引擎
  3. group by具有去重的功能
  4. 致:测试工程师们!超2000种连接件,下载96页完整选型目录!
  5. hdu 3038(种类并查集)
  6. Java web学习(一)Servlet简介
  7. Linux线程时间片如何修改,请教如何修改线程时间片
  8. 易维帮助台:论工业产品售后服务升级转型的正确打开姿势
  9. spring学习(33):id和name
  10. VS2017打开低版本的VS MVC架构的项目的时候需要修改的地方
  11. leetcode-345-Reverse Vowels of a String
  12. 【优化预测】基于matlab灰狼算法优化BP神经网络预测【含Matlab源码 1729期】
  13. STC15F2K60S2单片机利用24C02记录单片机上电次数
  14. “飞思卡尔”杯全国大学生智能车竞赛
  15. Intro.js 简介和用法
  16. 数据学习(十四)-方差分析与试验设计
  17. 西部数据硬盘第一次启动很慢
  18. 利用“bert模型”预测英语“完形填空”答案
  19. C/C++ —— 什么是定义?什么是声明?
  20. Mac显示/隐藏文件夹

热门文章

  1. java获取ajax传的数组对象,ajax传递对象数组
  2. 发现一本自学单片机很好的书,推荐一下 王云51单片机C语言教程
  3. 用超级计算机打游戏是什么样的体验,用超级计算机来玩游戏 GTX Titan显卡评测...
  4. Netbeans 高分屏 设置
  5. 目标检测网络之 YOLOv3
  6. C++学习资料和视频
  7. 框架 --mybatis(ORM映射)-数据库技术
  8. 辨别虚假高音质(320k/Ape/Flac)的音乐文件
  9. 多模态机器学习入门——文献阅读(一)Multimodal Machine Learning: A Survey and Taxonomy
  10. 新冠病毒核酸检测点建模分析