demoEventService;
+
+ @Override
+ public Order createOrder(Order order)
+ {
+ save(order);
+ raiseCreateOrderEvent(order);
+
+ return order;
+ }
+
+ private void raiseCreateOrderEvent(Order order)
+ {
+ DemoEvent event = new DemoEvent(order.getId(), order.getRegionId());
+
+ event.setDomainName(AppConfig.DOMAIN_NAME);
+ event.setEventName(AppConfig.CREATE_ORDER_EVENT_NAME);
+ event.setExchange(AppConfig.REGION_EXCHANGES[event.getRegionId()]);
+ event.setRoutingKey(AppConfig.CREATE_ORDER_ROUTING_KEY);
+ event.setMsg(JSONObject.toJSONString(order));
+
+ demoEventService.save(event);
+ }
+
+}
diff --git a/hp-demo/hp-demo-mq-producer/src/main/resources/application.yml b/hp-demo/hp-demo-mq-producer/src/main/resources/application.yml
new file mode 100644
index 0000000..14ef671
--- /dev/null
+++ b/hp-demo/hp-demo-mq-producer/src/main/resources/application.yml
@@ -0,0 +1 @@
+## ---------------------------- Environment-independent application private configurations ---------------------------- ##
diff --git a/hp-demo/hp-demo-mq-producer/src/main/resources/bootstrap.yml b/hp-demo/hp-demo-mq-producer/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..558370a
--- /dev/null
+++ b/hp-demo/hp-demo-mq-producer/src/main/resources/bootstrap.yml
@@ -0,0 +1,61 @@
+# app
+hp.soa.web:
+ app:
+ id: "0010100011"
+ name: ${project.artifactId}
+ version: ${project.version}
+ organization: HP-Socket
+ owner: Kingfisher
+ component-scan:
+ base-package: ${project.groupId}
+ access-verification:
+ enabled: true
+ DefaultAccessPolicy: maybe_login
+
+# logging
+logging.config: classpath:log4j2-kafka.xml
+
+spring.cloud.nacos.config:
+ #server-addr: 192.168.56.23:8848
+ #username: nacos
+ #password: 123456
+ #namespace: DEV
+ group: DEMO_GROUP
+ name: ${hp.soa.web.app.name}
+ file-extension: yml
+ refresh-enabled: true
+ shared-configs:
+ - group: GLOBAL_GROUP
+ data-id: hp-soa-web.yml
+ refresh: true
+ - group: GLOBAL_GROUP
+ data-id: spring-boot.yml
+ refresh: true
+ - group: GLOBAL_GROUP
+ data-id: spring-task.yml
+ refresh: true
+ - group: GLOBAL_GROUP
+ data-id: rabbitmq.yml
+ refresh: true
+ - group: GLOBAL_GROUP
+ data-id: dubbo.yml
+ refresh: true
+ - group: GLOBAL_GROUP
+ data-id: mysql.yml
+ refresh: true
+ - group: GLOBAL_GROUP
+ data-id: redis.yml
+ refresh: true
+
+# dubbo
+dubbo.protocols:
+ #dubbo:
+ # name: dubbo
+ # port: 5011
+ tri:
+ name: tri
+ port: 6011
+
+# server
+server.port: 9011
+
diff --git a/hp-demo/hp-demo-mq-producer/src/main/resources/log4j2-kafka.xml b/hp-demo/hp-demo-mq-producer/src/main/resources/log4j2-kafka.xml
new file mode 100644
index 0000000..3116311
--- /dev/null
+++ b/hp-demo/hp-demo-mq-producer/src/main/resources/log4j2-kafka.xml
@@ -0,0 +1,139 @@
+
+
+
+
+ ${project.groupId}
+ com\.github\.hpsocket\.demo\..*\.dao\..+
+ ${sys:log4j.include.location:-true}
+ ${sys:log4j.log.level:-DEBUG}
+ ${sys:log4j.kafka.bootstrap.servers:-192.168.56.23:9092}
+ ${sys:log4j.kafka.sasl.jaas.config:-}
+ ${sys:log4j.kafka.topic:-hp-soa}
+ ${sys:log4j.kafka.logType:-hp-soa}
+ true
+ true
+ ${sys:log4j.logfile.path:-/data/logs/access}/${project.artifactId}
+ 100 MB
+ 10
+ ${sys:log4j.logfile.path:-/data/logs/access}/${project.artifactId}/${date:yyyy-MM}
+ %d{yyyy-MM-dd}-%i.log.gz
+ org.springframework.security.web.ObservationFilterChainDecorator,org.apache.catalina,org.apache.coyote,org.apache.tomcat,org.hibernate,org.apache.el,org.apache.cxf,org.junit,junit.framework,org.jboss,org.h2,org.eclipse,org.richfaces,java.lang.reflect,java.base/java.lang.reflect,jdk.internal.reflect,java.base/jdk.internal.reflect,com.sun,javax.servlet,jakarta.servlet
+ %d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%t] %C{1.1.1.*}#%M\(L:%L\) -> %m%xEx{filters(${logfile.stacktrace.filters})}%n
+ classpath:log4j2-default-template.json
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${kafka.bootstrap.servers}
+ ${kafka.sasl.jaas.config}
+
+
+
+
+
+
+
+
+ ${kafka.bootstrap.servers}
+ ${kafka.sasl.jaas.config}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hp-demo/hp-demo-mq-producer/src/main/resources/log4j2.xml b/hp-demo/hp-demo-mq-producer/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..9b9eb32
--- /dev/null
+++ b/hp-demo/hp-demo-mq-producer/src/main/resources/log4j2.xml
@@ -0,0 +1,100 @@
+
+
+
+
+ ${project.groupId}
+ com\.github\.hpsocket\.demo\..*\.dao\..+
+ ${sys:log4j.include.location:-true}
+ ${sys:log4j.log.level:-DEBUG}
+ ${sys:log4j.logfile.path:-/data/logs/access}/${project.artifactId}
+ 100 MB
+ 10
+ ${sys:log4j.logfile.path:-/data/logs/access}/${project.artifactId}/${date:yyyy-MM}
+ %d{yyyy-MM-dd}-%i.log.gz
+ org.springframework.security.web.ObservationFilterChainDecorator,org.apache.catalina,org.apache.coyote,org.apache.tomcat,org.hibernate,org.apache.el,org.apache.cxf,org.junit,junit.framework,org.jboss,org.h2,org.eclipse,org.richfaces,java.lang.reflect,java.base/java.lang.reflect,jdk.internal.reflect,java.base/jdk.internal.reflect,com.sun,javax.servlet,jakarta.servlet
+ %d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%t] %C{1.1.1.*}#%M\(L:%L\) -> %m%xEx{filters(${logfile.stacktrace.filters})}%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hp-demo/pom.xml b/hp-demo/pom.xml
new file mode 100644
index 0000000..95e362f
--- /dev/null
+++ b/hp-demo/pom.xml
@@ -0,0 +1,84 @@
+
+ 4.0.0
+
+ io.github.hpsocket
+ hp-soa-parent
+ ${revision}
+
+ io.github.hpsocket.demo
+ hp-demo
+ ${project.artifactId}
+ pom
+
+
+
+
+
+ hp-demo-infra-basic
+ hp-demo-infra-nacos
+ hp-demo-infra-mysql
+ hp-demo-infra-sentinel
+ hp-demo-infra-skywalking
+ hp-demo-bff-basic
+ hp-demo-bff-nacos
+ hp-demo-bff-mysql
+ hp-demo-bff-sentinel
+ hp-demo-bff-skywalking
+ hp-demo-job
+ hp-demo-mq-producer
+ hp-demo-mq-consumer
+
+
+
+
+
+ io.github.hpsocket
+ hp-soa-dependencies
+ ${project.parent.version}
+ pom
+ import
+
+
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+
+ org.apache.maven.plugins
+ maven-install-plugin
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+
+ true
+
+
+
+
+
diff --git a/hp-soa-dependencies/.gitignore b/hp-soa-dependencies/.gitignore
new file mode 100644
index 0000000..1ee8e9f
--- /dev/null
+++ b/hp-soa-dependencies/.gitignore
@@ -0,0 +1,5 @@
+.classpath
+.project
+.flattened-pom.xml
+.settings
+/target
diff --git a/hp-soa-dependencies/pom.xml b/hp-soa-dependencies/pom.xml
new file mode 100644
index 0000000..3e04e9f
--- /dev/null
+++ b/hp-soa-dependencies/pom.xml
@@ -0,0 +1,1398 @@
+
+
+ 4.0.0
+
+ io.github.hpsocket
+ hp-soa-parent
+ ${revision}
+
+ hp-soa-dependencies
+ ${project.artifactId}
+ pom
+ hp-soa: a fully functional, easy-to-use, and highly scalable microservice framework
+ https://github.com/ldcsaa/hp-soa
+
+
+ 2.2.4
+ 0.2.12
+ 3.2.5
+ 4.1.97.Final
+ 3.9.0
+ 0.11
+ 5.5.0
+ 3.0.4-jdk17
+ 2.4.0
+ 1.8.6
+
+
+
+ 6.0.11
+ 3.1.3
+ 2022.0.4
+ 2022.0.0.0
+ 2.5.2.RELEASE
+ 1.1.1.RELEASE
+ 3.1.3
+ 3.1.3
+ 3.1.3
+ 3.1.3
+ 4.1.3
+ 3.0.8
+ 3.0.8
+ 3.0.8
+ 3.0.11
+ 3.5.1
+ 1.2.19
+ 4.4.4
+ 6.2.6.RELEASE
+ 3.23.4
+ 5.18.0
+ 0.12.0
+ 3.12.14
+ 8.1.0
+ 3.0.2
+ 3.5.13
+ 3.0.2
+ 3.5.3.2
+ 4.1.3
+ 5.4.0
+ 5.2.1
+ 3.10.8
+
+ 2.13.0
+ 3.9.0
+ 2.6
+ 3.13.0
+ 1.9.4
+ 3.2.2
+ 4.4
+ 1.16.0
+ 1.5.4.0
+ 2.11.1
+ 3.1
+
+ 6.0.0
+ 3.0.2
+ 5.0.1
+ 2.1.1
+ 2.1.2
+ 4.0.0
+ 3.1.0
+
+ 8.0.1
+ 4.0.1
+ 3.0.1-b06
+ 3.0.1-b12
+ 2.0.1.Final
+ 1.6.2
+
+ 2.0.9
+ 2.20.0
+ 3.4.4
+ 8.16.0
+ 4.13.2
+ 5.10.0
+
+ 2.0.40
+ 2.0.40
+ 3.24.3
+ 2.3.2
+ 4.5.14
+ 5.2.1
+ 1.4.1
+ 1.4.20
+ 8.0.1.Final
+ 2.3
+ 2.3.32
+ 3.15.8.RELEASE
+
+ 4.1.0
+ 2.10.1
+ 2.15.2
+ 4.0.66
+ 3.5.2
+ 2.7.5
+ 4.11.0
+ 32.1.2-jre
+
+ 1.16.1
+ 4.12.1
+
+ 5.2.3
+ 3.3.2
+ 2.12.2
+ 5.3.3
+ 2.2.0
+
+ 5.5.0
+ 5.8.21
+ 0.11.5
+
+ 1.7.1
+
+ 0.2.2
+ 1.11.3
+
+ 5.16.0
+ 2.16.4
+
+
+
+
+
+ io.github.hpsocket
+ hp-soa-framework-core
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-framework-web
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-web
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-task
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-nacos
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-sentinel
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-skywalking
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-data-redis
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-data-mysql
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-job-xxljob
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-job-exclusive
+ ${project.parent.version}
+
+
+ io.github.hpsocket
+ hp-soa-starter-rabbitmq
+ ${project.parent.version}
+
+
+
+ org.apache.dubbo
+ dubbo
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-qos
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-starter
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-observability-starter
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-tracing-otel-zipkin-starter
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-spring-boot-actuator
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-registry-nacos
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-configcenter-nacos
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-metadata-report-nacos
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-registry-zookeeper
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-configcenter-zookeeper
+ ${dubbo.version}
+
+
+ org.apache.dubbo
+ dubbo-metadata-report-zookeeper
+ ${dubbo.version}
+
+
+
+ com.alibaba.nacos
+ nacos-client
+ ${nacos-client.version}
+
+
+
+ com.alibaba.boot
+ nacos-config-spring-boot-starter
+ ${nacos-config-spring-boot-starter.version}
+
+
+
+ org.apache.curator
+ curator-recipes
+ ${curator.version}
+
+
+ org.apache.curator
+ curator-framework
+ ${curator.version}
+
+
+ org.apache.curator
+ curator-client
+ ${curator.version}
+
+
+
+ org.apache.zookeeper
+ zookeeper
+ ${zookeeper.version}
+
+
+ com.101tec
+ zkclient
+ ${zkclient.version}
+
+
+
+ io.netty
+ netty-all
+ ${netty.version}
+
+
+
+ jakarta.validation
+ jakarta.validation-api
+ ${jakarta.validation-api.version}
+
+
+
+ jakarta.servlet
+ jakarta.servlet-api
+ ${jakarta.servlet-api.version}
+
+
+
+ jakarta.el
+ jakarta.el-api
+ ${jakarta.el-api.version}
+
+
+
+ jakarta.annotation
+ jakarta.annotation-api
+ ${jakarta.annotation-api.version}
+
+
+
+ jakarta.activation
+ jakarta.activation-api
+ ${jakarta.activation-api.version}
+
+
+
+ jakarta.persistence
+ jakarta.persistence-api
+ ${jakarta.persistence-api.version}
+
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ ${jakarta.xml.bind-api.version}
+
+
+
+ javax
+ javaee-api
+ ${javax-javaee-api.version}
+
+
+ javax.servlet
+ javax.servlet-api
+ ${javax.servlet-api.version}
+
+
+ javax.el
+ javax.el-api
+ ${javax-el-api.version}
+
+
+ org.glassfish
+ javax.el
+ ${javax-el.version}
+
+
+
+ javax.validation
+ validation-api
+ ${javax-validation-api.version}
+
+
+
+ javax.mail
+ mail
+ ${javax-mail.version}
+
+
+
+ org.hibernate.validator
+ hibernate-validator
+ ${hibernate-validator.version}
+
+
+
+ com.google.code.gson
+ gson
+ ${gson.version}
+
+
+
+ org.ehcache
+ ehcache
+ ${ehcache.version}
+
+
+
+ com.esotericsoftware
+ kryo
+ ${kryo.version}
+
+
+
+ de.ruedigermoeller
+ fst
+ ${fst.version}
+
+
+
+ com.xuxueli
+ xxl-job-core
+ ${xxl-job.version}
+
+
+
+ com.alibaba.csp
+ sentinel-core
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-annotation-aspectj
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-datasource-nacos
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-transport-simple-http
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-datasource-extension
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-parameter-flow-control
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-apache-dubbo3-adapter
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-spring-webmvc-adapter
+ ${sentinel.version}
+
+
+ com.alibaba.csp
+ sentinel-web-servlet
+ ${sentinel.version}
+
+
+
+
+
+ com.google.zxing
+ javase
+ ${zxing-javase.version}
+
+
+
+ com.squareup.okhttp
+ okhttp
+ ${okhttp2.version}
+
+
+ com.squareup.okhttp3
+ okhttp
+ ${okhttp3.version}
+
+
+
+ org.apache.velocity
+ velocity-engine-core
+ ${velocity.version}
+
+
+ org.freemarker
+ freemarker
+ ${freemarker.version}
+
+
+ com.ibeetl
+ beetl
+ ${beetl.version}
+
+
+
+ com.rabbitmq
+ amqp-client
+ ${amqp-client.version}
+
+
+ org.springframework.amqp
+ spring-rabbit
+ ${spring-rabbit.version}
+
+
+ com.rabbitmq
+ stream-client
+ ${stream-client.version}
+
+
+ org.springframework.amqp
+ spring-rabbit-stream
+ ${spring-rabbit-stream.version}
+
+
+
+
+ org.springframework.data
+ spring-data-commons
+ ${spring-data.version}
+
+
+ org.springframework.amqp
+ spring-amqp
+ ${spring-amqp.version}
+
+
+ org.springframework.data
+ spring-data-redis
+ ${spring-data-redis.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+ ${spring-boot-starter-data-redis.version}
+
+
+
+ org.springframework.data
+ spring-data-mongodb
+ ${spring-data-mongodb.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+ ${spring-boot-starter-data-mongodb.version}
+
+
+
+ org.springframework.kafka
+ spring-kafka
+ ${spring-kafka.version}
+
+
+ org.apache.kafka
+ kafka-clients
+ ${kafka-clients.version}
+
+
+ org.apache.kafka
+ kafka-log4j-appender
+ ${kafka-clients.version}
+
+
+
+ org.mybatis
+ mybatis
+ ${mybatis.version}
+
+
+ org.mybatis
+ mybatis-spring
+ ${mybatis-spring.version}
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ ${mybatis-spring-boot-starter.version}
+
+
+
+ com.baomidou
+ mybatis-plus-core
+ ${mybatis-plus.version}
+
+
+ com.baomidou
+ mybatis-plus-annotation
+ ${mybatis-plus.version}
+
+
+ com.baomidou
+ mybatis-plus-generator
+ ${mybatis-plus-generator.version}
+
+
+ com.baomidou
+ mybatis-plus-extension
+ ${mybatis-plus.version}
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatis-plus.version}
+
+
+
+ com.baomidou
+ dynamic-datasource-spring-boot3-starter
+ ${dynamic-datasource-spring-boot3-starter.version}
+
+
+
+ org.apache.shardingsphere
+ shardingsphere-jdbc-core
+ ${shardingsphere-jdbc-core.version}
+
+
+ org.apache.shardingsphere
+ shardingsphere-jdbc-core-spring-boot-starter
+ ${shardingsphere-jdbc-core-spring-boot-starter.version}
+
+
+
+ org.springframework.security.oauth
+ spring-security-oauth2
+ ${spring-security-oauth.version}
+
+
+ org.springframework.security
+ spring-security-jwt
+ ${spring-security-jwt.version}
+
+
+
+ com.mysql
+ mysql-connector-j
+ ${mysql-connector-j.version}
+
+
+
+ org.mongodb
+ mongo-java-driver
+ ${mongo-java-driver.version}
+
+
+
+ redis.clients
+ jedis
+ ${jedis.version}
+
+
+ io.lettuce
+ lettuce-core
+ ${lettuce.version}
+
+
+ org.redisson
+ redisson
+ ${redisson.version}
+
+
+ org.redisson
+ redisson-spring-boot-starter
+ ${redisson.version}
+
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
+
+
+ org.apache.logging.log4j
+ log4j-core
+ ${log4j.version}
+
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+ ${log4j.version}
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+
+
+
+ org.apache.logging.log4j
+ log4j-layout-template-json
+ ${log4j.version}
+
+
+
+ org.apache.logging.log4j
+ log4j-spring-boot
+ ${log4j.version}
+
+
+
+ com.lmax
+ disruptor
+ ${disruptor.version}
+
+
+
+ org.apache.skywalking
+ apm-toolkit-log4j-2.x
+ ${skywalking.apm-toolkit.version}
+
+
+ org.apache.skywalking
+ apm-toolkit-trace
+ ${skywalking.apm-toolkit.version}
+
+
+ org.apache.skywalking
+ apm-toolkit-micrometer-registry
+ ${skywalking.apm-toolkit.version}
+
+
+ org.apache.skywalking
+ apm-toolkit-micrometer-1.10
+ ${skywalking.apm-toolkit.version}
+
+
+
+ org.quartz-scheduler
+ quartz
+ ${quartz.version}
+
+
+
+ com.thoughtworks.xstream
+ xstream
+ ${xstream.version}
+
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+
+ commons-net
+ commons-net
+ ${commons-net.version}
+
+
+
+ commons-lang
+ commons-lang
+ ${commons-lang.version}
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+ commons-beanutils
+ commons-beanutils
+ ${commons-beanutils.version}
+
+
+
+ commons-collections
+ commons-collections
+ ${commons-collections.version}
+
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+
+ org.apache.commons
+ commons-pool
+ ${commons-pool.version}
+
+
+
+ org.apache.commons
+ commons-pool2
+ ${commons-pool2.version}
+
+
+
+ commons-httpclient
+ commons-httpclient
+ ${commons-httpclient.version}
+
+
+
+ org.jsoup
+ jsoup
+ ${jsoup.version}
+
+
+
+ com.maxmind.geoip2
+ geoip2
+ ${geoip2.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ ${jackson.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ ${jackson.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-dataformat-xaml
+ ${jackson.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-dataformat-yaml
+ ${jackson.version}
+
+
+
+ org.codehaus.jackson
+ jackson-all
+ ${jackson-all.version}
+
+
+
+ com.alibaba
+ fastjson
+ ${fastjson.version}
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ ${fastjson2.version}
+
+
+ com.alibaba.fastjson2
+ fastjson2-extension-spring6
+ ${fastjson2.version}
+
+
+
+ com.google.protobuf
+ protobuf-java
+ ${protobuf-java.version}
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ ${httpclient.version}
+
+
+ org.apache.httpcomponents
+ httpmime
+ ${httpclient.version}
+
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+ ${httpclient5.version}
+
+
+
+ com.blueconic
+ browscap-java
+ ${browscap-java.version}
+
+
+
+ com.alibaba
+ druid
+ ${druid.version}
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ ${druid.version}
+
+
+ com.alibaba
+ druid-spring-boot-3-starter
+ ${druid.version}
+
+
+
+ com.caucho
+ hessian
+ ${hessian.version}
+
+
+
+ org.springframework
+ spring-core
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-test
+ ${spring.version}
+ test
+
+
+
+ org.springframework
+ spring-oxm
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-orm
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-aspects
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-messaging
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-instrument
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-jdbc
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-context-support
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-context
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-aop
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-beans
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-expression
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-web
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-webmvc
+ ${spring.version}
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+ com.alibaba.cloud
+ spring-cloud-alibaba-dependencies
+ ${spring-cloud-alibaba.version}
+ pom
+ import
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit5.version}
+ test
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-core
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-http
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-crypto
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-json
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-log
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-extra
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-cache
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-setting
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-db
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-captcha
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-system
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-jwt
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-poi
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-cron
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-bom
+ ${hutool.version}
+ pom
+
+
+ cn.hutool
+ hutool-script
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-socket
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-dfa
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-bloomFilter
+ ${hutool.version}
+
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ ${jjwt.version}
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+ org.projectlombok
+ lombok-mapstruct-binding
+ ${lombok-mapstruct-binding.version}
+
+
+
+ org.mapstruct
+ mapstruct
+ ${mapstruct.version}
+
+
+ org.mapstruct
+ mapstruct-jdk8
+ ${mapstruct.version}
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+
+ org.apache.poi
+ poi-ooxml
+ ${poi.version}
+
+
+ stax-api
+ stax
+
+
+ commons-codec
+ commons-codec
+
+
+
+
+
+ com.alibaba
+ easyexcel
+ ${easyexcel.version}
+
+
+
+ xerces
+ xercesImpl
+ ${xerces.version}
+
+
+
+ com.googlecode.aviator
+ aviator
+ ${aviator.version}
+
+
+
+ org.seleniumhq.selenium
+ selenium-java
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-api
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-chrome-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-edge-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-firefox-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-ie-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-opera-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-remote-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-safari-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-support
+ ${selenium.version}
+
+
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ ${springdoc-openapi.version}
+
+
+
+
+ io.seata
+ seata-all
+ ${seata.version}
+
+
+ io.seata
+ seata-spring-boot-starter
+ ${seata.version}
+
+
+
+
+ io.github.mweirauch
+ micrometer-jvm-extras
+ ${micrometer-jvm-extras.version}
+
+
+ io.micrometer
+ micrometer-core
+ ${micrometer-core.version}
+
+
+
+
+ io.zipkin.brave
+ brave
+ ${zipkin-brave.version}
+
+
+ io.zipkin.brave
+ brave-context-slf4j
+ ${zipkin-brave.version}
+
+
+ io.zipkin.brave
+ brave-spring-beans
+ ${zipkin-brave.version}
+
+
+ io.zipkin.brave
+ brave-instrumentation-spring-rabbit
+ ${zipkin-brave.version}
+
+
+ io.zipkin.brave
+ brave-instrumentation-http
+ ${zipkin-brave.version}
+
+
+ io.zipkin.brave
+ brave-instrumentation-servlet
+ ${zipkin-brave.version}
+
+
+ io.zipkin.brave
+ brave-instrumentation-mysql
+ ${zipkin-brave.version}
+
+
+ io.zipkin.reporter2
+ zipkin-sender-urlconnection
+ ${zipkin-reporter.version}
+
+
+ io.zipkin.reporter2
+ zipkin-sender-okhttp3
+ ${zipkin-reporter.version}
+
+
+ io.zipkin.reporter2
+ zipkin-sender-amqp-client
+ ${zipkin-reporter.version}
+
+
+ io.zipkin.reporter2
+ zipkin-reporter-spring-beans
+ ${zipkin-reporter.version}
+
+
+
+
+
diff --git a/hp-soa-framework/.gitignore b/hp-soa-framework/.gitignore
new file mode 100644
index 0000000..1ee8e9f
--- /dev/null
+++ b/hp-soa-framework/.gitignore
@@ -0,0 +1,5 @@
+.classpath
+.project
+.flattened-pom.xml
+.settings
+/target
diff --git a/hp-soa-framework/hp-soa-framework-core/.gitignore b/hp-soa-framework/hp-soa-framework-core/.gitignore
new file mode 100644
index 0000000..1ee8e9f
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/.gitignore
@@ -0,0 +1,5 @@
+.classpath
+.project
+.flattened-pom.xml
+.settings
+/target
diff --git a/hp-soa-framework/hp-soa-framework-core/pom.xml b/hp-soa-framework/hp-soa-framework-core/pom.xml
new file mode 100644
index 0000000..a0357fc
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+ io.github.hpsocket
+ hp-soa-framework
+ ${revision}
+
+ hp-soa-framework-core
+ ${project.artifactId}
+ jar
+ hp-soa: a fully functional, easy-to-use, and highly scalable microservice framework
+ https://github.com/ldcsaa/hp-soa
+
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ org.apache.logging.log4j
+ log4j-core
+
+
+
+ org.apache.logging.log4j
+ log4j-slf4j2-impl
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+
+
+
+ org.apache.logging.log4j
+ log4j-layout-template-json
+
+
+
+ com.lmax
+ disruptor
+
+
+
+ com.google.guava
+ guava
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+ cn.hutool
+ hutool-core
+
+
+
+ org.projectlombok
+ lombok
+
+
+ org.projectlombok
+ lombok-mapstruct-binding
+
+
+
+ org.mapstruct
+ mapstruct
+
+
+ org.mapstruct
+ mapstruct-processor
+
+
+
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/exception/ServiceException.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/exception/ServiceException.java
new file mode 100644
index 0000000..7f6518d
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/exception/ServiceException.java
@@ -0,0 +1,281 @@
+package io.github.hpsocket.soa.framework.core.exception;
+
+import org.slf4j.Logger;
+
+/** HP-SOA 统一异常 */
+@SuppressWarnings("serial")
+public class ServiceException extends RuntimeException
+{
+ /** 成功 */
+ public static final int OK = 0;
+ /** 已接受 */
+ public static final int ACCEPTED = 202;
+ /** 空内容 */
+ public static final int NO_CONTENT = 204;
+ /** 部分成功 */
+ public static final int PARTIAL_OK = 206;
+ /** 非法请求 */
+ public static final int BAD_REQUEST = 400;
+ /** 目标不存在 */
+ public static final int NOT_EXIST = 404;
+ /** 参数校验失败 */
+ public static final int PARAM_VERIFY_ERROR = 409;
+ /** 服务器内部错误 */
+ public static final int GENERAL_ERROR = 500;
+ /** 参数验证错误 */
+ public static final int PARAM_VALIDATION_ERROR = 501;
+ /** 接口未实现 */
+ public static final int NOT_IMPLEMENTED = 502;
+ /** 频次超限 */
+ public static final int FREQUENCY_LIMIT_ERROR = 503;
+ /** 拒绝访问 */
+ public static final int FORBID_ERROR = 504;
+ /** 请求参数非法 */
+ public static final int PARAMS_ERROR = 505;
+ /** 重复请求 */
+ public static final int REPEATED_REQ_ERROR = 506;
+ /** 访问被限流 */
+ public static final int TRAFFIC_LIMIT_ERROR = 507;
+ /** 接口不支持 */
+ public static final int NOT_SUPPORTED = 508;
+ /** 禁止更新 */
+ public static final int FORBID_UPDATE_ERROR = 509;
+ /** 调用超时 */
+ public static final int TIMEOUT_ERROR = 511;
+ /** APP CODE 不存在 */
+ public static final int APPCODE_NOT_EXIST_ERROR = 601;
+ /** APP CODE 已存在 */
+ public static final int APPCODE_EXIST_ERROR = 602;
+ /** 用户验证错误 */
+ public static final int AUTHEN_ERROR = 701;
+ /** 用户授权错误 */
+ public static final int AUTHOR_ERROR = 702;
+ /** 网络错误 */
+ public static final int NETWORK_ERROR = 801;
+ /** 外部服务调用失败 */
+ public static final int OUTER_API_CALL_FAIL = 802;
+ /** 内部服务调用失败 */
+ public static final int INNER_API_CALL_FAIL = 803;
+ /** 签名验证失败 */
+ public static final int SIGN_VERIFY_ERROR = 901;
+ /** 登录已失效 */
+ public static final int LOGIN_INVALID = 904;
+ /** 未登录 */
+ public static final int NOT_LOGGED_IN = 907;
+
+ public static final ServiceException BAD_REQUEST_EXCEPTION = new ServiceException("非法请求", BAD_REQUEST);
+ public static final ServiceException NOT_EXIST_EXCEPTION = new ServiceException("目标不存在", NOT_EXIST);
+ public static final ServiceException PARAM_VERIFY_EXCEPTION = new ServiceException("参数校验失败", PARAM_VERIFY_ERROR);
+ public static final ServiceException GENERAL_EXCEPTION = new ServiceException("服务器内部错误", GENERAL_ERROR);
+ public static final ServiceException PARAM_VALIDATION_EXCEPTION = new ServiceException("参数验证错误", PARAM_VALIDATION_ERROR);
+ public static final ServiceException NOT_IMPLEMENTED_EXCEPTION = new ServiceException("接口未实现", NOT_IMPLEMENTED);
+ public static final ServiceException NOT_SUPPORTED_EXCEPTION = new ServiceException("接口不支持", NOT_SUPPORTED);
+ public static final ServiceException FORBID_SERVICE_EXCEPTION = new ServiceException("禁止更新", FORBID_UPDATE_ERROR);
+ public static final ServiceException APPCODE_NOT_EXIST_EXCEPTION= new ServiceException("应用程序编号不存在", APPCODE_NOT_EXIST_ERROR);
+ public static final ServiceException APPCODE_EXIST_EXCEPTION = new ServiceException("应用程序编号已存在", APPCODE_EXIST_ERROR);
+ public static final ServiceException AUTHEN_EXCEPTION = new ServiceException("用户认证失败", AUTHEN_ERROR);
+ public static final ServiceException AUTHOR_EXCEPTION = new ServiceException("授权验证失败", AUTHOR_ERROR);
+ public static final ServiceException NETWORK_EXCEPTION = new ServiceException("网络错误", NETWORK_ERROR);
+ public static final ServiceException PARAMS_EXCEPTION = new ServiceException("请求参数非法", PARAMS_ERROR);
+ public static final ServiceException REPEATED_REQ_EXCEPTION = new ServiceException("请勿重复请求", REPEATED_REQ_ERROR);
+ public static final ServiceException TIMEOUT_EXCEPTION = new ServiceException("调用超时", TIMEOUT_ERROR);
+ public static final ServiceException OUTER_API_CALL_EXCEPTION = new ServiceException("外部服务调用失败", OUTER_API_CALL_FAIL);
+ public static final ServiceException INNER_API_CALL_EXCEPTION = new ServiceException("内部服务调用失败", INNER_API_CALL_FAIL);
+ public static final ServiceException SIGN_VERIFY_EXCEPTION = new ServiceException("签名验证失败", SIGN_VERIFY_ERROR);
+
+ public static final ServiceException FREQUENCY_LIMIT_EXCEPTION = new UnimportantException("系统繁忙", FREQUENCY_LIMIT_ERROR);
+ public static final ServiceException FORBID_EXCEPTION = new UnimportantException("拒绝访问", FORBID_ERROR);
+ public static final ServiceException TRAFFIC_LIMIT_EXCEPTION = new UnimportantException("系统繁忙", TRAFFIC_LIMIT_ERROR);
+ public static final ServiceException LOGIN_INVALID_EXCEPTION = new UnimportantException("登录已失效", LOGIN_INVALID);
+ public static final ServiceException NOT_LOGGED_IN_EXCEPTION = new UnimportantException("未登录", NOT_LOGGED_IN);
+
+ /** 状态码:{@linkplain ServiceException#OK OK} - 成功,其它 - 失败 */
+ private Integer statusCode;
+ /** 结果码:用于服务内部监控、统计,不暴露到调用方,{@linkplain ServiceException#OK OK} - 成功,其它 - 失败 */
+ private transient Integer resultCode;
+
+ public ServiceException()
+ {
+ }
+
+ public ServiceException(String message)
+ {
+ this(message, GENERAL_ERROR);
+ }
+
+ public ServiceException(String message, Integer statusCode)
+ {
+ this(message, statusCode, statusCode);
+ }
+
+ public ServiceException(String message, Integer statusCode, Integer resultCode)
+ {
+ super(message);
+ setStatusCode(statusCode);
+ setResultCode(resultCode);
+ }
+
+ public ServiceException(String message, Throwable cause)
+ {
+ super(message, cause);
+ if(cause instanceof ServiceException)
+ {
+ setStatusCode(((ServiceException)cause).getStatusCode());
+ setResultCode(((ServiceException)cause).getResultCode());
+ }
+ }
+
+ public ServiceException(String message, Integer statusCode, Throwable cause)
+ {
+ super(message, cause);
+ setStatusCode(statusCode);
+ setResultCode(statusCode);
+ }
+
+ public Integer getResultCode()
+ {
+ return resultCode;
+ }
+
+ public void setResultCode(Integer resultCode)
+ {
+ this.resultCode = resultCode;
+ }
+
+ public Integer getStatusCode()
+ {
+ return statusCode;
+ }
+
+ public void setStatusCode(Integer statusCode)
+ {
+ this.statusCode = statusCode;
+ }
+
+ public static final ServiceException wrapServiceException(Throwable e)
+ {
+ return wrapServiceException(GENERAL_EXCEPTION.getMessage(), GENERAL_EXCEPTION.statusCode, e);
+ }
+
+ public static final ServiceException wrapServiceException(ServiceException se, Throwable e)
+ {
+ return wrapServiceException(se.getMessage(), se.getStatusCode(), e);
+ }
+
+ public static final ServiceException wrapServiceException(String message, Integer statusCode, Throwable e)
+ {
+ if(!(e instanceof ServiceException))
+ e = new ServiceException(message, statusCode, e);
+
+ return (ServiceException)e;
+ }
+
+ public static final void throwServiceException(Throwable e)
+ {
+ throw wrapServiceException(e);
+ }
+
+ public static final void throwServiceException(Throwable e, String message)
+ {
+ throw wrapServiceException(message, GENERAL_ERROR, e);
+ }
+
+ public static final void throwServiceException(Throwable e, String format, Object... args)
+ {
+ String message = String.format(format, args);
+ throw wrapServiceException(message, GENERAL_ERROR, e);
+ }
+
+ public static final void throwServiceException(String message, Integer statusCode)
+ {
+ throw new ServiceException(message, statusCode);
+ }
+
+ public static final void throwServiceException(String message, Integer statusCode, Throwable e)
+ {
+ throw new ServiceException(message, statusCode, e);
+ }
+
+ public static final void throwServiceException(ServiceException e, Object... args)
+ {
+ throwFormattedServiceException(e, e.getMessage(), args);
+ }
+
+ public static final void throwFormattedServiceException(Integer statusCode, String format, Object... args)
+ {
+ throw wrapFormattedServiceException(statusCode, format, args);
+ }
+
+ public static final ServiceException wrapFormattedServiceException(Integer statusCode, String format, Object... args)
+ {
+ String message = String.format(format, args);
+ return new ServiceException(message, statusCode);
+ }
+
+ public static final void throwFormattedServiceException(ServiceException e, String format, Object... args)
+ {
+ throw wrapFormattedServiceException(e, format, args);
+ }
+
+ public static final ServiceException wrapFormattedServiceException(ServiceException e, String format, Object... args)
+ {
+ String message = String.format(format, args);
+ return new ServiceException(message, e.getStatusCode(), e.getCause());
+ }
+
+ public static final void throwValidateException(String message)
+ {
+ throw wrapValidateException(message);
+ }
+
+ public static final ServiceException wrapValidateException(String message)
+ {
+ return new ServiceException(message, PARAM_VALIDATION_ERROR);
+ }
+
+ public static final void throwValidateException(String format, Object... args)
+ {
+ throwFormattedServiceException(PARAM_VALIDATION_EXCEPTION, format, args);
+ }
+
+ public static final ServiceException wrapValidateException(String format, Object... args)
+ {
+ return wrapFormattedServiceException(PARAM_VALIDATION_EXCEPTION, format, args);
+ }
+
+ public static void logException(Logger logger, Throwable e)
+ {
+ if(e instanceof ServiceException)
+ logServiceException(logger, (ServiceException)e);
+ else
+ logException(logger, GENERAL_ERROR, e.getMessage(), e);
+ }
+
+ public static void logException(Logger logger, Integer code, String msg, Throwable e)
+ {
+ logServiceException(logger, new ServiceException(msg, code, e));
+ }
+
+ public static void logServiceException(Logger logger, ServiceException e)
+ {
+ logServiceException(logger, e.getMessage(), e);
+ }
+
+ public static void logServiceException(Logger logger, String msg, ServiceException e)
+ {
+ final String FORMAT = "(SERVICE EXCEPTION - SC: {}, RC: {}) -> {}";
+ final Integer statusCode = e.getStatusCode();
+ final Integer resultCode = e.getResultCode();
+
+ if(GENERAL_ERROR == statusCode)
+ logger.error(FORMAT, statusCode, resultCode, msg, e);
+ else
+ {
+ if(e instanceof UnimportantException)
+ logger.info(FORMAT, statusCode, resultCode, msg);
+ else
+ logger.warn(FORMAT, statusCode, resultCode, msg, e);
+ }
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/exception/UnimportantException.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/exception/UnimportantException.java
new file mode 100644
index 0000000..ef361a4
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/exception/UnimportantException.java
@@ -0,0 +1,39 @@
+
+package io.github.hpsocket.soa.framework.core.exception;
+
+/** HP-SOA 统一非严重异常,即使引发异常也认为调用成功
+ * {@linkplain UnimportantException#getResultCode() getResultCode()} 总是返回 {@linkplain ServiceException#OK OK}
+ * 如:用户输错密码导致登录失败,触发 {@linkplain ServiceException#LOGIN_INVALID_EXCEPTION LOGIN_INVALID_EXCEPTION},用户调用是失败的,但服务内部处理是成功的。因此监控系统也会把该请求看作成功请求
+ */
+@SuppressWarnings("serial")
+public class UnimportantException extends ServiceException
+{
+ public UnimportantException()
+ {
+ setResultCode(OK);
+ }
+
+ public UnimportantException(String message)
+ {
+ super(message);
+ setResultCode(OK);
+ }
+
+ public UnimportantException(String message, Integer statusCode)
+ {
+ super(message, statusCode);
+ setResultCode(OK);
+ }
+
+ public UnimportantException(String message, Throwable cause)
+ {
+ super(message, cause);
+ setResultCode(OK);
+ }
+
+ public UnimportantException(String message, Integer statusCode, Throwable cause)
+ {
+ super(message, statusCode, cause);
+ setResultCode(OK);
+ }
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/id/IdGenerator.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/id/IdGenerator.java
new file mode 100644
index 0000000..b9d93f6
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/id/IdGenerator.java
@@ -0,0 +1,55 @@
+package io.github.hpsocket.soa.framework.core.id;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+
+/** ID 生成器 */
+public class IdGenerator
+{
+ private static final DateTimeFormatter DATE_TIME_PATTERN = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
+
+ private static Sequence SEQUENCE = new Sequence();
+
+ /**
+ * 重置雪花 ID 生成器的 workerId 和 datacenterId
+ * @param workerId :参考 {@linkplain Sequence#workerId}
+ * @param datacenterId :参考 {@linkplain Sequence#datacenterId}
+ */
+ public static final void resetSequence(long workerId, long datacenterId)
+ {
+ SEQUENCE = new Sequence(workerId, datacenterId);
+ }
+
+ /** 获取新雪花 ID */
+ public static final long nextId()
+ {
+ return SEQUENCE.nextId();
+ }
+
+ /** 获取新雪花 ID */
+ public static final String nextIdStr()
+ {
+ return String.valueOf(nextId());
+ }
+
+ /** 获取新雪花 UUID */
+ public static final String nextUUID()
+ {
+ ThreadLocalRandom random = ThreadLocalRandom.current();
+ return new UUID(random.nextLong(), random.nextLong()).toString();
+ }
+
+ /** 获取新雪花 UUID,并移除 UUID 中的 '-' */
+ public static final String nextCompactUUID()
+ {
+ return nextUUID().replaceAll("-", "");
+ }
+
+ /** 获取当前时间并格式化为字符串(精确到毫秒) */
+ public static final String curMillisecondStr()
+ {
+ return LocalDateTime.now().format(DATE_TIME_PATTERN);
+ }
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/id/Sequence.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/id/Sequence.java
new file mode 100644
index 0000000..453a5d4
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/id/Sequence.java
@@ -0,0 +1,325 @@
+
+package io.github.hpsocket.soa.framework.core.id;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Enumeration;
+import java.util.concurrent.ThreadLocalRandom;
+
+/** 雪花 ID 生成器 */
+@Slf4j
+public class Sequence
+{
+ /**
+ * 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
+ */
+ private final long twepoch = 1688140800000L;
+
+ /**
+ * 5位的数据中心id
+ */
+ private final long datacenterIdBits = 5L;
+ /**
+ * 5位的机器id
+ */
+ private final long workerIdBits = 5L;
+ /**
+ * 每毫秒内产生的id数: 2的12次方个
+ */
+ private final long sequenceBits = 12L;
+
+ protected final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+ protected final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+ private final long workerIdShift = sequenceBits;
+ private final long datacenterIdShift = sequenceBits + workerIdBits;
+
+ /**
+ * 时间戳左移动位
+ */
+ private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+ private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+ /**
+ * 所属数据中心id
+ */
+ private final long datacenterId;
+ /**
+ * 所属机器id
+ */
+ private final long workerId;
+ /**
+ * 并发控制序列
+ */
+ private long sequence = 0L;
+
+ /**
+ * 上次生产 ID 时间戳
+ */
+ private long lastTimestamp = -1L;
+
+ private static volatile InetAddress LOCAL_ADDRESS = null;
+
+ public Sequence()
+ {
+ this.datacenterId = calcDatacenterId();
+ this.workerId = getMaxWorkerId(datacenterId);
+ }
+
+ /**
+ * 有参构造器
+ *
+ * @param workerId
+ * 工作机器 ID
+ * @param datacenterId
+ * 序列号
+ */
+ public Sequence(long workerId, long datacenterId)
+ {
+ if(workerId > maxWorkerId || workerId < 0)
+ {
+ throw new IllegalArgumentException(String.format("Worker Id can't be greater than %d or less than 0", maxWorkerId));
+ }
+ if(datacenterId > maxDatacenterId || datacenterId < 0)
+ {
+ throw new IllegalArgumentException(String.format("Datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+ }
+
+ this.workerId = workerId;
+ this.datacenterId = datacenterId;
+ }
+
+ /**
+ * 基于网卡MAC地址计算余数作为数据中心
+ *
+ * 可自定扩展
+ */
+ protected long calcDatacenterId()
+ {
+ long id = 0L;
+
+ try
+ {
+ NetworkInterface nic = NetworkInterface.getByInetAddress(getLocalAddress());
+
+ if(null == nic)
+ {
+ id = 1L;
+ }
+ else
+ {
+ byte[] mac = nic.getHardwareAddress();
+
+ if(null != mac)
+ {
+ id = ((0x000000FF & (long)mac[mac.length - 2]) | (0x0000FF00 & (((long)mac[mac.length - 1]) << 8))) >> 6;
+ id = id % (maxDatacenterId + 1);
+ }
+ }
+ }
+ catch(Exception e)
+ {
+ log.warn(" calcDatacenterId: " + e.getMessage());
+ }
+
+ return id;
+ }
+
+ /**
+ * 基于 MAC + PID 的 hashcode 获取16个低位
+ *
+ * 可自定扩展
+ */
+ protected long getMaxWorkerId(long datacenterId)
+ {
+ StringBuilder mpId = new StringBuilder();
+ mpId.append(datacenterId);
+
+ String name = ManagementFactory.getRuntimeMXBean().getName();
+
+ if(name != null && name.length() > 0)
+ {
+ // GET jvmPid
+ mpId.append(name.split("@")[0]);
+ }
+
+ // MAC + PID 的 hashcode 获取16个低位
+ return (mpId.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
+ }
+
+ /**
+ * 获取下一个 ID
+ */
+ public synchronized long nextId()
+ {
+ long timestamp = timeGen();
+
+ // 闰秒
+ if(timestamp < lastTimestamp)
+ {
+ long offset = lastTimestamp - timestamp;
+
+ if(offset <= 5)
+ {
+ try
+ {
+ // 休眠双倍差值后重新获取,再次校验
+ wait(offset << 1);
+ timestamp = timeGen();
+
+ if(timestamp < lastTimestamp)
+ {
+ throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
+ }
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ else
+ {
+ throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
+ }
+ }
+
+ if(lastTimestamp == timestamp)
+ {
+ // 相同毫秒内,序列号自增
+ sequence = (sequence + 1) & sequenceMask;
+
+ if(sequence == 0)
+ {
+ // 同一毫秒的序列数已经达到最大
+ timestamp = tilNextMillis(lastTimestamp);
+ }
+ }
+ else
+ {
+ // 不同毫秒内,序列号置为 1 - 3 随机数
+ sequence = ThreadLocalRandom.current().nextLong(1, 3);
+ }
+
+ lastTimestamp = timestamp;
+
+ // 时间戳部分 | 数据中心部分 | 机器标识部分 | 序列号部分
+ return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
+ }
+
+ protected long tilNextMillis(long lastTimestamp)
+ {
+ long timestamp = timeGen();
+
+ while(timestamp <= lastTimestamp)
+ {
+ timestamp = timeGen();
+ }
+
+ return timestamp;
+ }
+
+ protected long timeGen()
+ {
+ return System.currentTimeMillis();
+ }
+
+ /**
+ * 从网卡获取第一个
+ *
+ * @return first valid local IP
+ */
+ protected static InetAddress getLocalAddress()
+ {
+ if(LOCAL_ADDRESS == null)
+ {
+ synchronized(Sequence.class)
+ {
+ if(LOCAL_ADDRESS == null)
+ {
+ LOCAL_ADDRESS = getLocalAddress0();
+ }
+ }
+ }
+
+ return LOCAL_ADDRESS;
+ }
+
+ private static InetAddress getLocalAddress0()
+ {
+ InetAddress localAddress = null;
+
+ try
+ {
+ localAddress = InetAddress.getLocalHost();
+
+ if(isValidAddress(localAddress))
+ {
+ return localAddress;
+ }
+ }
+ catch(Throwable e)
+ {
+ log.warn("Failed to retrieving ip address, " + e.getMessage(), e);
+ }
+
+ try
+ {
+ Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
+
+ if(interfaces != null)
+ {
+ while(interfaces.hasMoreElements())
+ {
+ try
+ {
+ NetworkInterface network = interfaces.nextElement();
+ Enumeration addresses = network.getInetAddresses();
+
+ while(addresses.hasMoreElements())
+ {
+ try
+ {
+ InetAddress address = addresses.nextElement();
+
+ if(isValidAddress(address))
+ {
+ return address;
+ }
+ }
+ catch(Throwable e)
+ {
+ log.warn("Failed to retrieving ip address, " + e.getMessage(), e);
+ }
+ }
+ }
+ catch(Throwable e)
+ {
+ log.warn("Failed to retrieving ip address, " + e.getMessage(), e);
+ }
+ }
+ }
+ }
+ catch(Throwable e)
+ {
+ log.warn("Failed to retrieving ip address, " + e.getMessage(), e);
+ }
+
+ log.error("Could not get local host ip address, will use 127.0.0.1 instead.");
+
+ return localAddress;
+ }
+
+ private static boolean isValidAddress(InetAddress address)
+ {
+ if(address == null || address.isLoopbackAddress() || address.isAnyLocalAddress() || address.isMulticastAddress())
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/log/LoggerNameFilter.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/log/LoggerNameFilter.java
new file mode 100644
index 0000000..499a994
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/log/LoggerNameFilter.java
@@ -0,0 +1,108 @@
+
+package io.github.hpsocket.soa.framework.core.log;
+
+import java.util.regex.Pattern;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.config.Node;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.filter.AbstractFilter;
+import org.apache.logging.log4j.message.Message;
+
+import io.github.hpsocket.soa.framework.core.util.GeneralHelper;
+
+/** log4j2 logger 日志过滤器
+ * 用于调整 logger 名称匹配特定正则表达式的 logger 的日志级别
+ */
+@Plugin(name = "LoggerNameFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
+public class LoggerNameFilter extends AbstractFilter
+{
+ private final Level level;
+ private final Pattern name;
+
+ private LoggerNameFilter(final Pattern name, final Level level, final Result onMatch, final Result onMismatch)
+ {
+ super(onMatch, onMismatch);
+ this.level = level;
+ this.name = name;
+ }
+
+ @Override
+ public Result filter(final Logger logger, final Level level, final Marker marker, final String msg, final Object... params)
+ {
+ return filter(logger.getName(), level);
+ }
+
+ @Override
+ public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg, final Throwable t)
+ {
+ return filter(logger.getName(), level);
+ }
+
+ @Override
+ public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg, final Throwable t)
+ {
+ return filter(logger.getName(), level);
+ }
+
+ @Override
+ public Result filter(final LogEvent event)
+ {
+ return filter(event.getLoggerName(), event.getLevel());
+ }
+
+ private Result filter(String name, final Level level)
+ {
+ if(level.isLessSpecificThan(this.level) && this.name.matcher(name).matches())
+ return onMismatch;
+
+ return onMatch;
+ }
+
+ public Level getLevel()
+ {
+ return level;
+ }
+
+ public String getName()
+ {
+ return name.toString();
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append("level=").append(level);
+ sb.append(", name=").append(name);
+
+ return sb.toString();
+ }
+
+ @PluginFactory
+ public static LoggerNameFilter createFilter(
+ @PluginAttribute("name") final String name,
+ @PluginAttribute("level") final Level level,
+ @PluginAttribute("onMatch") final Result match,
+ @PluginAttribute("onMismatch") final Result mismatch)
+ {
+ if(GeneralHelper.isStrEmpty(name))
+ {
+ LOGGER.error("'name' attribute must be provided for LoggerNameFilter");
+ return null;
+ }
+
+ final Level actualLevel = level == null ? Level.ERROR : level;
+ final Result onMatch = match == null ? Result.NEUTRAL : match;
+ final Result onMismatch = mismatch == null ? Result.DENY : mismatch;
+
+ return new LoggerNameFilter(Pattern.compile(name), actualLevel, onMatch, onMismatch);
+ }
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcAttr.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcAttr.java
new file mode 100644
index 0000000..493291b
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcAttr.java
@@ -0,0 +1,354 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.MDC;
+
+/** 调用链跟踪 {@linkplain MDC} 属性 */
+public class MdcAttr
+{
+ public static final String MDC_TRACE_ID_KEY = "__traceId";
+ public static final String MDC_REQUEST_ID_KEY = "__requestId";
+ public static final String MDC_CLIENT_ID_KEY = "__clientId";
+ public static final String MDC_SESSION_ID_KEY = "__sessionId";
+ public static final String MDC_APP_CODE_KEY = "__appCode";
+ public static final String MDC_SRC_APP_CODE_KEY = "__srcAppCode";
+ public static final String MDC_TOKEN_KEY = "__token";
+ public static final String MDC_USER_ID_KEY = "__userId";
+ public static final String MDC_GROUP_ID_KEY = "__groupId";
+ public static final String MDC_EXTRA_KEY = "__extra";
+ public static final String MDC_APP_ID_KEY = "__appId";
+ public static final String MDC_APP_NAME_KEY = "__appName";
+ public static final String MDC_SERVICE_ID_KEY = "__serviceId";
+ public static final String MDC_SERVICE_NAME_KEY = "__serviceName";
+ public static final String MDC_SERVICE_ADDR_KEY = "__serviceAddr";
+ public static final String MDC_ORG_KEY = "__organization";
+ public static final String MDC_OWNER_KEY = "__owner";
+
+ public static final String MDC_MESSAGE_ID_KEY = "__messageId";
+ public static final String MDC_SOURCE_REQUEST_ID_KEY = "__sourceRequestId";
+
+ public static final String MDC_FROM_SERVICE_ID_KEY = "__fromServiceId";
+ public static final String MDC_FROM_SERVICE_NAME_KEY = "__fromServiceName";
+ public static final String MDC_FROM_SERVICE_ADDR_KEY = "__fromServiceAddr";
+
+ public static final String TRANSFER_MDC_KEYS[] = {
+ MDC_TRACE_ID_KEY,
+ MDC_REQUEST_ID_KEY,
+ MDC_CLIENT_ID_KEY,
+ MDC_SESSION_ID_KEY,
+ MDC_MESSAGE_ID_KEY,
+ MDC_SOURCE_REQUEST_ID_KEY,
+ MDC_APP_CODE_KEY,
+ MDC_SRC_APP_CODE_KEY,
+ MDC_TOKEN_KEY,
+ MDC_USER_ID_KEY,
+ MDC_GROUP_ID_KEY,
+ MDC_EXTRA_KEY,
+ MDC_APP_ID_KEY,
+ MDC_APP_NAME_KEY
+ };
+
+ public static final String TRANSFER_MDC_ALL_KEYS[] = {
+ MDC_TRACE_ID_KEY,
+ MDC_REQUEST_ID_KEY,
+ MDC_CLIENT_ID_KEY,
+ MDC_SESSION_ID_KEY,
+ MDC_MESSAGE_ID_KEY,
+ MDC_SOURCE_REQUEST_ID_KEY,
+ MDC_APP_CODE_KEY,
+ MDC_SRC_APP_CODE_KEY,
+ MDC_TOKEN_KEY,
+ MDC_USER_ID_KEY,
+ MDC_GROUP_ID_KEY,
+ MDC_EXTRA_KEY,
+ MDC_APP_ID_KEY,
+ MDC_APP_NAME_KEY,
+ MDC_FROM_SERVICE_ID_KEY,
+ MDC_FROM_SERVICE_NAME_KEY,
+ MDC_FROM_SERVICE_ADDR_KEY
+ };
+
+ Map ctxMap;
+
+ public MdcAttr()
+ {
+ ctxMap = new HashMap<>();
+ }
+
+ public MdcAttr(Map mdcMap)
+ {
+ this.ctxMap = mdcMap;
+ }
+
+ public static MdcAttr from(Map mdcMap)
+ {
+ return new MdcAttr(mdcMap);
+ }
+
+ public static MdcAttr fromMdc()
+ {
+ return new MdcAttr(MDC.getCopyOfContextMap());
+ }
+
+ public void putMdc()
+ {
+ ctxMap.forEach((k, v) -> MDC.put(k, v));
+ }
+
+ public void removeMdc()
+ {
+ removeMdc(true);
+ }
+
+ public void removeMdc(boolean clearMdcMap)
+ {
+ ctxMap.forEach((k, v) -> MDC.remove(k));
+
+ if(clearMdcMap)
+ ctxMap.clear();
+ }
+
+ public void set(String key, String val)
+ {
+ ctxMap.put(key, val);
+ }
+
+ public String remove(String key)
+ {
+ return ctxMap.remove(key);
+ }
+
+ public String get(String key)
+ {
+ return ctxMap.get(key);
+ }
+
+ public Map getCtxMap()
+ {
+ return ctxMap;
+ }
+
+ public void setCtxMap(Map ctxMap)
+ {
+ this.ctxMap = ctxMap;
+ }
+
+ public String getTraceId()
+ {
+ return get(MDC_TRACE_ID_KEY);
+ }
+
+ public void setTraceId(String traceId)
+ {
+ set(MDC_TRACE_ID_KEY, traceId);
+ }
+
+ public String getClientId()
+ {
+ return get(MDC_CLIENT_ID_KEY);
+ }
+
+ public void setClientId(String clientId)
+ {
+ set(MDC_CLIENT_ID_KEY, clientId);
+ }
+
+ public String getRequestId()
+ {
+ return get(MDC_REQUEST_ID_KEY);
+ }
+
+ public void setRequestId(String requestId)
+ {
+ set(MDC_REQUEST_ID_KEY, requestId);
+ }
+
+ public String getSessionId()
+ {
+ return get(MDC_SESSION_ID_KEY);
+ }
+
+ public void setSessionId(String sessionId)
+ {
+ set(MDC_SESSION_ID_KEY, sessionId);
+ }
+
+ public String getMessageId()
+ {
+ return get(MDC_MESSAGE_ID_KEY);
+ }
+
+ public void setMessageId(String messageId)
+ {
+ set(MDC_MESSAGE_ID_KEY, messageId);
+ }
+
+ public String getSourceRequestId()
+ {
+ return get(MDC_SOURCE_REQUEST_ID_KEY);
+ }
+
+ public void setSourceRequestId(String sourceRequestId)
+ {
+ set(MDC_SOURCE_REQUEST_ID_KEY, sourceRequestId);
+ }
+
+ public String getToken()
+ {
+ return get(MDC_TOKEN_KEY);
+ }
+
+ public void setToken(String token)
+ {
+ set(MDC_TOKEN_KEY, token);
+ }
+
+ public String getUserId()
+ {
+ return get(MDC_USER_ID_KEY);
+ }
+
+ public void setUserId(String userId)
+ {
+ set(MDC_USER_ID_KEY, userId);
+ }
+
+ public String getGroupId()
+ {
+ return get(MDC_GROUP_ID_KEY);
+ }
+
+ public void setGroupId(String groupId)
+ {
+ set(MDC_GROUP_ID_KEY, groupId);
+ }
+
+ public String getExtra()
+ {
+ return get(MDC_EXTRA_KEY);
+ }
+
+ public void setExtra(String extra)
+ {
+ set(MDC_EXTRA_KEY, extra);
+ }
+
+ public String getAppCode()
+ {
+ return get(MDC_APP_CODE_KEY);
+ }
+
+ public void setAppCode(String appCode)
+ {
+ set(MDC_APP_CODE_KEY, appCode);
+ }
+
+ public void setSrcAppCode(String srcAppCode)
+ {
+ set(MDC_SRC_APP_CODE_KEY, srcAppCode);
+ }
+
+ public String getAppName()
+ {
+ return get(MDC_APP_NAME_KEY);
+ }
+
+ public void setAppName(String appName)
+ {
+ set(MDC_APP_NAME_KEY, appName);
+ }
+
+ public String getAppId()
+ {
+ return get(MDC_APP_ID_KEY);
+ }
+
+ public void setAppId(String appId)
+ {
+ set(MDC_APP_ID_KEY, appId);
+ }
+
+ public String getServiceId()
+ {
+ return get(MDC_SERVICE_ID_KEY);
+ }
+
+ public void setServiceId(String serviceId)
+ {
+ set(MDC_SERVICE_ID_KEY, serviceId);
+ }
+
+ public String getServiceName()
+ {
+ return get(MDC_SERVICE_NAME_KEY);
+ }
+
+ public void setServiceName(String serviceName)
+ {
+ set(MDC_SERVICE_NAME_KEY, serviceName);
+ }
+
+ public String getServiceAddr()
+ {
+ return get(MDC_SERVICE_ADDR_KEY);
+ }
+
+ public void setServiceAddr(String serviceAddr)
+ {
+ set(MDC_SERVICE_ADDR_KEY, serviceAddr);
+ }
+
+ public String getFromServiceId()
+ {
+ return get(MDC_FROM_SERVICE_ID_KEY);
+ }
+
+ public void setFromServiceId(String fromServiceId)
+ {
+ set(MDC_FROM_SERVICE_ID_KEY, fromServiceId);
+ }
+
+ public String getFromServiceName()
+ {
+ return get(MDC_FROM_SERVICE_NAME_KEY);
+ }
+
+ public void setFromServiceName(String fromServiceName)
+ {
+ set(MDC_FROM_SERVICE_NAME_KEY, fromServiceName);
+ }
+
+ public String getFromServiceAddr()
+ {
+ return get(MDC_FROM_SERVICE_ADDR_KEY);
+ }
+
+ public void setFromServiceAddr(String fromServiceAddr)
+ {
+ set(MDC_FROM_SERVICE_ADDR_KEY, fromServiceAddr);
+ }
+
+ public String getOrganization()
+ {
+ return get(MDC_ORG_KEY);
+ }
+
+ public void setOrganization(String orgName)
+ {
+ set(MDC_ORG_KEY, orgName);
+ }
+
+ public String getOwner()
+ {
+ return get(MDC_OWNER_KEY);
+ }
+
+ public void setOwner(String ownerName)
+ {
+ set(MDC_OWNER_KEY, ownerName);
+ }
+
+}
+
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcCallable.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcCallable.java
new file mode 100644
index 0000000..fbf08c3
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcCallable.java
@@ -0,0 +1,40 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.concurrent.Callable;
+
+import lombok.Getter;
+
+/** {@linkplain Callable} 基类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+abstract public class MdcCallable implements Callable
+{
+ private MdcAttr mdcAttr;
+
+ abstract protected T doCall() throws Exception;
+
+ public MdcCallable()
+ {
+ this(MdcAttr.fromMdc());
+ }
+
+ public MdcCallable(MdcAttr mdcAttr)
+ {
+ this.mdcAttr = mdcAttr;
+ }
+
+ @Override
+ public T call() throws Exception
+ {
+ try
+ {
+ mdcAttr.putMdc();
+
+ return doCall();
+ }
+ finally
+ {
+ mdcAttr.removeMdc();
+ }
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcCallableWrapper.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcCallableWrapper.java
new file mode 100644
index 0000000..804a38a
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcCallableWrapper.java
@@ -0,0 +1,34 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.concurrent.Callable;
+
+import lombok.Getter;
+
+/** {@linkplain Callable} 包装类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+public class MdcCallableWrapper extends MdcCallable
+{
+ private Callable c;
+
+ public MdcCallableWrapper(Callable c)
+ {
+ this.c = c;
+ }
+
+ public MdcCallableWrapper(Callable c, MdcAttr mdcAttr)
+ {
+ super(mdcAttr);
+ this.c = c;
+ }
+
+ @Override
+ public T doCall() throws Exception
+ {
+ return c.call();
+ }
+
+ public static MdcCallableWrapper of(Callable c)
+ {
+ return new MdcCallableWrapper(c);
+ }
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcConsumer.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcConsumer.java
new file mode 100644
index 0000000..6bac1ee
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcConsumer.java
@@ -0,0 +1,39 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.function.Consumer;
+
+import lombok.Getter;
+/** {@linkplain Consumer} 基类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+abstract public class MdcConsumer implements Consumer
+{
+ private final MdcAttr mdcAttr;
+
+ abstract protected void doAccept(T t);
+
+ public MdcConsumer()
+ {
+ this(MdcAttr.fromMdc());
+ }
+
+ public MdcConsumer(MdcAttr mdcAttr)
+ {
+ this.mdcAttr = mdcAttr;
+ }
+
+ @Override
+ public void accept(T t)
+ {
+ try
+ {
+ mdcAttr.putMdc();
+
+ doAccept(t);
+ }
+ finally
+ {
+ mdcAttr.removeMdc();
+ }
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcConsumerWrapper.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcConsumerWrapper.java
new file mode 100644
index 0000000..6aafc0e
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcConsumerWrapper.java
@@ -0,0 +1,34 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.function.Consumer;
+
+import lombok.Getter;
+
+/** {@linkplain Consumer} 包装类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+public class MdcConsumerWrapper extends MdcConsumer
+{
+ private Consumer c;
+
+ public MdcConsumerWrapper(Consumer c)
+ {
+ this.c = c;
+ }
+
+ public MdcConsumerWrapper(Consumer c, MdcAttr mdcAttr)
+ {
+ super(mdcAttr);
+ this.c = c;
+ }
+
+ @Override
+ public void doAccept(T t)
+ {
+ c.accept(t);
+ }
+
+ public static MdcConsumerWrapper of(Consumer c)
+ {
+ return new MdcConsumerWrapper(c);
+ }
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcFunction.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcFunction.java
new file mode 100644
index 0000000..20b44cb
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcFunction.java
@@ -0,0 +1,39 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.function.Function;
+
+import lombok.Getter;
+
+/** {@linkplain Function} 基类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+abstract public class MdcFunction implements Function
+{
+ private final MdcAttr mdcAttr;
+
+ abstract protected R doApply(T t);
+
+ public MdcFunction()
+ {
+ this(MdcAttr.fromMdc());
+ }
+
+ public MdcFunction(MdcAttr mdcAttr)
+ {
+ this.mdcAttr = mdcAttr;
+ }
+
+ @Override
+ public R apply(T t)
+ {
+ try
+ {
+ mdcAttr.putMdc();
+
+ return doApply(t);
+ }
+ finally
+ {
+ mdcAttr.removeMdc();
+ }
+ }
+}
\ No newline at end of file
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcFunctionWrapper.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcFunctionWrapper.java
new file mode 100644
index 0000000..5c53f28
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcFunctionWrapper.java
@@ -0,0 +1,34 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.function.Function;
+
+import lombok.Getter;
+
+/** {@linkplain Function} 包装类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+public class MdcFunctionWrapper extends MdcFunction
+{
+ private Function f;
+
+ public MdcFunctionWrapper(Function f)
+ {
+ this.f = f;
+ }
+
+ public MdcFunctionWrapper(Function f, MdcAttr mdcAttr)
+ {
+ super(mdcAttr);
+ this.f = f;
+ }
+
+ @Override
+ public R doApply(T t)
+ {
+ return f.apply(t);
+ }
+
+ public static MdcFunctionWrapper of(Function f)
+ {
+ return new MdcFunctionWrapper(f);
+ }
+}
\ No newline at end of file
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRecursiveAction.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRecursiveAction.java
new file mode 100644
index 0000000..71e3ec0
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRecursiveAction.java
@@ -0,0 +1,41 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.concurrent.RecursiveAction;
+
+import lombok.Getter;
+
+/** {@linkplain RecursiveAction} 基类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+@SuppressWarnings("serial")
+abstract public class MdcRecursiveAction extends RecursiveAction
+{
+ private final MdcAttr mdcAttr;
+
+ abstract protected void doCompute();
+
+ public MdcRecursiveAction()
+ {
+ this(MdcAttr.fromMdc());
+ }
+
+ public MdcRecursiveAction(MdcAttr mdcAttr)
+ {
+ this.mdcAttr = mdcAttr;
+ }
+
+ @Override
+ protected void compute()
+ {
+ try
+ {
+ mdcAttr.putMdc();
+
+ doCompute();
+ }
+ finally
+ {
+ mdcAttr.removeMdc();
+ }
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRecursiveTask.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRecursiveTask.java
new file mode 100644
index 0000000..0113c51
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRecursiveTask.java
@@ -0,0 +1,41 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.concurrent.RecursiveTask;
+
+import lombok.Getter;
+
+/** {@linkplain RecursiveTask} 基类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+@SuppressWarnings("serial")
+abstract public class MdcRecursiveTask extends RecursiveTask
+{
+ private final MdcAttr mdcAttr;
+
+ abstract protected T doCompute();
+
+ public MdcRecursiveTask()
+ {
+ this(MdcAttr.fromMdc());
+ }
+
+ public MdcRecursiveTask(MdcAttr mdcAttr)
+ {
+ this.mdcAttr = mdcAttr;
+ }
+
+ @Override
+ protected T compute()
+ {
+ try
+ {
+ mdcAttr.putMdc();
+
+ return doCompute();
+ }
+ finally
+ {
+ mdcAttr.removeMdc();
+ }
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRunnable.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRunnable.java
new file mode 100644
index 0000000..6291bdf
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRunnable.java
@@ -0,0 +1,38 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import lombok.Getter;
+
+/** {@linkplain Runnable} 基类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+abstract public class MdcRunnable implements Runnable
+{
+ private final MdcAttr mdcAttr;
+
+ abstract protected void doRun();
+
+ public MdcRunnable()
+ {
+ this(MdcAttr.fromMdc());
+ }
+
+ public MdcRunnable(MdcAttr mdcAttr)
+ {
+ this.mdcAttr = mdcAttr;
+ }
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ mdcAttr.putMdc();
+
+ doRun();
+ }
+ finally
+ {
+ mdcAttr.removeMdc();
+ }
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRunnableWrapper.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRunnableWrapper.java
new file mode 100644
index 0000000..194912c
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcRunnableWrapper.java
@@ -0,0 +1,32 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import lombok.Getter;
+
+/** {@linkplain Runnable} 包装类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+public class MdcRunnableWrapper extends MdcRunnable
+{
+ private Runnable r;
+
+ public MdcRunnableWrapper(Runnable r)
+ {
+ this.r = r;
+ }
+
+ public MdcRunnableWrapper(Runnable r, MdcAttr mdcAttr)
+ {
+ super(mdcAttr);
+ this.r = r;
+ }
+
+ @Override
+ public void doRun()
+ {
+ r.run();
+ }
+
+ public static MdcRunnableWrapper of(Runnable r)
+ {
+ return new MdcRunnableWrapper(r);
+ }
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcSupplier.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcSupplier.java
new file mode 100644
index 0000000..83b209a
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcSupplier.java
@@ -0,0 +1,40 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.function.Supplier;
+
+import lombok.Getter;
+
+/** {@linkplain Supplier} 基类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+abstract public class MdcSupplier implements Supplier
+{
+ private final MdcAttr mdcAttr;
+
+ abstract protected T doGet();
+
+ public MdcSupplier()
+ {
+ this(MdcAttr.fromMdc());
+ }
+
+ public MdcSupplier(MdcAttr mdcAttr)
+ {
+ this.mdcAttr = mdcAttr;
+ }
+
+ @Override
+ public T get()
+ {
+ try
+ {
+ mdcAttr.putMdc();
+
+ return doGet();
+ }
+ finally
+ {
+ mdcAttr.removeMdc();
+ }
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcSupplierWrapper.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcSupplierWrapper.java
new file mode 100644
index 0000000..2921953
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/mdc/MdcSupplierWrapper.java
@@ -0,0 +1,35 @@
+package io.github.hpsocket.soa.framework.core.mdc;
+
+import java.util.function.Supplier;
+
+import lombok.Getter;
+
+/** {@linkplain Supplier} 包装类(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+public class MdcSupplierWrapper extends MdcSupplier
+{
+ private Supplier s;
+
+ public MdcSupplierWrapper(Supplier s)
+ {
+ this.s = s;
+ }
+
+ public MdcSupplierWrapper(Supplier s, MdcAttr mdcAttr)
+ {
+ super(mdcAttr);
+ this.s = s;
+ }
+
+ @Override
+ public T doGet()
+ {
+ return s.get();
+ }
+
+ public static MdcSupplierWrapper of(Supplier s)
+ {
+ return new MdcSupplierWrapper(s);
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/paging/PageInfo.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/paging/PageInfo.java
new file mode 100644
index 0000000..d791a45
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/paging/PageInfo.java
@@ -0,0 +1,47 @@
+
+package io.github.hpsocket.soa.framework.core.paging;
+
+import java.io.Serializable;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/** 通用分页信息 */
+@Getter
+@Setter
+@NoArgsConstructor
+@SuppressWarnings("serial")
+public class PageInfo implements Serializable
+{
+ public static final int DEFAULT_PAGE_SIZE = 20;
+
+ private int pageRows = 0;
+ private int pageNumber = 1;
+ private int pageSize = DEFAULT_PAGE_SIZE;
+ private int pageCount = 0;
+ private int totalRows = 0;
+
+ public int calculatePageCount()
+ {
+ pageCount = totalRows / pageSize + ((totalRows % pageSize == 0) ? 0 : 1);
+
+ if(pageNumber < pageCount)
+ pageRows = pageSize;
+ else if(pageNumber == pageCount)
+ pageRows = totalRows - (pageCount - 1) * pageSize;
+
+ return pageCount;
+ }
+
+ public boolean outofBounds()
+ {
+ return pageNumber > pageCount || pageNumber < 1;
+ }
+
+ public int limitStart()
+ {
+ return (pageNumber - 1) * pageSize;
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/paging/PageRequest.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/paging/PageRequest.java
new file mode 100644
index 0000000..912d34a
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/paging/PageRequest.java
@@ -0,0 +1,20 @@
+package io.github.hpsocket.soa.framework.core.paging;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/** 通用分页请求 */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class PageRequest
+{
+ private int pageNumber = 1;
+ private int pageSize = PageInfo.DEFAULT_PAGE_SIZE;
+ private String orderBy;
+
+ private T param;
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/paging/PageResult.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/paging/PageResult.java
new file mode 100644
index 0000000..b999fec
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/paging/PageResult.java
@@ -0,0 +1,19 @@
+package io.github.hpsocket.soa.framework.core.paging;
+
+import java.util.List;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/** 通用分页结果 */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class PageResult
+{
+ private PageInfo page;
+ private List data;
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/thread/AsyncThreadPoolExecutor.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/thread/AsyncThreadPoolExecutor.java
new file mode 100644
index 0000000..6693efa
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/thread/AsyncThreadPoolExecutor.java
@@ -0,0 +1,48 @@
+package io.github.hpsocket.soa.framework.core.thread;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import io.github.hpsocket.soa.framework.core.mdc.MdcRunnableWrapper;
+
+import lombok.Getter;
+
+/** 异步线程池(支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪) */
+@Getter
+public class AsyncThreadPoolExecutor extends ThreadPoolExecutor
+{
+ public AsyncThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue)
+ {
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
+ }
+
+ public AsyncThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory)
+ {
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
+ }
+
+ public AsyncThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler)
+ {
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
+ }
+
+ public AsyncThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
+ {
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
+ }
+
+ @Override
+ public void execute(Runnable task)
+ {
+ super.execute(decorate(task));
+ }
+
+ protected Runnable decorate(Runnable task)
+ {
+ return MdcRunnableWrapper.of(task);
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/thread/LocalExecutorServiceFactory.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/thread/LocalExecutorServiceFactory.java
new file mode 100644
index 0000000..ab71cc2
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/thread/LocalExecutorServiceFactory.java
@@ -0,0 +1,81 @@
+package io.github.hpsocket.soa.framework.core.thread;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/** 线程局部线程池工厂:每个线程拥有独立线程池
+ * (支持 {@linkplain org.slf4j.MDC MDC} 调用链跟踪)
+ */
+
+public class LocalExecutorServiceFactory
+{
+ public static final LocalExecutorServiceFactory DEFAULT_FACTORY = new LocalExecutorServiceFactory();
+ private static final RejectedExecutionHandler DEFAULT_REJECT_HANDLER = new SynchronousRejectedExecutionHandler();
+
+ private ThreadLocal local = new ThreadLocal();
+
+ public LocalExecutorServiceFactory()
+ {
+
+ }
+
+ public ExecutorService get()
+ {
+ return get(Integer.MAX_VALUE, 60L, TimeUnit.SECONDS);
+ }
+
+ public ExecutorService get(int maximumPoolSize)
+ {
+ return get(maximumPoolSize, 60L, TimeUnit.SECONDS);
+ }
+
+ public ExecutorService get(long keepAliveTime, TimeUnit unit)
+ {
+ return get(Integer.MAX_VALUE, keepAliveTime, unit);
+ }
+
+ public ExecutorService get(int maximumPoolSize, long keepAliveTime, TimeUnit unit)
+ {
+ return get(maximumPoolSize, keepAliveTime, unit, null);
+ }
+
+ public ExecutorService get(int maximumPoolSize, long keepAliveTime, TimeUnit unit, RejectedExecutionHandler rejectHandler)
+ {
+ ThreadPoolExecutor executor = local.get();
+
+ if(rejectHandler == null)
+ rejectHandler = DEFAULT_REJECT_HANDLER;
+
+ if(executor == null)
+ {
+ executor = createExecutor(0, maximumPoolSize, keepAliveTime, unit, new SynchronousQueue(), rejectHandler);
+ local.set(executor);
+ }
+ else
+ {
+ if(executor.getMaximumPoolSize() != maximumPoolSize)
+ executor.setMaximumPoolSize(maximumPoolSize);
+ if(executor.getKeepAliveTime(TimeUnit.NANOSECONDS) != unit.toNanos(keepAliveTime))
+ executor.setKeepAliveTime(keepAliveTime, unit);
+ if(executor.getRejectedExecutionHandler() != rejectHandler)
+ executor.setRejectedExecutionHandler(rejectHandler);
+ }
+
+ return executor;
+ }
+
+ public void remove()
+ {
+ local.remove();
+ }
+
+ private ThreadPoolExecutor createExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue synchronousQueue, RejectedExecutionHandler rejectHandler)
+ {
+ return new AsyncThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, synchronousQueue, rejectHandler);
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/thread/SynchronousRejectedExecutionHandler.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/thread/SynchronousRejectedExecutionHandler.java
new file mode 100644
index 0000000..0b0f3fe
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/thread/SynchronousRejectedExecutionHandler.java
@@ -0,0 +1,30 @@
+package io.github.hpsocket.soa.framework.core.thread;
+
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import lombok.extern.slf4j.Slf4j;
+
+/** 阻塞式 {@linkplain RejectedExecutionHandler}
+ * 当线程池的工作队列已满时,阻塞任务提交并等待。
+ */
+@Slf4j
+public class SynchronousRejectedExecutionHandler implements RejectedExecutionHandler
+{
+ @Override
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor executor)
+ {
+ if(!executor.isShutdown())
+ {
+ try
+ {
+ executor.getQueue().put(r);
+ }
+ catch(InterruptedException e)
+ {
+ log.error("submit task {} interrupted", r, e);
+ }
+ }
+ }
+
+}
diff --git a/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/util/BeanHelper.java b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/util/BeanHelper.java
new file mode 100644
index 0000000..d2ba8f4
--- /dev/null
+++ b/hp-soa-framework/hp-soa-framework-core/src/main/java/io/github/hpsocket/soa/framework/core/util/BeanHelper.java
@@ -0,0 +1,1654 @@
+package io.github.hpsocket.soa.framework.core.util;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/** Java Bean 帮助类,执行 Java Bean 反射和内省等相关操作 */
+public class BeanHelper
+{
+ /** 原生数据类型集合 */
+ public static final Set> NATIVE_CLASS_SET = new HashSet>(8);
+ /** 简单数据类型集合 */
+ public static final Set> SMIPLE_CLASS_SET = new HashSet>(18);
+ /** 基本类型包装类集合 */
+ public static final Set> WRAPPER_CLASS_SET = new HashSet>(8);
+
+ private static final String STRING_DELIMITERS = " ,;|\t\n\r\f";
+ private static final char ATTR_SEP_CHAR = '.';
+
+ static
+ {
+ NATIVE_CLASS_SET.add(int.class);
+ NATIVE_CLASS_SET.add(long.class);
+ NATIVE_CLASS_SET.add(float.class);
+ NATIVE_CLASS_SET.add(double.class);
+ NATIVE_CLASS_SET.add(byte.class);
+ NATIVE_CLASS_SET.add(char.class);
+ NATIVE_CLASS_SET.add(short.class);
+ NATIVE_CLASS_SET.add(boolean.class);
+
+ SMIPLE_CLASS_SET.add(int.class);
+ SMIPLE_CLASS_SET.add(long.class);
+ SMIPLE_CLASS_SET.add(float.class);
+ SMIPLE_CLASS_SET.add(double.class);
+ SMIPLE_CLASS_SET.add(byte.class);
+ SMIPLE_CLASS_SET.add(char.class);
+ SMIPLE_CLASS_SET.add(short.class);
+ SMIPLE_CLASS_SET.add(boolean.class);
+ SMIPLE_CLASS_SET.add(Integer.class);
+ SMIPLE_CLASS_SET.add(Long.class);
+ SMIPLE_CLASS_SET.add(Float.class);
+ SMIPLE_CLASS_SET.add(Double.class);
+ SMIPLE_CLASS_SET.add(Byte.class);
+ SMIPLE_CLASS_SET.add(Character.class);
+ SMIPLE_CLASS_SET.add(Short.class);
+ SMIPLE_CLASS_SET.add(Boolean.class);
+ SMIPLE_CLASS_SET.add(String.class);
+ SMIPLE_CLASS_SET.add(Date.class);
+
+ WRAPPER_CLASS_SET.add(Integer.class);
+ WRAPPER_CLASS_SET.add(Long.class);
+ WRAPPER_CLASS_SET.add(Float.class);
+ WRAPPER_CLASS_SET.add(Double.class);
+ WRAPPER_CLASS_SET.add(Byte.class);
+ WRAPPER_CLASS_SET.add(Character.class);
+ WRAPPER_CLASS_SET.add(Short.class);
+ WRAPPER_CLASS_SET.add(Boolean.class);
+ }
+
+ /** 检查是否为非抽象公共实例方法 */
+ public static final boolean isInstanceField(Field field)
+ {
+ int flag = field.getModifiers();
+ return (!Modifier.isStatic(flag));
+ }
+
+ /** 检查是否为非抽象公共实例方法 */
+ public static final boolean isInstanceNotFinalField(Field field)
+ {
+ int flag = field.getModifiers();
+ return (!Modifier.isStatic(flag) && !Modifier.isFinal(flag));
+ }
+
+ /** 检查是否为非抽象公共实例方法 */
+ public static final boolean isPublicInstanceMethod(Method method)
+ {
+ int flag = method.getModifiers();
+ return (!Modifier.isStatic(flag) && !Modifier.isAbstract(flag) && Modifier.isPublic(flag));
+ }
+
+ /** 检查是否为公共接口 */
+ public static final boolean isPublicInterface(Class> clazz)
+ {
+ int flag = clazz.getModifiers();
+ return (Modifier.isInterface(flag) && Modifier.isPublic(flag));
+ }
+
+ /** 检查是否为公共类 */
+ public static final boolean isPublicClass(Class> clazz)
+ {
+ int flag = clazz.getModifiers();
+ return (!Modifier.isInterface(flag) && Modifier.isPublic(flag));
+ }
+
+ /** 检查是否为非接口非抽象公共类 */
+ public static final boolean isPublicNotAbstractClass(Class> clazz)
+ {
+ int flag = clazz.getModifiers();
+ return (!Modifier.isInterface(flag) && !Modifier.isAbstract(flag) && Modifier.isPublic(flag));
+ }
+
+ /** 检查 clazz 是否为原生数据类型 */
+ public final static boolean isNativeType(Class> clazz)
+ {
+ return NATIVE_CLASS_SET.contains(clazz);
+ }
+
+ /** 检查 clazz 是否为简单数据类型 */
+ public final static boolean isSimpleType(Class> clazz)
+ {
+ return SMIPLE_CLASS_SET.contains(clazz);
+ }
+
+ /** 检查 clazz 是否为基础类型包装类 */
+ public final static boolean isWrapperType(Class> clazz)
+ {
+ return WRAPPER_CLASS_SET.contains(clazz);
+ }
+
+ /** 检查包装类和基础类型是否匹配 */
+ public final static boolean isWrapperAndPrimitiveMatch(Class> wrapperClazz, Class> primitiveClass)
+ {
+ if(!primitiveClass.isPrimitive()) return false;
+ if(!isWrapperType(wrapperClazz)) return false;
+
+ try
+ {
+ Field f = wrapperClazz.getDeclaredField("TYPE");
+ return f.get(null) == primitiveClass;
+ }
+ catch(Exception e)
+ {
+
+ }
+
+ return false;
+ }
+
+ /** 检查源类型是否兼容目标类型 */
+ public static final boolean isCompatibleType(Class> srcClazz,Class> destClazz)
+ {
+ return (
+ destClazz.isAssignableFrom(srcClazz) ||
+ isWrapperAndPrimitiveMatch(destClazz, srcClazz) ||
+ isWrapperAndPrimitiveMatch(srcClazz, destClazz)
+ );
+ }
+
+ /** 检查源数组的元素类型是否兼容目标数组的元素类型 */
+ public static final boolean isCompatibleArray(Class> srcClazz, Class> destClazz)
+ {
+ if(srcClazz.isArray() && destClazz.isArray())
+ {
+ Class> srcComponentType = srcClazz.getComponentType();
+ Class> destComponentType = destClazz.getComponentType();
+
+ return isCompatibleType(srcComponentType, destComponentType);
+ }
+
+ return false;
+ }
+
+ /** 检查属性是否可以联级装配 */
+ public static final boolean isCascadableProperty(PropertyDescriptor pd)
+ {
+ return (pd != null && getPropertyWriteMethod(pd) != null && isCascadable(pd.getPropertyType()));
+ }
+
+ /** 检查成员变量是否可以联级装配 */
+ public static final boolean isCascadableField(Field f)
+ {
+ return (f != null && isInstanceNotFinalField(f) && isCascadable(f.getType()));
+ }
+
+ /** 检查类是否可以联级装配 */
+ public static final boolean isCascadable(Class> clazz)
+ {
+ return isPublicNotAbstractClass(clazz) &&
+ !isSimpleType(clazz) &&
+ !clazz.isArray() &&
+ !Collection.class.isAssignableFrom(clazz) &&
+ !Map.class.isAssignableFrom(clazz) ;
+ }
+
+ /** 创建指定类型的 Java Bean,并设置相关属性或成员变量
+ *
+ * @param clazz : Bean 类型
+ * @param properties : 属性或成员变量名 / 值映射
+ * 其中名称为 {@link String} 类型,与属性或成员变量名称一致
+ * 属性或成员变量值可能为以下 3 中类型:
+ * 1) 属性或成员变量的实际类型:直接对属性或成员变量赋值
+ * 2) {@link String} 类型:先执行自动类型转换再对属性或成员变量赋值
+ * 3) {@link String}[] 类型:先执行自动类型转换再对属性或成员变量赋值
+ * @return : 生成的 Bean 实例
+ */
+ public static final B createBean(Class clazz, Map properties)
+ {
+ return createBean(clazz, properties, null);
+ }
+
+ /** 创建指定类型的 Java Bean,并设置相关属性或成员变量
+ *
+ * @param clazz : Bean 类型
+ * @param valueMap : 属性或成员变量名 / 值映射
+ * 其中名称为 {@link String} 类型,与属性或成员变量名称可能一直也可能不一致
+ * 属性或成员变量值可能为以下 3 中类型:
+ * 1) 属性的实际类型:直接对属性或成员变量赋值
+ * 2) {@link String} 类型:先执行自动类型转换再对属性或成员变量赋值
+ * 3) {@link String}[] 类型:先执行自动类型转换再对属性或成员变量赋值
+ * @param keyMap : properties.key / Bean 属性或成员变量名映射,当 properties 的 key 与属性或成员变量名不对应时,
+ * 用 keyMap 把它们关联起来
+ * @return 生成的 Bean 实例
+ */
+ public static final B createBean(Class clazz, Map valueMap, Map keyMap)
+ {
+ B bean = null;
+
+ try
+ {
+ bean = clazz.getDeclaredConstructor().newInstance();
+ setPropertiesOrFieldValues(bean, valueMap, keyMap);
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return bean;
+ }
+
+ /** 创建指定类型的 Java Bean,并设置相关属性
+ *
+ * @param clazz : Bean 类型
+ * @param properties : 属性名 / 值映射
+ * 其中名称为 {@link String} 类型,与属性名称一致
+ * 属性值可能为以下 3 中类型:
+ * 1) 属性的实际类型:直接对属性赋值
+ * 2) {@link String} 类型:先执行自动类型转换再对属性赋值
+ * 3) {@link String}[] 类型:先执行自动类型转换再对属性赋值
+ * @return : 生成的 Bean 实例
+ */
+ public static final B createBeanByProperties(Class clazz, Map properties)
+ {
+ return createBeanByProperties(clazz, properties, null);
+ }
+
+ /** 创建指定类型的 Java Bean,并设置相关属性
+ *
+ * @param clazz : Bean 类型
+ * @param properties : 属性名 / 值映射
+ * 其中名称为 {@link String} 类型,与属性名称可能一直也可能不一致
+ * 属性值可能为以下 3 中类型:
+ * 1) 属性的实际类型:直接对属性赋值
+ * 2) {@link String} 类型:先执行自动类型转换再对属性赋值
+ * 3) {@link String}[] 类型:先执行自动类型转换再对属性赋值
+ * @param keyMap : properties.key / Bean 属性名映射,当 properties 的 key 与属性名不对应时,
+ * 用 keyMap 把它们关联起来
+ * @return 生成的 Bean 实例
+ */
+ public static final B createBeanByProperties(Class clazz, Map properties, Map keyMap)
+ {
+ B bean = null;
+
+ try
+ {
+ bean = clazz.getDeclaredConstructor().newInstance();
+ setProperties(bean, properties, keyMap);
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return bean;
+ }
+
+ /** 创建指定类型的 Java Bean,并设置相关属性
+ *
+ * @param clazz : Bean 类型
+ * @param values : 成员变量名 / 值映射
+ * 其中名称为 {@link String} 类型,与成员变量名称可能一直也可能不一致
+ * 成员变量值可能为以下 3 中类型:
+ * 1) 成员变量的实际类型:直接对成员变量赋值
+ * 2) {@link String} 类型:先执行自动类型转换再对成员变量值
+ * 3) {@link String}[] 类型:先执行自动类型转换再对成员变量值
+ * @return 生成的 Bean 实例
+ */
+ public static final B createBeanByFieldValues(Class clazz, Map values)
+ {
+ return createBeanByFieldValues(clazz, values, null);
+ }
+
+ /** 创建指定类型的 Java Bean,并设置相关属性
+ *
+ * @param clazz : Bean 类型
+ * @param values : 成员变量名 / 值映射
+ * 其中名称为 {@link String} 类型,与成员变量名称可能一直也可能不一致
+ * 成员变量值可能为以下 3 中类型:
+ * 1) 成员变量的实际类型:直接对成员变量赋值
+ * 2) {@link String} 类型:先执行自动类型转换再对成员变量值
+ * 3) {@link String}[] 类型:先执行自动类型转换再对成员变量值
+ * @param keyMap : values.key / Bean 成员变量名映射,当 values 的 key 与成员变量名不对应时,
+ * 用 keyMap 把它们关联起来
+ * @return 生成的 Bean 实例
+ */
+ public static final B createBeanByFieldValues(Class clazz, Map values, Map keyMap)
+ {
+ B bean = null;
+
+ try
+ {
+ bean = clazz.getDeclaredConstructor().newInstance();
+ setFieldValues(bean, values, keyMap);
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return bean;
+ }
+
+ /** 设置 Java Bean 的属性
+ *
+ * @param bean : Bean 实例
+ * @param properties : 属性名 / 值映射
+ * 其中名称为 {@link String} 类型,与属性名称一致
+ * 属性值可能为以下 3 中类型:
+ * 1) 属性的实际类型:直接对属性赋值
+ * 2) {@link String} 类型:先执行自动类型转换再对属性赋值
+ * 3) {@link String}[] 类型:先执行自动类型转换再对属性赋值
+ */
+ public static final void setProperties(Object bean, Map properties)
+ {
+ setProperties(bean, properties, null);
+ }
+
+ /** 设置 Java Bean 的属性
+ *
+ * @param bean : Bean 实例
+ * @param properties : 属性名 / 值映射
+ * 其中名称为 {@link String} 类型,与属性名称可能一直也可能不一致
+ * 属性值可能为以下 3 中类型:
+ * 1) 属性的实际类型:直接对属性赋值
+ * 2) {@link String} 类型:先执行自动类型转换再对属性赋值
+ * 3) {@link String}[] 类型:先执行自动类型转换再对属性赋值
+ * @param keyMap : properties.key / Bean 属性名映射,当 properties 的 key 与属性名不对应时,
+ * 用 keyMap 把它们关联起来
+ */
+ public static final void setProperties(Object bean, Map properties, Map keyMap)
+ {
+ if(properties == null || properties.isEmpty())
+ return;
+
+ Map