diff --git a/frameworktest/src/main/java/com/xfj/frameworktest/PropertiesLoad.java b/frameworktest/src/main/java/com/xfj/frameworktest/PropertiesLoad.java deleted file mode 100644 index 6ee826c..0000000 --- a/frameworktest/src/main/java/com/xfj/frameworktest/PropertiesLoad.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.xfj.frameworktest; - -import org.junit.Test; -import simple.xfj.framework.annotation.Controller; -import simple.xfj.framework.constant.ConfigConstant; -import simple.xfj.framework.util.ClassUtil; -import simple.xfj.framework.util.PropsUtil; - -import java.util.Properties; - -/** - * Created by asus on 2017/4/17. - */ -@Controller -public class PropertiesLoad { - - -} diff --git a/frameworktest/src/main/java/com/xfj/frameworktest/aspect/TimeAspect.java b/frameworktest/src/main/java/com/xfj/frameworktest/aspect/TimeAspect.java new file mode 100644 index 0000000..9f310c3 --- /dev/null +++ b/frameworktest/src/main/java/com/xfj/frameworktest/aspect/TimeAspect.java @@ -0,0 +1,35 @@ +package com.xfj.frameworktest.aspect; + +import simple.xfj.framework.annotation.Aspect; +import simple.xfj.framework.annotation.Controller; +import simple.xfj.framework.annotation.Execution; +import simple.xfj.framework.proxy.AspectProxy; + +import java.lang.reflect.Method; + +/** + * Created by asus on 2017/4/20. + */ +@Aspect(value = Controller.class)//声明这个类是增强类,并且去拦截被所有被controller标注的类的方法 +//@Execution(value = "com.xfj.frameworktest.*find.*") //com.xfj.frameworktest包下所有类以good开头的方法 +public class TimeAspect extends AspectProxy{ + @Override + public void before(Class cls, Method method, Object[] params) throws Throwable { + super.before(cls, method, params); + System.out.println(cls.getName() + "." + method.getName()); + System.out.println("前置增强"); + System.out.println(System.currentTimeMillis()); + } + + @Override + public void after(Class cls, Method method, Object[] params, Object result) throws Throwable { + super.after(cls, method, params, result); + System.out.println("后置增强"); + System.out.println(cls.getName() + "." + method.getName()); + System.out.println(System.currentTimeMillis()); + } + + public static void main(String[] agrs){ + System.out.println(AspectProxy.class.isAssignableFrom(TimeAspect.class)); + } +} diff --git a/frameworktest/src/main/java/com/xfj/frameworktest/controller/CartController.java b/frameworktest/src/main/java/com/xfj/frameworktest/controller/CartController.java new file mode 100644 index 0000000..496fba8 --- /dev/null +++ b/frameworktest/src/main/java/com/xfj/frameworktest/controller/CartController.java @@ -0,0 +1,50 @@ +package com.xfj.frameworktest.controller; + +import com.xfj.frameworktest.pojo.Student; +import com.xfj.frameworktest.service.CartService; +import simple.xfj.framework.annotation.Action; +import simple.xfj.framework.annotation.Autowired; +import simple.xfj.framework.annotation.Controller; +import simple.xfj.framework.bean.Data; +import simple.xfj.framework.bean.Param; +import simple.xfj.framework.bean.View; +import simple.xfj.framework.constant.RequestMethod; + +/** + * Created by asus on 2017/4/18. + */ +@Controller +public class CartController { + + private static int i = 0; + + @Autowired + private CartService cartService; + + @Action(value = "/helloworld",method = RequestMethod.GET) + public View getRequest(Param param){ + Student s = new Student("xfh",24); + Data data = new Data(); + data.setModel(s); + View view = new View("error.jsp",null); + return view; + } + + @Action(value = "/findname",method = RequestMethod.GET) + public Data findName(Param param){ + Student s = new Student("xfh",25); + Data data = new Data(); + data.setModel(s); + System.out.println(i++); + return data; + } + + public CartService getCartService() { + return cartService; + } + + public void setCartService(CartService cartService) { + this.cartService = cartService; + } + +} diff --git a/frameworktest/src/main/java/com/xfj/frameworktest/pojo/Student.java b/frameworktest/src/main/java/com/xfj/frameworktest/pojo/Student.java new file mode 100644 index 0000000..3e7492b --- /dev/null +++ b/frameworktest/src/main/java/com/xfj/frameworktest/pojo/Student.java @@ -0,0 +1,34 @@ +package com.xfj.frameworktest.pojo; + +import java.io.InputStream; + +/** + * Created by asus on 2017/4/19. + */ +public class Student { + + private String name; + + private Integer age; + + public Student(String name, Integer age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } +} diff --git a/frameworktest/src/main/java/com/xfj/frameworktest/service/CartService.java b/frameworktest/src/main/java/com/xfj/frameworktest/service/CartService.java new file mode 100644 index 0000000..e5a8d12 --- /dev/null +++ b/frameworktest/src/main/java/com/xfj/frameworktest/service/CartService.java @@ -0,0 +1,15 @@ +package com.xfj.frameworktest.service; + +import simple.xfj.framework.annotation.Service; + +/** + * Created by asus on 2017/4/18. + */ +@Service +public class CartService { + + public void xfindUserByName(){ + + } + +} diff --git a/frameworktest/src/main/java/com/xfj/frameworktest/service/StudentService.java b/frameworktest/src/main/java/com/xfj/frameworktest/service/StudentService.java new file mode 100644 index 0000000..147b58e --- /dev/null +++ b/frameworktest/src/main/java/com/xfj/frameworktest/service/StudentService.java @@ -0,0 +1,11 @@ +package com.xfj.frameworktest.service; + +/** + * Created by asus on 2017/4/21. + */ +public class StudentService { + + public void xfindStudentById(){ + + } +} diff --git a/frameworktest/src/main/java/com/xfj/frameworktest/util/world.java b/frameworktest/src/main/java/com/xfj/frameworktest/util/world.java deleted file mode 100644 index dd431c2..0000000 --- a/frameworktest/src/main/java/com/xfj/frameworktest/util/world.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.xfj.frameworktest.util; - -/** - * Created by asus on 2017/4/18. - */ -public class world { -} diff --git a/frameworktest/src/test/java/PropertiesLoadTest.java b/frameworktest/src/test/java/PropertiesLoadTest.java index 8b0b814..a7b5a7b 100644 --- a/frameworktest/src/test/java/PropertiesLoadTest.java +++ b/frameworktest/src/test/java/PropertiesLoadTest.java @@ -1,11 +1,19 @@ +import com.xfj.frameworktest.controller.CartController; +import com.xfj.frameworktest.service.CartService; import org.junit.Before; import org.junit.Test; +import simple.xfj.framework.bean.Handler; +import simple.xfj.framework.bean.Request; import simple.xfj.framework.constant.ConfigConstant; +import simple.xfj.framework.helper.BeanHelper; import simple.xfj.framework.helper.ClassHelper; +import simple.xfj.framework.helper.ControllerHelper; +import simple.xfj.framework.helper.IocHelper; import simple.xfj.framework.util.ClassUtil; import simple.xfj.framework.util.PropsUtil; import java.io.IOException; +import java.util.Map; import java.util.Properties; import java.util.Set; @@ -44,4 +52,45 @@ public void testGetControllerBean(){ } } + + + /** + * 测试cartservice是否依赖注入到cartcontroller中 + */ + @Test + public void testFrameWorkIOC()throws Exception{ + Set> beanSet = ClassHelper.getBeanSet(); + ClassUtil.loadClass(IocHelper.class.getName(),true); + Map, Object> beanMap = BeanHelper.getBeanMap(); + Set> keys = BeanHelper.getBeanMap().keySet(); + for(Class clazz : keys){ + System.out.println(clazz.getName()); + System.out.println(beanMap.get(clazz)); + } + CartController cartController = (CartController) beanMap.get(CartController.class); + System.out.println(cartController.getCartService() == beanMap.get(CartService.class) ); + } + + @Test + public void testControllerHelper(){ + ClassUtil.loadClass(ControllerHelper.class.getName(),true); + Map actionMap = ControllerHelper.getActionMap(); + Set keys = actionMap.keySet(); + for(Request re : keys){ + System.out.println(re.getRequestPath()); + System.out.println(re.getRequestMethod()); + System.out.println(actionMap.get(re).getControllerClass().getName()); + System.out.println(actionMap.get(re).getActionMethod().getName()); + } + } + + @Test + public void testRegexMatchClass(){ + ClassUtil.loadClass(ClassHelper.class.getName(),true); + Set> classSet = ClassHelper.getClassSetByMatchMethodName("com.xfj.frameworktest.*find.*"); + for(Class cls : classSet){ + System.out.println(cls.getName()); + } + } + } diff --git a/pom.xml b/pom.xml index 337dc02..779eaef 100644 --- a/pom.xml +++ b/pom.xml @@ -77,6 +77,12 @@ commons-dbcp 1.4 + + + cglib + cglib + 2.2.2 + diff --git a/src/main/java/simple/xfj/framework/DispatcherServlet.java b/src/main/java/simple/xfj/framework/DispatcherServlet.java new file mode 100644 index 0000000..cd5da93 --- /dev/null +++ b/src/main/java/simple/xfj/framework/DispatcherServlet.java @@ -0,0 +1,130 @@ +package simple.xfj.framework; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import simple.xfj.framework.bean.*; +import simple.xfj.framework.bootstarp.HelperInitiler; +import simple.xfj.framework.helper.BeanHelper; +import simple.xfj.framework.helper.ConfigHelper; +import simple.xfj.framework.helper.ControllerHelper; +import simple.xfj.framework.util.DEcodeUtil; +import simple.xfj.framework.util.JsonUtil; +import simple.xfj.framework.util.ReflectionUtil; +import simple.xfj.framework.util.StreamUtil; + +import javax.servlet.*; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by asus on 2017/4/18. + */ +@WebServlet(urlPatterns = "/*",loadOnStartup = 0) +public class DispatcherServlet extends HttpServlet{ + + private static final Logger LOGGER = LoggerFactory.getLogger(DispatcherServlet.class); + + @Override + public void init(ServletConfig config) throws ServletException { + System.out.println("servlet start"); + //容器初始化 + HelperInitiler.init(); + ServletContext context = config.getServletContext(); + ServletRegistration jspServlet = context.getServletRegistration("jsp"); + jspServlet.addMapping(ConfigHelper.getAPPJspPath() + "*"); + ServletRegistration defaultServlet = context.getServletRegistration("default"); + defaultServlet.addMapping(ConfigHelper.getAPPAsset() + "*"); + } + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String method = req.getMethod().toLowerCase(); + String requestPath = req.getPathInfo(); + Request request = new Request(method,requestPath); + Handler handler = ControllerHelper.getActionMap().get(request); + if(null != handler){ + Class handlerClass = handler.getControllerClass(); + Object handlerBean = BeanHelper.getClassBean(handlerClass); + //创建param + Param param = getParam(req); + Object res = ReflectionUtil.methodInvoke(handler.getActionMethod(), handlerBean, param); + try { + doResult(req,resp,res); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private Param getParam(HttpServletRequest req){ + Map paramMap = new HashMap(); + //URL中的参数收集 + Enumeration paramNames = req.getParameterNames(); + while (paramNames.hasMoreElements()){ + String name = paramNames.nextElement(); + String value = req.getParameter(name); + paramMap.put(name,value); + } + //form表单中的参数收集 + try { + String StringParam = DEcodeUtil.Decode(StreamUtil.getStringFromStream(req.getInputStream())); + if(StringParam.length() == 0) + return new Param(paramMap); + String[] nameValue = StringParam.split("&"); + if(nameValue != null && nameValue.length > 0){ + for(int i = 0; i < nameValue.length;i++){ + String[] pair = nameValue[i].split("="); + paramMap.put(pair[0],pair[1]); + } + } + } catch (IOException e) { + LOGGER.error("read param from Stream failure"); + throw new RuntimeException(e); + } + return new Param(paramMap); + } + + + private void doResult(HttpServletRequest req,HttpServletResponse pon,Object res) throws Exception{ + if(res == null){ + req.getRequestDispatcher(ConfigHelper.getAPPJspPath() + "error.jsp").forward(req,pon); + } + if(res instanceof View){ + View view = (View) res; + String path = view.getPath(); + if(path != null && path.length() > 0){ + if(path.startsWith("/")){ + pon.sendRedirect(req.getContextPath() + path); + }else{ + Map model = view.getModel(); + if(model != null && model.size()>0){ + for(Map.Entry ele : model.entrySet()){ + req.setAttribute(ele.getKey(),ele.getValue()); + } + } + req.getRequestDispatcher(ConfigHelper.getAPPJspPath() + path).forward(req,pon); + } + } + }else if(res instanceof Data){ + //返回json数据 + Data data = (Data) res; + Object model = data.getModel(); + if(null != model){ + pon.setContentType("application/json"); + pon.setCharacterEncoding("UTF-8"); + PrintWriter writer = pon.getWriter(); + String json = JsonUtil.ObjToStr(model); + writer.write(json); + writer.flush(); + writer.close(); + } + } + } +} diff --git a/src/main/java/simple/xfj/framework/annotation/Action.java b/src/main/java/simple/xfj/framework/annotation/Action.java index 6d59fe5..4a83787 100644 --- a/src/main/java/simple/xfj/framework/annotation/Action.java +++ b/src/main/java/simple/xfj/framework/annotation/Action.java @@ -12,4 +12,5 @@ @Retention(RetentionPolicy.RUNTIME) public @interface Action { String value(); + String method(); } diff --git a/src/main/java/simple/xfj/framework/annotation/Aspect.java b/src/main/java/simple/xfj/framework/annotation/Aspect.java new file mode 100644 index 0000000..9be635b --- /dev/null +++ b/src/main/java/simple/xfj/framework/annotation/Aspect.java @@ -0,0 +1,12 @@ +package simple.xfj.framework.annotation; + +import java.lang.annotation.*; + +/** + * Created by asus on 2017/4/20. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Aspect { + Class value(); +} diff --git a/src/main/java/simple/xfj/framework/annotation/Execution.java b/src/main/java/simple/xfj/framework/annotation/Execution.java new file mode 100644 index 0000000..ce30757 --- /dev/null +++ b/src/main/java/simple/xfj/framework/annotation/Execution.java @@ -0,0 +1,16 @@ +package simple.xfj.framework.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Created by asus on 2017/4/21. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Execution +{ + String value(); +} diff --git a/src/main/java/simple/xfj/framework/bean/Data.java b/src/main/java/simple/xfj/framework/bean/Data.java new file mode 100644 index 0000000..17a75cf --- /dev/null +++ b/src/main/java/simple/xfj/framework/bean/Data.java @@ -0,0 +1,17 @@ +package simple.xfj.framework.bean; + +/** + * Created by asus on 2017/4/18. + */ +public class Data { + + private Object model; + + public Object getModel() { + return model; + } + + public void setModel(Object model) { + this.model = model; + } +} diff --git a/src/main/java/simple/xfj/framework/bean/Handler.java b/src/main/java/simple/xfj/framework/bean/Handler.java new file mode 100644 index 0000000..f8ed842 --- /dev/null +++ b/src/main/java/simple/xfj/framework/bean/Handler.java @@ -0,0 +1,34 @@ +package simple.xfj.framework.bean; + +import java.lang.reflect.Method; + +/** + * Created by asus on 2017/4/18. + */ +public class Handler { + + private Class controllerClass; + + private Method actionMethod; + + public Handler(Class controllerClass, Method actionMethod) { + this.controllerClass = controllerClass; + this.actionMethod = actionMethod; + } + + public Class getControllerClass() { + return controllerClass; + } + + public void setControllerClass(Class controllerClass) { + this.controllerClass = controllerClass; + } + + public Method getActionMethod() { + return actionMethod; + } + + public void setActionMethod(Method actionMethod) { + this.actionMethod = actionMethod; + } +} diff --git a/src/main/java/simple/xfj/framework/bean/Param.java b/src/main/java/simple/xfj/framework/bean/Param.java new file mode 100644 index 0000000..c192087 --- /dev/null +++ b/src/main/java/simple/xfj/framework/bean/Param.java @@ -0,0 +1,20 @@ +package simple.xfj.framework.bean; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by asus on 2017/4/18. + */ +public class Param { + + private Map paramMap = new HashMap(); + + public Param(Map paramMap) { + this.paramMap = paramMap; + } + + public Map getParamMap() { + return paramMap; + } +} diff --git a/src/main/java/simple/xfj/framework/bean/RegexSet.java b/src/main/java/simple/xfj/framework/bean/RegexSet.java new file mode 100644 index 0000000..8419010 --- /dev/null +++ b/src/main/java/simple/xfj/framework/bean/RegexSet.java @@ -0,0 +1,34 @@ +package simple.xfj.framework.bean; + +import java.util.Set; + +/** + * Created by asus on 2017/4/21. + */ +public class RegexSet{ + String regex; + + Set> classSet; + + public RegexSet(String regex, Set> classSet) { + this.regex = regex; + this.classSet = classSet; + } + + + public String getRegex() { + return regex; + } + + public void setRegex(String regex) { + this.regex = regex; + } + + public Set> getClassSet() { + return classSet; + } + + public void setClassSet(Set> classSet) { + this.classSet = classSet; + } +} diff --git a/src/main/java/simple/xfj/framework/bean/Request.java b/src/main/java/simple/xfj/framework/bean/Request.java new file mode 100644 index 0000000..2798b5e --- /dev/null +++ b/src/main/java/simple/xfj/framework/bean/Request.java @@ -0,0 +1,53 @@ +package simple.xfj.framework.bean; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Created by asus on 2017/4/18. + */ +public class Request { + + private String requestMethod; + + private String requestPath; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Request request = (Request) o; + + if (!requestMethod.equals(request.requestMethod)) return false; + return requestPath.equals(request.requestPath); + } + + @Override + public int hashCode() { + int result = requestMethod.hashCode(); + result = 31 * result + requestPath.hashCode(); + return result; + } + + public String getRequestMethod() { + return requestMethod; + } + + public void setRequestMethod(String requestMethod) { + this.requestMethod = requestMethod; + } + + public String getRequestPath() { + return requestPath; + } + + public void setRequestPath(String requestPath) { + this.requestPath = requestPath; + } + + public Request(String requestMethod, String requestPath) { + this.requestMethod = requestMethod; + this.requestPath = requestPath; + } +} diff --git a/src/main/java/simple/xfj/framework/bean/View.java b/src/main/java/simple/xfj/framework/bean/View.java new file mode 100644 index 0000000..2fa2a4d --- /dev/null +++ b/src/main/java/simple/xfj/framework/bean/View.java @@ -0,0 +1,46 @@ +package simple.xfj.framework.bean; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by asus on 2017/4/18. + */ +public class View { + + //返回视图路径 + private String path; + + //返回时所携带的数据模型 + private Map model; + + public View(String path, Map model) { + this.path = path; + this.model = model; + } + + public View() { + + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Map getModel() { + return model; + } + + public void addMode(String key,Object obj){ + if(model == null){ + model = new HashMap(); + model.put(key,obj); + }else { + model.put(key,obj); + } + } +} diff --git a/src/main/java/simple/xfj/framework/bootstarp/HelperInitiler.java b/src/main/java/simple/xfj/framework/bootstarp/HelperInitiler.java new file mode 100644 index 0000000..6d4797b --- /dev/null +++ b/src/main/java/simple/xfj/framework/bootstarp/HelperInitiler.java @@ -0,0 +1,29 @@ +package simple.xfj.framework.bootstarp; + +import simple.xfj.framework.annotation.Controller; +import simple.xfj.framework.helper.AopHelper; +import simple.xfj.framework.helper.BeanHelper; +import simple.xfj.framework.helper.ClassHelper; +import simple.xfj.framework.helper.IocHelper; +import simple.xfj.framework.util.ClassUtil; + +/** + * Created by asus on 2017/4/18. + */ +public class HelperInitiler { + + public static void init(){ + Class[] clazzs = new Class[]{ + ClassHelper.class, + BeanHelper.class, + AopHelper.class,// AopHelper要在beanHelper之后,IocHelper之前初始化 + IocHelper.class, + Controller.class + }; + + for(int i = 0;i < clazzs.length;i++){ + ClassUtil.loadClass(clazzs[i].getName(),true); + } + } + +} diff --git a/src/main/java/simple/xfj/framework/constant/RequestMethod.java b/src/main/java/simple/xfj/framework/constant/RequestMethod.java new file mode 100644 index 0000000..12b26c9 --- /dev/null +++ b/src/main/java/simple/xfj/framework/constant/RequestMethod.java @@ -0,0 +1,14 @@ +package simple.xfj.framework.constant; + +/** + * Created by asus on 2017/4/18. + */ +public final class RequestMethod { + + public static final String GET = "get"; + + public static final String POST = "post"; + + + +} diff --git a/src/main/java/simple/xfj/framework/helper/AopHelper.java b/src/main/java/simple/xfj/framework/helper/AopHelper.java new file mode 100644 index 0000000..55be708 --- /dev/null +++ b/src/main/java/simple/xfj/framework/helper/AopHelper.java @@ -0,0 +1,134 @@ +package simple.xfj.framework.helper; + +import simple.xfj.framework.annotation.Aspect; +import simple.xfj.framework.annotation.Execution; +import simple.xfj.framework.bean.RegexSet; +import simple.xfj.framework.proxy.AspectProxy; +import simple.xfj.framework.proxy.Proxy; +import simple.xfj.framework.proxy.ProxyManager; +import simple.xfj.framework.util.ReflectionUtil; + +import java.lang.annotation.Annotation; +import java.util.*; + +/** + * Created by asus on 2017/4/20. + */ +public class AopHelper { + + static { + //类加载时初始化AOP,并将其设置到Bean中 + Map, List> target2ProxyList = getTarget2ProxyList(); + if(null != target2ProxyList && target2ProxyList.size() > 0){ + Set, List>> entries = target2ProxyList.entrySet(); + for(Map.Entry, List> entry: entries){ + Class clazz = entry.getKey(); + List proxyList = entry.getValue(); + Object bean = ProxyManager.getProxy(clazz, proxyList); + BeanHelper.setBean(clazz,bean); + } + } + } + + /** + * 获取切面要去增强的所有类 + * @param aspect + * @return + */ + private static RegexSet getTargetClassSet(Aspect aspect){ + Set> targetClass = new HashSet>(); + if(aspect != null){ + Class annotation = aspect.value(); + if(annotation != null && !annotation.equals(Aspect.class)){ + Set> classSetByAnnoation = ClassHelper.getClassSetByAnnoation(annotation); + targetClass.addAll(classSetByAnnoation); + } + } + if(targetClass != null && targetClass.size() > 0){ + return new RegexSet(null,targetClass); + } + return null; + } + + + private static RegexSet getTargetClassSetByRegex(Execution execution){ + if(null != execution){ + String regex = execution.value(); + if(regex != null && regex.length() > 0){ + Set> classSet = ClassHelper.getClassSetByMatchMethodName(regex); + if(classSet != null && classSet.size()>0){ + return new RegexSet(regex,classSet); + } + } + } + return null; + } + + /** + * 获取所有的切面类aspest与目标类的映射关系 + */ + + private static Map, RegexSet> getAspect2Target(){ + Map, RegexSet> proxyMap = new HashMap, RegexSet>(); + Set> aspectClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class); + for(Class clazz : aspectClassSet){ + if(clazz.isAnnotationPresent(Aspect.class)){ + Aspect aspect = (Aspect)clazz.getAnnotation(Aspect.class); + RegexSet regexAllSet = getTargetClassSet(aspect); + proxyMap.put(clazz,regexAllSet); + } + if(clazz.isAnnotationPresent(Execution.class)){ + Execution execution = (Execution)clazz.getAnnotation(Execution.class); + RegexSet regexStringSet = getTargetClassSetByRegex(execution); + proxyMap.put(clazz,regexStringSet); // classSet 与 regexClassSet可能会有重复 + } + } + return proxyMap; + } + + /** + * 将每个目标类所需要增强的增强类整理成1对多的map集合以便在beanHelper中用去取代原来的原始bean + * @return + */ + private static Map,List> getTarget2ProxyList(){ + Map,List> clazz4Proxy = new HashMap, List>(); + Map, RegexSet> aspect2Target = getAspect2Target(); + Set, RegexSet>> entries = aspect2Target.entrySet(); + for(Map.Entry, RegexSet> entry : entries){ + Class proxyClass = entry.getKey(); + RegexSet targetSet = entry.getValue(); + if(targetSet != null){ + String regex = targetSet.getRegex(); + Set> classes = targetSet.getClassSet(); + if(classes != null && classes.size() >0){ + for(Class cls : classes){ + List proxies = clazz4Proxy.get(cls); + if(null == proxies){ + proxies = new ArrayList(); + Proxy reproxy = ReflectionUtil.newInstance(proxyClass); + reproxy.setRegex(regex); + proxies.add(reproxy); + clazz4Proxy.put(cls,proxies); + }else{ + Proxy reproxy = ReflectionUtil.newInstance(proxyClass); + reproxy.setRegex(regex); + proxies.add(reproxy); + } + } + } + } + /* for(Class cls : targetSet){ + List proxies = clazz4Proxy.get(cls); + if(null == proxies){ + proxies = new ArrayList(); + proxies.add(ReflectionUtil.newInstance(proxyClass)); + clazz4Proxy.put(cls,proxies); + }else{ + proxies.add(ReflectionUtil.newInstance(proxyClass)); + } + }*/ + } + return clazz4Proxy; + } + +} diff --git a/src/main/java/simple/xfj/framework/helper/BeanHelper.java b/src/main/java/simple/xfj/framework/helper/BeanHelper.java index 4f0e285..5bebaa8 100644 --- a/src/main/java/simple/xfj/framework/helper/BeanHelper.java +++ b/src/main/java/simple/xfj/framework/helper/BeanHelper.java @@ -36,4 +36,9 @@ public static T getClassBean(Class clazz){ } return null; } + + public static void setBean(Class clazz,Object object){ + //用于在aop生成代理类后,替换bean容器里的原有目标类, + beanMap.put(clazz,object); + } } diff --git a/src/main/java/simple/xfj/framework/helper/ClassHelper.java b/src/main/java/simple/xfj/framework/helper/ClassHelper.java index 3415180..4fdc971 100644 --- a/src/main/java/simple/xfj/framework/helper/ClassHelper.java +++ b/src/main/java/simple/xfj/framework/helper/ClassHelper.java @@ -10,8 +10,11 @@ import simple.xfj.framework.annotation.Service; import simple.xfj.framework.util.ClassUtil; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; +import java.util.regex.Pattern; /** * 获取指定包名下的各种注解类的helper类 @@ -76,4 +79,62 @@ public static Set> getBeanSet(){ return beanSet; } + + /** + * 获得某个父类下的所有子类 + * @param clazz + * @return + */ + public static Set> getClassSetBySuper(Class clazz){ + Set> classSet = new HashSet>(); + for(Class cls : CLAZZ_SET){ + if(clazz.isAssignableFrom(cls) && !cls.equals(clazz)){ + classSet.add(cls); + } + } + return classSet; + } + + /** + * 获取被某个注解注释的类 + * @param annoationClass + * @return + */ + public static Set> getClassSetByAnnoation(Class annoationClass){ + Set> classSet = new HashSet>(); + for(Class cls : CLAZZ_SET){ + if(cls.isAnnotationPresent(annoationClass)){ + classSet.add(cls); + } + } + return classSet; + } + + + /** + * 根据正则选取正则匹配方法名的class类 + * @param regex + * @return + */ + public static Set> getClassSetByMatchMethodName(String regex){ + Set> classSet = new HashSet>(); + Pattern pattern = Pattern.compile(regex); + for(Class cls : CLAZZ_SET){ + String clsName = cls.getName(); + Method[] methods = cls.getDeclaredMethods(); + if(methods != null && methods.length > 0){ + for(Method method : methods){ + String methodName = clsName + "." + method.getName().toLowerCase(); + if(pattern.matcher(methodName).matches()){ + classSet.add(cls); + //只要添加一次就可以了 + break; + } + } + } + } + return classSet; + } + + } diff --git a/src/main/java/simple/xfj/framework/helper/ControllerHelper.java b/src/main/java/simple/xfj/framework/helper/ControllerHelper.java new file mode 100644 index 0000000..c75b563 --- /dev/null +++ b/src/main/java/simple/xfj/framework/helper/ControllerHelper.java @@ -0,0 +1,49 @@ +package simple.xfj.framework.helper; + +import simple.xfj.framework.annotation.Action; +import simple.xfj.framework.bean.Handler; +import simple.xfj.framework.bean.Request; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Created by asus on 2017/4/18. + */ +public final class ControllerHelper { + + /** + * 存放请求路径与处理器之间的映射关系 + */ + private static Map ACTION_MAP = new HashMap(); + + static { + Set> controllerSet = ClassHelper.getControllerSet(); + if(null != controllerSet && controllerSet.size() > 0){ + for(Class clazz : controllerSet){ + Method[] methods = clazz.getMethods(); + if(null != methods && methods.length > 0){ + for(Method method: methods){ + if(method.isAnnotationPresent(Action.class)){ + Action action = method.getAnnotation(Action.class); + String mapping = action.value(); + if(mapping.matches("^/.*") ){ + Request request = new Request(action.method(),mapping); + Handler handler = new Handler(clazz,method); + //将请求路径与处理的类的方法一一对应,联系起来 + ACTION_MAP.put(request,handler); + } + } + } + } + } + } + } + + public static Map getActionMap() { + return ACTION_MAP; + } +} diff --git a/src/main/java/simple/xfj/framework/proxy/AspectProxy.java b/src/main/java/simple/xfj/framework/proxy/AspectProxy.java new file mode 100644 index 0000000..86c671f --- /dev/null +++ b/src/main/java/simple/xfj/framework/proxy/AspectProxy.java @@ -0,0 +1,80 @@ +package simple.xfj.framework.proxy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; +import java.util.regex.Pattern; + +/** + * Created by asus on 2017/4/20. + */ +public class AspectProxy extends Proxy{ + + + private static final Logger LOGGER = LoggerFactory.getLogger(AspectProxy.class); + + public Object doProxy(ProxyChain proxyChain) throws Throwable { + Object res = null; + Class targetClass = proxyChain.getTargetClass(); + Object[] methodParams = proxyChain.getMethodParams(); + Method targetMethod = proxyChain.getTargetMethod(); + begin(); + try{ + if(intercept(targetClass,targetMethod,methodParams)){ + before(targetClass,targetMethod,methodParams); + res = proxyChain.doProxyChain(); + after(targetClass,targetMethod,methodParams,res); + }else{ + res = proxyChain.doProxyChain(); + } + }catch (Exception e){ + LOGGER.error("invoke method chain proxy error" + targetMethod.getName()); + throw e; + }finally { + end(); + } + return res; + } + public void begin(){ + + } + + public boolean intercept(Class cls,Method method,Object[] params) throws Throwable{ + if(super.getRegex() == null) { + //对@Aspect注解的类的所有方法进行增强,其他的如@Execution的注解进行拦截判断 + Method[] declaredMethods = cls.getDeclaredMethods(); + if(null != declaredMethods && declaredMethods.length > 0){ + for(int i = 0;i< declaredMethods.length;i++){ + if(method.equals(declaredMethods[i])) + //只对自己声明的方法进行增强 + return true; + } + return false; + } + }else { + String regex = super.getRegex(); + Pattern pattern = Pattern.compile(regex); + String compileMethodName = cls.getName() + "." + method.getName().toLowerCase(); + if(pattern.matcher(compileMethodName).matches()){ + return true; + }else + return false; + } + return false; + } + + public void before(Class cls,Method method,Object[] params) throws Throwable{ + System.out.println("ni hao"); + + } + + public void after(Class cls,Method method,Object[] params,Object result) throws Throwable{ + System.out.println("ni huai"); + } + public void end(){ + + } + + +} diff --git a/src/main/java/simple/xfj/framework/proxy/Proxy.java b/src/main/java/simple/xfj/framework/proxy/Proxy.java new file mode 100644 index 0000000..9d47a46 --- /dev/null +++ b/src/main/java/simple/xfj/framework/proxy/Proxy.java @@ -0,0 +1,19 @@ +package simple.xfj.framework.proxy; + +/** + * Created by asus on 2017/4/20. + */ +public abstract class Proxy { + + private String regex; + + public abstract Object doProxy(ProxyChain proxyChain) throws Throwable; + + public String getRegex() { + return regex; + } + + public void setRegex(String regex) { + this.regex = regex; + } +} diff --git a/src/main/java/simple/xfj/framework/proxy/ProxyChain.java b/src/main/java/simple/xfj/framework/proxy/ProxyChain.java new file mode 100644 index 0000000..bc1592a --- /dev/null +++ b/src/main/java/simple/xfj/framework/proxy/ProxyChain.java @@ -0,0 +1,60 @@ +package simple.xfj.framework.proxy; + +import net.sf.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by asus on 2017/4/20. + */ +public class ProxyChain { + + private final Class targetClass; + private final Object target; + private final Method targetMethod; + private final MethodProxy methodProxy; + private final Object[] methodParams; + + private List proxyList = new ArrayList(); + + private int proxyIndex = 0; + + public ProxyChain(Class targetClass, Object target, Method targetMethod, MethodProxy methodProxy, Object[] methodParams) { + this.targetClass = targetClass; + this.target = target; + this.targetMethod = targetMethod; + this.methodProxy = methodProxy; + this.methodParams = methodParams; + } + + public Class getTargetClass() { + return targetClass; + } + + public Method getTargetMethod() { + return targetMethod; + } + + public Object[] getMethodParams() { + return methodParams; + } + + public ProxyChain setProxyList(List proxyList){ + this.proxyList = proxyList; + return this; + } + + public Object doProxyChain() throws Throwable{ + Object res = null; + if(null != proxyList && proxyIndex < proxyList.size()){ + //将链条中的代理一个一个的添加到代理方法中 + res = proxyList.get(proxyIndex++).doProxy(this); + }else{ + res = methodProxy.invokeSuper(target,methodParams); + } + return res; + } + +} diff --git a/src/main/java/simple/xfj/framework/proxy/ProxyManager.java b/src/main/java/simple/xfj/framework/proxy/ProxyManager.java new file mode 100644 index 0000000..f7e45f9 --- /dev/null +++ b/src/main/java/simple/xfj/framework/proxy/ProxyManager.java @@ -0,0 +1,24 @@ +package simple.xfj.framework.proxy; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; +import java.util.List; + +/** + * Created by asus on 2017/4/20. + */ +public class ProxyManager { + + //产生代理的管理类 + public static T getProxy(final Class clazz , final List proxyList){ + return (T)Enhancer.create(clazz, new MethodInterceptor() { + public Object intercept(Object target, Method method, Object[] agrs, MethodProxy methodProxy) throws Throwable { + return new ProxyChain(clazz,target,method,methodProxy,agrs).setProxyList(proxyList).doProxyChain(); + } + }); + } + +} diff --git a/src/main/java/simple/xfj/framework/util/ClassUtil.java b/src/main/java/simple/xfj/framework/util/ClassUtil.java index 62dd22d..5bbabce 100644 --- a/src/main/java/simple/xfj/framework/util/ClassUtil.java +++ b/src/main/java/simple/xfj/framework/util/ClassUtil.java @@ -92,6 +92,10 @@ private static void addClass(Set> set,String packagePath,String package public boolean accept(File f) { return f.isFile() && f.getName().endsWith(".class") || f.isDirectory(); }}); + //如果有空文件夹 需要跳过考虑 + if(files == null || files.length == 0){ + return; + } for(File f: files){ String fileName = f.getName(); if(f.isFile()){ @@ -102,12 +106,13 @@ public boolean accept(File f) { doAddClass(set,className); }else { //如果存在子文件夹,则递归读取子文件夹下的所有class文件,并加载 - String subPackageName = fileName; + String subPackageName = null; + String subPackagePath = null; if(packageName != null && packageName.length() >0){ - packageName = packageName + "." + subPackageName; - packagePath = packagePath + "/" + subPackageName; + subPackageName = packageName + "." + fileName; + subPackagePath = packagePath + "/" + fileName; } - addClass(set,packagePath,packageName); + addClass(set,subPackagePath,subPackageName); } } } diff --git a/src/main/java/simple/xfj/framework/util/DEcodeUtil.java b/src/main/java/simple/xfj/framework/util/DEcodeUtil.java new file mode 100644 index 0000000..0dada73 --- /dev/null +++ b/src/main/java/simple/xfj/framework/util/DEcodeUtil.java @@ -0,0 +1,42 @@ +package simple.xfj.framework.util; + +import com.sun.org.apache.xml.internal.utils.StringToStringTableVector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; + +/** + * Created by asus on 2017/4/19. + */ +public class DEcodeUtil { + + private static final Logger LOGGER = LoggerFactory.getLogger(DEcodeUtil.class); + + public static final String Decode(String str){ + String res = null; + try { + /* byte[] bytes = str.getBytes("ISO8859-1"); + res = new String(bytes, "GBK");*/ + res = URLDecoder.decode(str,"UTF-8"); + } catch (UnsupportedEncodingException e) { + LOGGER.error("decode String error"); + throw new RuntimeException(e); + } + return res; + } + + public static final String Encode(String str){ + try { + str = URLEncoder.encode(str,"ISO8859-1"); + } catch (UnsupportedEncodingException e) { + LOGGER.error("encode String error"); + throw new RuntimeException(e); + } + return str; + } + + +} diff --git a/src/main/java/simple/xfj/framework/util/JsonUtil.java b/src/main/java/simple/xfj/framework/util/JsonUtil.java new file mode 100644 index 0000000..ab0574b --- /dev/null +++ b/src/main/java/simple/xfj/framework/util/JsonUtil.java @@ -0,0 +1,41 @@ +package simple.xfj.framework.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * Created by asus on 2017/4/19. + */ +public class JsonUtil { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class); + + public static final String ObjToStr(Object object){ + String res = null; + try { + res = MAPPER.writeValueAsString(object); + } catch (JsonProcessingException e) { + LOGGER.error("transform object to json string failure"); + throw new RuntimeException(e); + } + return res; + } + + public static final T strToObj(String str,Class clazz){ + T t = null; + try { + t = MAPPER.readValue(str,clazz); + } catch (IOException e) { + LOGGER.error("parse json to obj string failure"); + throw new RuntimeException(e); + } + return t; + } + +} diff --git a/src/main/java/simple/xfj/framework/util/ReflectionUtil.java b/src/main/java/simple/xfj/framework/util/ReflectionUtil.java index 4e54eec..d2a022c 100644 --- a/src/main/java/simple/xfj/framework/util/ReflectionUtil.java +++ b/src/main/java/simple/xfj/framework/util/ReflectionUtil.java @@ -15,7 +15,7 @@ public class ReflectionUtil { private static Logger LOGGER = LoggerFactory.getLogger(ReflectionUtil.class); - public static Object newInstance(Class clazz){ + public static T newInstance(Class clazz){ Object obj = null; try { obj = clazz.newInstance(); @@ -23,19 +23,19 @@ public static Object newInstance(Class clazz){ LOGGER.error("can new " + clazz.getName()); throw new RuntimeException(e); } - return obj; + return (T)obj; } public static Object methodInvoke(Method method,Object obj,Object... args){ Object result = null; if(!method.isAccessible()){ method.setAccessible(true); - try { - result = method.invoke(obj,args); - } catch (Exception e) { - LOGGER.error("can not invoke method:" + method.getName()); - throw new RuntimeException("invoke method failure:" + method.getName()); - } + } + try { + result = method.invoke(obj,args); + } catch (Exception e) { + LOGGER.error("can not invoke method:" + method.getName()); + throw new RuntimeException("invoke method failure:" + method.getName()); } return result; } diff --git a/src/main/java/simple/xfj/framework/util/StreamUtil.java b/src/main/java/simple/xfj/framework/util/StreamUtil.java new file mode 100644 index 0000000..1b9e5de --- /dev/null +++ b/src/main/java/simple/xfj/framework/util/StreamUtil.java @@ -0,0 +1,33 @@ +package simple.xfj.framework.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * Created by asus on 2017/4/18. + */ +public class StreamUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(StreamUtil.class); + //从输入流中获得字符串 + public static String getStringFromStream(InputStream in){ + StringBuffer sb = new StringBuffer(); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + String line; + while ((line = reader.readLine())!= null){ + sb.append(line); + } + reader.close(); + in.close(); + }catch (Exception e){ + LOGGER.error("read String from Stream failure"); + throw new RuntimeException(e); + } + return sb.toString(); + } + +}