spring mvc框架源码分析(二)-自定义注解以及通过反射获取注解
2017-03-08 10:42
549 查看
大多数框架都是通过注解,反射来实现很多框架功能的,在我们这个框架中,我们可以通过注解来标识不同的层,以及每个路径所对应的方法。
之后定义一个方法级注解@MyRequestMapping,这个注解用于作用于方法,主要作用就是标识某个请求路径所对应的处理这个请求的方法。
注解中有两个值,path为请求路径,method为请求方式,这里我们会定义一个枚举变量RequestMethod来记录一般的请求方式
最后还定义了一个注解@MyResponseString用于标识方法是返回一个字符串还是一个页面
首先定义一个AnnotationUtil类来处理注解,之后再定义一个监听器AnnotationListener用于容器启动时执行AnnotationUtil中对应的方法
web.xml配置
这里我们开始编写AnnotionUtil,先说一下整体的流程:最开始我们需要定义一个变量stringList,来储存结果集,之后通过反射来读取controller目录下所有的类,最后再扫描这些类获取结果集。
AnnotionUtil中获取的List<String>里面有请求路径,请求方式,是否返回字符串,路径对应的类名,路径对应的处理方法,之后我们需要把它存储在ServletContext 中,在之前定义的监听器AnnotationListener 中
之后我们就可以通过getServletContext().getAttribute("annotationList");来获取路径以及其对应的方法了。
如何使用注解:
参考spring的@Controller和RequestMapping,我们这个框架也可以自定义这两个注解,首先定义一个控制层注解@MyMontroller,这个注解作用于类,主要作用是标识某个类是否为控制层。@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyController { String name() default ""; }
之后定义一个方法级注解@MyRequestMapping,这个注解用于作用于方法,主要作用就是标识某个请求路径所对应的处理这个请求的方法。
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyRequestMapping { String path() default ""; RequestMethod[] method() default {}; }
注解中有两个值,path为请求路径,method为请求方式,这里我们会定义一个枚举变量RequestMethod来记录一般的请求方式
public enum RequestMethod { GET,POST,PUT,DELETE }
最后还定义了一个注解@MyResponseString用于标识方法是返回一个字符串还是一个页面
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyResponseString { }
容器初始化时通过反射获取注解:
至此Controller层基本的注解大概定义完了,接下来的事情就是在容器初始化的时候通过反射来获取每个路径以及每个路径所对应的注解,储存为list类型然后保存到ServletContext中首先定义一个AnnotationUtil类来处理注解,之后再定义一个监听器AnnotationListener用于容器启动时执行AnnotationUtil中对应的方法
public class AnnotationListener implements ServletContextListener{ @Override public void contextInitialized(ServletContextEvent servletContextEvent) { } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { } }
web.xml配置
<listener> <listener-class>com.example.listener.AnnotationListener</listener-class> </listener>
这里我们开始编写AnnotionUtil,先说一下整体的流程:最开始我们需要定义一个变量stringList,来储存结果集,之后通过反射来读取controller目录下所有的类,最后再扫描这些类获取结果集。
public class AnnotationUtil { private List<String> stringList; private List<Class> getClassList(String dir, String srcPath) throws ClassNotFoundException { List<Class> classList = new ArrayList<Class>(); String newDir = dir.replace(".","/"); String abSolutePath = srcPath + newDir; //构成完整路径 //file:/E:/dev/testServlet/out/artifacts/testServlet_war_exploded/WEB-INF/classes/src/com/example/myController //去除srcPath 获取到的字符串前缀file:/ String ss = abSolutePath.substring(6, abSolutePath.length()); abSolutePath = ss.replace("/",File.separator); File dirFile = new File(abSolutePath); File[] files = dirFile.listFiles(); Class<?> cla = null; for (File file:files){ //遍历文件夹里面的所有文件遇到文件夹则向下查找 if (file.isDirectory()){ String child = dir + "."+file.getName(); getClassList(child, getSrcPath()); }else { cla = Class.forName(dir+"."+file.getName().split("\\.")[0]); classList.add(cla); } } return classList; } private String getSrcPath(){ String path=""; try { path =Thread.currentThread().getContextClassLoader().getResource("")+""; //获取src路径 } catch (Exception e) { e.printStackTrace(); } return path; } private void setRequestMapping(List<Class> list) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException { for (Class<?> cla:list){ if (cla.getAnnotation(MyController.class)!=null){ //是否有MyController注解 Method[] methods = cla.getMethods(); for (Method method : methods){ if (method.getAnnotation(MyRequestMapping.class)!=null){//判断方法上是否有@MyRequestMapping MyRequestMapping annotation = method.getAnnotation(MyRequestMapping.class); if (method.getAnnotation(MyResponseString.class) != null){//判断方法上是否有@MyResponseString stringList.add(annotation.path()+" "+annotation.method()[0].toString()+" "+ SystemConfig.ResponseString+" "+cla.getName()+" "+method.getName()); }else { stringList.add(annotation.path()+" "+annotation.method()[0].toString()+" "+SystemConfig.ResponsePage+" "+cla.getName()+" "+method.getName()); } } } } } } public List<String> getRequestMapping(){ stringList = new ArrayList<String>(); List<Class> list = null; try { list = getClassList("com.example.myController", getSrcPath());//获取com.example.myController目录下所有的类 setRequestMapping(list);//选择符合条件的类,并且把类中所有的路劲,方法储存到list中 } catch (Exception e) { e.printStackTrace(); } return stringList; } }
AnnotionUtil中获取的List<String>里面有请求路径,请求方式,是否返回字符串,路径对应的类名,路径对应的处理方法,之后我们需要把它存储在ServletContext 中,在之前定义的监听器AnnotationListener 中
public class AnnotationListener implements ServletContextListener{ private ServletContext servletContext; @Override public void contextInitialized(ServletContextEvent servletContextEvent) { List<String> list = new AnnotationUtil().getRequestMapping(); this.servletContext = servletContextEvent.getServletContext(); servletContext.setAttribute("annotationList",list); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { } }
之后我们就可以通过getServletContext().getAttribute("annotationList");来获取路径以及其对应的方法了。
实际运用注解:
@MyController public class RequestController { @MyResponseString @MyRequestMapping(path = "/zhu/test1",method = RequestMethod.GET) public String testA(HttpServletRequest httpServletRequest){ return "xx"; } @MyRequestMapping(path = "/zhu/test",method = RequestMethod.GET) public String testOne(){ return "index.jsp"; } @MyRequestMapping(path = "/zhu/test",method = RequestMethod.POST) public String testOnea(){ return "cao.html"; } @MyRequestMapping(path = "/zhu/html_test",method = RequestMethod.GET) public String testOneaa(){ return "xxx.html"; } }
相关文章推荐
- 自己动手设计java web框架(二)-自定义注解以及通过反射获取注解
- Reflect 通过反射获取自定义注解值给另外一个对象赋值
- 框架架构-运用JAVA反射获取自定义注解实例
- java 自定义注解annotation和通过反射获取注解
- Reflect 通过反射获取自定义注解值给另外一个对象赋值
- java中自定义注解并通过反射获取注解属性值
- java通过反射获取类名、属性名称以及@Table注解上的表名称
- spring源码分析(web)--通过注解获取bean源码分析
- android 自定义注解 通过反射获取注解属性值
- spring boot 中 自定义注解,并通过注解反射获取类实例
- Reflect 通过反射获取自定义注解值给另外一个对象赋值
- java中自定义注解并通过反射获取注解属性值
- Java通过反射获取自定义注解
- java中自定义注解并通过反射获取注解属性值
- java中自定义注解并通过反射获取注解属性值
- java中自定义注解并通过反射获取注解属性值
- 基于Spring MVC框架JSR-303的自定义注解Validator验证实现
- java 注解annotation的使用,以及反射如何获取注解
- java 注解annotation的使用,以及反射如何获取注解
- Java自定义注解和运行时靠反射获取注解