├── .gitignore ├── EasyRest ├── pom.xml └── src │ └── main │ ├── java │ ├── META-INF │ │ └── MANIFEST.MF │ └── tech │ │ └── dbgsoftware │ │ └── easyrest │ │ ├── EasyRest.java │ │ ├── EasyRestCallback.java │ │ ├── actors │ │ ├── ActorFactory.java │ │ ├── AnalysisMethodActor.java │ │ ├── EasyRestAkkaConf.java │ │ ├── ExceptionHandleActor.java │ │ ├── Signal.java │ │ ├── remote │ │ │ ├── RemoteInvokeActor.java │ │ │ ├── RemoteObjectAnalysisActor.java │ │ │ ├── RemoteRequestUtil.java │ │ │ ├── RemoteServiceExchangeActor.java │ │ │ ├── conf │ │ │ │ ├── EasyRestDistributedServiceBind.java │ │ │ │ └── ServiceMapping.java │ │ │ └── model │ │ │ │ ├── RemoteInvokeObject.java │ │ │ │ └── ServiceInfo.java │ │ ├── request │ │ │ ├── ControllerInvokeActor.java │ │ │ └── RequestProcessActor.java │ │ └── response │ │ │ ├── OutputActor.java │ │ │ └── ResponseProcessActor.java │ │ ├── annotations │ │ ├── async │ │ │ ├── AsyncRequest.java │ │ │ └── SyncRequest.java │ │ ├── bean │ │ │ ├── BindService.java │ │ │ └── EasyRestInterface.java │ │ ├── history │ │ │ └── HistoryRequired.java │ │ ├── method │ │ │ ├── BindURL.java │ │ │ ├── Delete.java │ │ │ ├── Get.java │ │ │ ├── Post.java │ │ │ ├── Put.java │ │ │ ├── RequestMethod.java │ │ │ ├── SkipCustomerInject.java │ │ │ └── SkipCustomerResponse.java │ │ ├── parameter │ │ │ ├── AllDefined.java │ │ │ ├── AutoInject.java │ │ │ ├── FromPath.java │ │ │ ├── NotNull.java │ │ │ ├── Optional.java │ │ │ ├── SkipInject.java │ │ │ └── validation │ │ │ │ ├── AllDefinedValidation.java │ │ │ │ └── NotNullValidation.java │ │ ├── permission │ │ │ └── PermissionRequired.java │ │ └── transaction │ │ │ └── TransactionRequired.java │ │ ├── aop │ │ ├── AopPostCommitStep.java │ │ ├── AopPreCommitStep.java │ │ ├── AopStep.java │ │ ├── StaticAopStepUtil.java │ │ ├── customer │ │ │ ├── CustomInjection.java │ │ │ └── CustomResponse.java │ │ ├── pre │ │ │ ├── AopInitRequestInfoStep.java │ │ │ ├── AopParametersInjectStep.java │ │ │ └── AopRequestValidateStep.java │ │ └── resolvers │ │ │ ├── FormDataResolve.java │ │ │ ├── JsonDataResolve.java │ │ │ ├── ParameterTypeResolve.java │ │ │ └── UrlDataResolve.java │ │ ├── exception │ │ ├── ConditionMissingException.java │ │ ├── EasyRestException.java │ │ ├── ExceptionHandler.java │ │ ├── MethodNotAllowedException.java │ │ ├── PageNotFoundException.java │ │ ├── ParameterNotFoundException.java │ │ └── PermissionException.java │ │ ├── ioc │ │ ├── remote │ │ │ ├── EasyRestProxyFactory.java │ │ │ ├── EasyRestServiceLookup.java │ │ │ └── proxy │ │ │ │ ├── ProxyForBeanClassInvoke.java │ │ │ │ └── ProxyForBeanNameInvoke.java │ │ └── utils │ │ │ ├── BeanOperationUtils.java │ │ │ └── StaticClassUtils.java │ │ ├── model │ │ ├── ErrorResponse.java │ │ ├── HttpEntity.java │ │ ├── Response.java │ │ ├── ResponseEntity.java │ │ └── request │ │ │ ├── AbstractRequestModel.java │ │ │ ├── Request.java │ │ │ ├── RequestModel.java │ │ │ └── RestObject.java │ │ ├── network │ │ ├── NettyInit.java │ │ ├── NettyLaunch.java │ │ ├── conf │ │ │ └── ChannelOptionBuilder.java │ │ ├── core │ │ │ ├── api │ │ │ │ └── BaseConfiguration.java │ │ │ └── pipeline │ │ │ │ ├── in │ │ │ │ └── RequestProcessHandler.java │ │ │ │ └── utils │ │ │ │ └── ByteBufUtils.java │ │ ├── exception │ │ │ └── ConfigurationException.java │ │ └── router │ │ │ ├── PathNode.java │ │ │ ├── PathStore.java │ │ │ ├── RouterProvider.java │ │ │ └── UrlFormat.java │ │ └── utils │ │ ├── DateUtils.java │ │ ├── DoubleTypeAdapter.java │ │ ├── DoubleUtils.java │ │ ├── IntegerTypeAdapter.java │ │ ├── IntegerUtils.java │ │ ├── JsonTranslationUtil.java │ │ ├── LogUtils.java │ │ ├── LongTypeAdapter.java │ │ ├── StringUtils.java │ │ └── ThreadStackUtils.java │ └── resources │ └── easyrest-applicationContext-01.xml ├── Example ├── Example-Distributed-Service-1 │ ├── example-service-1-api │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── api │ │ │ └── Service1.java │ ├── example-service-1-main │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── main │ │ │ │ ├── Startup.java │ │ │ │ └── impl │ │ │ │ └── Service1Impl.java │ │ │ └── resources │ │ │ ├── MyExampleApplicationContext-01.xml │ │ │ ├── application.conf │ │ │ ├── log4j.properties │ │ │ └── services-mapping-01.json │ └── pom.xml ├── Example-Distributed-Service-2 │ ├── example-service-2-api │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── api │ │ │ └── Service2.java │ ├── example-service-2-main │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── main │ │ │ │ ├── Startup.java │ │ │ │ └── impl │ │ │ │ └── Service2Impl.java │ │ │ └── resources │ │ │ ├── MyExampleApplicationContext-02.xml │ │ │ ├── application.conf │ │ │ ├── log4j.properties │ │ │ └── services-mapping-02.json │ └── pom.xml ├── Example-Distributed-Service-Model │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── example │ │ └── model │ │ └── People.java ├── Example-Quick-Start │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── Example.java │ │ │ ├── InfoMation.java │ │ │ ├── model │ │ │ └── Stock.java │ │ │ ├── rest │ │ │ ├── StockInfoRest.java │ │ │ └── TestRestService.java │ │ │ └── services │ │ │ ├── StockInfoRestServiceImpl.java │ │ │ └── TestServiceImpl.java │ │ └── resources │ │ ├── MyExampleApplicationContext.xml │ │ └── log4j.properties └── pom.xml ├── README-zh.md ├── README.md └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.war 3 | *.jar 4 | *.iml 5 | .idea/ 6 | out/ 7 | target/ -------------------------------------------------------------------------------- /EasyRest/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | tech.dbgsoftware.easyrest 8 | EasyRest-NAS-All-In-One 9 | 0.0.1 10 | 11 | 12 | org.sonatype.oss 13 | oss-parent 14 | 7 15 | 16 | 17 | 18 | UTF-8 19 | UTF-8 20 | 21 | 22 | 23 | 24 | io.netty 25 | netty-all 26 | 4.1.36.Final 27 | 28 | 29 | com.typesafe.akka 30 | akka-actor_2.12 31 | 2.5.12 32 | 33 | 34 | com.typesafe.akka 35 | akka-cluster_2.12 36 | 2.5.12 37 | 38 | 39 | com.typesafe.akka 40 | akka-remote_2.12 41 | 2.5.12 42 | 43 | 44 | org.springframework 45 | spring-webmvc 46 | 4.1.6.RELEASE 47 | 48 | 49 | com.google.code.gson 50 | gson 51 | 2.3.1 52 | 53 | 54 | org.javassist 55 | javassist 56 | 3.22.0-GA 57 | 58 | 59 | com.google.guava 60 | guava 61 | 19.0 62 | 63 | 64 | log4j 65 | log4j 66 | 1.2.17 67 | 68 | 69 | org.slf4j 70 | slf4j-api 71 | 1.7.21 72 | 73 | 74 | org.slf4j 75 | slf4j-simple 76 | 1.7.21 77 | 78 | 79 | 80 | 81 | 82 | The Apache Software License, Version 2.0 83 | http://www.apache.org/licenses/LICENSE-2.0.txt 84 | repo 85 | 86 | 87 | 88 | 89 | https://github.com/liuhongyuand/EasyRest-NAS 90 | git@github.com:liuhongyuand/EasyRest-NAS.git 91 | liuhongyu.louie@gmail.com 92 | 93 | 94 | 95 | 96 | Louie 97 | liuhongyu.louie@gmail.com 98 | liuhongyu.louie@gmail.com 99 | 100 | 101 | 102 | 103 | 104 | release 105 | 106 | 107 | 108 | 109 | org.apache.maven.plugins 110 | maven-source-plugin 111 | 2.2.1 112 | 113 | 114 | package 115 | 116 | jar-no-fork 117 | 118 | 119 | 120 | 121 | 122 | 123 | org.apache.maven.plugins 124 | maven-javadoc-plugin 125 | 2.9.1 126 | 127 | 128 | package 129 | 130 | jar 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | org.apache.maven.plugins 139 | maven-gpg-plugin 140 | 1.6 141 | 142 | 143 | verify 144 | 145 | sign 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | sonatype-nexus-snapshots 155 | https://oss.sonatype.org/content/repositories/snapshots 156 | 157 | 158 | sonatype-nexus-staging 159 | https://oss.sonatype.org/service/local/staging/deploy/maven2 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | org.apache.maven.plugins 169 | maven-compiler-plugin 170 | 2.0.2 171 | 172 | 1.8 173 | 1.8 174 | ${project.build.sourceEncoding} 175 | 176 | 177 | 178 | org.apache.maven.plugins 179 | maven-shade-plugin 180 | 1.4 181 | 182 | 183 | package 184 | 185 | shade 186 | 187 | 188 | false 189 | true 190 | ALL 191 | 192 | 193 | *:* 194 | 195 | 196 | 197 | 199 | META-INF/spring.handlers 200 | 201 | 203 | META-INF/spring.schemas 204 | 205 | 207 | reference.conf 208 | 209 | 211 | 212 | akka.Main 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: spring-webmvc-4.1.6.RELEASE.jar akka-stream_2.12-2.5.12.ja 3 | r aopalliance-1.0.jar scala-java8-compat_2.12-0.8.0.jar aeron-driver- 4 | 1.7.0.jar guava-19.0.jar agrona-0.9.12.jar spring-expression-4.1.6.RE 5 | LEASE.jar akka-remote_2.12-2.5.12.jar spring-context-4.1.6.RELEASE.ja 6 | r gson-2.3.1.jar spring-aop-4.1.6.RELEASE.jar slf4j-api-1.7.21.jar sp 7 | ring-beans-4.1.6.RELEASE.jar akka-actor_2.12-2.5.12.jar reactive-stre 8 | ams-1.0.2.jar config-1.3.2.jar spring-core-4.1.6.RELEASE.jar slf4j-si 9 | mple-1.7.21.jar commons-logging-1.2.jar netty-3.10.6.Final.jar log4j- 10 | 1.2.17.jar scala-library-2.12.5.jar javassist-3.22.0-GA.jar scala-par 11 | ser-combinators_2.12-1.1.0.jar ssl-config-core_2.12-0.2.3.jar akka-pr 12 | otobuf_2.12-2.5.12.jar spring-web-4.1.6.RELEASE.jar aeron-client-1.7. 13 | 0.jar netty-all-4.1.22.Final.jar akka-cluster_2.12-2.5.12.jar 14 | 15 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/EasyRest.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest; 2 | 3 | import akka.actor.ActorRef; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | import tech.dbgsoftware.easyrest.actors.ActorFactory; 6 | import tech.dbgsoftware.easyrest.actors.AnalysisMethodActor; 7 | import tech.dbgsoftware.easyrest.ioc.utils.BeanOperationUtils; 8 | import tech.dbgsoftware.easyrest.network.NettyInit; 9 | 10 | public class EasyRest { 11 | 12 | private EasyRestCallback easyRestCallback; 13 | 14 | private String systemName; 15 | 16 | private NettyInit nettyInit; 17 | 18 | public EasyRest() { 19 | BeanOperationUtils.setApplicationContext(new ClassPathXmlApplicationContext("classpath:easyrest-applicationContext-01.xml")); 20 | } 21 | 22 | public EasyRest(String springXmlPath) { 23 | String[] xmls = new String[]{"classpath:easyrest-applicationContext-01.xml", springXmlPath}; 24 | BeanOperationUtils.setApplicationContext(new ClassPathXmlApplicationContext(xmls)); 25 | } 26 | 27 | public EasyRest(String... springXmlPaths) { 28 | String[] xmls = new String[springXmlPaths.length + 1]; 29 | xmls[0] = "classpath:easyrest-applicationContext-01.xml"; 30 | System.arraycopy(springXmlPaths, 0, xmls, 1, xmls.length - 1); 31 | BeanOperationUtils.setApplicationContext(new ClassPathXmlApplicationContext(xmls)); 32 | } 33 | 34 | public void startup() { 35 | startup(NettyInit.SystemName, new NettyInit()); 36 | } 37 | 38 | public void startup(EasyRestCallback easyRestCallback) { 39 | startup(NettyInit.SystemName, new NettyInit(), easyRestCallback); 40 | } 41 | 42 | public void startup(String systemName) { 43 | startup(systemName, new NettyInit()); 44 | } 45 | 46 | public void startup(String systemName, EasyRestCallback easyRestCallback) { 47 | startup(systemName, new NettyInit(), easyRestCallback); 48 | } 49 | 50 | public void startup(String systemName, int port) { 51 | startup(systemName, new NettyInit(port)); 52 | } 53 | 54 | public void startup(String systemName, int port, EasyRestCallback easyRestCallback) { 55 | startup(systemName, new NettyInit(port), easyRestCallback); 56 | } 57 | 58 | public void startup(String SystemName, NettyInit nettyInit) { 59 | startup(SystemName, nettyInit, null); 60 | } 61 | 62 | public void startup(String systemName, NettyInit nettyInit, EasyRestCallback easyRestCallback){ 63 | this.systemName = systemName; 64 | this.nettyInit = nettyInit; 65 | NettyInit.SystemName = systemName; 66 | this.easyRestCallback = easyRestCallback; 67 | if (this.easyRestCallback == null) { 68 | this.easyRestCallback = new EasyRestCallback() { 69 | @Override 70 | public void onStartSuccess() { 71 | 72 | } 73 | 74 | @Override 75 | public void onStartFailed() { 76 | 77 | } 78 | }; 79 | } 80 | ActorFactory.createActor(AnalysisMethodActor.class).tell(this, ActorRef.noSender()); 81 | } 82 | 83 | public String getSystemName() { 84 | return systemName; 85 | } 86 | 87 | public NettyInit getNettyInit() { 88 | return nettyInit; 89 | } 90 | 91 | public EasyRestCallback getEasyRestCallback() { 92 | return easyRestCallback; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/EasyRestCallback.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest; 2 | 3 | public interface EasyRestCallback { 4 | 5 | void onStartSuccess(); 6 | 7 | void onStartFailed(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/ActorFactory.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.ActorSystem; 5 | import akka.actor.Props; 6 | import tech.dbgsoftware.easyrest.actors.remote.RemoteInvokeActor; 7 | import tech.dbgsoftware.easyrest.actors.remote.RemoteServiceExchangeActor; 8 | import tech.dbgsoftware.easyrest.network.NettyInit; 9 | import tech.dbgsoftware.easyrest.utils.LogUtils; 10 | 11 | import java.util.Map; 12 | import java.util.concurrent.ConcurrentHashMap; 13 | import java.util.concurrent.TimeUnit; 14 | import java.util.concurrent.locks.Lock; 15 | import java.util.concurrent.locks.ReentrantLock; 16 | 17 | public class ActorFactory { 18 | 19 | private static ActorSystem ACTOR_SYSTEM; 20 | 21 | private static final Map ACTOR_REF_CACHE = new ConcurrentHashMap<>(); 22 | 23 | private static final Lock LOCK = new ReentrantLock(); 24 | 25 | static { 26 | ACTOR_SYSTEM = ActorSystem.create(NettyInit.SystemName); 27 | createActorWithName(RemoteInvokeActor.class); 28 | createActorWithName(RemoteServiceExchangeActor.class); 29 | } 30 | 31 | public static ActorSystem getActorSystem() { 32 | return ACTOR_SYSTEM; 33 | } 34 | 35 | public static ActorRef createActor(Class target){ 36 | try { 37 | if (!ACTOR_REF_CACHE.containsKey(target) && LOCK.tryLock(1, TimeUnit.MINUTES)){ 38 | try { 39 | Props props = Props.create(target); 40 | ACTOR_REF_CACHE.putIfAbsent(target, ACTOR_SYSTEM.actorOf(props)); 41 | } finally { 42 | LOCK.unlock(); 43 | } 44 | } 45 | return ACTOR_REF_CACHE.get(target); 46 | } catch (InterruptedException e) { 47 | LogUtils.error(e.getMessage(), e); 48 | return ACTOR_SYSTEM.actorOf(Props.create(target)); 49 | } 50 | } 51 | 52 | private static void createActorWithName(Class target){ 53 | try { 54 | if (!ACTOR_REF_CACHE.containsKey(target) && LOCK.tryLock(1, TimeUnit.MINUTES)){ 55 | try { 56 | Props props = Props.create(target); 57 | ACTOR_REF_CACHE.putIfAbsent(target, ACTOR_SYSTEM.actorOf(props, target.getSimpleName())); 58 | } finally { 59 | LOCK.unlock(); 60 | } 61 | } 62 | } catch (InterruptedException e) { 63 | LogUtils.error(e.getMessage(), e); 64 | } 65 | } 66 | 67 | public static ActorRef createRemoteServiceExchangedActor(String systemName, String host, String port){ 68 | return ACTOR_SYSTEM.actorFor(String.format("akka.tcp://%s@%s:%s/user/RemoteServiceExchangeActor", systemName, host, port)); 69 | } 70 | 71 | public static ActorRef createRemoteInvokeActor(String systemName, String host, String port){ 72 | return ACTOR_SYSTEM.actorFor(String.format("akka.tcp://%s@%s:%s/user/RemoteInvokeActor", systemName, host, port)); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/AnalysisMethodActor.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors; 2 | 3 | import akka.actor.AbstractActor; 4 | import akka.actor.ActorRef; 5 | import io.netty.handler.codec.http.HttpMethod; 6 | import tech.dbgsoftware.easyrest.EasyRest; 7 | import tech.dbgsoftware.easyrest.actors.remote.conf.EasyRestDistributedServiceBind; 8 | import tech.dbgsoftware.easyrest.annotations.method.*; 9 | import tech.dbgsoftware.easyrest.ioc.utils.BeanOperationUtils; 10 | import tech.dbgsoftware.easyrest.network.NettyLaunch; 11 | import tech.dbgsoftware.easyrest.network.exception.ConfigurationException; 12 | import tech.dbgsoftware.easyrest.network.router.RouterProvider; 13 | 14 | import java.lang.reflect.Method; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | public class AnalysisMethodActor extends AbstractActor { 19 | 20 | @Override 21 | public Receive createReceive() { 22 | return receiveBuilder().match(EasyRest.class, (this::analysisRestObject)).build(); 23 | } 24 | 25 | private void analysisRestObject(EasyRest easyRest) { 26 | List easyRestClass = new ArrayList<>(); 27 | BeanOperationUtils.getAllBeansClass().forEach((aClass -> { 28 | for (Class _interface : aClass.getInterfaces()){ 29 | if (_interface.isAnnotationPresent(BindURL.class)){ 30 | easyRestClass.add(_interface); 31 | } 32 | } 33 | })); 34 | for (Class requestModel : easyRestClass) { 35 | if (!requestModel.isInterface()) { 36 | throw new ConfigurationException("Only interface can be registered."); 37 | } 38 | Class controller = BeanOperationUtils.getBeansFromInterface(requestModel).getClass(); 39 | StringBuffer[] restUri = new StringBuffer[1]; 40 | if (requestModel.isAnnotationPresent(BindURL.class)) { 41 | String[] uris = requestModel.getAnnotation(BindURL.class).value(); 42 | restUri = new StringBuffer[uris.length]; 43 | for (int i = 0; i < restUri.length; i++) { 44 | restUri[i] = new StringBuffer(uris[i]); 45 | } 46 | } 47 | for (Method method : requestModel.getMethods()) { 48 | if (method.isAnnotationPresent(Post.class)) { 49 | RouterProvider.methodRouterResolve(restUri, method.getName(), method.getAnnotation(Post.class).value(), HttpMethod.POST, method, controller); 50 | } 51 | if (method.isAnnotationPresent(Get.class)) { 52 | RouterProvider.methodRouterResolve(restUri, method.getName(), method.getAnnotation(Get.class).value(), HttpMethod.GET, method, controller); 53 | } 54 | if (method.isAnnotationPresent(Put.class)) { 55 | RouterProvider.methodRouterResolve(restUri, method.getName(), method.getAnnotation(Put.class).value(), HttpMethod.PUT, method, controller); 56 | } 57 | if (method.isAnnotationPresent(Delete.class)) { 58 | RouterProvider.methodRouterResolve(restUri, method.getName(), method.getAnnotation(Delete.class).value(), HttpMethod.DELETE, method, controller); 59 | } 60 | } 61 | EasyRestDistributedServiceBind.addService(requestModel, controller); 62 | } 63 | ActorFactory.createActor(NettyLaunch.class).tell(easyRest, ActorRef.noSender()); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/EasyRestAkkaConf.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors; 2 | 3 | public class EasyRestAkkaConf { 4 | 5 | public static int REMOTE_PORT = 2550; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/ExceptionHandleActor.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors; 2 | 3 | import akka.actor.AbstractActor; 4 | import tech.dbgsoftware.easyrest.model.ErrorResponse; 5 | import tech.dbgsoftware.easyrest.model.HttpEntity; 6 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 7 | 8 | public class ExceptionHandleActor extends AbstractActor { 9 | 10 | @Override 11 | public Receive createReceive() { 12 | return receiveBuilder() 13 | .match(HttpEntity.class, (httpEntity -> { 14 | httpEntity.getResponse().buildResponse(ResponseEntity.buildFailedResponse(new ErrorResponse(httpEntity.getErrorMap()))); 15 | httpEntity.getChannelHandlerContext().writeAndFlush(httpEntity.getResponse().getRealResponse()); 16 | })).build(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/Signal.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 6 | 7 | public class Signal { 8 | 9 | private static final Gson GSON = new GsonBuilder().create(); 10 | 11 | public static final String SUCCESS = "SUCCESS"; 12 | 13 | public static final String FAILED = "FAILED"; 14 | 15 | public static String getFailedMessage(){ 16 | return GSON.toJson(ResponseEntity.buildFailedResponse()); 17 | } 18 | 19 | public static String getSuccessMessage(){ 20 | return GSON.toJson(ResponseEntity.buildOkResponse()); 21 | } 22 | 23 | public static String getFailedMessage(String message){ 24 | return GSON.toJson(ResponseEntity.buildFailedResponse(message)); 25 | } 26 | 27 | public static String getSuccessMessage(String message){ 28 | return GSON.toJson(ResponseEntity.buildOkResponse(message)); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/remote/RemoteInvokeActor.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.remote; 2 | 3 | import akka.actor.AbstractActor; 4 | import akka.actor.ActorRef; 5 | import com.google.gson.Gson; 6 | import com.google.gson.GsonBuilder; 7 | import tech.dbgsoftware.easyrest.actors.ActorFactory; 8 | import tech.dbgsoftware.easyrest.actors.remote.model.RemoteInvokeObject; 9 | 10 | public class RemoteInvokeActor extends AbstractActor { 11 | 12 | private static final Gson GSON = new GsonBuilder().create(); 13 | 14 | @Override 15 | public Receive createReceive() { 16 | return receiveBuilder().match(String.class, (jsonData)-> { 17 | RemoteInvokeObject remoteInvokeObject = GSON.fromJson(jsonData, RemoteInvokeObject.class); 18 | remoteInvokeObject.setSender(getSender()); 19 | ActorFactory.createActor(RemoteObjectAnalysisActor.class).tell(remoteInvokeObject, ActorRef.noSender()); 20 | }).build(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/remote/RemoteObjectAnalysisActor.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.remote; 2 | 3 | import akka.actor.AbstractActor; 4 | import akka.actor.ActorRef; 5 | import tech.dbgsoftware.easyrest.actors.ActorFactory; 6 | import tech.dbgsoftware.easyrest.actors.Signal; 7 | import tech.dbgsoftware.easyrest.actors.remote.conf.EasyRestDistributedServiceBind; 8 | import tech.dbgsoftware.easyrest.actors.remote.model.RemoteInvokeObject; 9 | import tech.dbgsoftware.easyrest.actors.request.ControllerInvokeActor; 10 | import tech.dbgsoftware.easyrest.aop.resolvers.JsonDataResolve; 11 | 12 | import java.lang.reflect.Method; 13 | 14 | public class RemoteObjectAnalysisActor extends AbstractActor { 15 | 16 | @Override 17 | public Receive createReceive() { 18 | return receiveBuilder().match(RemoteInvokeObject.class, (remoteInvokeObject -> { 19 | Class controller = EasyRestDistributedServiceBind.getLocalServiceControllerMap().get(remoteInvokeObject.getInterfaceClassName()); 20 | remoteInvokeObject.setImplClass(controller); 21 | Method invokeMethod = null; 22 | for (Method method : controller.getMethods()) { 23 | if (method.getName().equals(remoteInvokeObject.getMethodName())){ 24 | invokeMethod = method; 25 | break; 26 | } 27 | } 28 | if (invokeMethod == null){ 29 | remoteInvokeObject.getSender().tell(Signal.getFailedMessage(remoteInvokeObject.getMethodName() + " not found"), remoteInvokeObject.getSender()); 30 | } else { 31 | if (invokeMethod.getGenericParameterTypes().length != remoteInvokeObject.getArgs().length){ 32 | remoteInvokeObject.getSender().tell(Signal.getFailedMessage("parameter number not correct"), remoteInvokeObject.getSender()); 33 | } 34 | remoteInvokeObject.setMethod(invokeMethod); 35 | remoteInvokeObject.updateArgs(JsonDataResolve.resolveArgs(invokeMethod.getGenericParameterTypes(), remoteInvokeObject.getArgs())); 36 | ActorFactory.createActor(ControllerInvokeActor.class).tell(remoteInvokeObject, ActorRef.noSender()); 37 | } 38 | })).build(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/remote/RemoteRequestUtil.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.remote; 2 | 3 | import akka.pattern.Patterns; 4 | import akka.util.Timeout; 5 | import scala.concurrent.Await; 6 | import scala.concurrent.Future; 7 | import scala.concurrent.duration.Duration; 8 | import tech.dbgsoftware.easyrest.actors.ActorFactory; 9 | import tech.dbgsoftware.easyrest.actors.remote.conf.EasyRestDistributedServiceBind; 10 | import tech.dbgsoftware.easyrest.actors.remote.model.RemoteInvokeObject; 11 | import tech.dbgsoftware.easyrest.actors.remote.model.ServiceInfo; 12 | import tech.dbgsoftware.easyrest.utils.JsonTranslationUtil; 13 | import tech.dbgsoftware.easyrest.utils.LogUtils; 14 | 15 | import java.lang.reflect.Method; 16 | 17 | public class RemoteRequestUtil { 18 | 19 | private static final Timeout REQUEST_TIMEOUT = new Timeout(Duration.create(60, "seconds")); 20 | 21 | private static final Timeout REQUEST_TIMEOUT_FOR_INIT = new Timeout(Duration.create(10, "seconds")); 22 | 23 | public static Object createRemoteRequest(Method method, Object[] args, long connectionMillis, long resultMillis){ 24 | return createRemoteRequest(method, args, null, connectionMillis, resultMillis); 25 | } 26 | 27 | public static Object createRemoteRequest(Method method, Object[] args, String invokeBeanName, long connectionMillis, long resultMillis){ 28 | ServiceInfo serviceInfo = EasyRestDistributedServiceBind.getServiceInfoMap().get(method.getDeclaringClass().getName()); 29 | RemoteInvokeObject remoteInvokeObject; 30 | if (invokeBeanName != null) { 31 | remoteInvokeObject = new RemoteInvokeObject(method, args, invokeBeanName); 32 | } else { 33 | remoteInvokeObject = new RemoteInvokeObject(method, args); 34 | } 35 | return getInvoke(serviceInfo.getAkkaSystemName(), serviceInfo.getHost(), serviceInfo.getPort(), JsonTranslationUtil.toJsonString(remoteInvokeObject), connectionMillis, resultMillis); 36 | } 37 | 38 | private static Object getInvoke(String remoteActorSystemName, String remoteHost, String port, Object msg, long connectionMillis, long resultMillis){ 39 | try { 40 | if (connectionMillis > 0 && resultMillis > 0){ 41 | return Await.result(getInvokeFuture(remoteActorSystemName, remoteHost, port, msg, new Timeout(Duration.create(connectionMillis, "millis"))), new Timeout(Duration.create(resultMillis, "millis")).duration()); 42 | } else { 43 | return Await.result(getInvokeFuture(remoteActorSystemName, remoteHost, port, msg, REQUEST_TIMEOUT), REQUEST_TIMEOUT.duration()); 44 | } 45 | } catch (Exception e) { 46 | LogUtils.error(e.getMessage(), e); 47 | return null; 48 | } 49 | } 50 | 51 | private static Future getInvokeFuture(String remoteActorSystemName, String remoteHost, String port, Object msg, Timeout timeout){ 52 | try { 53 | return Patterns.ask(ActorFactory.createRemoteInvokeActor(remoteActorSystemName, remoteHost, port), msg, timeout); 54 | } catch (Exception e) { 55 | LogUtils.error(e.getMessage(), e); 56 | return null; 57 | } 58 | } 59 | 60 | static Object getServiceExchanged(String remoteActorSystemName, String remoteHost, String port, Object msg){ 61 | try { 62 | return Await.result(Patterns.ask(ActorFactory.createRemoteServiceExchangedActor(remoteActorSystemName, remoteHost, port), msg, REQUEST_TIMEOUT_FOR_INIT), REQUEST_TIMEOUT_FOR_INIT.duration()); 63 | } catch (Exception e) { 64 | LogUtils.error(e.getMessage(), e); 65 | return null; 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/remote/RemoteServiceExchangeActor.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.remote; 2 | 3 | import akka.actor.AbstractActor; 4 | import tech.dbgsoftware.easyrest.actors.remote.conf.EasyRestDistributedServiceBind; 5 | import tech.dbgsoftware.easyrest.utils.LogUtils; 6 | 7 | import java.util.Set; 8 | import java.util.concurrent.CountDownLatch; 9 | import java.util.concurrent.ExecutorService; 10 | import java.util.concurrent.Executors; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | public class RemoteServiceExchangeActor extends AbstractActor { 14 | 15 | public static void initServiceMap() { 16 | ExecutorService executors = Executors.newFixedThreadPool(5); 17 | try { 18 | CountDownLatch countDownLatch = new CountDownLatch(EasyRestDistributedServiceBind.getServiceMapping().getServices().size() - 1); 19 | EasyRestDistributedServiceBind.getServiceMapping().getServices() 20 | .stream() 21 | .filter((serviceInfo -> !serviceInfo.getAkkaSystemName().equals(EasyRestDistributedServiceBind.getServiceMapping().getSelf().getAkkaSystemName()))) 22 | .forEach((serviceInfo -> { 23 | Thread askThread = new Thread(() -> { 24 | Object result = RemoteRequestUtil.getServiceExchanged(serviceInfo.getAkkaSystemName(), serviceInfo.getHost(), serviceInfo.getPort(), RemoteServiceExchangeActor.class); 25 | while (!(result instanceof Set)) { 26 | try { 27 | Thread.sleep(500); 28 | result = RemoteRequestUtil.getServiceExchanged(serviceInfo.getAkkaSystemName(), serviceInfo.getHost(), serviceInfo.getPort(), RemoteServiceExchangeActor.class); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | ((Set) result).forEach((service) -> EasyRestDistributedServiceBind.getServiceInfoMap().putIfAbsent(String.valueOf(service), serviceInfo)); 34 | countDownLatch.countDown(); 35 | }); 36 | executors.execute(askThread); 37 | })); 38 | countDownLatch.await(60, TimeUnit.MINUTES); 39 | LogUtils.info("Service mapping init success.", RemoteServiceExchangeActor.class); 40 | } catch (InterruptedException e) { 41 | LogUtils.error(e.getMessage(), e); 42 | } finally { 43 | executors.shutdown(); 44 | } 45 | } 46 | 47 | @Override 48 | public Receive createReceive() { 49 | return receiveBuilder().matchAny((exchangeActor) -> { 50 | if (EasyRestDistributedServiceBind.isInitFinished()) { 51 | getSender().tell(EasyRestDistributedServiceBind.getLocalService(), getSender()); 52 | } else { 53 | getSender().tell(EasyRestDistributedServiceBind.isInitFinished(), getSender()); 54 | } 55 | }).build(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/remote/conf/EasyRestDistributedServiceBind.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.remote.conf; 2 | 3 | import tech.dbgsoftware.easyrest.actors.remote.model.ServiceInfo; 4 | import com.google.gson.Gson; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.InputStreamReader; 10 | import java.util.*; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | 13 | public class EasyRestDistributedServiceBind { 14 | 15 | private static boolean initFinished = false; 16 | 17 | private static boolean isNeedDistributed = false; 18 | 19 | private static ServiceMapping serviceMapping = null; 20 | 21 | private static final Set localService = new HashSet<>(); 22 | 23 | private static final Map LOCAL_SERVICE_CONTROLLER_MAP = new HashMap<>(); 24 | 25 | private static final Map SERVICE_INFO_MAP = new ConcurrentHashMap<>(); 26 | 27 | public static void loadConfiguration(InputStream resourceAsStream) throws IOException { 28 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resourceAsStream)); 29 | String temp; 30 | StringBuilder configuration = new StringBuilder(); 31 | while ((temp = bufferedReader.readLine()) != null){ 32 | configuration.append(temp); 33 | } 34 | bufferedReader.close(); 35 | resourceAsStream.close(); 36 | serviceMapping = new Gson().fromJson(configuration.toString(), ServiceMapping.class); 37 | isNeedDistributed = true; 38 | } 39 | 40 | public static boolean isInitFinished() { 41 | return initFinished; 42 | } 43 | 44 | public static void setInitFinished(boolean initFinished) { 45 | EasyRestDistributedServiceBind.initFinished = initFinished; 46 | } 47 | 48 | public static void addService(Class aClass, Class controller){ 49 | localService.add(aClass.getName()); 50 | LOCAL_SERVICE_CONTROLLER_MAP.putIfAbsent(aClass.getName(), controller); 51 | } 52 | 53 | public static ServiceMapping getServiceMapping() { 54 | return serviceMapping; 55 | } 56 | 57 | public static boolean isIsNeedDistributed() { 58 | return isNeedDistributed; 59 | } 60 | 61 | public static Set getLocalService() { 62 | return localService; 63 | } 64 | 65 | public static Map getServiceInfoMap() { 66 | return SERVICE_INFO_MAP; 67 | } 68 | 69 | public static Map getLocalServiceControllerMap() { 70 | return LOCAL_SERVICE_CONTROLLER_MAP; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/remote/conf/ServiceMapping.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.remote.conf; 2 | 3 | import tech.dbgsoftware.easyrest.actors.remote.model.ServiceInfo; 4 | 5 | import java.util.List; 6 | 7 | public class ServiceMapping { 8 | 9 | private ServiceInfo self; 10 | private List services; 11 | 12 | public ServiceInfo getSelf() { 13 | return self; 14 | } 15 | 16 | public List getServices() { 17 | return services; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/remote/model/RemoteInvokeObject.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.remote.model; 2 | 3 | import akka.actor.ActorRef; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | public class RemoteInvokeObject { 8 | 9 | private ActorRef sender; 10 | 11 | private Class implClass; 12 | 13 | private Method method; 14 | 15 | private String interfaceClassName; 16 | 17 | private String methodName; 18 | 19 | private Object[] args; 20 | 21 | private Object result; 22 | 23 | private String invokeBeanName = "null"; 24 | 25 | public RemoteInvokeObject(Method method, Object[] args) { 26 | this.interfaceClassName = method.getDeclaringClass().getName(); 27 | this.methodName = method.getName(); 28 | this.args = args; 29 | } 30 | 31 | public RemoteInvokeObject(Method method, Object[] args, String invokeBeanName) { 32 | this.interfaceClassName = method.getDeclaringClass().getName(); 33 | this.methodName = method.getName(); 34 | this.args = args; 35 | this.invokeBeanName = invokeBeanName; 36 | } 37 | 38 | public String getInterfaceClassName() { 39 | return interfaceClassName; 40 | } 41 | 42 | public String getMethodName() { 43 | return methodName; 44 | } 45 | 46 | public void updateArgs(Object[] args) { 47 | this.args = args; 48 | } 49 | 50 | public Object[] getArgs() { 51 | return args; 52 | } 53 | 54 | public ActorRef getSender() { 55 | return sender; 56 | } 57 | 58 | public Class getImplClass() { 59 | return implClass; 60 | } 61 | 62 | public void setImplClass(Class implClass) { 63 | this.implClass = implClass; 64 | } 65 | 66 | public Method getMethod() { 67 | return method; 68 | } 69 | 70 | public void setMethod(Method method) { 71 | this.method = method; 72 | } 73 | 74 | public void setSender(ActorRef sender) { 75 | this.sender = sender; 76 | } 77 | 78 | public Object getResult() { 79 | return result; 80 | } 81 | 82 | public void setResult(Object result) { 83 | this.result = result; 84 | } 85 | 86 | public String getInvokeBeanName() { 87 | return invokeBeanName; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/remote/model/ServiceInfo.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.remote.model; 2 | 3 | public class ServiceInfo { 4 | 5 | private String akkaSystemName; 6 | private String host; 7 | private String port; 8 | 9 | public String getAkkaSystemName() { 10 | return akkaSystemName; 11 | } 12 | 13 | public String getHost() { 14 | return host; 15 | } 16 | 17 | public String getPort() { 18 | return port; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/request/ControllerInvokeActor.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.request; 2 | 3 | import akka.actor.AbstractActor; 4 | import akka.actor.ActorRef; 5 | import tech.dbgsoftware.easyrest.actors.ActorFactory; 6 | import tech.dbgsoftware.easyrest.actors.ExceptionHandleActor; 7 | import tech.dbgsoftware.easyrest.actors.Signal; 8 | import tech.dbgsoftware.easyrest.actors.remote.model.RemoteInvokeObject; 9 | import tech.dbgsoftware.easyrest.actors.response.ResponseProcessActor; 10 | import tech.dbgsoftware.easyrest.annotations.method.SkipCustomerInject; 11 | import tech.dbgsoftware.easyrest.annotations.method.SkipCustomerResponse; 12 | import tech.dbgsoftware.easyrest.aop.customer.CustomInjection; 13 | import tech.dbgsoftware.easyrest.aop.customer.CustomResponse; 14 | import tech.dbgsoftware.easyrest.ioc.utils.BeanOperationUtils; 15 | import tech.dbgsoftware.easyrest.model.HttpEntity; 16 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 17 | import tech.dbgsoftware.easyrest.utils.LogUtils; 18 | 19 | import java.lang.reflect.Method; 20 | import java.util.concurrent.ExecutorService; 21 | import java.util.concurrent.Executors; 22 | 23 | public class ControllerInvokeActor extends AbstractActor { 24 | 25 | private static final ExecutorService OPERATION_SERVICE = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 10); 26 | 27 | @Override 28 | public Receive createReceive() { 29 | return receiveBuilder().match(HttpEntity.class, (httpEntity -> { 30 | try { 31 | Method method = httpEntity.getMethod(); 32 | Class controller = httpEntity.getController(); 33 | if (method.getReturnType().getName().equalsIgnoreCase(Void.class.getSimpleName())) { 34 | OPERATION_SERVICE.execute(() -> { 35 | try { 36 | invokeMethod(method, controller, httpEntity.getArgs(), null, httpEntity); 37 | } catch (Exception e) { 38 | LogUtils.error(e.getMessage(), e); 39 | } 40 | }); 41 | httpEntity.setResponseEntity(ResponseEntity.buildOkResponse()); 42 | ActorFactory.createActor(ResponseProcessActor.class).tell(httpEntity, ActorRef.noSender()); 43 | } else if (method.getReturnType().equals(ResponseEntity.class)) { 44 | OPERATION_SERVICE.execute(() -> { 45 | try { 46 | httpEntity.setResponseEntity((ResponseEntity) invokeMethod(method, controller, httpEntity.getArgs(), null, httpEntity)); 47 | ActorFactory.createActor(ResponseProcessActor.class).tell(httpEntity, ActorRef.noSender()); 48 | } catch (Exception e) { 49 | LogUtils.error(e.getMessage(), e); 50 | httpEntity.addError(e.getCause()); 51 | ActorFactory.createActor(ExceptionHandleActor.class).tell(httpEntity, ActorRef.noSender()); 52 | } 53 | }); 54 | } else { 55 | OPERATION_SERVICE.execute(() -> { 56 | try { 57 | httpEntity.setResponseEntity(ResponseEntity.buildBaseResponse(invokeMethod(method, controller, httpEntity.getArgs(), null, httpEntity))); 58 | ActorFactory.createActor(ResponseProcessActor.class).tell(httpEntity, ActorRef.noSender()); 59 | } catch (Exception e) { 60 | LogUtils.error(e.getMessage(), e); 61 | httpEntity.addError(e.getCause()); 62 | ActorFactory.createActor(ExceptionHandleActor.class).tell(httpEntity, ActorRef.noSender()); 63 | } 64 | }); 65 | } 66 | } catch (Exception e) { 67 | LogUtils.error(e.getMessage(), e); 68 | httpEntity.addError(e.getCause()); 69 | ActorFactory.createActor(ExceptionHandleActor.class).tell(httpEntity, ActorRef.noSender()); 70 | } 71 | })).match(RemoteInvokeObject.class, (remoteInvokeObject -> { 72 | try { 73 | Object result = invokeMethod(remoteInvokeObject.getMethod(), remoteInvokeObject.getImplClass(), remoteInvokeObject.getArgs(), remoteInvokeObject.getInvokeBeanName(), null); 74 | if (remoteInvokeObject.getMethod().getReturnType().getName().equalsIgnoreCase(Void.class.getSimpleName())) { 75 | remoteInvokeObject.setResult(ResponseEntity.buildOkResponse()); 76 | } else { 77 | remoteInvokeObject.setResult(result); 78 | } 79 | ActorFactory.createActor(ResponseProcessActor.class).tell(remoteInvokeObject, ActorRef.noSender()); 80 | } catch (Exception e) { 81 | LogUtils.error(e.getMessage(), e); 82 | remoteInvokeObject.getSender().tell(Signal.getFailedMessage(e.getMessage()), remoteInvokeObject.getSender()); 83 | } 84 | })).build(); 85 | } 86 | 87 | private Object invokeMethod(Method method, Class controller, Object[] args, String invokeBeanName, HttpEntity httpEntity) throws Exception { 88 | if (args.length > 0) { 89 | if (invokeBeanName == null || invokeBeanName.equalsIgnoreCase("null")) { 90 | Object object = BeanOperationUtils.getBean(controller); 91 | invokePerCheck(object, httpEntity); 92 | return invokeCustomResponse(object, httpEntity, method.invoke(object, args)); 93 | } else { 94 | Object object = BeanOperationUtils.getBean(invokeBeanName, controller); 95 | invokePerCheck(object, httpEntity); 96 | return invokeCustomResponse(object, httpEntity, method.invoke(object, args)); 97 | } 98 | } else { 99 | if (invokeBeanName == null || invokeBeanName.equalsIgnoreCase("null")) { 100 | Object object = BeanOperationUtils.getBean(controller); 101 | invokePerCheck(object, httpEntity); 102 | return invokeCustomResponse(object, httpEntity, method.invoke(object)); 103 | } else { 104 | Object object = BeanOperationUtils.getBean(invokeBeanName, controller); 105 | invokePerCheck(object, httpEntity); 106 | return invokeCustomResponse(object, httpEntity, method.invoke(object)); 107 | } 108 | } 109 | } 110 | 111 | private void invokePerCheck(Object classz, HttpEntity httpEntity) throws Exception { 112 | if (!httpEntity.getMethod().isAnnotationPresent(SkipCustomerInject.class) && httpEntity != null && classz instanceof CustomInjection) { 113 | CustomInjection.class.getMethods()[0].invoke(classz, httpEntity); 114 | } 115 | } 116 | 117 | private Object invokeCustomResponse(Object classz, HttpEntity httpEntity, Object response) throws Exception { 118 | if (!httpEntity.getMethod().isAnnotationPresent(SkipCustomerResponse.class) && httpEntity != null && classz instanceof CustomResponse) { 119 | return CustomResponse.class.getMethods()[0].invoke(classz, httpEntity, response); 120 | } 121 | return response; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/request/RequestProcessActor.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.request; 2 | 3 | import akka.actor.AbstractActor; 4 | import akka.actor.ActorRef; 5 | import tech.dbgsoftware.easyrest.actors.ActorFactory; 6 | import tech.dbgsoftware.easyrest.actors.ExceptionHandleActor; 7 | import tech.dbgsoftware.easyrest.actors.response.OutputActor; 8 | import tech.dbgsoftware.easyrest.aop.StaticAopStepUtil; 9 | import tech.dbgsoftware.easyrest.exception.PageNotFoundException; 10 | import tech.dbgsoftware.easyrest.model.HttpEntity; 11 | import tech.dbgsoftware.easyrest.utils.LogUtils; 12 | 13 | public class RequestProcessActor extends AbstractActor { 14 | 15 | @Override 16 | public Receive createReceive() { 17 | return receiveBuilder().match(HttpEntity.class, (httpEntity -> { 18 | HttpEntity[] httpEntityTemp = {httpEntity}; 19 | StaticAopStepUtil.getAopPreCommitStepList().forEach((step) -> { 20 | if (httpEntityTemp[0].getErrorMap().size() == 0 && !httpEntityTemp[0].isOptionsCheck()) { 21 | try { 22 | httpEntityTemp[0] = step.executeStep(httpEntityTemp[0]); 23 | } catch (Exception e) { 24 | httpEntityTemp[0].addError(e); 25 | if (e instanceof PageNotFoundException) { 26 | httpEntity.getChannelHandlerContext().close(); 27 | return; 28 | } 29 | LogUtils.error(e.getMessage(), e); 30 | } 31 | } 32 | }); 33 | if (httpEntityTemp[0].getErrorMap().size() == 0) { 34 | if (httpEntityTemp[0].isOptionsCheck()) { 35 | ActorFactory.createActor(OutputActor.class).tell(httpEntityTemp[0], ActorRef.noSender()); 36 | } else { 37 | ActorFactory.createActor(ControllerInvokeActor.class).tell(httpEntityTemp[0], ActorRef.noSender()); 38 | } 39 | } else { 40 | ActorFactory.createActor(ExceptionHandleActor.class).tell(httpEntityTemp[0], ActorRef.noSender()); 41 | } 42 | })).build(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/response/OutputActor.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.response; 2 | 3 | import akka.actor.AbstractActor; 4 | import tech.dbgsoftware.easyrest.actors.remote.model.RemoteInvokeObject; 5 | import tech.dbgsoftware.easyrest.model.HttpEntity; 6 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 7 | import tech.dbgsoftware.easyrest.utils.JsonTranslationUtil; 8 | 9 | public class OutputActor extends AbstractActor { 10 | @Override 11 | public Receive createReceive() { 12 | return receiveBuilder().match(HttpEntity.class, (httpEntity -> { 13 | if (httpEntity.isOptionsCheck() || 14 | httpEntity.getRestObject().getMethod().getReturnType().equals(ResponseEntity.class) || 15 | httpEntity.getRestObject().getMethod().getReturnType().getSimpleName().equalsIgnoreCase(Void.class.getSimpleName())) { 16 | httpEntity.getResponse().buildResponse(httpEntity.getResponseEntity()); 17 | } else if (httpEntity.getRestObject().getMethod().getReturnType().equals(String.class)) { 18 | httpEntity.getResponse().buildStringResponse(String.valueOf(httpEntity.getResponseEntity().getData())); 19 | } else { 20 | httpEntity.getResponse().buildResponse(httpEntity.getResponseEntity().getData()); 21 | } 22 | httpEntity.getChannelHandlerContext().writeAndFlush(httpEntity.getResponse().getRealResponse()); 23 | })).match(RemoteInvokeObject.class, (remoteInvokeObject -> remoteInvokeObject.getSender().tell(JsonTranslationUtil.toJsonString(remoteInvokeObject.getResult()), remoteInvokeObject.getSender()))).build(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/actors/response/ResponseProcessActor.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.actors.response; 2 | 3 | import akka.actor.AbstractActor; 4 | import akka.actor.ActorRef; 5 | import tech.dbgsoftware.easyrest.actors.ActorFactory; 6 | import tech.dbgsoftware.easyrest.actors.ExceptionHandleActor; 7 | import tech.dbgsoftware.easyrest.actors.remote.model.RemoteInvokeObject; 8 | import tech.dbgsoftware.easyrest.aop.StaticAopStepUtil; 9 | import tech.dbgsoftware.easyrest.model.HttpEntity; 10 | import tech.dbgsoftware.easyrest.utils.LogUtils; 11 | 12 | public class ResponseProcessActor extends AbstractActor { 13 | 14 | @Override 15 | public Receive createReceive() { 16 | return receiveBuilder().match(HttpEntity.class, (httpEntity -> { 17 | HttpEntity[] httpEntityTemp = {httpEntity}; 18 | StaticAopStepUtil.getAopPostCommitStepList().forEach((step) -> { 19 | if (httpEntityTemp[0].getErrorMap().size() == 0) { 20 | try { 21 | httpEntityTemp[0] = step.executeStep(httpEntityTemp[0]); 22 | } catch (Exception e) { 23 | LogUtils.error(e.getMessage(), e); 24 | httpEntityTemp[0].addError(e); 25 | } 26 | } 27 | }); 28 | if (httpEntityTemp[0].getErrorMap().size() == 0) { 29 | ActorFactory.createActor(OutputActor.class).tell(httpEntityTemp[0], ActorRef.noSender()); 30 | } else { 31 | ActorFactory.createActor(ExceptionHandleActor.class).tell(httpEntityTemp[0], ActorRef.noSender()); 32 | } 33 | })).match(RemoteInvokeObject.class, (remoteInvokeObject -> ActorFactory.createActor(OutputActor.class).tell(remoteInvokeObject, ActorRef.noSender()))).build(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/async/AsyncRequest.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.async; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by liuhongyu.louie on 2017/4/4. 10 | */ 11 | @Target({ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface AsyncRequest { 14 | } 15 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/async/SyncRequest.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.async; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by liuhongyu.louie on 2017/4/4. 10 | */ 11 | @Target({ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface SyncRequest { 14 | } 15 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/bean/BindService.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.bean; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by liuhongyu.louie on 2017/4/4. 10 | */ 11 | @Target({ElementType.TYPE, ElementType.METHOD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface BindService { 14 | Class value(); 15 | } 16 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/bean/EasyRestInterface.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.bean; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by liuhongyu.louie on 2017/4/4. 10 | */ 11 | @Target({ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface EasyRestInterface { 14 | } 15 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/history/HistoryRequired.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.history; 2 | 3 | 4 | import tech.dbgsoftware.easyrest.annotations.transaction.TransactionRequired; 5 | 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | /** 12 | * Created by liuhongyu.louie on 2017/1/9. 13 | */ 14 | @Target({ElementType.TYPE, ElementType.FIELD}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @TransactionRequired 17 | public @interface HistoryRequired { 18 | String[] value() default {}; 19 | } 20 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/method/BindURL.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.method; 2 | 3 | import tech.dbgsoftware.easyrest.annotations.bean.EasyRestInterface; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * Created by liuhongyu.louie on 2017/4/4. 12 | */ 13 | @Target({ElementType.TYPE}) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @EasyRestInterface 16 | public @interface BindURL { 17 | String[] value(); 18 | } 19 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/method/Delete.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.method; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2016/10/23. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Delete { 12 | String value() default ""; 13 | } 14 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/method/Get.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.method; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2016/10/23. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Get { 12 | String value() default ""; 13 | } 14 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/method/Post.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.method; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2016/10/23. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Post { 12 | String value() default ""; 13 | } 14 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/method/Put.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.method; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2016/10/23. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Put { 12 | String value() default ""; 13 | } 14 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/method/RequestMethod.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.method; 2 | 3 | /** 4 | * Created by liuhongyu.louie on 2016/12/29. 5 | */ 6 | public enum RequestMethod { 7 | 8 | POST("POST", Post.class), 9 | 10 | GET("GET", Get.class), 11 | 12 | PUT("PUT", Put.class), 13 | 14 | DELETE("DELETE", Delete.class); 15 | 16 | String methodName; 17 | 18 | Class methodClass; 19 | 20 | RequestMethod(String methodName, Class methodClass){ 21 | this.methodName = methodName; 22 | this.methodClass = methodClass; 23 | } 24 | 25 | public final String getMethodName(){ 26 | return methodName; 27 | } 28 | 29 | public final Class getMethodClass(){ 30 | return methodClass; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/method/SkipCustomerInject.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.method; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by honliu on 2019/6/26. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface SkipCustomerInject { 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/method/SkipCustomerResponse.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.method; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) 6 | @Retention(RetentionPolicy.RUNTIME) 7 | @Documented 8 | public @interface SkipCustomerResponse { 9 | } 10 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/parameter/AllDefined.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.parameter; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2016/10/1. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface AllDefined { 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/parameter/AutoInject.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.parameter; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2016/9/30. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | @AllDefined 12 | public @interface AutoInject { 13 | } 14 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/parameter/FromPath.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.parameter; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2017/1/15. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.PARAMETER}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface FromPath { 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/parameter/NotNull.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.parameter; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2016/10/23. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface NotNull { 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/parameter/Optional.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.parameter; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2017/1/15. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Optional { 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/parameter/SkipInject.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.parameter; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by ${Lhy} on 17/2/4. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface SkipInject { 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/parameter/validation/AllDefinedValidation.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.parameter.validation; 2 | 3 | import tech.dbgsoftware.easyrest.annotations.parameter.AllDefined; 4 | import tech.dbgsoftware.easyrest.model.HttpEntity; 5 | import tech.dbgsoftware.easyrest.model.request.RestObject; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class AllDefinedValidation { 11 | 12 | public static List validate(HttpEntity httpEntity){ 13 | List errorList = new ArrayList<>(); 14 | RestObject restObject = httpEntity.getRestObject(); 15 | if (restObject.getMethod().isAnnotationPresent(AllDefined.class)){ 16 | int[] index = new int[1]; 17 | restObject.getParameterTypeMap().forEach((name, type) -> { 18 | if (httpEntity.getArgs()[index[0]] == null){ 19 | errorList.add(name); 20 | } 21 | index[0]++; 22 | }); 23 | } 24 | return errorList; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/parameter/validation/NotNullValidation.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.parameter.validation; 2 | 3 | import tech.dbgsoftware.easyrest.annotations.parameter.NotNull; 4 | import tech.dbgsoftware.easyrest.model.HttpEntity; 5 | import tech.dbgsoftware.easyrest.model.request.RestObject; 6 | 7 | import java.lang.reflect.Parameter; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class NotNullValidation { 12 | 13 | public static List validate(HttpEntity httpEntity){ 14 | List errorList = new ArrayList<>(); 15 | RestObject restObject = httpEntity.getRestObject(); 16 | for (Parameter parameter : restObject.getMethod().getParameters()) { 17 | if (parameter.isAnnotationPresent(NotNull.class)){ 18 | int[] index = new int[1]; 19 | restObject.getParameterTypeMap().forEach((name, type) -> { 20 | if (httpEntity.getArgs()[index[0]] == null) { 21 | errorList.add(name); 22 | } 23 | index[0]++; 24 | }); 25 | } 26 | } 27 | return errorList; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/permission/PermissionRequired.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.permission; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2016/10/9. 7 | */ 8 | @Target({ElementType.TYPE, ElementType.FIELD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface PermissionRequired { 12 | String[] parameters() default {""}; 13 | } 14 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/annotations/transaction/TransactionRequired.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.annotations.transaction; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by liuhongyu.louie on 2017/1/12. 10 | */ 11 | @Target({ElementType.TYPE, ElementType.FIELD}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface TransactionRequired { 14 | } 15 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/AopPostCommitStep.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop; 2 | 3 | public interface AopPostCommitStep extends AopStep { 4 | } 5 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/AopPreCommitStep.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop; 2 | 3 | public interface AopPreCommitStep extends AopStep { 4 | } 5 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/AopStep.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop; 2 | 3 | import tech.dbgsoftware.easyrest.model.HttpEntity; 4 | 5 | /** 6 | * Created by liuhongyu.louie on 2016/12/29. 7 | */ 8 | public interface AopStep { 9 | 10 | HttpEntity executeStep(HttpEntity httpEntity) throws Exception; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/StaticAopStepUtil.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Component 9 | public class StaticAopStepUtil { 10 | 11 | private static List AOP_PRE_COMMIT_STEP_LIST = new ArrayList<>(); 12 | 13 | private static List AOP_POST_COMMIT_STEP_LIST = new ArrayList<>(); 14 | 15 | public void setAopPreCommitStepList(List aopPreCommitStepList) { 16 | AOP_PRE_COMMIT_STEP_LIST = aopPreCommitStepList; 17 | } 18 | 19 | public void setAopPostCommitStepList(List aopPostCommitStepList){ 20 | AOP_POST_COMMIT_STEP_LIST = aopPostCommitStepList; 21 | } 22 | 23 | public static List getAopPreCommitStepList() { 24 | return AOP_PRE_COMMIT_STEP_LIST; 25 | } 26 | 27 | public static List getAopPostCommitStepList(){ 28 | return AOP_POST_COMMIT_STEP_LIST; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/customer/CustomInjection.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop.customer; 2 | 3 | import tech.dbgsoftware.easyrest.model.HttpEntity; 4 | 5 | public interface CustomInjection { 6 | 7 | HttpEntity preCheck(HttpEntity httpEntity) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/customer/CustomResponse.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop.customer; 2 | 3 | import tech.dbgsoftware.easyrest.model.HttpEntity; 4 | 5 | public interface CustomResponse { 6 | 7 | Object processResponse(HttpEntity httpEntity, Object response); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/pre/AopInitRequestInfoStep.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop.pre; 2 | 3 | import tech.dbgsoftware.easyrest.aop.AopPreCommitStep; 4 | import tech.dbgsoftware.easyrest.model.HttpEntity; 5 | 6 | /** 7 | * Created by liuhongyu.louie on 2016/12/31. 8 | */ 9 | public class AopInitRequestInfoStep implements AopPreCommitStep { 10 | 11 | @Override 12 | public HttpEntity executeStep(HttpEntity entity) { 13 | entity.setMethod(entity.getRestObject().getMethod()); 14 | entity.setController(entity.getRestObject().getController()); 15 | return entity; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/pre/AopParametersInjectStep.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop.pre; 2 | 3 | import io.netty.handler.codec.http.HttpMethod; 4 | import tech.dbgsoftware.easyrest.annotations.parameter.validation.AllDefinedValidation; 5 | import tech.dbgsoftware.easyrest.aop.AopPreCommitStep; 6 | import tech.dbgsoftware.easyrest.aop.resolvers.FormDataResolve; 7 | import tech.dbgsoftware.easyrest.aop.resolvers.JsonDataResolve; 8 | import tech.dbgsoftware.easyrest.aop.resolvers.UrlDataResolve; 9 | import tech.dbgsoftware.easyrest.exception.ParameterNotFoundException; 10 | import tech.dbgsoftware.easyrest.model.HttpEntity; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | public class AopParametersInjectStep implements AopPreCommitStep { 16 | 17 | @Override 18 | public HttpEntity executeStep(HttpEntity entity) { 19 | return inject(entity); 20 | } 21 | 22 | private HttpEntity inject(HttpEntity httpEntity){ 23 | if (httpEntity.getRequest().isMultipart()){ 24 | httpEntity.setArgs(FormDataResolve.resolveArgs(httpEntity)); 25 | } else { 26 | if (httpEntity.getRequest().getRequestHttpMethod().equalsIgnoreCase(HttpMethod.GET.name())){ 27 | httpEntity.setArgs(UrlDataResolve.resolveArgs(httpEntity)); 28 | } else { 29 | httpEntity.setArgs(JsonDataResolve.resolveArgs(httpEntity)); 30 | } 31 | } 32 | List errorParams = validationParameters(httpEntity); 33 | if (errorParams.size() > 0){ 34 | StringBuilder stringBuilder = new StringBuilder(); 35 | errorParams.forEach((name) -> stringBuilder.append(name).append(", ")); 36 | stringBuilder.delete(stringBuilder.length() - 2, stringBuilder.length()); 37 | if (errorParams.size() == 1){ 38 | stringBuilder.append(" is not defined."); 39 | } else { 40 | stringBuilder.append(" are not defined."); 41 | } 42 | httpEntity.addError(new ParameterNotFoundException(stringBuilder.toString())); 43 | } 44 | return httpEntity; 45 | } 46 | 47 | private List validationParameters(HttpEntity httpEntity){ 48 | List errorNames = new ArrayList<>(); 49 | errorNames.addAll(AllDefinedValidation.validate(httpEntity)); 50 | return errorNames; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/pre/AopRequestValidateStep.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop.pre; 2 | 3 | import io.netty.handler.codec.http.HttpResponseStatus; 4 | import org.springframework.stereotype.Service; 5 | import tech.dbgsoftware.easyrest.aop.AopPreCommitStep; 6 | import tech.dbgsoftware.easyrest.exception.MethodNotAllowedException; 7 | import tech.dbgsoftware.easyrest.exception.PageNotFoundException; 8 | import tech.dbgsoftware.easyrest.model.HttpEntity; 9 | import tech.dbgsoftware.easyrest.model.request.RestObject; 10 | import tech.dbgsoftware.easyrest.network.router.RouterProvider; 11 | 12 | 13 | /** 14 | * Created by liuhongyu.louie on 2016/12/29. 15 | */ 16 | @Service 17 | public class AopRequestValidateStep implements AopPreCommitStep { 18 | 19 | private static final String NOT_ALLOWED = "%s is not allowed."; 20 | 21 | private static final String NOT_FOUND = "%s is not found."; 22 | 23 | @Override 24 | public HttpEntity executeStep(HttpEntity entity) throws Exception { 25 | String url = entity.getRequest().getRequestUri(); 26 | RestObject restObject = RouterProvider.getRestObject(url); 27 | if (restObject == null){ 28 | entity.getResponse().getRealResponse().setStatus(HttpResponseStatus.NOT_FOUND); 29 | throw new PageNotFoundException(String.format(NOT_FOUND, url)); 30 | } else { 31 | if (!restObject.getHttpMethodList().contains(entity.getRequest().getRequestHttpMethod().toLowerCase())){ 32 | if (entity.getRequest().getRequestHttpMethod().toLowerCase().equalsIgnoreCase("options")) { 33 | entity.setOptionsCheck(true); 34 | } else { 35 | entity.getResponse().getRealResponse().setStatus(HttpResponseStatus.METHOD_NOT_ALLOWED); 36 | throw new MethodNotAllowedException(String.format(NOT_ALLOWED, entity.getRequest().getRequestHttpMethod())); 37 | } 38 | } 39 | } 40 | entity.setRestObject(restObject); 41 | return entity; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/resolvers/FormDataResolve.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop.resolvers; 2 | 3 | import tech.dbgsoftware.easyrest.model.HttpEntity; 4 | import tech.dbgsoftware.easyrest.model.request.RestObject; 5 | import tech.dbgsoftware.easyrest.network.router.RouterProvider; 6 | 7 | public class FormDataResolve { 8 | 9 | public static Object[] resolveArgs(HttpEntity httpEntity){ 10 | RestObject restObject = RouterProvider.getRestObject(httpEntity.getRequest().getRequestUri()); 11 | Object[] args = new Object[restObject.getParameterTypeMap().size()]; 12 | final int[] index = {0}; 13 | restObject.getParameterTypeMap().forEach((name, type) -> { 14 | try { 15 | if (httpEntity.getRestObject().getUriValues().containsKey(name)){ 16 | args[index[0]] = httpEntity.getRestObject().getUriValues().get(name); 17 | } else { 18 | args[index[0]] = ParameterTypeResolve.resolveType(type, httpEntity.getRequest().getFormData().get(name)); 19 | } 20 | } catch (NumberFormatException e) { 21 | httpEntity.addError(e); 22 | } 23 | index[0]++; 24 | }); 25 | return args; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/resolvers/JsonDataResolve.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop.resolvers; 2 | 3 | import tech.dbgsoftware.easyrest.model.HttpEntity; 4 | import tech.dbgsoftware.easyrest.model.request.RestObject; 5 | import tech.dbgsoftware.easyrest.network.router.RouterProvider; 6 | import tech.dbgsoftware.easyrest.utils.JsonTranslationUtil; 7 | 8 | import java.lang.reflect.Type; 9 | import java.util.Map; 10 | 11 | public class JsonDataResolve { 12 | 13 | public static Object[] resolveArgs(Type[] genericParameterTypes, Object[] args){ 14 | for (int i = 0; i < args.length; i++) { 15 | args[i] = JsonTranslationUtil.fromJson(String.valueOf(args[i]), genericParameterTypes[i]); 16 | } 17 | return args; 18 | } 19 | 20 | public static Object[] resolveArgs(HttpEntity httpEntity){ 21 | RestObject restObject = RouterProvider.getRestObject(httpEntity.getRequest().getRequestUri()); 22 | Object[] args = new Object[restObject.getParameterTypeMap().size()]; 23 | final int[] index = {0}; 24 | if (args.length > 1){ 25 | Map dataMap = JsonTranslationUtil.fromJson(httpEntity.getRequest().getJsonData(), Map.class); 26 | restObject.getParameterTypeMap().forEach((name, type) -> { 27 | if (httpEntity.getRestObject().getUriValues().containsKey(name)){ 28 | args[index[0]] = httpEntity.getRestObject().getUriValues().get(name); 29 | } else { 30 | args[index[0]] = dataMap == null ? null : JsonTranslationUtil.fromJson(String.valueOf(dataMap.get(name)), type); 31 | } 32 | index[0]++; 33 | }); 34 | } else if (args.length == 1){ 35 | restObject.getParameterTypeMap().forEach((name, type) -> { 36 | if (httpEntity.getRestObject().getUriValues().containsKey(name)){ 37 | args[index[0]] = httpEntity.getRestObject().getUriValues().get(name); 38 | } else { 39 | args[index[0]] = isBasicType(type) ? null : JsonTranslationUtil.fromJson(httpEntity.getRequest().getJsonData(), type); 40 | if (args[index[0]] == null) { 41 | Map data = JsonTranslationUtil.fromJson(httpEntity.getRequest().getJsonData(), Map.class); 42 | if (data != null && data.containsKey(name)) { 43 | args[index[0]] = JsonTranslationUtil.fromJson(data.get(name).toString(), type); 44 | } 45 | } 46 | } 47 | index[0]++; 48 | }); 49 | } 50 | return args; 51 | } 52 | 53 | private static boolean isBasicType(Type type) { 54 | if (type.getTypeName().equals(String.class.getName())){ 55 | return true; 56 | } else if (type.getTypeName().equals(Integer.class.getName()) || type.getTypeName().equals("int")){ 57 | return true; 58 | } else if (type.getTypeName().equals(Double.class.getName()) || type.getTypeName().equals("double")){ 59 | return true; 60 | } else if (type.getTypeName().equals(Long.class.getName()) || type.getTypeName().equals("long")){ 61 | return true; 62 | } else if (type.getTypeName().equals(Float.class.getName()) || type.getTypeName().equals("float")){ 63 | return true; 64 | } else return type.getTypeName().equals(Short.class.getName()) || type.getTypeName().equals("short"); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/resolvers/ParameterTypeResolve.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop.resolvers; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | public class ParameterTypeResolve { 6 | 7 | static Object resolveType(Type type, String value) throws NumberFormatException { 8 | if (type.getTypeName().equals(String.class.getName())){ 9 | return String.valueOf(value); 10 | } else if (type.getTypeName().equals(Integer.class.getName()) || type.getTypeName().equals("int")){ 11 | return Double.valueOf(value).intValue(); 12 | } else if (type.getTypeName().equals(Double.class.getName()) || type.getTypeName().equals("double")){ 13 | return Double.valueOf(value); 14 | } else if (type.getTypeName().equals(Long.class.getName()) || type.getTypeName().equals("long")){ 15 | return Double.valueOf(value).longValue(); 16 | } else if (type.getTypeName().equals(Float.class.getName()) || type.getTypeName().equals("float")){ 17 | return Double.valueOf(value).floatValue(); 18 | } else { 19 | throw new UnsupportedOperationException("Unsupported type in multipart/form-data."); 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/aop/resolvers/UrlDataResolve.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.aop.resolvers; 2 | 3 | import tech.dbgsoftware.easyrest.model.HttpEntity; 4 | 5 | public class UrlDataResolve { 6 | 7 | public static Object[] resolveArgs(HttpEntity httpEntity){ 8 | Object[] args = new Object[httpEntity.getRestObject().getParameterTypeMap().size()]; 9 | final int[] index = {0}; 10 | httpEntity.getRestObject().getParameterTypeMap().forEach((name, type) -> { 11 | try { 12 | if (httpEntity.getRestObject().getUriValues().containsKey(name)){ 13 | args[index[0]] = httpEntity.getRestObject().getUriValues().get(name); 14 | } else { 15 | if (httpEntity.getRequest().getParameterFromURL().get(name) != null) { 16 | args[index[0]] = ParameterTypeResolve.resolveType(type, httpEntity.getRequest().getParameterFromURL().get(name)); 17 | } 18 | } 19 | } catch (NumberFormatException e) { 20 | httpEntity.addError(e); 21 | } 22 | index[0]++; 23 | }); 24 | return args; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/exception/ConditionMissingException.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.exception; 2 | 3 | /** 4 | * Created by liuhongyu.louie on 2016/12/29. 5 | */ 6 | public class ConditionMissingException extends EasyRestException { 7 | 8 | public ConditionMissingException(String errorMsg){ 9 | super(errorMsg); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/exception/EasyRestException.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.exception; 2 | 3 | /** 4 | * Created by liuhongyu.louie on 2017/4/3. 5 | */ 6 | public class EasyRestException extends RuntimeException { 7 | 8 | public EasyRestException(String message) { 9 | super(message); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/exception/ExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.exception; 2 | 3 | /** 4 | * Catch error and exceptions. 5 | * Created by liuhongyu.louie on 2016/9/29. 6 | */ 7 | public class ExceptionHandler extends Exception { 8 | 9 | 10 | } 11 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/exception/MethodNotAllowedException.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.exception; 2 | 3 | /** 4 | * Created by liuhongyu.louie on 2016/12/29. 5 | */ 6 | public class MethodNotAllowedException extends EasyRestException { 7 | 8 | public MethodNotAllowedException(String s) { 9 | super(s); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/exception/PageNotFoundException.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.exception; 2 | 3 | /** 4 | * Page not found exception. 5 | * Created by liuhongyu.louie on 2016/10/1. 6 | */ 7 | public class PageNotFoundException extends EasyRestException { 8 | 9 | public PageNotFoundException(String message) { 10 | super(message); 11 | } 12 | 13 | public static PageNotFoundException getException(String message){ 14 | return new PageNotFoundException(message); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/exception/ParameterNotFoundException.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.exception; 2 | 3 | /** 4 | * Created by liuhongyu.louie on 2016/10/8. 5 | */ 6 | public class ParameterNotFoundException extends EasyRestException { 7 | 8 | public ParameterNotFoundException(String s) { 9 | super(s); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/exception/PermissionException.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.exception; 2 | 3 | /** 4 | * Created by liuhongyu.louie on 2016/10/9. 5 | */ 6 | public class PermissionException extends EasyRestException { 7 | 8 | public PermissionException(String s) { 9 | super(s); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/ioc/remote/EasyRestProxyFactory.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.ioc.remote; 2 | 3 | import tech.dbgsoftware.easyrest.ioc.remote.proxy.ProxyForBeanClassInvoke; 4 | import tech.dbgsoftware.easyrest.ioc.remote.proxy.ProxyForBeanNameInvoke; 5 | 6 | import java.lang.reflect.InvocationHandler; 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | public class EasyRestProxyFactory{ 11 | 12 | private static final InvocationHandler EASY_REST_SIMPLE_PROXY = new ProxyForBeanClassInvoke(); 13 | 14 | private static final Map INVOCATION_HANDLER_CACHE = new ConcurrentHashMap<>(); 15 | 16 | private EasyRestProxyFactory(){} 17 | 18 | static InvocationHandler getSingleProxyInstance(){ 19 | return EASY_REST_SIMPLE_PROXY; 20 | } 21 | 22 | static InvocationHandler getProxyInstanceWithTimeout(long connectionMillis, long resultMillis){ 23 | if (connectionMillis <= 0 || resultMillis <= 0){ 24 | connectionMillis = resultMillis = 0; 25 | } 26 | String key = keyResolver(ProxyForBeanClassInvoke.class.getSimpleName(), String.valueOf(connectionMillis), String.valueOf(resultMillis)); 27 | if (!INVOCATION_HANDLER_CACHE.containsKey(key)){ 28 | INVOCATION_HANDLER_CACHE.putIfAbsent(key, new ProxyForBeanClassInvoke(connectionMillis, resultMillis)); 29 | } 30 | return INVOCATION_HANDLER_CACHE.get(key); 31 | } 32 | 33 | static InvocationHandler getProxyInstanceWithBeanName(String beanName){ 34 | String key = keyResolver(ProxyForBeanNameInvoke.class.getSimpleName(), beanName); 35 | if (!INVOCATION_HANDLER_CACHE.containsKey(key)){ 36 | INVOCATION_HANDLER_CACHE.putIfAbsent(key, new ProxyForBeanNameInvoke(beanName)); 37 | } 38 | return INVOCATION_HANDLER_CACHE.get(key); 39 | } 40 | 41 | static InvocationHandler getProxyInstanceWithBeanNameAndTimeout(String beanName, long connectionMillis, long resultMillis){ 42 | String key = keyResolver(ProxyForBeanNameInvoke.class.getSimpleName(), beanName, String.valueOf(connectionMillis), String.valueOf(resultMillis)); 43 | if (!INVOCATION_HANDLER_CACHE.containsKey(key)){ 44 | INVOCATION_HANDLER_CACHE.putIfAbsent(key, new ProxyForBeanNameInvoke(beanName, connectionMillis, resultMillis)); 45 | } 46 | return INVOCATION_HANDLER_CACHE.get(key); 47 | } 48 | 49 | private static String keyResolver(String... args){ 50 | StringBuilder stringBuilder = new StringBuilder(); 51 | for (String arg: args) { 52 | stringBuilder.append(arg).append("-"); 53 | } 54 | return stringBuilder.toString(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/ioc/remote/EasyRestServiceLookup.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.ioc.remote; 2 | 3 | import tech.dbgsoftware.easyrest.actors.remote.conf.EasyRestDistributedServiceBind; 4 | import tech.dbgsoftware.easyrest.ioc.utils.BeanOperationUtils; 5 | 6 | import java.lang.reflect.Proxy; 7 | 8 | public class EasyRestServiceLookup { 9 | 10 | public static T lookup(Class service){ 11 | if (EasyRestDistributedServiceBind.getLocalService().contains(service.getName())){ 12 | return BeanOperationUtils.getBeansFromInterface(service); 13 | } else { 14 | return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, EasyRestProxyFactory.getSingleProxyInstance()); 15 | } 16 | } 17 | 18 | public static T lookup(Class service, long connectionMillis, long resultMillis){ 19 | if (EasyRestDistributedServiceBind.getLocalService().contains(service.getName())){ 20 | return BeanOperationUtils.getBeansFromInterface(service); 21 | } else { 22 | return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, EasyRestProxyFactory.getProxyInstanceWithTimeout(connectionMillis, resultMillis)); 23 | } 24 | } 25 | 26 | public static T lookup(Class service, String beanName){ 27 | return lookup(service, beanName, 0, 0); 28 | } 29 | 30 | public static T lookup(Class service, String beanName, long connectionMillis, long resultMillis){ 31 | if (EasyRestDistributedServiceBind.getLocalService().contains(service.getName())){ 32 | return BeanOperationUtils.getBeansFromInterface(service, beanName); 33 | } else { 34 | return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, EasyRestProxyFactory.getProxyInstanceWithBeanNameAndTimeout(beanName, connectionMillis, resultMillis)); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/ioc/remote/proxy/ProxyForBeanClassInvoke.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.ioc.remote.proxy; 2 | 3 | import tech.dbgsoftware.easyrest.actors.remote.RemoteRequestUtil; 4 | import tech.dbgsoftware.easyrest.utils.JsonTranslationUtil; 5 | import tech.dbgsoftware.easyrest.utils.LogUtils; 6 | 7 | import java.lang.reflect.InvocationHandler; 8 | import java.lang.reflect.Method; 9 | 10 | public class ProxyForBeanClassInvoke implements InvocationHandler { 11 | 12 | private long connectionMillis; 13 | 14 | private long resultMillis; 15 | 16 | public ProxyForBeanClassInvoke() { 17 | connectionMillis = -1; 18 | resultMillis = -1; 19 | } 20 | 21 | public ProxyForBeanClassInvoke(long connectionMillis, long resultMillis) { 22 | this.connectionMillis = connectionMillis; 23 | this.resultMillis = resultMillis; 24 | } 25 | 26 | @Override 27 | public Object invoke(Object proxy, Method method, Object[] args) { 28 | try { 29 | Object result = RemoteRequestUtil.createRemoteRequest(method, args, connectionMillis, resultMillis); 30 | if (method.getReturnType().getName().equalsIgnoreCase(Void.class.getSimpleName())) { 31 | return null; 32 | } 33 | return JsonTranslationUtil.fromJson(String.valueOf(result), method.getGenericReturnType()); 34 | } catch (Exception e){ 35 | LogUtils.error(String.format("Method %s invoke failed. Cause %s", method.getName(), e.getMessage()), e); 36 | return null; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/ioc/remote/proxy/ProxyForBeanNameInvoke.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.ioc.remote.proxy; 2 | 3 | import tech.dbgsoftware.easyrest.actors.remote.RemoteRequestUtil; 4 | import tech.dbgsoftware.easyrest.utils.JsonTranslationUtil; 5 | import tech.dbgsoftware.easyrest.utils.LogUtils; 6 | 7 | import java.lang.reflect.InvocationHandler; 8 | import java.lang.reflect.Method; 9 | 10 | public class ProxyForBeanNameInvoke implements InvocationHandler { 11 | 12 | private String beanName; 13 | 14 | private long connectionMillis; 15 | 16 | private long resultMillis; 17 | 18 | public ProxyForBeanNameInvoke(String beanName) { 19 | this.beanName = beanName; 20 | connectionMillis = -1; 21 | resultMillis = -1; 22 | } 23 | 24 | public ProxyForBeanNameInvoke(String beanName, long connectionMillis, long resultMillis) { 25 | this.beanName = beanName; 26 | this.connectionMillis = connectionMillis; 27 | this.resultMillis = resultMillis; 28 | } 29 | 30 | @Override 31 | public Object invoke(Object proxy, Method method, Object[] args) { 32 | try { 33 | Object result = RemoteRequestUtil.createRemoteRequest(method, args, beanName, connectionMillis, resultMillis); 34 | if (method.getReturnType().getName().equalsIgnoreCase(Void.class.getSimpleName())) { 35 | return null; 36 | } 37 | return JsonTranslationUtil.fromJson(String.valueOf(result), method.getGenericReturnType()); 38 | } catch (Exception e){ 39 | LogUtils.error(String.format("Method %s invoke failed. Cause %s", method.getName(), e.getMessage()), e); 40 | return null; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/ioc/utils/BeanOperationUtils.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.ioc.utils; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.BeanDefinition; 5 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 6 | import org.springframework.beans.factory.support.GenericBeanDefinition; 7 | import org.springframework.context.ApplicationContext; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by liuhongyu.louie on 2017/4/3. 14 | */ 15 | public class BeanOperationUtils { 16 | 17 | private static BeanDefinition bean; 18 | 19 | private static DefaultListableBeanFactory defaultListableBeanFactory; 20 | 21 | public static T registerBean(String beanName, Class aClass) { 22 | bean.setBeanClassName(aClass.getName()); 23 | defaultListableBeanFactory.registerBeanDefinition(beanName, bean); 24 | return getBean(beanName, aClass); 25 | } 26 | 27 | public static T getBean(String beanName, Class beanClass) { 28 | try { 29 | return defaultListableBeanFactory.getBean(beanName, beanClass); 30 | } catch (Exception e) { 31 | return null; 32 | } 33 | } 34 | 35 | public static List getAllBeansClass(){ 36 | List beans = new ArrayList<>(); 37 | for (String name: defaultListableBeanFactory.getBeanDefinitionNames()){ 38 | beans.add(defaultListableBeanFactory.getBean(name).getClass()); 39 | } 40 | return beans; 41 | } 42 | 43 | public static T getBeansFromInterface(Class _interface){ 44 | return getBeansFromInterface(_interface, null); 45 | } 46 | 47 | public static T getBeansFromInterface(Class _interface, String name){ 48 | try { 49 | if (name == null){ 50 | final List firstBean = new ArrayList<>(); 51 | defaultListableBeanFactory.getBeansOfType(_interface).forEach((beanName, bean) -> { 52 | if (firstBean.size() == 0) { 53 | firstBean.add(bean); 54 | } 55 | }); 56 | if (firstBean.size() > 0){ 57 | return firstBean.get(0); 58 | } else { 59 | return null; 60 | } 61 | } else { 62 | return defaultListableBeanFactory.getBeansOfType(_interface).get(name); 63 | } 64 | } catch (Exception e){ 65 | return null; 66 | } 67 | } 68 | 69 | public static T getBean(Class beanClass) { 70 | try { 71 | return defaultListableBeanFactory.getBean(beanClass); 72 | } catch (Exception e) { 73 | return null; 74 | } 75 | } 76 | 77 | public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 78 | bean = new GenericBeanDefinition(); 79 | defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/ioc/utils/StaticClassUtils.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.ioc.utils; 2 | 3 | import org.springframework.core.ParameterNameDiscoverer; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class StaticClassUtils { 8 | 9 | private static ParameterNameDiscoverer parameterNameDiscoverer; 10 | 11 | public void setParameterNameDiscoverer(ParameterNameDiscoverer _parameterNameDiscoverer){ 12 | parameterNameDiscoverer = _parameterNameDiscoverer; 13 | } 14 | 15 | public static ParameterNameDiscoverer getParameterNameDiscoverer() { 16 | return parameterNameDiscoverer; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/model/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.model; 2 | 3 | import java.util.Map; 4 | 5 | public class ErrorResponse { 6 | 7 | private String errorType; 8 | 9 | private String errorMessage; 10 | 11 | public ErrorResponse(String errorMessage, String errorType) { 12 | this.errorMessage = errorMessage; 13 | this.errorType = errorType; 14 | } 15 | 16 | public ErrorResponse(Map errorMap) { 17 | errorMap.forEach((k, v) -> { 18 | this.errorMessage = k; 19 | this.errorType = v; 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/model/HttpEntity.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.model; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import tech.dbgsoftware.easyrest.model.request.Request; 5 | import tech.dbgsoftware.easyrest.model.request.RestObject; 6 | 7 | import java.lang.reflect.Method; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public class HttpEntity { 12 | 13 | private Method method; 14 | private Request request; 15 | private Response response; 16 | private Class controller; 17 | private Boolean isOptionsCheck = false; 18 | private ChannelHandlerContext channelHandlerContext; 19 | private ResponseEntity responseEntity; 20 | private RestObject restObject; 21 | private Map errorMap = new HashMap<>(); 22 | private Object[] args = new Object[0]; 23 | 24 | public HttpEntity(Request request, Response response, ChannelHandlerContext channelHandlerContext) { 25 | this.request = request; 26 | this.response = response; 27 | this.channelHandlerContext = channelHandlerContext; 28 | } 29 | 30 | public Boolean isOptionsCheck() { 31 | return isOptionsCheck; 32 | } 33 | 34 | public void setOptionsCheck(Boolean optionsCheck) { 35 | isOptionsCheck = optionsCheck; 36 | } 37 | 38 | public void setMethod(Method method) { 39 | this.method = method; 40 | } 41 | 42 | public Method getMethod() { 43 | return method; 44 | } 45 | 46 | public Request getRequest() { 47 | return request; 48 | } 49 | 50 | public Response getResponse() { 51 | return response; 52 | } 53 | 54 | public ResponseEntity getResponseEntity() { 55 | return responseEntity; 56 | } 57 | 58 | public void setResponseEntity(ResponseEntity responseEntity) { 59 | this.responseEntity = responseEntity; 60 | } 61 | 62 | public ChannelHandlerContext getChannelHandlerContext() { 63 | return channelHandlerContext; 64 | } 65 | 66 | public Class getController() { 67 | return controller; 68 | } 69 | 70 | public void setController(Class controller) { 71 | this.controller = controller; 72 | } 73 | 74 | public Object[] getArgs() { 75 | return args; 76 | } 77 | 78 | public void setArgs(Object[] args) { 79 | this.args = args; 80 | } 81 | 82 | public void addError(Exception e){ 83 | errorMap.put(e.getMessage(), e.getClass().getSimpleName()); 84 | } 85 | 86 | public void addError(Throwable e){ 87 | errorMap.put(e.getMessage(), e.getClass().getSimpleName()); 88 | } 89 | 90 | public RestObject getRestObject() { 91 | return restObject; 92 | } 93 | 94 | public void setRestObject(RestObject restObject) { 95 | this.restObject = restObject; 96 | } 97 | 98 | public Map getErrorMap() { 99 | return errorMap; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/model/Response.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.model; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import io.netty.buffer.Unpooled; 6 | import io.netty.handler.codec.http.DefaultFullHttpResponse; 7 | import io.netty.handler.codec.http.FullHttpResponse; 8 | import io.netty.handler.codec.http.HttpHeaderValues; 9 | import io.netty.handler.codec.http.HttpResponseStatus; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | import static io.netty.handler.codec.http.HttpHeaderNames.*; 15 | import static io.netty.handler.codec.http.HttpResponseStatus.OK; 16 | import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; 17 | 18 | public class Response { 19 | 20 | private final static Gson GSON = new GsonBuilder().serializeSpecialFloatingPointValues().create(); 21 | private FullHttpResponse response; 22 | private HttpResponseStatus status = HttpResponseStatus.OK; 23 | private Map responseHeaders = new HashMap<>(); 24 | 25 | public Response(){ 26 | this.response = newResponse(ResponseEntity.buildOkResponse()); 27 | this.response.setStatus(status); 28 | } 29 | 30 | public Map getResponseHeaders() { 31 | return responseHeaders; 32 | } 33 | 34 | public Response buildResponse(Object responseEntity){ 35 | this.response = newResponse(responseEntity); 36 | this.response.setStatus(status); 37 | return this; 38 | } 39 | 40 | public Response buildStringResponse(String responseString){ 41 | this.response = newStringResponse(responseString); 42 | this.response.setStatus(status); 43 | return this; 44 | } 45 | 46 | public void setStatus(HttpResponseStatus status) { 47 | this.status = status; 48 | } 49 | 50 | public FullHttpResponse getRealResponse() { 51 | return response; 52 | } 53 | 54 | private FullHttpResponse newResponse(Object responseEntity){ 55 | FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(GSON.toJson(responseEntity).getBytes())); 56 | response.headers().set(CONTENT_TYPE, "application/json"); 57 | response.headers().set(CONTENT_LENGTH, response.content().readableBytes()); 58 | response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE); 59 | responseHeaders.forEach((k, v) -> response.headers().set(k, v)); 60 | return response; 61 | } 62 | 63 | private FullHttpResponse newStringResponse(String responseString){ 64 | FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(responseString.getBytes())); 65 | response.headers().set(CONTENT_TYPE, "text/plain"); 66 | response.headers().set(CONTENT_LENGTH, response.content().readableBytes()); 67 | response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE); 68 | responseHeaders.forEach((k, v) -> response.headers().set(k, v)); 69 | return response; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/model/ResponseEntity.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by Louie on 2016/10/2. 7 | */ 8 | public class ResponseEntity implements Serializable { 9 | private String code = "1"; 10 | private String message; 11 | private T data; 12 | 13 | public String getCode() { 14 | return code; 15 | } 16 | 17 | private void setCode(String code) { 18 | this.code = code; 19 | } 20 | 21 | public String getMessage() { 22 | return message; 23 | } 24 | 25 | private void setMessage(String message) { 26 | this.message = message; 27 | } 28 | 29 | public T getData() { 30 | return data; 31 | } 32 | 33 | private ResponseEntity setFailed(){ 34 | setFailed("Failed"); 35 | return this; 36 | } 37 | 38 | private ResponseEntity setFailed(String message){ 39 | setFailed("-1", message); 40 | return this; 41 | } 42 | 43 | private void setFailed(String code, String message){ 44 | setCode(code); 45 | setMessage(message); 46 | } 47 | 48 | private void setSuccess(){ 49 | setSuccess("Success"); 50 | } 51 | 52 | private void setSuccess(String message){ 53 | setSuccess("1", message); 54 | } 55 | 56 | private void setSuccess(String code, String message){ 57 | setCode(code); 58 | setMessage(message); 59 | } 60 | 61 | private void setData(T data) { 62 | this.data = data; 63 | } 64 | 65 | public static ResponseEntity buildOkResponse(){ 66 | ResponseEntity responseEntity = new ResponseEntity<>(); 67 | responseEntity.setMessage("ok"); 68 | return responseEntity; 69 | } 70 | 71 | public static ResponseEntity buildOkResponse(T t){ 72 | ResponseEntity responseEntity = new ResponseEntity<>(); 73 | responseEntity.setData(t); 74 | return responseEntity; 75 | } 76 | 77 | public static ResponseEntity buildFailedResponse(){ 78 | ResponseEntity responseEntity = new ResponseEntity<>(); 79 | responseEntity.setData(false); 80 | responseEntity.setFailed(); 81 | return responseEntity; 82 | } 83 | 84 | public static ResponseEntity buildFailedResponse(T t){ 85 | ResponseEntity responseEntity = new ResponseEntity<>(); 86 | responseEntity.setData(t); 87 | responseEntity.setFailed(); 88 | return responseEntity; 89 | } 90 | 91 | public static ResponseEntity buildCustomizeResponse(int code, String message, T t){ 92 | ResponseEntity responseEntity = new ResponseEntity<>(); 93 | responseEntity.setData(t); 94 | responseEntity.setCode(String.valueOf(code)); 95 | responseEntity.setMessage(message); 96 | return responseEntity; 97 | } 98 | 99 | public static ResponseEntity buildBaseResponse(T t){ 100 | ResponseEntity responseEntity = new ResponseEntity<>(); 101 | responseEntity.setData(t); 102 | responseEntity.setCode(null); 103 | responseEntity.setMessage(null); 104 | return responseEntity; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/model/request/AbstractRequestModel.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.model.request; 2 | 3 | 4 | import tech.dbgsoftware.easyrest.annotations.parameter.AllDefined; 5 | import tech.dbgsoftware.easyrest.annotations.parameter.NotNull; 6 | import tech.dbgsoftware.easyrest.annotations.parameter.Optional; 7 | import tech.dbgsoftware.easyrest.exception.ConditionMissingException; 8 | import tech.dbgsoftware.easyrest.model.HttpEntity; 9 | import tech.dbgsoftware.easyrest.utils.StringUtils; 10 | 11 | import java.lang.reflect.Field; 12 | 13 | /** 14 | * Created by liuhongyu.louie on 2016/9/30. 15 | */ 16 | public abstract class AbstractRequestModel implements RequestModel { 17 | 18 | @Override 19 | public boolean notNullFieldCheck(){ 20 | try { 21 | for (Field field : this.getClass().getDeclaredFields()){ 22 | field.setAccessible(true); 23 | if (field.isAnnotationPresent(NotNull.class) && (field.get(this) == null || StringUtils.isEmptyString((String) field.get(this)))) { 24 | return false; 25 | } 26 | } 27 | } catch (IllegalAccessException ignored){} 28 | return true; 29 | } 30 | 31 | @Override 32 | public boolean isAllFieldDefined() { 33 | try { 34 | for (Field field : this.getClass().getDeclaredFields()){ 35 | field.setAccessible(true); 36 | if (field.get(this) == null || (field.getType().equals(String.class) && StringUtils.isEmptyString((String)field.get(this)))) { 37 | if (!field.isAnnotationPresent(Optional.class)) { 38 | return false; 39 | } 40 | } 41 | } 42 | } catch (IllegalAccessException ignored){} 43 | return true; 44 | } 45 | 46 | @Override 47 | public String getNotDefinedFields(Class aClass){ 48 | StringBuilder stringBuilder = new StringBuilder(); 49 | try { 50 | for (Field field : this.getClass().getDeclaredFields()){ 51 | field.setAccessible(true); 52 | if (aClass.equals(NotNull.class)){ 53 | if (field.get(this) == null || (field.getType().equals(String.class) && StringUtils.isEmptyString((String)field.get(this)))) { 54 | stringBuilder.append(field.getName()).append(",").append(" "); 55 | } 56 | } else if (aClass.equals(AllDefined.class)) { 57 | if (field.get(this) == null || (field.getType().equals(String.class) && StringUtils.isEmptyString((String)field.get(this)))) { 58 | stringBuilder.append(field.getName()).append(",").append(" "); 59 | } 60 | } 61 | } 62 | } catch (IllegalAccessException ignored){} 63 | return stringBuilder.toString(); 64 | } 65 | 66 | @Override 67 | public String getFieldValue(String fieldName) { 68 | try { 69 | Field field = this.getClass().getDeclaredField(fieldName); 70 | field.setAccessible(true); 71 | return String.valueOf(field.get(this)); 72 | } catch (NoSuchFieldException | IllegalAccessException e) { 73 | return null; 74 | } 75 | } 76 | 77 | @Override 78 | public void customizedCheck(HttpEntity httpEntity) throws ConditionMissingException {} 79 | 80 | } 81 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/model/request/Request.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.model.request; 2 | 3 | import io.netty.handler.codec.http.FullHttpRequest; 4 | import io.netty.handler.codec.http.multipart.Attribute; 5 | import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder; 6 | import tech.dbgsoftware.easyrest.network.core.pipeline.utils.ByteBufUtils; 7 | import tech.dbgsoftware.easyrest.network.router.UrlFormat; 8 | import tech.dbgsoftware.easyrest.utils.LogUtils; 9 | 10 | import java.io.IOException; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | public class Request { 15 | 16 | private String requestHttpMethod; 17 | 18 | private String requestUri; 19 | 20 | private Map headers = new HashMap<>(); 21 | 22 | private byte[] originByte; 23 | 24 | private String jsonData; 25 | 26 | private boolean isMultipart = false; 27 | 28 | private Map formData = new HashMap<>(); 29 | 30 | private Map parameterFromURL = new HashMap<>(); 31 | 32 | public Request(FullHttpRequest fullHttpRequest) { 33 | try { 34 | requestHttpMethod = fullHttpRequest.method().name(); 35 | requestUri = UrlFormat.getUrl(fullHttpRequest.uri(), parameterFromURL); 36 | fullHttpRequest.headers().forEach((header) -> headers.putIfAbsent(header.getKey(), header.getValue())); 37 | HttpPostRequestDecoder postRequestDecoder = new HttpPostRequestDecoder(fullHttpRequest); 38 | originByte = ByteBufUtils.readAll(fullHttpRequest.content()); 39 | jsonData = new String(originByte, 0, originByte.length); 40 | if (postRequestDecoder.isMultipart()) { 41 | postRequestDecoder.getBodyHttpDatas().forEach((interfaceHttpData -> { 42 | isMultipart = true; 43 | Attribute attribute = (Attribute) interfaceHttpData; 44 | try { 45 | String key = interfaceHttpData.getName(); 46 | String value = attribute.getValue(); 47 | formData.put(key, value); 48 | } catch (IOException e) { 49 | LogUtils.error(e.getMessage(), e); 50 | } 51 | })); 52 | } 53 | } catch (Exception e) { 54 | LogUtils.error("Ref count = " + fullHttpRequest.refCnt() + " " + e.getMessage()); 55 | } finally { 56 | fullHttpRequest.release(); 57 | } 58 | } 59 | 60 | public byte[] getOriginByte() { 61 | return originByte; 62 | } 63 | 64 | public String getJsonData() { 65 | return jsonData; 66 | } 67 | 68 | public String getRequestHttpMethod() { 69 | return requestHttpMethod; 70 | } 71 | 72 | public Map getParameterFromURL() { 73 | return parameterFromURL; 74 | } 75 | 76 | public String getRequestUri() { 77 | return requestUri; 78 | } 79 | 80 | public Map getHeaders() { 81 | return headers; 82 | } 83 | 84 | public Map getFormData() { 85 | return formData; 86 | } 87 | 88 | public boolean isMultipart() { 89 | return isMultipart; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/model/request/RequestModel.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.model.request; 2 | 3 | 4 | import tech.dbgsoftware.easyrest.exception.ConditionMissingException; 5 | import tech.dbgsoftware.easyrest.model.HttpEntity; 6 | 7 | /** 8 | * Created by liuhongyu.louie on 2016/12/27. 9 | */ 10 | public interface RequestModel { 11 | 12 | boolean notNullFieldCheck(); 13 | 14 | boolean isAllFieldDefined(); 15 | 16 | String getNotDefinedFields(Class aClass); 17 | 18 | void customizedCheck(HttpEntity httpEntity) throws ConditionMissingException; 19 | 20 | String getFieldValue(String fieldName); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/model/request/RestObject.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.model.request; 2 | 3 | import io.netty.handler.codec.http.HttpMethod; 4 | import javassist.*; 5 | import javassist.bytecode.CodeAttribute; 6 | import javassist.bytecode.LocalVariableAttribute; 7 | import javassist.bytecode.MethodInfo; 8 | 9 | import java.lang.reflect.Method; 10 | import java.lang.reflect.Type; 11 | import java.util.*; 12 | 13 | public class RestObject { 14 | 15 | private Method method; 16 | 17 | private List httpMethodList = new ArrayList<>(); 18 | 19 | private Class controller; 20 | 21 | private Map parameterTypeMap = new LinkedHashMap<>(); 22 | 23 | private Map UriValues = new HashMap<>(); 24 | 25 | private String originalPath; 26 | 27 | public RestObject(Method method, HttpMethod httpMethodName, Class controller) { 28 | this.method = method; 29 | this.httpMethodList.add(httpMethodName.name().toLowerCase()); 30 | this.controller = controller; 31 | analysisMethod(); 32 | } 33 | 34 | public void addHttpMethod(HttpMethod httpMethod){ 35 | if (!httpMethodList.contains(httpMethod.name().toLowerCase())){ 36 | httpMethodList.add(httpMethod.name().toLowerCase()); 37 | } 38 | } 39 | 40 | public void putToUriValueMap(String name, String value){ 41 | UriValues.put(name, value); 42 | } 43 | 44 | public String getOriginalPath() { 45 | return originalPath; 46 | } 47 | 48 | public void setOriginalPath(String originalPath) { 49 | this.originalPath = originalPath; 50 | } 51 | 52 | public Map getUriValues() { 53 | return UriValues; 54 | } 55 | 56 | public Method getMethod() { 57 | return method; 58 | } 59 | 60 | public List getHttpMethodList() { 61 | return httpMethodList; 62 | } 63 | 64 | public Class getController() { 65 | return controller; 66 | } 67 | 68 | public Map getParameterTypeMap() { 69 | return parameterTypeMap; 70 | } 71 | 72 | @Override 73 | public int hashCode() { 74 | return method.hashCode() + controller.hashCode(); 75 | } 76 | 77 | private void analysisMethod(){ 78 | try { 79 | ClassPool pool = ClassPool.getDefault(); 80 | pool.insertClassPath(new ClassClassPath(controller)); 81 | CtClass cc = pool.get(controller.getName()); 82 | CtClass[] ctClasses = new CtClass[method.getParameterCount()]; 83 | int index = 0; 84 | for (Class aClass : method.getParameterTypes()) { 85 | ClassPool poolPara = ClassPool.getDefault(); 86 | poolPara.insertClassPath(new ClassClassPath(aClass)); 87 | ctClasses[index++] = poolPara.get(aClass.getName()); 88 | } 89 | CtMethod cm = ctClasses.length == 0 ? cc.getDeclaredMethod(method.getName()) : cc.getDeclaredMethod(method.getName(), ctClasses); 90 | MethodInfo methodInfo = cm.getMethodInfo(); 91 | CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); 92 | LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); 93 | boolean afterThis = false; 94 | List paraName = new ArrayList<>(method.getParameters().length); 95 | for (int i = 0; i < attr.tableLength(); i++) { 96 | String name = attr.variableName(i); 97 | if (!afterThis && name.equalsIgnoreCase("this")){ 98 | afterThis = true; 99 | continue; 100 | } 101 | if (afterThis && paraName.size() < method.getParameters().length) { 102 | paraName.add(name); 103 | } 104 | } 105 | for (int i = 0; i < method.getParameters().length; i++) { 106 | Type type = method.getParameters()[i].getParameterizedType(); 107 | parameterTypeMap.put(paraName.get(i), type); 108 | } 109 | } catch (Exception e){ 110 | e.printStackTrace(); 111 | System.exit(-1); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/NettyInit.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.epoll.Epoll; 6 | import io.netty.channel.epoll.EpollEventLoopGroup; 7 | import io.netty.channel.epoll.EpollServerSocketChannel; 8 | import io.netty.channel.nio.NioEventLoopGroup; 9 | import io.netty.channel.socket.SocketChannel; 10 | import io.netty.channel.socket.nio.NioServerSocketChannel; 11 | import io.netty.handler.codec.http.HttpContentDecompressor; 12 | import io.netty.handler.codec.http.HttpObjectAggregator; 13 | import io.netty.handler.codec.http.HttpRequestDecoder; 14 | import io.netty.handler.codec.http.HttpResponseEncoder; 15 | import io.netty.handler.ssl.SslHandler; 16 | import io.netty.handler.stream.ChunkedWriteHandler; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | import tech.dbgsoftware.easyrest.network.conf.ChannelOptionBuilder; 20 | import tech.dbgsoftware.easyrest.network.core.api.BaseConfiguration; 21 | import tech.dbgsoftware.easyrest.network.core.pipeline.in.RequestProcessHandler; 22 | 23 | import javax.net.ssl.SSLContext; 24 | import javax.net.ssl.SSLEngine; 25 | import java.lang.annotation.Annotation; 26 | import java.util.*; 27 | import java.util.function.Function; 28 | 29 | public class NettyInit implements BaseConfiguration { 30 | 31 | private int port = 8080; 32 | private String host = "*"; 33 | private int ioExecutors = Runtime.getRuntime().availableProcessors() * 2; 34 | public static String SystemName = "EasyRest"; 35 | private int maxContentLength = 20480; 36 | private EventLoopGroup bossEventLoopGroup; 37 | private EventLoopGroup workerEventLoopGroup; 38 | private SSLContext sslContext; 39 | private CustomizeChannel customizeChannel = new CustomizeChannel(); 40 | private ChannelOptionBuilder channelOptionBuilder = new ChannelOptionBuilder().buildWithDefaultOptions(); 41 | private Map properties = new HashMap<>(); 42 | private List AccessControlAllowHeaders = new ArrayList<>(); 43 | private ChannelFuture channelFuture; 44 | private static final Logger LOGGER = LoggerFactory.getLogger(NettyInit.class); 45 | 46 | public NettyInit(){} 47 | 48 | public NettyInit(int port){ 49 | this("*", port); 50 | } 51 | 52 | public NettyInit(String host, int port) { 53 | setPort(port); 54 | setHost(host); 55 | } 56 | 57 | public ServerBootstrap build(){ 58 | return build(SystemName); 59 | } 60 | 61 | public ServerBootstrap build(String _systemName){ 62 | SystemName = _systemName; 63 | if (Epoll.isAvailable()){ 64 | bossEventLoopGroup = new EpollEventLoopGroup((ioExecutors / 2) + 1); 65 | workerEventLoopGroup = new EpollEventLoopGroup(ioExecutors); 66 | } else { 67 | bossEventLoopGroup = new NioEventLoopGroup((ioExecutors / 2) + 1); 68 | workerEventLoopGroup = new NioEventLoopGroup(ioExecutors); 69 | } 70 | AccessControlAllowHeaders.addAll(Arrays.asList("DNT","X-Mx-ReqToken","Keep-Alive","User-Agent","X-Requested-With","If-Modified-Since","Cache-Control","Content-Type","Authorization")); 71 | return initServerBootstrap(); 72 | } 73 | 74 | private ServerBootstrap initServerBootstrap() { 75 | ServerBootstrap bootstrap = new ServerBootstrap().group(bossEventLoopGroup, workerEventLoopGroup).channel(Epoll.isAvailable() ? EpollServerSocketChannel.class : NioServerSocketChannel.class); 76 | addCustomizeHandle(new RequestProcessHandler(this)); 77 | customizeChannel.setChannelHandlerToServerBootstrap(bootstrap); 78 | channelOptionBuilder.build(bootstrap); 79 | return bootstrap; 80 | } 81 | 82 | public NettyInit setPort(int port){ 83 | if (port > 0 && port <= 65535){ 84 | this.port = port; 85 | } 86 | return this; 87 | } 88 | 89 | @Override 90 | public String getHost() { 91 | return host; 92 | } 93 | 94 | public void setHost(String host) { 95 | this.host = host; 96 | } 97 | 98 | public NettyInit setIoExecutors(int ioExecutors){ 99 | if (ioExecutors < 1) { 100 | this.ioExecutors = Runtime.getRuntime().availableProcessors() * 2 + 1; 101 | } else { 102 | this.ioExecutors = ioExecutors; 103 | } 104 | return this; 105 | } 106 | 107 | public NettyInit setChannelOption(ChannelOptionBuilder channelOption){ 108 | if (channelOption != null){ 109 | this.channelOptionBuilder = channelOption; 110 | } 111 | return this; 112 | } 113 | 114 | public NettyInit setSslContext(SSLContext sslContext){ 115 | this.sslContext = sslContext; 116 | customizeChannel.setInnerSslContext(sslContext); 117 | return this; 118 | } 119 | 120 | public NettyInit setMaxContentLength(int maxContentLength) { 121 | if (maxContentLength < 0) { 122 | maxContentLength = this.maxContentLength; 123 | } 124 | this.maxContentLength = maxContentLength; 125 | customizeChannel.setMaxContentLength(this.maxContentLength); 126 | return this; 127 | } 128 | 129 | public NettyInit addConfigurations(String key, Object value){ 130 | properties.put(key, value); 131 | return this; 132 | } 133 | 134 | public NettyInit addCustomizeHandle(ChannelHandler handler){ 135 | return addCustomizeHandle(handler.getClass().getSimpleName(), handler); 136 | } 137 | 138 | public NettyInit addCustomizeHandle(String name, ChannelHandler handler){ 139 | LinkedHashMap channelHandlerLinkedHashMap = new LinkedHashMap<>(); 140 | channelHandlerLinkedHashMap.put(name, handler); 141 | return addCustomizeHandle(channelHandlerLinkedHashMap); 142 | } 143 | 144 | public NettyInit addCustomizeHandle(LinkedHashMap userHandlers){ 145 | customizeChannel.addUserHandlers(userHandlers); 146 | return this; 147 | } 148 | 149 | protected ChannelFuture bindChannelFuture(ChannelFuture channelFuture){ 150 | this.channelFuture = channelFuture; 151 | return channelFuture; 152 | } 153 | 154 | @Override 155 | public Map getProperties() { 156 | return properties; 157 | } 158 | 159 | @Override 160 | public List getAccessControlAllowHeaders() { 161 | return AccessControlAllowHeaders; 162 | } 163 | 164 | public int getPort() { 165 | return port; 166 | } 167 | 168 | public int getIoExecutors() { 169 | return ioExecutors; 170 | } 171 | 172 | public String getSystemName() { 173 | return SystemName; 174 | } 175 | 176 | public int getMaxContentLength() { 177 | return maxContentLength; 178 | } 179 | 180 | private class CustomizeChannel extends ChannelInitializer { 181 | 182 | private Map userHandlers = new LinkedHashMap<>(); 183 | private Map isSharableMapping = new HashMap<>(); 184 | private Integer maxContentLength = 20480; 185 | private SSLContext innerSslContext; 186 | void addUserHandlers(LinkedHashMap userHandlers) { 187 | if (userHandlers != null) { 188 | this.userHandlers.putAll(userHandlers); 189 | } 190 | } 191 | 192 | void setInnerSslContext(SSLContext innerSslContext) { 193 | this.innerSslContext = innerSslContext; 194 | } 195 | 196 | void setMaxContentLength(Integer maxContentLength) { 197 | this.maxContentLength = maxContentLength; 198 | } 199 | 200 | void setChannelHandlerToServerBootstrap(ServerBootstrap serverBootstrap){ 201 | serverBootstrap.childHandler(this); 202 | } 203 | 204 | @Override 205 | protected void initChannel(SocketChannel socketChannel) throws Exception { 206 | ChannelPipeline pipeline = socketChannel.pipeline(); 207 | if (innerSslContext != null){ 208 | SSLEngine sslEngine = sslContext.createSSLEngine(); 209 | sslEngine.setUseClientMode(false); 210 | SslHandler sslHandler = new SslHandler(sslEngine); 211 | pipeline.addLast("ssl", sslHandler); 212 | } 213 | 214 | // Inbound handlers 215 | pipeline.addLast("decoder", new HttpRequestDecoder()); 216 | pipeline.addLast("inflater", new HttpContentDecompressor()); 217 | pipeline.addLast("aggregator", new HttpObjectAggregator(maxContentLength)); 218 | 219 | // Outbound handlers 220 | pipeline.addLast("encoder", new HttpResponseEncoder()); 221 | pipeline.addLast("chunkWriter", new ChunkedWriteHandler()); 222 | 223 | //register customize handlers 224 | registerUserHandlers(pipeline); 225 | } 226 | 227 | private void checkUserHandlers(){ 228 | isSharableMapping.clear(); 229 | userHandlers.forEach((name, handler) -> { 230 | isSharableMapping.put(name, false); 231 | Annotation[] annotations = handler.getClass().getAnnotations(); 232 | for (Annotation annotation : annotations){ 233 | if (annotation.annotationType().equals(Sharable.class)){ 234 | isSharableMapping.put(name, true); 235 | break; 236 | } 237 | } 238 | }); 239 | } 240 | 241 | private void registerUserHandlers(ChannelPipeline pipeline){ 242 | checkUserHandlers(); 243 | userHandlers.forEach((name, handler) -> { 244 | Function, ChannelHandler> handlerPredicate = newHandler -> { 245 | try { 246 | if (newHandler != null && handler != null && newHandler.containsKey(name) && !newHandler.get(name)) { 247 | return handler.getClass().newInstance(); 248 | } 249 | } catch (Exception e) { 250 | LOGGER.error(e.getMessage(), e); 251 | } 252 | return handler; 253 | }; 254 | ChannelHandler channelHandler = handlerPredicate.apply(isSharableMapping); 255 | if (channelHandler != null) { 256 | pipeline.addLast(workerEventLoopGroup, channelHandler); 257 | } 258 | }); 259 | } 260 | } 261 | 262 | } 263 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/NettyLaunch.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network; 2 | 3 | import akka.actor.AbstractActor; 4 | import io.netty.bootstrap.ServerBootstrap; 5 | import tech.dbgsoftware.easyrest.EasyRest; 6 | import tech.dbgsoftware.easyrest.actors.remote.RemoteServiceExchangeActor; 7 | import tech.dbgsoftware.easyrest.actors.remote.conf.EasyRestDistributedServiceBind; 8 | import tech.dbgsoftware.easyrest.network.exception.ConfigurationException; 9 | import tech.dbgsoftware.easyrest.utils.LogUtils; 10 | 11 | public class NettyLaunch extends AbstractActor { 12 | 13 | @Override 14 | public Receive createReceive() { 15 | return receiveBuilder().match(EasyRest.class, (easyRest) -> { 16 | try { 17 | if (easyRest.getNettyInit() == null) { 18 | throw new ConfigurationException(String.format("%s can not be null.", NettyInit.class.getName())); 19 | } 20 | EasyRestDistributedServiceBind.setInitFinished(true); 21 | if (EasyRestDistributedServiceBind.isIsNeedDistributed()) { 22 | RemoteServiceExchangeActor.initServiceMap(); 23 | } 24 | ServerBootstrap bootstrap = easyRest.getNettyInit().build(easyRest.getSystemName()); 25 | easyRest.getNettyInit().bindChannelFuture(bootstrap.bind(easyRest.getNettyInit().getPort())); 26 | LogUtils.info(String.format("%s is running on the port %s.", easyRest.getSystemName(), easyRest.getNettyInit().getPort())); 27 | easyRest.getEasyRestCallback().onStartSuccess(); 28 | } catch (Exception e) { 29 | LogUtils.error(e.getMessage(), e); 30 | easyRest.getEasyRestCallback().onStartFailed(); 31 | } 32 | }).build(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/conf/ChannelOptionBuilder.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network.conf; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.buffer.ByteBufAllocator; 5 | import io.netty.buffer.PooledByteBufAllocator; 6 | import io.netty.channel.ChannelOption; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | 12 | /** 13 | * The connect option setting. 14 | * Created by liuhongyu.louie on 2016/9/17. 15 | */ 16 | public class ChannelOptionBuilder { 17 | 18 | private boolean tcpNoDelay= true; 19 | private boolean soKeepAlive = true; 20 | private boolean soReuseAddr = true; 21 | private int soBackLog = 1024; 22 | private int soLinger = -1; //Default closed 23 | private int soRcvBuf = 262140; //Java Default 24 | private int connectTimeOutMillis = 10000; // Netty default 25 | private ByteBufAllocator allocator = new PooledByteBufAllocator(true); 26 | private Map options = new HashMap<>(); 27 | private Map childOptions = new HashMap<>(); 28 | 29 | public ChannelOptionBuilder addOption(ChannelOption option, T value, OptionType type){ 30 | switch (type){ 31 | case Parent:options.put(option, value); 32 | break; 33 | case Child:childOptions.put(option, value); 34 | break; 35 | default: 36 | options.put(option, value); 37 | childOptions.put(option, value); 38 | } 39 | return this; 40 | } 41 | 42 | public ChannelOptionBuilder buildWithDefaultOptions(){ 43 | options.put(ChannelOption.SO_BACKLOG, soBackLog); 44 | options.put(ChannelOption.SO_REUSEADDR, soReuseAddr); 45 | options.put(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeOutMillis); 46 | 47 | //For child 48 | childOptions.put(ChannelOption.SO_KEEPALIVE, soKeepAlive); 49 | childOptions.put(ChannelOption.SO_LINGER, soLinger); 50 | childOptions.put(ChannelOption.TCP_NODELAY, tcpNoDelay); 51 | childOptions.put(ChannelOption.ALLOCATOR, allocator); 52 | childOptions.put(ChannelOption.SO_RCVBUF, soRcvBuf); 53 | childOptions.put(ChannelOption.SO_REUSEADDR, soReuseAddr); 54 | return this; 55 | } 56 | 57 | public void build(ServerBootstrap serverBootstrap){ 58 | options.forEach(serverBootstrap::option); 59 | childOptions.forEach(serverBootstrap::childOption); 60 | } 61 | 62 | public enum OptionType{ 63 | Parent, 64 | Child, 65 | Both 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/core/api/BaseConfiguration.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network.core.api; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | public interface BaseConfiguration { 7 | 8 | int getPort(); 9 | 10 | String getHost(); 11 | 12 | int getIoExecutors(); 13 | 14 | String getSystemName(); 15 | 16 | int getMaxContentLength(); 17 | 18 | Map getProperties(); 19 | 20 | List getAccessControlAllowHeaders(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/core/pipeline/in/RequestProcessHandler.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network.core.pipeline.in; 2 | 3 | import akka.actor.ActorRef; 4 | import io.netty.channel.ChannelHandler; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.ChannelInboundHandlerAdapter; 7 | import io.netty.handler.codec.http.FullHttpRequest; 8 | import tech.dbgsoftware.easyrest.actors.ActorFactory; 9 | import tech.dbgsoftware.easyrest.actors.request.RequestProcessActor; 10 | import tech.dbgsoftware.easyrest.model.HttpEntity; 11 | import tech.dbgsoftware.easyrest.model.Response; 12 | import tech.dbgsoftware.easyrest.model.request.Request; 13 | import tech.dbgsoftware.easyrest.network.core.api.BaseConfiguration; 14 | 15 | /** 16 | * The rest entrance 17 | * Created by liuhongyu.louie on 2016/9/17. 18 | */ 19 | @ChannelHandler.Sharable 20 | public class RequestProcessHandler extends ChannelInboundHandlerAdapter { 21 | 22 | private BaseConfiguration baseConfiguration; 23 | 24 | public RequestProcessHandler(BaseConfiguration baseConfiguration) { 25 | this.baseConfiguration = baseConfiguration; 26 | } 27 | 28 | @Override 29 | public void channelRead(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception { 30 | HttpEntity httpEntity = createNewRequestEntity(channelHandlerContext, (FullHttpRequest) msg); 31 | ActorFactory.createActor(RequestProcessActor.class).tell(httpEntity, ActorRef.noSender()); 32 | } 33 | 34 | @Override 35 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 36 | if (ctx.channel().isActive()){ 37 | ctx.close(); 38 | } 39 | } 40 | 41 | private HttpEntity createNewRequestEntity(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest){ 42 | Request request = new Request(fullHttpRequest); 43 | Response response = new Response(); 44 | StringBuilder headers = new StringBuilder(); 45 | baseConfiguration.getAccessControlAllowHeaders().forEach((header) -> headers.append(header).append(",")); 46 | headers.deleteCharAt(headers.length() - 1); 47 | HttpEntity httpEntity = new HttpEntity(request, response, channelHandlerContext); 48 | httpEntity.getResponse().getResponseHeaders().put("Access-Control-Allow-Origin", baseConfiguration.getHost().equalsIgnoreCase("*") ? "*" : (baseConfiguration.getHost() + ":" + baseConfiguration.getPort())); 49 | httpEntity.getResponse().getResponseHeaders().put("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE"); 50 | httpEntity.getResponse().getResponseHeaders().put("Access-Control-Allow-Headers", headers.toString()); 51 | return httpEntity; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/core/pipeline/utils/ByteBufUtils.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network.core.pipeline.utils; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import tech.dbgsoftware.easyrest.utils.LogUtils; 5 | 6 | public class ByteBufUtils { 7 | 8 | public static byte[] readAll(ByteBuf byteBuf) { 9 | try { 10 | byte[] contentByte = new byte[byteBuf.readableBytes()]; 11 | byteBuf.readBytes(contentByte); 12 | return contentByte; 13 | } catch (Exception e) { 14 | LogUtils.error(e.getMessage()); 15 | } 16 | return new byte[0]; 17 | } 18 | } -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/exception/ConfigurationException.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network.exception; 2 | 3 | /** 4 | * Created by liuhongyu.louie on 2016/9/16. 5 | */ 6 | public class ConfigurationException extends RuntimeException { 7 | 8 | public ConfigurationException(String message) { 9 | super(message); 10 | } 11 | 12 | public ConfigurationException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | 16 | public ConfigurationException(Throwable cause) { 17 | super(cause); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/router/PathNode.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network.router; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class PathNode { 7 | 8 | private String path; 9 | 10 | private Map childPathMap = new HashMap<>(); 11 | 12 | public PathNode(String path) { 13 | if (path.startsWith("{") && path.endsWith("}")){ 14 | path = "*"; 15 | } 16 | this.path = path; 17 | } 18 | 19 | public String getPath() { 20 | return path; 21 | } 22 | 23 | public void setPath(String path) { 24 | this.path = path; 25 | } 26 | 27 | public Map getChildPathMap() { 28 | return childPathMap; 29 | } 30 | 31 | public void putChildPathMap(PathNode child) { 32 | this.childPathMap.put(child.getPath(), child); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/router/PathStore.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network.router; 2 | 3 | import tech.dbgsoftware.easyrest.utils.StringUtils; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class PathStore { 9 | 10 | private static final Map ROUTER_MAPPING = new HashMap<>(); 11 | 12 | public static String queryPath(String url){ 13 | StringBuilder modifiedUrl = new StringBuilder(); 14 | String[] paths = StringUtils.split(url, "/"); 15 | PathNode parent = null; 16 | PathNode matchAny = new PathNode("*"); 17 | for (String path : paths) { 18 | modifiedUrl.append("/"); 19 | PathNode pathNode = new PathNode(path); 20 | if (parent == null) { 21 | parent = pathNode; 22 | if (ROUTER_MAPPING.containsKey(parent.getPath())) { 23 | modifiedUrl.append(parent.getPath()); 24 | parent = ROUTER_MAPPING.get(parent.getPath()); 25 | } else { 26 | if (ROUTER_MAPPING.containsKey(matchAny.getPath())){ 27 | modifiedUrl.append("*"); 28 | parent = ROUTER_MAPPING.get(matchAny.getPath()); 29 | } else { 30 | return null; 31 | } 32 | } 33 | } else { 34 | if (!parent.getChildPathMap().containsKey(pathNode.getPath())){ 35 | if (!parent.getChildPathMap().containsKey(matchAny.getPath())) { 36 | return null; 37 | } else { 38 | modifiedUrl.append("*"); 39 | parent = parent.getChildPathMap().get(matchAny.getPath()); 40 | } 41 | } else { 42 | modifiedUrl.append(pathNode.getPath()); 43 | parent = parent.getChildPathMap().get(pathNode.getPath()); 44 | } 45 | 46 | } 47 | } 48 | return modifiedUrl.toString(); 49 | } 50 | 51 | public static void putPath(String url){ 52 | String[] paths = StringUtils.split(url, "/"); 53 | PathNode parent = null; 54 | for (String path : paths) { 55 | PathNode pathNode = new PathNode(path); 56 | if (parent == null) { 57 | parent = pathNode; 58 | if (ROUTER_MAPPING.containsKey(parent.getPath())) { 59 | parent = ROUTER_MAPPING.get(parent.getPath()); 60 | } else { 61 | ROUTER_MAPPING.put(parent.getPath(), parent); 62 | } 63 | } else { 64 | if (!parent.getChildPathMap().containsKey(pathNode.getPath())) { 65 | parent.getChildPathMap().put(pathNode.getPath(), pathNode); 66 | } 67 | parent = parent.getChildPathMap().get(pathNode.getPath()); 68 | } 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/router/RouterProvider.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network.router; 2 | 3 | import io.netty.handler.codec.http.HttpMethod; 4 | import tech.dbgsoftware.easyrest.model.request.RestObject; 5 | import tech.dbgsoftware.easyrest.utils.StringUtils; 6 | 7 | import java.lang.reflect.Method; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public class RouterProvider { 12 | 13 | private static Map restObjectMap = new HashMap<>(); 14 | 15 | public static Map getRestObjectMap() { 16 | return restObjectMap; 17 | } 18 | 19 | public static RestObject getRestObject(String url) { 20 | String modifiedUrl = PathStore.queryPath(url); 21 | if (modifiedUrl != null) { 22 | if (modifiedUrl.contains("*")) { 23 | RestObject restObject = restObjectMap.get(modifiedUrl); 24 | if (restObject != null) { 25 | String[] originPaths = StringUtils.split(restObject.getOriginalPath(), "/"); 26 | String[] modifiedPaths = StringUtils.split(modifiedUrl, "/"); 27 | String[] requestPaths = StringUtils.split(url, "/"); 28 | if (originPaths.length == requestPaths.length) { 29 | for (int i = 0; i < originPaths.length; i++) { 30 | if (modifiedPaths[i].equalsIgnoreCase("*")) { 31 | restObject.putToUriValueMap(originPaths[i].replace("{", "").replace("}", ""), requestPaths[i]); 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } 38 | return restObjectMap.get(modifiedUrl); 39 | } 40 | 41 | public static void methodRouterResolve(StringBuffer[] restUri, String methodName, String urlFromMethod, HttpMethod httpMethod, Method method, Class controller){ 42 | if (urlFromMethod.startsWith("/")){ 43 | methodName = urlFromMethod; 44 | } 45 | RestObject restObject = new RestObject(method, httpMethod, controller); 46 | for (StringBuffer aRestUri : restUri) { 47 | putRouter(aRestUri.toString(), methodName, httpMethod, restObject); 48 | } 49 | } 50 | 51 | public static void registerUrl(String url, HttpMethod httpMethod, RestObject restObject){ 52 | restObject.setOriginalPath(url); 53 | PathStore.putPath(url); 54 | String[] paths = StringUtils.split(url, "/"); 55 | StringBuilder modifiedUrl = new StringBuilder(); 56 | for (String path : paths) { 57 | modifiedUrl.append("/"); 58 | if (path.startsWith("{") && path.endsWith("}")) { 59 | modifiedUrl.append("*"); 60 | } else { 61 | modifiedUrl.append(path); 62 | } 63 | } 64 | if (restObjectMap.containsKey(modifiedUrl.toString())){ 65 | restObjectMap.get(modifiedUrl.toString()).addHttpMethod(httpMethod); 66 | } else { 67 | restObjectMap.put(modifiedUrl.toString(), restObject); 68 | } 69 | } 70 | 71 | private static void putRouter(String bindUrl, String methodUrl, HttpMethod httpMethod, RestObject restObject){ 72 | StringBuilder url = new StringBuilder(bindUrl); 73 | if (!bindUrl.startsWith("/")){ 74 | url.insert(0, "/"); 75 | } 76 | if (!bindUrl.endsWith("/") && !methodUrl.startsWith("/")){ 77 | url.insert(url.length(), "/"); 78 | } 79 | url.append(methodUrl); 80 | RouterProvider.registerUrl(url.toString(), httpMethod, restObject); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/network/router/UrlFormat.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.network.router; 2 | 3 | import io.netty.handler.codec.http.QueryStringDecoder; 4 | 5 | import java.util.Map; 6 | 7 | public class UrlFormat { 8 | 9 | private static final String PARAMETER_SPLIT = "\\?"; 10 | 11 | private static final String PARAMETER_CONTAIN = "?"; 12 | 13 | public static String getUrl(String requestUrl, Map parameterFromURL){ 14 | if (requestUrl.indexOf(PARAMETER_CONTAIN) > 0){ 15 | String[] parameters = requestUrl.split(PARAMETER_SPLIT); 16 | QueryStringDecoder decoder = new QueryStringDecoder(requestUrl); 17 | decoder.parameters().forEach((key, value) -> parameterFromURL.put(key, value.get(0))); 18 | return parameters[0]; 19 | } else { 20 | return requestUrl; 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/DateUtils.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | import java.sql.Timestamp; 4 | import java.util.Calendar; 5 | import java.util.Date; 6 | 7 | /** 8 | * Created by liuhongyu.louie on 2016/10/16. 9 | */ 10 | public class DateUtils { 11 | 12 | private DateUtils(){} 13 | 14 | public static long getNow(){ 15 | return new Date().getTime(); 16 | } 17 | 18 | public static Timestamp dateToTimeStamp(Date date){ 19 | Calendar calendar = Calendar.getInstance(); 20 | calendar.setTime(date); 21 | calendar.set(Calendar.MILLISECOND, 0); 22 | return new Timestamp(calendar.getTimeInMillis()); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/DoubleTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | import com.google.gson.TypeAdapter; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonToken; 6 | import com.google.gson.stream.JsonWriter; 7 | 8 | import java.io.IOException; 9 | 10 | public class DoubleTypeAdapter extends TypeAdapter { 11 | @Override 12 | public Double read(JsonReader reader) throws IOException { 13 | if(reader.peek() == JsonToken.NULL){ 14 | reader.nextNull(); 15 | return 0D; 16 | } 17 | String stringValue = reader.nextString(); 18 | try{ 19 | Double value = Double.valueOf(stringValue); 20 | return value; 21 | }catch(NumberFormatException e){ 22 | return 0D; 23 | } 24 | } 25 | @Override 26 | public void write(JsonWriter writer, Double value) throws IOException { 27 | if (value == null) { 28 | writer.nullValue(); 29 | return; 30 | } 31 | writer.value(value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/DoubleUtils.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | /** 4 | * Created by liuhongyu.louie on 2017/1/15. 5 | */ 6 | public class DoubleUtils { 7 | 8 | public static double valueOf(String string){ 9 | try { 10 | return Double.valueOf(string); 11 | } catch (NumberFormatException | NullPointerException e){ 12 | return 0.0; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/IntegerTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | import com.google.gson.TypeAdapter; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonToken; 6 | import com.google.gson.stream.JsonWriter; 7 | 8 | import java.io.IOException; 9 | 10 | public class IntegerTypeAdapter extends TypeAdapter { 11 | @Override 12 | public Integer read(JsonReader reader) throws IOException { 13 | if(reader.peek() == JsonToken.NULL){ 14 | reader.nextNull(); 15 | return 0; 16 | } 17 | String stringValue = reader.nextString(); 18 | try{ 19 | Integer value = Integer.valueOf(stringValue); 20 | return value; 21 | }catch(NumberFormatException e){ 22 | return 0; 23 | } 24 | } 25 | @Override 26 | public void write(JsonWriter writer, Integer value) throws IOException { 27 | if (value == null) { 28 | writer.nullValue(); 29 | return; 30 | } 31 | writer.value(value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/IntegerUtils.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | /** 4 | * Created by liuhongyu.louie on 2017/1/15. 5 | */ 6 | public class IntegerUtils { 7 | 8 | public static int valueOf(String string){ 9 | try{ 10 | return Integer.valueOf(string); 11 | } catch (NumberFormatException | NullPointerException e){ 12 | return 0; 13 | } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/JsonTranslationUtil.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | 6 | import java.lang.reflect.Type; 7 | 8 | public class JsonTranslationUtil { 9 | 10 | private static final Gson GSON = new GsonBuilder() 11 | .registerTypeAdapter(Long.class, new LongTypeAdapter()) 12 | .registerTypeAdapter(long.class, new LongTypeAdapter()) 13 | .registerTypeAdapter(Double.class, new DoubleTypeAdapter()) 14 | .registerTypeAdapter(double.class, new DoubleTypeAdapter()) 15 | .registerTypeAdapter(Integer.class, new IntegerTypeAdapter()) 16 | .registerTypeAdapter(int.class, new IntegerTypeAdapter()) 17 | .create(); 18 | 19 | public static String toJsonString(Object object){ 20 | return GSON.toJson(object); 21 | } 22 | 23 | public static T fromJson(String jsonString, Class aClass){ 24 | return GSON.fromJson(jsonString, aClass); 25 | } 26 | 27 | public static T fromJson(String jsonString, Type type){ 28 | try { 29 | return GSON.fromJson(jsonString, type); 30 | } catch (Exception e){ 31 | LogUtils.error(jsonString); 32 | LogUtils.error(e.getMessage(), e); 33 | return null; 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/LogUtils.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import tech.dbgsoftware.easyrest.exception.PageNotFoundException; 8 | 9 | import java.util.Date; 10 | import java.util.concurrent.ExecutorService; 11 | import java.util.concurrent.Executors; 12 | import java.util.function.Function; 13 | 14 | public class LogUtils { 15 | 16 | private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(2); 17 | private static final Logger LOGGER = LoggerFactory.getLogger(LogUtils.class); 18 | private static final Gson GSON = new GsonBuilder().setPrettyPrinting().serializeNulls().create(); 19 | private static Function INFO_FUNCTION = null; 20 | private static Function ERROR_FUNCTION = null; 21 | 22 | public static void setFunction(Function infoFunction, Function errorFunction) { 23 | INFO_FUNCTION = infoFunction; 24 | ERROR_FUNCTION = errorFunction; 25 | } 26 | 27 | public static String printGsonObject(final Object obj){ 28 | String jsonResult = GSON.toJson(obj); 29 | LOGGER.info(jsonResult); 30 | return jsonResult; 31 | } 32 | 33 | public static void debug(String string, Class aClass){ 34 | LOGGER.debug(String.format("%s %s", new Date(), "From " + aClass.getName() + ": " + string)); 35 | } 36 | 37 | public static void debug(Object obj, Class aClass){ 38 | LOGGER.debug(String.format("%s %s", new Date(), "From " + aClass.getName() + ": " + GSON.toJson(obj))); 39 | } 40 | 41 | public static void info(String string, Class aClass){ 42 | String log = String.format("%s %s", new Date(), "From " + aClass.getName() + ": " + string); 43 | LOGGER.info(log); 44 | if (INFO_FUNCTION != null) { 45 | StringBuilder stringBuilder = new StringBuilder(); 46 | stringBuilder.append('['); 47 | stringBuilder.append(Thread.currentThread().getName()); 48 | stringBuilder.append("] "); 49 | EXECUTOR_SERVICE.execute(() -> INFO_FUNCTION.apply(stringBuilder.append(log).toString())); 50 | } 51 | } 52 | 53 | public static void info(Object obj, Class aClass){ 54 | String log = String.format("%s %s", new Date(), "From " + aClass.getName() + ": " + GSON.toJson(obj)); 55 | LOGGER.info(log); 56 | if (INFO_FUNCTION != null) { 57 | StringBuilder stringBuilder = new StringBuilder(); 58 | stringBuilder.append('['); 59 | stringBuilder.append(Thread.currentThread().getName()); 60 | stringBuilder.append("] "); 61 | EXECUTOR_SERVICE.execute(() -> INFO_FUNCTION.apply(stringBuilder.append(log).toString())); 62 | } 63 | } 64 | 65 | public static void info(String string){ 66 | String log = String.format("%s %s", new Date(), string); 67 | LOGGER.info(log); 68 | if (INFO_FUNCTION != null) { 69 | StringBuilder stringBuilder = new StringBuilder(); 70 | stringBuilder.append('['); 71 | stringBuilder.append(Thread.currentThread().getName()); 72 | stringBuilder.append("] "); 73 | EXECUTOR_SERVICE.execute(() -> INFO_FUNCTION.apply(stringBuilder.append(log).toString())); 74 | } 75 | } 76 | 77 | public static void info(Object obj){ 78 | String log = String.format("%s %s", new Date(), GSON.toJson(obj)); 79 | LOGGER.info(log); 80 | if (INFO_FUNCTION != null) { 81 | StringBuilder stringBuilder = new StringBuilder(); 82 | stringBuilder.append('['); 83 | stringBuilder.append(Thread.currentThread().getName()); 84 | stringBuilder.append("] "); 85 | EXECUTOR_SERVICE.execute(() -> INFO_FUNCTION.apply(stringBuilder.append(log).toString())); 86 | } 87 | } 88 | 89 | public static void error(String message){ 90 | String error = String.format("%s %s", new Date(), message + "\r\n" + ThreadStackUtils.getStackInfo()); 91 | LOGGER.error(error); 92 | if (ERROR_FUNCTION != null) { 93 | StringBuilder stringBuilder = new StringBuilder(); 94 | stringBuilder.append('['); 95 | stringBuilder.append(Thread.currentThread().getName()); 96 | stringBuilder.append("] "); 97 | EXECUTOR_SERVICE.execute(() -> ERROR_FUNCTION.apply(stringBuilder.append(error).toString())); 98 | } 99 | } 100 | 101 | public static void error(String message, Object object){ 102 | if (object == null) { 103 | error(message + "\r\n" + ThreadStackUtils.getStackInfo()); 104 | if (ERROR_FUNCTION != null) { 105 | StringBuilder stringBuilder = new StringBuilder(); 106 | stringBuilder.append('['); 107 | stringBuilder.append(Thread.currentThread().getName()); 108 | stringBuilder.append("] "); 109 | EXECUTOR_SERVICE.execute(() -> ERROR_FUNCTION.apply(stringBuilder.append(message).append("\r\n").append(ThreadStackUtils.getStackInfo()).toString())); 110 | } 111 | } else { 112 | String error = String.format("%s %s", new Date(), message + "\r\n" + ThreadStackUtils.getStackInfo()); 113 | LOGGER.error(error, object); 114 | if (ERROR_FUNCTION != null) { 115 | StringBuilder stringBuilder = new StringBuilder(); 116 | stringBuilder.append('['); 117 | stringBuilder.append(Thread.currentThread().getName()); 118 | stringBuilder.append("] "); 119 | EXECUTOR_SERVICE.execute(() -> ERROR_FUNCTION.apply(stringBuilder.append(error).toString())); 120 | } 121 | } 122 | } 123 | 124 | public static void error(String message, Exception e){ 125 | if (e instanceof PageNotFoundException) { 126 | error(message + " " + e.toString() + "\r\n" + ThreadStackUtils.getStackInfo(e)); 127 | if (ERROR_FUNCTION != null) { 128 | StringBuilder stringBuilder = new StringBuilder(); 129 | stringBuilder.append('['); 130 | stringBuilder.append(Thread.currentThread().getName()); 131 | stringBuilder.append("] "); 132 | EXECUTOR_SERVICE.execute(() -> ERROR_FUNCTION.apply(stringBuilder.append(message).append("\r\n").append(ThreadStackUtils.getStackInfo(e)).toString())); 133 | } 134 | } else { 135 | String error = String.format("%s %s", new Date(), message + " " + e.toString() + "\r\n" + ThreadStackUtils.getStackInfo(e)); 136 | LOGGER.error(error, e); 137 | if (ERROR_FUNCTION != null) { 138 | StringBuilder stringBuilder = new StringBuilder(); 139 | stringBuilder.append('['); 140 | stringBuilder.append(Thread.currentThread().getName()); 141 | stringBuilder.append("] "); 142 | EXECUTOR_SERVICE.execute(() -> ERROR_FUNCTION.apply(stringBuilder.append(message).toString())); 143 | } 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/LongTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | import com.google.gson.TypeAdapter; 4 | import com.google.gson.stream.JsonReader; 5 | import com.google.gson.stream.JsonToken; 6 | import com.google.gson.stream.JsonWriter; 7 | 8 | import java.io.IOException; 9 | 10 | public class LongTypeAdapter extends TypeAdapter { 11 | @Override 12 | public Long read(JsonReader reader) throws IOException { 13 | if(reader.peek() == JsonToken.NULL){ 14 | reader.nextNull(); 15 | return 0L; 16 | } 17 | String stringValue = reader.nextString(); 18 | try{ 19 | Long value = Long.valueOf(stringValue); 20 | return value; 21 | }catch(NumberFormatException e){ 22 | return 0L; 23 | } 24 | } 25 | @Override 26 | public void write(JsonWriter writer, Long value) throws IOException { 27 | if (value == null) { 28 | writer.nullValue(); 29 | return; 30 | } 31 | writer.value(value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * String utils 8 | * Created by liuhongyu.louie on 2016/10/1. 9 | */ 10 | public class StringUtils{ 11 | 12 | public static String replaceNull(String str){ 13 | if (isEmptyString(str) || str.equalsIgnoreCase("null")){ 14 | return ""; 15 | } 16 | return str; 17 | } 18 | 19 | public static boolean isEmptyString(String str){ 20 | return str == null || str.isEmpty() || str.equalsIgnoreCase("null"); 21 | } 22 | 23 | public static String[] split(String string, String splitString){ 24 | if (string.contains(splitString)){ 25 | List pathList = new ArrayList<>(); 26 | for (String path : string.split(splitString)) { 27 | if (path != null && path.length() > 0){ 28 | pathList.add(path); 29 | } 30 | } 31 | return pathList.toArray(new String[]{}); 32 | } else { 33 | return new String[]{string}; 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /EasyRest/src/main/java/tech/dbgsoftware/easyrest/utils/ThreadStackUtils.java: -------------------------------------------------------------------------------- 1 | package tech.dbgsoftware.easyrest.utils; 2 | 3 | public class ThreadStackUtils { 4 | 5 | public static String getStackInfo() { 6 | StringBuilder stringBuffer = new StringBuilder(); 7 | for (int i = 0; i < Math.min(18, Thread.currentThread().getStackTrace().length); i++) { 8 | String className = Thread.currentThread().getStackTrace()[i].getClassName(); 9 | String methodName = Thread.currentThread().getStackTrace()[i].getMethodName(); 10 | String line = String.valueOf(Thread.currentThread().getStackTrace()[i].getLineNumber()); 11 | stringBuffer.append(className).append(":").append(methodName).append(":").append(line).append(","); 12 | } 13 | return stringBuffer.toString(); 14 | } 15 | 16 | public static String getStackInfo(Exception e) { 17 | StringBuilder stringBuffer = new StringBuilder(); 18 | for (int i = 0; i < Math.min(18, e.getStackTrace().length); i++) { 19 | String className = e.getStackTrace()[i].getClassName(); 20 | String methodName = e.getStackTrace()[i].getMethodName(); 21 | String line = String.valueOf(e.getStackTrace()[i].getLineNumber()); 22 | stringBuffer.append(className).append(":").append(methodName).append(":").append(line).append(","); 23 | } 24 | return stringBuffer.toString(); 25 | } 26 | 27 | public static void main(String[] args) { 28 | try { 29 | System.out.println(123); 30 | System.out.println(Double.valueOf("")); 31 | } catch (Exception e) { 32 | System.out.println(JsonTranslationUtil.toJsonString(getStackInfo(e))); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /EasyRest/src/main/resources/easyrest-applicationContext-01.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/example-service-1-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Example-Distributed-Service-1 7 | EasyRest 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | example-service-1-api 13 | 14 | 15 | EasyRest 16 | Example-Distributed-Service-Model 17 | 0.0.1-SNAPSHOT 18 | compile 19 | 20 | 21 | tech.dbgsoftware.easyrest 22 | EasyRest-NAS-All-In-One 23 | 0.0.1 24 | compile 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/example-service-1-api/src/main/java/com/example/api/Service1.java: -------------------------------------------------------------------------------- 1 | package com.example.api; 2 | 3 | import tech.dbgsoftware.easyrest.annotations.method.BindURL; 4 | import tech.dbgsoftware.easyrest.annotations.method.Post; 5 | import tech.dbgsoftware.easyrest.annotations.parameter.AllDefined; 6 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 7 | import com.example.model.People; 8 | 9 | import java.util.List; 10 | 11 | @BindURL("/service1") 12 | public interface Service1 { 13 | 14 | @Post 15 | @AllDefined 16 | ResponseEntity createPeople(String name, int age, long birthday, List skills, People boss); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/example-service-1-main/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Example-Distributed-Service-1 7 | EasyRest 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | example-service-1-main 13 | 14 | 15 | EasyRest 16 | example-service-1-api 17 | 0.0.1-SNAPSHOT 18 | compile 19 | 20 | 21 | EasyRest 22 | example-service-2-api 23 | 0.0.1-SNAPSHOT 24 | compile 25 | 26 | 27 | 28 | 29 | UTF-8 30 | UTF-8 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/example-service-1-main/src/main/java/com/example/main/Startup.java: -------------------------------------------------------------------------------- 1 | package com.example.main; 2 | 3 | import tech.dbgsoftware.easyrest.EasyRest; 4 | import tech.dbgsoftware.easyrest.actors.remote.conf.EasyRestDistributedServiceBind; 5 | import tech.dbgsoftware.easyrest.network.NettyInit; 6 | 7 | import java.io.IOException; 8 | 9 | public class Startup { 10 | 11 | public static void main(String[] args) throws IOException { 12 | EasyRestDistributedServiceBind.loadConfiguration(Startup.class.getClassLoader().getResourceAsStream("services-mapping-01.json")); 13 | EasyRest easyRest = new EasyRest("classpath:MyExampleApplicationContext-01.xml"); 14 | easyRest.startup("example-service-1", new NettyInit(8001)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/example-service-1-main/src/main/java/com/example/main/impl/Service1Impl.java: -------------------------------------------------------------------------------- 1 | package com.example.main.impl; 2 | 3 | import tech.dbgsoftware.easyrest.ioc.remote.EasyRestServiceLookup; 4 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 5 | import com.example.api.Service1; 6 | import com.example.api.Service2; 7 | import com.example.model.People; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.List; 11 | 12 | @Service 13 | public class Service1Impl implements Service1 { 14 | 15 | @Override 16 | public ResponseEntity createPeople(String name, int age, long birthday, List skills, People boss) { 17 | Service2 service2 = EasyRestServiceLookup.lookup(Service2.class); 18 | return ResponseEntity.buildOkResponse(service2.getPeople(name, age, birthday, skills, boss)); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/example-service-1-main/src/main/resources/MyExampleApplicationContext-01.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/example-service-1-main/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | actor { 3 | provider = "akka.remote.RemoteActorRefProvider" 4 | } 5 | remote { 6 | transport = "akka.remote.netty.NettyRemoteTransport" 7 | netty { 8 | tcp { 9 | hostname = "127.0.0.1" 10 | port = 2551 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/example-service-1-main/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhongyuand/EasyRest-NAS/94d3c1d22ca2b7ff3cf1f95a91d97214b4feb55a/Example/Example-Distributed-Service-1/example-service-1-main/src/main/resources/log4j.properties -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/example-service-1-main/src/main/resources/services-mapping-01.json: -------------------------------------------------------------------------------- 1 | { 2 | "self": { 3 | "akkaSystemName": "example-service-1", 4 | "host": "127.0.0.1", 5 | "port": "2551" 6 | }, 7 | "services" : [ 8 | { 9 | "akkaSystemName": "example-service-1", 10 | "host": "127.0.0.1", 11 | "port": "2551" 12 | }, 13 | { 14 | "akkaSystemName": "example-service-2", 15 | "host": "127.0.0.1", 16 | "port": "2552" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | EasyRest-example 7 | EasyRest 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | Example-Distributed-Service-1 13 | pom 14 | 15 | example-service-1-api 16 | example-service-1-main 17 | 18 | 19 | 20 | EasyRest 21 | Example-Distributed-Service-2 22 | 0.0.1-SNAPSHOT 23 | compile 24 | 25 | 26 | 27 | 28 | UTF-8 29 | UTF-8 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/example-service-2-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Example-Distributed-Service-2 7 | EasyRest 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | example-service-2-api 13 | 14 | 15 | EasyRest 16 | Example-Distributed-Service-Model 17 | 0.0.1-SNAPSHOT 18 | compile 19 | 20 | 21 | tech.dbgsoftware.easyrest 22 | EasyRest-NAS-All-In-One 23 | 0.0.1 24 | compile 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/example-service-2-api/src/main/java/com/example/api/Service2.java: -------------------------------------------------------------------------------- 1 | package com.example.api; 2 | 3 | 4 | import tech.dbgsoftware.easyrest.annotations.method.BindURL; 5 | import tech.dbgsoftware.easyrest.annotations.method.Get; 6 | import com.example.model.People; 7 | 8 | import java.util.List; 9 | 10 | @BindURL("/service2") 11 | public interface Service2 { 12 | 13 | @Get 14 | People getPeople(String name, int age, long birthday, List skills, People boss); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/example-service-2-main/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Example-Distributed-Service-2 7 | EasyRest 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | example-service-2-main 13 | 14 | 15 | EasyRest 16 | Example-Distributed-Service-Model 17 | 0.0.1-SNAPSHOT 18 | compile 19 | 20 | 21 | EasyRest 22 | example-service-2-api 23 | 0.0.1-SNAPSHOT 24 | compile 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/example-service-2-main/src/main/java/com/example/main/Startup.java: -------------------------------------------------------------------------------- 1 | package com.example.main; 2 | 3 | import tech.dbgsoftware.easyrest.EasyRest; 4 | import tech.dbgsoftware.easyrest.actors.remote.conf.EasyRestDistributedServiceBind; 5 | import tech.dbgsoftware.easyrest.network.NettyInit; 6 | 7 | import java.io.IOException; 8 | 9 | public class Startup { 10 | 11 | public static void main(String[] args) throws IOException { 12 | EasyRestDistributedServiceBind.loadConfiguration(Startup.class.getClassLoader().getResourceAsStream("services-mapping-02.json")); 13 | EasyRest easyRest = new EasyRest("classpath:MyExampleApplicationContext-02.xml"); 14 | easyRest.startup("example-service-2", new NettyInit(8002)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/example-service-2-main/src/main/java/com/example/main/impl/Service2Impl.java: -------------------------------------------------------------------------------- 1 | package com.example.main.impl; 2 | 3 | import com.example.api.Service2; 4 | import com.example.model.People; 5 | import org.springframework.stereotype.Service; 6 | 7 | import java.util.List; 8 | 9 | @Service 10 | public class Service2Impl implements Service2 { 11 | 12 | @Override 13 | public People getPeople(String name, int age, long birthday, List skills, People boss) { 14 | return new People(name, age, birthday, skills, boss); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/example-service-2-main/src/main/resources/MyExampleApplicationContext-02.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/example-service-2-main/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | actor { 3 | provider = "akka.remote.RemoteActorRefProvider" 4 | } 5 | remote { 6 | transport = "akka.remote.netty.NettyRemoteTransport" 7 | netty { 8 | tcp { 9 | hostname = "127.0.0.1" 10 | port = 2552 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/example-service-2-main/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhongyuand/EasyRest-NAS/94d3c1d22ca2b7ff3cf1f95a91d97214b4feb55a/Example/Example-Distributed-Service-2/example-service-2-main/src/main/resources/log4j.properties -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/example-service-2-main/src/main/resources/services-mapping-02.json: -------------------------------------------------------------------------------- 1 | { 2 | "self": { 3 | "akkaSystemName": "example-service-2", 4 | "host": "127.0.0.1", 5 | "port": "2552" 6 | }, 7 | "services" : [ 8 | { 9 | "akkaSystemName": "example-service-1", 10 | "host": "127.0.0.1", 11 | "port": "2551" 12 | }, 13 | { 14 | "akkaSystemName": "example-service-2", 15 | "host": "127.0.0.1", 16 | "port": "2552" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | EasyRest-example 7 | EasyRest 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | Example-Distributed-Service-2 13 | pom 14 | 15 | example-service-2-api 16 | example-service-2-main 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-Model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | EasyRest-example 7 | EasyRest 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | Example-Distributed-Service-Model 13 | 14 | -------------------------------------------------------------------------------- /Example/Example-Distributed-Service-Model/src/main/java/com/example/model/People.java: -------------------------------------------------------------------------------- 1 | package com.example.model; 2 | 3 | import java.util.List; 4 | 5 | public class People { 6 | 7 | private String name; 8 | private int age; 9 | private long birthday; 10 | private List skills; 11 | private People boss; 12 | 13 | public People(String name, int age, long birthday, List skills, People boss) { 14 | this.name = name; 15 | this.age = age; 16 | this.birthday = birthday; 17 | this.skills = skills; 18 | this.boss = boss; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | EasyRest-example 7 | EasyRest 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | Example-Quick-Start 13 | 14 | 15 | tech.dbgsoftware.easyrest 16 | EasyRest-NAS-All-In-One 17 | 0.0.1 18 | compile 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/src/main/java/com/example/Example.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | 4 | import tech.dbgsoftware.easyrest.EasyRest; 5 | import tech.dbgsoftware.easyrest.network.NettyInit; 6 | 7 | public class Example { 8 | 9 | public static void main(String[] args) { 10 | NettyInit nettyInit = new NettyInit("127.0.0.1", 8181); 11 | nettyInit.setIoExecutors(1); 12 | EasyRest easyRest = new EasyRest("classpath:MyExampleApplicationContext.xml"); 13 | easyRest.startup("EasyRestServer", nettyInit); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/src/main/java/com/example/InfoMation.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.SecretKey; 5 | import javax.crypto.SecretKeyFactory; 6 | import javax.crypto.spec.DESKeySpec; 7 | import java.security.SecureRandom; 8 | 9 | public class InfoMation { 10 | 11 | 12 | //算法密匙 13 | private static final byte[] DES_KEY = "desPasswordKey08".getBytes(); 14 | 15 | /** 16 | * 数据加密,算法(DES) 17 | * 18 | * @param data 19 | * 要进行加密的数据 20 | * @return 加密后的数据 21 | */ 22 | public static String encryptBasedDes(String data) { 23 | String encryptedData = null; 24 | try { 25 | // DES算法要求有一个可信任的随机数源 26 | SecureRandom sr = new SecureRandom(); 27 | DESKeySpec deskey = new DESKeySpec(DES_KEY); 28 | // 创建一个密匙工厂,然后用它把DESKeySpec转换成一个SecretKey对象 29 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 30 | SecretKey key = keyFactory.generateSecret(deskey); 31 | // 加密对象 32 | Cipher cipher = Cipher.getInstance("DES"); 33 | cipher.init(Cipher.ENCRYPT_MODE, key, sr); 34 | // 加密,并把字节数组编码成字符串 35 | encryptedData = new sun.misc.BASE64Encoder().encode(cipher.doFinal(data.getBytes())); 36 | } catch (Exception e) { 37 | // log.error("加密错误,错误信息:", e); 加密后UpSbNP/AeM5AfGnWB21HZQ== UpSbNP/AeM5AfGnWB21HZQ== 38 | throw new RuntimeException("加密错误,错误信息:", e); 39 | } 40 | return encryptedData; 41 | } 42 | 43 | /** 44 | * 解密 45 | * @param cryptData 46 | * @return 47 | */ 48 | public static String decryptBasedDes(String cryptData) { 49 | String decryptedData = null; 50 | try { 51 | // DES算法要求有一个可信任的随机数源 52 | SecureRandom sr = new SecureRandom(); 53 | DESKeySpec deskey = new DESKeySpec(DES_KEY); 54 | // 创建一个密匙工厂,然后用它把DESKeySpec转换成一个SecretKey对象 55 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 56 | SecretKey key = keyFactory.generateSecret(deskey); 57 | // 解密对象 58 | Cipher cipher = Cipher.getInstance("DES"); 59 | cipher.init(Cipher.DECRYPT_MODE, key, sr); 60 | // 把字符串解码为字节数组,并解密 61 | decryptedData = new String(cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(cryptData))); 62 | } catch (Exception e) { 63 | // log.error("解密错误,错误信息:", e); 64 | throw new RuntimeException("解密错误,错误信息:", e); 65 | } 66 | return decryptedData; 67 | } 68 | 69 | public static void main(String[] args) { 70 | 71 | String str1="12014-11-15"; 72 | // DES数据加密 73 | // String s1=encryptBasedDes(str); 74 | String s1=encryptBasedDes(str1); 75 | 76 | System.out.println("加密后"+s1); 77 | 78 | // DES数据解密 79 | String s2=decryptBasedDes(s1); 80 | 81 | System.err.println("解密后"+s2); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/src/main/java/com/example/model/Stock.java: -------------------------------------------------------------------------------- 1 | package com.example.model; 2 | 3 | public class Stock { 4 | 5 | private int code; 6 | 7 | private String name; 8 | 9 | public Stock(int code, String name) { 10 | this.code = code; 11 | this.name = name; 12 | } 13 | 14 | public int getCode() { 15 | return code; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/src/main/java/com/example/rest/StockInfoRest.java: -------------------------------------------------------------------------------- 1 | package com.example.rest; 2 | 3 | import tech.dbgsoftware.easyrest.annotations.method.BindURL; 4 | import tech.dbgsoftware.easyrest.annotations.method.Get; 5 | import tech.dbgsoftware.easyrest.annotations.method.Post; 6 | import tech.dbgsoftware.easyrest.annotations.parameter.AllDefined; 7 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 8 | import com.example.model.Stock; 9 | 10 | import java.util.List; 11 | 12 | @BindURL("/rest/{TENANT}/stock") 13 | public interface StockInfoRest { 14 | 15 | @Post("/personal/{USER_ID}/favorite/{CODE}") 16 | void addFavorite(String TENANT, String USER_ID, String CODE, long time); 17 | 18 | @Post 19 | @AllDefined 20 | ResponseEntity addStocks(int userNumber, String userName, List stockList); 21 | 22 | @Get("/personal/{USER_ID}/favorite/list") 23 | List getStockList(String USER_ID); 24 | 25 | @Post 26 | @AllDefined 27 | ResponseEntity getA(String a); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/src/main/java/com/example/rest/TestRestService.java: -------------------------------------------------------------------------------- 1 | package com.example.rest; 2 | 3 | import com.example.InfoMation; 4 | import tech.dbgsoftware.easyrest.annotations.method.*; 5 | import tech.dbgsoftware.easyrest.annotations.parameter.AllDefined; 6 | import tech.dbgsoftware.easyrest.aop.customer.CustomInjection; 7 | import tech.dbgsoftware.easyrest.aop.customer.CustomResponse; 8 | import tech.dbgsoftware.easyrest.exception.PermissionException; 9 | import tech.dbgsoftware.easyrest.model.HttpEntity; 10 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 11 | import tech.dbgsoftware.easyrest.utils.JsonTranslationUtil; 12 | 13 | @BindURL("/test") 14 | public interface TestRestService extends CustomInjection, CustomResponse { 15 | 16 | @Get 17 | @SkipCustomerInject 18 | @SkipCustomerResponse 19 | void ping(String a); 20 | 21 | @Post 22 | @SkipCustomerInject 23 | @SkipCustomerResponse 24 | void postPing(String a); 25 | 26 | @Get 27 | @AllDefined 28 | @SkipCustomerInject 29 | @SkipCustomerResponse 30 | ResponseEntity testApi(String a, String b); 31 | 32 | @Get 33 | @AllDefined 34 | @SkipCustomerInject 35 | @SkipCustomerResponse 36 | String test(String a, String b); 37 | 38 | @Override 39 | default HttpEntity preCheck(HttpEntity httpEntity) { 40 | throw new PermissionException("No permission for this rest api."); 41 | } 42 | 43 | @Override 44 | default ResponseEntity processResponse(HttpEntity httpEntity, Object response) { 45 | return ResponseEntity.buildBaseResponse(InfoMation.encryptBasedDes(JsonTranslationUtil.toJsonString(response))); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/src/main/java/com/example/services/StockInfoRestServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.services; 2 | 3 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 4 | import com.example.model.Stock; 5 | import com.example.rest.StockInfoRest; 6 | import com.google.common.collect.Lists; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.util.List; 10 | 11 | @Service 12 | public class StockInfoRestServiceImpl implements StockInfoRest { 13 | 14 | @Override 15 | public void addFavorite(String TENANT, String USER_ID, String CODE, long time) { 16 | System.out.println(TENANT + " " + USER_ID + " " + CODE + " " + time); 17 | } 18 | 19 | @Override 20 | public ResponseEntity addStocks(int userNumber, String userName, List stockList) { 21 | return ResponseEntity.buildOkResponse(Lists.asList(userNumber, userName, new List[]{stockList})); 22 | } 23 | 24 | @Override 25 | public List getStockList(String USER_ID) { 26 | return Lists.newArrayList(new Stock(100000, "stock1"), new Stock(100001, "stock2"), new Stock(100002, "stock3")); 27 | } 28 | 29 | @Override 30 | public ResponseEntity getA(String a) { 31 | return ResponseEntity.buildOkResponse(a); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/src/main/java/com/example/services/TestServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.services; 2 | 3 | import com.example.rest.TestRestService; 4 | import org.springframework.stereotype.Service; 5 | import tech.dbgsoftware.easyrest.model.ResponseEntity; 6 | import tech.dbgsoftware.easyrest.utils.LogUtils; 7 | 8 | @Service 9 | public class TestServiceImpl implements TestRestService { 10 | 11 | @Override 12 | public void ping(String a) { 13 | System.out.println(a); 14 | } 15 | 16 | @Override 17 | public void postPing(String a) { 18 | System.out.println(a); 19 | } 20 | 21 | @Override 22 | public ResponseEntity testApi(String a, String b) { 23 | LogUtils.info(a + " " + b); 24 | return ResponseEntity.buildOkResponse(a + "-" + b); 25 | } 26 | 27 | @Override 28 | public String test(String a, String b) { 29 | String c; 30 | String d; 31 | String e; 32 | String f; 33 | String g; 34 | if (a.equalsIgnoreCase(b)){ 35 | c = a; 36 | d = a; 37 | e = a; 38 | f = a; 39 | g = a; 40 | } else { 41 | c = a; 42 | d = b; 43 | e = "e"; 44 | f = "f"; 45 | g = "g"; 46 | } 47 | return c + "-" + d + "-" + e + "-" + f + "-" + g; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/src/main/resources/MyExampleApplicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Example/Example-Quick-Start/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuhongyuand/EasyRest-NAS/94d3c1d22ca2b7ff3cf1f95a91d97214b4feb55a/Example/Example-Quick-Start/src/main/resources/log4j.properties -------------------------------------------------------------------------------- /Example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | EasyRest 8 | EasyRest-example 9 | pom 10 | 0.0.1-SNAPSHOT 11 | 12 | Example-Distributed-Service-1 13 | Example-Distributed-Service-2 14 | Example-Distributed-Service-Model 15 | Example-Quick-Start 16 | 17 | 18 | 19 | UTF-8 20 | UTF-8 21 | 22 | 23 | 24 | 25 | 26 | 27 | org.apache.maven.plugins 28 | maven-compiler-plugin 29 | 2.0.2 30 | 31 | 1.8 32 | 1.8 33 | ${project.build.sourceEncoding} 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /README-zh.md: -------------------------------------------------------------------------------- 1 | # EasyRest-NAS 2 | 3 | English doc: 4 | > https://github.com/liuhongyuand/EasyRest-NAS/blob/master/README.md 5 | 6 | ### EasyRest 与 Netty, Akka 和 Spring 的整合. 7 | 8 | * ##### 这是一个为快速开发而设计的高性能RESTful框架,极易搭建集群和使用分布式。你可以完全专注在你的业务逻辑上。 9 | 10 | * ##### 不需要 Tomcat,不需要 web.xml 配置,只需一个有 main 函数的 jar 包,你就能拥有一个完美的分布式系统。 11 | 12 | * ##### 你可以不知道 Netty,也可以不知道 akka,甚至不熟悉 Spring,但仍然可以使用该框架。 13 | 14 | ## 快速开始: 15 | 16 | * REST接口定义 17 | 18 | ```java 19 | @BindURL("/rest/{TENANT}/stock") 20 | public interface StockInfoRest { 21 | 22 | @Post("/personal/{USER_ID}/favorite/{CODE}") 23 | void addFavorite(String TENANT, String USER_ID, String CODE, long time); 24 | 25 | @Post 26 | ResponseEntity addStocks(int userNumber, String userName, List stockList); 27 | 28 | @Get("/personal/{USER_ID}/favorite/list") 29 | List getStockList(String USER_ID); 30 | 31 | } 32 | ``` 33 | 34 | * 使用@Service注解,将该类交给Spring生成bean并管理,该框架可以和spring无缝对接使用。 35 | 36 | ```java 37 | @Service 38 | public class StockInfoRestController implements StockInfoRest { 39 | 40 | @Override 41 | public void addFavorite(String TENANT, String USER_ID, String CODE, long time) { 42 | System.out.println(TENANT + " " + USER_ID + " " + CODE + " " + time); 43 | } 44 | 45 | @Override 46 | @AllDefined 47 | public ResponseEntity addStocks(int userNumber, String userName, List stockList) { 48 | return ResponseEntity.buildOkResponse(Lists.asList(userNumber, userName, new List[]{stockList})); 49 | } 50 | 51 | @Override 52 | public List getStockList(String USER_ID) { 53 | return Lists.newArrayList(new Stock(100000, "stock1"), new Stock(100001, "stock2"), new Stock(100002, "stock3")); 54 | } 55 | } 56 | ``` 57 | 58 | * 主函数类,用于启动以及配置。 59 | 60 | ```java 61 | public class Example { 62 | 63 | public static void main(String[] args) { 64 | EasyRest easyRest = new EasyRest("classpath:MyExampleApplicationContext.xml"); 65 | easyRest.startup("EasyRestServer"); 66 | } 67 | 68 | } 69 | ``` 70 | 71 | * 一个基础的spring配置文件 72 | 73 | ```xml 74 | 75 | 79 | 80 | 81 | 82 | 83 | 84 | ``` 85 | 86 | *** 87 | 88 | * @BindURL("/rest/{TENANT}/stock") 会绑定该类监听 "/rest/{TENANT}/stock" 路径的请求。 89 | 90 | * @AllDefined 会要求该方法所有的参数在请求中都被赋予非空值,如果检测到有null,框架将会直接拒绝这个请求。可以减少用户的空值判断。 91 | 92 | * @Service 这个是spring的annotation,将交给spring生成bean并管理。 93 | 94 | * ResponseEntity 是一个通用的返回格式,你能将所有格式的数据放进去。(你也可以不使用这个,直接返回任何你想返回的格式) 95 | 96 | * 如果你有很多其他的spring配置文件,你可以这样启动EasyRest: 97 | 98 | ```java 99 | EasyRest easyRest = new EasyRest("classpath:MyApplicationContext-01.xml", "classpath:MyApplicationContext-02.xml"...); 100 | ``` 101 | 102 | * 所有你想暴露的数据接口,EasyRest都会自动检测到,你只需要启动server。 103 | 104 | ```java 105 | easyRest.startup("EasyRestServer"); 106 | ``` 107 | 108 | *** 109 | 110 | ### 接口调用示例 111 | 112 | * 函数 1 113 | 114 | ```java 115 | @Post("/personal/{USER_ID}/favorite/{CODE}") 116 | void addFavorite(String TENANT, String USER_ID, String CODE, long time); 117 | ``` 118 | 调用地址: 119 | > http://127.0.0.1:8080/rest/100000001/stock/personal/001/favorite/100001 120 | 121 | Content-Type is 'application/json' 122 | 123 | 请求内容: 124 | 125 | ```json 126 | {"time":1524827542} 127 | ``` 128 | 129 | 控制台输出: 130 | 131 | ```java 132 | 100000001 001 100001 1524827542 133 | ``` 134 | 135 | 收到的响应内容: 136 | 137 | ```java 138 | { 139 | "code": "1", 140 | "message": "ok" 141 | } 142 | ``` 143 | 144 | *** 145 | 146 | * 函数 2 147 | 148 | ```java 149 | @Post 150 | @AllDefined 151 | ResponseEntity addStocks(int userNumber, String userName, List stockList); 152 | ``` 153 | 154 | 调用地址: 155 | > http://127.0.0.1:8080/rest/100000001/stock/addStocks 156 | 157 | Content-Type is 'application/json' 158 | 159 | 请求内容: 160 | 161 | ```json 162 | {"userNumber":1, "userName":"Louie", "stockList":[{"code":100001, "name":"stock1"}, {"code":100002, "name":"stock2"}]} 163 | ``` 164 | 165 | 响应内容: 166 | 167 | ```java 168 | { 169 | "code": "1", 170 | "data": [ 171 | 1, 172 | "Louie", 173 | [ 174 | { 175 | "code": 100001, 176 | "name": "stock1" 177 | }, 178 | { 179 | "code": 100002, 180 | "name": "stock2" 181 | } 182 | ] 183 | ] 184 | } 185 | ``` 186 | 187 | 这个函数有一个 @AllDefined 的注解,所以如果任何参数的值为null,比如:“UserName”,那么响应结果将会如下: 188 | 189 | ```java 190 | { 191 | "code": "-1", 192 | "message": "Failed", 193 | "data": { 194 | "errorType": "ParameterNotFoundException", 195 | "errorMessage": "userName is not defined." 196 | } 197 | } 198 | ``` 199 | 200 | *** 201 | 202 | * 函数 3 203 | 204 | ```java 205 | @Get("/personal/{USER_ID}/favorite/list") 206 | List getStockList(String USER_ID); 207 | ``` 208 | 209 | 调用地址: 210 | > http://127.0.0.1:8080/rest/100000001/stock/personal/001/favorite/list 211 | 212 | 响应内容: 213 | 214 | ```java 215 | [ 216 | { 217 | "code": 100000, 218 | "name": "stock1" 219 | }, 220 | { 221 | "code": 100001, 222 | "name": "stock2" 223 | }, 224 | { 225 | "code": 100002, 226 | "name": "stock3" 227 | } 228 | ] 229 | ``` 230 | 231 | *** 232 | 233 | * 对于 content type, 'multipart/form-data' 也是支持的. 234 | 235 | * 框架支持分布式服务,并且十分容易搭建. 236 | 237 | ## 分布式服务示例 238 | 239 | ### 所有的代码都在 Example 的模块中 240 | 241 | #### 代码结构 242 | 243 | - Example-Distributed-Service-1 244 | 245 | - example-service-1-api 246 | 247 | - example-service-1-main 248 | 249 | 250 | - Example-Distributed-Service-2 251 | 252 | - example-service-2-api 253 | 254 | - example-service-2-main 255 | 256 | 257 | - Example-Distributed-Service-Model 258 | 259 | > Example-Distributed-Service-1 会收到请求,然后会调用 Example-Distributed-Service-2 的服务去创建一个 People,然后将这个 People 做为响应数据返回出去。 260 | 261 | #### Example-Distributed-Service-Model 262 | 263 | * People 类 264 | 265 | ```java 266 | public class People { 267 | 268 | private String name; 269 | private int age; 270 | private long birthday; 271 | private List skills; 272 | private People boss; 273 | 274 | public People(String name, int age, long birthday, List skills, People boss) { 275 | this.name = name; 276 | this.age = age; 277 | this.birthday = birthday; 278 | this.skills = skills; 279 | this.boss = boss; 280 | } 281 | 282 | } 283 | ``` 284 | 285 | #### Example-Distributed-Service-1 286 | ##### example-service-1-api 287 | 288 | * 接口定义 289 | 290 | ```java 291 | @BindURL("/service1") 292 | public interface Service1 { 293 | 294 | @Post 295 | @AllDefined 296 | ResponseEntity createPeople(String name, int age, long birthday, List skills, People boss); 297 | 298 | } 299 | ``` 300 | 301 | ##### example-service-1-main 302 | 303 | * 接口实现 304 | 305 | ```java 306 | @Service 307 | public class Service1Impl implements Service1 { 308 | 309 | @Override 310 | public ResponseEntity createPeople(String name, int age, long birthday, List skills, People boss) { 311 | Service2 service2 = EasyRestServiceLookup.lookup(Service2.class); 312 | return ResponseEntity.buildOkResponse(service2.getPeople(name, age, birthday, skills, boss)); 313 | } 314 | 315 | } 316 | ``` 317 | 318 | > EasyRestServiceLookup 有一个静态方法 lookup. 你能使用这个函数获得任何交给 EasyRest,或者spring 的bean实例,包括在其他服务器上的实例,你都能直接调用。 319 | 320 | * 主函数 321 | 322 | ```java 323 | public class Startup { 324 | 325 | private static String systemName = "example-service-1"; 326 | 327 | public static void main(String[] args) throws IOException { 328 | EasyRestDistributedServiceBind.loadConfiguration(Startup.class.getClassLoader().getResourceAsStream("services-mapping-01.json")); 329 | EasyRest easyRest = new EasyRest("classpath:MyExampleApplicationContext-01.xml"); 330 | easyRest.startup(systemName, new NettyInit(8001)); 331 | } 332 | 333 | } 334 | ``` 335 | 336 | > EasyRestDistributedServiceBind.loadConfiguration(Startup.class.getClassLoader().getResourceAsStream("services-mapping-01.json")); 将会为框架载入服务映射的关系配置文件。 337 | 338 | * akka 配置文件: application.conf 339 | 340 | ```java 341 | akka { 342 | actor { 343 | provider = "akka.remote.RemoteActorRefProvider" 344 | } 345 | remote { 346 | transport = "akka.remote.netty.NettyRemoteTransport" 347 | netty { 348 | tcp { 349 | hostname = "127.0.0.1" 350 | port = 2551 351 | } 352 | } 353 | } 354 | } 355 | ``` 356 | 357 | > Akka 系统会检测到这个配置文件,然后在指定的端口监听远程请求。 358 | 359 | * 分布式服务映射关系表:(services-mapping-01.json) 360 | 361 | ```json 362 | { 363 | "self": { 364 | "akkaSystemName": "example-service-1", 365 | "host": "127.0.0.1", 366 | "port": "2551" 367 | }, 368 | "services" : [ 369 | { 370 | "akkaSystemName": "example-service-1", 371 | "host": "127.0.0.1", 372 | "port": "2551" 373 | }, 374 | { 375 | "akkaSystemName": "example-service-2", 376 | "host": "127.0.0.1", 377 | "port": "2552" 378 | } 379 | ] 380 | } 381 | ``` 382 | 383 | > 服务映射关系表只需要2个字段: 384 | > Self 记录本地的服务器信息. 385 | > Services 是一个数组,记录所有的服务器信息,包括自己本身. 386 | > 387 | > 字段 akkaSystemName 的值必须和主函数中 systemName 的值一致!!! 388 | 389 | *一个基本的spring配置文件: 390 | 391 | ```xml 392 | 393 | 397 | 398 | 399 | 400 | 401 | 402 | ``` 403 | 404 | #### Example-Distributed-Service-2 405 | ##### example-service-2-api 406 | 407 | * 接口定义 408 | 409 | ```java 410 | @BindURL("/service2") 411 | public interface Service2 { 412 | 413 | @Get 414 | People getPeople(String name, int age, long birthday, List skills, People boss); 415 | 416 | } 417 | 418 | ``` 419 | 420 | ##### example-service-2-main 421 | 422 | * 接口实现 423 | 424 | ```java 425 | @Service 426 | public class Service2Impl implements Service2 { 427 | 428 | @Override 429 | public People getPeople(String name, int age, long birthday, List skills, People boss) { 430 | return new People(name, age, birthday, skills, boss); 431 | } 432 | } 433 | ``` 434 | 435 | * 主函数 436 | 437 | ```java 438 | public class Startup { 439 | 440 | private static String systemName = "example-service-2"; 441 | 442 | public static void main(String[] args) throws IOException { 443 | EasyRestDistributedServiceBind.loadConfiguration(Startup.class.getClassLoader().getResourceAsStream("services-mapping-02.json")); 444 | EasyRest easyRest = new EasyRest("classpath:MyExampleApplicationContext-02.xml"); 445 | easyRest.startup(systemName, new NettyInit(8002)); 446 | } 447 | 448 | } 449 | ``` 450 | 451 | * akka 配置文件: application.conf 452 | 453 | ```java 454 | akka { 455 | actor { 456 | provider = "akka.remote.RemoteActorRefProvider" 457 | } 458 | remote { 459 | transport = "akka.remote.netty.NettyRemoteTransport" 460 | netty { 461 | tcp { 462 | hostname = "127.0.0.1" 463 | port = 2552 464 | } 465 | } 466 | } 467 | } 468 | ``` 469 | 470 | * 分布式服务映射表:(services-mapping-02.json) 471 | 472 | ```json 473 | { 474 | "self": { 475 | "akkaSystemName": "example-service-2", 476 | "host": "127.0.0.1", 477 | "port": "2552" 478 | }, 479 | "services" : [ 480 | { 481 | "akkaSystemName": "example-service-1", 482 | "host": "127.0.0.1", 483 | "port": "2551" 484 | }, 485 | { 486 | "akkaSystemName": "example-service-2", 487 | "host": "127.0.0.1", 488 | "port": "2552" 489 | } 490 | ] 491 | } 492 | ``` 493 | 494 | * 一个基本的spring配置文件: 495 | 496 | ```xml 497 | 498 | 502 | 503 | 504 | 505 | 506 | 507 | ``` 508 | *** 509 | 510 | #### 启动 Service 1 和 Service 2. 511 | 512 | ##### 当你在两边的控制台分别看到如下的日志: 513 | 514 | ```java 515 | [example-service-1-akka.actor.default-dispatcher-5] INFO com.easyrest.utils.LogUtils - From com.easyrest.actors.remote.RemoteServiceExchangeActor: Service mapping init success. 516 | [example-service-1-akka.actor.default-dispatcher-5] INFO com.easyrest.utils.LogUtils - example-service-2 is running on the port 8001. 517 | ``` 518 | 519 | ```java 520 | [example-service-2-akka.actor.default-dispatcher-3] INFO com.easyrest.utils.LogUtils - From com.easyrest.actors.remote.RemoteServiceExchangeActor: Service mapping init success. 521 | [example-service-2-akka.actor.default-dispatcher-3] INFO com.easyrest.utils.LogUtils - example-service-2 is running on the port 8002. 522 | ``` 523 | 524 | #### 这表示两个service现在已经就绪了! 525 | 526 | ##### 现在我们将通过rest call调用service1. 527 | 528 | > http://127.0.0.1:8001/service1/createPeople 529 | > Content-Type:application/json 530 | > Body: 531 | > {"name":"Louie", "age":18, "birthday":763401600, "skills":["java", "netty", "akka", "spring"], "boss":{"name":"Louie_B", "age":18, "birthday":763401600}} 532 | 533 | ##### 收到的响应内容: 534 | 535 | ```java 536 | { 537 | "code": "1", 538 | "data": { 539 | "name": "Louie", 540 | "age": 18, 541 | "birthday": 763401600, 542 | "skills": [ 543 | "java", 544 | "netty", 545 | "akka", 546 | "spring" 547 | ], 548 | "boss": { 549 | "name": "Louie_B", 550 | "age": 18, 551 | "birthday": 763401600 552 | } 553 | } 554 | } 555 | ``` 556 | 557 | ### That's work! 558 | 559 | *** 560 | ##### 持续跟新... 561 | 562 | ##### TODO 563 | 564 | * 支持分布式回调函数 -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | EasyRest 8 | EasyRest-NAS 9 | 0.0.1-SNAPSHOT 10 | 11 | 12 | UTF-8 13 | UTF-8 14 | 15 | 16 | 17 | EasyRest 18 | Example 19 | 20 | 21 | 22 | 23 | 24 | org.apache.maven.plugins 25 | maven-compiler-plugin 26 | 2.0.2 27 | 28 | 1.8 29 | 1.8 30 | ${project.build.sourceEncoding} 31 | 32 | 33 | 34 | 35 | 36 | --------------------------------------------------------------------------------