上篇博客介绍了通过反射读取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; //用迭代器去判断里面有多少文件,遍历文件的一个方法 Iteratoriter = 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 Listlist = new ArrayList (); 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 enumFiles = jar.entries(); JarEntry entry; //测试此枚举是否包含更多的元素 while(enumFiles.hasMoreElements()){ entry = (JarEntry)enumFiles.nextElement(); if(entry.getName().indexOf("META-INF") 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包,有兴趣的可以下载下来试一试,有什么问题请在下方留言,欢迎和我沟通。