内容简介:听说的最多的是不是“不要重复的造轮子”?不要被这句话蒙骗了,这句话应该还没说完整,在什么情况下不要造轮子?实际项目中由于工期和质量原因,肯定不希望你造轮子,你造轮子花费时间且质量不如现有的轮子。
听说的最多的是不是“不要重复的造轮子”?不要被这句话蒙骗了,这句话应该还没说完整,在什么情况下不要造轮子?
实际项目中由于工期和质量原因,肯定不希望你造轮子,你造轮子花费时间且质量不如现有的轮子。
但是!不造轮子怎么去装X!不造轮子怎么去了解其中原理!不造轮子怎么成长!
那在造参数校验器轮子的过程中我学到了什么呢?
- 注解的定义与使用
- 反射的应用
- Spring AOP的使用
- 异常的抛出与处理
造之前的规划
雄心勃勃的规划,开干!我一定比hibernate validator做的好!
我要支持:
- 属性验证
- 方法参数验证
- 方法验证
- 方法内主动验证
注解
你初见注解时,是不是有种疑惑?为什么在某个类或方法属性上添加一个注解,它就能拥有某种功能呢?
那么我将为你慢慢解开这个迷惑。
注解就相当于一个标签,它本身并没有任何功能性,只是打个标签说明一下这是什么。那它怎么实现的某些功能呢?这就要说说反射了,只有注解和反射双剑合璧,才能发挥它的功效。我们先说注解,后说反射。
如何定义一个注解
格式
自定义注解的格式为:
public @interface 注解名{注解体}
- @interface用来声明一个注解,并自动继承java.lang.annotation.Annotation接口。
- 注解体中的类似方法定义的,我们称为注解中的元素。
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface NotNull{ String value() default ""; }
注解元素
格式: 权限修饰符 数据类型 元素名() default 默认值
权限修饰符:只能public和default(默认)
返回值类型:8种基本数据类型和String,Class,enum,Annotaion及他们的数组
默认值限制:编译器对元素的默认值有些挑剔,元素的值不能为null并且不能有不确定的默认值(即要么有默认值,要么使用时提供值),所以一般我们在定义注解时便加上默认值。
元注解
定义注解一定要使用到 Java 给我们提供的四种元注解,用于注解其他注解的。
@Target @Retention @Documented @Inherited
我们重点关注@Target和@Retention.
@Target
说明定义的注解所作用的范围(可以用于修饰什么)。
取值(ElementType)有:
值 | 意义 |
---|---|
CONSTRUCTOR | 构造器声明 |
FIELD | 属性声明(包括enum实例) |
LOCAL_VARIABLE | 局部变量声明 |
METHOD | 方法声明 |
PACKAGE | 包声明 |
PARAMETER | 参数声明 |
TYPE | 用于描述类、接口(包括注解类型) 或enum声明 |
@Retention
表示需要在什么级别保存该注释信息,用于描述注解的生命周期(被描述的注解在什么范围内有效)
取值(RetentionPoicy)有:
值 | 意义 |
---|---|
SOURCE | 在源文件中有效(即源文件保留) |
CLASS | 在class文件中有效(即class保留) |
RUNTIME | 在运行时有效(即运行时保留) |
自定义的注解
参数校验定义的常用注解:
注解 | 意义 |
---|---|
NotNull | 参数不能为空 |
On | 数值的范围 |
OnMax | 最大值不能超过 |
OnMin | 最小值不能低于 |
邮箱格式 |
反射
反射中牵涉的类有Class,Method,Parameter,Annotation,Field
类 | 获取方式 |
---|---|
Class | Class.forName(""); clazz.getClass(); Type.class; |
Method | clazz.getMethods(); |
Parameter | method.getParameters(); constructor.getParameters(); |
Annotation | clazz.getAnnotations(); method.getAnnotations(); field.getAnnotations() |
Field | clazz.getFields(); |
用好反射的关键在于了解反射的API,之后我会单独一篇讲下我们常用的反射API。
Spring AOP的使用
我将借助Spring AOP来实现找到这些注解的功能。我这里只讲讲浅显一点的,因为很多人对于Spring AOP的使用还不了解。这个轮子是基于Spring Boot构建,所以我只讲声明式编程,就是注解实现的。
使用比较简单,只需三步走:
- 定义切面类
- 指定切入点
- 定义通知类型
@Component //声明这是一个组件 @Aspect //声明这是一个切面 public class ServiceAspect { //定义切入点,没有方法体 @Pointcut("@annotation(定义的注解)") public void pointcut(){ } /* * 前置通知,使用pointcut()上注册的切入点 * * @param joinPoint 接受JoinPoint切入点对象,可以没有该参数 */ @Before("pointcut()") public void before(JoinPoint joinPoint){ } //后置通知 @After("pointcut()") public void after(JoinPoint joinPoint){ } //环绕通知 @Around("pointcut()") public void around(JoinPoint joinPoint){ MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); //反射就此打开序幕 } //后置返回通知 @AfterReturning("pointcut()") public void afterReturn(JoinPoint joinPoint){ } //抛出异常后通知 @AfterThrowing(pointcut="pointcut()", throwing="ex") public void afterThrow(JoinPoint joinPoint, Exception ex){ } }
AOP底层原理是使用动态代理,动态代理有JDK动态代理和cglib动态代理,这里暂不细说了。
异常
自定义异常类
public class FastValidatorException extends RuntimeException { public FastValidatorException(String message) { super(message); } }
设计时有两种失败模式:快速失败和安全失败
当参数校验,不符合要求时,快速失败将直接抛出此异常,安全失败将收集所有失败返回。
如:
private void emptyResult(String fieldName) { if (isFailFast) { throw new FastValidatorException(fieldName + "不能为空"); } else { formatResult(fieldName + "不能为空"); } } private void formatResult(String msg) { if (!msg.isEmpty()) { result.getErrors().add(msg); } }
处理异常
如果使用快速失败模式,那么使用者将要对异常做全局统一处理。
将参数异常类信息,封装成比较友好的信息给前端。
@RestControllerAdvice public class ErrorHandler { @ExceptionHandler(FastValidatorException.class) public JSONResult handle(FastValidatorException ex) { return new JSONResult(ex.getMessage(), ex.getStatus()); } }
造之后的感想
还是hibernate validator做的好!(捂脸哭) 我服!
but
造轮子能迫使我去了解更多的知识点,能迫使我去了解轮子的原理,也能加深我对知识的理解,顺便还能吹吹!
做的过程中你会思考如何优化它,一遍遍的推倒重来,会想到用怎么来解耦?用什么提高扩展性,灵活性?
造轮子的意义在于能让你不断的思考和学习。无论造的好坏,行动就好。
轮子地址: https://github.com/flyhero/fa... 忘不吝指教!
发现这个面试视频不错,分享给大家,公众号回复: 面试视频
更多精彩技术文章尽在微信公众号:码上实战
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python网络编程(第3版)
[美] Brandon Rhodes、[美] John Goerzen / 诸豪文 / 人民邮电出版社 / 2016-9 / 79.00元
本书针对想要深入理解使用Python来解决网络相关问题或是构建网络应用程序的技术人员,结合实例讲解了网络协议、网络数据及错误、电子邮件、服务器架构和HTTP及Web应用程序等经典话题。具体内容包括:全面介绍Python3中最新提供的SSL支持,异步I/O循环的编写,用Flask框架在Python代码中配置URL,跨站脚本以及跨站请求伪造攻击网站的原理及保护方法,等等。一起来看看 《Python网络编程(第3版)》 这本书的介绍吧!