【springboot注解有哪些 SpringBoot2 参数管理实践,入参出参与校验】但是在日常开发中,碍于很多客观因素,很少有时间去不断思考和优化代码,所以只能从实际情况的角度去思考如何构建系统代码,保证以后自己还能读懂自己的代码,在自己的几年编程中,实际会考虑如下几个方面:代码层级一、参数管理在编程系统中,为了能写出良好的代码,会根据是各种设计模式、原则、约束等去规范代码,从而提高代码的可读性、复用性、可修改,实际上个人觉得,如果写出的代码很好,即别人修改也无法破坏原作者的思路和封装,这应该是非常高水准 。
但是在日常开发中,碍于很多客观因素,很少有时间去不断思考和优化代码,所以只能从实际情况的角度去思考如何构建系统代码,保证以后自己还能读懂自己的代码,在自己的几年编程中,实际会考虑如下几个方面:代码层级管理,命名和注释统一,合理的设计业务数据库,明确参数风格 。
这里就来聊一下参数管理,围绕:入参、校验、返参三个方面内容 。
如何理解代码规范这个概念:即大多数开发认同,愿意遵守的约束,例如Spring框架和Mvc模式对于工程的管理,《Java开发手册》中对于业务开发的规定,其根本目的都是想避免随着业务发展,代码演变到无法维护的境界 。
二、接收参数接收参数方式有很多种,List,Map,Object等等,但是为了明确参数的语义,通常都需要设计参数对象的结构并且遵守一定的规范,例如明确禁止Map接收参数:
Rest风格接收单个ID参数:
@GetMapping("/param/single/{id}")public String paramSingle (@PathVariable Integer id){return "Resp:"+id ;}接收多个指定的参数:
@GetMapping("/param/multi")public String paramMulti (@RequestParam("key") String key, @RequestParam("var") String var){return "Resp:"+key+var ;}基于Java包装对象入参:
@PostMapping("/param/wrap")public ParamIn paramWrap (@RequestBody ParamIn paramIn){return paramIn ;}-- 参数对象实体public class ParamIn {private Integer id ;private String key ;private String var ;private String name ;}以上是在开发中常用的几种接参方式,这里通常会遵守下面几个习惯:
- 参数语义:明确接收参数的作用;
- 个数限制:参数超过三个使用包装对象;
- 避免多个接口使用单个包装对象入参;
- 避免包装对象主体过于复杂;
在业务层封装复杂的BO对象来降低业务管理的复杂度,这是合理常见的操作,可以在web接口层面根据接口功能各自管理入参主体,在业务实现的过程中,再传入BO对象中 。
避免复杂的业务包装对象在各个层乱飘,如果多个接口入参都是同一个复杂的对象,很容易让开发人员迷茫 。
三、响应参数与参数接收相对应的就是参数响应,参数响应通常具有明确的约束规范:响应主体数据,响应码,描述信息 。通常来说就是这样三个核心要素 。
响应参数主体:
这里泛型的使用通常用来做主体数据的接收 。
public class Resp<T> {private int code ;private String msg ;private T data ;public static <T> Resp<T> ok (T data) {Resp<T> result = new Resp<>(HttpStatus.OK);result.setData(data);return result ;}public Resp (HttpStatus httpStatus) {this.code = httpStatus.value();this.msg = httpStatus.getReasonPhrase();}public Resp(int code, String msg, T data) {this.code = code;this.msg = msg;this.data = https://tazarkount.com/read/data;}}Code状态码即接口状态,建议参照并遵守
HttpStatus中状态码的描述,这是开发普遍遵守的规范,如果不满足业务需求,在适当自定义部分编码,可以完全自定义一套响应码,但是没太多必要 。Msg描述
描述接口的响应的Msg可能就是:成功或失败,更多的时候是需要处理业务异常的提示信息,例如单号不存在,账号冻结等等,通常需要从业务异常中捕获提示信息,并响应页面,或者入参校验不通过的描述 。
Data数据
接口响应的主体数据,不同的业务响应的对象肯定不同,所以这里基于泛型机制接收即可,再以JSON格式响应页面 。
参考案例
接口返参:
@PostMapping("/resp/wrap")public Resp<KeyValue> respWrap (@RequestBody KeyValue keyValue){return Resp.ok(keyValue) ;}响应格式:{"code": 200,"msg": "OK","data": {"key": "hello","value": "world"}}四、参数校验参数接收和响应相对都不是复杂的,比较难处理的就是参数校验:入参约束校验,业务合法性校验,响应参数非空非null校验,等各种场景 。在系统运行过程中,任何参数都不是绝对可靠的,所以参数校验随处可见,不同场景下的参数校验,都有其必要性,但其根本目的都是为了给到请求端提示信息,快速打断流程,快速响应 。
1、借鉴参考很多封装思想,设计模式,或者这里说的参数校验,都可以参考现有Java源码或者优秀的框架,这是一个应该具备的基础意识 。
Java原生方法之
java.lang.Thread线程:public void interrupt() {if (this != Thread.currentThread())checkAccess();synchronized (blockerLock) {Interruptible b = blocker;if (b != null) {interrupt0();b.interrupt(this);return;}}interrupt0();}在Java源码中,大部分都是采用原生的if判断方式,对参数执行校验Spring框架之
org.springframework.util.ClassUtils工具类部分代码:public static Class<?> forName(String name, @Nullable ClassLoader classLoader)throws ClassNotFoundException, LinkageError {Assert.notNull(name, "Name must not be null");Class<?> clazz = resolvePrimitiveClassName(name);if (clazz == null) {clazz = commonClassCache.get(name);}if (clazz != null) {return clazz;}}在Spring框架中除了基础的if判断之外,还封装一个org.springframework.util.Assert断言工具类 。2、常用校验方式If判断
@GetMapping("/check/base")public String baseCheck (@RequestParam("var") String var){if (var == null) {return var+" is null" ;}if ("".equals(var)){return var+" is empty" ;}if ("hello".equals(var)){return var+" sensitive word " ;}return var + " through " ;}这种判断在代码中很常见,只是一旦遇到校验的主体对象很大,并且在分布式的环境中,需要重复写if判断的话,容易出错是一个方面,对开发人员的耐心考验是另一个方面 。Valid组件
在早几年的时候,比较流行的常用校验组件
Hibernate-Validator,后来兴起的Validation-Api,据说是参考前者实现,不过这并不重要,二者都简化了对JavaBean的校验机制 。基于注解的方式,标记Java对象的字段属性,并设定如果校验失败的提示信息 。
public class JavaValid {@NotNull(message="ID不能为空")private Integer id ;@Email(message="邮箱格式异常")private String email ;@NotEmpty(message = "字段不能为空")@Size(min = 2,max = 10,message = "字段长度不合理")private String data ;}校验结果打印:public class JavaValidTest {private static Validator validator ;@BeforeClasspublic static void beforeBuild (){validator = Validation.buildDefaultValidatorFactory().getValidator();}@Testpublic void checkValid (){JavaValid valid = new JavaValid(null,"email","data") ;Set<ConstraintViolation<JavaValid>> validateInfo = validator.validate(valid) ;// 打印校验结果validateInfo.stream().forEach(validObj -> {System.out.println("validateInfo:"+validObj.getMessage());});}}接口使用:@PostMapping("/java/valid")public JavaValid javaValid (@RequestBody @Valid JavaValid javaValid,BindingResult errorMsg){if (errorMsg.hasErrors()){List<ObjectError> objectErrors = errorMsg.getAllErrors() ;objectErrors.stream().forEach(objectError -> {logger.info("CheckRes:{}",objectError.getDefaultMessage());});}return javaValid ;}这种校验机制基于注解方式,可以大幅度简化普通的入参校验,但是对业务参数的合法校验并不适应,例如常见的ID不存在,状态拦截等 。Assert断言
关于Assert断言方式,起初是在单元测试中常见,后来在各种优秀的框架中开始常见,例如Spring、Mybatis等,然后就开始出现在业务代码中:
public class AssertTest {private String varObject ;@Beforepublic void before (){varObject = RandomUtil.randomString(6) ;}@Testpublic void testEquals (){Assert.assertEquals(varObject+"不匹配",varObject,RandomUtil.randomString(6));}@Testpublic void testEmpty (){Assert.assertTrue(StrUtil.isNotEmpty(varObject));Assert.assertFalse(varObject+" not empty",StrUtil.isNotEmpty(varObject));}@Testpublic void testArray (){/*数组元素不相等: arrays first differed at element [1];Expected :u08Actual:mwm*/String var = RandomUtil.randomString(5) ;String[] arrOne = new String[]{var,RandomUtil.randomString(3)} ;String[] arrTwo = new String[]{var,RandomUtil.randomString(3)} ;Assert.assertArrayEquals("数组元素不相等",arrOne,arrTwo);}}Assert断言,可以替换传统的if判断,大量减少参数校验的代码行数,提高程序的可读性,这种风格是目前比较流行的方式 。五、源代码地址
GitHub·地址https://github.com/cicadasmile/middle-ware-parentGitEE·地址https://gitee.com/cicadasmile/middle-ware-parent
文章插图
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
