java实现的轻量级web MVC框架

        该项目是一个轻量级MVC框架,重点实现了IOCAOP特性,适合需要学习这两方面知识的人。

这个项目是博主在git上找到并且自己做了修改和注释的。希望可以帮到大家,也促进我自己的学习。其中原git地址为:git地址:https://github.com/wacxt/light-framework。博主的git地址为:https://github.com/wenjieyatou/light-framework。

项目的整体架构是:

(1):依赖注入的实现:通过BeanHelper(位于Helper包中)获取所有Bean Map(是一个记录了类与对象的映射关系的Map<Class<?>,Object>结构),遍历这个映射关系,取出Bean类与Bean实例,通过反射获取类中的所有成员变量,然后遍历这些变量,判断是否带有Inject注解,有的话从Map中取出Bean实例,通过Field.set方法来修改当前成员变量的值

(2):Aop的实现:使用动态代理来实现具有局限性:(1)代理类必须实现一个接口(2)反射大量生成类文件可能导致方法区触发Full GC。于是采用Cglib来实现 因为一个类可以被多重代理,(安全验证,时间计算等),采用了代理链的思路

项目的整体流程:

(1)DispatcherServlet的init方法实例化ClassHelper.class,BeanHelper.class,AopHelper.class,IocHelper.class,ControllerHelper.class

关键代码:

package com.light.framework;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.light.framework.bean.Handler;
import com.light.framework.bean.Param;
import com.light.framework.bean.View;
import com.light.framework.helper.BeanHelper;
import com.light.framework.helper.ConfigHelper;
import com.light.framework.helper.ControllerHelper;
import com.light.framework.helper.RequestHelper;
import com.light.framework.helper.ServletHelper;
import com.light.framework.helper.UploadHelper;
import com.light.framework.util.ArrayUtil;
import com.light.framework.util.CodeUtil;
import com.light.framework.util.JsonUtil;
import com.light.framework.util.ReflectionUtil;
import com.light.framework.util.StreamUtil;
import com.light.framework.util.StringUtil;

/**
 * 请求转发器
 * @author wenjie
 * @since 1.0.0 
 */
@WebServlet(urlPatterns = "/*", loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {

	@Override
	public void init(ServletConfig serveltConfig) throws ServletException {
		//初始化相关Helper类,实例化各种Bean,解析注解
		HelperLoader.init();
		//获取ServletContext 对象(用于注册Servlet)
		ServletContext servletContext = serveltConfig.getServletContext();
		//注册处理JSP 的 Servlet
		ServletRegistration jspServlet = servletContext.getServletRegistration("jsp");
		String appJspPath = ConfigHelper.getAppJspPath() + "*";
		jspServlet.addMapping(appJspPath);
		//注册处理静态资源的默认Servlet
		ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
		defaultServlet.addMapping(ConfigHelper.getAppAssertPath() + "*");
		//初始化文件上传助手
		UploadHelper.init(servletContext);
	}
	
	
	public void dservice(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{
		//获取请求方法与请求路径
		String requestMethod = request.getMethod().toUpperCase();
		String requestPath = request.getPathInfo();
		//获取Action处理器
		Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
		if(handler != null){
			//获取Controller类及其Bean实例
			Class<?> controllerClass = handler.getControllerClass();
			Object controllerBean = BeanHelper.getBean(controllerClass);
			//System.out.println(controllerBean.getClass().getName());
			//创建请求参数对象
			Map<String, Object> paramMap = new HashMap<String,Object>();
			Enumeration<String> paramNames = request.getParameterNames();
			while(paramNames.hasMoreElements()){
				String paramName = paramNames.nextElement();
				String paramValue = request.getParameter(paramName);
				paramMap.put(paramName, paramValue);
			}
			String body = CodeUtil.decodeURL(StreamUtil.getString(request.getInputStream()));
			if(StringUtil.isNotEmpty(body)){
				String []params = StringUtil.splitString(body, "&");
				if(ArrayUtil.isNotEmpty(params)){
					for(String param : params){
						String[] array = StringUtil.splitString(param,"=");
						if(ArrayUtil.isNotEmpty(array) && array.length == 2){
							String paramName = array[0];
							String paramValue = array[1];
							paramMap.put(paramName, paramValue);
						}
					}

				}
			}
			Param param = new Param(paramMap);
			//调用Action方法
			Method actionMethod = handler.getActionMethod();
			//System.out.println(actionMethod);
			Object result;
			// 这里需对 param  处理,
			if(paramMap != null && paramMap.size() > 0){
				result = ReflectionUtil.invokedMethod(controllerBean, actionMethod, param);
			}else{
				result = ReflectionUtil.invokedMethod(controllerBean, actionMethod);
			}
			//处理Action方法返回值
			if(result instanceof View){
				//返回JSP页面
				View view = (View) result;
				String path = view.getPath();
				if(StringUtil.isEmpty(path)){
					if(path.startsWith("/")){
						response.sendRedirect(request.getContextPath() + path);
					}else{
						Map<String,Object> model = view.getModel();
						for(Map.Entry<String, Object>entry : model.entrySet()){
							request.setAttribute(entry.getKey(), entry.getValue());
						}
						request.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(request, response);
					}
				} else if(result instanceof Data){
					//返回JSON数据
					Data data = (Data)result;
					Object model = data.getModel();
					if(model != null){
						response.setContentType("application/json");
						response.setCharacterEncoding("UTF-8");
						PrintWriter writer = response.getWriter();
						String json = JsonUtil.toJson(model);
						writer.write(json);
						writer.flush();
						writer.close();
					}
				}
			}

		}
	}
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		ServletHelper.init(request, response);
		try{
			//获取请求方法与请求路径 ,获取客户机的请求方式
			String requestMethod = request.getMethod();
			String requestPath = request.getPathInfo();
			
			if(requestPath.equals("/favicon.ico")){
				return;
			}
			
			//获取Action 处理器
			Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
			if(handler != null){
				//获取Controller类极其Bean实例
				Class<?> controllerClass = handler.getControllerClass();
				Object controllerBean = BeanHelper.getBean(controllerClass);
				
				Param param;
				if(UploadHelper.isMultipart(request)){
					param = UploadHelper.createParam(request);
				}else{
					param = RequestHelper.createParam(request);
				}
				
				Object result;
				Method actionMethod = handler.getActionMethod();
				if(param.isEmpty()){
					result = ReflectionUtil.invokedMethod(controllerBean, actionMethod);
				}else{
					result = ReflectionUtil.invokedMethod(controllerBean, actionMethod, param);
				}
				
				if(result instanceof View){
					handleViewResult((View)result, request, response);
				}else if( result instanceof Data){
					handleDataResult((Data) result,response);
				}
			}
		}finally{
			ServletHelper.destory();
		}
	}
	private void handleViewResult(View view,HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException{
		String path = view.getPath();
		if(StringUtil.isNotEmpty(path)){
			if(path.startsWith("/")){
				response.sendRedirect(request.getContextPath() + path);
			}else{
				Map<String,Object> model = view.getModel();
				for(Map.Entry<String, Object> entry : model.entrySet()){
					request.setAttribute(entry.getKey(), entry.getValue());
				}
				request.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(request, response);			}
		}
	}
	
	private void handleDataResult(Data data,HttpServletResponse response)throws IOException{
		Object model = data.getModel();
		if(model != null){
			response.setContentType("application/json");
			response.setCharacterEncoding("UTF-8");
			PrintWriter writer = response.getWriter();
			String json = JsonUtil.toJson(model);
			writer.write(json);
			writer.flush();
			writer.close();
		}
	}
}
加载类,通过class.forName()。参考代码如下:
package com.light.framework;

import com.light.framework.helper.AopHelper;
import com.light.framework.helper.BeanHelper;
import com.light.framework.helper.ClassHelper;
import com.light.framework.helper.ControllerHelper;
import com.light.framework.helper.IocHelper;
import com.light.framework.util.ClassUtil;

/**
 * 加载响应的Helper类
 * @author wenjie
 * @since 1.0.0 
 */

public final class HelperLoader {
	
	public static void init(){
		//需要注意AopHelper要在IocHelper之前加载,因为首先需要通过AopHelper获取代理对象,然后才能通过IocHelper进行依赖注入
		Class<?>[] classList = {
			ClassHelper.class,
			BeanHelper.class,
			AopHelper.class,
			IocHelper.class,
			ControllerHelper.class,		
		};
		for(Class<?> cls : classList){
			ClassUtil.loadClass(cls.getName());  //通过类的全限定名加载类
		}
	}
}
(2)ClassHelper类:用于获取应用包名下的类(所有类,Service类,Controller类,其他的带有某注解的类)
package com.light.framework.helper;

import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;

import com.light.framework.util.ClassUtil;
import com.ligth.framework.annotation.Service;
import com.ligth.framework.annotation.Controller;
/**
 * 类操作助手类 
 */
public class ClassHelper {
	
	/**
	 * 定义类集合(存放所加载的类)
	 */
	private static final Set<Class<?>> CLASS_SET;
	
	static {
		String basePackage = ConfigHelper.getAppBasePackage();
		CLASS_SET = ClassUtil.getClassSet(basePackage);
	}
	
	/**
	 * 获取应用包名下的所有类 
	 */
	public static Set<Class<?>> getClassSet(){
		return CLASS_SET;
	}
	
	/**
	 * 获取应用包名下所有Service类 
	 */
	public static Set<Class<?>> getServiceClassSet(){
		Set<Class<?>> classSet = new HashSet<Class<?>>();
		for(Class<?> cls : CLASS_SET){
			if(cls.isAnnotationPresent(Service.class)){
				classSet.add(cls);
			}
		}
		return classSet;
	}
	
	/**
	 * 获取应用包名下所有Controller类 
	 */
	public static Set<Class<?>> getControllerClassSet(){
		Set<Class<?>> classSet = new HashSet<Class<?>>();
		for(Class<?> cls : CLASS_SET){
			if(cls.isAnnotationPresent(Controller.class)){
				classSet.add(cls);
			}
		}
		return classSet;
	}
	
	/**
	 * 获取应用包名下所有bean类(包括Service,Controller等) 
	 */
	public static Set<Class<?>> getBeanClassSet(){
		Set<Class<?>> beanClassSet = new HashSet<Class<?>>();
		beanClassSet.addAll(getServiceClassSet());
		beanClassSet.addAll(getControllerClassSet());
		return beanClassSet;
	}
	
	/**
	 * 获取应用包名下某父类(或者接口)的所有子类(或者实现类) 
	 */
	public static Set<Class<?>> getClassSetBySuper(Class<?> superClass) {
		Set<Class<?>> classSet = new HashSet<Class<?>>();
		for (Class<?> cls : CLASS_SET) {
			// 此Class对象所表示的类或接口是否相同,前后则关系是父与子关系或接口与被实现关系,但又不同名
			// 关系是 父亲.isAssignableFrom(子)
			if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)) {
				classSet.add(cls);
			}
		}
		return classSet;
	}
	
	/**
	 * 获取应用包名下带有某注解的所有类比如获取所有注解(Annotation)是Controller的类(即所有的控制器类,就是切面类要管理的目标类)
	 */
	public static Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotationClass) {
		Set<Class<?>> classSet = new HashSet<Class<?>>();
		for (Class<?> cls : CLASS_SET) {
			if (cls.isAnnotationPresent(annotationClass)) {
				classSet.add(cls);
			}
		}
		return classSet;
	}
}
其中获得类的扩展方法为:
package com.light.framework.util;

import java.io.File;
import java.io.FileFilter;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.light.framework.util.StringUtil;

/**
* @ClassName: ClassUtil
* @Description: 类工具
* @author wenjie 
*/
public final class ClassUtil {
	private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);
	/**
	 * 获取类加载器
	 */
	public static ClassLoader getClassLoader(){
		return Thread.currentThread().getContextClassLoader();
	}
	
	/**
	 * 加载类,为了提高加载性能,可将isInitialized设为false
	 */
	public static Class<?> loadClass(String className,boolean isInitialized){
		Class<?> cls;
		try{
			cls = Class.forName(className,isInitialized,getClassLoader());
		}catch (ClassNotFoundException e) {
			LOGGER.error("load class failure",e);
			throw new RuntimeException(e);
		}
		return cls;
	}
	
	/**
	 * 加载类,为了提高加载性能,可将isInitialized设为false
	 * ,则不会加载该类的静态块,使得Bean没有被初始化,如果使用则报空指针错误。
	 * 所以,如果要使用则isInitialized设为true
	 */
	public static Class<?> loadClass(String className){
		Class<?> cls;
		try{
			cls = Class.forName(className,true,getClassLoader());
		}catch (Exception e) {
			LOGGER.error("load class failure",e);
			throw new RuntimeException(e);
		}
		return cls;
	}
	
	/**
	 * 获取指定包名下的所有类
	 */
	public static Set<Class<?>> getClassSet(String packageName){
		Set<Class<?>> classSet = new HashSet<Class<?>>();
		try{
			Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".", "/"));
			while(urls.hasMoreElements()){
				URL url = urls.nextElement();
				if(url != null){
					String protocol = url.getProtocol();
					if(protocol.equals("file")){
						String packagePath = url.getPath().replaceAll("%20", " ");
						addClass(classSet,packagePath,packageName);
					}else if(protocol.equals("jar")){
						JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection();
						if(jarURLConnection !=  null){
							JarFile jarFile = jarURLConnection.getJarFile();
							if(jarFile != null){
								Enumeration<JarEntry> jarEntries = jarFile.entries();
								while(jarEntries.hasMoreElements()){
									JarEntry jarEntry = jarEntries.nextElement();
									String jarEntryName = jarEntry.getName();
									//System.out.println(" jarEntryName------------------ > " + jarEntryName);
									if(jarEntryName.endsWith(".class")){
										String className = jarEntryName.substring(0,jarEntryName.lastIndexOf(".")).replace("/", ".");
										
										doAddClass(classSet,className);
									}
								}
							}
						}
					}
				}
			}
		}catch (Exception e) {
			LOGGER.error("load class set failure",e);
			throw new RuntimeException(e);
		}
		return classSet;
	}
	
	private static void addClass(Set<Class<?>> classSet,String packagePath,String packageName){
		File[] files = new File(packagePath).listFiles(new FileFilter() {
			@Override
			public boolean accept(File file) {
				//只要class文件或者目录,其他文件不要
				return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
			}
		});
		for(File file : files){
			String fileName = file.getName();
			if(file.isFile()){
				String className = fileName.substring(0,fileName.lastIndexOf("."));
				if(StringUtil.isNotEmpty(packageName)){
					className = packageName + "." + className;
				}
				doAddClass(classSet,className);
			}else{
				String subPackagePath = fileName;
				if(StringUtil.isNotEmpty(packagePath)){
					subPackagePath = packagePath + "/" + subPackagePath;
				}
				String subPackageName = fileName;
				if(StringUtil.isNotEmpty(packageName)){
					subPackageName = packageName + "." + subPackageName;
				}
				addClass(classSet,subPackagePath,subPackageName);
			}
		}
	}
	
	public static void doAddClass(Set<Class<?>> classSet,String className){
		Class<?> cls = loadClass(className,false);
		if(cls != null){
			classSet.add(cls);
		}

	}
}
(3)BeanHelper类:主要用于存放Bean类与Bean实例的映射关系
package com.light.framework.helper;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.light.framework.util.ReflectionUtil;

/**
 * Bean助手类
 * @author wenjie
 * @since 1.0.0 
 */

public final class BeanHelper {
	
	/**
	 * 定义Bean映射(用于存放Bean类与Bean实例的映射关系) 
	 */
	private static final Map<Class<?>,Object> BEAN_MAP = new HashMap<Class<?>, Object>();
	
	static{
		Set<Class<?>> beanClassSet = ClassHelper.getBeanClassSet();
		for(Class<?> beanclass : beanClassSet){
			Object obj = ReflectionUtil.newInstance(beanclass);//实例化类
			BEAN_MAP.put(beanclass, obj); //使用map创建一个类名与类实例的一个映射关系
		}
		//System.out.println("BEAN_MAP:"+BEAN_MAP.size());
	}
	
	/**
	 * 获取Bean映射 
	 */
	public static Map<Class<?>,Object> getBeanMap(){
		return BEAN_MAP;
	}
	
	/**
	 *  获取Bean实例 
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(Class<T> cls){
		if(!BEAN_MAP.containsKey(cls)){
			throw new RuntimeException("can not get bean by class: " + cls);
		}
		return (T) BEAN_MAP.get(cls);
	}
	
	/**
	 * 设置Bean实例 
	 */
	public static void setBean(Class<?> cls, Object obj){
		BEAN_MAP.put(cls, obj);
	}
}
(4)AopHelper类:切面辅助类,用于初始化AOP框架
package com.light.framework.helper;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.light.framework.proxy.AspectProxy;
import com.light.framework.proxy.Proxy;
import com.light.framework.proxy.ProxyManager;
import com.light.framework.proxy.TransactionProxy;
import com.ligth.framework.annotation.Aspect;
import com.ligth.framework.annotation.Service;

public final class AopHelper {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(AopHelper.class);
	
	/**
	 * 静态块初始化AOP框架
	 */
	static{
		try{
			//代理类和目标类集合的映射关系Map,包含普通切面类和事务切面类
			Map<Class<?>,Set<Class<?>>> proxyMap = createProxyMap();
			//key-value 转换 即目标类(被切类)- 切面类
			Map<Class<?>,List<Proxy>> targetMap = createTargetMap(proxyMap);
			for(Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()){
				//目标类
				Class<?> targetClass = targetEntry.getKey();
				//System.out.println(targetClass.getName());
				//切面类,有可能一个目标类有多个切面类,比如权限切面、日志切面等
				List<Proxy> proxyList = targetEntry.getValue();
				//动态生成某个类具体的切面(代理)类
				Object proxy = ProxyManager.createProxy(targetClass, proxyList);
				BeanHelper.setBean(targetClass, proxy);
			}
		}catch (Exception e) {
			LOGGER.error("aop failure",e);
		}
	}
	

	/**
	 * 获取注解类是aspect.value()的所有类,比如aspect.value()=Controller ,那就是所有带注解是Controller类的
	 */
	private static Set<Class<?>> createTargetClassSet(Aspect aspect) throws Exception{
		Set<Class<?>> targetClassSet = new HashSet<Class<?>>();
		//其实就是Aspect注解
		Class<? extends Annotation> annotation = aspect.value();
		if(annotation != null && !annotation.equals(Aspect.class)){
			//比如aspect.value()是 controller,那么本此的目标类就是注解是Controller的类(所有的控制器类)
			targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));
		}
		return targetClassSet;
	}
	
	/**
	 * 获取目标类和代理类的映射关系
	 */
	private static Map<Class<?>,Set<Class<?>>> createProxyMap() throws Exception{
		Map<Class<?>,Set<Class<?>>> proxyMap = new HashMap<Class<?>, Set<Class<?>>>();
		//表示继承了AspectProxy 的类可能会是代理类,下面会过滤,如果Annotation是Aspect那么就是代理类
/*		Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
		for(Class<?> proxyClass : proxyClassSet){
			if(proxyClass.isAnnotationPresent(Aspect.class)){
				Aspect aspect = proxyClass.getAnnotation(Aspect.class);
				Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
				proxyMap.put(proxyClass, targetClassSet);
			}
		}*/
		addAspectProxy(proxyMap);
		addTransactionProxy(proxyMap);
		return proxyMap;
	}
	
	/**
	 * 根据映射关系分析目标类和代理对象列表之间的映射关系(key-value 转换)
	 * 将原来的1个切面类对应一个被切类(委托类)集合变换成1个被切类(目标类OR被代理类)
	 * 对应一个切面类(代理类),也就是添加一一对应关系可以直接从Map中找到
	 */					 
	private static Map<Class<?>,List<Proxy>> createTargetMap(Map<Class<?>,Set<Class<?>>> proxyMap) throws Exception{
		Map<Class<?>,List<Proxy>> targetMap = new HashMap<Class<?>,List<Proxy>>();
		for(Map.Entry<Class<?>, Set<Class<?>>> proxyEntry : proxyMap.entrySet()){
			//切面类
			Class<?> proxyClass = proxyEntry.getKey();
			//被切类
			Set<Class<?>> targetClassSet = proxyEntry.getValue();
			for(Class<?> targetClass : targetClassSet){
				//切面类实例
				Proxy proxy = (Proxy) proxyClass.newInstance();
				//如果目标类(被切类)已经包含了,则将该切面类的实例映射到该目标类上
				if(targetMap.containsKey(targetClass)){
					targetMap.get(targetClass).add(proxy);
				}else{
					List<Proxy> proxyList = new ArrayList<Proxy>();
					proxyList.add(proxy);
					targetMap.put(targetClass, proxyList);
				}
			}
		}
		return targetMap;
	}
	
	/**
	 * 添加普通切面代理
	 */
	private static void addAspectProxy(Map<Class<?>,Set<Class<?>>> proxyMap) throws Exception{
		//普通切面类必须是继承AspectProxy,获取所有切面类
		Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
		for(Class<?> proxyClass : proxyClassSet){
			//普通切面类必须是有Aspect的标识,获取所有切面类
			if(proxyClass.isAnnotationPresent(Aspect.class)){
				//获取Aspect的值,即获取该切面类要横切的对象或者哪一类对象
				//(比如@Aspect(Controller.class) 表示该切面类横切带Controller注解的类,即控制器类)
				Aspect aspect = proxyClass.getAnnotation(Aspect.class);
				//创建被横切的类,比如所有的Controller类
				Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
				proxyMap.put(proxyClass,targetClassSet);
			}
		}
	}
	
	/**
	 * 添加事务切面代理
	 */
	private static void addTransactionProxy(Map<Class<?>,Set<Class<?>>> proxyMap){
		Set<Class<?>> serviceClassSet = ClassHelper.getClassSetByAnnotation(Service.class);
		proxyMap.put(TransactionProxy.class, serviceClassSet);
	}
}
(5)IocHelper类:依赖注入类,通过遍历BeanMap,找出Field中带有Inject注解的成员变量,然后通过反射进行初始化
package com.light.framework.helper;

import java.lang.reflect.Field;

import java.util.Map;

import com.light.framework.util.ArrayUtil;
import com.light.framework.util.CollectionUtil;
import com.light.framework.util.ReflectionUtil;
import com.ligth.framework.annotation.Inject;

/**
 * 依赖注入助手类
 * @author wenjie
 * @since 1.0.0 
 */

public final class IocHelper {
	static{
		//获取所有的Bean类与Bean实例之间的映射关系(简称 Bean Map)
		Map<Class<?>,Object> beanMap = BeanHelper.getBeanMap();
		if(CollectionUtil.isNotEmpty(beanMap)){
			//遍历Bean Map
			for(Map.Entry<Class<?>, Object>beanEntry : beanMap.entrySet()){
				//从BeanMap 中获取Bean类与Bean实例
				Class<?> beanClass = beanEntry.getKey();
				Object beanInstance = beanEntry.getValue();
				//获取Bean 类定义的所有成员变量(简称Bean Field)
				Field[] beanFields = beanClass.getDeclaredFields();
				if(ArrayUtil.isNotEmpty(beanFields)){
					//遍历Bean Field
					for(Field beanField : beanFields){
						//判断当前Bean Field 是否 带有 Inject 注解
						if(beanField.isAnnotationPresent(Inject.class)){
							//System.out.println("当前方法"+beanField);
							//在Bean Map中获取Bean Field对应的实例
							Class<?> beanFieldClass = beanField.getType();
							Object beanFieldInstance = beanMap.get(beanFieldClass);
							if(beanFieldInstance != null){
								//通过反射初始化BeanField的值 将某属性值设置到对应的实例化对象中
								ReflectionUtil.setField(beanInstance, beanField, beanFieldInstance);
							}
						}
					}
				}
			}
		}
	}
}
相当于对属性进行一个属性注入的过程。首先获得bean,然后得到bean的实例对象,通过反射得到成员变量,注入。

(6)ControllerHelper类:用于存放请求和处理器的映射关系
package com.light.framework.helper;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import com.light.framework.bean.Handler;
import com.light.framework.bean.Request;
import com.light.framework.util.ArrayUtil;
import com.light.framework.util.CollectionUtil;
import com.ligth.framework.annotation.Action;

/**
 * 控制器助手类
 * @author wenjie
 * @since 1.0.0 
 */
public final class ControllerHelper {
	//用于存放请求与处理器映射关系(简称Action Map)
	private static final Map<Request,Handler> ACTION_MAP = new HashMap<Request,Handler>();
	static{
		//获取所有的Controller类
		Set<Class<?>> controllerClassSet = ClassHelper.getControllerClassSet();
		if(CollectionUtil.isNotEmpty(controllerClassSet)){
			for(Class<?> controllerClass : controllerClassSet){
				//获取Controller类中定义的方法
				Method[] methods = controllerClass.getDeclaredMethods();
				if(ArrayUtil.isNotEmpty(methods)){
					//遍历这些Controller中的方法
					for(Method method : methods){
						//判断当前方法是否带有Action 注解
						if(method.isAnnotationPresent(Action.class)){
							//从Action注解中获取URL 映射规则
							Action action = method.getAnnotation(Action.class);
							String mapping = action.value();
							//验证URL映射规则
							if(mapping.matches("\\w+:/\\w*")){
								String[] array = mapping.split(":");
								if(ArrayUtil.isNotEmpty(array) && array.length == 2){
									//获取请求方法与请求路径
									String requestMethod = array[0];
									String requestPath = array[1];
									Request request = new Request(requestMethod, requestPath);
									Handler handler = new Handler(controllerClass, method);
									//初始化Action Map
									ACTION_MAP.put(request, handler);
								}
							}
						}
					}
				}
			}
		}

	}
	
	/**
	 * 获取Handler
	 */
	public static Handler getHandler(String requestMethod,String requestPath){
		Request request = new Request(requestMethod, requestPath);

		return ACTION_MAP.get(request);
	}
}
其实就是获得Controller bean,查看注解中的Action,得到他的映射地址,处理方法等。

项目优化:

(1)使用ThreadLocal来存放JDBC Connection (2)增加事务控制特性

package com.light.framework.proxy;

import java.lang.reflect.Method;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.light.framework.helper.DatabaseHelper;
import com.ligth.framework.annotation.Transaction;

/**
 * 事务代理
 * @author wenjie
 * @since 1.0.0 
 */

public class TransactionProxy implements Proxy {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(TransactionProxy.class);
	//保证同一线程中事务控制相关逻辑只会执行一次
	private static final ThreadLocal<Boolean> FLAG_HOLDER = new ThreadLocal<Boolean>(){
		@Override
		protected Boolean initialValue(){
			return false;
		}
	};
	
	@Override
	public Object doProxy(ProxyChain proxyChain) throws Throwable{
		Object result = null;
		boolean flag = FLAG_HOLDER.get();
		Method method = proxyChain.getTargetMethod();
		if(!flag && method.isAnnotationPresent(Transaction.class)){
			FLAG_HOLDER.set(true);
			try{
				DatabaseHelper.beginTransaction(); //增加了事务处理
				LOGGER.debug("begin transaction");
				result = proxyChain.doProxyChain();
				DatabaseHelper.commitTransaction();
				LOGGER.debug("commit transaction");
			} catch(Exception e){
				DatabaseHelper.rollbackTransaction();
				LOGGER.debug("rollback transaction");
			} finally{
				FLAG_HOLDER.remove();
			}
		} else{
			result = proxyChain.doProxyChain();
		}
		return result;
	}
	
}
package com.light.framework.helper;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.light.framework.util.CollectionUtil;
import com.light.framework.util.PropsUtil;

/**
 *  数据库操作助手类
 */
public final class DatabaseHelper {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseHelper.class);
	
	private static final QueryRunner QUERY_RUNNER;
	
	private static final BasicDataSource DATA_SOURCE;
	
	//利用ThreadLocal来存储connection
	private static final ThreadLocal<Connection> CONNECTION_HOLDER;
	
	/**
	 * 数据库相关配置信息
	 */
	private static final String DRIVER;
	private static final String URL;
	private static final String USERNAME;
	private static final String PASSWORD;
	
	static{
		CONNECTION_HOLDER = new ThreadLocal<Connection>(); 
		QUERY_RUNNER = new QueryRunner();
		Properties conf = PropsUtil.LoadProps("light.properties");
		DRIVER = conf.getProperty("light.framework.jdbc.driver");
		URL = conf.getProperty("light.framework.jdbc.url");
		USERNAME = conf.getProperty("light.framework.jdbc.username");
		PASSWORD = conf.getProperty("light.framework.jdbc.password");
		
		DATA_SOURCE = new BasicDataSource();
		DATA_SOURCE.setDriverClassName(DRIVER);
		DATA_SOURCE.setUrl(URL);
		DATA_SOURCE.setUsername(USERNAME);
		DATA_SOURCE.setPassword(PASSWORD);
		
		try {
			Class.forName(DRIVER);
		} catch (ClassNotFoundException e) {
			LOGGER.error("can not load jdbc driver",e);
		}
	}
	
	/**
	 * 获取数据库连接 
	 */
	public static Connection getConnection(){
		Connection conn = CONNECTION_HOLDER.get();
		if(conn == null){
			try {
				//conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
				conn = DATA_SOURCE.getConnection();
			} catch (SQLException e) {
				LOGGER.error("get connection fail",e);
				throw new RuntimeException(e);
			} finally {
				CONNECTION_HOLDER.set(conn);
			}
		}
		return conn;
	}
	
	/**
	 * 关闭数据库连接 
	 */
	@Deprecated
	public static void closeConnection(){
		Connection conn = CONNECTION_HOLDER.get();
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				LOGGER.error("close connection fail",e);
				throw new RuntimeException(e);
			} finally{
				CONNECTION_HOLDER.remove();
			}
		}
	}
	
	/**
	 * 开启事务 
	 */
	public static void beginTransaction(){
		Connection conn = getConnection();
		if(conn != null){
			try {
				conn.setAutoCommit(false);
			} catch (SQLException e) {
				LOGGER.error("begin transaction fail",e);
				throw new RuntimeException(e);
			} finally{
				CONNECTION_HOLDER.set(conn);
			}
		}
	}
	
	/**
	 * 提交事务 
	 */
	public static void commitTransaction(){
		Connection conn = getConnection();
		if(conn != null){
			try {
				conn.commit();
				conn.close();
			} catch (SQLException e) {
				LOGGER.error("commit transaction fail",e);
				throw new RuntimeException(e);
			}
		}
	}
	
	/**
	 * 事务回滚 
	 */
	public static void rollbackTransaction(){
		Connection conn = getConnection();
		if(conn != null){
			try {
				conn.rollback();
				conn.close();
			} catch (SQLException e) {
				LOGGER.error("rollback transaction fail",e);
				throw new RuntimeException(e);
			}
		}
	}
	
	/**
	 * 查询实例列表 
	 */
	public static <T> List<T> queryEntityList(Class<T> entityClass, String sql,Object... params) {
		List<T> entityList;
		try {
			Connection conn = getConnection();
			entityList = QUERY_RUNNER.query(conn, sql, new BeanListHandler<T>(entityClass), params);
		} catch (SQLException e) {
			LOGGER.error("query entity list failure", e);
			throw new RuntimeException(e);
		} 
		return entityList;
	}
	
	/**
	 * 查询单个实体对象 
	 */
	public static <T> T queryEntity(Class<T> entityClass,String sql,Object... params){
		T entity;
		try{
			Connection conn = getConnection();
			entity = QUERY_RUNNER.query(conn, sql,new BeanHandler<T>(entityClass),params);
		}catch (SQLException e) {
			LOGGER.error("query entity failure",e);
			throw new RuntimeException(e);
		}
		return entity;
	}
	
	/**
	 * 执行查询语句 
	 */
	public static List<Map<String,Object>> executeQuery(String sql, Object ...params){
		List<Map<String,Object>> result = null;
		try {
			Connection conn = getConnection();
			QUERY_RUNNER.query(conn, sql, new MapListHandler(), params);
		} catch (SQLException e) {
			LOGGER.error("execute query fail");
			throw new RuntimeException(e);
		}
		return result;
	}
	
	/**
	 * 执行更新语句(包括update,insert,delete) 
	 */
	public static int executeUpdate(String sql,Object...objects){
		int rows = 0;
		try{
			Connection conn = getConnection();
			rows = QUERY_RUNNER.update(conn,sql,objects);
		}catch (SQLException e) {
			LOGGER.error("execute update failure",e);
		}
		return rows;
	}
	
	/**
	* @Title: insertEntity
	* @Description: 插入实体
	* @param @param entityClass
	* @param @param fieldMap
	* @param @return    设定文件
	* @return boolean    返回类型
	* @throws
	*/
	public static <T> boolean insertEntity(Class<T> entityClass,Map<String,Object> fieldMap){
		if(CollectionUtil.isEmpty(fieldMap)){
			LOGGER.error("can not insert entity: fieldMap is empty");
			return false;
		}
		String sql = "insert into " + getTableName(entityClass);
		StringBuilder columns = new StringBuilder("(");
		StringBuilder values = new StringBuilder("(");
		for(String fieldName : fieldMap.keySet()){
			columns.append(fieldName).append(", ");
			values.append("?, ");
		}
		//columns 将最后一个, 换成)
		columns.replace(columns.lastIndexOf(", "),columns.length(),")");
		//values 将最后一个, 换成)
		values.replace(values.lastIndexOf(", "), values.length(), ")");
		sql += columns + " values " + values;
		Object[] params = fieldMap.values().toArray();
		return executeUpdate(sql,params) == 1;
	}
	
	/**
	* @Title: updateEntity
	* @Description: 更新实体
	* @param @param entityClass
	* @param @param id
	* @param @param fieldMap
	* @param @return    设定文件
	* @return boolean    返回类型
	* @throws
	*/
	public static <T> boolean updateEntity(Class<T> entityClass,long id,Map<String,Object> fieldMap){
		if(CollectionUtil.isEmpty(fieldMap)){
			LOGGER.error("can not update entity: fieldMap is empty");
			return false;
		}
		String sql = " update " + getTableName(entityClass) + " set ";
		StringBuilder columns = new StringBuilder();
		for(String fieldName : fieldMap.keySet()){
			columns.append(fieldName).append("=?, ");
		}
		sql += columns.substring(0, columns.lastIndexOf(", ")) + " where id = ?";
		List<Object> paramList = new ArrayList<Object>();
		paramList.addAll(fieldMap.values());
		paramList.add(id);
		Object[] params = paramList.toArray();
		return executeUpdate(sql,params) == 1;
	}
	
	/**
	* @Title: deleteEntity
	* @Description: 删除实体
	* @param @param entityClass
	* @param @param id
	* @param @return    设定文件
	* @return boolean    返回类型
	* @throws
	*/
	public static <T> boolean deleteEntity(Class<T> entityClass,long id){
		String sql = " delete from " + getTableName(entityClass) + " where id=?";
		return executeUpdate(sql, id) == 1;
	}
	
	/**
	* @Title: getTableName
	* @Description: 获取表名(实体类名,要求数据库表名和实体类名相同)
	* @param @param entityClass
	* @param @return    设定文件
	* @return String    返回类型
	* @throws
	*/
	public static String getTableName(Class<?> entityClass){
		return entityClass.getSimpleName();
	}
	
}

Aop是使用代理链实现的。事务也是利用代理链。

TODO: (1)增加Shiro (2)增加Web服务框架(计划使用CXF)

猜你喜欢

转载自blog.csdn.net/wenjieyatou/article/details/80333338