您的位置:首页 > 其它

简单的一个轮子MVC

2018-04-08 16:05 120 查看
这里是一个简单的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自带的代理模式,需要接口实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: