微服务架构的6中设计模式
1.代理设计模式
2.聚合设计模式
3.链条设计模式
4.聚合链条设计模式
5.数据共享设计模式
6.异步消息设计模式
微服务设计模式实战
代理链条模式实战
1.Product服务
这个product服务是根据前面的一篇文章声明式服务调用中的product改造的。在之前中我们没有加入数据库连接,而现在我们加入了数据库连接。
product的api结构目录:
Product中是实体类,这里就不贴代码了。
注意的是实体类可以是根据逆向工程生成的。大多数都是使用的逆向工程。
ProductFacade中的代码:
@RequestMapping("product")
public interface ProductFacade {
@RequestMapping(value="findAllProduct",method=RequestMethod.GET)
public List<Product> findAllProduct();
//无参
@RequestMapping(value="list",method=RequestMethod.GET)
public List<Product> listProduct();
//一个参数
@RequestMapping(value="get",method=RequestMethod.GET)
public Product getProduct(@RequestParam("id") Integer id);
//------------------------多参数----------------------
@RequestMapping(value="get1",method=RequestMethod.GET,consumes=MediaType.APPLICATION_JSON_VALUE)
public Product getProduct1(Product obj);
@RequestMapping(value="get2",method=RequestMethod.GET)
public Product getProduct2(@RequestParam("id") Integer id,@RequestParam("name") String name);
//------------------------POST-------------------------
@RequestMapping(value="add",method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
public Product addProduct(@RequestBody Product obj);
}
这个主要就是写的接口。
然后pom也没有什么需要添加的。
product中core的目录结构:
pom中的依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>e-book-product-api</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
配置文件:
spring.application.name=e-book-product
#配置自定义端口
server.port=8084
#指定一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:test@eureka2:8762/eureka/,http://user:test@eureka1:8761/eureka/
#默认是hostname 注册,改成IP 注册
eureka.instance.perferIpAddress=true
#--------------db----------------
mybatis.type-aliases-package=com.me.book.product.domain
mybatis.mapper-locations=classpath:mybatis/com/me/book/product/*.xml
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/book-product?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=123
注意这里的端口,项目名称,数据库名称密码,包名都是你自己设置的,还有指向注册中心都是不同的,你可以自己设置。主要总结可以就是配置了名称,端口号,指向注册中心,添加数据库的连接。
引入xml:
这个可以根据逆向工程直接生成,也可以你自己写。
ProductApplication代码:
@EnableEurekaClient
@SpringBootApplication
@MapperScan("com.me.book.product.persistence")
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
ProductFacadeImpl代码:
@RestController
public class ProductFacadeImpl implements ProductFacade{
@Autowired
private ProductService productService;
public List<Product> findAllProduct() {
return this.productService.findAllProduct();
}
@RequestMapping(value="list",method=RequestMethod.GET)
public List<Product> listProduct(){
return this.productService.findAllProduct();
}
@Override
public Product getProduct(Integer id) {
return this.productService.getProduct(id);
}
@Override
public Product getProduct1(@RequestBody Product obj) {
return obj;
}
@Override
public Product getProduct2(Integer id, String name) {
return new Product(id,name);
}
@Override
public Product addProduct(@RequestBody Product obj) {
return obj;
}
}
这个类继承了api中的接口。
productMapper代码:
public interface productMapper {
int deleteByPrimaryKey(Integer id);
int insert(Product record);
int insertSelective(Product record);
Product selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(Product record);
int updateByPrimaryKeyWithBLOBs(Product record);
int updateByPrimaryKey(Product record);
public List<Product> findAllProduct();
}
这个可以自己写,也可以用逆向工程生成过后粘贴过来。
ProductService中的代码:
@Service
public class ProductService {
@Autowired
private productMapper productMapper;
public List<Product> findAllProduct() {
return this.productMapper.findAllProduct();
}
public List<Product> listProduct(){
return this.productMapper.findAllProduct();
}
public Product getProduct(Integer id) {
return this.productMapper.selectByPrimaryKey(id);
}
}
这个就是实现业务逻辑的层。
以上就是product服务。然后还有user服务,order订单服务,trade交易服务。由于代码过长不能一一贴在上面,所以如果想要源码的小伙伴可以加我的qq997355706。原理和product差不多,只是借口实现的功能不一样而已。
最后,还有consumer代理服务。
目录结构:
pom中依赖:
<dependencies>
<dependency>
<groupId>com.me.springcloud</groupId>
<artifactId>e-book-user-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.me.springcloud</groupId>
<artifactId>e-book-product-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.me.springcloud</groupId>
<artifactId>e-book-order-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.me.springcloud</groupId>
<artifactId>e-book-trade-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
配置文件代码:
spring.application.name=e-book-consumer-order
server.port=8090
eureka.client.serviceUrl.defaultZone=http://user:test@eureka2:8762/eureka/,http://user:test@eureka1:8761/eureka/
ConsumerOrderApplication代码:
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerOrderApplication {
@Bean
public Logger.Level feignLoggerLevel() {
return feign.Logger.Level.FULL;
}
public static void main(String[] args) {
SpringApplication.run(ConsumerOrderApplication.class, args);
}
}
OrderController代码:
@RestController
public class OrderController {
@Autowired
private UserService userService;
@Autowired
private ProductService productService;
@Autowired
private OrderService orderService;
@Autowired
private TradeService tradeService;
/**
* 模拟内容: 登录 查看产品 下订单
*
* 1.测试登录 账号 admin admin
* 2.查看所有产品列表
* 3.选第一款产品,下订单
* 4.实现订单交易支付
* 5.查看所有的订单信息
*
* @throws ParseException
*/
@RequestMapping(value = "/createOrder", method = RequestMethod.GET)
public List<Order> createOrder() {
// 1.测试登录 账号 admin admin
Integer userid = this.login();
// 2.查看所有产品列表
List<Product> products = this.productService.findAllProduct();
// 3.选第一款产品,下订单
Product product = products.get(0);
Order order = new Order();
order.setUserId(userid);
order.setProductId(product.getId());
order.setPrice(product.getPrice());
Integer orderid=this.orderService.createOrder(order);
// System.out.println(order.getId()+"------------------------------------------------");
// return null;
// 4.实现订单交易支付
Trade trade = new Trade();
trade.setUserId(order.getUserId());
trade.setOrderId(orderid);
trade.setPrice(order.getPrice());
trade.setPayType((byte)1);// 支付类型:1-支付宝支付,2-网银在线,3-银联,4-微信支付
trade.setPayStatus((byte)4);// 1 未付款 2 付款中 3 付款失败 4 付款完成
trade.setGatewayPayNum(String.valueOf((new Date()).getTime()));// 网关支付流水号取当前时间
trade.setGatewayPayPrice(order.getPrice());
trade.setGatewayPayTime(new Date());
this.tradeService.createTrade(trade);
// 5.查看所有的订单信息
List<Order> orders = this.orderService.findOrderByUserId(userid);
return orders;
}
private Integer login() {
String userName = "admin";
String password = "admin";
Integer id = this.userService.login(userName, password);
if (id != null) {
System.out.println("登录成功 id=" + id);
} else {
System.out.println("登录失败");
}
return id;
}
}
controller中代码主要模拟了一个用户登录,查看产品列表,选中,下单实现交易和查看所有订单信息的过程。其中订单和交易就是链条模式。
OrderService代码:
@FeignClient(name="e-book-order")
public interface OrderService extends OrderFacade{
}
ProductService代码:
@FeignClient(name="e-book-product")
public interface ProductService extends ProductFacade{
}
TradeService代码:
@FeignClient(name="e-book-trade")
public interface TradeService extends TradeFacade{
}
UserService代码:
@FeignClient(name="e-book-user")
public interface UserService extends UserFacade{
}
以上用到的就是声明式服务的功能,如果不清楚的可以看我写的另外一篇博客声明式服务这样我们的代理服务就可以用product,user,order,trade的服务了。
测试
启动完项目在eureka中查看:
测试controller写的代码:
显示成功!如果有小伙伴想要源码可以加我的qq997355706。
分享一下我自己遇到的坑,配置文件中注意包名,数据库等设置的问题,还有xml中包名等问题。