标签:
继续上一篇的内容
本篇讲述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啦
讲的有些凌乱,不懂的话多看几遍,因为写框架本来就不是容易的事,这只是刚刚开始
我也写了几个月,下一篇,就会讲解如何处理请求和映射表单提交的参数
标签:
原文地址:http://www.cnblogs.com/nimendezaige/p/4914644.html