我准备用一个@MyActionde 的注解,来配上需要装载进入方法容器的类,自定义在类上写上@MyAction(value="/root"),则代码访问该类需要"/root"根路径,然后在方法上加上@MyAction(value = "/test"),表示执行该方法的路径为,“/root/test”。
package action;
import myframe.annotation.MyAction;
import myframe.annotation.MyMethod;
/**
* Created by yuyufeng on 2017/5/5.
*/
@MyAction(value="/root")
public class TestAction {
@MyAction(value = "/test")
public String testMyMethod() {
System.out.println("TestAction.testMyMethod");
return "index";
}
@MyAction(value = "/test2")
public String testMyMethod2() {
System.out.println("TestAction.testMyMethod2");
return "test";
}
}
在容器map中,设计路径为键,要执行的类方法为值。
注解MyAction
package myframe.annotation;
import java.lang.annotation.*;
/**
* Created by yuyufeng on 2017/5/5.
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAction {
String value() default "";
}
Map容器中值为类方法,所以先设计类结构ActionBean如下:
package myframe.bean;
import java.lang.reflect.Method;
/**
* Created by yuyufeng on 2017/5/5.
*/
public class ActionBean {
private Class<?> clazz;
private Method method;
public ActionBean(Class<?> clazz, Method method) {
this.clazz = clazz;
this.method = method;
}
public Class<?> getClazz() {
return clazz;
}
public void setClazz(Class<?> clazz) {
this.clazz = clazz;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
}
整理一下思路就是,通过uri去执行一个对象实例中的某个方法。
所以,我们需要两个容器。一个容器装载Action类实例,一个容器装载uri和ActionBean。
因为我们是通过方法调用的,所以只需要一个实例就好,一个Action放如一个实例到容器即可。(这个容器也类似Spring的IOC管理bean)
在反射过程中,我们需要从项目的package中获取带有@MyAction注解的类和方法,我们需要一个类扫描器,
类扫描工具类如下:
我们执行一个junit测试类,去执行扫描执行。
Action实例:
package action;
import myframe.annotation.MyAction;
/**
* Created by yuyufeng on 2017/5/5.
*/
@MyAction(value="/root")
public class TestAction {
@MyAction(value = "/test")
public String testMyMethod() {
System.out.println("TestAction.testMyMethod");
return "index";
}
@MyAction(value = "/test2")
public String testMyMethod2() {
System.out.println("TestAction.testMyMethod2");
return "test";
}
}
test:
import myframe.annotation.MyAction;
import myframe.bean.ActionBean;
import myframe.commons.ClassUtil;
import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Created by yuyufeng on 2017/5/5.
*/
public class TestAnno {
private static Map<String, ActionBean> map = new HashMap<String, ActionBean>();
private static Map<Class<?>, Object> objectMap = new HashMap<Class<?>, Object>();
@Test
public void test() throws IllegalAccessException, InstantiationException {
Set<Class<?>> classes = ClassUtil.getClasses("action");
for (Class<?> aClass : classes) {
System.out.println(aClass);
if (aClass.isAnnotationPresent(MyAction.class)) {
MyAction mac = aClass.getAnnotation(MyAction.class);
String classAnnoValue = mac.value().trim();
objectMap.put(aClass,aClass.newInstance());
for (Method method : aClass.getMethods()) {
if (method.isAnnotationPresent(MyAction.class)) {
MyAction mam = method.getAnnotation(MyAction.class);
String methodAnnoValue = mam.value().trim();
String actionName = classAnnoValue + methodAnnoValue;
map.put(actionName,new ActionBean(aClass,method));
}
}
}
}
ActionBean ab = map.get("/root/test2");
System.out.println(ab);
try {
String result= (String) ab.getMethod().invoke(objectMap.get(ab.getClazz()));
System.out.println(result);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
执行结果:
Connected to the target VM, address: '127.0.0.1:59438', transport: 'socket'
class action.TestAction
myframe.bean.ActionBean@475530b9
TestAction.testMyMethod2
test
Disconnected from the target VM, address: '127.0.0.1:59438', transport: 'socket'
Process finished with exit code 0
到这一步,根据uri反射执行类方法已经初步实现。
这些方法在框架初始化阶段执行装载即可。
建立一个初始化执行类:
package myframe.init;
import myframe.annotation.MyAction;
import myframe.bean.ActionBean;
import myframe.commons.ClassUtil;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Created by yuyufeng on 2017/5/5.
*/
public class MyFrameInit {
private static Map<String, ActionBean> actionMap;
private static Map<Class<?>, Object> objectMap;
public static Object getObject(Class<?> clazz) {
return objectMap.get(clazz);
}
public static ActionBean getActionBean(String key) {
return actionMap.get(key);
}
public static void init() throws IllegalAccessException, InstantiationException {
actionMap = new HashMap<String, ActionBean>();
objectMap = new HashMap<Class<?>, Object>();
Set<Class<?>> classes = ClassUtil.getClasses("action");
for (Class<?> aClass : classes) {
System.out.println(aClass);
if (aClass.isAnnotationPresent(MyAction.class)) {
MyAction mac = aClass.getAnnotation(MyAction.class);
String classAnnoValue = mac.value().trim();
objectMap.put(aClass, aClass.newInstance());
for (Method method : aClass.getMethods()) {
if (method.isAnnotationPresent(MyAction.class)) {
MyAction mam = method.getAnnotation(MyAction.class);
String methodAnnoValue = mam.value().trim();
String actionName = classAnnoValue + methodAnnoValue;
actionMap.put(actionName, new ActionBean(aClass, method));
}
}
}
}
System.out.println("MyFrameInit.init==================初始化完毕");
}
}
然后,我们在入口Servlet第一次执行的时候去调用初始化方法:
public class MyFrameServlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
try {
MyFrameInit.init();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
入口Servlet的doGet完善
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取要执行的动作
String uri = req.getRequestURI();
String actionName = uri.substring(0, uri.indexOf(".do"));
System.out.println("访问Action:" + actionName);
//do
ActionBean actionBean = MyFrameInit.getActionBean(actionName);
String result = "";
try {
result = (String) actionBean.getMethod().invoke(MyFrameInit.getObject(actionBean.getClazz()));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//return
String fileName = result;
System.out.println("执行完毕,跳转路径"+"/WEB-INF/jsp/" + fileName + ".jsp");
req.getRequestDispatcher("/WEB-INF/jsp/" + fileName + ".jsp").forward(req, resp);
}
配置tomcat,启动
访问http://127.0.0.1:8080/root/test.do
访问http://127.0.0.1:8080/root/test2.do
日志打印:
class action.TestAction
MyFrameInit.init==================初始化完毕
访问Action:/root/test
TestAction.testMyMethod
执行完毕,跳转路径/WEB-INF/jsp/index.jsp
访问Action:/root/test2
TestAction.testMyMethod2
执行完毕,跳转路径/WEB-INF/jsp/test.jsp
现在,页面的控制以及服务器方法的执行已经成功了。