码迷,mamicode.com
首页 > Web开发 > 详细

我要写框架之MVC(2)------初始化

时间:2015-10-27 17:31:06      阅读:270      评论:0      收藏:0      [点我收藏+]

标签:

继续上一篇的内容

本篇讲述MVC框架的初始化工作

我们可以在我们的核心控制器ActionCore里面的init方法进行初始化

之前说过我们用的是注解实现的而不是用xml,所以我们先新建一个注解

技术分享

@Retention指定的是注解的声明周期,RUNTIME 意思是在运行时

@Target 表示注解定义在哪,而METHOD则代表方法

其中两个属性代表使用注解的时候的参数都是可选的 但有默认值"",使用如下

技术分享

相信用过spring mvc 的人看到这里都会比较熟悉,就是当有add这个请求来到的时候会调用这个方法

而method="post" 表示只接收post请求

建好注解之后我们要进行初始化的第一步:

就是扫描所以的类,扫描来干嘛呢? 当然是扫描来映射成一个map集合

你想想我们有好多方法

@NfAction("/add")
public void add(){

}
@NfAction("/save")
public void save(){

}
@NfAction("/delete")
public void delete(){

}

我们扫描一遍,映射成map集合,就像

"/add":add()

"/save":save()

"/delete":delete()

这样当有一个add请求来的时候就很简单的获取到这个方法啦,

当然我们要记录的不止是这个方法,还有请求方式呢,

要有调用这方法要用到对象,

还有......

既然那么多东西要用到,当然就把他们封装成一个对象啦

我们就叫MyActionMapping 

技术分享

然后提供对应的get/set方法

说到这里,一般写框架都会用到反射,如果不会的朋友,可以先去学学

我们看到其中一个属性paras,就是代表着参数,这里会是我们遇到的第一个难题

学过反射的都知道,我们通过反射应该获取参数是Parameter,可是为什么我要自己写一个Para呢?

因为 Parameter不能获取到参数名,我们映射参数需要用到参数名,所以大家先建一个实体类

技术分享

而获取参数名我们编写个Util获取需要导入javassist-3.15.0-GA.jar 这个包

具体代码如下

//获取参数名
	public static String[] getParaNames(Method m) throws NotFoundException {
		// 实例化类型池  
	    ClassPool classPool = ClassPool.getDefault();  
	    classPool.appendClassPath(new ClassClassPath(m.getDeclaringClass()));  
	    CtClass ctClass = classPool.get(m.getDeclaringClass().getName());  
	    // 获取方法  
	    CtMethod method = ctClass.getDeclaredMethod(m.getName());  
	    // 判断是否为静态方法  
	    int staticIndex = Modifier.isStatic(method.getModifiers()) ? 0 : 1;   
	      
	    // 获取方法的参数  
	    //在得到方法后,返回代表这个方法的文件
	    MethodInfo methodInfo = method.getMethodInfo();  
	    CodeAttribute codeAttribute = methodInfo.getCodeAttribute();  
	    LocalVariableAttribute localVariableAttribute = (LocalVariableAttribute)codeAttribute.getAttribute(LocalVariableAttribute.tag);  
	    String[] names = new String[method.getParameterTypes().length];
	    for (int i = 0; i < method.getParameterTypes().length; i++) {  
	        names[i] = localVariableAttribute.variableName(staticIndex + i);
	    }  
		return names;
	}

绕了那么远,总体来说就是建立两个实体类,和获取参数名

回到我们的扫描 映射成map

我们扫描所有的class文件

public class ScanUtil {
	public List<String> scan(String url){
		List<String> list = new ArrayList<String>();
		//遍历这个文件夹下面的所有文件
		list = ergodic(url);
		//把路径换成类名
		return subString(list,url);
	}
	//递归遍历文件夹
	private List<String> ergodic(String url){
		List<String> list = new ArrayList<String>();
		File file = new File(url);
		if(file.isFile()){
			if(file.getName().matches(".*\\.class")){
				list.add(file.getAbsolutePath());
			}
		}else{
			File[] files = file.listFiles();
			for (File f : files) {
				if(f.isFile()){
					if(f.getName().matches(".*\\.class")){
						list.add(f.getAbsolutePath());
					}
				}else{
					List<String> temp = ergodic(url+File.separator+f.getName());
					for (String t : temp) {
						list.add(t);
					}
				}
			}
		}
		return list;
	}
	//截取字符串
	private List<String> subString(List<String> list,String u) {
		u = u.substring(1);
		u= u.replace("/","\\");
		List<String> paths = new ArrayList<String>();
		for (String str : list) {
			String url = str.replace(".class","");
			//换斜杠
			 
			String newUrl = url.replace(u,"");
			String newStr = newUrl.replace("\\",".");
			paths.add(newStr);
		}
		return paths;
	}
	
	
}

扫描完然后调用一个方法annotetionMapping

  通过反射生成对象获取里面的方法,属性等 封装成Maaping,判断有没有我们的注解,有就放到map集合,就那么简单

private Map<String,MyActionMapping> annotetionMapping(List<String> list){
		Map<String,MyActionMapping> map = new HashMap<String,MyActionMapping>();
		//遍历这些类
		for (String str : list) {
			Class<?> clazz = null;
			try {
				clazz = Class.forName(str);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			//获取遍历这些类的方法有没有NfAction注解
			Method[] meths = clazz.getMethods();
			for (Method method : meths) {
				NfAction myAction = method.getAnnotation(NfAction.class);
				//如果有NfAction注解
				if(myAction != null){
					String val = myAction.value();
					MyActionMapping mapping = new MyActionMapping();
					mapping.setAnnotation(myAction);
					//获取这个类
					mapping.setClazz(clazz);
					//获取这个类属性
					mapping.setFields(clazz.getFields());
					//获取这个方法
					mapping.setMethod(method);
					//获取这个方法的参数和参数名
					List<Para> paras = new ArrayList<Para>();
					String[] names = null;
					try {
						names = ParameterUtil.getParaNames(method);
					} catch (NotFoundException e) {
						e.printStackTrace();
					}
					Parameter[] ps = method.getParameters();
					for(int i=0;i<ps.length;i++){
						Para p = new Para();
						p.setName(names[i]);
						p.setPara(ps[i]);
						paras.add(p);
					}
					mapping.setParas(paras);
					map.put(val,mapping);
				}
			}
		}
		return map;
	}

最后把这个封装的结果放到我们Actioncore的成员变量里 Map<String,MyActionMapping> mappingMap;

初始化就OK啦,之后有请求来从这个map里获取就OK啦

讲的有些凌乱,不懂的话多看几遍,因为写框架本来就不是容易的事,这只是刚刚开始

我也写了几个月,下一篇,就会讲解如何处理请求和映射表单提交的参数

 

我要写框架之MVC(2)------初始化

标签:

原文地址:http://www.cnblogs.com/nimendezaige/p/4914644.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!