diff --git a/LICENSE b/LICENSE index 261eeb9..f6f8211 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,5 @@ - Apache License + Apache License + Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -186,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2018 俞晔 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -198,4 +199,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md index 62328dc..7f7fb48 100644 --- a/README.md +++ b/README.md @@ -1 +1,83 @@ -# Mars-java \ No newline at end of file +

Java Web development framework that does not require a container

+ +

+ +
+ +

Introduction to the framework

+ +

First of all, thanks to mybatis, fastjson, cglib, pagehelper, druid, jwt, jyaml, netty, hutool. Because of the integration of these open source projects, my framework can be developed smoothly.

+ +

Goge-framework is a java development framework that mimics springboot. It supports functions similar to springboot: AOP, IOC, MVC also integrates mybatis as a persistence layer. Unlike springboot it is:

+ +

+    + 1. This framework uses netty as the http service +
+    + 2. Session management with JWT +
+    + 3. Only support the main method to start, can not play the war package +
+    + 4. Controller can only return json, does not support forwarding and redirection +

+ +

Document

+ +[Document](http://goge-framework.com/doc.html) + +

Extension package

+ +

Support redis connection

+ +

Encapsulated mail delivery, MD5, AES and other tools class

+ +[Extension package](https://github.com/yuyenews/Goge-extends) + +

Project structure

+ +

Red module is temporarily unavailable

+

+ +

Simple contrast

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
nameAOPIOCMVCmybatisconfiguration filestartup method
GogesupportsupportsupportDirect integrationOnly need onemain method
SpringbootsupportsupportsupportCan be integrationOnly need onemain method,war+tomcat
+ +

Contact

+ +

If you have any questions, you can add my QQ group:773291321

+ +

+ diff --git a/mars-aop/pom.xml b/mars-aop/pom.xml new file mode 100644 index 0000000..57839ff --- /dev/null +++ b/mars-aop/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + com.gitee.sherlockholmnes + Mars-java + 2.1.0 + + mars-aop + + + + com.gitee.sherlockholmnes + mars-core + + + + org.ow2.asm + asm + + + cglib + cglib + + + \ No newline at end of file diff --git a/mars-aop/src/main/java/com/yuyenews/aop/base/BaseAop.java b/mars-aop/src/main/java/com/yuyenews/aop/base/BaseAop.java new file mode 100644 index 0000000..3b28d5f --- /dev/null +++ b/mars-aop/src/main/java/com/yuyenews/aop/base/BaseAop.java @@ -0,0 +1,26 @@ +package com.yuyenews.aop.base; + +/** + * AOP定义模板 + * @author yuye + * + */ +public interface BaseAop { + + /** + * 方法开始前调用 + * @param args 参数 + */ + void startMethod(Object[] args); + + /** + * 方法结束后调用 + * @param args 参数 + */ + void endMethod(Object[] args); + + /** + * 出异常后调用 + */ + void exp(Throwable e); +} diff --git a/mars-aop/src/main/java/com/yuyenews/aop/proxy/CglibProxy.java b/mars-aop/src/main/java/com/yuyenews/aop/proxy/CglibProxy.java new file mode 100644 index 0000000..2793378 --- /dev/null +++ b/mars-aop/src/main/java/com/yuyenews/aop/proxy/CglibProxy.java @@ -0,0 +1,72 @@ +package com.yuyenews.aop.proxy; + +import java.lang.reflect.Method; +import java.util.Map; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/** + * 代理类 + * @author yuye + * + */ +public class CglibProxy implements MethodInterceptor { + + private Enhancer enhancer; + + private Map> list; + + /** + * 获取代理对象 + * @param clazz bean的class + * @param list aop类的class + * @return 对象 + */ + public Object getProxy(Class clazz,Map> list) { + + this.list = list; + enhancer = new Enhancer(); + // 设置需要创建子类的类 + enhancer.setSuperclass(clazz); + enhancer.setCallback(this); + // 通过字节码技术动态创建子类实例 + return enhancer.create(); + } + + + /** + * 绑定代理 + */ + @Override + public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + Object obj = null; + Class c = list.get(method.getName()); + if(c != null){ + obj = c.getDeclaredConstructor().newInstance(); + Method m2 = c.getDeclaredMethod("startMethod",new Class[] {Object[].class}); + m2.invoke(obj,new Object[] {args}); + } + + Object o1 = null; + try { + o1 = methodProxy.invokeSuper(o, args); + + if(c != null){ + Method m3 = c.getDeclaredMethod("endMethod",new Class[] {Object[].class}); + m3.invoke(obj,new Object[] {args}); + } + + return o1; + } catch (Throwable e) { + if(c != null){ + Method m4 = c.getDeclaredMethod("exp",new Class[] {Throwable.class}); + m4.invoke(obj,new Object[] {e}); + } + + throw e; + } + } + +} diff --git a/mars-core/pom.xml b/mars-core/pom.xml new file mode 100644 index 0000000..0ca6d36 --- /dev/null +++ b/mars-core/pom.xml @@ -0,0 +1,39 @@ + + 4.0.0 + + com.gitee.sherlockholmnes + Mars-java + 2.1.0 + + mars-core + + + + com.alibaba + fastjson + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-jdk14 + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + + + org.jyaml + jyaml + + + + \ No newline at end of file diff --git a/mars-core/src/main/java/com/yuyenews/core/after/StartAfter.java b/mars-core/src/main/java/com/yuyenews/core/after/StartAfter.java new file mode 100644 index 0000000..56197c8 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/after/StartAfter.java @@ -0,0 +1,36 @@ +package com.yuyenews.core.after; + +import com.yuyenews.core.constant.EasyConstant; +import com.yuyenews.core.constant.EasySpace; + +import java.lang.reflect.Method; +import java.util.List; + +/** + * 框架启动后立刻执行 + */ +public class StartAfter { + + private static EasySpace constants = EasySpace.getEasySpace(); + + /** + * 框架启动后立刻执行 + */ + public static void after() throws Exception { + try { + Object objs = constants.getAttr(EasyConstant.EASYAFTERS); + if(objs != null) { + List easyLoads = (List)objs; + + for(Class cls : easyLoads){ + Object obj = cls.getDeclaredConstructor().newInstance(); + Method method2 = cls.getDeclaredMethod("after"); + method2.invoke(obj); + } + } + } catch (Exception e) { + throw e; + } + + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/Controller.java b/mars-core/src/main/java/com/yuyenews/core/annotation/Controller.java new file mode 100644 index 0000000..2a4feb4 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/Controller.java @@ -0,0 +1,14 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Controller { + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/DataSource.java b/mars-core/src/main/java/com/yuyenews/core/annotation/DataSource.java new file mode 100644 index 0000000..00b0f81 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/DataSource.java @@ -0,0 +1,16 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataSource { + + String value(); + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/EasyAfter.java b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyAfter.java new file mode 100644 index 0000000..27bf10f --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyAfter.java @@ -0,0 +1,9 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EasyAfter { +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/EasyAop.java b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyAop.java new file mode 100644 index 0000000..6f8b096 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyAop.java @@ -0,0 +1,15 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EasyAop { + + Class className(); +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/EasyAopType.java b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyAopType.java new file mode 100644 index 0000000..508c787 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyAopType.java @@ -0,0 +1,16 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EasyAopType { + + Class className(); + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/EasyBean.java b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyBean.java new file mode 100644 index 0000000..35358aa --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyBean.java @@ -0,0 +1,14 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EasyBean { + String value() default ""; +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/EasyDao.java b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyDao.java new file mode 100644 index 0000000..051b9f7 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyDao.java @@ -0,0 +1,10 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EasyDao { + String value() default ""; +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/EasyInterceptor.java b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyInterceptor.java new file mode 100644 index 0000000..f096863 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyInterceptor.java @@ -0,0 +1,10 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EasyInterceptor { + String pattern() default ""; +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/EasyLog.java b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyLog.java new file mode 100644 index 0000000..d03053d --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyLog.java @@ -0,0 +1,15 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.*; + +/** + * 加在controller的方法上 表示打印日志 + * @author yuye + * + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EasyLog { + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/EasyMapping.java b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyMapping.java new file mode 100644 index 0000000..e69649f --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/EasyMapping.java @@ -0,0 +1,23 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.yuyenews.core.annotation.enums.RequestMetohd; + +/** + * 映射控制层方法的注解 + * @author yuye + * + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface EasyMapping { + + String value() default ""; + RequestMetohd method() default RequestMetohd.GET; +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/Resource.java b/mars-core/src/main/java/com/yuyenews/core/annotation/Resource.java new file mode 100644 index 0000000..43f4e4e --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/Resource.java @@ -0,0 +1,15 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Resource { + + String value() default ""; +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/Traction.java b/mars-core/src/main/java/com/yuyenews/core/annotation/Traction.java new file mode 100644 index 0000000..0df65e8 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/Traction.java @@ -0,0 +1,14 @@ +package com.yuyenews.core.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Traction { + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/annotation/enums/RequestMetohd.java b/mars-core/src/main/java/com/yuyenews/core/annotation/enums/RequestMetohd.java new file mode 100644 index 0000000..f191573 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/annotation/enums/RequestMetohd.java @@ -0,0 +1,12 @@ +package com.yuyenews.core.annotation.enums; + +/** + * 请求方式 + * + * @author yuye + * + */ +public enum RequestMetohd { + + POST, GET, HEAD, OPTIONS, PUT, DELETE, TRACE, CONNECT +} diff --git a/mars-core/src/main/java/com/yuyenews/core/base/BaseAfter.java b/mars-core/src/main/java/com/yuyenews/core/base/BaseAfter.java new file mode 100644 index 0000000..08a338c --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/base/BaseAfter.java @@ -0,0 +1,9 @@ +package com.yuyenews.core.base; + +/** + * 框架启动后立刻执行的类 必须实现这个接口 + */ +public interface BaseAfter { + + void after() throws Exception; +} diff --git a/mars-core/src/main/java/com/yuyenews/core/constant/EasyConstant.java b/mars-core/src/main/java/com/yuyenews/core/constant/EasyConstant.java new file mode 100644 index 0000000..9ed164a --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/constant/EasyConstant.java @@ -0,0 +1,56 @@ +package com.yuyenews.core.constant; + +/** + * 框架常量 + */ +public class EasyConstant { + + /** + * 本地配置文件 + */ + public static final String CONFIG_PATH = "/goge.yml"; + /** + * 所有的easyAfter类信息 + */ + public static final String EASYAFTERS = "easyAfters"; + /** + * 记录是否已经调用完createbean方法了 + */ + public static final String HAS_START="hasStart"; + /** + * 所有的controller类信息 + */ + public static final String CONTROLLERS = "contorllers"; + /** + * 所有的easyBeans类信息 + */ + public static final String EASYBEANS = "easyBeans"; + /** + * 所有的interceptors类信息 + */ + public static final String INTERCEPTORS = "interceptors"; + /** + * 所有的easyDaos类信息 + */ + public static final String EASYDAOS = "easyDaos"; + + /** + * 所有的controller对象 + */ + public static final String CONTROLLER_OBJECTS = "controlObjects"; + + /** + * 所有的bean对象,包括 easyBean和easydDao + */ + public static final String EASYBEAN_OBJECTS = "easyBeanObjects"; + + /** + * 接受远程配置中心通知的controller + */ + public static final String REMOTE_CONFIG_CONTROLLER = "com.yuyenews.remote.config.RemoteConfigController"; + + /** + * 读取远程配置的路径 + */ + public static final String READ_REMOTE_CONFIG = "http://${0}/getConfig"; +} diff --git a/mars-core/src/main/java/com/yuyenews/core/constant/EasySpace.java b/mars-core/src/main/java/com/yuyenews/core/constant/EasySpace.java new file mode 100644 index 0000000..284efe9 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/constant/EasySpace.java @@ -0,0 +1,53 @@ +package com.yuyenews.core.constant; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 全局存储空间 + * @author yuye + * + */ +public class EasySpace { + + private static EasySpace constants; + + private Map map = new ConcurrentHashMap<>(); + + private EasySpace() { + } + + public static EasySpace getEasySpace() { + if (constants == null) { + constants = new EasySpace(); + } + + return constants; + } + + /** + * 往Constants里添加数据 + * @param key 键 + * @param value 值 + */ + public void setAttr(String key,Object value) { + map.put(key, value); + } + + /** + * 从Constants里获取数据 + * @param key 键 + * @return 值 + */ + public Object getAttr(String key) { + return map.get(key); + } + + /** + * 移除元素 + * @param key + */ + public void remove(String key) { + map.remove(key); + } +} \ No newline at end of file diff --git a/mars-core/src/main/java/com/yuyenews/core/load/LoadClass.java b/mars-core/src/main/java/com/yuyenews/core/load/LoadClass.java new file mode 100644 index 0000000..1870370 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/load/LoadClass.java @@ -0,0 +1,71 @@ +package com.yuyenews.core.load; + +import com.yuyenews.core.annotation.*; +import com.yuyenews.core.util.ReadClass; + +import java.util.Set; + +/** + * 获取项目中的所有class + * + * @author yuye + * + */ +public class LoadClass { + + /** + * 加载所有bean,包括controller 的class对象 + * @param packageName + */ + public static void loadBeans(String packageName) throws Exception{ + try { + /* 加载本地bean */ + LoadNactive.loadNactiveBeans(); + + /* 加载框架用户的所有bean */ + loadAllBeans(packageName); + } catch (Exception e){ + throw new Exception("加载bean出错",e); + } + } + + /** + * 加载所有的bean,包括controller 的class对象 + * @param packageName bean所在的包名 + */ + private static void loadAllBeans(String packageName) throws Exception { + try { + Set classList = ReadClass.loadClassList(packageName); + for (String str : classList) { + Class cls = Class.forName(str); + Controller controller = cls.getAnnotation(Controller.class); + EasyBean easyBean = cls.getAnnotation(EasyBean.class); + EasyInterceptor easyInterceptor = cls.getAnnotation(EasyInterceptor.class); + EasyDao easyDao = cls.getAnnotation(EasyDao.class); + EasyAfter easyAfter = cls.getAnnotation(EasyAfter.class); + + if(controller != null) { + LoadNactive.loadController(cls, controller); + } + if(easyBean != null) { + LoadNactive.loadEasyBean(cls, easyBean); + } + if(easyInterceptor != null){ + LoadNactive.loadInterceptor(cls,easyInterceptor); + } + if(easyDao != null){ + LoadNactive.loadDao(cls,easyDao); + } + if(easyAfter != null){ + LoadNactive.loadEasyAfter(cls); + } + } + } catch (Exception e) { + throw new Exception("扫描["+packageName+"]包下的类发生错误",e); + } + + } + + + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/load/LoadNactive.java b/mars-core/src/main/java/com/yuyenews/core/load/LoadNactive.java new file mode 100644 index 0000000..1c5e658 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/load/LoadNactive.java @@ -0,0 +1,121 @@ +package com.yuyenews.core.load; + +import com.yuyenews.core.annotation.Controller; +import com.yuyenews.core.annotation.EasyBean; +import com.yuyenews.core.annotation.EasyDao; +import com.yuyenews.core.annotation.EasyInterceptor; +import com.yuyenews.core.constant.EasyConstant; +import com.yuyenews.core.constant.EasySpace; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 加载本地资源 + */ +public class LoadNactive { + + private static EasySpace constants = EasySpace.getEasySpace(); + + /** + * 加载本地bean + * @throws Exception + */ + public static void loadNactiveBeans() throws Exception { + + /* 加载 接受远程配置中心通知的controller */ + Class cls = Class.forName(EasyConstant.REMOTE_CONFIG_CONTROLLER); + Controller controller = cls.getAnnotation(Controller.class); + loadController(cls, controller); + + } + + + /** + * 将所有controller存到全局存储空间 + * @param cls + * @param controller + */ + public static void loadController(Class cls,Controller controller) { + Object objs = constants.getAttr(EasyConstant.CONTROLLERS); + List> contorls = new ArrayList<>(); + if(objs != null) { + contorls = (List>)objs; + } + Map contorl = new HashMap<>(); + contorl.put("className", cls); + contorl.put("annotation", controller); + contorls.add(contorl); + constants.setAttr(EasyConstant.CONTROLLERS, contorls); + } + + /** + * 将所有easybean存到全局存储空间 + * @param cls + * @param easyBean + */ + public static void loadEasyBean(Class cls, EasyBean easyBean) { + Object objs = constants.getAttr(EasyConstant.EASYBEANS); + List> easyBeans = new ArrayList<>(); + if(objs != null) { + easyBeans = (List>)objs; + } + Map eb = new HashMap<>(); + eb.put("className", cls); + eb.put("annotation", easyBean); + easyBeans.add(eb); + constants.setAttr(EasyConstant.EASYBEANS, easyBeans); + } + + /** + * 将所有拦截器存到全局存储空间 + * @param cls + * @param interceptor + */ + public static void loadInterceptor(Class cls, EasyInterceptor interceptor){ + Object objs = constants.getAttr(EasyConstant.INTERCEPTORS); + List> interceptors = new ArrayList<>(); + if(objs != null) { + interceptors = (List>)objs; + } + Map eb = new HashMap<>(); + eb.put("className", cls); + eb.put("annotation", interceptor); + interceptors.add(eb); + constants.setAttr(EasyConstant.INTERCEPTORS, interceptors); + } + + /** + * 加载dao + * @param cls + * @param easyDao + */ + public static void loadDao(Class cls, EasyDao easyDao){ + Object objs = constants.getAttr(EasyConstant.EASYDAOS); + List> easyDaos = new ArrayList<>(); + if(objs != null) { + easyDaos = (List>)objs; + } + Map eb = new HashMap<>(); + eb.put("className", cls); + eb.put("annotation", easyDao); + easyDaos.add(eb); + constants.setAttr(EasyConstant.EASYDAOS, easyDaos); + } + + /** + * 加载easyAfter + * @param cls + */ + public static void loadEasyAfter(Class cls){ + Object objs = constants.getAttr(EasyConstant.EASYAFTERS); + List easyLoads = new ArrayList<>(); + if(objs != null) { + easyLoads = (List)objs; + } + easyLoads.add(cls); + constants.setAttr(EasyConstant.EASYAFTERS, easyLoads); + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/logger/GogeLog4jUtil.java b/mars-core/src/main/java/com/yuyenews/core/logger/GogeLog4jUtil.java new file mode 100644 index 0000000..de28732 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/logger/GogeLog4jUtil.java @@ -0,0 +1,49 @@ +package com.yuyenews.core.logger; + +import com.alibaba.fastjson.JSONObject; +import org.apache.logging.log4j.core.config.ConfigurationSource; +import org.apache.logging.log4j.core.config.Configurator; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +public class GogeLog4jUtil { + + /** + * 加载log4j配置文件 + * @throws Exception + */ + public static void initLog4jConfig(JSONObject config) throws Exception { + String path = config.getString("logFile"); + if(path != null){ + if(path.startsWith("classPath-")){ + String logCfgPath = path.replace("classPath-",""); + InputStream inputStream = GogeLog4jUtil.class.getResourceAsStream("/"+logCfgPath); + initLog4jPath(inputStream); + } else { + File file = new File(path); + initLog4jPath(new FileInputStream(file)); + } + } + } + + /** + * 加载log4j配置文件 + * @param inputStream 文件流 + * @throws Exception + */ + private static void initLog4jPath(InputStream inputStream) throws Exception { + try { + BufferedInputStream in = new BufferedInputStream(inputStream); + ConfigurationSource source = new ConfigurationSource(in); + Configurator.initialize(null, source); + + inputStream.close(); + in.close(); + } catch (Exception e){ + throw new Exception("logFile指向的路径下找不到相应的文件",e); + } + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/logger/GogeLogger.java b/mars-core/src/main/java/com/yuyenews/core/logger/GogeLogger.java new file mode 100644 index 0000000..25859d5 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/logger/GogeLogger.java @@ -0,0 +1,42 @@ +package com.yuyenews.core.logger; + +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.core.util.ConfigUtil; + +public abstract class GogeLogger { + + + public abstract void info(String info); + + public abstract void warn(String info); + + public abstract void error(String info,Throwable e); + + public abstract void error(String info); + + /** + * 获取GogeLogger 对象 + * @param cls + * @return + */ + public static GogeLogger getLogger(Class cls){ + boolean str = hasLog4j(); + if(str){ + return new LoggerSlf4j(cls); + } + return new LoggerLog4j(cls); + } + + /** + * 检查用户是否使用了log4j + * @return 布尔值 + */ + private static boolean hasLog4j(){ + JSONObject config = ConfigUtil.getConfig(); + if(config == null){ + return true; + } + Object obj = config.get("logFile"); + return obj == null; + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/logger/LoggerLog4j.java b/mars-core/src/main/java/com/yuyenews/core/logger/LoggerLog4j.java new file mode 100644 index 0000000..bddee11 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/logger/LoggerLog4j.java @@ -0,0 +1,36 @@ +package com.yuyenews.core.logger; + + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class LoggerLog4j extends GogeLogger { + + private Logger logger; + + public LoggerLog4j(Class cls){ + logger = LogManager.getLogger(cls); + } + + @Override + public void info(String info) { + logger.info(info); + } + + @Override + public void error(String info, Throwable e) { + logger.error(info,e); + } + + @Override + public void warn(String info) { + logger.warn(info); + } + + @Override + public void error(String info) { + logger.error(info); + } + + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/logger/LoggerSlf4j.java b/mars-core/src/main/java/com/yuyenews/core/logger/LoggerSlf4j.java new file mode 100644 index 0000000..127f5c0 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/logger/LoggerSlf4j.java @@ -0,0 +1,34 @@ +package com.yuyenews.core.logger; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LoggerSlf4j extends GogeLogger { + + private Logger logger; + + public LoggerSlf4j(Class cls){ + logger = LoggerFactory.getLogger(cls); + } + + @Override + public void info(String info) { + logger.info(info); + } + + @Override + public void error(String info, Throwable e) { + logger.error(info,e); + } + + @Override + public void warn(String info) { + logger.warn(info); + } + + @Override + public void error(String info) { + logger.error(info); + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/model/EasyBeanModel.java b/mars-core/src/main/java/com/yuyenews/core/model/EasyBeanModel.java new file mode 100644 index 0000000..fe76bd2 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/model/EasyBeanModel.java @@ -0,0 +1,50 @@ +package com.yuyenews.core.model; + +/** + * easybean的实体类 + * + * @author yuye + * + */ +public class EasyBeanModel { + + /** + * bean名称 + */ + private String name; + + /** + * bean对象 + */ + private Object obj; + + /** + * class对象 + */ + private Class cls; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Object getObj() { + return obj; + } + + public void setObj(Object obj) { + this.obj = obj; + } + + public Class getCls() { + return cls; + } + + public void setCls(Class cls) { + this.cls = cls; + } + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/remote/config/RemoteConfigService.java b/mars-core/src/main/java/com/yuyenews/core/remote/config/RemoteConfigService.java new file mode 100644 index 0000000..3f1834b --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/remote/config/RemoteConfigService.java @@ -0,0 +1,18 @@ +package com.yuyenews.core.remote.config; + +/** + * 远程配置服务 + */ +public class RemoteConfigService { + + /** + * 重新加载配置 + * @param config + * + * @return 加载结果 + */ + public static String reloadConfig(Object config){ + return null; + } + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/util/ConfigUtil.java b/mars-core/src/main/java/com/yuyenews/core/util/ConfigUtil.java new file mode 100644 index 0000000..71c0b15 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/util/ConfigUtil.java @@ -0,0 +1,81 @@ +package com.yuyenews.core.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.core.constant.EasyConstant; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLog4jUtil; + +/** + * 配置文件工具类 + * @author yuye + * + */ +public class ConfigUtil { + + private static EasySpace constants = EasySpace.getEasySpace(); + + + /** + * 加载配置文件 + */ + public static void loadConfig() throws Exception{ + try { + /* 读取本地配置文件 */ + String content = FileUtil.readYml(EasyConstant.CONFIG_PATH); + JSONObject object = JSONObject.parseObject(content); + + /* 从配置中心获取配置信息 */ + JSONObject config = RemoteConfigUtil.remoteConfig(object); + + /* 保证端口号不被修改 */ + config.put("port",object.get("port")); + + /* 将配置信息缓存下来 */ + constants.setAttr("config", config); + + /* 加载log4j配置文件 */ + GogeLog4jUtil.initLog4jConfig(config); + } catch (Exception e) { + throw new Exception("加载配置文件出错",e); + } + } + + + /** + * 获取配置信息 + * @return json + */ + public static JSONObject getConfig() { + Object obj = constants.getAttr("config"); + if(obj != null) { + JSONObject jsonObject = (JSONObject)obj; + + return jsonObject; + } + + return null; + } + + /** + * 获取JDBC配置信息 + * + * @return 配置信息 + */ + public static JSONObject getJdbcConfig() throws Exception { + try { + JSONObject jsonObject = getConfig(); + + if (jsonObject != null) { + + JSONObject jdbc = JSONObject.parseObject(JSON.toJSONString(jsonObject.get("jdbc"))); + + return jdbc; + } + } catch (Exception e) { + throw new Exception("从配置文件中读取jdbc模块配置出错",e); + } + return new JSONObject(); + } + +} diff --git a/mars-core/src/main/java/com/yuyenews/core/util/FileUtil.java b/mars-core/src/main/java/com/yuyenews/core/util/FileUtil.java new file mode 100644 index 0000000..e91353a --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/util/FileUtil.java @@ -0,0 +1,153 @@ +package com.yuyenews.core.util; + +import com.alibaba.fastjson.JSON; +import com.yuyenews.core.logger.GogeLogger; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.HashMap; + +/** + * 文件帮助 + * + * @author yuye + */ +public class FileUtil { + + private static GogeLogger logger = GogeLogger.getLogger(FileUtil.class); + + public static String local = null; + + /** + * 根据文件路径 获取文件中的字符串内容 + * + * @param path 路径 + * @return str + */ + public static String readFileString(String path) { + InputStream inputStream = null; + BufferedReader reader = null; + try { + inputStream = FileUtil.class.getResourceAsStream(path); + reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + StringBuffer sb = new StringBuffer(); + String str = ""; + while ((str = reader.readLine()) != null) { + sb.append(str); + } + return sb.toString(); + } catch (Exception e) { + if (local == null) { + logger.error("", e); + } else { + logger.warn("自定义mybatis配置文件加载失败或者不存在,将自动使用默认配置"); + } + } finally { + try{ + reader.close(); + inputStream.close(); + } catch (Exception e){ + } + } + return null; + } + + /** + * 根据文件路径 获取yml配置文件 + * + * @param path 路径 + * @return str + */ + public static String readYml(String path) throws Exception { + InputStream inputStream = null; + try { + inputStream = FileUtil.class.getResourceAsStream(path); + HashMap testEntity = org.ho.yaml.Yaml.loadType(inputStream, HashMap.class);//如果是读入Map,这里不可以写Map接口,必须写实现 + return JSON.toJSONString(testEntity); + } catch (Exception e) { + logger.error("", e); + throw e; + } finally { + try{ + inputStream.close(); + } catch (Exception e){ + } + } + } + + /** + * 将file转化成二进制流 + * + * @param file 文件流 + * @return 转化后的二进制流 + */ + public static byte[] getFileToByte(File file) { + InputStream is = null; + ByteArrayOutputStream bytestream = new ByteArrayOutputStream(); + byte[] by = new byte[(int) file.length()]; + try { + is = new FileInputStream(file); + byte[] bb = new byte[2048]; + int ch; + ch = is.read(bb); + while (ch != -1) { + bytestream.write(bb, 0, ch); + ch = is.read(bb); + } + return bytestream.toByteArray(); + } catch (Exception ex) { + logger.error("File转化成byte[]报错",ex); + return null; + } finally { + try{ + bytestream.close(); + is.close(); + } catch (Exception e) { + } + } + } + + /** + * 将InputStream转化成二进制流 + * @param inStream InputStream + * @return 二进制流 + */ + public static byte[] getInputStreamToByte(InputStream inStream) { + ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); + try { + byte[] buff = new byte[100]; + int rc = 0; + while ((rc = inStream.read(buff, 0, 100)) > 0) { + swapStream.write(buff, 0, rc); + } + return swapStream.toByteArray(); + } catch (Exception e) { + logger.error("InputStream转化成byte[]报错",e); + return null; + } finally { + try{ + swapStream.close(); + } catch (Exception e) { + } + } + + } + + public static byte[] getBufferedImageToByte(BufferedImage bufferedImage){ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try{ + ImageIO.write(bufferedImage, "gif", out); + return out.toByteArray(); + } catch (Exception e){ + logger.error("BufferedImage转化成byte[]报错",e); + return null; + } finally { + try{ + out.close(); + } catch (Exception e) { + } + } + + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/util/HttpUtil.java b/mars-core/src/main/java/com/yuyenews/core/util/HttpUtil.java new file mode 100644 index 0000000..02bcf43 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/util/HttpUtil.java @@ -0,0 +1,64 @@ +package com.yuyenews.core.util; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Map; + +/** + * HTTP工具类 + */ +public class HttpUtil { + + /** + * 发起post请求 + * @param url 链接 + * @param params 参数 + * @return 响应结果 + */ + public static Object post(String url, Map params) throws Exception { + return request(url,params,"POST"); + } + + /** + * 发起get请求 + * @param url 链接 + * @param params 参数 + * @return 响应结果 + */ + public static Object get(String url, Map params) throws Exception { + return request(url,params,"GET"); + } + + /** + * 发起请求 + * @param strUrl 链接 + * @param params 参数 + * @param method 请求方式 + * @return 响应结果 + */ + public static Object request(String strUrl, Map params,String method) throws Exception{ + + try { + URL url = new URL(strUrl); + HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); + httpConn.setRequestMethod(method); + if(params != null){ + for(String key : params.keySet()){ + httpConn.setRequestProperty(key,params.get(key)); + } + } + InputStreamReader input = new InputStreamReader(httpConn.getInputStream(), "UTF-8"); + BufferedReader bufReader = new BufferedReader(input); + String line = ""; + StringBuffer stringBuffer = new StringBuffer(); + while ((line = bufReader.readLine()) != null) { + stringBuffer.append(line); + } + return stringBuffer.toString(); + } catch (Exception e) { + throw e; + } + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/util/MatchUtil.java b/mars-core/src/main/java/com/yuyenews/core/util/MatchUtil.java new file mode 100644 index 0000000..8b37270 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/util/MatchUtil.java @@ -0,0 +1,32 @@ +package com.yuyenews.core.util; + +/** + * 判断字符串是否与规则匹配 + * @author yuye + * + */ +public class MatchUtil { + + /** + * 判断带通配符的字符串与另一个字符串是否匹配 + * @param rule 规则 + * @param str 字符串 + * @return boolean + */ + public static Boolean isMatch(String rule,String str){ + if(rule==null || str == null){ + return false; + } + int ind = rule.indexOf("*"); + if(ind>-1){ + if(rule.length()==1){ + return true; + }else{ + String ru = rule.replaceAll("\\*", "([a-zA-Z1-9]+)"); + return str.matches(ru); + } + }else{ + return rule.equals(str); + } + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/util/MesUtil.java b/mars-core/src/main/java/com/yuyenews/core/util/MesUtil.java new file mode 100644 index 0000000..cf3b973 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/util/MesUtil.java @@ -0,0 +1,20 @@ +package com.yuyenews.core.util; + +import com.alibaba.fastjson.JSONObject; + +/** + * 错误提示信息 工具类 + */ +public class MesUtil { + + /** + * 获取错误提示信息 + * @return + */ + public static JSONObject getMes(Integer errorCode,String errorMsg){ + JSONObject jsonObject = new JSONObject(); + jsonObject.put("error_code", errorCode); + jsonObject.put("error_info", errorMsg); + return jsonObject; + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/util/ReadClass.java b/mars-core/src/main/java/com/yuyenews/core/util/ReadClass.java new file mode 100644 index 0000000..852a0de --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/util/ReadClass.java @@ -0,0 +1,164 @@ +package com.yuyenews.core.util; + +import com.yuyenews.core.logger.GogeLogger; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.JarURLConnection; +import java.net.URL; +import java.net.URLDecoder; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * 读取class文件 + * + * @author yuye + * + */ +public class ReadClass { + + private static GogeLogger log = GogeLogger.getLogger(ReadClass.class); + + + /** + * 获取某包下(包括该包的所有子包)所有类 + * + * @param packageName + * 包名 + * @return 类的完整名称 + * @throws UnsupportedEncodingException + */ + public static Set loadClassList(String packageName) throws IOException { + if(packageName == null) { + return new LinkedHashSet<>(); + } + return getClasses(packageName); + } + + /** + * 从包package中获取所有的Class + * + * @param pack + * @return + */ + private static Set getClasses(String pack) { + + // 第一个class类的集合 + Set classes = new LinkedHashSet(); + // 是否循环迭代 + boolean recursive = true; + // 获取包的名字 并进行替换 + String packageName = pack; + String packageDirName = packageName.replace('.', '/'); + // 定义一个枚举的集合 并进行循环来处理这个目录下的things + Enumeration dirs; + try { + 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"); + // 以文件的方式扫描整个包下的文件 并添加到集合中 + findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes); + } else if ("jar".equals(protocol)) { + // 如果是jar包文件 + // 定义一个JarFile + JarFile jar; + try { + // 获取jar + jar = ((JarURLConnection) url.openConnection()).getJarFile(); + // 从此jar包 得到一个枚举类 + Enumeration entries = jar.entries(); + // 同样的进行循环迭代 + while (entries.hasMoreElements()) { + // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + // 如果是以/开头的 + if (name.charAt(0) == '/') { + // 获取后面的字符串 + name = name.substring(1); + } + // 如果前半部分和定义的包名相同 + if (name.startsWith(packageDirName)) { + int idx = name.lastIndexOf('/'); + // 如果以"/"结尾 是一个包 + if (idx != -1) { + // 获取包名 把"/"替换成"." + packageName = name.substring(0, idx).replace('/', '.'); + } + // 如果可以迭代下去 并且是一个包 + if ((idx != -1) || recursive) { + // 如果是一个.class文件 而且不是目录 + if (name.endsWith(".class") && !entry.isDirectory()) { + // 去掉后面的".class" 获取真正的类名 + String className = name.substring(packageName.length() + 1, name.length() - 6); + // 添加到classes + classes.add(packageName + '.' + className); + } + } + } + } + } catch (IOException e) { + // log.error("在扫描用户定义视图时从jar包获取文件出错"); + log.error("",e); + } + } + } + } catch (IOException e) { + log.error("扫描["+packageName+"]包下的类发送错误",e); + } + + return classes; + } + + /** + * 以文件的形式来获取包下的所有Class + * + * @param packageName + * @param packagePath + * @param recursive + * @param classes + */ + public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, + Set classes) { + // 获取此包的目录 建立一个File + File dir = new File(packagePath); + // 如果不存在或者 也不是目录就直接返回 + if (!dir.exists() || !dir.isDirectory()) { + // log.warn("用户定义包名 " + packageName + " 下没有任何文件"); + return; + } + // 如果存在 就获取包下的所有文件 包括目录 + File[] dirfiles = dir.listFiles(new FileFilter() { + // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) + public boolean accept(File file) { + return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); + } + }); + // 循环所有文件 + for (File file : dirfiles) { + // 如果是目录 则继续扫描 + if (file.isDirectory()) { + findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, + classes); + } else { + // 如果是java类文件 去掉后面的.class 只留下类名 + String className = file.getName().substring(0, file.getName().length() - 6); + classes.add(packageName + '.' + className); + } + } + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/util/RemoteConfigUtil.java b/mars-core/src/main/java/com/yuyenews/core/util/RemoteConfigUtil.java new file mode 100644 index 0000000..f2a7b00 --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/util/RemoteConfigUtil.java @@ -0,0 +1,43 @@ +package com.yuyenews.core.util; + +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.core.constant.EasyConstant; + +import java.util.HashMap; +import java.util.Map; + +public class RemoteConfigUtil { + + /** + * 从远程配置中心读取配置信息 + * @param object 本地配置 + * @return 远程配置 + * @throws Exception 异常 + */ + public static JSONObject remoteConfig(JSONObject object) throws Exception { + try{ + Map params = new HashMap<>(); + + /* 读取并判断用户有无使用远程配置中心,如果没有 则直接返回本地配置文件信息 */ + JSONObject config = object.getJSONObject("config"); + if(config == null){ + return object; + } + + /* 解析远程配置 并获取数据 */ + String furl = config.getString("url"); + String url = EasyConstant.READ_REMOTE_CONFIG.replace("${0}",furl); + + params.put("name",config.getString("name")); + params.put("myIp",config.getString("myIp")); + params.put("port",object.getString("port")); + + Object result = HttpUtil.post(url,params); + + JSONObject jsonObject = JSONObject.parseObject(result.toString()); + return jsonObject; + } catch (Exception e){ + throw new Exception("读取远程配置中心失败",e); + } + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/util/StringUtil.java b/mars-core/src/main/java/com/yuyenews/core/util/StringUtil.java new file mode 100644 index 0000000..d0d9e7c --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/util/StringUtil.java @@ -0,0 +1,33 @@ +package com.yuyenews.core.util; + +/** + * 字符串工具类 + * @author yuye + * + */ +public class StringUtil { + + /** + * 将字符串首字母转成小写 + * @param str 参数 + * @return string + */ + public static String getFirstLowerCase(String str) { + String str2 = str.substring(1); + String str3 = str.substring(0,1); + + return str3.toLowerCase()+str2; + } + + /** + * 判断字符串是否为空 + * @param obj 参数 + * @return string + */ + public static boolean isNull(Object obj) { + if(obj == null || obj.toString().trim().equals("")) { + return true; + } + return false; + } +} diff --git a/mars-core/src/main/java/com/yuyenews/core/util/ThreadUtil.java b/mars-core/src/main/java/com/yuyenews/core/util/ThreadUtil.java new file mode 100644 index 0000000..7a3fd5f --- /dev/null +++ b/mars-core/src/main/java/com/yuyenews/core/util/ThreadUtil.java @@ -0,0 +1,35 @@ +package com.yuyenews.core.util; + +/** + * 线程工具类 + * @author yuye + * + */ +public class ThreadUtil { + + /** + * 获取当前线程的ID + * @return id + */ + public static String getThreadIdToTraction() { + return getThreadId("traction"); + } + + /** + * 获取当前线程的ID + * @param tag + * @return id + */ + public static String getThreadId(String tag) { + return String.valueOf(Thread.currentThread().getId())+tag; + } + + /** + * 获取当前线程的ID + * @return id + */ + public static String getThreadId() { + return String.valueOf(Thread.currentThread().getId()); + } + +} diff --git a/mars-ioc/pom.xml b/mars-ioc/pom.xml new file mode 100644 index 0000000..541cf1e --- /dev/null +++ b/mars-ioc/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + + com.gitee.sherlockholmnes + Mars-java + 2.1.0 + + mars-ioc + + + + com.gitee.sherlockholmnes + mars-aop + + + \ No newline at end of file diff --git a/mars-ioc/src/main/java/com/yuyenews/ioc/factory/BeanFactory.java b/mars-ioc/src/main/java/com/yuyenews/ioc/factory/BeanFactory.java new file mode 100644 index 0000000..0f4879c --- /dev/null +++ b/mars-ioc/src/main/java/com/yuyenews/ioc/factory/BeanFactory.java @@ -0,0 +1,117 @@ +package com.yuyenews.ioc.factory; + +import com.yuyenews.aop.proxy.CglibProxy; +import com.yuyenews.core.annotation.EasyAop; +import com.yuyenews.core.annotation.EasyAopType; +import com.yuyenews.core.annotation.Traction; +import com.yuyenews.core.constant.EasyConstant; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.model.EasyBeanModel; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * bean工厂 + * @author yuye + * + */ +public class BeanFactory { + + private static GogeLogger log = GogeLogger.getLogger(BeanFactory.class); + + private static EasySpace constants = EasySpace.getEasySpace(); + + /** + * 创建bean + * @param className lei + * @return duixiang + */ + public static Object createBean(Class className) throws Exception { + try { + + Object hasStart = constants.getAttr(EasyConstant.HAS_START); + if(hasStart != null){ + throw new Exception("只有Goge才可以调用此方法,不可以手动显式调用"); + } + + Map> list = new HashMap<>(); + + /* 判断当前类中有没有方法有 aop注解 */ + getAopClass(className,list); + + /* 如果有aop注解,则通过动态代理来创建bean */ + if(list != null && list.size()>0) { + CglibProxy cglibProxy = new CglibProxy(); + return cglibProxy.getProxy(className, list); + } else { + /* 如果没有aop注解,则直接new一个bean */ + return className.getDeclaredConstructor().newInstance(); + } + + } catch (Exception e) { + throw new Exception("创建["+className.getName()+"]类型的bean对象出现错误",e); + } + } + + /** + * 获取aop类 + * @param className lei + * @param list jihe + * @throws Exception cuowu + */ + private static void getAopClass(Class className,Map> list) throws Exception { + + EasyAopType allEasyAop = className.getAnnotation(EasyAopType.class); + + Method[] methods = className.getMethods(); + for(Method method : methods) { + EasyAop easyAop = method.getAnnotation(EasyAop.class); + Traction traction = method.getAnnotation(Traction.class); + + /* 校验同一个方法上不能同时存在aop和trac注解 */ + if(easyAop != null && traction != null) { + log.error(className.getName()+"类中的["+method.getName()+"]方法同时存在EasyAop和Traction注解"); + throw new Exception(className.getName()+"类中的["+method.getName()+"]方法同时存在EasyAop和Traction注解"); + } + + /* 如果类的AOP注解不为空,那么将注解中的监听类 添加到集合中 */ + if(allEasyAop != null) { + list.put(method.getName(),allEasyAop.className()); + } + + /* 如果方法上也有AOP注解,那么以方法上的为准 */ + if(easyAop != null) { + list.put(method.getName(),easyAop.className()); + } else if(traction != null) { + Class aopClass = Class.forName("com.yuyenews.easy.traction.TractionAop"); + list.put(method.getName(),aopClass); + } + } + } + + + /** + * 获取bean + * @param name mingc + * @return duix + */ + public static Object getBean(String name) throws Exception { + + try { + + + Object objs2 = constants.getAttr(EasyConstant.EASYBEAN_OBJECTS); + Map easyBeanObjs = new HashMap<>(); + if(objs2 != null) { + easyBeanObjs = (Map)objs2; + } + + return easyBeanObjs.get(name).getObj(); + } catch (Exception e) { + throw new Exception("找不到name为["+name+"]的bean",e); + } + } +} diff --git a/mars-ioc/src/main/java/com/yuyenews/ioc/load/LoadEasyBean.java b/mars-ioc/src/main/java/com/yuyenews/ioc/load/LoadEasyBean.java new file mode 100644 index 0000000..9537864 --- /dev/null +++ b/mars-ioc/src/main/java/com/yuyenews/ioc/load/LoadEasyBean.java @@ -0,0 +1,120 @@ +package com.yuyenews.ioc.load; + +import com.yuyenews.core.annotation.EasyBean; +import com.yuyenews.core.annotation.Resource; +import com.yuyenews.core.constant.EasyConstant; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.model.EasyBeanModel; +import com.yuyenews.core.util.StringUtil; +import com.yuyenews.ioc.factory.BeanFactory; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 加载easyBean + * @author yuye + * + */ +public class LoadEasyBean { + + private static GogeLogger log = GogeLogger.getLogger(LoadEasyBean.class); + + /** + * 获取全局存储空间 + */ + private static EasySpace constants = EasySpace.getEasySpace(); + + /** + * 创建easyBean对象,并完成对象注入 + */ + @SuppressWarnings({ "unchecked" }) + public static void loadBean() throws Exception{ + try { + /* 获取所有的bean数据 */ + Object objs = constants.getAttr(EasyConstant.EASYBEANS); + List> contorls = null; + if(objs != null) { + contorls = (List>)objs; + } else { + return; + } + + /* 创建bean对象,并保存起来 */ + Object objs2 = constants.getAttr(EasyConstant.EASYBEAN_OBJECTS); + Map easyBeanObjs = new HashMap<>(); + if(objs2 != null) { + easyBeanObjs = (Map)objs2; + } + for(Map map : contorls) { + + Class cls = (Class)map.get("className"); + EasyBean easyBean = (EasyBean)map.get("annotation"); + + String beanName = easyBean.value(); + if(beanName == null || beanName.equals("")) { + beanName = StringUtil.getFirstLowerCase(cls.getSimpleName()); + } + if(easyBeanObjs.get(beanName) == null) { + EasyBeanModel beanModel = new EasyBeanModel(); + beanModel.setName(beanName); + beanModel.setCls(cls); + beanModel.setObj(BeanFactory.createBean(cls)); + easyBeanObjs.put(beanName, beanModel); + } else { + throw new Exception("已经存在name为["+beanName+"]的bean了"); + } + } + /* 注入对象 */ + iocBean(easyBeanObjs); + } catch (Exception e) { + throw new Exception("加载并注入EasyBean的时候出现错误",e); + } + } + + /** + * easyBean注入 + * @param easyBeanObjs 对象 + */ + private static void iocBean(Map easyBeanObjs) throws Exception{ + + try { + for(String key : easyBeanObjs.keySet()) { + EasyBeanModel easyBeanModel = easyBeanObjs.get(key); + Object obj = easyBeanModel.getObj(); + Class cls = easyBeanModel.getCls(); + /* 获取对象属性,完成注入 */ + Field[] fields = cls.getDeclaredFields(); + for(Field f : fields){ + Resource resource = f.getAnnotation(Resource.class); + if(resource!=null){ + f.setAccessible(true); + + String filedName = resource.value(); + if(filedName == null || filedName.equals("")) { + filedName = f.getName(); + } + + EasyBeanModel beanModel = easyBeanObjs.get(filedName); + if(beanModel!=null){ + f.set(obj, beanModel.getObj()); + log.info(cls.getName()+"的属性"+f.getName()+"注入成功"); + }else{ + throw new Exception("不存在name为"+filedName+"的easyBean"); + } + } + } + /* 保险起见,重新插入数据 */ + easyBeanModel.setCls(cls); + easyBeanObjs.put(key, easyBeanModel); + } + + constants.setAttr(EasyConstant.EASYBEAN_OBJECTS, easyBeanObjs); + } catch (Exception e) { + throw new Exception("加载并注入EasyBean的时候出现错误",e); + } + } +} diff --git a/mars-jdbc/mars-jdbc-base/pom.xml b/mars-jdbc/mars-jdbc-base/pom.xml new file mode 100644 index 0000000..3aa8d5e --- /dev/null +++ b/mars-jdbc/mars-jdbc-base/pom.xml @@ -0,0 +1,31 @@ + + + + mars-jdbc + com.gitee.sherlockholmnes + 2.1.0 + + 4.0.0 + + mars-jdbc-base + + + + com.gitee.sherlockholmnes + mars-aop + ${project.parent.version} + + + + mysql + mysql-connector-java + + + + com.alibaba + druid + + + \ No newline at end of file diff --git a/mars-jdbc/mars-jdbc-base/src/main/java/com/yuyenews/jdbc/base/BaseInitJdbc.java b/mars-jdbc/mars-jdbc-base/src/main/java/com/yuyenews/jdbc/base/BaseInitJdbc.java new file mode 100644 index 0000000..ebbd5c3 --- /dev/null +++ b/mars-jdbc/mars-jdbc-base/src/main/java/com/yuyenews/jdbc/base/BaseInitJdbc.java @@ -0,0 +1,9 @@ +package com.yuyenews.jdbc.base; + +public interface BaseInitJdbc { + + /** + * 加载配置 + */ + void init() throws Exception; +} diff --git a/mars-jdbc/mars-jdbc-base/src/main/java/com/yuyenews/jdbc/base/BaseJdbcProxy.java b/mars-jdbc/mars-jdbc-base/src/main/java/com/yuyenews/jdbc/base/BaseJdbcProxy.java new file mode 100644 index 0000000..6901e49 --- /dev/null +++ b/mars-jdbc/mars-jdbc-base/src/main/java/com/yuyenews/jdbc/base/BaseJdbcProxy.java @@ -0,0 +1,14 @@ +package com.yuyenews.jdbc.base; + +/** + * JDBC代理 + */ +public abstract class BaseJdbcProxy { + + /** + * 获取代理对象 + * @param clazz bean的class + * @return 对象 + */ + public abstract Object getProxy(Class clazz); +} diff --git a/mars-jdbc/mars-jdbc-base/src/main/java/com/yuyenews/jdbc/load/LoadDaos.java b/mars-jdbc/mars-jdbc-base/src/main/java/com/yuyenews/jdbc/load/LoadDaos.java new file mode 100644 index 0000000..fa53f17 --- /dev/null +++ b/mars-jdbc/mars-jdbc-base/src/main/java/com/yuyenews/jdbc/load/LoadDaos.java @@ -0,0 +1,66 @@ +package com.yuyenews.jdbc.load; + + +import com.yuyenews.core.annotation.EasyDao; +import com.yuyenews.core.constant.EasyConstant; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.model.EasyBeanModel; +import com.yuyenews.core.util.StringUtil; +import com.yuyenews.jdbc.base.BaseJdbcProxy; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class LoadDaos { + + /** + * 获取全局存储空间 + */ + private static EasySpace constants = EasySpace.getEasySpace(); + + /** + * 创建dao对象 + */ + public static void loadDao(BaseJdbcProxy baseProxy) throws Exception{ + try { + + Object objs = constants.getAttr(EasyConstant.EASYDAOS); + if(objs != null) { + List> easyDaos = (List>)objs; + + /* 创建bean对象,并保存起来 */ + Object objs2 = constants.getAttr(EasyConstant.EASYBEAN_OBJECTS); + Map easyBeanObjs = new HashMap<>(); + if(objs2 != null) { + easyBeanObjs = (Map)objs2; + } + + for(Map map : easyDaos) { + Class cls = (Class) map.get("className"); + EasyDao easyDao = (EasyDao)map.get("annotation"); + + String beanName = easyDao.value(); + if(beanName == null || beanName.equals("")){ + beanName = StringUtil.getFirstLowerCase(cls.getSimpleName()); + } + if(easyBeanObjs.get(beanName) == null) { + EasyBeanModel beanModel = new EasyBeanModel(); + beanModel.setName(beanName); + beanModel.setCls(cls); + beanModel.setObj(baseProxy.getProxy(cls)); + easyBeanObjs.put(beanName, beanModel); + } else { + throw new Exception("已经存在name为["+beanName+"]的EasyDao了"); + } + } + + constants.setAttr(EasyConstant.EASYBEAN_OBJECTS,easyBeanObjs); + } + + } catch (Exception e) { + throw new Exception("加载EasyDao的时候出现错误",e); + } + } + +} diff --git a/mars-jdbc/mars-jpa/pom.xml b/mars-jdbc/mars-jpa/pom.xml new file mode 100644 index 0000000..cc6d0f6 --- /dev/null +++ b/mars-jdbc/mars-jpa/pom.xml @@ -0,0 +1,21 @@ + + + + mars-jdbc + com.gitee.sherlockholmnes + 2.1.0 + + 4.0.0 + + mars-jpa + + + + com.gitee.sherlockholmnes + mars-jdbc-base + ${project.parent.version} + + + \ No newline at end of file diff --git a/mars-jdbc/mars-jpa/src/main/java/com/yuyenews/easy/jpa/init/InitJdbc.java b/mars-jdbc/mars-jpa/src/main/java/com/yuyenews/easy/jpa/init/InitJdbc.java new file mode 100644 index 0000000..191977f --- /dev/null +++ b/mars-jdbc/mars-jpa/src/main/java/com/yuyenews/easy/jpa/init/InitJdbc.java @@ -0,0 +1,26 @@ +package com.yuyenews.easy.jpa.init; + +import com.yuyenews.easy.jpa.proxy.JpaProxy; +import com.yuyenews.jdbc.base.BaseInitJdbc; +import com.yuyenews.jdbc.load.LoadDaos; + +/** + * 初始化jdbc + * @author yuye + * + */ +public class InitJdbc implements BaseInitJdbc { + + /** + * 加载配置 + */ + @Override + public void init() throws Exception{ + + /* 加载jpa配置 */ + + /* 创建dao对象 */ + LoadDaos.loadDao(new JpaProxy()); + + } +} diff --git a/mars-jdbc/mars-jpa/src/main/java/com/yuyenews/easy/jpa/proxy/JpaProxy.java b/mars-jdbc/mars-jpa/src/main/java/com/yuyenews/easy/jpa/proxy/JpaProxy.java new file mode 100644 index 0000000..7a4f7f9 --- /dev/null +++ b/mars-jdbc/mars-jpa/src/main/java/com/yuyenews/easy/jpa/proxy/JpaProxy.java @@ -0,0 +1,83 @@ +package com.yuyenews.easy.jpa.proxy; + + +import com.yuyenews.core.annotation.DataSource; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.util.ThreadUtil; +import com.yuyenews.jdbc.base.BaseJdbcProxy; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; + +/** + * 代理类 + * @author yuye + * + */ +public class JpaProxy extends BaseJdbcProxy implements MethodInterceptor { + + private EasySpace easySpace = EasySpace.getEasySpace(); + + + /** + * 获取代理对象 + * @param clazz bean的class + * @return 对象 + */ + @Override + public Object getProxy(Class clazz) { + Enhancer enhancer = new Enhancer(); + // 设置需要创建子类的类 + enhancer.setSuperclass(clazz); + enhancer.setCallback(this); + // 通过字节码技术动态创建子类实例 + return enhancer.create(); + } + + + /** + * 绑定代理 + * @param o + * @param method + * @param args + * @param methodProxy + * @return obj + * @throws Throwable + */ + @Override + public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + + /* 获取当前线程中的sqlSession */ + Object obj = easySpace.getAttr(ThreadUtil.getThreadIdToTraction()); + + + /* 返回数据 */ + Object result = null; + + + + return result; + } + + /** + * 获取数据源名称 + * @param method + * @return str + */ + private String getDataSourceName(Method method) { + String dataSourceName = null; + DataSource dataSource = method.getAnnotation(DataSource.class); + if(dataSource != null) { + /* 如果dao的方法上有DataSource注解,则使用注解中的数据源名称 */ + dataSourceName = dataSource.value(); + } else { + /* 否则使用默认数据源名称 */ + dataSourceName = easySpace.getAttr("defaultDataSource").toString(); + } + return dataSourceName; + } +} + + diff --git a/mars-jdbc/mars-mybatis/pom.xml b/mars-jdbc/mars-mybatis/pom.xml new file mode 100644 index 0000000..c54dfb6 --- /dev/null +++ b/mars-jdbc/mars-mybatis/pom.xml @@ -0,0 +1,29 @@ + + 4.0.0 + + com.gitee.sherlockholmnes + mars-jdbc + 2.1.0 + + mars-mybatis + + + + com.gitee.sherlockholmnes + mars-jdbc-base + ${project.parent.version} + + + + org.mybatis + mybatis + + + + com.github.pagehelper + pagehelper + + + \ No newline at end of file diff --git a/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/init/InitJdbc.java b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/init/InitJdbc.java new file mode 100644 index 0000000..38a7186 --- /dev/null +++ b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/init/InitJdbc.java @@ -0,0 +1,27 @@ +package com.yuyenews.easy.init; + +import com.yuyenews.easy.proxy.MappersProxy; +import com.yuyenews.jdbc.base.BaseInitJdbc; +import com.yuyenews.jdbc.load.LoadDaos; + +/** + * 初始化jdbc + * @author yuye + * + */ +public class InitJdbc implements BaseInitJdbc { + + /** + * 加载配置 + */ + @Override + public void init() throws Exception{ + + /* 加载mybatis配置 */ + LoadSqlSessionFactory.getLoadSqlSessionFactory(); + + /* 创建dao对象 */ + LoadDaos.loadDao(new MappersProxy()); + + } +} diff --git a/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/init/LoadMybatisConfig.java b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/init/LoadMybatisConfig.java new file mode 100644 index 0000000..28d953a --- /dev/null +++ b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/init/LoadMybatisConfig.java @@ -0,0 +1,189 @@ +package com.yuyenews.easy.init; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.ConfigUtil; +import com.yuyenews.core.util.FileUtil; +import com.yuyenews.easy.util.ReadXml; +import com.yuyenews.easy.util.extend.MyDataSourceFactory; + +import java.io.IOException; +import java.rmi.server.ExportException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * 组装myBatis配置文件 + * @author yuye + * + */ +public class LoadMybatisConfig { + + private static GogeLogger logger = GogeLogger.getLogger(LoadMybatisConfig.class); + + private static EasySpace easySpace = EasySpace.getEasySpace(); + + /** + * 获取配置文件并以字符串形式返回 + * @return str + */ + public static String getConfigStr() throws Exception { + try { + FileUtil.local = String.valueOf(ConfigUtil.getJdbcConfig().get("config-location")); + String str = FileUtil.readFileString("/"+FileUtil.local); + if(str == null) { + str = defaultConfig(); + } + + /* 禁止在mybatis配置文件里配置数据源 */ + if(str.indexOf("environment") > -1 || str.indexOf("dataSource") > -1 || str.indexOf("environments") > -1) { + throw new Exception("不可以在mybatis配置文件里配置数据源"); + } + + /* 禁止在mybatis配置文件里配置mappers */ + if(str.indexOf("mappers") > -1 || str.indexOf("mapper") > -1) { + throw new Exception("不可以在mybatis配置文件里配置mappers"); + } + + str = str.replaceAll("", ""); + str += getDataSources(); + str += getMappers(); + str += ""; + + return str; + } catch (Exception e) { + throw new Exception("加载mybatis配置出错",e); + } + } + + /** + * 获取所有mapper文件路径,并组装成xml格式的字符串返回 + * @return str + */ + private static String getMappers() throws Exception { + try { + String mappers = ConfigUtil.getJdbcConfig().getString("mappers"); + + Set xmls = ReadXml.loadXmlList(mappers); + + StringBuffer buffer = new StringBuffer(""); + for(String str : xmls) { + buffer.append(""); + } + buffer.append(""); + return buffer.toString(); + } catch (Exception e) { + throw new Exception("加载mybatis配置文件出错",e); + } + } + + /** + * 加载数据源配置 + * @return str + */ + private static String getDataSources() throws Exception { + try { + String def = ""; + + JSONArray array = ConfigUtil.getJdbcConfig().getJSONArray("dataSource"); + + StringBuffer dataSource = new StringBuffer("") ; + + List daNames = new ArrayList<>(); + + for (int i = 0; i < array.size(); i++) { + + JSONObject jsonObject = array.getJSONObject(i); + + ckDsConfig(jsonObject); + + if(i == 0) { + def = jsonObject.getString("name"); + } + + String type = getDataSourceType(); + + StringBuffer buffer = new StringBuffer(); + buffer.append(""); + buffer.append(""); + buffer.append(""); + for(String key : jsonObject.keySet()) { + if(!key.equals("name") && !key.equals("type")) { + buffer.append(""); + } + } + buffer.append(""); + buffer.append(""); + dataSource.append(buffer); + + daNames.add(jsonObject.getString("name")); + } + + easySpace.setAttr("dataSourceNames", daNames); + easySpace.setAttr("defaultDataSource", def); + + dataSource.append(""); + + return dataSource.toString().replace("${def}", def); + } catch (Exception e) { + throw new Exception("加载mybatis数据源出错",e); + } + } + + /** + * 获取数据源类型 + * @return str + */ + private static String getDataSourceType() { + return MyDataSourceFactory.class.getName(); + } + + /** + * 验证数据源配置 + * @return str + */ + private static boolean ckDsConfig(JSONObject jsonObject) throws Exception { + if(jsonObject.get("name") == null) { + logger.error("数据源没有指定name"); + throw new Exception("数据源没有指定name"); + } + return true; + } + + /** + * 默认配置 + * @return str + */ + private static String defaultConfig() throws Exception { + try { + + Object dialect = ConfigUtil.getJdbcConfig().get("dialect"); + + if(dialect == null) { + /* 方言 默认mysql */ + dialect = "mysql"; + } + + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + stringBuffer.append(""); + + return stringBuffer.toString(); + } catch (Exception e) { + throw new Exception("加载mybatis配置文件出错",e); + } + } +} diff --git a/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/init/LoadSqlSessionFactory.java b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/init/LoadSqlSessionFactory.java new file mode 100644 index 0000000..ba5b9a7 --- /dev/null +++ b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/init/LoadSqlSessionFactory.java @@ -0,0 +1,96 @@ +package com.yuyenews.easy.init; + +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLogger; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * 加载 + * @author yuye + * + */ +public class LoadSqlSessionFactory { + + private GogeLogger logger = GogeLogger.getLogger(LoadSqlSessionFactory.class); + + private static LoadSqlSessionFactory factory; + + private String resource; + + private static EasySpace easySpace = EasySpace.getEasySpace(); + + /** + * 单例,防止重复加载配置文件 + */ + private LoadSqlSessionFactory() {} + + /** + * 获取本类的对象 + * @return obj + */ + public static LoadSqlSessionFactory getLoadSqlSessionFactory() { + + if(factory == null) { + factory = new LoadSqlSessionFactory(); + factory.loadConfig(); + factory.loadSqlSessionFactorys(); + } + + return factory; + } + + /** + * 将配置文件字符串转换成输入流 + */ + private void loadConfig() { + try { + resource = LoadMybatisConfig.getConfigStr(); + } catch (Exception e) { + logger.error("加载配置文件出错",e); + } + } + + /** + * 加载sqlSessionFactory + */ + private void loadSqlSessionFactorys() { + List daNames = (List) easySpace.getAttr("dataSourceNames"); + + Map maps = new HashMap<>(); + for(String str : daNames) { + InputStream inputStream = new ByteArrayInputStream(resource.getBytes()); + maps.put(str, new SqlSessionFactoryBuilder().build(inputStream,str)); + } + easySpace.setAttr("sqlSessionFactorys", maps); + } + + /** + * 获取sqlSession + * @return session + */ + public SqlSession getSqlSession() { + return getSqlSession(null,true); + } + + /** + * 获取sqlSession + * @return session + */ + public SqlSession getSqlSession(String dataSourceName,Boolean autoCommit) { + Map maps = (Map) easySpace.getAttr("sqlSessionFactorys"); + if(dataSourceName == null) { + Object defDa = easySpace.getAttr("defaultDataSource"); + return maps.get(defDa.toString()).openSession(autoCommit); + } + return maps.get(dataSourceName).openSession(autoCommit); + } +} diff --git a/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/proxy/MappersProxy.java b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/proxy/MappersProxy.java new file mode 100644 index 0000000..3d5aac8 --- /dev/null +++ b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/proxy/MappersProxy.java @@ -0,0 +1,147 @@ +package com.yuyenews.easy.proxy; + +import com.yuyenews.core.annotation.DataSource; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.util.ThreadUtil; +import com.yuyenews.easy.init.LoadSqlSessionFactory; +import com.yuyenews.jdbc.base.BaseJdbcProxy; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; +import org.apache.ibatis.mapping.SqlCommandType; +import org.apache.ibatis.session.SqlSession; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; + +/** + * 代理类 + * @author yuye + * + */ +public class MappersProxy extends BaseJdbcProxy implements MethodInterceptor { + + private EasySpace easySpace = EasySpace.getEasySpace(); + + private LoadSqlSessionFactory loadSqlSessionFactory = LoadSqlSessionFactory.getLoadSqlSessionFactory(); + + /** + * 获取代理对象 + * @param clazz bean的class + * @return 对象 + */ + @Override + public Object getProxy(Class clazz) { + Enhancer enhancer = new Enhancer(); + // 设置需要创建子类的类 + enhancer.setSuperclass(clazz); + enhancer.setCallback(this); + // 通过字节码技术动态创建子类实例 + return enhancer.create(); + } + + + /** + * 绑定代理 + * @param o + * @param method + * @param args + * @param methodProxy + * @return obj + * @throws Throwable + */ + @Override + public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + + /* 获取当前线程中的sqlSession */ + Object obj = easySpace.getAttr(ThreadUtil.getThreadIdToTraction()); + + /* 用来执行sql的sqlSession */ + SqlSession session = null; + + /* 是否需要手动关闭sqlSession(默认不需要) */ + Boolean flag = false; + + /* 返回数据 */ + Object result = null; + + /* 获取数据源名称 */ + String dataSourceName = getDataSourceName(method); + + if(obj != null) { + /* 如果当前线程中有sqlSession 则从当前线程中获取sqlSession */ + Map sqlSessions = (Map)obj; + session = sqlSessions.get(dataSourceName); + } else { + /* 否则 手动获取(这种情况,当执行完以后需要手动关闭sqlSession) */ + session = loadSqlSessionFactory.getSqlSession(dataSourceName, false); + flag = true; + } + + /* 获取要执行的sql的ID */ + String statement = method.getName(); + + /* 根据要执行的sql的ID 获取这条sql的类型是select还是update */ + SqlCommandType tag = session.getConfiguration().getMappedStatement(statement).getSqlCommandType(); + String commType = tag.toString().toUpperCase(); + + if(commType.equals("SELECT")) { + /* 如果是select,则判断方法的返回值是不是list */ + Class returnType = method.getReturnType(); + if(returnType.getName().equals(List.class.getName())) { + /* 如果方法的返回值是list,则执行selectList方法 */ + if(args != null && args.length > 0 && args[0] != null) { + result = session.selectList(statement, args[0]); + } else { + result = session.selectList(statement); + } + } else { + /* 如果不是list,则执行selectOne方法 */ + if(args != null && args.length > 0 && args[0] != null) { + result = session.selectOne(statement, args[0]); + } else { + result = session.selectOne(statement); + } + } + + } else if(commType.equals("UPDATE") || commType.equals("INSERT") || commType.equals("DELETE")) { + /* 如果要执行的sql是update类型(增删改),则执行update方法 */ + if(args != null && args.length > 0 && args[0] != null) { + result = session.update(statement, args[0]); + } else { + result = session.update(statement); + } + + if(flag) { + /* 如果sqlSession是手动获取的,那么执行完以后要立刻提交事务 */ + session.commit(); + } + } + + if(flag) { + /* 手工关闭sqlSession 节约回收的开销 */ + session.close(); + } + + return result; + } + + /** + * 获取数据源名称 + * @param method + * @return str + */ + private String getDataSourceName(Method method) { + String dataSourceName = null; + DataSource dataSource = method.getAnnotation(DataSource.class); + if(dataSource != null) { + /* 如果dao的方法上有DataSource注解,则使用注解中的数据源名称 */ + dataSourceName = dataSource.value(); + } else { + /* 否则使用默认数据源名称 */ + dataSourceName = easySpace.getAttr("defaultDataSource").toString(); + } + return dataSourceName; + } +} diff --git a/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/traction/TractionAop.java b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/traction/TractionAop.java new file mode 100644 index 0000000..7828e07 --- /dev/null +++ b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/traction/TractionAop.java @@ -0,0 +1,94 @@ +package com.yuyenews.easy.traction; + +import com.yuyenews.aop.base.BaseAop; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.ThreadUtil; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * 事务管理aop + * @author yuye + * + */ +public class TractionAop implements BaseAop { + + private GogeLogger logger = GogeLogger.getLogger(TractionAop.class); + + private static EasySpace easySpace = EasySpace.getEasySpace(); + + /** + * 获取数据库连接,并设置为不自动提交 + * + * 将获取到的连接 放到缓存中 + * + * @param args canshu + */ + @SuppressWarnings("unchecked") + public void startMethod(Object[] args) { + try { + Map maps = (Map)easySpace.getAttr("sqlSessionFactorys"); + + Map sqlSessions = new HashMap<>(); + + for(String key : maps.keySet()) { + sqlSessions.put(key, maps.get(key).openSession(false)); + } + + easySpace.setAttr(ThreadUtil.getThreadIdToTraction(), sqlSessions); + } catch (Exception e) { + logger.error("开启事务出错",e); + } + } + + /** + * 从缓存中获取当前线程的数据库连接,并提交事务 + * + * @param args canshu + */ + public void endMethod(Object[] args) { + try { + @SuppressWarnings("unchecked") + Map sqlSessions = (Map)easySpace.getAttr(ThreadUtil.getThreadIdToTraction()); + + for(String key : sqlSessions.keySet()) { + SqlSession session = sqlSessions.get(key); + session.commit(); + session.close(); + } + } catch (Exception e) { + logger.error("提交事务出错",e); + } finally { + easySpace.remove(ThreadUtil.getThreadIdToTraction()); + } + + } + + /** + * 从缓存中获取当前线程的数据库连接,并回滚事务 + * @param e 异常 + */ + public void exp(Throwable e) { + try { + @SuppressWarnings("unchecked") + Map sqlSessions = (Map)easySpace.getAttr(ThreadUtil.getThreadIdToTraction()); + + for(String key : sqlSessions.keySet()) { + SqlSession session = sqlSessions.get(key); + session.rollback(); + session.close(); + } + + logger.error("",e); + } catch (Exception ex) { + logger.error("回滚事务出错",ex); + } finally { + easySpace.remove(ThreadUtil.getThreadIdToTraction()); + } + } + +} diff --git a/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/util/ReadXml.java b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/util/ReadXml.java new file mode 100644 index 0000000..6c6409c --- /dev/null +++ b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/util/ReadXml.java @@ -0,0 +1,162 @@ +package com.yuyenews.easy.util; + +import com.yuyenews.core.logger.GogeLogger; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.net.JarURLConnection; +import java.net.URL; +import java.net.URLDecoder; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * 读取class文件 + * + * @author yuye + * + */ +public class ReadXml { + + private static GogeLogger log = GogeLogger.getLogger(ReadXml.class); + + + /** + * 获取某包下(包括该包的所有子包)所有xml + * + * @param packageName + * 包名 + * @return xml的完整名称 + * @throws IOException 异常 + */ + public static Set loadXmlList(String packageName) throws IOException { + if(packageName == null) { + return new LinkedHashSet<>(); + } + return getXmls(packageName); + } + + /** + * 从包package中获取所有的xml + * + * @param pack + * @return set + */ + private static Set getXmls(String pack) { + + // 第一个class类的集合 + Set classes = new LinkedHashSet(); + // 是否循环迭代 + boolean recursive = true; + // 获取包的名字 并进行替换 + String packageName = pack; + String packageDirName = packageName.replace('.', '/'); + // 定义一个枚举的集合 并进行循环来处理这个目录下的things + Enumeration dirs; + try { + 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"); + // 以文件的方式扫描整个包下的文件 并添加到集合中 + findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes); + } else if ("jar".equals(protocol)) { + // 如果是jar包文件 + // 定义一个JarFile + JarFile jar; + try { + // 获取jar + jar = ((JarURLConnection) url.openConnection()).getJarFile(); + // 从此jar包 得到一个枚举类 + Enumeration entries = jar.entries(); + // 同样的进行循环迭代 + while (entries.hasMoreElements()) { + // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + // 如果是以/开头的 + if (name.charAt(0) == '/') { + // 获取后面的字符串 + name = name.substring(1); + } + // 如果前半部分和定义的包名相同 + if (name.startsWith(packageDirName)) { + int idx = name.lastIndexOf('/'); + // 如果以"/"结尾 是一个包 + if (idx != -1) { + // 获取包名 把"/"替换成"." + packageName = name.substring(0, idx); + } + // 如果可以迭代下去 并且是一个包 + if ((idx != -1) || recursive) { + // 如果是一个.xml文件 而且不是目录 + if (name.endsWith(".xml") && !entry.isDirectory()) { + // 去掉后面的".class" 获取真正的类名 + String className = name.substring(packageName.length() + 1); + // 添加到classes + classes.add(packageName + '/' + className); + } + } + } + } + } catch (IOException e) { + // log.error("在扫描用户定义视图时从jar包获取文件出错"); + log.error("",e); + } + } + } + } catch (IOException e) { + log.error("扫描["+packageName+"]包下的类发送错误",e); + } + + return classes; + } + + /** + * 以文件的形式来获取包下的所有Class + * + * @param packageName + * @param packagePath + * @param recursive + * @param classes + */ + public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, + Set classes) { + // 获取此包的目录 建立一个File + File dir = new File(packagePath); + // 如果不存在或者 也不是目录就直接返回 + if (!dir.exists() || !dir.isDirectory()) { + // log.warn("用户定义包名 " + packageName + " 下没有任何文件"); + return; + } + // 如果存在 就获取包下的所有文件 包括目录 + File[] dirfiles = dir.listFiles(new FileFilter() { + // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.xml结尾的文件 + public boolean accept(File file) { + return (recursive && file.isDirectory()) || (file.getName().endsWith(".xml")); + } + }); + // 循环所有文件 + for (File file : dirfiles) { + // 如果是目录 则继续扫描 + if (file.isDirectory()) { + findAndAddClassesInPackageByFile(packageName + "/" + file.getName(), file.getAbsolutePath(), recursive, + classes); + } else { + String className = file.getName(); + classes.add(packageName + '/' + className); + } + } + } +} diff --git a/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/util/extend/MyDataSourceFactory.java b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/util/extend/MyDataSourceFactory.java new file mode 100644 index 0000000..5545f22 --- /dev/null +++ b/mars-jdbc/mars-mybatis/src/main/java/com/yuyenews/easy/util/extend/MyDataSourceFactory.java @@ -0,0 +1,32 @@ +package com.yuyenews.easy.util.extend; + +import com.alibaba.druid.pool.DruidDataSourceFactory; +import com.yuyenews.core.logger.GogeLogger; +import org.apache.ibatis.datasource.DataSourceFactory; + +import javax.sql.DataSource; +import java.util.Properties; + +public class MyDataSourceFactory extends DruidDataSourceFactory implements DataSourceFactory { + + private GogeLogger logger = GogeLogger.getLogger(MyDataSourceFactory.class); + + protected Properties properties; + + @Override + public void setProperties(Properties props) { + this.properties = props; + } + + @Override + public DataSource getDataSource() { + try { + return createDataSource(properties); + } catch (Exception e) { + logger.error("",e); + } + + return null; + } + +} diff --git a/mars-jdbc/pom.xml b/mars-jdbc/pom.xml new file mode 100644 index 0000000..162aebb --- /dev/null +++ b/mars-jdbc/pom.xml @@ -0,0 +1,20 @@ + + + + Mars-java + com.gitee.sherlockholmnes + 2.1.0 + + 4.0.0 + pom + mars-jdbc + + + mars-mybatis + mars-jpa + mars-jdbc-base + + + \ No newline at end of file diff --git a/mars-mvc/pom.xml b/mars-mvc/pom.xml new file mode 100644 index 0000000..ec5ef82 --- /dev/null +++ b/mars-mvc/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + + com.gitee.sherlockholmnes + Mars-java + 2.1.0 + + mars-mvc + + + + com.gitee.sherlockholmnes + mars-netty + + + \ No newline at end of file diff --git a/mars-mvc/src/main/java/com/yuyenews/base/BaseInterceptor.java b/mars-mvc/src/main/java/com/yuyenews/base/BaseInterceptor.java new file mode 100644 index 0000000..cb86cc0 --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/base/BaseInterceptor.java @@ -0,0 +1,39 @@ +package com.yuyenews.base; + +import com.yuyenews.easy.server.request.HttpRequest; +import com.yuyenews.easy.server.request.HttpResponse; + +/** + * 拦截器基类,强制继承 + * @author yuye + * + */ +public interface BaseInterceptor { + + /** + * 通过 + */ + String SUCCESS = "success"; + + /** + * 不通过 + */ + String ERROR = "error"; + + /** + * 控制层执行之前 + * @param request + * @param response + * @return + */ + Object startRequest(HttpRequest request,HttpResponse response); + + /** + * 控制层执行之后 + * @param request + * @param response + * @param obj 控制层返回的数据 + * @return + */ + Object endRequest(HttpRequest request,HttpResponse response,Object obj); +} diff --git a/mars-mvc/src/main/java/com/yuyenews/logs/LogAop.java b/mars-mvc/src/main/java/com/yuyenews/logs/LogAop.java new file mode 100644 index 0000000..7044149 --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/logs/LogAop.java @@ -0,0 +1,80 @@ +package com.yuyenews.logs; + +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.easy.server.request.HttpRequest; + +import java.util.Map; + +/** + * controller方法打印日志 + */ +public class LogAop { + + private GogeLogger logger = GogeLogger.getLogger(LogAop.class); + + private Class cls; + private String methodName; + + public LogAop(Class cls,String methodName){ + this.cls = cls; + this.methodName = methodName; + } + + /** + * controller方法开始执行 + * @param args + */ + public void startMethod(Object[] args) { + Object obj = args[0]; + if(obj != null && obj instanceof HttpRequest){ + HttpRequest request = (HttpRequest)obj; + Map params = request.getParemeters(); + + StringBuffer buffer = new StringBuffer(); + buffer.append("开始执行"); + buffer.append(cls.getName()); + buffer.append("->"); + buffer.append(methodName); + buffer.append(",参数:["); + buffer.append(JSONObject.toJSONString(params)); + buffer.append("]"); + + logger.info(buffer.toString()); + } + } + + /** + * controller方法结束执行 + * @param args + * @param result + */ + public void endMethod(Object[] args,Object result) { + + StringBuffer buffer = new StringBuffer(); + buffer.append("执行结束"); + buffer.append(cls.getName()); + buffer.append("->"); + buffer.append(methodName); + buffer.append(",返回数据:["); + buffer.append(JSONObject.toJSONString(result)); + buffer.append("]"); + + logger.info(buffer.toString()); + } + + /** + * controller方法出异常 + * @param e + */ + public void exp(Throwable e){ + StringBuffer buffer = new StringBuffer(); + buffer.append("执行异常"); + buffer.append(cls.getName()); + buffer.append("->"); + buffer.append(methodName); + buffer.append(",异常信息:"); + + logger.error(buffer.toString(),e); + } +} diff --git a/mars-mvc/src/main/java/com/yuyenews/proxy/MvcCglibProxy.java b/mars-mvc/src/main/java/com/yuyenews/proxy/MvcCglibProxy.java new file mode 100644 index 0000000..4714542 --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/proxy/MvcCglibProxy.java @@ -0,0 +1,68 @@ +package com.yuyenews.proxy; + +import com.yuyenews.core.annotation.EasyLog; +import com.yuyenews.logs.LogAop; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; + +/** + * 代理类 + * @author yuye + * + */ +public class MvcCglibProxy implements MethodInterceptor { + + private Enhancer enhancer; + + private Class cls; + + /** + * 获取代理对象 + * @param clazz bean的class + * @return 对象 + */ + public Object getProxy(Class clazz) { + this.cls = clazz; + + enhancer = new Enhancer(); + // 设置需要创建子类的类 + enhancer.setSuperclass(clazz); + enhancer.setCallback(this); + // 通过字节码技术动态创建子类实例 + return enhancer.create(); + } + + + /** + * 绑定代理 + */ + @Override + public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + LogAop c = null; + + EasyLog easyLog = method.getAnnotation(EasyLog.class); + if(easyLog != null){ + c = new LogAop(cls,method.getName()); + c.startMethod(args); + } + + try{ + Object o1 = methodProxy.invokeSuper(o, args); + + if(c != null){ + c.endMethod(args,o1); + } + + return o1; + } catch (Throwable e) { + if(c != null) { + c.exp(e); + } + throw e; + } + } + +} diff --git a/mars-mvc/src/main/java/com/yuyenews/remote/config/RemoteConfigController.java b/mars-mvc/src/main/java/com/yuyenews/remote/config/RemoteConfigController.java new file mode 100644 index 0000000..0653410 --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/remote/config/RemoteConfigController.java @@ -0,0 +1,42 @@ +package com.yuyenews.remote.config; + +import com.yuyenews.core.annotation.Controller; +import com.yuyenews.core.annotation.EasyLog; +import com.yuyenews.core.annotation.EasyMapping; +import com.yuyenews.core.annotation.enums.RequestMetohd; +import com.yuyenews.core.remote.config.RemoteConfigService; +import com.yuyenews.easy.server.request.HttpRequest; +import com.yuyenews.easy.server.request.HttpResponse; + +import java.util.HashMap; +import java.util.Map; + +/** + * 修改远程配置后 接受配置中心的通知 + */ +@Controller +public class RemoteConfigController { + + /** + * 重新加载配置 + * @param request + * @param response + * @return 结果 + */ + @EasyMapping(value = "reloadConfig",method = RequestMetohd.POST) + @EasyLog + public Map reloadConfig(HttpRequest request, HttpResponse response) { + Object config = request.getParemeter("config"); + String result = RemoteConfigService.reloadConfig(config); + + Map returns = new HashMap<>(); + if(result.equals("ok")){ + returns.put("msg","通知成功"); + returns.put("success","ok"); + } else { + returns.put("msg","通知失败"); + returns.put("success","no"); + } + return returns; + } +} diff --git a/mars-mvc/src/main/java/com/yuyenews/resolve/ExecuteEasy.java b/mars-mvc/src/main/java/com/yuyenews/resolve/ExecuteEasy.java new file mode 100644 index 0000000..a217214 --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/resolve/ExecuteEasy.java @@ -0,0 +1,101 @@ +package com.yuyenews.resolve; + +import com.yuyenews.base.BaseInterceptor; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.MesUtil; +import com.yuyenews.easy.server.request.HttpRequest; +import com.yuyenews.easy.server.request.HttpResponse; +import com.yuyenews.easy.util.RequestUtil; +import com.yuyenews.resolve.model.EasyMappingModel; +import io.netty.handler.codec.http.HttpMethod; + +import java.lang.reflect.Method; +import java.util.List; + +/** + * 执行器 + * + * @author yuye + * + */ +public class ExecuteEasy { + + private GogeLogger log = GogeLogger.getLogger(ExecuteEasy.class); + + private static ExecuteEasy executeEasy; + + private ExecuteEasy() { + } + + public static ExecuteEasy getExecuteEasy() { + if (executeEasy == null) { + executeEasy = new ExecuteEasy(); + } + return executeEasy; + } + + /** + * 执行controller + * @param easyMappingModel duix + * @param method fangfa + * @param request qingqiu + * @param response xiangying + * @return duix + */ + public Object execute(EasyMappingModel easyMappingModel, HttpMethod method, HttpRequest request, HttpResponse response) { + + try { + + if(easyMappingModel == null) { + return MesUtil.getMes(404,"服务器上没有相应的接口"); + } + + String strMethod = method.name().toString().toLowerCase(); + + String mathodReuest = easyMappingModel.getRequestMetohd().name().toLowerCase(); + + if (strMethod.equals(mathodReuest)) { + + /* 获取拦截器 并执行 控制层执行前的方法 */ + String uriEnd = RequestUtil.getUriName(request); + List list = ExecuteInters.getInters(uriEnd); + Object inres = ExecuteInters.executeIntersStart(list,request, response); + if(!inres.toString().equals(BaseInterceptor.SUCCESS)) { + return inres; + } + + /* 获取要执行的controller的信息 */ + Object obj = easyMappingModel.getObject(); + Class cls = easyMappingModel.getCls(); + Method method2 = cls.getDeclaredMethod(easyMappingModel.getMethod(), new Class[] { HttpRequest.class, HttpResponse.class }); + + /* 获取controller返回值的类型 */ + Class cl = method2.getReturnType(); + String st = cl.getName(); + + Object result = null; + if(st.toLowerCase().trim().equals("void")){ + method2.invoke(obj, new Object[] { request, response }); + result = "void405cb55d6781877e9e930aa8e046098b"; + } else { + result = method2.invoke(obj, new Object[] { request, response }); + } + + /* 执行拦截器 在控制层执行后的方法 */ + Object inres2 = ExecuteInters.executeIntersEnd(list,request, response,result); + if(!inres2.toString().equals(BaseInterceptor.SUCCESS)) { + return inres2; + } + + return result; + } else { + /* 如果请求方式和controller的映射不一致,则提示客户端 */ + return MesUtil.getMes(403,"此接口的请求方式为[" + mathodReuest + "]"); + } + } catch (Exception e) { + log.error("执行控制层的时候报错",e); + return MesUtil.getMes(500,"执行控制层的时候报错"); + } + } + +} diff --git a/mars-mvc/src/main/java/com/yuyenews/resolve/ExecuteInters.java b/mars-mvc/src/main/java/com/yuyenews/resolve/ExecuteInters.java new file mode 100644 index 0000000..76699b7 --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/resolve/ExecuteInters.java @@ -0,0 +1,127 @@ +package com.yuyenews.resolve; + +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.base.BaseInterceptor; +import com.yuyenews.core.annotation.EasyInterceptor; +import com.yuyenews.core.constant.EasyConstant; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.MatchUtil; +import com.yuyenews.core.util.MesUtil; +import com.yuyenews.easy.server.request.HttpRequest; +import com.yuyenews.easy.server.request.HttpResponse; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 执行拦截器 + * @author yuye + * + */ +public class ExecuteInters { + + private static GogeLogger logger = GogeLogger.getLogger(ExecuteInters.class); + + /** + * 执行拦截器的开始方法 + * @param list jihe + * @param request qingqiu + * @param response xiangying + * @return duix + */ + public static Object executeIntersStart(List list,HttpRequest request, HttpResponse response) { + Class clss = null; + try { + for(Object obj : list) { + clss = obj.getClass(); + + Method method2 = clss.getDeclaredMethod("startRequest", new Class[] { HttpRequest.class, HttpResponse.class }); + Object result = method2.invoke(obj, new Object[] { request, response }); + if(!result.toString().equals(BaseInterceptor.SUCCESS)) { + return result; + } + } + + return BaseInterceptor.SUCCESS; + } catch (Exception e) { + logger.error("执行拦截器报错,拦截器类型["+clss.getName()+"]",e); + return errorResult(clss); + } + + } + + /** + * 执行拦截器的结束方法 + * @param list jihe + * @param request qingqiu + * @param response xiangying + * @return duix + */ + public static Object executeIntersEnd(List list,HttpRequest request, HttpResponse response,Object objs) { + Class clss = null; + try { + + for(Object obj : list) { + clss = obj.getClass(); + + Method method2 = clss.getDeclaredMethod("endRequest", new Class[] { HttpRequest.class, HttpResponse.class, Object.class }); + Object result = method2.invoke(obj, new Object[] { request, response, objs }); + if(!result.toString().equals(BaseInterceptor.SUCCESS)) { + return result; + } + } + + return BaseInterceptor.SUCCESS; + } catch (Exception e) { + logger.error("执行拦截器报错,拦截器类型["+clss.getName()+"]",e); + return errorResult(clss); + } + } + + /** + * 获取所有符合条件的拦截器 + * @param uriEnd uel + * @return duix + */ + public static List getInters(String uriEnd){ + + try { + List list = new ArrayList<>(); + + Object objs = EasySpace.getEasySpace().getAttr(EasyConstant.INTERCEPTORS); + + if(objs != null) { + List> interceptors = (List>)objs; + + for(Map map : interceptors) { + + EasyInterceptor easyInterceptor = (EasyInterceptor)map.get("annotation"); + String pattern = easyInterceptor.pattern(); + + if(MatchUtil.isMatch(pattern, uriEnd)){ + Class cls = (Class)map.get("className"); + list.add(cls.getDeclaredConstructor().newInstance()); + } + } + } + + + return list; + } catch (Exception e) { + logger.error("读取拦截器报错",e); + return new ArrayList<>(); + } + } + + /** + * 返回错误信息 + * @param cls + * @return + */ + private static JSONObject errorResult(Class cls) { + return MesUtil.getMes(500,"执行拦截器报错,拦截器类型["+cls.getName()+"]"); + } +} diff --git a/mars-mvc/src/main/java/com/yuyenews/resolve/LoadController.java b/mars-mvc/src/main/java/com/yuyenews/resolve/LoadController.java new file mode 100644 index 0000000..a379034 --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/resolve/LoadController.java @@ -0,0 +1,143 @@ +package com.yuyenews.resolve; + +import com.yuyenews.core.annotation.Controller; +import com.yuyenews.core.annotation.EasyMapping; +import com.yuyenews.core.annotation.Resource; +import com.yuyenews.core.constant.EasyConstant; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.model.EasyBeanModel; +import com.yuyenews.proxy.MvcCglibProxy; +import com.yuyenews.resolve.model.EasyMappingModel; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 加载所有的controller,并完成注入 + * @author yuye + * + */ +public class LoadController { + + private static GogeLogger log = GogeLogger.getLogger(LoadController.class); + + /** + * 获取全局存储空间 + */ + private static EasySpace constants = EasySpace.getEasySpace(); + + /** + * 创建controller对象,并将服务层对象注入进去 + */ + @SuppressWarnings("unchecked") + public static void loadContrl() throws Exception{ + + try { + Map controlObjects = new HashMap<>(); + + /* 获取所有的controller数据 */ + Object objs = constants.getAttr(EasyConstant.CONTROLLERS); + List> contorls = null; + if(objs != null) { + contorls = (List>)objs; + } else { + return; + } + + Map easyBeanObjs = getEasyBeans(); + + for(Map map : contorls) { + + Class cls = (Class)map.get("className"); + Controller control = (Controller)map.get("annotation"); + + /* + * 由于controller里只允许注入easybean,所以不需要等controller都创建好了再注入 + * 直接 迭代一次 就给一个controller注入一次 + */ + Object obj = iocControl(cls,control,easyBeanObjs); + + if(obj != null) { + /* 获取controller的所有方法 */ + Method[] methods = cls.getMethods(); + for(Method method : methods) { + EasyMapping easyMapping = method.getAnnotation(EasyMapping.class); + if(easyMapping != null) { + EasyMappingModel easyMappingModel = new EasyMappingModel(); + easyMappingModel.setObject(obj); + easyMappingModel.setRequestMetohd(easyMapping.method()); + easyMappingModel.setMethod(method.getName()); + easyMappingModel.setCls(cls); + controlObjects.put(easyMapping.value(), easyMappingModel); + } + } + } + } + + constants.setAttr(EasyConstant.CONTROLLER_OBJECTS, controlObjects); + } catch (Exception e) { + throw new Exception("加载controller并注入的时候报错",e); + } + } + + /** + * 往controller对象中注入easybean + * @param cls lei + * @param control kongzhi + * @param easyBeanObjs duix + * @return duix + */ + private static Object iocControl(Class cls,Controller control,Map easyBeanObjs) throws Exception{ + + try { + + MvcCglibProxy mvcCglibProxy = new MvcCglibProxy(); + Object obj = mvcCglibProxy.getProxy(cls); + + /* 获取对象属性,完成注入 */ + Field[] fields = cls.getDeclaredFields(); + for(Field f : fields){ + Resource resource = f.getAnnotation(Resource.class); + if(resource!=null){ + f.setAccessible(true); + + String filedName = resource.value(); + if(filedName == null || filedName.equals("")) { + filedName = f.getName(); + } + + EasyBeanModel beanModel = easyBeanObjs.get(filedName); + if(beanModel!=null){ + f.set(obj, beanModel.getObj()); + log.info(cls.getName()+"的属性"+f.getName()+"注入成功"); + }else{ + throw new Exception("不存在name为"+filedName+"的easyBean"); + } + } + } + + return obj; + } catch (Exception e) { + throw new Exception("创建controller并注入的时候报错",e); + } + } + + /** + * 获取所有的easybean + * @return duix + */ + @SuppressWarnings("unchecked") + private static Map getEasyBeans() { + Object objs2 = constants.getAttr(EasyConstant.EASYBEAN_OBJECTS); + Map easyBeanObjs = new HashMap<>(); + if(objs2 != null) { + easyBeanObjs = (Map)objs2; + } + + return easyBeanObjs; + } +} diff --git a/mars-mvc/src/main/java/com/yuyenews/resolve/ResolveRequest.java b/mars-mvc/src/main/java/com/yuyenews/resolve/ResolveRequest.java new file mode 100644 index 0000000..abcb9cc --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/resolve/ResolveRequest.java @@ -0,0 +1,89 @@ +package com.yuyenews.resolve; + +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.MesUtil; +import com.yuyenews.easy.server.request.HttpRequest; +import com.yuyenews.easy.server.request.HttpResponse; +import com.yuyenews.easy.util.RequestUtil; +import com.yuyenews.resolve.model.EasyMappingModel; + +import java.util.Map; + +/** + * 解析请求 + * @author yuye + * + */ +public class ResolveRequest { + + private static GogeLogger log = GogeLogger.getLogger(ResolveRequest.class); + + private static ResolveRequest resolveRequest; + + private EasySpace constants = EasySpace.getEasySpace(); + + /** + * 执行器对象 + */ + private ExecuteEasy executeEasy = ExecuteEasy.getExecuteEasy(); + + private ResolveRequest() {} + + public static ResolveRequest getResolveRequest() { + if(resolveRequest == null) { + resolveRequest = new ResolveRequest(); + } + return resolveRequest; + } + + /** + * 解释请求,并调用对应的控制层方法进行处理 + * @param request qingqiu + * @param response xiangying + * @return duix + */ + public Object resolve(HttpRequest request,HttpResponse response) { + + try { + Map maps = getControllers(); + + String uri = getRequestPath(request); + + return executeEasy.execute(maps.get(uri),request.getMethod(),request,response); + } catch (Exception e) { + log.error("解释请求的时候报错",e); + } + return MesUtil.getMes(500,"解析请求报错"); + } + + /** + * 从uri中提取 请求连接的最末端,用来匹配控制层映射 + * @param request qingqiu + * @return + */ + private String getRequestPath(HttpRequest request) { + /* 获取路径 */ + String uri = RequestUtil.getUriName(request); + if(uri.startsWith("/")) { + uri = uri.substring(1); + } + return uri; + } + + /** + * 获取所有的controller对象 + * @return duix + */ + @SuppressWarnings("unchecked") + private Map getControllers() { + + Map controlObjects = null; + Object obj = constants.getAttr("controlObjects"); + if(obj != null) { + controlObjects = (Map)obj; + } + + return controlObjects; + } +} diff --git a/mars-mvc/src/main/java/com/yuyenews/resolve/model/EasyMappingModel.java b/mars-mvc/src/main/java/com/yuyenews/resolve/model/EasyMappingModel.java new file mode 100644 index 0000000..03d6844 --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/resolve/model/EasyMappingModel.java @@ -0,0 +1,65 @@ +package com.yuyenews.resolve.model; + +import com.yuyenews.core.annotation.enums.RequestMetohd; + +/** + * 控制器映射实体 + * + * @author yuye + * + */ +public class EasyMappingModel { + + /** + * 对象 + */ + private Object object; + + /** + * 请求方式 + */ + private RequestMetohd requestMetohd; + + /** + * 映射的方法 + */ + private String method; + + /** + * 控制层class对象 + */ + private Class cls; + + public Object getObject() { + return object; + } + + public void setObject(Object object) { + this.object = object; + } + + public RequestMetohd getRequestMetohd() { + return requestMetohd; + } + + public void setRequestMetohd(RequestMetohd requestMetohd) { + this.requestMetohd = requestMetohd; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public Class getCls() { + return cls; + } + + public void setCls(Class cls) { + this.cls = cls; + } + +} diff --git a/mars-mvc/src/main/java/com/yuyenews/servlcet/EasyCoreServlet.java b/mars-mvc/src/main/java/com/yuyenews/servlcet/EasyCoreServlet.java new file mode 100644 index 0000000..28b60b8 --- /dev/null +++ b/mars-mvc/src/main/java/com/yuyenews/servlcet/EasyCoreServlet.java @@ -0,0 +1,36 @@ +package com.yuyenews.servlcet; + +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.MesUtil; +import com.yuyenews.easy.server.request.HttpRequest; +import com.yuyenews.easy.server.request.HttpResponse; +import com.yuyenews.easy.server.servlet.EasyServlet; +import com.yuyenews.resolve.ResolveRequest; + +/** + * 核心servlet,用于接收所有请求,并调用相应的方法进行处理 + * @author yuye + * + */ +public class EasyCoreServlet implements EasyServlet{ + + private static GogeLogger log = GogeLogger.getLogger(EasyCoreServlet.class); + + @Override + public Object doRequest(HttpRequest request, HttpResponse response) { + try { + + /* 将请求丢给解释器 去解释,并调用对应的控制层方法进行处理 */ + ResolveRequest resolveRequest = ResolveRequest.getResolveRequest(); + Object result = resolveRequest.resolve(request,response); + + /*将控制层 返回的结果 返回给netty,让其响应给客户端*/ + return result; + + } catch (Exception e) { + log.error("解释请求的时候报错",e); + } + return MesUtil.getMes(500,"解析请求报错"); + } + +} diff --git a/mars-netty/pom.xml b/mars-netty/pom.xml new file mode 100644 index 0000000..13be44b --- /dev/null +++ b/mars-netty/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + + com.gitee.sherlockholmnes + Mars-java + 2.1.0 + + mars-netty + + + + com.gitee.sherlockholmnes + mars-server + + + \ No newline at end of file diff --git a/mars-netty/src/main/java/com/yuyenews/easy/netty/server/EasyServer.java b/mars-netty/src/main/java/com/yuyenews/easy/netty/server/EasyServer.java new file mode 100644 index 0000000..de142f2 --- /dev/null +++ b/mars-netty/src/main/java/com/yuyenews/easy/netty/server/EasyServer.java @@ -0,0 +1,47 @@ +package com.yuyenews.easy.netty.server; + +import com.yuyenews.core.logger.GogeLogger; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +/** + * netty服务 + * @author yuye + * + */ +public class EasyServer { + + private static GogeLogger log = GogeLogger.getLogger(EasyServer.class); + + /** + * 启动netty服务 + * @param portNumber + */ + public static void start(final int portNumber) { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + try { + + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup); + b.channel(NioServerSocketChannel.class); + b.childHandler(new EasyServerInitializer()); + + /* 服务器绑定端口监听 */ + ChannelFuture f = b.bind(portNumber).sync(); + + log.info("启动结束"); + + /* 监听服务器关闭监听 */ + f.channel().closeFuture().sync(); + } catch (Exception e) { + log.error("启动netty报错",e); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } +} diff --git a/mars-netty/src/main/java/com/yuyenews/easy/netty/server/EasyServerHandler.java b/mars-netty/src/main/java/com/yuyenews/easy/netty/server/EasyServerHandler.java new file mode 100644 index 0000000..c1317a2 --- /dev/null +++ b/mars-netty/src/main/java/com/yuyenews/easy/netty/server/EasyServerHandler.java @@ -0,0 +1,112 @@ +package com.yuyenews.easy.netty.server; + +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.MesUtil; +import com.yuyenews.easy.netty.thread.RequestThread; +import com.yuyenews.easy.netty.thread.ThreadPool; +import com.yuyenews.easy.server.request.HttpResponse; +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.timeout.IdleStateEvent; + +import java.net.InetAddress; + +/** + * 接收netty服务 + * @author yuye + * + */ +public class EasyServerHandler extends ChannelHandlerAdapter { + + private GogeLogger log = GogeLogger.getLogger(EasyServerHandler.class); + + /** + * 接收并处理 客户端请求 + */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + + FullHttpRequest httpRequest = null; + + try { + if (msg instanceof FullHttpRequest) { + + httpRequest = (FullHttpRequest) msg; + + /* 用新线程处理请求 */ + RequestThread requestThread = new RequestThread(); + requestThread.setHttpRequest(httpRequest); + requestThread.setCtx(ctx); + ThreadPool.execute(requestThread); + } else { + sendBad(ctx,"处理请求发生错误"); + } + + } catch (Exception e) { + log.error("处理请求失败!", e); + sendBad(ctx,"处理请求发生错误"+e); + + /* 已经通过线程中的finally 释放请求了,所以这里,在出异常的时候,才释放 */ + try { + httpRequest.release(); + } catch (Exception e2) { + } + } + } + + + + /** + * 建立连接时,返回消息 + */ + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ctx.writeAndFlush("客户端" + InetAddress.getLocalHost().getHostName() + "成功与服务端建立连接! "); + super.channelActive(ctx); + } + + /** + * 超时处理 + * @param ctx + * @param evt + * @throws Exception + */ + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if(evt instanceof IdleStateEvent){ + IdleStateEvent idleStateEvent = (IdleStateEvent)evt; + + switch (idleStateEvent.state()){ + case READER_IDLE: + sendTimeout(ctx,"请求超时"); + break; + case WRITER_IDLE: + sendTimeout(ctx,"请求超时"); + break; + default: + super.userEventTriggered(ctx, evt); + } + } + } + + + /** + * 响应 + * @param ctx + */ + private void sendBad(ChannelHandlerContext ctx,String ex){ + HttpResponse response = new HttpResponse(ctx); + response.send(MesUtil.getMes(500,ex).toJSONString(), HttpResponseStatus.BAD_REQUEST); + } + + /** + * 响应请求超时 + * @param ctx + */ + private void sendTimeout(ChannelHandlerContext ctx,String ex){ + HttpResponse response = new HttpResponse(ctx); + response.send(MesUtil.getMes(503,ex).toJSONString(), HttpResponseStatus.BAD_REQUEST); + } +} diff --git a/mars-netty/src/main/java/com/yuyenews/easy/netty/server/EasyServerInitializer.java b/mars-netty/src/main/java/com/yuyenews/easy/netty/server/EasyServerInitializer.java new file mode 100644 index 0000000..4c2882e --- /dev/null +++ b/mars-netty/src/main/java/com/yuyenews/easy/netty/server/EasyServerInitializer.java @@ -0,0 +1,65 @@ +package com.yuyenews.easy.netty.server; + +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.core.util.ConfigUtil; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpRequestDecoder; +import io.netty.handler.codec.http.HttpResponseEncoder; +import io.netty.handler.timeout.IdleStateHandler; + +/** + * 定义netty服务 + * @author yuye + * + */ +public class EasyServerInitializer extends ChannelInitializer { + + private int timeOut = 10; + private int maxContentLength = 10485760; + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + + /* 加载配置文件 */ + getConfig(); + + /* 处理http服务的关键handler */ + ChannelPipeline ph = ch.pipeline(); + ph.addLast("idlestatus", getIdleStateHandler()); + ph.addLast("encoder", new HttpResponseEncoder()); + ph.addLast("decoder", new HttpRequestDecoder()); + ph.addLast("aggregator", getHttpObjectAggregator()); + ph.addLast("handler", new EasyServerHandler());// 服务端业务逻辑 + } + + + private IdleStateHandler getIdleStateHandler(){ + return new IdleStateHandler(timeOut,2000000000,0); + } + + private HttpObjectAggregator getHttpObjectAggregator(){ + return new HttpObjectAggregator(maxContentLength); + } + + /** + * 超时时间 + * @return + */ + private void getConfig() { + + JSONObject jsonObject = ConfigUtil.getConfig(); + Object timeOuto = jsonObject.get("timeOut"); + Object maxContentLengtho = jsonObject.get("maxContentLength"); + + if(timeOuto!=null) { + timeOut = Integer.parseInt(timeOuto.toString()); + } + + if(maxContentLengtho != null){ + maxContentLength = Integer.parseInt(maxContentLengtho.toString()); + } + } +} diff --git a/mars-netty/src/main/java/com/yuyenews/easy/netty/thread/RequestThread.java b/mars-netty/src/main/java/com/yuyenews/easy/netty/thread/RequestThread.java new file mode 100644 index 0000000..0060db2 --- /dev/null +++ b/mars-netty/src/main/java/com/yuyenews/easy/netty/thread/RequestThread.java @@ -0,0 +1,72 @@ +package com.yuyenews.easy.netty.thread; + +import com.alibaba.fastjson.JSON; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.MesUtil; +import com.yuyenews.easy.server.request.HttpRequest; +import com.yuyenews.easy.server.request.HttpResponse; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; + +import java.lang.reflect.Method; + +/** + * 处理请求的线程 + * @author yuye + * + */ +public class RequestThread implements Runnable { + + private GogeLogger log = GogeLogger.getLogger(RequestThread.class); + + /** + * netty的request对象 + */ + private FullHttpRequest httpRequest; + + private ChannelHandlerContext ctx; + + public void setHttpRequest(FullHttpRequest httpRequest) { + this.httpRequest = httpRequest; + } + + public void setCtx(ChannelHandlerContext ctx) { + this.ctx = ctx; + } + + public void run() { + + /* 组装httprequest对象 */ + HttpRequest request = new HttpRequest(httpRequest,ctx); + + /* 组装httpresponse对象 */ + HttpResponse response = new HttpResponse(ctx); + + try { + + /* 获取全局存储空间 */ + EasySpace constants = EasySpace.getEasySpace(); + /* 从存储空间里获取核心servlet的全限名 */ + String className = constants.getAttr("core").toString(); + + /* 通过反射执行核心servlet */ + Class cls = Class.forName(className); + Object object = cls.getDeclaredConstructor().newInstance(); + Method helloMethod = cls.getDeclaredMethod("doRequest", new Class[] { HttpRequest.class ,HttpResponse.class}); + Object result = helloMethod.invoke(object, new Object[] { request ,response}); + if(result != null && result.toString().equals("void405cb55d6781877e9e930aa8e046098b")) { + return; + } + /* 将控制层返回的数据,转成json字符串返回 */ + response.send(JSON.toJSONString(result)); + + } catch (Exception e) { + log.error("处理请求的时候出错",e); + response.send(MesUtil.getMes(500,"处理请求发生错误"+e).toJSONString()); + } finally { + // 释放请求 + httpRequest.release(); + } + } +} diff --git a/mars-netty/src/main/java/com/yuyenews/easy/netty/thread/ThreadPool.java b/mars-netty/src/main/java/com/yuyenews/easy/netty/thread/ThreadPool.java new file mode 100644 index 0000000..46ee32e --- /dev/null +++ b/mars-netty/src/main/java/com/yuyenews/easy/netty/thread/ThreadPool.java @@ -0,0 +1,66 @@ +package com.yuyenews.easy.netty.thread; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.core.util.ConfigUtil; + +import java.util.concurrent.*; + +/** + * 线程池,用于处理并发 + * @author yuye + * + */ +public class ThreadPool { + + private static BlockingQueue workQueue; + + private static ThreadPoolExecutor pool; + + private static int corePoolSize = 100; + + private static int maximumPoolSize = 1000; + + private static int keepAliveTime = 60; + + + + /** + * 新增请求的线程 + * @param command + */ + public static void execute(Runnable command) { + if(pool == null){ + init(); + workQueue = new ArrayBlockingQueue<>(maximumPoolSize - corePoolSize); + pool = new ThreadPoolExecutor(corePoolSize,maximumPoolSize, keepAliveTime,TimeUnit.SECONDS,workQueue); + } + pool.execute(command); + } + + /** + * 读取线程池的配置 + */ + private static void init(){ + JSONObject jsonObject = ConfigUtil.getConfig(); + Object obj = jsonObject.get("threadPool"); + if(obj != null){ + JSONObject threadPool = JSONObject.parseObject(JSON.toJSONString(obj)); + + Object cs = threadPool.get("corePoolSize"); + Object mp = threadPool.get("maximumPoolSize"); + Object kt = threadPool.get("keepAliveTime"); + + if(cs != null){ + corePoolSize = Integer.parseInt(cs.toString()); + } + if(mp != null){ + maximumPoolSize = Integer.parseInt(mp.toString()); + } + if(kt != null){ + keepAliveTime = Integer.parseInt(kt.toString()); + } + } + } +} + diff --git a/mars-server/pom.xml b/mars-server/pom.xml new file mode 100644 index 0000000..f962a56 --- /dev/null +++ b/mars-server/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + com.gitee.sherlockholmnes + Mars-java + 2.1.0 + + mars-server + + + + io.netty + netty-all + + + com.auth0 + java-jwt + + + + com.gitee.sherlockholmnes + mars-ioc + + + \ No newline at end of file diff --git a/mars-server/src/main/java/com/yuyenews/easy/server/jwt/JwtManager.java b/mars-server/src/main/java/com/yuyenews/easy/server/jwt/JwtManager.java new file mode 100644 index 0000000..5c8f391 --- /dev/null +++ b/mars-server/src/main/java/com/yuyenews/easy/server/jwt/JwtManager.java @@ -0,0 +1,138 @@ +package com.yuyenews.easy.server.jwt; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTCreator; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.yuyenews.core.util.ConfigUtil; + +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * JWT管理类 + */ +public class JwtManager { + /** + * token秘钥 + */ + private final String SECRET = "gogeframworkwinno1123456"; + /** + * token 过期时间: 10天 + */ + private final int calendarField = Calendar.DATE; + private int calendarInterval = 10; + + private static JwtManager jwtManager; + private JwtManager(){} + + public static JwtManager getJwtManager(){ + if(jwtManager == null){ + jwtManager = new JwtManager(); + jwtManager.loadCalendarInterval(); + } + return jwtManager; + } + + /** + * 加载配置文件中的jwt失效时间 + */ + private void loadCalendarInterval(){ + JSONObject config = ConfigUtil.getConfig(); + Object jwtTime = config.get("jwtTime"); + + if(jwtTime != null){ + calendarInterval = Integer.parseInt(jwtTime.toString()); + } + } + + /** + * WT生成Token. + * @param obj + * @return str + */ + public String createToken(Object obj) { + Date iatDate = new Date(); + // expire time + Calendar nowTime = Calendar.getInstance(); + nowTime.add(calendarField, calendarInterval); + Date expiresDate = nowTime.getTime(); + + // header Map + Map map = new HashMap<>(); + map.put("alg", "HS256"); + map.put("typ", "JWT"); + + // header + JWTCreator.Builder builder = JWT.create().withHeader(map); + // payload + + JSONObject json = JSONObject.parseObject(JSON.toJSONString(obj)); + + for (String key : json.keySet()) { + builder.withClaim(key, json.get(key).toString()); + } + + builder.withIssuedAt(iatDate); // sign time + builder.withExpiresAt(expiresDate); // expire time + String token = builder.sign(Algorithm.HMAC256(SECRET)); // signature + + return token; + } + + /** + * 校验Token + * + * @param token + * @return map + */ + public boolean verifyToken(String token) { + Map claims = decryptToken(token); + return claims != null; + } + + /** + * 解密Token + * + * @param token + * @return map + */ + private Map decryptToken(String token) { + DecodedJWT jwt = null; + try { + JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build(); + jwt = verifier.verify(token); + return jwt.getClaims(); + } catch (Exception e) { + return null; + } + } + + /** + * 根据Token获取存进去的对象 + * @param token + * @param cls + * @param + * @return obj + */ + public T getObject(String token,Class cls) { + JSONObject json = new JSONObject(); + try { + Map claims = decryptToken(token); + for (String key : claims.keySet()) { + json.put(key, claims.get(key).asString()); + } + + return json.toJavaObject(cls); + } catch (Exception e) { + return null; + } + } + +} diff --git a/mars-server/src/main/java/com/yuyenews/easy/server/request/HttpContext.java b/mars-server/src/main/java/com/yuyenews/easy/server/request/HttpContext.java new file mode 100644 index 0000000..9ee6b60 --- /dev/null +++ b/mars-server/src/main/java/com/yuyenews/easy/server/request/HttpContext.java @@ -0,0 +1,48 @@ +package com.yuyenews.easy.server.request; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 全局对象,类似于tomcat的servletcontext + * + * @author yuye + * + */ +public class HttpContext { + + private static HttpContext context; + + private Map map = new ConcurrentHashMap<>(); + + private HttpContext() { + } + + public static HttpContext getHttpContext() { + if (context == null) { + context = new HttpContext(); + } + + return context; + } + + /** + * 往context里添加数据 + * + * @param key 键 + * @param value 值 + */ + public void setAttr(String key, Object value) { + map.put(key, value); + } + + /** + * 从context里获取数据 + * + * @param key 键 + * @return 值 + */ + public Object getAttr(String key) { + return map.get(key); + } +} diff --git a/mars-server/src/main/java/com/yuyenews/easy/server/request/HttpRequest.java b/mars-server/src/main/java/com/yuyenews/easy/server/request/HttpRequest.java new file mode 100644 index 0000000..4cb7b04 --- /dev/null +++ b/mars-server/src/main/java/com/yuyenews/easy/server/request/HttpRequest.java @@ -0,0 +1,241 @@ +package com.yuyenews.easy.server.request; + +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.easy.server.jwt.JwtManager; +import com.yuyenews.easy.server.request.model.FileUpLoad; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.util.CharsetUtil; + +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 请求对象,对原生netty的request的补充 + * @author yuye + * + */ +public class HttpRequest { + + private GogeLogger logger = GogeLogger.getLogger(HttpRequest.class); + + /** + * netty原生request + */ + private FullHttpRequest httpRequest; + + /** + * netty原生通道 + */ + private ChannelHandlerContext ctx; + + /** + * 请求体 + */ + private String body; + + /** + * 参数 + */ + private Map paremeters; + + /** + * 请求的文件 + */ + private Map files; + + /** + * 构造函数,框架自己用的,程序员用不到,用了也没意义 + * @param httpRequest + * @param ctx + */ + public HttpRequest(FullHttpRequest httpRequest,ChannelHandlerContext ctx) { + this.body = getBody(httpRequest); + this.setParameters(getParams(httpRequest)); + this.httpRequest = httpRequest; + this.ctx = ctx; + } + + /** + * 获取请求方法 + * @return 请求方法 + */ + public HttpMethod getMethod() { + return httpRequest.method(); + } + + /** + * 获取要请求的uri + * @return 请求方法 + */ + public String getUri() { + return httpRequest.uri(); + } + + /** + * 获取请求头数据 + * @param key 键 + * @return 头数据 + */ + public Object getHeader(String key) { + return httpRequest.headers().get(key); + } + + /** + * 获取请求头 + * @return 请求头 + */ + public HttpHeaders getHeaders() { + return httpRequest.headers(); + } + + /** + * 获取请求的参数集 + * @return 请求参数 + */ + public Map getParemeters() { + return paremeters; + } + + /** + * 组装请求的参数 + * @param paremeters 请求参数 + */ + private void setParameters(Map paremeters) { + Object obj = paremeters.get("files"); + if (obj != null) { + Map files = (Map) obj; + this.files = files; + paremeters.remove("files"); + } + + this.paremeters = paremeters; + + } + + /** + * 获取单个请求的参数 + * @param key 键 + * @return 请求参数 + */ + @SuppressWarnings("unchecked") + public Object getParemeter(String key) { + Object objs = paremeters.get(key); + if(objs != null) { + List lis = (List)objs; + return lis.get(0); + } + return null; + } + + /** + * 获取单个请求的参数 + * @param key 键 + * @return 请求参数 + */ + public List getParemeterValues(String key) { + Object objs = paremeters.get(key); + if(objs != null) { + List lis = (List)objs; + return lis; + } + return null; + } + + /** + * 获取请求的文件 + * @return 文件列表 + */ + public Map getFiles() { + return files; + } + + /** + * 获取单个请求的文件 + * + * @param name 名称 + * @return 单个文件 + */ + public FileUpLoad getFile(String name) { + if (files != null && files.size() > 0) { + return files.get(name); + } else { + return null; + } + } + + /** + * 获取请求的url + * @return 请求的路径 + */ + public String getUrl() { + return httpRequest.uri(); + } + + /** + * 获取请求的body + * @return 请求体 + */ + public String getBody() { + return body; + } + + /** + * 获取netty原生request + * @return 原生请求对象 + */ + public FullHttpRequest getFullHttpRequest() { + return httpRequest; + } + + /** + * 获取body参数 + * + * @param request 请求对象 + * @return 请求体 + */ + private String getBody(FullHttpRequest request) { + ByteBuf buf = request.content(); + return buf.toString(CharsetUtil.UTF_8); + } + + /** + * 将GET, POST所有请求参数转换成Map对象 + * @param request 原生请求对象 + * @return 请求参数 + */ + private Map getParams(FullHttpRequest request) { + try { + return new RequestParser(request).parse(); + } catch (Exception e) { + logger.error("从请求中获取参数,报错",e); + } + return new HashMap<>(); + } + + /** + * 获取JWT管理类对象 + * @return jwt + */ + public JwtManager getJwtManager(){ + return JwtManager.getJwtManager(); + } + + /** + * 获取客户端IP + * @return ip + */ + public String getIp() { + String clientIP = String.valueOf(httpRequest.headers().get("X-Forwarded-For")); + if (clientIP == null || clientIP.equals("null")) { + InetSocketAddress insocket = (InetSocketAddress) this.ctx.channel().remoteAddress(); + clientIP = insocket.getAddress().getHostAddress(); + } + return clientIP; + } +} diff --git a/mars-server/src/main/java/com/yuyenews/easy/server/request/HttpResponse.java b/mars-server/src/main/java/com/yuyenews/easy/server/request/HttpResponse.java new file mode 100644 index 0000000..d9ca08d --- /dev/null +++ b/mars-server/src/main/java/com/yuyenews/easy/server/request/HttpResponse.java @@ -0,0 +1,199 @@ +package com.yuyenews.easy.server.request; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.ConfigUtil; +import com.yuyenews.core.util.FileUtil; +import com.yuyenews.core.util.MesUtil; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.*; +import io.netty.util.CharsetUtil; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +/** + * 响应对象,对netty原生response的扩展 + *

+ * 暂时没有提供response的支持 + * + * @author yuye + */ +public class HttpResponse { + + private GogeLogger logger = GogeLogger.getLogger(HttpResponse.class); + + /** + * netty原生通道 + */ + private ChannelHandlerContext ctx; + + /** + * 响应头 + */ + private Map header; + + + /** + * 构造函数,框架自己用的,程序员用不到,用了也没意义 + * + * @param ctx netty原生通道 + */ + public HttpResponse(ChannelHandlerContext ctx) { + this.ctx = ctx; + this.header = new HashMap<>(); + } + + /** + * 获取netty原生通道 + * @return netty原生通道 + */ + public ChannelHandlerContext getChannelHandlerContext() { + return ctx; + } + + /** + * 设置响应头 + * + * @param key 键 + * @param value 值 + */ + public void setHeader(String key, String value) { + this.header.put(key, value); + } + + /** + * 响应数据 + * + * @param context 消息 + */ + public void send(String context) { + send(context, HttpResponseStatus.OK); + } + + + /** + * 响应数据 + * + * @param context 消息 + * @param status 状态 + */ + public void send(String context, HttpResponseStatus status) { + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, + Unpooled.copiedBuffer(context, CharsetUtil.UTF_8)); + + crossDomain(response); + + if (header != null) { + for (String key : header.keySet()) { + response.headers().set(key, header.get(key)); + } + } + + response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/json; charset=UTF-8"); + ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + } + + /** + * 文件下载 + * + * @param file 要下载的文件 + */ + public void sendFile(File file) { + try{ + setHeader("Content-Length", String.valueOf(file.length())); + sendFile(FileUtil.getFileToByte(file),file.getName()); + } catch (Exception e){ + logger.error("将流文件流响应给客户端出错",e); + } + } + + /** + * 文件下载 + * + * @param file 要下载的文件 + */ + public void sendFile(InputStream file,String fileName) { + sendFile(FileUtil.getInputStreamToByte(file),fileName); + } + + /** + * 文件下载 + * + * @param file 要下载的文件 + */ + public void sendFile(BufferedImage file, String fileName){ + sendFile(FileUtil.getBufferedImageToByte(file),fileName); + } + + /** + * 文件下载 + * + * @param file 要下载的文件 + */ + public void sendFile(byte[] file,String fileName) { + try{ + + if(file == null){ + if(this.header.get("Content-Length") != null){ + this.header.remove("Content-Length"); + } + send(MesUtil.getMes(404,"要下载的文件不存在").toJSONString()); + throw new Exception("要下载的文件不存在"); + } + + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, + Unpooled.copiedBuffer(file)); + + crossDomain(response); + + if (header != null) { + for (String key : header.keySet()) { + response.headers().set(key, header.get(key)); + } + } + response.headers().set("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(),"UTF-8")); + response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/octet-stream; charset=UTF-8"); + ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); + } catch (Exception e){ + logger.error("将流文件流响应给客户端出错",e); + } + } + + /** + * 设置跨域 + */ + private void crossDomain(FullHttpResponse response) { + JSONObject jsonObject = getConfig(); + Object object = jsonObject.get("cross_domain"); + if (object != null) { + JSONObject ob = JSONObject.parseObject(JSON.toJSONString(object)); + + response.headers().set("Access-Control-Allow-Origin", ob.get("origin").toString()); + response.headers().set("Access-Control-Allow-Methods", ob.get("methods").toString()); + response.headers().set("Access-Control-Max-Age", ob.get("maxAge").toString()); + response.headers().set("Access-Control-Allow-Headers", ob.get("headers").toString()); + response.headers().set("Access-Control-Allow-Credentials", ob.get("credentials").toString()); + } + } + + /** + * 获取配置文件 + * + * @return 配置文件对象 + */ + private JSONObject getConfig() { + JSONObject jsonObject = ConfigUtil.getConfig(); + if (jsonObject != null) { + return jsonObject; + } + + return new JSONObject(); + } +} diff --git a/mars-server/src/main/java/com/yuyenews/easy/server/request/RequestParser.java b/mars-server/src/main/java/com/yuyenews/easy/server/request/RequestParser.java new file mode 100644 index 0000000..4f2318d --- /dev/null +++ b/mars-server/src/main/java/com/yuyenews/easy/server/request/RequestParser.java @@ -0,0 +1,106 @@ +package com.yuyenews.easy.server.request; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import com.yuyenews.easy.server.request.model.FileUpLoad; + +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.QueryStringDecoder; +import io.netty.handler.codec.http.multipart.Attribute; +import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import io.netty.handler.codec.http.multipart.MixedFileUpload; + +/** + * 参数解析器 + * + * @author yuye + * + */ +public class RequestParser { + + private FullHttpRequest fullReq; + + /** + * 构造一个解析器 + * + * @param req 请求对象 + */ + public RequestParser(FullHttpRequest req) { + this.fullReq = req; + } + + /** + * 解析请求参数 + * + * @return 包含所有请求参数的键值对, 如果没有参数, 则返回空Map + * + * @throws Exception 异常 + */ + @SuppressWarnings("unchecked") + public Map parse() throws Exception { + HttpMethod method = fullReq.method(); + + Map parmMap = new HashMap<>(); + + if (HttpMethod.GET == method) { + // 是GET请求 + QueryStringDecoder decoder = new QueryStringDecoder(fullReq.uri()); + Map> params = decoder.parameters(); + for(String key : params.keySet()){ + parmMap.put(key, params.get(key)); + } + } else if (HttpMethod.POST == method) { + // 是POST请求 + HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(fullReq); + decoder.offer(fullReq); + + List parmList = decoder.getBodyHttpDatas(); + + Map files = new Hashtable<>(); + + for (InterfaceHttpData parm : parmList) { + + if (parm instanceof Attribute) { + Attribute data = (Attribute) parm; + List ps = null; + Object objs = parmMap.get(data.getName()); + if (objs == null) { + ps = new ArrayList<>(); + } else { + ps = (List) objs; + } + ps.add(data.getValue()); + parmMap.put(data.getName(), ps); + + } else if (parm instanceof MixedFileUpload) { + MixedFileUpload fileUpload = (MixedFileUpload) parm; + + byte[] bs = fileUpload.get(); + + InputStream inputStream = new ByteArrayInputStream(bs); + + FileUpLoad upLoad = new FileUpLoad(); + upLoad.setFileName(fileUpload.getFilename()); + upLoad.setInputStream(inputStream); + upLoad.setName(fileUpload.getName()); + + files.put(fileUpload.getName(), upLoad); + } + + } + parmMap.put("files", files); + } + + return parmMap; + } + +} diff --git a/mars-server/src/main/java/com/yuyenews/easy/server/request/model/FileUpLoad.java b/mars-server/src/main/java/com/yuyenews/easy/server/request/model/FileUpLoad.java new file mode 100644 index 0000000..da74e44 --- /dev/null +++ b/mars-server/src/main/java/com/yuyenews/easy/server/request/model/FileUpLoad.java @@ -0,0 +1,51 @@ +package com.yuyenews.easy.server.request.model; + +import java.io.InputStream; + +/** + * 文件参数实体类 + * @author yuye + * + */ +public class FileUpLoad { + + /** + * 请求name + */ + private String name; + + /** + * 文件名 + */ + private String fileName; + + /** + * 文件流 + */ + private InputStream inputStream; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public InputStream getInputStream() { + return inputStream; + } + + public void setInputStream(InputStream inputStream) { + this.inputStream = inputStream; + } + +} diff --git a/mars-server/src/main/java/com/yuyenews/easy/server/servlet/EasyServlet.java b/mars-server/src/main/java/com/yuyenews/easy/server/servlet/EasyServlet.java new file mode 100644 index 0000000..eb91f14 --- /dev/null +++ b/mars-server/src/main/java/com/yuyenews/easy/server/servlet/EasyServlet.java @@ -0,0 +1,21 @@ +package com.yuyenews.easy.server.servlet; + +import com.yuyenews.easy.server.request.HttpRequest; +import com.yuyenews.easy.server.request.HttpResponse; + +/** + * servlet 模板 + * @author yuye + * + */ +public interface EasyServlet { + + + /** + * 请求接受方法 + * @param request + * @param response + * @return obj + */ + Object doRequest(HttpRequest request,HttpResponse response); +} diff --git a/mars-server/src/main/java/com/yuyenews/easy/util/RequestUtil.java b/mars-server/src/main/java/com/yuyenews/easy/util/RequestUtil.java new file mode 100644 index 0000000..b09247c --- /dev/null +++ b/mars-server/src/main/java/com/yuyenews/easy/util/RequestUtil.java @@ -0,0 +1,25 @@ +package com.yuyenews.easy.util; + +import com.yuyenews.easy.server.request.HttpRequest; + +/** + * 请求工具类 + * @author yuye + * + */ +public class RequestUtil { + + /** + * 从uri中提取最末端 + * @param request 请求 + * @return string + */ + public static String getUriName(HttpRequest request) { + /* 获取路径 */ + String uri = request.getUri(); + if(uri.indexOf("?")>-1) { + uri = uri.substring(0,uri.indexOf("?")); + } + return uri; + } +} diff --git a/mars-start/mars-start-base/pom.xml b/mars-start/mars-start-base/pom.xml new file mode 100644 index 0000000..b407854 --- /dev/null +++ b/mars-start/mars-start-base/pom.xml @@ -0,0 +1,27 @@ + + + + mars-start + com.gitee.sherlockholmnes + 2.1.0 + + 4.0.0 + + mars-start-base + + + + com.gitee.sherlockholmnes + mars-jdbc-base + ${project.parent.version} + + + com.gitee.sherlockholmnes + mars-mvc + ${project.parent.version} + + + + \ No newline at end of file diff --git a/mars-start/mars-start-base/src/main/java/com/yuyenews/start/base/BaseStartEasy.java b/mars-start/mars-start-base/src/main/java/com/yuyenews/start/base/BaseStartEasy.java new file mode 100644 index 0000000..b428d56 --- /dev/null +++ b/mars-start/mars-start-base/src/main/java/com/yuyenews/start/base/BaseStartEasy.java @@ -0,0 +1,105 @@ +package com.yuyenews.start.base; + +import com.alibaba.fastjson.JSONObject; +import com.yuyenews.core.after.StartAfter; +import com.yuyenews.core.constant.EasyConstant; +import com.yuyenews.core.constant.EasySpace; +import com.yuyenews.core.load.LoadClass; +import com.yuyenews.core.logger.GogeLogger; +import com.yuyenews.core.util.ConfigUtil; +import com.yuyenews.easy.netty.server.EasyServer; +import com.yuyenews.ioc.load.LoadEasyBean; +import com.yuyenews.jdbc.base.BaseInitJdbc; +import com.yuyenews.resolve.LoadController; +import com.yuyenews.servlcet.EasyCoreServlet; + +/** + * 启动easy框架 + * @author yuye + * + */ +public class BaseStartEasy { + + private static GogeLogger log = GogeLogger.getLogger(BaseStartEasy.class); + + /** + * 获取全局存储空间 + */ + private static EasySpace constants = EasySpace.getEasySpace(); + + /** + * 启动easy框架 + * @param clazz + */ + public static void start(Class clazz, BaseInitJdbc baseInitJdbc) { + try { + + log.info("程序启动中......"); + + /* 加载框架数据 */ + load(clazz,baseInitJdbc); + + /* 标识createbean方法已经调用完毕 */ + constants.setAttr(EasyConstant.HAS_START,"yes"); + + /* 启动after方法 */ + StartAfter.after(); + + /* 启动netty */ + EasyServer.start(getPort()); + + } catch (Exception e) { + log.error("",e); + } + } + + /** + * 加载控制层所有的类和所需数据 + */ + private static void load(Class clazz, BaseInitJdbc baseInitJdbc) throws Exception{ + + /* 配置核心servlet */ + constants.setAttr("core", EasyCoreServlet.class.getName()); + + /* 加载配置文件 */ + ConfigUtil.loadConfig(); + + /*获取要扫描的包*/ + String className = clazz.getName(); + className = className.substring(0,className.lastIndexOf(".")); + + /* 将要扫描的包名存到全局存储空间,给别的需要的地方使用 */ + constants.setAttr("rootPath", className); + + /* 获取此包下面的所有类(包括jar中的) */ + LoadClass.loadBeans(className); + + /* 加载JDBC模块 */ + if(baseInitJdbc != null){ + baseInitJdbc.init(); + } + + /* 创建bean对象 */ + LoadEasyBean.loadBean(); + + /* 创建controller对象 */ + LoadController.loadContrl(); + + } + + /** + * 获取端口号,默认8080 + * @return + */ + private static int getPort() { + + JSONObject jsonObject = ConfigUtil.getConfig(); + Object por = jsonObject.get("port"); + if(por!=null) { + return Integer.parseInt(por.toString()); + } + + return 8080; + } + +} diff --git a/mars-start/mars-start-base/src/main/resources/demo/goge.yml b/mars-start/mars-start-base/src/main/resources/demo/goge.yml new file mode 100644 index 0000000..42d288d --- /dev/null +++ b/mars-start/mars-start-base/src/main/resources/demo/goge.yml @@ -0,0 +1,85 @@ +#此配置文件只是个demo,对开发没什么卵用 + +#配置端口号(默认8080) +port: 8088 +#配置jwt有效期(默认1),单位:天 +jwtTime: 20 +#请求超时时间(默认10),单位:秒 +timeOut: 10 +#请求数据的最大值(默认10485760) +maxContentLength: 10 +#配置跨域请求 +cross_domain: + origin: * + methods: "GET,POST" + maxAge: 9 + headers: "x-requested-with,Cache-Control,Pragma,Content-Type,Token" + credentials: "true" + + +#配置处理请求的线程池参数(这些都是默认值) +threadPool: + corePoolSize: 100 + maximumPoolSize: 1000 + keepAliveTime: 60 + +#配置持久层 +jdbc: + #配置数据源,必须是数组 + dataSource: + - + name: dataSource + url: jdbc:mysql://10.211.55.5:3306/test?serverTimezone=GMT%2B8 + username: root + password: rootroot + driverClassName: com.mysql.cj.jdbc.Driver + + #配置mybatis方言 + dialect: mysql + #配置要扫描的mapper.xml 文件存放路径 + mappers: mappers + +#log4j2 配置文件的路径 +#相对路径必须以classPath- 开头,区分大小写 +#绝对路径直接写即可,不需要开头 +logFile: classpath-log4j2.xml + + +#以下配置 必须在导入goge-extends 中的相应的jar包后 才生效 + +#redis配置 +redis: + maxTotal: 1000 + maxIdle: 100 + numTestsPerEvictionRun: 10 + timeBetweenEvictionRunsMillis: 10 + minEvictableIdleTimeMillis: 10 + softMinEvictableIdleTimeMillis: 10 + maxWaitMillis: 10 + testOnBorrow: false + testWhileIdle: false + testOnReturn: false + jmxEnabled: false + jmxNamePrefix: pool + blockWhenExhausted: false + # redis连接,必须是数组 因为可能需要连多个redis + jedisShardInfos: + - + name: master + host: 10.211.55.5 + port: 6379 + password: 123456 + # 这两个可以不配置 + connectionTimeout: 1000 + soTimeout: 1000 + +#邮件配置 只支持smtp +mail: + host: smtp.sina.com + port: 465 + smtpSslEnable: true + debug: false + # 发件箱 + sendMail: 发件箱 + sendMailPwd: 发件箱密码 + auth: true \ No newline at end of file diff --git a/mars-start/mars-start-base/src/main/resources/goge-config-demo/goge.yml b/mars-start/mars-start-base/src/main/resources/goge-config-demo/goge.yml new file mode 100644 index 0000000..90cea0e --- /dev/null +++ b/mars-start/mars-start-base/src/main/resources/goge-config-demo/goge.yml @@ -0,0 +1,10 @@ +#此配置文件只是个demo,对开发没什么卵用 + +#配置端口号(默认8080) +port: 8088 + +#goge-config 远程配置中心 +config: + name: user1 + myIp: 127.0.0.1 + url: 127.0.0.1:8090 \ No newline at end of file diff --git a/mars-start/mars-start-jpa/pom.xml b/mars-start/mars-start-jpa/pom.xml new file mode 100644 index 0000000..489798d --- /dev/null +++ b/mars-start/mars-start-jpa/pom.xml @@ -0,0 +1,26 @@ + + + + mars-start + com.gitee.sherlockholmnes + 2.1.0 + + 4.0.0 + + mars-start-jpa + + + + com.gitee.sherlockholmnes + mars-start-base + ${project.parent.version} + + + com.gitee.sherlockholmnes + mars-jpa + ${project.parent.version} + + + \ No newline at end of file diff --git a/mars-start/mars-start-jpa/src/main/java/com/yuyenews/start/StartEasy.java b/mars-start/mars-start-jpa/src/main/java/com/yuyenews/start/StartEasy.java new file mode 100644 index 0000000..9ba9b36 --- /dev/null +++ b/mars-start/mars-start-jpa/src/main/java/com/yuyenews/start/StartEasy.java @@ -0,0 +1,14 @@ +package com.yuyenews.start; + +import com.yuyenews.easy.jpa.init.InitJdbc; +import com.yuyenews.start.base.BaseStartEasy; + +public class StartEasy { + /** + * 启动easy框架 + * @param clazz + */ + public static void start(Class clazz){ + BaseStartEasy.start(clazz,new InitJdbc()); + } +} diff --git a/mars-start/mars-start-mybatis/pom.xml b/mars-start/mars-start-mybatis/pom.xml new file mode 100644 index 0000000..2856491 --- /dev/null +++ b/mars-start/mars-start-mybatis/pom.xml @@ -0,0 +1,27 @@ + + + + mars-start + com.gitee.sherlockholmnes + 2.1.0 + + 4.0.0 + + mars-start-mybatis + + + + com.gitee.sherlockholmnes + mars-start-base + ${project.parent.version} + + + com.gitee.sherlockholmnes + mars-mybatis + ${project.parent.version} + + + + \ No newline at end of file diff --git a/mars-start/mars-start-mybatis/src/main/java/com/yuyenews/start/StartEasy.java b/mars-start/mars-start-mybatis/src/main/java/com/yuyenews/start/StartEasy.java new file mode 100644 index 0000000..bfc39fb --- /dev/null +++ b/mars-start/mars-start-mybatis/src/main/java/com/yuyenews/start/StartEasy.java @@ -0,0 +1,23 @@ +package com.yuyenews.start; + +import com.yuyenews.easy.init.InitJdbc; +import com.yuyenews.start.base.BaseStartEasy; + +/** + * 启动easy框架 + * @author yuye + * + */ +public class StartEasy { + + + + /** + * 启动easy框架 + * @param clazz + */ + public static void start(Class clazz) { + BaseStartEasy.start(clazz,new InitJdbc()); + } + +} diff --git a/mars-start/mars-start-simple/pom.xml b/mars-start/mars-start-simple/pom.xml new file mode 100644 index 0000000..c6c1e7b --- /dev/null +++ b/mars-start/mars-start-simple/pom.xml @@ -0,0 +1,21 @@ + + + + mars-start + com.gitee.sherlockholmnes + 2.1.0 + + 4.0.0 + + mars-start-simple + + + + com.gitee.sherlockholmnes + mars-start-base + ${project.parent.version} + + + \ No newline at end of file diff --git a/mars-start/mars-start-simple/src/main/java/com/yuyenews/start/StartEasy.java b/mars-start/mars-start-simple/src/main/java/com/yuyenews/start/StartEasy.java new file mode 100644 index 0000000..7790495 --- /dev/null +++ b/mars-start/mars-start-simple/src/main/java/com/yuyenews/start/StartEasy.java @@ -0,0 +1,19 @@ +package com.yuyenews.start; + +import com.yuyenews.start.base.BaseStartEasy; + +/** + * 启动easy框架 + * @author yuye + * + */ +public class StartEasy { + + /** + * 启动easy框架 + * @param clazz + */ + public static void start(Class clazz) { + BaseStartEasy.start(clazz,null); + } +} diff --git a/mars-start/pom.xml b/mars-start/pom.xml new file mode 100644 index 0000000..1a919a7 --- /dev/null +++ b/mars-start/pom.xml @@ -0,0 +1,33 @@ + + + + Mars-java + com.gitee.sherlockholmnes + 2.1.0 + + 4.0.0 + pom + + mars-start-mybatis + mars-start-simple + mars-start-jpa + mars-start-base + + mars-start + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c58a6ff --- /dev/null +++ b/pom.xml @@ -0,0 +1,178 @@ + + 4.0.0 + com.gitee.sherlockholmnes + Mars-java + 2.1.0 + pom + + mars-aop + mars-ioc + mars-core + mars-mvc + mars-netty + mars-server + mars-start + mars-jdbc + + + + ${java.home}/../bin/javadoc + + + + + + com.gitee.sherlockholmnes + mars-aop + ${project.parent.version} + + + com.gitee.sherlockholmnes + mars-ioc + ${project.parent.version} + + + com.gitee.sherlockholmnes + mars-mvc + ${project.parent.version} + + + com.gitee.sherlockholmnes + mars-core + ${project.parent.version} + + + com.gitee.sherlockholmnes + mars-netty + ${project.parent.version} + + + + com.gitee.sherlockholmnes + mars-server + ${project.parent.version} + + + + io.netty + netty-all + 5.0.0.Alpha2 + + + + com.alibaba + fastjson + 1.2.47 + + + + org.slf4j + slf4j-api + 1.7.25 + + + org.slf4j + slf4j-jdk14 + 1.7.25 + + + + org.apache.logging.log4j + log4j-api + 2.11.2 + + + org.apache.logging.log4j + log4j-core + 2.11.2 + + + + org.ow2.asm + asm + 5.2 + + + cglib + cglib + 3.2.5 + + + + mysql + mysql-connector-java + 8.0.11 + + + + org.mybatis + mybatis + 3.4.6 + + + + com.alibaba + druid + 1.1.10 + + + + com.github.pagehelper + pagehelper + 4.1.3 + + + + com.auth0 + java-jwt + 3.4.1 + + + + org.jyaml + jyaml + 1.3 + + + + + + org.sonatype.oss + oss-parent + 7 + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + https://gitee.com/SherlockHolmnes/Goge-framework + https://gitee.com/SherlockHolmnes/Goge-framework.git + https://gitee.com/SherlockHolmnes/Goge-framework + + + + sherlockholmes + 1784955689@qq.com + https://gitee.com/SherlockHolmnes/Goge-framework + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + \ No newline at end of file