浅谈java反射和自定义注解的综合应用实例

前言

前几天学习了反射和自定义注解,刚好工作中遇到一个小问题:前台传递到后台的必填字段为空,导致不能插入数据库。就是这样一个小问题,让我考虑到是否可以做一个通用的方法,让前台传递过来的必填字段在后台也校验一遍,如果传递为空,则把响应字段返回提示。因此,我考虑的是用注解的方式,在必填字段上面定义,利用反射得到必填字段的字段名,判断是否为空,并返回响应的信息。

需求模拟

假设客户有:姓名,年龄,地址,手机号码,身份证号等信息,而我们是做金融业务,所以关键是看客户的三要素:姓名,身份证号,手机号码。我们要保证前台传递过来的这三个值不为空。
废话不多说,直接上代码。只看红框里面的即可。

目录结构

客户信息类:Customer

这个是个实体类,我们在:姓名,身份证号码,手机号码上都用了我们的自定义注解。

package com.dao.chu.po; 

/**
 *
* <p>Title: Customer</p>
* <p>Description:客户信息实体 </p>
 */
public class Customer { 

  private int id;
  @IsRequired
  private String name; // 姓名
  @IsRequired
  private String idnum; // 身份证号码
  @IsRequired
  private String phone; // 手机号
  private String sex; // 性别
  private int age; // 年龄
  private String address; // 地址 

  @Override
  public String toString() {
    return "Customer [id=" + id + ", name=" + name + ", idnum=" + idnum
        + ", phone=" + phone + ", sex=" + sex + ", age=" + age
        + ", address=" + address + "]";
  } 

  public int getId() {
    return id;
  } 

  public void setId(int id) {
    this.id = id;
  } 

  public String getName() {
    return name;
  } 

  public void setName(String name) {
    this.name = name;
  } 

  public String getIdnum() {
    return idnum;
  } 

  public void setIdnum(String idnum) {
    this.idnum = idnum;
  } 

  public String getPhone() {
    return phone;
  } 

  public void setPhone(String phone) {
    this.phone = phone;
  } 

  public String getSex() {
    return sex;
  } 

  public void setSex(String sex) {
    this.sex = sex;
  } 

  public int getAge() {
    return age;
  } 

  public void setAge(int age) {
    this.age = age;
  } 

  public String getAddress() {
    return address;
  } 

  public void setAddress(String address) {
    this.address = address;
  } 

}

自定义注解类:IsRequired

package com.dao.chu.po;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; 

/**
 *
* <p>Title: IsRequired</p>
* <p>Description: 字段是否必填 </p>
 */
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.FIELD})
public @interface IsRequired
{
  /**
   *  

  * <p>Title: isRequired</p>
  * <p>Description:true:必填 false:非必填 </p>
  * @return
   */
  boolean isRequired() default true;
}

关键工具类:PoUtils

我们在这个类里面主要用了反射的知识,得到带有自定义注解的字段,并取得这个对象的值进行判断

package com.dao.chu.po;  

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; 

import javax.jws.WebResult; 

import com.sun.xml.internal.ws.util.StringUtils; 

/**
 *
* <p>Title: PoUtils</p>
* <p>Description:Po操作工具类 </p>
 */
@SuppressWarnings("unused")
public class PoUtils
{  

  /**
  * <p>Title: getProperties</p>
  * <p>Description: 获取javabean属性通用方法 </p>
  * @param t
  * @param beanName
  * @return
  * @throws IllegalAccessException
  * @throws IllegalArgumentException
  * @throws InvocationTargetException
  * @throws IntrospectionException
   */
  private static <T> Object getProperties(T t, String beanName)
    throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException
  {
    Object nameValue = new PropertyDescriptor(beanName, t.getClass()).getReadMethod().invoke(t);
    return nameValue;
  }  

  /**
  * <p>Title: IsFieldBlank</p>
  * <p>Description:判断前台传过来的必填字段是否为空 ,不正确则将相应字段返回 </p>
  * @param t
  * @return
  * @throws IllegalAccessException
  * @throws IllegalArgumentException
  * @throws InvocationTargetException
  * @throws IntrospectionException
   */
  public static <T> RespBody IsFieldBlank(T t)
    throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException
  {
    RespBody respBody = new RespBody();
    StringBuffer sb = new StringBuffer();  

    Field[] declaredFields = t.getClass().getDeclaredFields();
    for (Field field : declaredFields)
    {
      field.setAccessible(true);
      String name = field.getName();
      boolean fieldHasAnno = field.isAnnotationPresent(IsRequired.class);
      if (fieldHasAnno)
      {
        IsRequired annotation = field.getAnnotation(IsRequired.class);
        boolean required = annotation.isRequired();
        if (required)
        {
          Object value = getProperties(t, name);
          if (null == value)
          {
            sb.append(name + ",");
          }
        }
      }
    }  

    if (null==sb.toString()||"".equals(sb.toString()))
    {
      respBody.isSuccess();
    }  

    respBody.setSuccess(false);
    respBody.setMsg(sb.toString().substring(0,sb.toString().lastIndexOf(",")) + " is required");
    return respBody;
  }
}

RespBody:响应实体类

封装了响应的成功失败以及一些信息

 package com.dao.chu.po; 

/**
 *
* <p>Title: RespBody</p>
* <p>Description: 响应实体类</p>
 */
public class RespBody
{
  private boolean isSuccess = true;  

  private String msg;  

  private Object data;  

  public boolean isSuccess()
  {
    return isSuccess;
  }  

  public void setSuccess(boolean isSuccess)
  {
    this.isSuccess = isSuccess;
  }  

  public String getMsg()
  {
    return msg;
  }  

  public void setMsg(String msg)
  {
    this.msg = msg;
  }  

  public Object getData()
  {
    return data;
  }  

  public void setData(Object data)
  {
    this.data = data;
  }  

  public RespBody(boolean isSuccess, String msg, Object data)
  {
    super();
    this.isSuccess = isSuccess;
    this.msg = msg;
    this.data = data;
  }  

  public RespBody(boolean isSuccess, String msg)
  {
    super();
    this.isSuccess = isSuccess;
    this.msg = msg;
  }  

  public RespBody()
  {
  }  

  @Override
  public String toString()
  {
    return "ReturnBody [isSuccess=" + isSuccess + ", msg=" + msg + ", data=" + data + "]";
  }
}

测试类:IsRequiredTest

 package com.dao.chu.po; 

/**
 *
* <p>Title: IsRequiredTest</p>
* <p>Description: 必填成员变量测试类</p>
 */
public class IsRequiredTest { 

  public static void main(String[] args) { 

    Customer customer = new Customer(); 

    try {
      //=========第一次不赋值==========
      RespBody respBody = PoUtils.IsFieldBlank(customer);
      //不通过则返回提示信息
      if (!respBody.isSuccess()) {
        System.out.println("1."+respBody.getMsg());
      } 

      //=========第二次给姓名赋值==========
      customer.setName("张三");
      respBody = PoUtils.IsFieldBlank(customer);
      //不通过则返回提示信息
      if (!respBody.isSuccess()) {
        System.out.println("2."+respBody.getMsg());
      } 

    } catch (Exception e) {
      e.printStackTrace();
    }
  } 

}

输出结果

第一次三个值都为空,提示三个都是必填的,第二次因为姓名赋值了,所以提示另外两个是必填的,本次实验宣告结束,本人知识有限,若有更好的方法欢迎指正

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2017-08-29

深入理解Java注解的使用方法

注解是jdk1.5新增的特性.大家都知道,jdk1.5在java的发展史上有着划时代的意义.而注解的出现,在某种程度上颠覆了框架的设计.比如,spring在注解出现后,改善了原先五大组件的模式,增加了基于注解的实现方式.现在重点讲讲注解的使用. 元注解: jdk1.5定义了4个元注解,元注解的作用是注解其他的注解. 1.@Retention 2.@Target 3.@Documented 4.@Inherited @Retention用于指明该注解存在的时机.参数有三个值可选:Retention

深入理解 Java注解及实例

 Java注解 什么是注解? Java中的注解就是Java源代码的元数据,也就是说注解是用来描述Java源代码的. 基本语法就是:@后面跟注解的名称. ①Override:标识某一个方法是否正确覆盖了它的父类的方法. ②Deprecated:表示已经不建议使用这个类成员了. 它是一个标记注解. ③SuppressWarnings:用来抑制警告信息 等等. 要更好的理解注解,我们可以自己写一个注解 @Target : 用来限制注解可以用到那几个地方.比方可以用到类上,可以用到方法胜都可以用@Tar

spring mvc常用注解_动力节点Java学院整理

Spring从2.5版本开始在编程中引入注解,用户可以使用@RequestMapping, @RequestParam, @ModelAttribute等等这样类似的注解.到目前为止,Spring的版本虽然发生了很大的变化,但注解的特性却是一直延续下来,并不断扩展,让广大的开发人员的双手变的更轻松起来,这都离不开Annotation的强大作用,今天我们就一起来看看Spring MVC 4中常用的那些注解吧. 1. @Controller Controller控制器是通过服务接口定义的提供访问应用

浅谈Java注解和动态代理

本文主要介绍Java中与注解和动态代理有关的部分知识,接下来我们看看具体内容. Annotation(注解) 其实就是代码里的特殊标记, 它用于替代配置文件,也就是说,传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行. 1. 三个基本的Annotation: Override:限定重写父类方法, 该注解只能用于方法 Deprecated:用于表示某个程序元素(类, 方法等)已过时 SuppressWarnings:抑制编译器警告. 2.自定义Annotati

java 自定义注解的实例详解

java  自定义注解的实例详解 Java的Annotation是在5.0版本之后引入的,可以用于创建文档,跟踪代码中的依赖性,并且可以执行编译时期检查.注解就是给虚拟机看的,代表程序的一些特殊的功能.JDK中提供了@Override,@SuppressWarning,@Deprecated三种注解,当让还有元注解,@Target,@Retention,@Documented,@Inherited,元注解的作用负责注解其它注解. 要想了解注解,就要了解自定义注解,了解是通过反射来实现的. 首先,

Java 自定义注解及利用反射读取注解的实例

一.自定义注解 元注解: @interface注解: 定义注解接口 @Target注解: 用于约束被描述的注解的使用范围,当被描述的注解超出使用范围则编译失败.如:ElementType.METHOD,ElementType.TYPE: @Retention 注解:用于约束被定义注解的作用范围,作用范围有三个: 1.RetentionPolicy.SOURCE:作用范围是源码,作用于Java文件中,当执行javac时去除该注解. 2.RetentionPolicy.CLASS:作用范围是二进制码

java注解的全面分析

全面解析java注解 Java中的常见注解 a.JDK中的注解 @Override 覆盖父类或者父接口的方法     @Deprecated 表示方法已经过时     @SuppressWarnings("deprecation") 忽略方法过时警告 b.常见的第三方注解 例如Spring中的@Autowired(自动注入) 注解的分类 a.按照运行机制分 1.源码注解         注解只在源码中存在,编译成class文件就不存在了 2.编译时注解         注解在源码和cl

java 注解的基础详细介绍

java 注解的基础详细介绍 前言 注解是Java引入的一项非常受欢迎的补充,它提供了一种结构化的,并且具有类型检查能力的新途径,从而使得程序员能够为代码加入元数据,而不会导致代码杂乱且难以阅读.使用注解能够帮助我们避免编写累赘的部署描述文件,以及其他生成的文件. 注解的语法比较简单,除了@符号的使用之外,它基本与java固有的语法一致.但由于java源码中提供的内置注解很少,所以大部分同学对注解都不是很了解,虽然我们都接触过,比如java内置的几种注解: @Override,表示当前的方法定义

Java自定义注解的详解

Java自定义注解 Java注解提供了关于代码的一些信息,但并不直接作用于它所注解的代码内容.在这个教程当中,我们将学习Java的注解,如何定制注解,注解的使用以及如何通过反射解析注解. Java1.5引入了注解,当前许多java框架中大量使用注解,如hibernate.Jersey.spring.注解作为程序的元数据嵌入到程序当中.注解可以被一些解析工具或者是编译工具进行解析.我们也可以声明注解在编译过程或执行时产生作用. 在使用注解之前,程序源数据只是通过java注释和javadoc,但是注

java中注解机制及其原理的详解

java中注解机制及其原理的详解 什么是注解 注解也叫元数据,例如我们常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包.类.接口.字段.方法参数.局部变量等进行注解.它主要的作用有以下四方面: 生成文档,通过代码里标识的元数据生成javadoc文档. 编译检查,通过代码里标识的元数据让编译器在编译期间进行检查验证. 编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码. 运行时动态处理,运行时通过代码里标识

java中Executor,ExecutorService,ThreadPoolExecutor详解

java中Executor,ExecutorService,ThreadPoolExecutor详解 1.Excutor 源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /** * Executes the given command at some time in the future. The command * may execute in a new thread, in a pooled thre

java 中maven pom.xml文件教程详解

maven pom.xml文件教程详解,具体内容如下所示: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x

Java中内存异常StackOverflowError与OutOfMemoryError详解

 Java中内存异常StackOverflowError与OutOfMemoryError详解 使用Java开发,经常回遇到内存异常的情况,而StackOverflowError和OutOfMemoryError便是最常遇见的错误. 首先,看看这两种错误的解释: 如果当前线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常. 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常. 这里把异常分为两种情况,但是存在一些相互重

java 中HttpClient传输xml字符串实例详解

java 中HttpClient传输xml字符串实例详解 介绍:我现在有一个对象page,需要将page对象转换为xml格式并以binary方式传输到服务端 其中涉及到的技术点有: 1.对象转xml流 2.输出流转输入流 3.httpClient发送二进制流数据 POM文件依赖配置 <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifact

java 中JDBC连接数据库代码和步骤详解及实例代码

java 中JDBC连接数据库代码和步骤详解 JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤:  1.加载JDBC驱动程序:  在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),这通过java.lang.Class类的静态方法forName(String  className)实现. 例如: try{ //加载MySql的驱动类 Class.forName("com.mysql.jdbc.Driver") ; }catch(Class

java 中模式匹配算法-KMP算法实例详解

java 中模式匹配算法-KMP算法实例详解 朴素模式匹配算法的最大问题就是太低效了.于是三位前辈发表了一种KMP算法,其中三个字母分别是这三个人名的首字母大写. 简单的说,KMP算法的对于主串的当前位置不回溯.也就是说,如果主串某次比较时,当前下标为i,i之前的字符和子串对应的字符匹配,那么不要再像朴素算法那样将主串的下标回溯,比如主串为"abcababcabcabcabcabc",子串为"abcabx".第一次匹配的时候,主串1,2,3,4,5字符都和子串相应的

java中的static{}块的实例详解

java中的static{}块的实例详解 一直以来对static块不是很熟系,今天特意写了两个程序来搞清楚一下: 第一个小程序: package com.babyDuncan.Sohu; public class testStatic { static { int x = 5; } static int x, y; public static void main(String[] args) { x--; myMethod(); System.out.println(x + y + ++x);

基于Java中进制的转换函数详解

十进制转成十六进制: Integer.toHexString(int i) 十进制转成八进制 Integer.toOctalString(int i) 十进制转成二进制 Integer.toBinaryString(int i) 十六进制转成十进制 Integer.valueOf("FFFF",16).toString() 八进制转成十进制 Integer.valueOf("876",8).toString() 二进制转十进制 Integer.valueOf(&qu

Java中Properties类的操作实例详解

Java中Properties类的操作实例详解 知识学而不用,就等于没用,到真正用到的时候还得重新再学.最近在看几款开源模拟器的源码,里面涉及到了很多关于Properties类的引用,由于Java已经好久没用了,而这些模拟器大多用Java来写,外加一些脚本语言Python,Perl之类的,不得已,又得重新拾起.本文通过看<Java编程思想>和一些网友的博客总结而来,只为简单介绍Properties类的相关操作.  一.Java Properties类 Java中有个比较重要的类Properti