feat: 增加 aggr 聚合服务层,并将 bff 中的 聚合API 迁移到 aggr
diff --git a/aggr/admin/.gitignore b/aggr/admin/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/aggr/admin/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/aggr/admin/Dockerfile b/aggr/admin/Dockerfile
new file mode 100644
index 0000000..b91c9f4
--- /dev/null
+++ b/aggr/admin/Dockerfile
@@ -0,0 +1,21 @@
+FROM harbor.supwisdom.com/institute/openjdk:8-jre-alpine
+
+ENV ENABLE_JMX_SSL=false
+ENV JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker
+ENV SPRING_PROFILES_ACTIVE=docker
+
+ARG NAME
+ARG VERSION
+ARG JAR_FILE
+
+LABEL name=$NAME \
+      version=$VERSION
+
+EXPOSE 8080
+
+EXPOSE 8443
+
+COPY --chown=java-app:java-app target/${JAR_FILE} /home/java-app/lib/app.jar
+
+# COPY --chown=java-app:java-app target/doc /home/java-app/doc
+# COPY --chown=java-app:java-app target/api-docs /home/java-app/api-docs
diff --git a/aggr/admin/pom.xml b/aggr/admin/pom.xml
new file mode 100644
index 0000000..38a14f1
--- /dev/null
+++ b/aggr/admin/pom.xml
@@ -0,0 +1,210 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.supwisdom.institute</groupId>
+    <artifactId>sw-backend-parent</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <relativePath>../../</relativePath>
+  </parent>
+
+  <groupId>com.supwisdom.institute</groupId>
+  <artifactId>sw-backend-admin-aggr</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>Supwisdom Backend Framework Admin Aggregator API</name>
+  <description>Supwisdom Backend Framework Admin Aggregator API project</description>
+
+  <properties>
+    <start-class>com.supwisdom.institute.backend.admin.aggr.Application</start-class>
+  </properties>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+    </dependency>
+
+    <!-- 微服务 健康监控 -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-actuator</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springframework.cloud</groupId>
+      <artifactId>spring-cloud-starter-openfeign</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-online-doc</artifactId>
+    </dependency>
+
+
+    <!-- <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-mvc</artifactId>
+    </dependency> -->
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-object-mapper</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-i18n</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-lang</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>com.supwisdom.institute</groupId>
+      <artifactId>sw-backend-common-framework</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>io.springfox</groupId>
+      <artifactId>springfox-swagger2</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.springfox</groupId>
+      <artifactId>springfox-swagger-ui</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+
+    <!-- 热部署,无需重启项目 -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-devtools</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <finalName>${project.artifactId}</finalName>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-failsafe-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-release-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+      </plugin>
+
+
+      <!-- <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <version>2.4.3</version>
+        <configuration>
+          <encoding>${project.build.sourceEncoding}</encoding>
+        </configuration>
+        <executions>
+          <execution>
+            <id>copy-doc-resources</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <encoding>utf-8</encoding>
+              <outputDirectory>${basedir}/target/doc</outputDirectory>
+              <overwrite>true</overwrite>
+              <resources>
+                <resource>
+                  <directory>${basedir}/../doc</directory>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>copy-api-docs-resources</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <encoding>utf-8</encoding>
+              <outputDirectory>${basedir}/target/api-docs</outputDirectory>
+              <overwrite>true</overwrite>
+              <resources>
+                <resource>
+                  <directory>${basedir}/../api-docs</directory>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin> -->
+
+
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+
+      <plugin>
+        <groupId>com.spotify</groupId>
+        <artifactId>dockerfile-maven-plugin</artifactId>
+        <configuration>
+          <skip>false</skip>
+        </configuration>
+      </plugin>
+
+    </plugins>
+
+  </build>
+
+</project>
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/Application.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/Application.java
new file mode 100644
index 0000000..f3762ce
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/Application.java
@@ -0,0 +1,42 @@
+package com.supwisdom.institute.backend.admin.aggr;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import com.supwisdom.infras.online.doc.configuration.EnableInfrasOnlineDoc;
+import com.supwisdom.institute.backend.common.core.transmit.annotation.EnableSimpleUserTransmit;
+import com.supwisdom.institute.backend.common.framework.exception.EnableCustomExceptionHandler;
+
+@SpringBootApplication
+@EnableFeignClients
+
+@EnableSimpleUserTransmit
+@EnableCustomExceptionHandler
+
+@EnableInfrasOnlineDoc
+public class Application {
+
+  public static void main(String[] args) {
+    SpringApplication.run(Application.class, args);
+  }
+  
+  @Bean
+  public CorsFilter corsFilter() {
+    final CorsConfiguration config = new CorsConfiguration();
+    // config.setAllowCredentials(true);
+    config.addAllowedOrigin("*");
+    config.addAllowedHeader("*");
+    config.addAllowedMethod("*");
+
+    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+    source.registerCorsConfiguration("/v2/api-docs", config);
+
+    return new CorsFilter(source);
+  }
+
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/controller/.gitkeep b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/controller/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/controller/.gitkeep
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/controller/base/AdminBaseController.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/controller/base/AdminBaseController.java
new file mode 100644
index 0000000..2411d5e
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/controller/base/AdminBaseController.java
@@ -0,0 +1,19 @@
+package com.supwisdom.institute.backend.admin.aggr.apis.controller.base;
+
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.supwisdom.institute.backend.common.core.transmit.user.UserContext;
+
+@RestController
+@RequestMapping(value = "/v1/admin/base")
+public class AdminBaseController {
+  
+  @RequestMapping(method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public String hello() {
+    return "hello, " + UserContext.getUsername();
+  }
+
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/controller/biz/AdminBizController.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/controller/biz/AdminBizController.java
new file mode 100644
index 0000000..30dfbcd
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/controller/biz/AdminBizController.java
@@ -0,0 +1,26 @@
+package com.supwisdom.institute.backend.admin.aggr.apis.controller.biz;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.supwisdom.institute.backend.admin.aggr.apis.service.biz.BizService;
+
+@RestController
+@RequestMapping(value = "/api/bff/v1/admin/biz")
+public class AdminBizController {
+  
+  @Autowired
+  BizService bizService;
+
+  @RequestMapping(method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public String biz() {
+    
+    bizService.query(true, -1, -1);
+    
+    return "biz";
+  }
+
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/model/.gitkeep b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/model/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/model/.gitkeep
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/model/biz/Biz.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/model/biz/Biz.java
new file mode 100644
index 0000000..b36e117
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/model/biz/Biz.java
@@ -0,0 +1,37 @@
+package com.supwisdom.institute.backend.admin.aggr.apis.model.biz;
+
+import java.util.Date;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+public class Biz extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 8755876583168251137L;
+  
+  @Getter
+  @Setter
+  private String id;
+
+  @Getter
+  @Setter
+  private String name;
+  
+  @Getter
+  @Setter
+  private Boolean bool;
+  
+  @Getter
+  @Setter
+  private Date date;
+
+  @Getter
+  @Setter
+  private Integer num;
+
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/.gitkeep b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/.gitkeep
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/biz/BizRemoteFallbackFactory.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/biz/BizRemoteFallbackFactory.java
new file mode 100644
index 0000000..22447f0
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/biz/BizRemoteFallbackFactory.java
@@ -0,0 +1,61 @@
+package com.supwisdom.institute.backend.admin.aggr.apis.remote.biz;
+
+import org.springframework.stereotype.Component;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.aggr.apis.model.biz.Biz;
+import com.supwisdom.institute.backend.admin.aggr.apis.remote.exception.FallbackError;
+
+import feign.hystrix.FallbackFactory;
+
+@Component
+public class BizRemoteFallbackFactory implements FallbackFactory<BizRemoteFeignClient> {
+
+  @Override
+  public BizRemoteFeignClient create(Throwable cause) {
+    return new BizRemoteFeignClient() {
+
+      @Override
+      public JSONObject query(boolean loadAll, int pageIndex, int pageSize) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject load(String id) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject create(Biz biz) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject update(String id, Biz biz) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject delete(String id) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+      
+    };
+  }
+
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/biz/BizRemoteFeignClient.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/biz/BizRemoteFeignClient.java
new file mode 100644
index 0000000..9361f45
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/biz/BizRemoteFeignClient.java
@@ -0,0 +1,49 @@
+package com.supwisdom.institute.backend.admin.aggr.apis.remote.biz;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.aggr.apis.model.biz.Biz;
+
+@FeignClient(
+    name = "biz-biz-remote-feign-client",
+    url = "${sw-backend-biz-api.uri}/v1/admin/biz",
+    fallbackFactory = BizRemoteFallbackFactory.class
+)
+public interface BizRemoteFeignClient {
+  
+  @RequestMapping(method = RequestMethod.GET)
+  JSONObject query(
+      @RequestParam(name = "loadAll") boolean loadAll,
+      @RequestParam(name = "pageIndex") int pageIndex,
+      @RequestParam(name = "pageSize") int pageSize
+      
+  );
+  
+  @RequestMapping(method = RequestMethod.GET, path = "/{id}")
+  JSONObject load(
+      @PathVariable(name = "id") String id
+  );
+
+  @RequestMapping(method = RequestMethod.POST)
+  JSONObject create(
+      @RequestBody Biz biz
+  );
+
+  @RequestMapping(method = RequestMethod.PUT, path = "/{id}")
+  JSONObject update(
+      @PathVariable(name = "id") String id,
+      @RequestBody Biz biz
+  );
+  
+  @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
+  JSONObject delete(
+      @PathVariable(name = "id") String id
+  );
+
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/exception/FallbackError.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/exception/FallbackError.java
new file mode 100644
index 0000000..51ae782
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/remote/exception/FallbackError.java
@@ -0,0 +1,21 @@
+package com.supwisdom.institute.backend.admin.aggr.apis.remote.exception;
+
+import com.alibaba.fastjson.JSONObject;
+
+public class FallbackError {
+  
+  private FallbackError() {
+    
+  }
+  
+  public static JSONObject defaultErrorJson(Throwable cause) {
+    JSONObject error = new JSONObject();
+    
+    error.put("code", -1);
+    error.put("message", cause.getMessage());
+    error.put("error", cause.getMessage());
+    
+    return error;
+  }
+
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/service/.gitkeep b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/service/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/service/.gitkeep
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/service/biz/BizService.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/service/biz/BizService.java
new file mode 100644
index 0000000..49baee2
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/service/biz/BizService.java
@@ -0,0 +1,32 @@
+package com.supwisdom.institute.backend.admin.aggr.apis.service.biz;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.aggr.apis.remote.biz.BizRemoteFeignClient;
+import com.supwisdom.institute.backend.admin.aggr.apis.vo.biz.response.data.BizQueryResponseData;
+
+@Service
+public class BizService {
+  
+  @Autowired
+  private BizRemoteFeignClient bizRemote;
+  
+  public BizQueryResponseData query(boolean loadAll, int pageIndex, int pageSize) {
+    
+    JSONObject jsonObject = bizRemote.query(loadAll, pageIndex, pageSize);
+    if (jsonObject == null) {
+      return null;
+    }
+    
+    if (jsonObject.getIntValue("code") == 0) {
+      JSONObject data = jsonObject.getJSONObject("data");
+      
+      return data.toJavaObject(BizQueryResponseData.class);
+    }
+    
+    return null;
+  }
+
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/vo/.gitkeep b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/vo/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/vo/.gitkeep
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/vo/biz/response/data/BizQueryResponseData.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/vo/biz/response/data/BizQueryResponseData.java
new file mode 100644
index 0000000..815cc6a
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/apis/vo/biz/response/data/BizQueryResponseData.java
@@ -0,0 +1,45 @@
+package com.supwisdom.institute.backend.admin.aggr.apis.vo.biz.response.data;
+
+import java.util.List;
+import java.util.Map;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.admin.aggr.apis.model.biz.Biz;
+import com.supwisdom.institute.backend.common.framework.vo.response.data.IApiQueryResponseData;
+
+public class BizQueryResponseData implements IApiQueryResponseData<Biz> {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -380945463584664943L;
+
+  @Getter
+  private boolean loadAll;
+  @Getter
+  private int pageIndex;
+  @Getter
+  private int pageSize;
+  @Getter
+  private Map<String, Object> mapBean;
+  @Getter
+  private Map<String, String> orderBy;
+  
+  @Getter
+  @Setter
+  private int pageCount;
+  @Getter
+  @Setter
+  private long recordCount;
+  
+  @Getter
+  @Setter
+  private int currentItemCount;
+  
+  @Getter
+  @Setter
+  private List<Biz> items;
+  
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/configuration/FeignClientConfiguration.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/configuration/FeignClientConfiguration.java
new file mode 100644
index 0000000..6bcf4c1
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/configuration/FeignClientConfiguration.java
@@ -0,0 +1,70 @@
+package com.supwisdom.institute.backend.admin.aggr.configuration;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.SSLContexts;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.ResourceUtils;
+
+import feign.Client;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Configuration
+public class FeignClientConfiguration {
+
+  @Bean
+  public Client feignClient(
+      @Value("${cas-server-sa-api.client-auth.enabled:false}") boolean enabled,
+      @Value("${cas-server-sa-api.client-auth.key-password:}") String keyPassword,
+      @Value("${cas-server-sa-api.client-auth.key-store:}") String keyStore,
+      @Value("${cas-server-sa-api.client-auth.key-store-password:}") String keyStorePassword,
+      @Value("${cas-server-sa-api.client-auth.trust-store:}") String trustStore,
+      @Value("${cas-server-sa-api.client-auth.trust-store-password:}") String trustStorePassword) {
+    
+    if (!enabled) {
+      return new Client.Default(null, null);
+    }
+    
+    if (keyStore == null || keyStore.isEmpty()) {
+      return new Client.Default(null, null);
+    } else {
+      try {
+        SSLContextBuilder sslContextBuilder = SSLContexts.custom();
+        if (trustStore == null || trustStore.isEmpty()) {
+        } else {
+          sslContextBuilder
+//            .loadTrustMaterial(TrustAllStrategy.INSTANCE)
+            .loadTrustMaterial(
+                ResourceUtils.getFile(trustStore),
+                trustStorePassword.toCharArray()
+            );
+        }
+        
+        sslContextBuilder
+          .loadKeyMaterial(
+              ResourceUtils.getFile(keyStore),
+              keyStorePassword.toCharArray(),
+              keyPassword.toCharArray());
+        
+        SSLContext sslContext = sslContextBuilder.build();
+        
+        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+
+        Client trustSSLSockets = new Client.Default(sslSocketFactory, new NoopHostnameVerifier());
+        log.info("feignClient load with ssl.");
+        return trustSSLSockets;
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+    }
+    
+    return new Client.Default(null, null);
+  }
+
+}
diff --git a/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/configuration/Swagger2Config.java b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/configuration/Swagger2Config.java
new file mode 100644
index 0000000..d6311e2
--- /dev/null
+++ b/aggr/admin/src/main/java/com/supwisdom/institute/backend/admin/aggr/configuration/Swagger2Config.java
@@ -0,0 +1,63 @@
+package com.supwisdom.institute.backend.admin.aggr.configuration;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger.web.UiConfiguration;
+import springfox.documentation.swagger.web.UiConfigurationBuilder;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class Swagger2Config {
+
+  @Value("${swagger2.apis.basePackage:com.supwisdom.institute}")
+  private String basePackage;
+
+  @Bean
+  public Docket createRestApi() {
+    return new Docket(DocumentationType.SWAGGER_2)
+        .apiInfo(apiInfo())
+        .select()
+        .apis(RequestHandlerSelectors.basePackage(basePackage))
+        .paths(PathSelectors.any())
+        .build()
+        ;
+  }
+
+  private ApiInfo apiInfo() {
+    Contact contact = new Contact("Backend Admin Aggregator API", "https://sw-backend-aggr.supwisdom.com/swagger-ui.html", ""); // name, url, email
+    return new ApiInfoBuilder()
+        .title("Backend Admin Aggregator APIs")
+        .description("管理后台 - 聚合接口")
+        .termsOfServiceUrl("http://www.supwisdom.com/")
+        .contact(contact)
+        .version("1.0")
+        .build();
+  }
+
+  @Bean
+  UiConfiguration uiConfig() {
+    
+    return UiConfigurationBuilder.builder().build();
+    
+//    return new UiConfiguration(null, // url
+//        "none", // docExpansion => none | list
+//        "alpha", // apiSorter => alpha
+//        "schema", // defaultModelRendering => schema
+//        UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS,
+//        false, // enableJsonEditor => true || false
+//        true, // showRequestHeaders => true | false
+//        60000L); // requestTimeout => in milliseconds, defaults to null
+//    // (uses jquery xh timeout)
+  }
+
+}
diff --git a/aggr/admin/src/main/resources/application-docker.yml b/aggr/admin/src/main/resources/application-docker.yml
new file mode 100644
index 0000000..a46fee8
--- /dev/null
+++ b/aggr/admin/src/main/resources/application-docker.yml
@@ -0,0 +1,68 @@
+server:
+  port: ${SERVER_PORT:8443}
+  ssl:
+    enabled: ${SSL_ENABLED:true}
+    clientAuth: NEED
+    key-store: ${SSL_KEYSTORE_FILE:file:/certs/server/server.keystore}
+    key-store-password: ${SSL_KEYSTORE_PASSWORD:}
+    trust-store: ${SSL_TRUSTSTORE_FILE:file:/certs/server/server.truststore}
+    trust-store-password: ${SSL_TRUSTSTORE_PASSWORD:}
+  tomcat: 
+    accesslog: 
+      enabled: ${TOMCAT_ACCESSLOG_ENABLED:false}
+      buffered: ${TOMCAT_ACCESSLOG_BUFFERED:true}
+      directory: ${TOMCAT_ACCESSLOG_DIR:log}
+      prefix: ${TOMCAT_ACCESSLOG_PREFIX:sa-api-accesslog}
+      suffix: ${TOMCAT_ACCESSLOG_SUFFIX:.log}
+      file-date-format: ${TOMCAT_ACCESSLOG_FILE_DATE_FORMAT:.yyyy-MM-dd}
+      rotate: ${TOMCAT_ACCESSLOG_ROTATE:true}
+
+
+##
+# logging
+#
+logging:
+  level:
+    root: INFO
+    com.supwisdom: INFO
+
+
+spring:
+  jackson:
+    time-zone: ${JACKSON_TIME_ZONE:Asia/Shanghai}
+
+
+##
+# online-doc
+#
+infras.online-doc.enabled: ${INFRAS_ONLINE_DOC_ENABLED:false}
+infras.online-doc.md-docs.staitc.path: ${INFRAS_ONLINE_DOC_MD_DOCS_STATIC_PATH:/doc/}
+infras.online-doc.api-docs.staitc.path: ${INFRAS_ONLINE_DOC_API_DOCS_STATIC_PATH:/api-docs/}
+
+
+##
+# server url for feign
+#
+sw-backend-base-api:
+  uri: ${SW_BACKEND_BASE_API_URI:https://sw-backend-admin-sa}
+  client-auth:
+    enabled: ${CASSERVER_SA_API_CLIENT_AUTH_ENABLED:true}
+    key-password: ${CASSERVER_SA_API_CLIENT_AUTH_KEY_PASSWORD:}
+    key-store: ${CASSERVER_SA_API_CLIENT_AUTH_KEYSTORE_FILE:file:/certs/common/common.keystore}
+    key-store-password: ${CASSERVER_SA_API_CLIENT_AUTH_KEYSTORE_PASSWORD:}
+    trust-store: ${CASSERVER_SA_API_CLIENT_AUTH_TRUSTSTORE_FILE:file:/certs/common/common.truststore}
+    trust-store-password: ${CASSERVER_SA_API_CLIENT_AUTH_TRUSTSTORE_PASSWORD:}
+  
+sw-backend-system-api.uri: http://localhost:8081
+sw-backend-biz-api.uri: http://localhost:8081
+
+sw-backend-api-admin:
+  server:
+    url: ${CASSERVER_SA_API_SERVER_URL:https://sw-backend}
+  client-auth:
+    enabled: ${CASSERVER_SA_API_CLIENT_AUTH_ENABLED:true}
+    key-password: ${CASSERVER_SA_API_CLIENT_AUTH_KEY_PASSWORD:}
+    key-store: ${CASSERVER_SA_API_CLIENT_AUTH_KEYSTORE_FILE:file:/certs/common/common.keystore}
+    key-store-password: ${CASSERVER_SA_API_CLIENT_AUTH_KEYSTORE_PASSWORD:}
+    trust-store: ${CASSERVER_SA_API_CLIENT_AUTH_TRUSTSTORE_FILE:file:/certs/common/common.truststore}
+    trust-store-password: ${CASSERVER_SA_API_CLIENT_AUTH_TRUSTSTORE_PASSWORD:}
diff --git a/aggr/admin/src/main/resources/application.yml b/aggr/admin/src/main/resources/application.yml
new file mode 100644
index 0000000..e0683b0
--- /dev/null
+++ b/aggr/admin/src/main/resources/application.yml
@@ -0,0 +1,39 @@
+server:
+  port: 8082
+  ssl:
+    enabled: false
+
+
+##
+# logging
+#
+logging:
+  level:
+    root: INFO
+    com.supwisdom: DEBUG
+#    org.springframework.web: INFO
+#    org.springframework.cloud.openfeign: INFO
+
+
+swagger2.apis.basePackage: com.supwisdom.institute
+
+
+spring:
+  jackson:
+    time-zone: Asia/Shanghai
+
+
+##
+# infras.online-doc
+#
+infras.online-doc.enabled: true
+infras.online-doc.md-docs.staitc.path: /Users/loie/c/work/git/institute/sw-backend/doc/
+infras.online-doc.api-docs.staitc.path: /Users/loie/c/work/git/institute/sw-backend/api-docs/
+
+
+##
+# server url for feign
+#
+sw-backend-base-api.uri: http://localhost:8081
+sw-backend-system-api.uri: http://localhost:8081
+sw-backend-biz-api.uri: http://localhost:8081
diff --git a/aggr/admin/src/main/resources/bootstrap.yml b/aggr/admin/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..b2a926b
--- /dev/null
+++ b/aggr/admin/src/main/resources/bootstrap.yml
@@ -0,0 +1,3 @@
+spring:
+  application:
+    name: sw-backend-admin-aggr
diff --git a/aggr/pom.xml b/aggr/pom.xml
new file mode 100644
index 0000000..1ec35e6
--- /dev/null
+++ b/aggr/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  
+  <parent>
+    <groupId>com.supwisdom.institute</groupId>
+    <artifactId>sw-backend-parent</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+  
+  <groupId>com.supwisdom.institute</groupId>
+  <artifactId>sw-backend-aggr-parent</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <name>Supwisdom Backend Framework Aggregator API</name>
+  <description>Supwisdom Backend Framework Aggregator API project</description>
+
+  <modules>
+    <module>admin</module>
+  </modules>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>