【动态页面】(三)之二:通过自定义注解读取Jar包的类名和属性名

上篇博客介绍了通过反射读取Jar包的类名和属性名,但是问题是读不出类名和属性名的中文注释和属性类型。所以上篇博客埋下了一个伏笔,就是通过自定义注解的方式读取Jar包的类名、属性名、中文注释和属性类型。这篇博客我们就来好好讲讲是如何实现的。

首先先说一下,由于我们的Jar包没有放到项目下,所以就想着怎么能把Jar包添加进来,所以先做了一个类似于上传文件的功能,将Jar上传进来,然后再读取Jar包里面的类名、属性名等一系列属性,再添加到数据库中。总体的思路确定了,下面就开始实施。

首先是上传Jar包。这个我以前写过springMVC的文件上传的博客,具体可以参考我之前写的博客。

/**
	 * Jar包上传
	 * @param request
	 * @param response
	 * @return
	 * @throws IllegalStateException
	 * @throws IOException
	 */
	@RequestMapping("/upload2")
	public String upload2(HttpServletRequest request,HttpServletResponse response) throws IllegalStateException, IOException{
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
		//判断request里面是否是Multipart类型的数据
		if(multipartResolver.isMultipart(request)){
			//把request强制转换成MultipartHttpServletRequest类型的
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;

			//用迭代器去判断里面有多少文件,遍历文件的一个方法
			Iterator<String> iter = multiRequest.getFileNames();
			while (iter.hasNext()) {
				//迭代器的作用就是一个一个拿文件,把文件拿到
				MultipartFile file = multiRequest.getFile((String)iter.next());
				if(file != null){
					//拿到文件之后输出文件
					//首先定义文件名称
					String fileName = file.getOriginalFilename();
					//定义输出路径
					String path = "G:/" + fileName;
					String fromFilePath = "G:\\" + fileName;
					//初始化文件
					File localFile = new File(path);
					//用stringMVC给咱们提供的方法给它写到本地去
					file.transferTo(localFile);	

					try {
						getJarName(fromFilePath, request, response);
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		return "/UploadJarBag";
	

下面就是为自定义注解做准备了,自定义一个注解解析器

package com.tgb.itoo.uisystem.entity;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 定义一个注解解析器
 * @author 高迎
 * @date 2015年3月11日10:10:49
 *
 */
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})//定义注解的作用目标**作用范围字段、枚举的常量/方法
@Documented//说明该注解将被包含在javadoc中
public @interface FieldMeta {

	 /**
     * 是否为序列号
     * @return
     */
    boolean id() default false;
    /**
     * 字段名称
     * @return
     */
    String name() default "";  

    /**
     * 字段长度,默认值为255
     * @return
     */
    int length() default 255; 

    /**
     * 是否可编辑
     * @return
     */
    boolean editable() default true;
    /**
     * 是否在列表中显示
     * @return
     */
    boolean summary() default true;
    /**
     * 字段描述
     * @return
     */
    String description() default "";
}

定义一个获得注解的帮助类

package com.tgb.itoo.uisystem.controller;

import java.lang.reflect.Field;

import com.tgb.itoo.uisystem.entity.FieldMeta;

/**
 * 获得到注解的帮助类
 * @author 高迎
 * @date 2015年3月11日10:12:15
 *
 */
public class SortableField {

	public SortableField(){}  

    public SortableField(FieldMeta meta, Field field) {
        super();
        this.meta = meta;
        this.field = field;
        this.name=field.getName();
        this.type=field.getType();
    }  

    public SortableField(FieldMeta meta, Field field, int length) {
        super();
        this.meta = meta;
        this.field = field;
        this.name=field.getName();
        this.type=field.getType();
        this.length=length;
    } 

    public SortableField(FieldMeta meta, String name, int length, Class<?> type) {
        super();
        this.meta = meta;
        this.name = name;
        this.length = length;
        this.type = type;
    }  

    private FieldMeta meta;
    private Field field;
    private String name;
    private int length;
	public int getLength() {
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	private Class<?> type;  

    public FieldMeta getMeta() {
        return meta;
    }
    public void setMeta(FieldMeta meta) {
        this.meta = meta;
    }
    public Field getField() {
        return field;
    }
    public void setField(Field field) {
        this.field = field;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }      

    public Class<?> getType() {
        return type;
    }
    public void setType(Class<?> type) {
        this.type = type;
    }
}

通过自定义注解读取Jar包的属性

/**
	 * 读取jar包的类名和属性名
	 * @param jarFile
	 * @throws Exception
	 */
	public void getJarName(String jarFile, HttpServletRequest request, HttpServletResponse response) throws Exception {
		//定义一个注解帮助类类型的list
		List<SortableField> list = new ArrayList<SortableField>();
		try{
			//通过将给定路径名字符串转换为抽象路径名来创建一个新File实例
			File f = new File(jarFile);
			URL realURL = f.toURI().toURL();
			URLClassLoader myClassLoader = new URLClassLoader(new URL[]{realURL},Thread.currentThread().getContextClassLoader());

			//通过jarFile和JarEntry得到所有的类
			JarFile jar = new JarFile(jarFile);
			//返回zip文件条目的枚举
			Enumeration<JarEntry> enumFiles = jar.entries();
			JarEntry entry;

			//测试此枚举是否包含更多的元素
			while(enumFiles.hasMoreElements()){
				entry = (JarEntry)enumFiles.nextElement();
				if(entry.getName().indexOf("META-INF")<0){   //在字符串entry中查找"META-INF"首次出现的位置
					String classFullName = entry.getName();
					if(classFullName.indexOf(".class")<0){  //在字符串classFullName中查找".class"首次出现的位置
						classFullName = classFullName.substring(0,classFullName.length()-1);
					} else{
						//去掉后缀.class
						String className = classFullName.substring(0,classFullName.length()-6).replace("/", ".");
						String strClassName=className.substring(className.lastIndexOf(".")+1, className.length());
						System.out.println("最后截取的类名:" + strClassName);
						Class<?> myclass = myClassLoader.loadClass(className);																

						//根据class对象获得属性
						Field[] fields = myclass.getDeclaredFields();  //这里面获得了四个字段
						Entities entitiesList = new Entities();

						//获得类上的注解
						FieldMeta meta111 = myclass.getAnnotation(FieldMeta.class);
						System.out.println("类名的中文注释:" + meta111.name());
						entitiesList.setEntityDesc(meta111.name());  //类名的中文描述(中文注释)

						for(Field f1 : fields){
							//获取字段中包含fieldMeta的注解
			                FieldMeta meta = f1.getAnnotation(FieldMeta.class);
			                System.out.println("打印长度:" +  meta.length());
			                System.out.println("打印 类型:" +  f1.getType().getName());
			                String getPropertyType = f1.getType().getName().toString();
			                String strPropertyType = getPropertyType.substring(getPropertyType.lastIndexOf(".")+1, getPropertyType.length());
							System.out.println("最后截取的属性类型:" + strPropertyType);
			                if(meta!=null){
			                	SortableField sf = new SortableField(meta, f1);
			                	//System.out.println("字段名称:"+l.getName()+"\t字段类型:"+l.getType()+"\t注解名称:"+l.getMeta().name()+"\t注解描述:"+l.getMeta().description());
		                        //System.out.println("字段名称:"+l.getName());
			                	 //将属性名和类名添加到实体中
								entitiesList.setEntityName(strClassName);  //类名
								entitiesList.setDataType(strPropertyType);  //属性类型
								//entitiesList.setDataType(meta.getClass().getTypeName());
								entitiesList.setDataLength(meta.length());  //长度
								entitiesList.setPropertyName(f1.getName());   //属性名
								entitiesList.setPropertyDesc(sf.getMeta().name());  //属性名的中文描述(中文注释)
								entitiesBean.addJarToTable(entitiesList);
			                }
						}
					}
				}
			}
		} catch(IOException e){
			e.printStackTrace();
		}
	}

到这里,通过自定义注解的方式读取Jar包的类名、属性名包括中文注释和属性类型就都能实现了。我上传了一份Jar包:http://download.csdn.net/detail/huanjileaimeidan/8548345 
这个是我上传上去可以进行测试的Jar包,有兴趣的可以下载下来试一试,有什么问题请在下方留言,欢迎和我沟通。

时间: 2024-07-29 14:35:42

【动态页面】(三)之二:通过自定义注解读取Jar包的类名和属性名的相关文章

【动态页面】(二)Java反射

Java的反射机制是Java语言非常重要的一个特性.先从Sun官网上看一下官网是怎样定义反射机制的. 大致翻译一下,翻译的可能不是非常准确. 反射(Reflection)是Java程序设计语言的一个特性,它要求Java程序执行的时候检查或自检,而且对内部的属性进行操作.比如,它能够让一个Java类获得它自己全部的成员名称而且显示出来.这样的能够从一个Java类内部进行检查和操作的能力听起来可能不是非常受喜欢,可是在其它程序语言中这样的特性(功能)根本就不存在. 比如,对于Pascla.C或者C#

Springboot注解整理 二《自定义注解》

自定义注解 @Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface CommonLog { String value() default ""; } @Target @Target 说明了Annotation所修饰的对象范围 取值ElementType 的类型如下所示: public enu

Gradle 自定义Task 打Jar包

可以作为Jar包内容的有两个地方: 1: build/intermediates/bundles/release/ 下的classes.jar 2: build/intermediates/classes/release/ 下 你的工程目录 方式1,采用的方式为copy,也就是网上最多.最容易搜索.最重复的方式: task makeJar(type: Copy) { delete 'build/libs/App'sName.jar' from( 'build/intermediates/bund

Dynamic CRM 2013学习笔记(三十二)自定义审批流3 - 节点及实体配置

上次介绍了<Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示> 以及如何配置自定义审批流的按钮:<Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮>,这次接着介绍如何配置审批流的节点及节点关系.     一. 模板头: 二.流程节点:        一共有三种节点:开始节点,中间节点,结束节点: 1.  开始节点: 2. 中间节点: .3.  结束节点:       三.流程节点关系:   四.实体配置 1.添加二个字段:

【动态页面】(一)前提

最近由于业务需要,转到动态页面的研究上来,因为我们的系统分为五个子系统,本着灵活.高效的原则,想着把前台页面这一块抽出来,不同以往把JSP表单.控件写死,而是以灵活可配置的方式,让各个系统高效的运转.可能后面还会想着跟权限结合起来,让权限去控制各个资源的调用,当然了那是后话,可能用不了多长时间就会着手去做这件事. 在动态页面这一块,我们最终想实现的效果是不在前台把JSP写死,而是通过动态绑定的方式生成系统想要的页面.我负责的是生成表单这一块,具体的业务要求是其他的子系统把自己的实体打成Jar包,

熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器、过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验。

熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器.过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验. 1.说一说Servlet生命周期(非常重要) Servlet生命周期包括三部分: 初始化:Web容器加载servlet,调用init()方法 只执行一次 处理请求:当请求到达时,运行其service()方法.service()自动调用与请求相对应的doXXX

spring中自定义注解(annotation)与AOP中获取注解

一.自定义注解(annotation) 自定义注解的作用:在反射中获取注解,以取得注解修饰的类.方法或属性的相关解释. package me.lichunlong.spring.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.R

跟王老师学注解(四):自定义注解

跟王老师学注解(四):自定义注解 主讲教师:王少华   QQ群号:483773664 到此,我们已经学习完了JDK提供的3种内建注解及4种元注解,下面来了解自定义注解 一.注解类型 (一)注解类型与接口:注解类型是一种接口,但它又不同于接口 1.注解类型使用关键字@interface而不是interface 1 2 public @interface TestAno { } @interface隐含继承java.lang.annotation.Annotation接口 2.注解类型的方法定义是独

Java注解(自定义注解、view注入)

注解这东西虽然在jdk1.5就加进来了,但他的存在还是因为使用Afinal框架的view注入才知道的.一直觉得注入特神奇,加了一句就可以把对应view生成了. 下面我们来认识一下注解这个东西 一.注解相关知识 注解相当于一种标记,在javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事.标记可以加在包,类,字段,方法,方法的参数以及局部变量上. 1.元注解:作用是负责注解其他注解.Java5.0定义了4个标准的meta-annotati