这里是一个简单的J2EE MVC实现例子数据库部分没有写,算是个玩具。
-
路由的简单实现
这里把路由抽象出来 路径、请求类型(GET、POST)、路径的事例对象、以及请求对应的执行方法
public class Route {
/**
* 路径
*/
private String path;
/**
* 执行方法
*/
private String method;
/**
* 方法类型
*/
private String type;
/**
* action控制类
*/
private Object action;
}
在项目初始化的时候用一个Filter来拦截请求,初始化的时候进行类扫描,扫描的部分是有路径注解的类。
这里配置的时候初始化一个Action的路径(这里的ACTION路径扫描没有进行全路径就是获取子文件夹中,
下面简单的IOC注入加了点东西全路径扫描)
/**
* 通过一个包路径扫描所有的类
* @param path
* @return
*/
public List<Route> getAllRoutes(String packageDirName){
Enumeration<URL> dirs;
List<Route> routeList=new ArrayList<Route>();
try {
packageDirName=packageDirName.replace('.', '/');
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (dirs.hasMoreElements()) {
// 获取下一个元素
URL url = dirs.nextElement();
// 得到协议的名称
String protocol = url.getProtocol();
// 如果是以文件的形式保存在服务器上
if ("file".equals(protocol)) {
// 获取包的物理路径
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
// 以文件的方式扫描整个包下的文件 并添加到集合中
File[] files=new File(filePath).listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
if(name.endsWith(".class")) {
return true;
}
return false;
}
});
for(File f:files) {
this.logger.info("扫描文件:"+f.getPath());
// if(filePath.endsWith(".class")) {
this.logger.info("扫描类路径:"+packageDirName.replace('/', '.')+"."+f.getName().substring(0, f.getName().lastIndexOf('.')));
Class cl=Class.forName(packageDirName.replace('/', '.')+"."+f.getName().substring(0, f.getName().lastIndexOf('.')));
PathAnnotation pa=(PathAnnotation) cl.getAnnotation(PathAnnotation.class);
String routPath="";
String beforePath="";
if(null!=pa) {
routPath=pa.path();
beforePath=routPath;
}
Method[] methods=cl.getMethods();
for(Method m:methods) {
routPath=beforePath;
pa=m.getAnnotation(PathAnnotation.class);
if(null==pa) {
continue;
}
routPath+="/"+pa.path();
Route rt=new Route(routPath,m.getName(),pa.type(),cl.newInstance());
logger.info("加载路由:"+rt.toString());
routeList.add(rt);
}
}
}
// }
}
}
}catch (Exception e) {
e.printStackTrace();
}
return routeList;
}
当后台路径初始化后,
获取请求的路径进行匹配
匹配上了执行相应的方法(这里简单的实现保留了之前servlet的调用用到了request,response对象)
这里想到的如何可以避开request,response参数,直接使用普通的类,首先要获取参数的属性,这里通过
获取参数属性和前台对应的数据是一直的(这里指的是属性名字),是否可以直接反射过去执行相应得方
法,后面在尝试
这里的做法是可以编译的时候添加参数-g,但是这样做的别人反编译会存在一个信息泄露的问题
public class Test {
public static void main(final String[] arguments) throws Exception {
Class<?> clazz = Test.class;
Method method = clazz.getDeclaredMethod("test", String.class, int.class);
System.out.print("test : ");
Parameter[] parameters = method.getParameters();
for (final Parameter parameter : parameters) {
System.out.print(parameter.getName() + ' ');
}
}
public static void test(String param1, int param2) {
System.out.println(param1 + param2);
}
}
获取采用注解的方式,参数添加注解
public void test(@Parameter("param1") String param1,
@Parameter("param2") int param2) {
System.out.println(param1 + param2);
}
获取采用其他方式
RouteUtil ru=new RouteUtil();
Route rt=ru.findRoute(request.getServletPath());
if(null!=rt) {
System.out.println(rt.toString());
Object o=rt.getAction();
try {
Method m=o.getClass().getDeclaredMethod(rt.getMethod(),HttpServletRequest.class,HttpServletResponse.class);
if(o.getClass().isInstance(Proxy.class)) {
m.invoke(o.getClass().newInstance(),request,response);
}else {
m.invoke(o,request,response);
}
-
IOC这里简单的实现
这里也扫描所有有注解定义(自动注入的注解)
首先扫描保存起来,然后遍历注入,这里加了点代码直接遍历了子文件夹
/**
* 通过一个包路径扫描所有的注入类
* @param path
* @return
*/
public Map<String,Object> getAllAop(String packageDirName){
Enumeration<URL> dirs;
Map<String,Object> aopMap=new HashMap<String,Object>();
try {
packageDirName=packageDirName.replace('.', '/');
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (dirs.hasMoreElements()) {
// 获取下一个元素
URL url = dirs.nextElement();
// 得到协议的名称
String protocol = url.getProtocol();
// 如果是以文件的形式保存在服务器上
if ("file".equals(protocol)) {
// 获取包的物理路径
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
//以文件的方式扫描整个包下的文件 并添加到集合中
File[] files=new File(filePath).listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
if(name.endsWith(".class")|| dir.isDirectory()) {
return true;
}
return false;
}
});
for(File f:files) {
if(f.isDirectory()) {
aopMap.putAll(this.getAllAop(packageDirName+"."+f.getName()));
// return aopMap;
}else {
this.logger.info("扫描文件:"+f.getPath());
// if(filePath.endsWith(".class")) {
this.logger.info("扫描类路径:"+packageDirName.replace('/', '.')+"."+f.getName().substring(0, f.getName().lastIndexOf('.')));
Class cl=Class.forName(packageDirName.replace('/', '.')+"."+f.getName().substring(0, f.getName().lastIndexOf('.')));
AopAnnotation pa=(AopAnnotation) cl.getAnnotation(AopAnnotation.class);
if(null!=pa) {
String className=pa.value();
if(aopMap.containsKey(className)) {
throw new Exception("注入类重复");
}else {
aopMap.put(className, cl.newInstance());
}
}else {
continue;
}
}
}
// }
}
}
}catch (Exception e) {
e.printStackTrace();
}
return aopMap;
}
3.AOP这里的实现
这里通过代理机制来实现,这里使用的是JAVA自带的代理模式,需要接口实现