目标:
实现一个自定义注解,能够获取到注解的属性value,并将自定义注解用于绑定方法,然后通过反射获取到注解的value,以及其对应的方法,形成映射关系
原因:
在写ssm项目中,@RequestMapping(url),不同的url会执行不同的Controller方法,所以该篇博客将阐述我模拟得到url与方法的映射关系的过程
实现思路:
1、编写一个自定义注解RequestMapping,设置其作用于方法上,并为其设置属性value,用于模拟ssm项目中的@RequestMapping
2、编写一个Controller的包,里面写一个ControllerTest的类,用于模拟ssm项目中的Controller层
3、我们应该可以动态的获取Controller包下的所有java文件,并获取到它们的名字,然后再通过字符串拼接出它们的类全名(全限定名),用于后续获得它们的类对象,这个步骤类似于ssm配置文件中设置Controller层的包名一样,设置好后可以动态扫描指定包下所有的 类。
4、获取到全限定名后,用全限定名的方式得到类对象,然后依次读取所有的方法和所有的注解,然后再匹配某个方法是否绑定了某个特定注解,如果有,读取该注解的值,并与该方法一起放到MAP中作为映射关系
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
String value() default "";
}
上述代码是我自定义的注解类,很简单,前三行是元注解,可以去了解一下,然后注解内部就一个获取value的函数,并且有默认值
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class readfile {
List<String> res=new ArrayList<String>();
public List<String> readfile(String filepath) throws FileNotFoundException, IOException {
File file = new File(filepath);
if (!file.isDirectory()) {
System.out.println(file.getName());
if(file.getName().contains(".java")) {
res.add(file.getName());
}
} else if (file.isDirectory()) {
String[] filelist = file.list();
for (int i = 0; i < filelist.length; i++) {
File readfile = new File(filepath + "\\" + filelist[i]);
if (!readfile.isDirectory()) {
if(readfile.getName().contains(".java")) {
res.add(readfile.getName());
}
} else if (readfile.isDirectory()) {
readfile(filepath + "\\" + filelist[i]);
}
}
}
return res;
}
}
上述代码其实就是一个输入想要读取文件的地址,然后返回该文件下的所有.java文件,以List<String>的格式,内容存储的是该java文件的文件名,如下:
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import qcby.RequestMapping;
import readfile.readfile;
public class Test {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
readfile rf=new readfile();
List<String> res=rf.readfile("D:\\eclipse-workspace-new\\Arithmetic\\src\\Controller");
System.out.println(res);
for(int i=0;i<res.size();i++) {
res.set(i, "Controller."+res.get(i).split(".java")[0]);
}
for(String item: res) {
System.out.println(item);
}
Class item=Class.forName("Controller.TestController");
Annotation[] annotations = item.getAnnotations();
Method[] methods=item.getMethods();
HashMap<String, Method> map=new HashMap<String, Method>();
for(Method method : methods){
if(method.isAnnotationPresent(RequestMapping.class)){
RequestMapping requestMapping=method.getAnnotation(RequestMapping.class);
map.put(requestMapping.value(), method);
}
}
System.out.println(map);
}
}
以上代码为测试的主函数,首先,将Controller的目录地址以字符串传入写好的方法,读取出想要的java文件,然后做字符串操作,去掉.java,加上包名,得到全限定名,方便后续的获取类对象的操作,由于只再Controller中写了一个文件,所以我就不循环了,直接以相同的全限定名获取类对象,然后让类对象调用.getAnnotations()方法,去获取这个类中所有的注解
然后获取所有方法,循环的遍历,查看该方法是否绑有特定的注解,method.isAnnotationPresent(RequestMapping.class)该句就会判断方法是否绑有RequestMapping注解,如果有,则用该方法获取注解,再通过返回值类型为特定 注解类,即可通过.value()获取到注解的Value值,从而将value值与方法对应起来,形成映射关系
当有这个映射关系后,我们就可以跟ssm项目一样,比如前端要访问一个url,那么我们就可以将该字符串拿去映射关系中匹配,即可知道到底该调用哪一个Controller层的方法。