├── .gitignore ├── LICENSE ├── LICENSE_CN ├── README.md ├── admin-server ├── Dockerfile ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── d2c │ │ │ └── admin │ │ │ ├── AdminServerApplication.java │ │ │ └── config │ │ │ └── WebSecurityConfig.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── d2c │ └── admin │ └── AdminServerApplicationTests.java ├── config-server ├── Dockerfile ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── d2c │ │ │ └── config │ │ │ └── ConfigServerApplication.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── d2c │ └── config │ └── ConfigServerApplicationTests.java ├── erureka-server ├── Dockerfile ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── d2c │ │ │ └── erureka │ │ │ └── ErurekaServerApplication.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── d2c │ └── erureka │ └── ErurekaServerApplicationTests.java ├── init.sql ├── mall-portal ├── Dockerfile ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── d2c │ │ │ └── portal │ │ │ ├── MallPortalApplication.java │ │ │ ├── client │ │ │ ├── MemberClient.java │ │ │ ├── OrderClient.java │ │ │ ├── ProductClient.java │ │ │ └── fallback │ │ │ │ ├── MemberClientFallback.java │ │ │ │ ├── OrderClientFallback.java │ │ │ │ └── ProductClientFallback.java │ │ │ ├── controller │ │ │ └── CreateOrderCtrl.java │ │ │ └── service │ │ │ ├── CreateOrderService.java │ │ │ └── impl │ │ │ └── CreateOrderServiceImpl.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── d2c │ └── portal │ └── MallPortalApplicationTests.java ├── pom.xml ├── service-member ├── Dockerfile ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── d2c │ │ │ └── member │ │ │ ├── ServiceMemberApplication.java │ │ │ ├── business │ │ │ ├── controller │ │ │ │ ├── ConfigCtrl.java │ │ │ │ └── UserRestCtrl.java │ │ │ ├── mapper │ │ │ │ └── UserMapper.java │ │ │ ├── model │ │ │ │ └── User.java │ │ │ └── service │ │ │ │ ├── UserService.java │ │ │ │ └── impl │ │ │ │ └── UserServiceImpl.java │ │ │ ├── config │ │ │ ├── mybatis │ │ │ │ └── MybatisConfig.java │ │ │ ├── redis │ │ │ │ ├── RedisConfig.java │ │ │ │ └── serializer │ │ │ │ │ └── FastJsonRedisSerializer.java │ │ │ └── transaction │ │ │ │ └── TransactionConfig.java │ │ │ ├── elasticsearch │ │ │ ├── document │ │ │ │ └── UserSearch.java │ │ │ └── repository │ │ │ │ └── UserSearchRepository.java │ │ │ └── mongodb │ │ │ ├── document │ │ │ └── UserMongo.java │ │ │ └── repository │ │ │ └── UserMongoRepository.java │ └── resources │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ └── mapper │ │ └── UserMapper.xml │ └── test │ └── java │ └── com │ └── d2c │ └── member │ └── ServiceMemberApplicationTests.java ├── service-order ├── Dockerfile ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── d2c │ │ │ └── order │ │ │ ├── ServiceOrderApplication.java │ │ │ ├── business │ │ │ ├── client │ │ │ │ ├── MemberClient.java │ │ │ │ ├── ProductClient.java │ │ │ │ └── fallback │ │ │ │ │ ├── MemberClientFallback.java │ │ │ │ │ └── ProductClientFallback.java │ │ │ ├── controller │ │ │ │ ├── ConfigCtrl.java │ │ │ │ └── OrderRestCtrl.java │ │ │ ├── mapper │ │ │ │ └── OrderMapper.java │ │ │ ├── model │ │ │ │ └── Order.java │ │ │ └── service │ │ │ │ ├── OrderService.java │ │ │ │ └── impl │ │ │ │ └── OrderServiceImpl.java │ │ │ ├── config │ │ │ ├── mybatis │ │ │ │ └── MybatisConfig.java │ │ │ ├── redis │ │ │ │ ├── RedisConfig.java │ │ │ │ └── serializer │ │ │ │ │ └── FastJsonRedisSerializer.java │ │ │ └── transaction │ │ │ │ └── TransactionConfig.java │ │ │ ├── elasticsearch │ │ │ ├── document │ │ │ │ └── OrderSearch.java │ │ │ └── repository │ │ │ │ └── OrderSearchRepository.java │ │ │ └── mongodb │ │ │ ├── document │ │ │ └── OrderMongo.java │ │ │ └── repository │ │ │ └── OrderMongoRepository.java │ └── resources │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ └── mapper │ │ └── OrderMapper.xml │ └── test │ └── java │ └── com │ └── d2c │ └── order │ └── MallOrderApplicationTests.java ├── service-product ├── Dockerfile ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── d2c │ │ │ └── product │ │ │ ├── ServiceProductApplication.java │ │ │ ├── business │ │ │ ├── controller │ │ │ │ ├── ConfigCtrl.java │ │ │ │ └── ProductRestCtrl.java │ │ │ ├── mapper │ │ │ │ └── ProductMapper.java │ │ │ ├── model │ │ │ │ └── Product.java │ │ │ └── service │ │ │ │ ├── ProductService.java │ │ │ │ └── impl │ │ │ │ └── ProductServiceImpl.java │ │ │ ├── config │ │ │ ├── mybatis │ │ │ │ └── MybatisConfig.java │ │ │ ├── redis │ │ │ │ ├── RedisConfig.java │ │ │ │ └── serializer │ │ │ │ │ └── FastJsonRedisSerializer.java │ │ │ └── transaction │ │ │ │ └── TransactionConfig.java │ │ │ ├── elasticsearch │ │ │ ├── document │ │ │ │ └── ProductSearch.java │ │ │ └── repository │ │ │ │ └── ProductSearchRepository.java │ │ │ └── mongodb │ │ │ ├── document │ │ │ └── ProductMongo.java │ │ │ └── repository │ │ │ └── ProductMongoRepository.java │ └── resources │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ └── mapper │ │ └── ProductMapper.xml │ └── test │ └── java │ └── com │ └── d2c │ └── product │ └── MallProductApplicationTests.java └── txlcn-tm-5.0.2.RELEASE.jar /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Maven template 3 | target/ 4 | pom.xml.tag 5 | pom.xml.releaseBackup 6 | pom.xml.versionsBackup 7 | pom.xml.next 8 | release.properties 9 | dependency-reduced-pom.xml 10 | buildNumber.properties 11 | .mvn/timing.properties 12 | 13 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 14 | !/.mvn/wrapper/maven-wrapper.jar 15 | ### Example user template template 16 | ### Example user template 17 | 18 | # IntelliJ project files 19 | .idea 20 | *.iml 21 | out 22 | gen 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2 | 3 | Anti 996 License Version 1.0 (Draft) 4 | 5 | Permission is hereby granted to any individual or legal entity 6 | obtaining a copy of this licensed work (including the source code, 7 | documentation and/or related items, hereinafter collectively referred 8 | to as the "licensed work"), free of charge, to deal with the licensed 9 | work for any purpose, including without limitation, the rights to use, 10 | reproduce, modify, prepare derivative works of, distribute, publish 11 | and sublicense the licensed work, subject to the following conditions: 12 | 13 | 1. The individual or the legal entity must conspicuously display, 14 | without modification, this License and the notice on each redistributed 15 | or derivative copy of the Licensed Work. 16 | 17 | 2. The individual or the legal entity must strictly comply with all 18 | applicable laws, regulations, rules and standards of the jurisdiction 19 | relating to labor and employment where the individual is physically 20 | located or where the individual was born or naturalized; or where the 21 | legal entity is registered or is operating (whichever is stricter). In 22 | case that the jurisdiction has no such laws, regulations, rules and 23 | standards or its laws, regulations, rules and standards are 24 | unenforceable, the individual or the legal entity are required to 25 | comply with Core International Labor Standards. 26 | 27 | 3. The individual or the legal entity shall not induce or force its 28 | employee(s), whether full-time or part-time, or its independent 29 | contractor(s), in any methods, to agree in oral or written form, to 30 | directly or indirectly restrict, weaken or relinquish his or her 31 | rights or remedies under such laws, regulations, rules and standards 32 | relating to labor and employment as mentioned above, no matter whether 33 | such written or oral agreement are enforceable under the laws of the 34 | said jurisdiction, nor shall such individual or the legal entity 35 | limit, in any methods, the rights of its employee(s) or independent 36 | contractor(s) from reporting or complaining to the copyright holder or 37 | relevant authorities monitoring the compliance of the license about 38 | its violation(s) of the said license. 39 | 40 | THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 41 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 42 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 43 | IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, 44 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 45 | OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE 46 | LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK. 47 | -------------------------------------------------------------------------------- /LICENSE_CN: -------------------------------------------------------------------------------- 1 | 版权所有(c)<年份><版权持有人> 2 | 3 | 反996许可证版本1.0 4 | 5 | 在符合下列条件的情况下,特此免费向任何得到本授权作品的副本(包括源代码、文件和/或相关内容,以下 6 | 统称为“授权作品”)的个人和法人实体授权:被授权个人或法人实体有权以任何目的处置授权作品,包括但 7 | 不限于使用、复制,修改,衍生利用、散布,发布和再许可: 8 | 9 | 1. 个人或法人实体必须在许可作品的每个再散布或衍生副本上包含以上版权声明和本许可证,不得自行修 10 | 改。 11 | 2. 个人或法人实体必须严格遵守与个人实际所在地或个人出生地或归化地、或法人实体注册地或经营地 12 | (以较严格者为准)的司法管辖区所有适用的与劳动和就业相关法律、法规、规则和标准。如果该司法管辖 13 | 区没有此类法律、法规、规章和标准或其法律、法规、规章和标准不可执行,则个人或法人实体必须遵守国 14 | 际劳工标准的核心公约。 15 | 3. 个人或法人不得以任何方式诱导或强迫其全职或兼职员工或其独立承包人以口头或书面形式同意直接或 16 | 间接限制、削弱或放弃其所拥有的,受相关与劳动和就业有关的法律、法规、规则和标准保护的权利或补救 17 | 措施,无论该等书面或口头协议是否被该司法管辖区的法律所承认,该等个人或法人实体也不得以任何方法 18 | 限制其雇员或独立承包人向版权持有人或监督许可证合规情况的有关当局报告或投诉上述违反许可证的行为 19 | 的权利。 20 | 21 | 该授权作品是"按原样"提供,不做任何明示或暗示的保证,包括但不限于对适销性、特定用途适用性和非侵 22 | 权性的保证。在任何情况下,无论是在合同诉讼、侵权诉讼或其他诉讼中,版权持有人均不承担因本软件或 23 | 本软件的使用或其他交易而产生、引起或与之相关的任何索赔、损害或其他责任。 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SpringCloud+SpringBoot+LCN项目骨架 2 | 3 | [![LICENSE](https://img.shields.io/badge/license-Anti%20996-blue.svg)](https://github.com/996icu/996.ICU/blob/master/LICENSE) 4 | [![Badge](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu/#/zh_CN) 5 | 6 |   SpringCloud(Finchley.RELEASE)+SpringBoot(2.0.7)项目骨架,eureka+config+bus+feign+ribbon+hystrix+zuul等组件支持,MyBatis+Redis+MongoDB+RabbitMQ+Elasticsearch等集群配置,LCN(5.0.2.RELEASE)分布式事务框架,支持Docker部署。
7 |   作者QQ:[709931138]() 作者邮箱:[709931138@qq.com]()
8 |   具体业务代码参见:https://github.com/D2C-Cai/shop-mall 支持平滑分布式改造 9 | 10 | ## 背景介绍 11 |   **骨架项目的精髓:框架流行,版本要新,配置清晰,代码简洁,案例完整。依赖最小化,不拖泥带水,不自以为是。** 12 | 13 | ## 环境介绍 14 |   此项目适用于有一定开发基础的开发者使用,项目内使用的框架和中间件都是市面上非常流行的,如何搭建环境的教程不作详细介绍,请开发者自行搭建必要的环境。
15 |   作者开发电脑局域网IP:192.168.5.20,服务器的局域网IP:192.168.0.146,要保证网络畅通,防火墙配置正确。
16 |   这里只给出几点建议:Linux服务器作者选用CentOS版本7,JDK选用1.8,MySql数据库5.6建议直接安装在系统上。一些中间件不论单机或集群请务必安装启动:Redis, Mongodb, Rabbitmq, Elasticsearch。 17 | 还有一个[tx-manager](),项目里带了[txlcn-tm-5.0.2.RELEASE.jar](),注意解压找到application.properties后修改配置,需要redis和mysql,这个是LCN分布式事务的管理服务端,LCN5.0以上版本是普通的SpringBoot项目,去官网下载源码,mvn打包启动就行。
18 |   下面会给出Docker容器中快捷安装的方案,注意容器时区,以及目录的映射,[命令只是建议,不要照抄]()! 19 | 20 | 21 | # 项目简介 22 | 23 | ## 模块功能 24 | | 名称 | 介绍 | 说明 | 25 | | ---- | ---- | ---- | 26 | | admin-server
| 远程监控管理服务 | 监控基于SpringBoot的应用,简洁的可视化UI | 27 | | config-server
| 远程配置管理服务 | 远程配置文件地址:https://github.com/D2C-Cai/mall-config | 28 | | erureka-server
| cloud微服务注册中心 | 基于REST的定位服务,以实现云端中间层服务发现和故障转移 | 29 | | mall-portal
| mall商城入口服务 | 用于演示 feign+ribbon+hystrix+zuul 等组件基本的使用和配置 | 30 | | service-member
| mall会员微服务(仅演示) | SpringBoot+MybatisPlus框架的业务模块微服务,可随意扩展重建,
附带feign+config+bus等组件以及LCN分布式事务[参与端]()的演示,
整合Redis+MongoDB+RabbitMQ+Elasticsearch中间件的基本使用 | 31 | | service-order
| mall订单微服务(仅演示) | SpringBoot+MybatisPlus框架的业务模块微服务,可随意扩展重建,
附带feign+config+bus等组件以及LCN分布式事务[发起端]()的演示,
整合Redis+MongoDB+RabbitMQ+Elasticsearch中间件的基本使用 | 32 | | service-product
| mall商品微服务(仅演示) | SpringBoot+MybatisPlus框架的业务模块微服务,可随意扩展重建,
附带feign+config+bus等组件以及LCN分布式事务[参与端]()的演示,
整合Redis+MongoDB+RabbitMQ+Elasticsearch中间件的基本使用 | 33 | 34 | ## 重点框架 35 | | 名称 | 版本 | 说明 | 36 | | ---- | ---- | ---- | 37 | | SpringCloud | Finchley.RELEASE | 与SpringBoot版本对应 | 38 | | SpringBoot | 2.0.7 | 与SpringCloud版本对应 | 39 | | MybatisPlus | 3.0.7.1 | Mybatis升级版,官网:https://mp.baomidou.com
用法详见:https://github.com/D2C-Cai/shop-mall | 40 | | TX-LCN | 5.0.2.RELEASE | 高性能的分布式事务解决方案,官网:http://www.txlcn.org/zh-cn | 41 | 42 | ## 中间件版本 43 | | 名称 | 版本 | 44 | | ---- | ---- | 45 | | MySql | 5.6 | 46 | | Redis | 3.2 | 47 | | Mongodb | 3.2 | 48 | | Elasticsearch | 5.6.8 | 49 | | Elasticsearch-ik | 5.6.x | 50 | | Elasticsearch-head | 5 | 51 | | Rabbitmq | 3.7.8 | 52 | 53 | ## 整合TX-LCN5.0 54 | 55 | #### 客户端配置 56 | ``` 57 | 58 | com.codingapi.txlcn 59 | txlcn-tc 60 | 5.0.2.RELEASE 61 | 62 | 63 | com.codingapi.txlcn 64 | txlcn-txmsg-netty 65 | 5.0.2.RELEASE 66 | 67 | ``` 68 | ``` 69 | # tx-lcn 70 | tx-lcn: 71 | client: 72 | manager-address: 192.168.0.146:8070 73 | resource-order: 0 74 | logger: 75 | enabled: false 76 | message: 77 | netty: 78 | wait-time: 5000 79 | springcloud: 80 | loadbalance: 81 | enabled: true 82 | 83 | ``` 84 | **解释:** 85 | 这里注意我们用的是 5.0.2.RELEASE 版本 86 | ``` 87 | @Configuration 88 | @EnableDiscoveryClient 89 | @EnableDistributedTransaction 90 | public class TransactionConfig { 91 | 92 | } 93 | ``` 94 | **解释:** 95 | 每个需要的客户端,都加上这两个标签的配置@EnableDiscoveryClient,@EnableDistributedTransaction 96 | ``` 97 | @FeignClient(name = "service-member", fallback = MemberClientFallback.class) 98 | public interface MemberClient { 99 | 100 | @GetMapping("/api/user/update/{id}") 101 | int updatePasswdById(@PathVariable(name = "id") Long id, @RequestParam(value = "password") String password); 102 | 103 | } 104 | ``` 105 | ``` 106 | @FeignClient(name = "service-product", fallback = ProductClientFallback.class) 107 | public interface ProductClient { 108 | 109 | @GetMapping("/api/product/update/{id}") 110 | int updatePriceById(@PathVariable(name = "id") Long id, @RequestParam(value = "price") BigDecimal price); 111 | 112 | } 113 | ``` 114 | **解释:** 115 | 这里是一个service-order通过FeignClient远程调用service-member和service-product的例子 116 | ``` 117 | @Override 118 | @LcnTransaction 119 | @Transactional 120 | public int doSomeThing(String sn, Long productId, Long memberId) { 121 | int rs1 = orderMapper.updateAmountBySn(sn, new BigDecimal((int) (Math.random() * 100 + 1))); 122 | int rs2 = memberClient.updatePasswdById(memberId, String.valueOf((int) (Math.random() * 100 + 1))); 123 | int rs3 = productClient.updatePriceById(productId, new BigDecimal((int) (Math.random() * 100 + 1))); 124 | //return rs1 + rs2 + rs3; 125 | throw new RuntimeException("doSomeThing更新失败"); 126 | } 127 | ``` 128 | **解释:** 129 | 这里使用LCN模式,其他模式也类似,发起端@LcnTransaction,propagation默认是REQUIRED 130 | ``` 131 | @Override 132 | @LcnTransaction(propagation = DTXPropagation.SUPPORTS) 133 | @Transactional 134 | public int updatePasswdById(Long id, String password) { 135 | return userMapper.updatePasswdById(id, password); 136 | } 137 | ``` 138 | ``` 139 | @Override 140 | @LcnTransaction(propagation = DTXPropagation.SUPPORTS) 141 | @Transactional 142 | public int updatePriceById(Long id, BigDecimal price) { 143 | return productMapper.updatePriceById(id, price); 144 | } 145 | 146 | ``` 147 | **解释:** 148 | 这里使用LCN模式,其他模式也类似,参与端@LcnTransaction(propagation = DTXPropagation.SUPPORTS)
149 | propagation有两种传播属性 REQUIRED(当前没有分布式事务,就创建。当前有分布式事务,就加入),SUPPORTS(当前没有分布式事务,非分布式事务运行。当前有分布式事务,就加入) 150 | 151 | #### 服务端配置 152 | ``` 153 | spring.application.name=tx-manager 154 | server.port=7970 155 | 156 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 157 | spring.datasource.url=jdbc:mysql://192.168.0.146:3306/tx-manager?characterEncoding=UTF-8 158 | spring.datasource.username=root 159 | spring.datasource.password=123456 160 | 161 | mybatis.configuration.map-underscore-to-camel-case=true 162 | mybatis.configuration.use-generated-keys=true 163 | 164 | spring.redis.host=192.168.0.146 165 | spring.redis.port=6379 166 | spring.redis.password= 167 | 168 | tx-lcn.manager.host=192.168.0.146 169 | tx-lcn.manager.port=8070 170 | tx-lcn.manager.admin-key=codingapi 171 | 172 | # 心跳检测时间(ms) 173 | tx-lcn.manager.heart-time=15000 174 | # 分布式事务执行总时间(ms) 175 | tx-lcn.manager.dtx-time=30000 176 | # 参数延迟删除时间(ms) 177 | tx-lcn.message.netty.attr-delay-time=10000 178 | # 事务处理并发等级. 默认为机器逻辑核心数5倍 179 | #tx-lcn.manager.concurrent-level=128 180 | 181 | # 开启日志 182 | #tx-lcn.logger.enabled=true 183 | #logging.level.com.codingapi=debug 184 | ``` 185 | **解释:** 186 | 注意服务端需要建立的几个数据库的表,官方代码里有sql脚本,这里不做展示 187 | 188 | #### SpringCloud集群部署下,LCN存在信道问题 189 | LCN模式,多个同名微服务部署环境下,在事务通知时,存在随机通知其中一个微服务的BUG,而不是定位到真正参与事务的那个微服务。解决方案就是通过ip+port作为标识来区分,需要修改源码如下:

190 | txlcn-tc模块下,增加如下代码,意为扩展ModId的生成方式: 191 | ``` 192 | package com.codingapi.txlcn.tc.support; 193 | 194 | import com.codingapi.txlcn.common.util.id.ModIdProvider; 195 | import org.springframework.beans.factory.annotation.Value; 196 | import org.springframework.stereotype.Component; 197 | 198 | import java.net.InetAddress; 199 | import java.net.UnknownHostException; 200 | 201 | @Component 202 | public class MyModIdProvider implements ModIdProvider { 203 | 204 | @Value("${server.port}") 205 | private int serverPort; 206 | 207 | public String getServerID() { 208 | InetAddress address = null; 209 | try { 210 | address = InetAddress.getLocalHost(); 211 | } catch (UnknownHostException e) { 212 | e.printStackTrace(); 213 | } 214 | return "http://" + address.getHostAddress() + ":" + this.serverPort; 215 | } 216 | 217 | @Override 218 | public String modId() { 219 | return getServerID(); 220 | } 221 | 222 | } 223 | ``` 224 | txlcn-txmsg-netty模块下,找到这个类com.codingapi.txlcn.txmsg.netty.bean.SocketManager 225 | ``` 226 | /** 227 | * 获取模块名称 228 | * 229 | * @param remoteKey 远程唯一标识 230 | * @return 模块名称 231 | */ 232 | public String getModuleName(String remoteKey) { 233 | AppInfo appInfo = appNames.get(remoteKey); 234 | return appInfo == null ? null : appInfo.getAppName(); // 原来的getAppName() 235 | } 236 | ``` 237 | ``` 238 | /** 239 | * 获取模块名称 240 | * 241 | * @param remoteKey 远程唯一标识 242 | * @return 模块名称 243 | */ 244 | public String getModuleName(String remoteKey) { 245 | AppInfo appInfo = appNames.get(remoteKey); 246 | return appInfo == null ? null : appInfo.getLabelName(); // 修改为getLabelName() 247 | } 248 | ``` 249 | 250 | # Docker容器中间件部署 251 | 252 | ## Redis 253 | 254 | > docker pull redis:3.2 255 | 256 | > docker run -p 6379:6379 --name redis -v /etc/localtime:/etc/localtime:ro -v /mnt/docker/redis/data:/data -d redis:3.2 redis-server --appendonly yes 257 | 258 | ## Mongodb 259 | 260 | > docker pull mongo:3.2 261 | 262 | > docker run -p 27017:27017 --name mongodb -v /etc/localtime:/etc/localtime:ro -v /mnt/docker/mongodb/db:/data/db -d mongo:3.2 263 | 264 | ## Rabbitmq 265 | 266 | > docker pull rabbitmq:management 267 | 268 | > docker run -p 5672:5672 -p 15672:15672 --name rabbitmq -v /etc/localtime:/etc/localtime:ro -d rabbitmq:management 269 | 270 | #### *rabbitmq-delayed-message-exchange 271 | 272 | https://dl.bintray.com/rabbitmq/community-plugins/3.7.x/rabbitmq_delayed_message_exchange 去这里下载一个版本3.7.x版本的插件,解压到/mnt/docker/rabbitmq,如下方式安装,最后重启容器即可 273 | 274 | > docker cp /mnt/docker/rabbitmq/rabbitmq_delayed_message_exchange-20171201-3.7.x.ez (容器ID):/plugins 275 | 276 | > docker exec -it (容器ID) /bin/bash 277 | 278 | > rabbitmq-plugins enable rabbitmq_delayed_message_exchange 279 | 280 | > rabbitmq-plugins list 281 | 282 | > exit 283 | 284 | > docker restart (容器ID) 285 | 286 | ## Elasticsearch 287 | 288 | > vi /etc/sysctl.conf 289 | 290 | ``` 291 | #文件中加入一行 292 | vm.max_map_count=655360 293 | ``` 294 | > sysctl -p 295 | 296 | > docker pull elasticsearch:5.6.8 297 | 298 | #### elasticsearch.yml 299 | 300 | ``` 301 | http.host: 0.0.0.0 302 | #集群名称 所有节点要相同 303 | cluster.name: "d2cmall-es" 304 | #本节点名称 305 | node.name: master 306 | #作为master节点 307 | node.master: true 308 | #是否存储数据 309 | node.data: true 310 | # head插件设置 311 | http.cors.enabled: true 312 | http.cors.allow-origin: "*" 313 | #设置可以访问的ip 这里全部设置通过 314 | network.bind_host: 0.0.0.0 315 | #设置节点 访问的地址 设置master所在机器的ip 316 | network.publish_host: 192.168.0.146 317 | ``` 318 | 319 | > docker run -p 9200:9200 -p 9300:9300 --name elasticsearch -v /etc/localtime:/etc/localtime:ro -v /mnt/docker/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /mnt/docker/elasticsearch/data:/usr/share/elasticsearch/data -v /mnt/docker/elasticsearch/plugins:/usr/share/elasticsearch/plugins -v /mnt/docker/elasticsearch/logs:/usr/share/elasticsearch/logs -d elasticsearch:5.6.8 320 | 321 | > curl -XPUT http://192.168.0.146:9200/index 322 | 323 | #### *elasticsearch-ik 324 | 325 | https://github.com/medcl/elasticsearch-analysis-ik/releases 去这里下载一个版本5.6.x版本的插件,解压到/mnt/docker/elasticsearch/plugins下,最后重启容器即可 326 | 327 | > docker restart (容器ID) 328 | 329 | > curl 'http://192.168.0.146:9200/index/_analyze?analyzer=ik_max_word&pretty=true' -d '{"text":"我们是大数据开发技术人员"}' 330 | 331 | #### *elasticsearch-head 332 | 333 | > docker pull mobz/elasticsearch-head:5 334 | 335 | > docker run -p 9100:9100 --name elasticsearch-head -v /etc/localtime:/etc/localtime:ro -d mobz/elasticsearch-head:5 336 | 337 | #### 下面是我保存的一些镜像 338 | 339 | > 709931138/mall:redis-3.2 340 | 341 | > 709931138/mall:mongo-3.2 342 | 343 | > 709931138/mall:elasticsearch-5.6.8 344 | 345 | > 709931138/mall:elasticsearch-head-5 346 | 347 | > 709931138/mall:rabbitmq-3.7.8 348 | 349 | 350 | # Service启动后的测试地址 351 | 352 | **#erureka-server** 353 | 354 | > http://192.168.0.146:1001/ 355 | 356 | **#admin-server** 357 | 358 | > http://192.168.0.146:3001/ 359 | 360 | **#tx-manager** 361 | 362 | > http://192.168.0.146:7970/ 363 | 364 | **#config-server** 365 | 366 | > http://192.168.0.146:2001/service-member-dev.yml 367 | 368 | > http://192.168.0.146:2001/service-member-test.yml 369 | 370 | > http://192.168.0.146:2001/service-member-prd.yml 371 | 372 | > http://192.168.0.146:2001/service-product-dev.yml 373 | 374 | > http://192.168.0.146:2001/service-product-test.yml 375 | 376 | > http://192.168.0.146:2001/service-product-prd.yml 377 | 378 | > http://192.168.0.146:2001/service-order-dev.yml 379 | 380 | > http://192.168.0.146:2001/service-order-test.yml 381 | 382 | > http://192.168.0.146:2001/service-order-prd.yml 383 | 384 | > http://192.168.0.146:2001/actuator/bus-refresh POST 385 | 386 | **#service-member** 387 | 388 | > http://192.168.5.20:8001/profile 389 | 390 | > http://192.168.5.20:8001/api/user?username=baicai 391 | 392 | > http://192.168.5.20:8001/api/user/cache?username=baicai 393 | 394 | > http://192.168.5.20:8001/api/user/mongo?username=baicai 395 | 396 | > http://192.168.5.20:8001/api/user/search?username=baicai 397 | 398 | **#service-product** 399 | 400 | > http://192.168.5.20:8003/profile 401 | 402 | > http://192.168.5.20:8003/api/product?sn=SN123456 403 | 404 | > http://192.168.5.20:8003/api/product/cache?sn=SN123456 405 | 406 | > http://192.168.5.20:8003/api/product/mongo?sn=SN123456 407 | 408 | > http://192.168.5.20:8003/api/product/search?sn=SN123456 409 | 410 | **#service-order** 411 | 412 | > http://192.168.5.20:8002/profile 413 | 414 | > http://192.168.5.20:8002/api/order?sn=Q123456 415 | 416 | > http://192.168.5.20:8002/api/order/cache?sn=Q123456 417 | 418 | > http://192.168.5.20:8002/api/order/mongo?sn=Q123456 419 | 420 | > http://192.168.5.20:8002/api/order/search?sn=Q123456 421 | 422 | > http://192.168.5.20:8002/api/order/tx?sn=Q123456&productId=1&memberId=1 423 | 424 | **#mall-portal** 425 | 426 | > http://192.168.5.20:9001/api/find/data?username=baicai&productSn=SN123456&orderSn=Q123456 427 | 428 | > http://192.168.5.20:9001/apigateway/member/api/user?username=baicai 429 | 430 | > http://192.168.5.20:9001/apigateway/product/api/product?sn=SN123456 431 | 432 | > http://192.168.5.20:9001/apigateway/order/api/order?sn=Q123456 433 | 434 | License 435 | --- 436 | 437 | [反 996 许可证](LICENSE) 438 | 439 | - 此许可证的目的是阻止违反劳动法的公司使用许可证下的软件或代码,并强迫这些公司权衡他们的行为。 440 | - 在此处查看反 996 许可证下的[完整项目列表](awesomelist/projects.md) 441 | - 此许可证的灵感来源于 @xushunke:[Design A Software License Of Labor Protection -- 996ICU License](https://github.com/996icu/996.ICU/pull/15642) 442 | - 当前版本反 996 许可证由 [伊利诺伊大学法学院的 Katt Gu, J.D](https://scholar.google.com.sg/citations?user=PTcpQwcAAAAJ&hl=en&oi=ao) 起草;由 [Dimension](https://www.dimension.im) 的首席执行官 [Suji Yan](https://www.linkedin.com/in/tedkoyan/) 提供建议。 443 | - 该草案改编自 MIT 许可证,如需更多信息请查看 [Wiki](https://github.com/kattgu7/996-License-Draft/wiki)。此许可证旨在与所有主流开源许可证兼容。 444 | - 如果你是法律专业人士,或是任何愿意为未来版本做出直接贡献的人,请访问 [Anti-996-License-1.0](https://github.com/kattgu7/996-License-Draft)。感谢你的帮助。 445 | -------------------------------------------------------------------------------- /admin-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | VOLUME /tmp 3 | ADD target/admin-server-0.0.1-SNAPSHOT.jar app.jar 4 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] -------------------------------------------------------------------------------- /admin-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.d2c 7 | admin-server 8 | 0.0.1-SNAPSHOT 9 | admin-server 10 | Demo project for Spring Boot 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.7.RELEASE 16 | 17 | 18 | 19 | 20 | 1.8 21 | UTF-8 22 | UTF-8 23 | Finchley.RELEASE 24 | mall 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-dependencies 32 | ${spring-cloud.version} 33 | pom 34 | import 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.cloud 42 | spring-cloud-starter-netflix-eureka-client 43 | 44 | 45 | de.codecentric 46 | spring-boot-admin-starter-server 47 | 2.0.4 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-web 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-security 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-starter-test 60 | test 61 | 62 | 63 | org.jolokia 64 | jolokia-core 65 | 66 | 67 | 68 | 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-maven-plugin 73 | 74 | 75 | com.spotify 76 | dockerfile-maven-plugin 77 | 1.4.6 78 | 79 | ${docker.image.prefix}/${project.artifactId} 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | spring-milestones 88 | Spring Milestones 89 | https://repo.spring.io/milestone 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /admin-server/src/main/java/com/d2c/admin/AdminServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.d2c.admin; 2 | 3 | import de.codecentric.boot.admin.server.config.EnableAdminServer; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | @EnableAdminServer 8 | @SpringBootApplication 9 | public class AdminServerApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(AdminServerApplication.class, args); 13 | } 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /admin-server/src/main/java/com/d2c/admin/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.admin.config; 2 | 3 | import de.codecentric.boot.admin.server.config.AdminServerProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 7 | import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; 8 | 9 | @Configuration 10 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 11 | 12 | private final String adminContextPath; 13 | 14 | public WebSecurityConfig(AdminServerProperties adminServerProperties) { 15 | this.adminContextPath = adminServerProperties.getContextPath(); 16 | } 17 | 18 | @Override 19 | protected void configure(HttpSecurity http) throws Exception { 20 | SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); 21 | successHandler.setTargetUrlParameter("redirectTo"); 22 | http 23 | .authorizeRequests() 24 | .antMatchers(adminContextPath + "/assets/**") 25 | .permitAll() 26 | .antMatchers(adminContextPath + "/login") 27 | .permitAll() 28 | .anyRequest() 29 | .authenticated() 30 | .and() 31 | .formLogin() 32 | .loginPage(adminContextPath + "/login") 33 | .successHandler(successHandler) 34 | .and() 35 | .logout() 36 | .logoutUrl(adminContextPath + "/logout") 37 | .and() 38 | .httpBasic() 39 | .and() 40 | .csrf() 41 | .disable(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /admin-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # tomcat 2 | server: 3 | port: 3001 4 | 5 | # eureka 6 | eureka: 7 | instance: 8 | lease-expiration-duration-in-seconds: 30 9 | lease-renewal-interval-in-seconds: 10 10 | health-check-url-path: /actuator/health 11 | metadata-map: 12 | user.name: admin 13 | user.password: 123456 14 | client: 15 | service-url: 16 | defaultZone: http://192.168.0.146:1001/eureka/ 17 | 18 | # actuator 19 | management: 20 | endpoints: 21 | web: 22 | exposure: 23 | include: "*" 24 | endpoint: 25 | health: 26 | show-details: ALWAYS 27 | 28 | # spring 29 | spring: 30 | application: 31 | name: admin-server 32 | security: 33 | user: 34 | name: admin 35 | password: 123456 -------------------------------------------------------------------------------- /admin-server/src/test/java/com/d2c/admin/AdminServerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.d2c.admin; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class AdminServerApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /config-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | VOLUME /tmp 3 | ADD target/config-server-0.0.1-SNAPSHOT.jar app.jar 4 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] -------------------------------------------------------------------------------- /config-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.d2c 7 | config-server 8 | 0.0.1-SNAPSHOT 9 | config-server 10 | Demo project for Spring Boot 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.7.RELEASE 16 | 17 | 18 | 19 | 20 | 1.8 21 | UTF-8 22 | UTF-8 23 | Finchley.RELEASE 24 | mall 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-dependencies 32 | ${spring-cloud.version} 33 | pom 34 | import 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.cloud 42 | spring-cloud-starter-netflix-eureka-client 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-config-server 47 | 48 | 49 | org.springframework.cloud 50 | spring-cloud-starter-bus-amqp 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-starter-test 55 | test 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-maven-plugin 64 | 65 | 66 | com.spotify 67 | dockerfile-maven-plugin 68 | 1.4.6 69 | 70 | ${docker.image.prefix}/${project.artifactId} 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | spring-milestones 79 | Spring Milestones 80 | https://repo.spring.io/milestone 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /config-server/src/main/java/com/d2c/config/ConfigServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.d2c.config; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.config.server.EnableConfigServer; 6 | 7 | @EnableConfigServer 8 | @SpringBootApplication 9 | public class ConfigServerApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ConfigServerApplication.class, args); 13 | } 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /config-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # tomcat 2 | server: 3 | port: 2001 4 | 5 | # eureka 6 | eureka: 7 | instance: 8 | lease-expiration-duration-in-seconds: 30 9 | lease-renewal-interval-in-seconds: 10 10 | client: 11 | service-url: 12 | defaultZone: http://192.168.0.146:1001/eureka/ 13 | 14 | # actuator 15 | management: 16 | endpoints: 17 | web: 18 | exposure: 19 | include: "bus-refresh" 20 | 21 | # spring 22 | spring: 23 | application: 24 | name: config-server 25 | 26 | # config 27 | cloud: 28 | config: 29 | server: 30 | git: 31 | uri: https://github.com/D2C-Cai/mall-config.git 32 | 33 | # rabbitmq 34 | rabbitmq: 35 | host: 192.168.0.146 36 | port: 5672 37 | username: guest 38 | password: guest -------------------------------------------------------------------------------- /config-server/src/test/java/com/d2c/config/ConfigServerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.d2c.config; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ConfigServerApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /erureka-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | VOLUME /tmp 3 | ADD target/erureka-server-0.0.1-SNAPSHOT.jar app.jar 4 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] -------------------------------------------------------------------------------- /erureka-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.d2c 7 | erureka-server 8 | 0.0.1-SNAPSHOT 9 | erureka-server 10 | Demo project for Spring Boot 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.7.RELEASE 16 | 17 | 18 | 19 | 20 | 1.8 21 | UTF-8 22 | UTF-8 23 | Finchley.RELEASE 24 | mall 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-dependencies 32 | ${spring-cloud.version} 33 | pom 34 | import 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.cloud 42 | spring-cloud-starter-netflix-eureka-server 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-test 47 | test 48 | 49 | 50 | 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-maven-plugin 56 | 57 | 58 | com.spotify 59 | dockerfile-maven-plugin 60 | 1.4.6 61 | 62 | ${docker.image.prefix}/${project.artifactId} 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | spring-milestones 71 | Spring Milestones 72 | https://repo.spring.io/milestone 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /erureka-server/src/main/java/com/d2c/erureka/ErurekaServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.d2c.erureka; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @EnableEurekaServer 8 | @SpringBootApplication 9 | public class ErurekaServerApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ErurekaServerApplication.class, args); 13 | } 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /erureka-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # tomcat 2 | server: 3 | port: 1001 4 | 5 | # eureka 6 | eureka: 7 | instance: 8 | hostname: 192.168.0.146 9 | prefer-ip-address: true 10 | server: 11 | enable-self-preservation: false 12 | eviction-interval-timer-in-ms: 30000 13 | client: 14 | register-with-eureka: false 15 | fetch-registry: false 16 | service-url: 17 | defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 18 | 19 | # spring 20 | spring: 21 | application: 22 | name: erureka-server -------------------------------------------------------------------------------- /erureka-server/src/test/java/com/d2c/erureka/ErurekaServerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.d2c.erureka; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ErurekaServerApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /init.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : mall146 5 | Source Server Type : MySQL 6 | Source Server Version : 50642 7 | Source Host : 192.168.0.146:3306 8 | Source Schema : shop 9 | 10 | Target Server Type : MySQL 11 | Target Server Version : 50642 12 | File Encoding : 65001 13 | 14 | Date: 25/01/2019 14:30:11 15 | */ 16 | 17 | SET NAMES utf8mb4; 18 | SET FOREIGN_KEY_CHECKS = 0; 19 | 20 | -- ---------------------------- 21 | -- Table structure for m_user 22 | -- ---------------------------- 23 | DROP TABLE IF EXISTS `m_user`; 24 | CREATE TABLE `m_user` ( 25 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 26 | `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, 27 | `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, 28 | PRIMARY KEY (`id`) USING BTREE 29 | ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Compact; 30 | 31 | -- ---------------------------- 32 | -- Records of m_user 33 | -- ---------------------------- 34 | INSERT INTO `m_user` VALUES (1, 'baicai', '123456'); 35 | 36 | -- ---------------------------- 37 | -- Table structure for o_order 38 | -- ---------------------------- 39 | DROP TABLE IF EXISTS `o_order`; 40 | CREATE TABLE `o_order` ( 41 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 42 | `sn` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, 43 | `pay_amount` decimal(10, 2) NULL DEFAULT NULL, 44 | PRIMARY KEY (`id`) USING BTREE 45 | ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Compact; 46 | 47 | -- ---------------------------- 48 | -- Records of o_order 49 | -- ---------------------------- 50 | INSERT INTO `o_order` VALUES (1, 'Q123456', 1099.00); 51 | 52 | -- ---------------------------- 53 | -- Table structure for p_product 54 | -- ---------------------------- 55 | DROP TABLE IF EXISTS `p_product`; 56 | CREATE TABLE `p_product` ( 57 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 58 | `sn` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, 59 | `price` decimal(10, 2) NULL DEFAULT NULL, 60 | PRIMARY KEY (`id`) USING BTREE 61 | ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Compact; 62 | 63 | -- ---------------------------- 64 | -- Records of p_product 65 | -- ---------------------------- 66 | INSERT INTO `p_product` VALUES (1, 'SN123456', 899.00); 67 | 68 | SET FOREIGN_KEY_CHECKS = 1; 69 | -------------------------------------------------------------------------------- /mall-portal/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | VOLUME /tmp 3 | ADD target/mall-portal-0.0.1-SNAPSHOT.jar app.jar 4 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] -------------------------------------------------------------------------------- /mall-portal/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.d2c 7 | mall-portal 8 | 0.0.1-SNAPSHOT 9 | mall-portal 10 | Demo project for Spring Boot 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.7.RELEASE 16 | 17 | 18 | 19 | 20 | 1.8 21 | UTF-8 22 | UTF-8 23 | Finchley.RELEASE 24 | mall 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-dependencies 32 | ${spring-cloud.version} 33 | pom 34 | import 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.cloud 42 | spring-cloud-starter-netflix-eureka-client 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-starter-netflix-hystrix 47 | 48 | 49 | org.springframework.cloud 50 | spring-cloud-starter-netflix-zuul 51 | 52 | 53 | org.springframework.cloud 54 | spring-cloud-starter-openfeign 55 | 56 | 57 | de.codecentric 58 | spring-boot-admin-starter-client 59 | 2.0.4 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-web 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-starter-logging 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-starter-actuator 73 | 74 | 75 | org.springframework.boot 76 | spring-boot-starter-test 77 | test 78 | 79 | 80 | 81 | com.alibaba 82 | fastjson 83 | 1.2.54 84 | 85 | 86 | org.apache.commons 87 | commons-lang3 88 | 3.8 89 | 90 | 91 | org.projectlombok 92 | lombok 93 | 1.18.4 94 | 95 | 96 | junit 97 | junit 98 | 4.12 99 | test 100 | 101 | 102 | 103 | 104 | 105 | 106 | org.springframework.boot 107 | spring-boot-maven-plugin 108 | 109 | 110 | com.spotify 111 | dockerfile-maven-plugin 112 | 1.4.6 113 | 114 | ${docker.image.prefix}/${project.artifactId} 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/MallPortalApplication.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 7 | import org.springframework.cloud.openfeign.EnableFeignClients; 8 | 9 | @EnableFeignClients 10 | @EnableCircuitBreaker 11 | @EnableZuulProxy 12 | @SpringBootApplication 13 | public class MallPortalApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(MallPortalApplication.class, args); 17 | } 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/client/MemberClient.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal.client; 2 | 3 | import com.d2c.portal.client.fallback.MemberClientFallback; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | 8 | @FeignClient(name = "service-member", fallback = MemberClientFallback.class) 9 | public interface MemberClient { 10 | 11 | @GetMapping("/api/user") 12 | String findByName(@RequestParam(value = "username") String username); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/client/OrderClient.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal.client; 2 | 3 | import com.d2c.portal.client.fallback.OrderClientFallback; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | 8 | @FeignClient(name = "service-order", fallback = OrderClientFallback.class) 9 | public interface OrderClient { 10 | 11 | @GetMapping("/api/order") 12 | String findBySn(@RequestParam(value = "sn") String sn); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/client/ProductClient.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal.client; 2 | 3 | import com.d2c.portal.client.fallback.ProductClientFallback; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | 8 | @FeignClient(name = "service-product", fallback = ProductClientFallback.class) 9 | public interface ProductClient { 10 | 11 | @GetMapping("/api/product") 12 | String findBySn(@RequestParam(value = "sn") String sn); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/client/fallback/MemberClientFallback.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal.client.fallback; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.d2c.portal.client.MemberClient; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class MemberClientFallback implements MemberClient { 9 | 10 | @Override 11 | public String findByName(String username) { 12 | System.out.println("MemberClientFallback中的降级方法"); 13 | JSONObject obj = new JSONObject(); 14 | obj.put("id", 9999L); 15 | obj.put("username", "admin"); 16 | obj.put("password", "admin"); 17 | return obj.toJSONString(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/client/fallback/OrderClientFallback.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal.client.fallback; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.d2c.portal.client.OrderClient; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class OrderClientFallback implements OrderClient { 9 | 10 | @Override 11 | public String findBySn(String sn) { 12 | System.out.println("OrderClientFallback中的降级方法"); 13 | JSONObject obj = new JSONObject(); 14 | obj.put("id", 9999L); 15 | obj.put("sn", "Q9999"); 16 | obj.put("payAmount", "999"); 17 | return obj.toJSONString(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/client/fallback/ProductClientFallback.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal.client.fallback; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.d2c.portal.client.ProductClient; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class ProductClientFallback implements ProductClient { 9 | 10 | @Override 11 | public String findBySn(String sn) { 12 | System.out.println("ProductClientFallback中的降级方法"); 13 | JSONObject obj = new JSONObject(); 14 | obj.put("id", 9999L); 15 | obj.put("sn", "SN9999"); 16 | obj.put("price", "999"); 17 | return obj.toJSONString(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/controller/CreateOrderCtrl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal.controller; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.d2c.portal.service.CreateOrderService; 5 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @RestController 12 | public class CreateOrderCtrl { 13 | 14 | @Autowired 15 | private CreateOrderService createOrderService; 16 | 17 | @HystrixCommand(fallbackMethod = "findThingsFail") 18 | @RequestMapping(value = "/api/find/data", method = RequestMethod.GET) 19 | public JSONObject findThings(String username, String productSn, String orderSn) { 20 | return createOrderService.findThings(username, productSn, orderSn); 21 | } 22 | 23 | private JSONObject findThingsFail(String username, String productSn, String orderSn) { 24 | System.out.println("controller中的降级方法"); 25 | JSONObject obj = new JSONObject(); 26 | obj.put("code", -1); 27 | obj.put("msg", "抢购人数太多,您被挤出来了,请稍等重试!"); 28 | return obj; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/service/CreateOrderService.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal.service; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | 5 | public interface CreateOrderService { 6 | 7 | JSONObject findThings(String username, String productSn, String orderSn); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /mall-portal/src/main/java/com/d2c/portal/service/impl/CreateOrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal.service.impl; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.d2c.portal.client.MemberClient; 5 | import com.d2c.portal.client.OrderClient; 6 | import com.d2c.portal.client.ProductClient; 7 | import com.d2c.portal.service.CreateOrderService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | public class CreateOrderServiceImpl implements CreateOrderService { 13 | 14 | @Autowired 15 | private ProductClient productClient; 16 | @Autowired 17 | private MemberClient memberClient; 18 | @Autowired 19 | private OrderClient orderClient; 20 | 21 | @Override 22 | public JSONObject findThings(String username, String productSn, String orderSn) { 23 | JSONObject result = new JSONObject(); 24 | String memberStr = memberClient.findByName(username); 25 | result.put("member", JSONObject.parseObject(memberStr)); 26 | String productStr = productClient.findBySn(productSn); 27 | result.put("product", JSONObject.parseObject(productStr)); 28 | String orderStr = orderClient.findBySn(orderSn); 29 | result.put("order", JSONObject.parseObject(orderStr)); 30 | return result; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /mall-portal/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # tomcat 2 | server: 3 | port: 9001 4 | 5 | # eureka 6 | eureka: 7 | instance: 8 | lease-expiration-duration-in-seconds: 30 9 | lease-renewal-interval-in-seconds: 10 10 | client: 11 | service-url: 12 | defaultZone: http://192.168.0.146:1001/eureka/ 13 | 14 | # feign 15 | feign: 16 | hystrix: 17 | enabled: true 18 | client: 19 | config: 20 | default: 21 | connectTimeout: 10000 22 | readTimeout: 5000 23 | 24 | # hystrix 25 | hystrix: 26 | command: 27 | default: 28 | execution: 29 | isolation: 30 | thread: 31 | timeoutInMilliseconds: 5000 32 | 33 | # ribbon 34 | service-product: 35 | ribbon: 36 | NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule 37 | 38 | service-member: 39 | ribbon: 40 | NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule 41 | 42 | service-order: 43 | ribbon: 44 | NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule 45 | 46 | # zuul 47 | zuul: 48 | ignored-services: '*' 49 | routes: 50 | service-product: /apigateway/product/** 51 | service-member: /apigateway/member/** 52 | service-order: /apigateway/order/** 53 | ignored-patterns: /service-*/** 54 | sensitive-headers: 55 | 56 | # actuator 57 | management: 58 | endpoints: 59 | web: 60 | exposure: 61 | include: "*" 62 | 63 | # spring 64 | spring: 65 | application: 66 | name: mall-portal -------------------------------------------------------------------------------- /mall-portal/src/test/java/com/d2c/portal/MallPortalApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.d2c.portal; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class MallPortalApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.d2c 8 | mall 9 | 1.0-SNAPSHOT 10 | pom 11 | 12 | 13 | admin-server 14 | config-server 15 | erureka-server 16 | mall-portal 17 | service-member 18 | service-order 19 | service-product 20 | 21 | 22 | -------------------------------------------------------------------------------- /service-member/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | VOLUME /tmp 3 | ADD target/service-member-0.0.1-SNAPSHOT.jar app.jar 4 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] -------------------------------------------------------------------------------- /service-member/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.d2c 7 | service-member 8 | 0.0.1-SNAPSHOT 9 | service-member 10 | Demo project for Spring Boot 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.7.RELEASE 16 | 17 | 18 | 19 | 20 | 1.8 21 | Finchley.RELEASE 22 | mall 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-dependencies 30 | ${spring-cloud.version} 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-netflix-eureka-client 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-config 45 | 46 | 47 | org.springframework.cloud 48 | spring-cloud-starter-bus-amqp 49 | 50 | 51 | de.codecentric 52 | spring-boot-admin-starter-client 53 | 2.0.4 54 | 55 | 56 | 57 | com.codingapi.txlcn 58 | txlcn-tc 59 | 5.0.2.RELEASE 60 | 61 | 62 | com.codingapi.txlcn 63 | txlcn-txmsg-netty 64 | 5.0.2.RELEASE 65 | 66 | 67 | 68 | org.springframework.boot 69 | spring-boot-starter-web 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-starter-aop 74 | 75 | 76 | org.springframework.boot 77 | spring-boot-starter-jdbc 78 | 79 | 80 | org.springframework.boot 81 | spring-boot-starter-logging 82 | 83 | 84 | org.springframework.boot 85 | spring-boot-starter-actuator 86 | 87 | 88 | org.springframework.boot 89 | spring-boot-starter-data-redis 90 | 91 | 92 | org.springframework.boot 93 | spring-boot-starter-data-mongodb 94 | 95 | 96 | org.springframework.boot 97 | spring-boot-starter-data-elasticsearch 98 | 99 | 100 | org.springframework.boot 101 | spring-boot-starter-test 102 | test 103 | 104 | 105 | 106 | com.baomidou 107 | mybatis-plus-boot-starter 108 | 3.0.7.1 109 | 110 | 111 | com.alibaba 112 | druid-spring-boot-starter 113 | 1.1.10 114 | 115 | 116 | mysql 117 | mysql-connector-java 118 | 5.1.44 119 | 120 | 121 | com.alibaba 122 | fastjson 123 | 1.2.54 124 | 125 | 126 | org.apache.commons 127 | commons-lang3 128 | 3.8 129 | 130 | 131 | org.projectlombok 132 | lombok 133 | 1.18.4 134 | 135 | 136 | junit 137 | junit 138 | 4.12 139 | test 140 | 141 | 142 | 143 | 144 | 145 | 146 | org.springframework.boot 147 | spring-boot-maven-plugin 148 | 149 | 150 | com.spotify 151 | dockerfile-maven-plugin 152 | 1.4.6 153 | 154 | ${docker.image.prefix}/${project.artifactId} 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/ServiceMemberApplication.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ServiceMemberApplication { 8 | 9 | public static void main(String[] args) { 10 | System.setProperty("es.set.netty.runtime.available.processors", "false"); 11 | SpringApplication.run(ServiceMemberApplication.class, args); 12 | } 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/business/controller/ConfigCtrl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.business.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.cloud.context.config.annotation.RefreshScope; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RefreshScope 9 | @RestController 10 | public class ConfigCtrl { 11 | 12 | @Value("${server.profile}") 13 | private String profile; 14 | 15 | @GetMapping("/profile") 16 | public String profile() { 17 | return this.profile; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/business/controller/UserRestCtrl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.business.controller; 2 | 3 | import com.d2c.member.business.model.User; 4 | import com.d2c.member.business.service.UserService; 5 | import com.d2c.member.elasticsearch.document.UserSearch; 6 | import com.d2c.member.mongodb.document.UserMongo; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | import java.util.List; 11 | 12 | @RestController 13 | public class UserRestCtrl { 14 | 15 | @Autowired 16 | private UserService userService; 17 | 18 | @RequestMapping(value = "/api/user", method = RequestMethod.GET) 19 | public User findByName(@RequestParam(value = "username", required = true) String username) { 20 | return userService.findByName(username); 21 | } 22 | 23 | @RequestMapping(value = "/api/user/cache", method = RequestMethod.GET) 24 | public User findCacheByName(@RequestParam(value = "username", required = true) String username) { 25 | return userService.findCacheByName(username); 26 | } 27 | 28 | @RequestMapping(value = "/api/user/mongo", method = RequestMethod.GET) 29 | public List findMongoByName(@RequestParam(value = "username", required = true) String username) { 30 | return userService.findMongoByName(username); 31 | } 32 | 33 | @RequestMapping(value = "/api/user/search", method = RequestMethod.GET) 34 | public List findSearchByName(@RequestParam(value = "username", required = true) String username) { 35 | return userService.findSearchByName(username); 36 | } 37 | 38 | @RequestMapping(value = "/api/user/update/{id}", method = RequestMethod.GET) 39 | public int updatePasswdById(@PathVariable(name = "id") Long id, @RequestParam(value = "password", required = true) String password) { 40 | return userService.updatePasswdById(id, password); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/business/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.business.mapper; 2 | 3 | import com.d2c.member.business.model.User; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | @Mapper 8 | public interface UserMapper { 9 | 10 | User findByName(@Param("username") String username); 11 | 12 | int updatePasswdById(@Param("id") Long id, @Param("password") String password); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/business/model/User.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.business.model; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class User implements Serializable { 12 | 13 | Long id; 14 | @NonNull 15 | String username; 16 | @NonNull 17 | String password; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/business/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.business.service; 2 | 3 | import com.d2c.member.business.model.User; 4 | import com.d2c.member.elasticsearch.document.UserSearch; 5 | import com.d2c.member.mongodb.document.UserMongo; 6 | 7 | import java.util.List; 8 | 9 | public interface UserService { 10 | 11 | User findByName(String username); 12 | 13 | User findCacheByName(String username); 14 | 15 | List findMongoByName(String username); 16 | 17 | List findSearchByName(String username); 18 | 19 | int updatePasswdById(Long id, String password); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/business/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.business.service.impl; 2 | 3 | import com.codingapi.txlcn.tc.annotation.DTXPropagation; 4 | import com.codingapi.txlcn.tc.annotation.LcnTransaction; 5 | import com.d2c.member.business.mapper.UserMapper; 6 | import com.d2c.member.business.model.User; 7 | import com.d2c.member.business.service.UserService; 8 | import com.d2c.member.elasticsearch.document.UserSearch; 9 | import com.d2c.member.elasticsearch.repository.UserSearchRepository; 10 | import com.d2c.member.mongodb.document.UserMongo; 11 | import com.d2c.member.mongodb.repository.UserMongoRepository; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.cache.annotation.Cacheable; 14 | import org.springframework.data.redis.core.RedisTemplate; 15 | import org.springframework.stereotype.Service; 16 | import org.springframework.transaction.annotation.Transactional; 17 | 18 | import java.util.List; 19 | 20 | @Service 21 | public class UserServiceImpl implements UserService { 22 | 23 | @Autowired 24 | private UserMapper userMapper; 25 | @Autowired 26 | private RedisTemplate redisTemplate; 27 | @Autowired 28 | private UserMongoRepository userMongoRepository; 29 | @Autowired 30 | private UserSearchRepository userSearchRepository; 31 | 32 | @Override 33 | public User findByName(String username) { 34 | User user = userMapper.findByName(username); 35 | redisTemplate.opsForValue().set("User::user:" + username, user); 36 | userMongoRepository.save(new UserMongo(user)); 37 | userSearchRepository.save(new UserSearch(user)); 38 | return user; 39 | } 40 | 41 | @Override 42 | @Cacheable(value = "User", key = "'user:'+#username", unless = "#result == null") 43 | public User findCacheByName(String username) { 44 | return null; 45 | } 46 | 47 | @Override 48 | public List findMongoByName(String username) { 49 | return userMongoRepository.findByUsername(username); 50 | } 51 | 52 | @Override 53 | public List findSearchByName(String username) { 54 | return userSearchRepository.findByUsername(username); 55 | } 56 | 57 | @Override 58 | @LcnTransaction(propagation = DTXPropagation.SUPPORTS) 59 | @Transactional 60 | public int updatePasswdById(Long id, String password) { 61 | return userMapper.updatePasswdById(id, password); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/config/mybatis/MybatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.config.mybatis; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; 4 | import org.mybatis.spring.annotation.MapperScan; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.transaction.annotation.EnableTransactionManagement; 8 | 9 | @Configuration 10 | @EnableTransactionManagement 11 | @MapperScan("com.d2c.*.*.mapper") 12 | public class MybatisConfig { 13 | 14 | @Bean 15 | public PaginationInterceptor paginationInterceptor() { 16 | return new PaginationInterceptor(); 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/config/redis/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.config.redis; 2 | 3 | import com.alibaba.fastjson.parser.ParserConfig; 4 | import com.d2c.member.config.redis.serializer.FastJsonRedisSerializer; 5 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 6 | import org.springframework.cache.CacheManager; 7 | import org.springframework.cache.annotation.CachingConfigurerSupport; 8 | import org.springframework.cache.annotation.EnableCaching; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.data.redis.cache.RedisCacheConfiguration; 12 | import org.springframework.data.redis.cache.RedisCacheManager; 13 | import org.springframework.data.redis.cache.RedisCacheWriter; 14 | import org.springframework.data.redis.connection.RedisConnectionFactory; 15 | import org.springframework.data.redis.core.RedisTemplate; 16 | import org.springframework.data.redis.serializer.RedisSerializationContext; 17 | import org.springframework.data.redis.serializer.StringRedisSerializer; 18 | 19 | import java.time.Duration; 20 | 21 | @Configuration 22 | @EnableCaching 23 | public class RedisConfig extends CachingConfigurerSupport { 24 | 25 | @Bean 26 | public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { 27 | RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); 28 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); 29 | RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer); 30 | RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); 31 | defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofHours(24)); 32 | RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig); 33 | ParserConfig.getGlobalInstance().addAccept("com.d2c.member.business.model."); 34 | return cacheManager; 35 | } 36 | 37 | @Bean 38 | public RedisCacheConfiguration redisCacheConfiguration() { 39 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); 40 | RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); 41 | configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(24)); 42 | return configuration; 43 | } 44 | 45 | @Bean 46 | @ConditionalOnMissingBean(name = "redisTemplate") 47 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { 48 | RedisTemplate template = new RedisTemplate<>(); 49 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); 50 | template.setValueSerializer(fastJsonRedisSerializer); 51 | template.setHashValueSerializer(fastJsonRedisSerializer); 52 | template.setKeySerializer(new StringRedisSerializer()); 53 | template.setHashKeySerializer(new StringRedisSerializer()); 54 | template.setConnectionFactory(redisConnectionFactory); 55 | return template; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/config/redis/serializer/FastJsonRedisSerializer.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.config.redis.serializer; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.serializer.SerializerFeature; 5 | import org.springframework.data.redis.serializer.RedisSerializer; 6 | import org.springframework.data.redis.serializer.SerializationException; 7 | 8 | import java.nio.charset.Charset; 9 | 10 | public class FastJsonRedisSerializer implements RedisSerializer { 11 | 12 | private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 13 | private Class clazz; 14 | 15 | public FastJsonRedisSerializer(Class clazz) { 16 | super(); 17 | this.clazz = clazz; 18 | } 19 | 20 | @Override 21 | public byte[] serialize(T t) throws SerializationException { 22 | if (null == t) { 23 | return new byte[0]; 24 | } 25 | return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); 26 | } 27 | 28 | @Override 29 | public T deserialize(byte[] bytes) throws SerializationException { 30 | if (null == bytes || bytes.length <= 0) { 31 | return null; 32 | } 33 | String str = new String(bytes, DEFAULT_CHARSET); 34 | return (T) JSON.parseObject(str, clazz); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/config/transaction/TransactionConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.config.transaction; 2 | 3 | import com.codingapi.txlcn.tc.config.EnableDistributedTransaction; 4 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | @EnableDiscoveryClient 9 | @EnableDistributedTransaction 10 | public class TransactionConfig { 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/elasticsearch/document/UserSearch.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.elasticsearch.document; 2 | 3 | import com.d2c.member.business.model.User; 4 | import lombok.Data; 5 | import lombok.NonNull; 6 | import org.springframework.beans.BeanUtils; 7 | import org.springframework.data.annotation.Id; 8 | import org.springframework.data.elasticsearch.annotations.Document; 9 | import org.springframework.data.elasticsearch.annotations.Field; 10 | import org.springframework.data.elasticsearch.annotations.FieldType; 11 | 12 | import java.io.Serializable; 13 | 14 | @Data 15 | @Document(indexName = "d2cmall-index", type = "user") 16 | public class UserSearch implements Serializable { 17 | 18 | @Id 19 | Long id; 20 | @NonNull 21 | @Field(type = FieldType.Keyword) 22 | String username; 23 | @NonNull 24 | String password; 25 | 26 | public UserSearch() { 27 | } 28 | 29 | public UserSearch(User user) { 30 | this(); 31 | BeanUtils.copyProperties(user, this); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/elasticsearch/repository/UserSearchRepository.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.elasticsearch.repository; 2 | 3 | import com.d2c.member.elasticsearch.document.UserSearch; 4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface UserSearchRepository extends ElasticsearchRepository { 9 | 10 | List findByUsername(String username); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/mongodb/document/UserMongo.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.mongodb.document; 2 | 3 | import com.d2c.member.business.model.User; 4 | import lombok.Data; 5 | import lombok.NonNull; 6 | import org.springframework.beans.BeanUtils; 7 | import org.springframework.data.annotation.Id; 8 | import org.springframework.data.mongodb.core.mapping.Document; 9 | 10 | @Data 11 | @Document(collection = "user") 12 | public class UserMongo { 13 | 14 | @Id 15 | Long id; 16 | @NonNull 17 | String username; 18 | @NonNull 19 | String password; 20 | 21 | public UserMongo() { 22 | } 23 | 24 | public UserMongo(User user) { 25 | this(); 26 | BeanUtils.copyProperties(user, this); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /service-member/src/main/java/com/d2c/member/mongodb/repository/UserMongoRepository.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member.mongodb.repository; 2 | 3 | import com.d2c.member.mongodb.document.UserMongo; 4 | import org.springframework.data.mongodb.repository.MongoRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface UserMongoRepository extends MongoRepository { 9 | 10 | List findByUsername(String username); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /service-member/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # tomcat 2 | server: 3 | port: 8001 4 | 5 | # eureka 6 | eureka: 7 | instance: 8 | lease-expiration-duration-in-seconds: 30 9 | lease-renewal-interval-in-seconds: 10 10 | client: 11 | service-url: 12 | defaultZone: http://192.168.0.146:1001/eureka/ 13 | 14 | # actuator 15 | management: 16 | endpoints: 17 | web: 18 | exposure: 19 | include: "*" 20 | 21 | # tx-lcn 22 | tx-lcn: 23 | client: 24 | manager-address: 192.168.0.146:8070 25 | resource-order: 0 26 | logger: 27 | enabled: false 28 | message: 29 | netty: 30 | wait-time: 5000 31 | springcloud: 32 | loadbalance: 33 | enabled: true 34 | 35 | # spring 36 | spring: 37 | application: 38 | name: service-member 39 | 40 | # database 41 | datasource: 42 | url: jdbc:mysql://192.168.0.146:3306/mall?useUnicode=true&characterEncoding=utf-8&useSSL=false 43 | username: root 44 | password: 123456 45 | type: com.alibaba.druid.pool.DruidDataSource 46 | driverClassName: com.mysql.jdbc.Driver 47 | 48 | # redis 49 | redis: 50 | database: 0 51 | host: 192.168.0.146 52 | port: 6379 53 | jedis: 54 | pool: 55 | max-active: 1000 56 | max-idle: 100 57 | min-idle: 1 58 | 59 | data: 60 | # mongodb 61 | mongodb: 62 | uri: mongodb://192.168.0.146:27017/mall 63 | 64 | # elasticsearch 65 | elasticsearch: 66 | cluster-name: d2cmall-es 67 | cluster-nodes: 192.168.0.146:9300 68 | 69 | # rabbitmq 70 | rabbitmq: 71 | host: 192.168.0.146 72 | port: 5672 73 | username: guest 74 | password: guest 75 | 76 | # mybatis-plus 77 | mybatis-plus: 78 | mapper-locations: classpath:/mapper/*.xml 79 | typeAliasesPackage: com.d2c.*.*.model 80 | global-config: 81 | db-config: 82 | id-type: id_worker 83 | field-strategy: not_null 84 | logic-delete-value: 1 85 | logic-not-delete-value: 0 86 | sql-parser-cache: true 87 | configuration: 88 | auto-mapping-behavior: partial 89 | map-underscore-to-camel-case: true 90 | cache-enabled: false 91 | 92 | 93 | ######################################################### cluster ###################################################### 94 | 95 | # # redis 96 | # redis: 97 | # database: 0 98 | # jedis: 99 | # pool: 100 | # max-active: 8 101 | # max-idle: 8 102 | # min-idle: 0 103 | # cluster: 104 | # nodes: 105 | # - 192.168.0.143:7001 106 | # - 192.168.0.143:7002 107 | # - 192.168.0.143:7003 108 | # - 192.168.0.143:7004 109 | # - 192.168.0.143:7005 110 | # - 192.168.0.143:7006 111 | 112 | # data: 113 | # # mongodb 114 | # mongodb: 115 | # uri: mongodb://192.168.0.143:27017,192.168.0.144:27017,192.168.0.145:27017/shop 116 | 117 | # # elasticsearch 118 | # elasticsearch: 119 | # cluster-name: d2cmall-es 120 | # cluster-nodes: 192.168.0.143:9300,192.168.0.144:9300,192.168.0.145:9300 121 | 122 | -------------------------------------------------------------------------------- /service-member/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: service-member 4 | # config 5 | cloud: 6 | config: 7 | uri: http://192.168.0.146:2001 8 | profile: dev 9 | label: master -------------------------------------------------------------------------------- /service-member/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | update m_user 19 | set password = #{password} 20 | where id = #{id} 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /service-member/src/test/java/com/d2c/member/ServiceMemberApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.d2c.member; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ServiceMemberApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /service-order/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | VOLUME /tmp 3 | ADD target/service-order-0.0.1-SNAPSHOT.jar app.jar 4 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] -------------------------------------------------------------------------------- /service-order/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.d2c 7 | service-order 8 | 0.0.1-SNAPSHOT 9 | service-order 10 | Demo project for Spring Boot 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.7.RELEASE 16 | 17 | 18 | 19 | 20 | 1.8 21 | Finchley.RELEASE 22 | mall 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-dependencies 30 | ${spring-cloud.version} 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-netflix-eureka-client 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-config 45 | 46 | 47 | org.springframework.cloud 48 | spring-cloud-starter-bus-amqp 49 | 50 | 51 | org.springframework.cloud 52 | spring-cloud-starter-netflix-hystrix 53 | 54 | 55 | org.springframework.cloud 56 | spring-cloud-starter-openfeign 57 | 58 | 59 | de.codecentric 60 | spring-boot-admin-starter-client 61 | 2.0.4 62 | 63 | 64 | 65 | com.codingapi.txlcn 66 | txlcn-tc 67 | 5.0.2.RELEASE 68 | 69 | 70 | com.codingapi.txlcn 71 | txlcn-txmsg-netty 72 | 5.0.2.RELEASE 73 | 74 | 75 | 76 | org.springframework.boot 77 | spring-boot-starter-web 78 | 79 | 80 | org.springframework.boot 81 | spring-boot-starter-aop 82 | 83 | 84 | org.springframework.boot 85 | spring-boot-starter-jdbc 86 | 87 | 88 | org.springframework.boot 89 | spring-boot-starter-logging 90 | 91 | 92 | org.springframework.boot 93 | spring-boot-starter-actuator 94 | 95 | 96 | org.springframework.boot 97 | spring-boot-starter-data-redis 98 | 99 | 100 | org.springframework.boot 101 | spring-boot-starter-data-mongodb 102 | 103 | 104 | org.springframework.boot 105 | spring-boot-starter-data-elasticsearch 106 | 107 | 108 | org.springframework.boot 109 | spring-boot-starter-test 110 | test 111 | 112 | 113 | 114 | com.baomidou 115 | mybatis-plus-boot-starter 116 | 3.0.7.1 117 | 118 | 119 | com.alibaba 120 | druid-spring-boot-starter 121 | 1.1.10 122 | 123 | 124 | mysql 125 | mysql-connector-java 126 | 5.1.44 127 | 128 | 129 | com.alibaba 130 | fastjson 131 | 1.2.54 132 | 133 | 134 | org.apache.commons 135 | commons-lang3 136 | 3.8 137 | 138 | 139 | org.projectlombok 140 | lombok 141 | 1.18.4 142 | 143 | 144 | junit 145 | junit 146 | 4.12 147 | test 148 | 149 | 150 | 151 | 152 | 153 | 154 | org.springframework.boot 155 | spring-boot-maven-plugin 156 | 157 | 158 | com.spotify 159 | dockerfile-maven-plugin 160 | 1.4.6 161 | 162 | ${docker.image.prefix}/${project.artifactId} 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/ServiceOrderApplication.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 6 | import org.springframework.cloud.openfeign.EnableFeignClients; 7 | 8 | @EnableFeignClients 9 | @EnableCircuitBreaker 10 | @SpringBootApplication 11 | public class ServiceOrderApplication { 12 | 13 | public static void main(String[] args) { 14 | System.setProperty("es.set.netty.runtime.available.processors", "false"); 15 | SpringApplication.run(ServiceOrderApplication.class, args); 16 | } 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/client/MemberClient.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.client; 2 | 3 | import com.d2c.order.business.client.fallback.MemberClientFallback; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | 9 | @FeignClient(name = "service-member", fallback = MemberClientFallback.class) 10 | public interface MemberClient { 11 | 12 | @GetMapping("/api/user/update/{id}") 13 | int updatePasswdById(@PathVariable(name = "id") Long id, @RequestParam(value = "password") String password); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/client/ProductClient.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.client; 2 | 3 | import com.d2c.order.business.client.fallback.ProductClientFallback; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | 9 | import java.math.BigDecimal; 10 | 11 | @FeignClient(name = "service-product", fallback = ProductClientFallback.class) 12 | public interface ProductClient { 13 | 14 | @GetMapping("/api/product/update/{id}") 15 | int updatePriceById(@PathVariable(name = "id") Long id, @RequestParam(value = "price") BigDecimal price); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/client/fallback/MemberClientFallback.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.client.fallback; 2 | 3 | import com.d2c.order.business.client.MemberClient; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class MemberClientFallback implements MemberClient { 8 | 9 | @Override 10 | public int updatePasswdById(Long id, String password) { 11 | System.out.println("MemberClientFallback中的降级方法"); 12 | throw new RuntimeException("updatePasswdById更新失败"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/client/fallback/ProductClientFallback.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.client.fallback; 2 | 3 | import com.d2c.order.business.client.ProductClient; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.math.BigDecimal; 7 | 8 | @Component 9 | public class ProductClientFallback implements ProductClient { 10 | 11 | @Override 12 | public int updatePriceById(Long id, BigDecimal price) { 13 | System.out.println("ProductClientFallback"); 14 | throw new RuntimeException("updatePriceBySn更新失败"); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/controller/ConfigCtrl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.cloud.context.config.annotation.RefreshScope; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RefreshScope 9 | @RestController 10 | public class ConfigCtrl { 11 | 12 | @Value("${server.profile}") 13 | private String profile; 14 | 15 | @GetMapping("/profile") 16 | public String profile() { 17 | return this.profile; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/controller/OrderRestCtrl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.controller; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.d2c.order.business.model.Order; 5 | import com.d2c.order.business.service.OrderService; 6 | import com.d2c.order.elasticsearch.document.OrderSearch; 7 | import com.d2c.order.mongodb.document.OrderMongo; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.RequestParam; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import java.util.List; 15 | 16 | @RestController 17 | public class OrderRestCtrl { 18 | 19 | @Autowired 20 | private OrderService orderService; 21 | 22 | @RequestMapping(value = "/api/order", method = RequestMethod.GET) 23 | public Order findBySn(@RequestParam(value = "sn", required = true) String sn) { 24 | return orderService.findBySn(sn); 25 | } 26 | 27 | @RequestMapping(value = "/api/order/cache", method = RequestMethod.GET) 28 | public Order findCacheBySn(@RequestParam(value = "sn", required = true) String sn) { 29 | return orderService.findCacheBySn(sn); 30 | } 31 | 32 | @RequestMapping(value = "/api/order/mongo", method = RequestMethod.GET) 33 | public List findMongoBySn(@RequestParam(value = "sn", required = true) String sn) { 34 | return orderService.findMongoBySn(sn); 35 | } 36 | 37 | @RequestMapping(value = "/api/order/search", method = RequestMethod.GET) 38 | public List findSearchBySn(@RequestParam(value = "sn", required = true) String sn) { 39 | return orderService.findSearchBySn(sn); 40 | } 41 | 42 | @RequestMapping(value = "/api/order/tx", method = RequestMethod.GET) 43 | public JSONObject doSomeThing(String sn, Long productId, Long memberId) { 44 | int result = orderService.doSomeThing(sn, productId, memberId); 45 | JSONObject obj = new JSONObject(); 46 | obj.put("result", result); 47 | return obj; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/mapper/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.mapper; 2 | 3 | import com.d2c.order.business.model.Order; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.math.BigDecimal; 8 | 9 | @Mapper 10 | public interface OrderMapper { 11 | 12 | Order findBySn(@Param("sn") String sn); 13 | 14 | int updateAmountBySn(@Param("sn") String sn, @Param("payAmount") BigDecimal payAmount); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/model/Order.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.model; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | 7 | import java.io.Serializable; 8 | import java.math.BigDecimal; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | public class Order implements Serializable { 13 | 14 | Long id; 15 | @NonNull 16 | String sn; 17 | BigDecimal payAmount; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.service; 2 | 3 | import com.d2c.order.business.model.Order; 4 | import com.d2c.order.elasticsearch.document.OrderSearch; 5 | import com.d2c.order.mongodb.document.OrderMongo; 6 | 7 | import java.util.List; 8 | 9 | public interface OrderService { 10 | 11 | Order findBySn(String sn); 12 | 13 | Order findCacheBySn(String sn); 14 | 15 | List findMongoBySn(String sn); 16 | 17 | List findSearchBySn(String sn); 18 | 19 | int doSomeThing(String sn, Long productId, Long memberId); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/business/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.business.service.impl; 2 | 3 | import com.codingapi.txlcn.tc.annotation.LcnTransaction; 4 | import com.d2c.order.business.client.MemberClient; 5 | import com.d2c.order.business.client.ProductClient; 6 | import com.d2c.order.business.mapper.OrderMapper; 7 | import com.d2c.order.business.model.Order; 8 | import com.d2c.order.business.service.OrderService; 9 | import com.d2c.order.elasticsearch.document.OrderSearch; 10 | import com.d2c.order.elasticsearch.repository.OrderSearchRepository; 11 | import com.d2c.order.mongodb.document.OrderMongo; 12 | import com.d2c.order.mongodb.repository.OrderMongoRepository; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.cache.annotation.Cacheable; 15 | import org.springframework.data.redis.core.RedisTemplate; 16 | import org.springframework.stereotype.Service; 17 | import org.springframework.transaction.annotation.Transactional; 18 | 19 | import java.math.BigDecimal; 20 | import java.util.List; 21 | 22 | @Service 23 | public class OrderServiceImpl implements OrderService { 24 | 25 | @Autowired 26 | private OrderMapper orderMapper; 27 | @Autowired 28 | private MemberClient memberClient; 29 | @Autowired 30 | private ProductClient productClient; 31 | @Autowired 32 | private RedisTemplate redisTemplate; 33 | @Autowired 34 | private OrderMongoRepository orderMongoRepository; 35 | @Autowired 36 | private OrderSearchRepository orderSearchRepository; 37 | 38 | @Override 39 | public Order findBySn(String sn) { 40 | Order order = orderMapper.findBySn(sn); 41 | redisTemplate.opsForValue().set("Order::order:" + sn, order); 42 | orderMongoRepository.save(new OrderMongo(order)); 43 | orderSearchRepository.save(new OrderSearch(order)); 44 | return order; 45 | } 46 | 47 | @Override 48 | @Cacheable(value = "Order", key = "'order:'+#sn", unless = "#result == null") 49 | public Order findCacheBySn(String sn) { 50 | return null; 51 | } 52 | 53 | @Override 54 | public List findMongoBySn(String sn) { 55 | return orderMongoRepository.findBySn(sn); 56 | } 57 | 58 | @Override 59 | public List findSearchBySn(String sn) { 60 | return orderSearchRepository.findBySn(sn); 61 | } 62 | 63 | @Override 64 | @LcnTransaction 65 | @Transactional 66 | public int doSomeThing(String sn, Long productId, Long memberId) { 67 | int rs1 = orderMapper.updateAmountBySn(sn, new BigDecimal((int) (Math.random() * 100 + 1))); 68 | int rs2 = memberClient.updatePasswdById(memberId, String.valueOf((int) (Math.random() * 100 + 1))); 69 | int rs3 = productClient.updatePriceById(productId, new BigDecimal((int) (Math.random() * 100 + 1))); 70 | //return rs1 + rs2 + rs3; 71 | throw new RuntimeException("doSomeThing更新失败"); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/config/mybatis/MybatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.config.mybatis; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; 4 | import org.mybatis.spring.annotation.MapperScan; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.transaction.annotation.EnableTransactionManagement; 8 | 9 | @Configuration 10 | @EnableTransactionManagement 11 | @MapperScan("com.d2c.*.*.mapper") 12 | public class MybatisConfig { 13 | 14 | @Bean 15 | public PaginationInterceptor paginationInterceptor() { 16 | return new PaginationInterceptor(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/config/redis/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.config.redis; 2 | 3 | import com.alibaba.fastjson.parser.ParserConfig; 4 | import com.d2c.order.config.redis.serializer.FastJsonRedisSerializer; 5 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 6 | import org.springframework.cache.CacheManager; 7 | import org.springframework.cache.annotation.CachingConfigurerSupport; 8 | import org.springframework.cache.annotation.EnableCaching; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.data.redis.cache.RedisCacheConfiguration; 12 | import org.springframework.data.redis.cache.RedisCacheManager; 13 | import org.springframework.data.redis.cache.RedisCacheWriter; 14 | import org.springframework.data.redis.connection.RedisConnectionFactory; 15 | import org.springframework.data.redis.core.RedisTemplate; 16 | import org.springframework.data.redis.serializer.RedisSerializationContext; 17 | import org.springframework.data.redis.serializer.StringRedisSerializer; 18 | 19 | import java.time.Duration; 20 | 21 | @Configuration 22 | @EnableCaching 23 | public class RedisConfig extends CachingConfigurerSupport { 24 | 25 | @Bean 26 | public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { 27 | RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); 28 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); 29 | RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer); 30 | RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); 31 | defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofHours(24)); 32 | RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig); 33 | ParserConfig.getGlobalInstance().addAccept("com.d2c.order.business.model."); 34 | return cacheManager; 35 | } 36 | 37 | @Bean 38 | public RedisCacheConfiguration redisCacheConfiguration() { 39 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); 40 | RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); 41 | configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(24)); 42 | return configuration; 43 | } 44 | 45 | @Bean 46 | @ConditionalOnMissingBean(name = "redisTemplate") 47 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { 48 | RedisTemplate template = new RedisTemplate<>(); 49 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); 50 | template.setValueSerializer(fastJsonRedisSerializer); 51 | template.setHashValueSerializer(fastJsonRedisSerializer); 52 | template.setKeySerializer(new StringRedisSerializer()); 53 | template.setHashKeySerializer(new StringRedisSerializer()); 54 | template.setConnectionFactory(redisConnectionFactory); 55 | return template; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/config/redis/serializer/FastJsonRedisSerializer.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.config.redis.serializer; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.serializer.SerializerFeature; 5 | import org.springframework.data.redis.serializer.RedisSerializer; 6 | import org.springframework.data.redis.serializer.SerializationException; 7 | 8 | import java.nio.charset.Charset; 9 | 10 | public class FastJsonRedisSerializer implements RedisSerializer { 11 | 12 | private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 13 | private Class clazz; 14 | 15 | public FastJsonRedisSerializer(Class clazz) { 16 | super(); 17 | this.clazz = clazz; 18 | } 19 | 20 | @Override 21 | public byte[] serialize(T t) throws SerializationException { 22 | if (null == t) { 23 | return new byte[0]; 24 | } 25 | return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); 26 | } 27 | 28 | @Override 29 | public T deserialize(byte[] bytes) throws SerializationException { 30 | if (null == bytes || bytes.length <= 0) { 31 | return null; 32 | } 33 | String str = new String(bytes, DEFAULT_CHARSET); 34 | return (T) JSON.parseObject(str, clazz); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/config/transaction/TransactionConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.config.transaction; 2 | 3 | import com.codingapi.txlcn.tc.config.EnableDistributedTransaction; 4 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | @EnableDiscoveryClient 9 | @EnableDistributedTransaction 10 | public class TransactionConfig { 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/elasticsearch/document/OrderSearch.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.elasticsearch.document; 2 | 3 | import com.d2c.order.business.model.Order; 4 | import lombok.Data; 5 | import lombok.NonNull; 6 | import org.springframework.beans.BeanUtils; 7 | import org.springframework.data.elasticsearch.annotations.Document; 8 | import org.springframework.data.elasticsearch.annotations.Field; 9 | import org.springframework.data.elasticsearch.annotations.FieldType; 10 | 11 | import java.io.Serializable; 12 | import java.math.BigDecimal; 13 | 14 | @Data 15 | @Document(indexName = "d2cmall-index", type = "order") 16 | public class OrderSearch implements Serializable { 17 | 18 | Long id; 19 | @NonNull 20 | @Field(type = FieldType.Keyword) 21 | String sn; 22 | BigDecimal payAmount; 23 | 24 | public OrderSearch() { 25 | } 26 | 27 | public OrderSearch(Order order) { 28 | this(); 29 | BeanUtils.copyProperties(order, this); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/elasticsearch/repository/OrderSearchRepository.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.elasticsearch.repository; 2 | 3 | import com.d2c.order.elasticsearch.document.OrderSearch; 4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface OrderSearchRepository extends ElasticsearchRepository { 9 | 10 | List findBySn(String sn); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/mongodb/document/OrderMongo.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.mongodb.document; 2 | 3 | import com.d2c.order.business.model.Order; 4 | import lombok.Data; 5 | import lombok.NonNull; 6 | import org.springframework.beans.BeanUtils; 7 | import org.springframework.data.mongodb.core.mapping.Document; 8 | 9 | import java.math.BigDecimal; 10 | 11 | @Data 12 | @Document(collection = "user") 13 | public class OrderMongo { 14 | 15 | Long id; 16 | @NonNull 17 | String sn; 18 | BigDecimal payAmount; 19 | 20 | public OrderMongo() { 21 | } 22 | 23 | public OrderMongo(Order order) { 24 | this(); 25 | BeanUtils.copyProperties(order, this); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /service-order/src/main/java/com/d2c/order/mongodb/repository/OrderMongoRepository.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order.mongodb.repository; 2 | 3 | import com.d2c.order.mongodb.document.OrderMongo; 4 | import org.springframework.data.mongodb.repository.MongoRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface OrderMongoRepository extends MongoRepository { 9 | 10 | List findBySn(String sn); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /service-order/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # tomcat 2 | server: 3 | port: 8002 4 | 5 | # eureka 6 | eureka: 7 | instance: 8 | lease-expiration-duration-in-seconds: 30 9 | lease-renewal-interval-in-seconds: 10 10 | client: 11 | service-url: 12 | defaultZone: http://192.168.0.146:1001/eureka/ 13 | 14 | # feign 15 | feign: 16 | hystrix: 17 | enabled: true 18 | client: 19 | config: 20 | default: 21 | connectTimeout: 10000 22 | readTimeout: 5000 23 | 24 | # hystrix 25 | hystrix: 26 | command: 27 | default: 28 | execution: 29 | isolation: 30 | thread: 31 | timeoutInMilliseconds: 5000 32 | 33 | # actuator 34 | management: 35 | endpoints: 36 | web: 37 | exposure: 38 | include: "*" 39 | 40 | # tx-lcn 41 | tx-lcn: 42 | client: 43 | manager-address: 192.168.0.146:8070 44 | resource-order: 0 45 | logger: 46 | enabled: false 47 | message: 48 | netty: 49 | wait-time: 5000 50 | springcloud: 51 | loadbalance: 52 | enabled: true 53 | 54 | # spring 55 | spring: 56 | application: 57 | name: service-order 58 | 59 | # database 60 | datasource: 61 | url: jdbc:mysql://192.168.0.146:3306/mall?useUnicode=true&characterEncoding=utf-8&useSSL=false 62 | username: root 63 | password: 123456 64 | type: com.alibaba.druid.pool.DruidDataSource 65 | driverClassName: com.mysql.jdbc.Driver 66 | 67 | # redis 68 | redis: 69 | database: 0 70 | host: 192.168.0.146 71 | port: 6379 72 | jedis: 73 | pool: 74 | max-active: 1000 75 | max-idle: 100 76 | min-idle: 1 77 | 78 | data: 79 | # mongodb 80 | mongodb: 81 | uri: mongodb://192.168.0.146:27017/mall 82 | 83 | # elasticsearch 84 | elasticsearch: 85 | cluster-name: d2cmall-es 86 | cluster-nodes: 192.168.0.146:9300 87 | 88 | # rabbitmq 89 | rabbitmq: 90 | host: 192.168.0.146 91 | port: 5672 92 | username: guest 93 | password: guest 94 | 95 | # mybatis-plus 96 | mybatis-plus: 97 | mapper-locations: classpath:/mapper/*.xml 98 | typeAliasesPackage: com.d2c.*.*.model 99 | global-config: 100 | db-config: 101 | id-type: id_worker 102 | field-strategy: not_null 103 | logic-delete-value: 1 104 | logic-not-delete-value: 0 105 | sql-parser-cache: true 106 | configuration: 107 | auto-mapping-behavior: partial 108 | map-underscore-to-camel-case: true 109 | cache-enabled: false 110 | 111 | 112 | ######################################################### cluster ###################################################### 113 | 114 | # # redis 115 | # redis: 116 | # database: 0 117 | # jedis: 118 | # pool: 119 | # max-active: 8 120 | # max-idle: 8 121 | # min-idle: 0 122 | # cluster: 123 | # nodes: 124 | # - 192.168.0.143:7001 125 | # - 192.168.0.143:7002 126 | # - 192.168.0.143:7003 127 | # - 192.168.0.143:7004 128 | # - 192.168.0.143:7005 129 | # - 192.168.0.143:7006 130 | 131 | # data: 132 | # # mongodb 133 | # mongodb: 134 | # uri: mongodb://192.168.0.143:27017,192.168.0.144:27017,192.168.0.145:27017/shop 135 | 136 | # # elasticsearch 137 | # elasticsearch: 138 | # cluster-name: d2cmall-es 139 | # cluster-nodes: 192.168.0.143:9300,192.168.0.144:9300,192.168.0.145:9300 140 | 141 | -------------------------------------------------------------------------------- /service-order/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: service-order 4 | # config 5 | cloud: 6 | config: 7 | uri: http://192.168.0.146:2001 8 | profile: dev 9 | label: master -------------------------------------------------------------------------------- /service-order/src/main/resources/mapper/OrderMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | update o_order 19 | set pay_amount = #{payAmount} 20 | where sn = #{sn} 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /service-order/src/test/java/com/d2c/order/MallOrderApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.d2c.order; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class MallOrderApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /service-product/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | VOLUME /tmp 3 | ADD target/service-product-0.0.1-SNAPSHOT.jar app.jar 4 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] -------------------------------------------------------------------------------- /service-product/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.d2c 7 | service-product 8 | 0.0.1-SNAPSHOT 9 | service-product 10 | Demo project for Spring Boot 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.0.7.RELEASE 16 | 17 | 18 | 19 | 20 | 1.8 21 | Finchley.RELEASE 22 | mall 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-dependencies 30 | ${spring-cloud.version} 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-netflix-eureka-client 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-config 45 | 46 | 47 | org.springframework.cloud 48 | spring-cloud-starter-bus-amqp 49 | 50 | 51 | de.codecentric 52 | spring-boot-admin-starter-client 53 | 2.0.4 54 | 55 | 56 | 57 | com.codingapi.txlcn 58 | txlcn-tc 59 | 5.0.2.RELEASE 60 | 61 | 62 | com.codingapi.txlcn 63 | txlcn-txmsg-netty 64 | 5.0.2.RELEASE 65 | 66 | 67 | 68 | org.springframework.boot 69 | spring-boot-starter-web 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-starter-aop 74 | 75 | 76 | org.springframework.boot 77 | spring-boot-starter-jdbc 78 | 79 | 80 | org.springframework.boot 81 | spring-boot-starter-logging 82 | 83 | 84 | org.springframework.boot 85 | spring-boot-starter-actuator 86 | 87 | 88 | org.springframework.boot 89 | spring-boot-starter-data-redis 90 | 91 | 92 | org.springframework.boot 93 | spring-boot-starter-data-mongodb 94 | 95 | 96 | org.springframework.boot 97 | spring-boot-starter-data-elasticsearch 98 | 99 | 100 | org.springframework.boot 101 | spring-boot-starter-test 102 | test 103 | 104 | 105 | 106 | com.baomidou 107 | mybatis-plus-boot-starter 108 | 3.0.7.1 109 | 110 | 111 | com.alibaba 112 | druid-spring-boot-starter 113 | 1.1.10 114 | 115 | 116 | mysql 117 | mysql-connector-java 118 | 5.1.44 119 | 120 | 121 | com.alibaba 122 | fastjson 123 | 1.2.54 124 | 125 | 126 | org.apache.commons 127 | commons-lang3 128 | 3.8 129 | 130 | 131 | org.projectlombok 132 | lombok 133 | 1.18.4 134 | 135 | 136 | junit 137 | junit 138 | 4.12 139 | test 140 | 141 | 142 | 143 | 144 | 145 | 146 | org.springframework.boot 147 | spring-boot-maven-plugin 148 | 149 | 150 | com.spotify 151 | dockerfile-maven-plugin 152 | 1.4.6 153 | 154 | ${docker.image.prefix}/${project.artifactId} 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/ServiceProductApplication.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ServiceProductApplication { 8 | 9 | public static void main(String[] args) { 10 | System.setProperty("es.set.netty.runtime.available.processors", "false"); 11 | SpringApplication.run(ServiceProductApplication.class, args); 12 | } 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/business/controller/ConfigCtrl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.business.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.cloud.context.config.annotation.RefreshScope; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RefreshScope 9 | @RestController 10 | public class ConfigCtrl { 11 | 12 | @Value("${server.profile}") 13 | private String profile; 14 | 15 | @GetMapping("/profile") 16 | public String profile() { 17 | return this.profile; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/business/controller/ProductRestCtrl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.business.controller; 2 | 3 | import com.d2c.product.business.model.Product; 4 | import com.d2c.product.business.service.ProductService; 5 | import com.d2c.product.elasticsearch.document.ProductSearch; 6 | import com.d2c.product.mongodb.document.ProductMongo; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | import java.math.BigDecimal; 11 | import java.util.List; 12 | 13 | @RestController 14 | public class ProductRestCtrl { 15 | 16 | @Autowired 17 | private ProductService productService; 18 | 19 | @RequestMapping(value = "/api/product", method = RequestMethod.GET) 20 | public Product findBySn(@RequestParam(value = "sn", required = true) String sn) { 21 | return productService.findBySn(sn); 22 | } 23 | 24 | @RequestMapping(value = "/api/product/cache", method = RequestMethod.GET) 25 | public Product findCacheBySn(@RequestParam(value = "sn", required = true) String sn) { 26 | return productService.findCacheBySn(sn); 27 | } 28 | 29 | @RequestMapping(value = "/api/product/mongo", method = RequestMethod.GET) 30 | public List findMongoBySn(@RequestParam(value = "sn", required = true) String sn) { 31 | return productService.findMongoBySn(sn); 32 | } 33 | 34 | @RequestMapping(value = "/api/product/search", method = RequestMethod.GET) 35 | public List findSearchBySn(@RequestParam(value = "sn", required = true) String sn) { 36 | return productService.findSearchBySn(sn); 37 | } 38 | 39 | @RequestMapping(value = "/api/product/update/{id}", method = RequestMethod.GET) 40 | public int updatePriceById(@PathVariable(name = "id") Long id, @RequestParam(value = "price", required = true) BigDecimal price) { 41 | return productService.updatePriceById(id, price); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/business/mapper/ProductMapper.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.business.mapper; 2 | 3 | import com.d2c.product.business.model.Product; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.math.BigDecimal; 8 | 9 | @Mapper 10 | public interface ProductMapper { 11 | 12 | Product findBySn(@Param("sn") String sn); 13 | 14 | int updatePriceById(@Param("id") Long id, @Param("price") BigDecimal price); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/business/model/Product.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.business.model; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | import lombok.NonNull; 6 | 7 | import java.io.Serializable; 8 | import java.math.BigDecimal; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | public class Product implements Serializable { 13 | 14 | Long id; 15 | @NonNull 16 | String sn; 17 | BigDecimal price; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/business/service/ProductService.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.business.service; 2 | 3 | import com.d2c.product.business.model.Product; 4 | import com.d2c.product.elasticsearch.document.ProductSearch; 5 | import com.d2c.product.mongodb.document.ProductMongo; 6 | 7 | import java.math.BigDecimal; 8 | import java.util.List; 9 | 10 | public interface ProductService { 11 | 12 | Product findBySn(String sn); 13 | 14 | Product findCacheBySn(String sn); 15 | 16 | List findMongoBySn(String sn); 17 | 18 | List findSearchBySn(String sn); 19 | 20 | int updatePriceById(Long id, BigDecimal price); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/business/service/impl/ProductServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.business.service.impl; 2 | 3 | import com.codingapi.txlcn.tc.annotation.DTXPropagation; 4 | import com.codingapi.txlcn.tc.annotation.LcnTransaction; 5 | import com.d2c.product.business.mapper.ProductMapper; 6 | import com.d2c.product.business.model.Product; 7 | import com.d2c.product.business.service.ProductService; 8 | import com.d2c.product.elasticsearch.document.ProductSearch; 9 | import com.d2c.product.elasticsearch.repository.ProductSearchRepository; 10 | import com.d2c.product.mongodb.document.ProductMongo; 11 | import com.d2c.product.mongodb.repository.ProductMongoRepository; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.cache.annotation.Cacheable; 14 | import org.springframework.data.redis.core.RedisTemplate; 15 | import org.springframework.stereotype.Service; 16 | import org.springframework.transaction.annotation.Transactional; 17 | 18 | import java.math.BigDecimal; 19 | import java.util.List; 20 | 21 | @Service 22 | public class ProductServiceImpl implements ProductService { 23 | 24 | @Autowired 25 | private ProductMapper productMapper; 26 | @Autowired 27 | private RedisTemplate redisTemplate; 28 | @Autowired 29 | private ProductMongoRepository productMongoRepository; 30 | @Autowired 31 | private ProductSearchRepository productSearchRepository; 32 | 33 | @Override 34 | public Product findBySn(String sn) { 35 | Product product = productMapper.findBySn(sn); 36 | redisTemplate.opsForValue().set("Product::product:" + sn, product); 37 | productMongoRepository.save(new ProductMongo(product)); 38 | productSearchRepository.save(new ProductSearch(product)); 39 | return product; 40 | } 41 | 42 | @Override 43 | @Cacheable(value = "Product", key = "'product:'+#sn", unless = "#result == null") 44 | public Product findCacheBySn(String sn) { 45 | return null; 46 | } 47 | 48 | @Override 49 | public List findMongoBySn(String sn) { 50 | return productMongoRepository.findBySn(sn); 51 | } 52 | 53 | @Override 54 | public List findSearchBySn(String sn) { 55 | return productSearchRepository.findBySn(sn); 56 | } 57 | 58 | @Override 59 | @LcnTransaction(propagation = DTXPropagation.SUPPORTS) 60 | @Transactional 61 | public int updatePriceById(Long id, BigDecimal price) { 62 | return productMapper.updatePriceById(id, price); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/config/mybatis/MybatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.config.mybatis; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; 4 | import org.mybatis.spring.annotation.MapperScan; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.transaction.annotation.EnableTransactionManagement; 8 | 9 | @Configuration 10 | @EnableTransactionManagement 11 | @MapperScan("com.d2c.*.*.mapper") 12 | public class MybatisConfig { 13 | 14 | @Bean 15 | public PaginationInterceptor paginationInterceptor() { 16 | return new PaginationInterceptor(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/config/redis/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.config.redis; 2 | 3 | import com.alibaba.fastjson.parser.ParserConfig; 4 | import com.d2c.product.config.redis.serializer.FastJsonRedisSerializer; 5 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 6 | import org.springframework.cache.CacheManager; 7 | import org.springframework.cache.annotation.CachingConfigurerSupport; 8 | import org.springframework.cache.annotation.EnableCaching; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.data.redis.cache.RedisCacheConfiguration; 12 | import org.springframework.data.redis.cache.RedisCacheManager; 13 | import org.springframework.data.redis.cache.RedisCacheWriter; 14 | import org.springframework.data.redis.connection.RedisConnectionFactory; 15 | import org.springframework.data.redis.core.RedisTemplate; 16 | import org.springframework.data.redis.serializer.RedisSerializationContext; 17 | import org.springframework.data.redis.serializer.StringRedisSerializer; 18 | 19 | import java.time.Duration; 20 | 21 | @Configuration 22 | @EnableCaching 23 | public class RedisConfig extends CachingConfigurerSupport { 24 | 25 | @Bean 26 | public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { 27 | RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); 28 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); 29 | RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer); 30 | RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); 31 | defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofHours(24)); 32 | RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig); 33 | ParserConfig.getGlobalInstance().addAccept("com.d2c.product.business.model."); 34 | return cacheManager; 35 | } 36 | 37 | @Bean 38 | public RedisCacheConfiguration redisCacheConfiguration() { 39 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); 40 | RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); 41 | configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(24)); 42 | return configuration; 43 | } 44 | 45 | @Bean 46 | @ConditionalOnMissingBean(name = "redisTemplate") 47 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { 48 | RedisTemplate template = new RedisTemplate<>(); 49 | FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); 50 | template.setValueSerializer(fastJsonRedisSerializer); 51 | template.setHashValueSerializer(fastJsonRedisSerializer); 52 | template.setKeySerializer(new StringRedisSerializer()); 53 | template.setHashKeySerializer(new StringRedisSerializer()); 54 | template.setConnectionFactory(redisConnectionFactory); 55 | return template; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/config/redis/serializer/FastJsonRedisSerializer.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.config.redis.serializer; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.serializer.SerializerFeature; 5 | import org.springframework.data.redis.serializer.RedisSerializer; 6 | import org.springframework.data.redis.serializer.SerializationException; 7 | 8 | import java.nio.charset.Charset; 9 | 10 | public class FastJsonRedisSerializer implements RedisSerializer { 11 | 12 | private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 13 | private Class clazz; 14 | 15 | public FastJsonRedisSerializer(Class clazz) { 16 | super(); 17 | this.clazz = clazz; 18 | } 19 | 20 | @Override 21 | public byte[] serialize(T t) throws SerializationException { 22 | if (null == t) { 23 | return new byte[0]; 24 | } 25 | return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); 26 | } 27 | 28 | @Override 29 | public T deserialize(byte[] bytes) throws SerializationException { 30 | if (null == bytes || bytes.length <= 0) { 31 | return null; 32 | } 33 | String str = new String(bytes, DEFAULT_CHARSET); 34 | return (T) JSON.parseObject(str, clazz); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/config/transaction/TransactionConfig.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.config.transaction; 2 | 3 | import com.codingapi.txlcn.tc.config.EnableDistributedTransaction; 4 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | @EnableDiscoveryClient 9 | @EnableDistributedTransaction 10 | public class TransactionConfig { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/elasticsearch/document/ProductSearch.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.elasticsearch.document; 2 | 3 | import com.d2c.product.business.model.Product; 4 | import lombok.Data; 5 | import lombok.NonNull; 6 | import org.springframework.beans.BeanUtils; 7 | import org.springframework.data.elasticsearch.annotations.Document; 8 | import org.springframework.data.elasticsearch.annotations.Field; 9 | import org.springframework.data.elasticsearch.annotations.FieldType; 10 | 11 | import java.io.Serializable; 12 | import java.math.BigDecimal; 13 | 14 | @Data 15 | @Document(indexName = "d2cmall-index", type = "product") 16 | public class ProductSearch implements Serializable { 17 | 18 | Long id; 19 | @NonNull 20 | @Field(type = FieldType.Keyword) 21 | String sn; 22 | BigDecimal price; 23 | 24 | public ProductSearch() { 25 | } 26 | 27 | public ProductSearch(Product product) { 28 | this(); 29 | BeanUtils.copyProperties(product, this); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/elasticsearch/repository/ProductSearchRepository.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.elasticsearch.repository; 2 | 3 | import com.d2c.product.elasticsearch.document.ProductSearch; 4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface ProductSearchRepository extends ElasticsearchRepository { 9 | 10 | List findBySn(String sn); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/mongodb/document/ProductMongo.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.mongodb.document; 2 | 3 | import com.d2c.product.business.model.Product; 4 | import lombok.Data; 5 | import lombok.NonNull; 6 | import org.springframework.beans.BeanUtils; 7 | import org.springframework.data.mongodb.core.mapping.Document; 8 | 9 | import java.math.BigDecimal; 10 | 11 | @Data 12 | @Document(collection = "user") 13 | public class ProductMongo { 14 | 15 | Long id; 16 | @NonNull 17 | String sn; 18 | BigDecimal price; 19 | 20 | public ProductMongo() { 21 | } 22 | 23 | public ProductMongo(Product product) { 24 | this(); 25 | BeanUtils.copyProperties(product, this); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /service-product/src/main/java/com/d2c/product/mongodb/repository/ProductMongoRepository.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product.mongodb.repository; 2 | 3 | import com.d2c.product.mongodb.document.ProductMongo; 4 | import org.springframework.data.mongodb.repository.MongoRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface ProductMongoRepository extends MongoRepository { 9 | 10 | List findBySn(String sn); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /service-product/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # tomcat 2 | server: 3 | port: 8003 4 | 5 | # eureka 6 | eureka: 7 | instance: 8 | lease-expiration-duration-in-seconds: 30 9 | lease-renewal-interval-in-seconds: 10 10 | client: 11 | service-url: 12 | defaultZone: http://192.168.0.146:1001/eureka/ 13 | 14 | # actuator 15 | management: 16 | endpoints: 17 | web: 18 | exposure: 19 | include: "*" 20 | 21 | # tx-lcn 22 | tx-lcn: 23 | client: 24 | manager-address: 192.168.0.146:8070 25 | resource-order: 0 26 | logger: 27 | enabled: false 28 | message: 29 | netty: 30 | wait-time: 5000 31 | springcloud: 32 | loadbalance: 33 | enabled: true 34 | 35 | # spring 36 | spring: 37 | application: 38 | name: service-product 39 | 40 | # database 41 | datasource: 42 | url: jdbc:mysql://192.168.0.146:3306/mall?useUnicode=true&characterEncoding=utf-8&useSSL=false 43 | username: root 44 | password: 123456 45 | type: com.alibaba.druid.pool.DruidDataSource 46 | driverClassName: com.mysql.jdbc.Driver 47 | 48 | # redis 49 | redis: 50 | database: 0 51 | host: 192.168.0.146 52 | port: 6379 53 | jedis: 54 | pool: 55 | max-active: 1000 56 | max-idle: 100 57 | min-idle: 1 58 | 59 | data: 60 | # mongodb 61 | mongodb: 62 | uri: mongodb://192.168.0.146:27017/mall 63 | 64 | # elasticsearch 65 | elasticsearch: 66 | cluster-name: d2cmall-es 67 | cluster-nodes: 192.168.0.146:9300 68 | 69 | # rabbitmq 70 | rabbitmq: 71 | host: 192.168.0.146 72 | port: 5672 73 | username: guest 74 | password: guest 75 | 76 | # mybatis-plus 77 | mybatis-plus: 78 | mapper-locations: classpath:/mapper/*.xml 79 | typeAliasesPackage: com.d2c.*.*.model 80 | global-config: 81 | db-config: 82 | id-type: id_worker 83 | field-strategy: not_null 84 | logic-delete-value: 1 85 | logic-not-delete-value: 0 86 | sql-parser-cache: true 87 | configuration: 88 | auto-mapping-behavior: partial 89 | map-underscore-to-camel-case: true 90 | cache-enabled: false 91 | 92 | 93 | ######################################################### cluster ###################################################### 94 | 95 | # # redis 96 | # redis: 97 | # database: 0 98 | # jedis: 99 | # pool: 100 | # max-active: 8 101 | # max-idle: 8 102 | # min-idle: 0 103 | # cluster: 104 | # nodes: 105 | # - 192.168.0.143:7001 106 | # - 192.168.0.143:7002 107 | # - 192.168.0.143:7003 108 | # - 192.168.0.143:7004 109 | # - 192.168.0.143:7005 110 | # - 192.168.0.143:7006 111 | 112 | # data: 113 | # # mongodb 114 | # mongodb: 115 | # uri: mongodb://192.168.0.143:27017,192.168.0.144:27017,192.168.0.145:27017/shop 116 | 117 | # # elasticsearch 118 | # elasticsearch: 119 | # cluster-name: d2cmall-es 120 | # cluster-nodes: 192.168.0.143:9300,192.168.0.144:9300,192.168.0.145:9300 121 | 122 | -------------------------------------------------------------------------------- /service-product/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: service-product 4 | # config 5 | cloud: 6 | config: 7 | uri: http://192.168.0.146:2001 8 | profile: dev 9 | label: master -------------------------------------------------------------------------------- /service-product/src/main/resources/mapper/ProductMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 16 | 17 | 18 | update p_product 19 | set price = #{price} 20 | where id = #{id} 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /service-product/src/test/java/com/d2c/product/MallProductApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.d2c.product; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class MallProductApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /txlcn-tm-5.0.2.RELEASE.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/D2C-Cai/mall/b90fdf13954384abe2971c01ff5ca21f06bc620b/txlcn-tm-5.0.2.RELEASE.jar --------------------------------------------------------------------------------