首先先学习一下注解,注解为我们在代码中添加信息提供了一种形式化的方法,使得我们在稍后的某个时刻可以方便地使用这些数据。
在日常的编码中我们一直都在使用注解,只是没有特别关注过,Java中内置了三种注解:@Override,@SuppressWarnings @Deprecated。相信只要学习过Java的同学一定是见过这些主角的 。
如果我们要写一个自定义的注解应该怎么呢?
首先需要定义一个注解标注出是自定义的注解
/** * * @author zhangwei_david * @version $Id: CustomerRule.java, v 0.1 2015年5月29日 下午10:12:16 zhangwei_david Exp $ */ @Documented @Target(ElementType.ANNOTATION_TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface CustomerValidator { }这个注解中没有任何内容,属于标记注解
自定义 日期类型校验器的注解
/** * * @author zhangwei_david * @version $Id: Date.java, v 0.1 2015年5月29日 下午10:00:20 zhangwei_david Exp $ */ @Documented @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @CustomerValidator public @interface DateString { String pattern() default "yyyy-MM-dd HH:mm:ss"; String errorCode() default "must date"; String message() default "must be date pattern"; }
, @Target是用来定义该注解将可以应用在什么地方,FIELD表示该注解应用在一个属性上,@Rectetion 用来定义该注解在哪一个级别可以使用 RUNTIME表示运行时。
String pattern() default "yyyy-MM-dd HH:mm:ss" 表示如果不指定pattern这个值的时候将返回默认值“yyyy-MM-dd HH:mm:ss” 。
有了自己的注解,那么就需要一个注解的处理器,定义一个处理器接
/** *自定义注解处理器接口 * * @author zhangwei_david * @version $Id: CustomerValidatorRule.java, v 0.1 2015年5月30日 上午8:51:52 zhangwei_david Exp $ */ public interface CustomerValidatorRule { /** * 判断是否支持该注解 * * @param annotation * @param property * @return */ public boolean support(Annotation annotation); /** * 校验处理 * * * @param annotation * @param field * @param errors */ public void valid(Annotation annotation, Object object, Field field, Errors errors) throws Exception; }
/** * * @author zhangwei_david * @version $Id: AbastractCustomerValidatorRule.java, v 0.1 2015年5月30日 上午11:22:19 zhangwei_david Exp $ */ public abstract class AbastractCustomerValidatorRule implements CustomerValidatorRule { /** * @see com.cathy.core.service.annotation.rule.CustomerValidatorRule#support(java.lang.annotation.Annotation) */ public abstract boolean support(Annotation annotation); /** * @param <T> * @see com.cathy.core.service.annotation.rule.CustomerValidatorRule#valid(java.lang.annotation.Annotation, java.lang.reflect.Field, org.springframework.validation.Errors) */ public void valid(Annotation annotation, Object target, final Field field, final Errors errors) throws Exception { preHandle(annotation, target, field, errors); PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor(target.getClass(), field.getName()); Method reader = propertyDescriptor.getReadMethod(); Object property = reader.invoke(target); validProperty(annotation, property, new PostHandler() { public void postHanle(String errorCode, String message) { errors.rejectValue(field.getName(), errorCode, message); } }); } public static interface PostHandler { public void postHanle(String errorCode, String message); } /** * */ private void preHandle(Annotation annotation, Object target, Field field, Errors errors) { Assert.notNull(target); Assert.notNull(annotation); Assert.notNull(errors); Assert.notNull(field); } public abstract void validProperty(Annotation annotation, Object property, PostHandler postHandler); }
/** * * @author zhangwei_david * @version $Id: DateValidatorRule.java, v 0.1 2015年5月30日 上午11:17:09 zhangwei_david Exp $ */ @CustomerRule public class DateValidatorRule extends AbastractCustomerValidatorRule { /** * @see com.cathy.core.service.annotation.rule.CustomerValidatorRule#support(java.lang.annotation.Annotation, java.lang.Object) */ @Override public boolean support(Annotation annotation) { return annotation instanceof DateString; } /** * @see com.cathy.core.service.annotation.rule.AbastractCustomerValidatorRule#validProperty(java.lang.annotation.Annotation, java.lang.Object) */ @Override public void validProperty(Annotation annotation, Object property, PostHandler postHandler) { DateString ds = (DateString) annotation; if (parse(ds.pattern(), (String) property) == null) { postHandler.postHanle(ds.errorCode(), ds.message()); } } private Date parse(String pattern, String property) { try { SimpleDateFormat sdf = new SimpleDateFormat(pattern); return sdf.parse(property); } catch (ParseException e) { //do noting } return null; } }
这样我们就有了一个注解处理器,为了方便扩展,该处使用注解的方式加载定义的注解处理器,这就需要定义一个标注是自定义的注解处理器的注解。
/** * * @author zhangwei_david * @version $Id: CustomerValidatorRule.java, v 0.1 2015年5月30日 下午12:51:20 zhangwei_david Exp $ */ @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Component public @interface CustomerRule { }
/** * * @author zhangwei_david * @version $Id: CustomerValidatorProcesser.java, v 0.1 2015年5月30日 下午12:38:33 zhangwei_david Exp $ */ public class CustomerValidatorConfig implements ApplicationContextAware { private Map<Annotation, CustomerValidatorRule> rules = new ConcurrentHashMap<Annotation, CustomerValidatorRule>(); Map<String, Object> customerValidationRules = null; /** * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) */ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { customerValidationRules = applicationContext .getBeansWithAnnotation(CustomerRule.class); System.out.println(customerValidationRules); } private CustomerValidatorRule findFormMap(Annotation annotation) { for (Entry<String, Object> entry : customerValidationRules.entrySet()) { if (entry.getValue() != null && ((CustomerValidatorRule) entry.getValue()).support(annotation)) { return (CustomerValidatorRule) entry.getValue(); } } return null; } public CustomerValidatorRule findRule(Annotation annotation) { CustomerValidatorRule customerValidatorRule = null; if (!rules.containsKey(annotation)) { CustomerValidatorRule cvr = findFormMap(annotation); if (cvr != null) { rules.put(annotation, cvr); } customerValidatorRule = cvr; } customerValidatorRule = rules.get(annotation); return customerValidatorRule; } }通过实现ApplicationContextAware接口,从上下文中自动加载处理器。
/** * * @author zhangwei_david * @version $Id: CustomerValidatorFactory.java, v 0.1 2015年5月30日 下午1:03:56 zhangwei_david Exp $ */ @Component public class CustomerValidatorFactory implements Validator { @Autowired private CustomerValidatorConfig customerValidatorConfig; /** * @see org.springframework.validation.Validator#supports(java.lang.Class) */ public boolean supports(Class<?> clazz) { return true; } /** * @see org.springframework.validation.Validator#validate(java.lang.Object, org.springframework.validation.Errors) */ public void validate(Object target, Errors errors) { Assert.notNull(target); Assert.notNull(errors); List<Field> fileds = getFields(target.getClass()); for (Field field : fileds) { Annotation[] annotations = field.getAnnotations(); for (Annotation annotation : annotations) { if (annotation.annotationType().getAnnotation(CustomerValidator.class) != null) { try { CustomerValidatorRule customerValidatorRule = customerValidatorConfig .findRule(annotation); if (customerValidatorRule != null) { customerValidatorRule.valid(annotation, target, field, errors); } } catch (Exception e) { e.printStackTrace(); } } } } } /** * 获取class的fields。 * * @param clazz bean所在的class * @return */ private List<Field> getFields(Class<? extends Object> clazz) { // 声明Field数组 List<Field> fields = new ArrayList<Field>(); // 如果class类型不为空 while (clazz != null) { // 添加属性到属性数组 Collections.addAll(fields, clazz.getDeclaredFields()); clazz = clazz.getSuperclass(); } return fields; } }
相关推荐
如何使用注解驱动的校验 使用校验功能时,处理方法要如何签名?? 校验错误信息存放在什么地方?? 页面如何显示错误信息 如何对错误信息进行国际化(1) 如何对错误信息进行国际化(2) 目录 数据模型访问结构 ...
采用 AOP + 自定义注解 + Redis 实现限制IP接口访问次数 采用 Nacos 作为服务发现和配置中心,轻松完成项目的配置的维护 采用 Sentinel 流量控制框架,通过配置再也不怕网站被爆破 支持Markdown 编辑器 采用 Elastic...
6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7...
6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.1.1. @Configurable object的单元测试 6.8.1.2. 多application context情况下的处理 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来...
12.2 在Spring中使用Hibernate 12.2.1 配置SessionFactory 12.2.2 使用HibernateTemplate 12.2.3 处理LOB类型数据 12.2.4 添加Hibernate事件监听器 12.2.5 使用原生Hibernate API 12.2.6 使用注解配置 12.2.7 事务...
6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7...
工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis...
6.2 在你的Servlet和过滤器中使用Spring 214 6.2.1 问题 214 6.2.2 解决方案 215 6.2.3 工作原理 215 6.3 将Spring与Struts 1.x集成 220 6.3.1 问题 220 6.3.2 解决方案 220 6.3.3 工作原理 220 6.4...
如何使用注解驱动的校验 使用校验功能时,处理方法要如何签名?? 校验错误信息存放在什么地方?? 页面如何显示错误信息 如何对错误信息进行国际化(1) 如何对错误信息进行国际化(2) 目录 数据模型访问结构 访问数据...
6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ Load-time weaving(LTW) 6.9. ...
12.2 在Spring中使用Hibernate 12.2.1 配置SessionFactory 12.2.2 使用HibernateTemplate 12.2.3 处理LOB类型数据 12.2.4 添加Hibernate事件监听器 12.2.5 使用原生Hibernate API 12.2.6 使用注解配置 12.2.7 事务...
6.2 在你的Servlet和过滤器中使用Spring 214 6.2.1 问题 214 6.2.2 解决方案 215 6.2.3 工作原理 215 6.3 将Spring与Struts 1.x集成 220 6.3.1 问题 220 6.3.2 解决方案 220 6.3.3 工作原理 220 6.4...
6.8.4. 在Spring应用中使用AspectJ Load-time weaving(LTW) 6.9. 其它资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点实施 7.2.3. AspectJ切入点表达式 7.2.4. ...
三、使用jQuery扩展插件Validate实现前端校验 3.1、jQuery扩展插件validate—1基本使用方法 3.2、jQuery扩展插件validate—2通过参数设置验证规则 3.3、jQuery扩展插件validate—3通过参数设置错误信息 3.4、jQuery...
自定义注解+拦截器实现基于RBAC接口权限校验(配套文档:https://blog.csdn.net/wujiangbo520/article/details/122057616) 全局异常处理 接口统一结果返回 一键生成数据库设计文档 大批量数据插入数据库测试 根据...
工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis...
工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis...
+ springBoot + springCloud + 日志组件logback-spring + 多配置 + 多数据源...+ 传参注解式校验 + session练习 + 公用日志设计封装 + db乐观锁设计 + 优雅启停 + 配置文件信息加密 + AES加解密 + spring 事件监听设计
工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis...
工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis...