├── .gitignore ├── README.md ├── dynamic-facade ├── pom.xml └── src │ └── main │ └── java │ └── io │ └── sofastack │ └── dynamic │ ├── facade │ └── StrategyService.java │ └── model │ └── ProductInfo.java ├── dynamic-provider ├── pom.xml └── src │ └── main │ ├── java │ └── io │ │ └── sofastack │ │ └── dynamic │ │ └── provider │ │ ├── ProviderApplication.java │ │ ├── controller │ │ └── ModuleController.java │ │ └── impl │ │ └── StrategyServiceImpl.java │ └── resources │ └── application.properties ├── dynamic-stock-mng ├── pom.xml └── src │ └── main │ ├── java │ └── io │ │ └── sofastack │ │ └── stockmng │ │ ├── StockMngApplication.java │ │ ├── controller │ │ └── IndexController.java │ │ └── data │ │ └── DatabaseSeed.java │ └── resources │ ├── application.properties │ ├── logback-spring.xml │ └── templates │ └── index.html ├── formatter.xml └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | bin 3 | bak 4 | .pmd 5 | .project 6 | .settings 7 | .classpath 8 | .idea.xml 9 | .idea 10 | *.class 11 | *.bak 12 | *.iml 13 | *.ipr 14 | *.iws 15 | bak 16 | null/ 17 | tree.log 18 | tmp/ 19 | velocity.log 20 | .DS_Store 21 | deploy.sh 22 | logs 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 该工程已经作为 [Koupleless](https://github.com/koupleless/koupleless) 的部分 samples 工程,已经迁移到最新地址,该工程已不再维护,请跳转到这里 [https://github.com/koupleless/koupleless/tree/master/samples/sofaboot-samples](https://github.com/koupleless/koupleless/tree/master/samples/sofaboot-samples) 2 | 3 | 4 | 5 | ## 实验内容 6 | 7 | 通过 [SOFAArk](https://github.com/sofastack/sofa-ark) 提供的动态模块能力,实现商品列表排序策略的动态变更。通过在不重启宿主机,不更改应用配置的情况下实现应用行为的改变。 8 | 9 | ## 任务 10 | 11 | ### 1、任务准备 12 | 13 | 从 github 上将 demo 工程克隆到本地 14 | 15 | ```bash 16 | git clone git@github.com:sofastack-guides/sofa-ark-dynamic-guides.git 17 | ``` 18 | 19 | 然后将工程导入到 IDEA 或者 eclipse,打开工程后,工程目录结构如下: 20 | 21 | ```bash 22 | ├── dynamic-facade 23 | ├── dynamic-provider 24 | ├── dynamic-stock-mng 25 | └── pom.xml 26 | ``` 27 | 28 | * dynamic-facade 定义了一个 Java 接口 io.sofastack.dynamic.facade.StrategyService,该接口用于对传入的商品列表进排序并返回 29 | * dynamic-provider 实现了 dynamic-facade 定义的接口,并将实现类发布成一个服务 30 | * dynamic-stock-mng 宿主应用,提供一个 web 页面,用于展示实验效果 31 | 32 | ### 2、将 dynamic-provider 打包成 ark biz 33 | 在 dynamic-provider/pom.xml 中,增加 ark 打包插件,该模块实现了宿主应用的一个接口,同时暴露一个rest服务,进行配置: 34 | 35 | ![image.png](https://gw.alipayobjects.com/mdn/rms_ff360b/afts/img/A*y2BvRKG14JUAAAAAAAAAAABkARQnAQ) 36 | 37 | 38 | ```xml 39 | 40 | 41 | 42 | com.alipay.sofa 43 | sofa-ark-maven-plugin 44 | 45 | 46 | default-cli 47 | 48 | repackage 49 | 50 | 51 | 52 | 53 | true 54 | ./target 55 | dynamic-provider 56 | provider 57 | true 58 | 59 | 60 | 61 | ``` 62 | 63 | ### 3、构建宿主应用 64 | 65 | 在已下载下来的工程中,dynamic-stock-mng 作为实验的宿主应用工程模型。通过此步骤,将 dynamic-stock-mng 构建成为动态模块的宿主应用。在SOFAArk2.0之后,宿主应用已经与普通应用并无差别,主要体现在下面会介绍到的宿主应用的打包方式、构建产物和启动方式。 66 | 67 | #### step1 : 引入动态模块依赖 68 | 69 | > 动态模块是通过 SOFAArk 组件来实现的,因此需要引入 SOFAArk 相关的依赖即可。关于 SOFAArk 可以参考[SOFABoot 类隔离](https://www.sofastack.tech/projects/sofa-boot/sofa-ark-readme/) 70 | 一节进行了解。 71 | 72 | ![image.png](https://gw.alipayobjects.com/mdn/rms_565baf/afts/img/A*lM_1SoNIXIYAAAAAAAAAAABkARQnAQ) 73 | 74 | * 宿主应用打包插件 75 | 76 | ```xml 77 | 78 | 79 | 80 | org.springframework.boot 81 | spring-boot-maven-plugin 82 | 83 | target 84 | ark-biz 85 | 86 | 87 | 88 | package 89 | 90 | repackage 91 | 92 | 93 | 94 | 95 | 96 | ``` 97 | 98 | ### 4、打包 & 启动宿主应用 99 | 100 | #### 启动宿主应用 101 | SOFAArk 2.0之后宿主应用可以直接启动,可以在IDE里增加`-Dsofa.ark.embed.enable=true` 启动参数,直接启动 StockMngApplication 类。 102 | 103 | 启动成功之后日志信息如下: 104 | 105 | ![image.png](https://gw.alipayobjects.com/mdn/rms_565baf/afts/img/A*3N_nS6P223IAAAAAAAAAAABkARQnAQ) 106 | 107 | ### 5、 引入默认的排序策略模块 108 | dynamic-provider 提供的 io.sofastack.dynamic.facade.StrategyService 实现类返回了默认排序。 109 | 110 | 执行 mvn clean package 进行打包,此时可以打包出新版本 dynamic-provider ark biz包,如下图所示: 111 | ![image.png](https://gw.alipayobjects.com/mdn/rms_c69e1f/afts/img/A*fbgOSpPdAIkAAAAAAAAAAABkARQnAQ) 112 | 113 | telnet 连接 SOFAArk,安装默认版本 dynamic-provider: 114 | ```bash 115 | ## 连接 SOFAArk telnet 116 | > telnet localhost 1234 117 | 118 | ## 安装新版本 dynamic-provider 119 | sofa-ark>biz -i file:///Users/sample/sofachannel-demo/dynamic-provider/target/dynamic-provider-1.0.0-ark-biz.jar 120 | Start to process install command now, pls wait and check. 121 | 122 | ## 查看安装的模块信息 123 | sofa-ark>biz -a 124 | stock-mng:1.0.0:activated 125 | dynamic-provider:1.0.0:activated 126 | biz count = 2 127 | ``` 128 | 129 | 访问 http://localhost:8080 ,现在展示的是默认的排列顺序,如下所示: 130 | 131 | ![image.png](https://gw.alipayobjects.com/mdn/rms_c69e1f/afts/img/A*HpKuR7Wn44UAAAAAAAAAAABkARQnAQ) 132 | 133 | ### 6、新建按照销量排序策略模块 134 | dynamic-provider 提供的 io.sofastack.dynamic.facade.StrategyService 实现类返回了默认排序,现在我们要开发一个新版本模块,这个新版本模块会按照销量高低返回商品列表。 135 | 136 | 首先,修改 io.sofastack.dynamic.provider.impl.StrategyServiceImpl 实现类如下: 137 | 138 | ```java 139 | @Service 140 | @SofaService 141 | public class StrategyServiceImpl implements StrategyService { 142 | @Override 143 | public List strategy(List products) { 144 | Collections.sort(products, (m, n) -> n.getOrderCount() - m.getOrderCount()); 145 | products.stream().forEach(p -> p.setName(p.getName()+"("+p.getOrderCount()+")")); 146 | return products; 147 | } 148 | } 149 | ``` 150 | 151 | 然后,修改 dynamic-provider 版本号 2.0.0: 152 | 153 | ```xml 154 | 2.0.0 155 | ``` 156 | 157 | 最后,由于本Demo引入web-ark-plugin,所以每个模块会复用同一个tomcat实例,所以需要更改server的webContextPath,搜索并修改dynamic-provider的pom由原来的 158 | 159 | ```xml 160 | provider 161 | ``` 162 | 换成一个不同的webContextPath 163 | ```xml 164 | provider-1 165 | ``` 166 | 167 | 配置完成之后,执行 mvn clean package 进行打包,此时可以打包出新版本 dynamic-provider ark biz包,如下图所示: 168 | ![pic](https://gw.alipayobjects.com/mdn/rms_c69e1f/afts/img/A*lWUSQb95azoAAAAAAAAAAABkARQnAQ) 169 | 170 | 171 | telnet 连接 SOFAArk,安装新版本 dynamic-provider: 172 | ```bash 173 | ## 连接 SOFAArk telnet 174 | > telnet localhost 1234 175 | 176 | ## 安装新版本 dynamic-provider 177 | sofa-ark>biz -i file:///Users/sample/sofachannel-demo/dynamic-provider/target/dynamic-provider-2.0.0-ark-biz.jar 178 | Start to process install command now, pls wait and check. 179 | 180 | ## 查看安装的模块信息 181 | sofa-ark>biz -a 182 | stock-mng:1.0.0:activated 183 | dynamic-provider:2.0.0:resolved 184 | dynamic-provider:1.0.0:activated 185 | biz count = 3 186 | 187 | ## 切换 activated 模块 188 | sofa-ark>biz -o dynamic-provider:2.0.0 189 | Start to process switch command now, pls wait and check. 190 | ``` 191 | 192 | 切换完模块后,访问 http://localhost:8080 ,现在展示的是列表编程按照销量进行排序,如下所示: 193 | 如果要访问模块中的rest请求,请带上模块 sofa-ark-maven-plugin 里定义的webContextPath 194 | 195 | ![image.png](https://gw.alipayobjects.com/mdn/rms_c69e1f/afts/img/A*vqEJQ4775u4AAAAAAAAAAABkARQnAQ) 196 | 197 | 198 | -------------------------------------------------------------------------------- /dynamic-facade/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | sofachannel-demo 7 | io.sofastack 8 | 1.0.0 9 | 10 | 4.0.0 11 | 12 | dynamic-facade 13 | 14 | -------------------------------------------------------------------------------- /dynamic-facade/src/main/java/io/sofastack/dynamic/facade/StrategyService.java: -------------------------------------------------------------------------------- 1 | package io.sofastack.dynamic.facade; 2 | 3 | import io.sofastack.dynamic.model.ProductInfo; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 对传入的商品列表进行排序并返回 9 | * 10 | * @author caojie.cj@antfin.com 11 | * @since 2020/2/11 12 | */ 13 | public interface StrategyService { 14 | List strategy(List products); 15 | } 16 | -------------------------------------------------------------------------------- /dynamic-facade/src/main/java/io/sofastack/dynamic/model/ProductInfo.java: -------------------------------------------------------------------------------- 1 | package io.sofastack.dynamic.model; 2 | 3 | /** 4 | * 商品信息类 5 | * 6 | * @author caojie.cj@antfin.com 7 | * @since 2020/2/11 8 | */ 9 | public class ProductInfo { 10 | private String name; 11 | private String author; 12 | private String src; 13 | private Integer orderCount; 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | public String getSrc() { 24 | return src; 25 | } 26 | 27 | public void setSrc(String src) { 28 | this.src = src; 29 | } 30 | 31 | public String getAuthor() { 32 | return author; 33 | } 34 | 35 | public void setAuthor(String author) { 36 | this.author = author; 37 | } 38 | 39 | public Integer getOrderCount() { 40 | return orderCount; 41 | } 42 | 43 | public void setOrderCount(Integer orderCount) { 44 | this.orderCount = orderCount; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /dynamic-provider/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | sofachannel-demo 7 | io.sofastack 8 | 1.0.0 9 | 10 | 4.0.0 11 | 12 | dynamic-provider 13 | 1.0.0 14 | 15 | 16 | io.sofastack 17 | dynamic-facade 18 | 1.0.0 19 | provided 20 | 21 | 22 | com.alipay.sofa 23 | runtime-sofa-boot-starter 24 | provided 25 | 26 | 27 | com.alipay.sofa 28 | healthcheck-sofa-boot-starter 29 | provided 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-web 34 | provided 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | com.alipay.sofa 43 | sofa-ark-maven-plugin 44 | 2.2.1 45 | 46 | 47 | default-cli 48 | 49 | repackage 50 | 51 | 52 | 53 | 54 | true 55 | ./target 56 | dynamic-provider 57 | provider 58 | true 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /dynamic-provider/src/main/java/io/sofastack/dynamic/provider/ProviderApplication.java: -------------------------------------------------------------------------------- 1 | package io.sofastack.dynamic.provider; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.boot.builder.SpringApplicationBuilder; 5 | import org.springframework.core.io.DefaultResourceLoader; 6 | import org.springframework.core.io.ResourceLoader; 7 | 8 | /** 9 | * dynamic-provider 启动类 10 | * 11 | * @author caojie.cj@antfin.com 12 | * @since 2020/2/11 13 | */ 14 | @SpringBootApplication 15 | public class ProviderApplication { 16 | public static void main(String[] args) { 17 | SpringApplicationBuilder builder = new SpringApplicationBuilder(ProviderApplication.class); 18 | ResourceLoader resourceLoader = new DefaultResourceLoader(ProviderApplication.class.getClassLoader()); 19 | builder.resourceLoader(resourceLoader); 20 | builder.build().run(args); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /dynamic-provider/src/main/java/io/sofastack/dynamic/provider/controller/ModuleController.java: -------------------------------------------------------------------------------- 1 | package io.sofastack.dynamic.provider.controller; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | /** 7 | * @author: guolei.sgl (glmapper_2018@163.com) 2020/6/13 2:36 PM 8 | * @since: 9 | **/ 10 | @RestController 11 | // please add biz webContextPath which defined in sofa-ark-maven-plugin ahead of this 12 | // for example: this can be accessed by 'provider/api/module' 13 | @RequestMapping("api") 14 | public class ModuleController { 15 | @RequestMapping("module") 16 | public String master(){ 17 | return "SUCCESS FROM MODULE"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /dynamic-provider/src/main/java/io/sofastack/dynamic/provider/impl/StrategyServiceImpl.java: -------------------------------------------------------------------------------- 1 | package io.sofastack.dynamic.provider.impl; 2 | 3 | import com.alipay.sofa.runtime.api.annotation.SofaService; 4 | import io.sofastack.dynamic.facade.StrategyService; 5 | import io.sofastack.dynamic.model.ProductInfo; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | /** 12 | * 对传入的商品列表进行排序实现类 13 | * 14 | * @author caojie.cj@antfin.com 15 | * @since 2020/2/11 16 | */ 17 | @Service 18 | @SofaService 19 | public class StrategyServiceImpl implements StrategyService { 20 | @Override 21 | public List strategy(List products) { 22 | // Collections.sort(products, (m, n) -> n.getOrderCount() - m.getOrderCount()); 23 | // products.stream().forEach(p -> p.setName(p.getName()+"("+p.getOrderCount()+")")); 24 | return products; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dynamic-provider/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=dynamic-provider 2 | logging.path=./logs/provider -------------------------------------------------------------------------------- /dynamic-stock-mng/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | sofachannel-demo 7 | io.sofastack 8 | 1.0.0 9 | 10 | 4.0.0 11 | dynamic-stock-mng 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-thymeleaf 16 | 17 | 18 | com.alipay.sofa 19 | healthcheck-sofa-boot-starter 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-web 24 | 25 | 26 | com.alipay.sofa 27 | runtime-sofa-boot-starter 28 | 29 | 30 | io.sofastack 31 | dynamic-facade 32 | 33 | 34 | com.alibaba 35 | fastjson 36 | 37 | 38 | 39 | com.alipay.sofa 40 | sofa-ark-all 41 | ${sofa.ark.version} 42 | 43 | 44 | ch.qos.logback 45 | logback-core 46 | 47 | 48 | ch.qos.logback 49 | logback-classic 50 | 51 | 52 | 53 | 54 | com.alipay.sofa 55 | sofa-ark-compatible-springboot2 56 | ${sofa.ark.version} 57 | 58 | 59 | com.alipay.sofa 60 | sofa-ark-springboot-starter 61 | ${sofa.ark.version} 62 | 63 | 64 | com.alipay.sofa 65 | sofa-ark-compatible-springboot1 66 | 67 | 68 | 69 | 70 | 71 | 72 | com.alipay.sofa 73 | web-ark-plugin 74 | 75 | 76 | com.alipay.sofa 77 | runtime-sofa-boot-plugin 78 | 79 | 80 | 81 | 82 | com.alipay.sofa 83 | hessian 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | org.springframework.boot 92 | spring-boot-maven-plugin 93 | 94 | target 95 | ark-biz 96 | 97 | 98 | 99 | package 100 | 101 | repackage 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /dynamic-stock-mng/src/main/java/io/sofastack/stockmng/StockMngApplication.java: -------------------------------------------------------------------------------- 1 | package io.sofastack.stockmng; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * dynamic-stock-mng 启动类 8 | * 9 | * @author caojie.cj@antfin.com 10 | * @since 2020/2/11 11 | */ 12 | @SpringBootApplication 13 | public class StockMngApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(StockMngApplication.class, args); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /dynamic-stock-mng/src/main/java/io/sofastack/stockmng/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package io.sofastack.stockmng.controller; 2 | 3 | import com.alipay.sofa.runtime.api.annotation.SofaReference; 4 | import io.sofastack.dynamic.facade.StrategyService; 5 | import io.sofastack.dynamic.model.ProductInfo; 6 | import io.sofastack.stockmng.data.DatabaseSeed; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.ui.Model; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * index controller 16 | * 17 | * @author caojie.cj@antfin.com 18 | * @since 2020/2/11 19 | */ 20 | @Controller 21 | public class IndexController { 22 | @SofaReference 23 | private StrategyService strategyService; 24 | 25 | @RequestMapping("/") 26 | public String index(Model model) { 27 | model.addAttribute("productList", strategyService.strategy(initProducts())); 28 | return "index"; 29 | } 30 | 31 | /** 32 | * 初始化默认展示列表,为了实验效果,此处初始化的列表与实际列表是相反的,但是实际排序结果与现场购买订单直接挂钩 33 | * 34 | * @return 35 | */ 36 | private List initProducts() { 37 | List products = new ArrayList<>(5); 38 | for (int i = 4; i >= 0; i--) { 39 | ProductInfo productInfo = new ProductInfo(); 40 | productInfo.setName(DatabaseSeed.name[i]); 41 | productInfo.setOrderCount(DatabaseSeed.orderCount[i]); 42 | productInfo.setSrc(DatabaseSeed.imageUrls[i]); 43 | productInfo.setAuthor(DatabaseSeed.authors[i]); 44 | products.add(productInfo); 45 | } 46 | return products; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /dynamic-stock-mng/src/main/java/io/sofastack/stockmng/data/DatabaseSeed.java: -------------------------------------------------------------------------------- 1 | package io.sofastack.stockmng.data; 2 | 3 | /** 4 | * 数据存储类 5 | * 6 | * @author caojie.cj@antfin.com 7 | * @since 2020/2/11 8 | */ 9 | public class DatabaseSeed { 10 | public static String[] name = new String[] { "未来架构: 从服务化到云原生", 11 | "Cloud Native Go: 构建基于Go和React的云原生Web应用与微服务", 12 | "云原生Java: Spring Boot、Spring Cloud与Cloud Foundry弹性系统设计", 13 | "Python云原生: 构建应对海量用户数据的高可扩展Web应用", "深入浅出Istio: Service Mesh快速入门与实践" }; 14 | 15 | public static Integer[] orderCount = new Integer[] { 86, 34, 128, 16 | 57, 181 }; 17 | 18 | public static String[] authors = new String[] { "张亮, 吴晟, 敖小剑, 宋净超", "Kevin Hoffman, 宋净超", "Josh Long, 张若飞, 宋净超", 19 | "Manish Sethi, 宋净超", "崔秀龙" }; 20 | 21 | public static String[] imageUrls = new String[] { "http://reserved-antcloud-cnshnfpub-opsware-v2.oss-cn-shanghai.aliyuncs.com/fas/books/1.png?OSSAccessKeyId=RZU9wKztYEqaBQGB&Expires=1647166160&Signature=xCS%2FpJtY8%2FVcdbLqfjHUp6z%2FoOw%3D", "http://reserved-antcloud-cnshnfpub-opsware-v2.oss-cn-shanghai.aliyuncs.com/fas/books/2.png?OSSAccessKeyId=RZU9wKztYEqaBQGB&Expires=1647166182&Signature=U4ep6Dsh4w8TqW6tLlDLoEopIm4%3D", "http://reserved-antcloud-cnshnfpub-opsware-v2.oss-cn-shanghai.aliyuncs.com/fas/books/3.png?OSSAccessKeyId=RZU9wKztYEqaBQGB&Expires=1647166193&Signature=WfYCQ1S8XLuqj7oCGxHYTH3VNdc%3D", 22 | "http://reserved-antcloud-cnshnfpub-opsware-v2.oss-cn-shanghai.aliyuncs.com/fas/books/4.png?OSSAccessKeyId=RZU9wKztYEqaBQGB&Expires=1647178695&Signature=9l4JHy7eMQVj3T3mXgRpAN9wdPI%3D", "http://reserved-antcloud-cnshnfpub-opsware-v2.oss-cn-shanghai.aliyuncs.com/fas/books/5.png?OSSAccessKeyId=RZU9wKztYEqaBQGB&Expires=1647179151&Signature=LIY%2F56jF8Out5eHsxAU1hkUOp7o%3D" }; 23 | } 24 | -------------------------------------------------------------------------------- /dynamic-stock-mng/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | # logging 3 | logging.level.io.sofastack=INFO 4 | logging.path=./logs/stock-mng 5 | # thymeleaf 6 | spring.thymeleaf.cache=false 7 | spring.thymeleaf.prefix=classpath:/templates/ 8 | spring.thymeleaf.check-template-location=true 9 | spring.thymeleaf.suffix=.html 10 | spring.thymeleaf.encoding=UTF-8 11 | spring.thymeleaf.mode=HTML5 12 | 13 | spring.application.name=stock-mng 14 | 15 | com.alipay.sofa.boot.skip-jvm-reference-health-check=true -------------------------------------------------------------------------------- /dynamic-stock-mng/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | %d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n 11 | 12 | 13 | 14 | 15 | true 16 | 17 | 18 | error 19 | 20 | 21 | ${logging.path}/common-error.log 22 | 23 | 24 | 25 | ${logging.path}/common-error.log.%d{yyyy-MM-dd} 26 | 27 | 30 28 | 29 | 30 | 31 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 32 | 33 | UTF-8 34 | 35 | 36 | 37 | 38 | true 39 | 40 | ${logging.level} 41 | 42 | ${logging.path}/default.log 43 | 44 | 45 | 46 | ${logging.path}/default.log.%d{yyyy-MM-dd} 47 | 48 | 49 | 30 50 | 51 | 52 | 53 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 54 | 55 | UTF-8 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /dynamic-stock-mng/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 72 | 73 | 74 | 75 |
76 |
77 | 78 |
79 | 80 |
81 | 82 |
83 |
84 |
85 |
86 |
87 |
88 | 89 |
90 |
91 | 92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | 101 | -------------------------------------------------------------------------------- /formatter.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | pom 6 | 7 | com.alipay.sofa 8 | sofaboot-dependencies 9 | 3.11.0 10 | 11 | 12 | 13 | io.sofastack 14 | sofachannel-demo 15 | 1.0.0 16 | sofachannel-demo 17 | Demo project for SofaStack Dynamic Module 18 | 19 | 20 | dynamic-stock-mng 21 | dynamic-provider 22 | dynamic-facade 23 | 24 | 25 | 26 | 1.8 27 | 2.2.1 28 | 2.9.1 29 | 1.3.2 30 | 5.1.46 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | com.alipay.sofa 41 | web-ark-plugin 42 | ${sofa.ark.version} 43 | 44 | 45 | 46 | 47 | org.mybatis.spring.boot 48 | mybatis-spring-boot-starter 49 | ${mybatis.version} 50 | 51 | 52 | mysql 53 | mysql-connector-java 54 | ${mysql.version} 55 | 56 | 57 | 58 | io.sofastack 59 | dynamic-facade 60 | 1.0.0 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-surefire-plugin 70 | 2.21.0 71 | 72 | 73 | 74 | 75 | 76 | 77 | default 78 | 79 | true 80 | 81 | 82 | 83 | 84 | true 85 | 86 | ark-snapshot 87 | https://oss.sonatype.org/content/repositories/snapshots 88 | 89 | 90 | 91 | 92 | 93 | true 94 | 95 | ark-snapshot 96 | https://oss.sonatype.org/content/repositories/snapshots 97 | 98 | 99 | 100 | 101 | 102 | 103 | --------------------------------------------------------------------------------