订单微服务的主要作用是从商品微服务中获取与订单相关的商品条目信息,进而完成对于订单数据的请求操作。
由于这里采用的是分布式的微服务架构,因而订单微服务中的商品条目信息是从两个商品微服务中以某种规则进行访问的,而这里,我们采用的是使用订单微服务以随机的方式访问不同的商品微服务。
springcloud-goods-orderOrderController源码:
package com.lyc.controller;import com.lyc.order.entity.Order;
import com.lyc.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class OrderController {@Autowiredprivate OrderService orderService;@GetMapping("order/{orderId}")public Order queryOrderById(@PathVariable("orderId") String orderId){return this.orderService.queryOrderById(orderId);}}
ItemFeignClient源码:
package com.lyc.feign;import com.lyc.item.entity.Item;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient(value = "springcloud-goods-item") //声明这是一个Feign的客户端
public interface ItemFeignClient {@GetMapping("/item/{id}")public Item queryItemById(@PathVariable("id") Long id);}
OrderProperties源码:
package com.lyc.properties;import com.lyc.order.entity.ItemProperties;
import lombok.*;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Component
@ConfigurationProperties(prefix = "springcloud-goods") //以springcloud-goods开头的配置被匹配到
public class OrderProperties {private ItemProperties item = new ItemProperties();}
ItemService源码:
package com.lyc.service;import com.lyc.feign.ItemFeignClient;
import com.lyc.item.entity.Item;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class ItemService {@Autowiredprivate ItemFeignClient itemFeignClient;/*** 调用商品的务提供的接口进行查询数据* @param id* @return*/@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod") //进行容错处理public Item queryItemById(Long id){return this.itemFeignClient.queryItemById(id);}public Item queryItemByIdFallbackMethod(Long id){ //请求失败执行的方法return new Item(id,"查询商品信息出错!",null,null,null);}}
OrderService源码:
package com.lyc.service;import com.lyc.item.entity.Item;
import com.lyc.order.dao.OrderDao;
import com.lyc.order.entity.Order;
import com.lyc.order.entity.OrderDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.*;@Service
public class OrderService {&#64;Autowiredprivate ItemService itemService;&#64;Autowiredprivate OrderDao orderDao;public Order queryOrderById(String orderId){Order order &#61; orderDao.queryOrderById(orderId);if(null &#61;&#61; order){return null;}List<OrderDetail> orderDetails &#61; order.getOrderDetails();for(OrderDetail orderDetail : orderDetails){//通过商品微服务查询商品数据Item item &#61; this.itemService.queryItemById(orderDetail.getItem().getId());if(null &#61;&#61; item){continue;}orderDetail.setItem(item);}return order;}
}
OrderApplication源码&#xff1a;
package com.lyc;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;&#64;EnableHystrix
&#64;EnableFeignClients
&#64;EnableEurekaServer //申明这是一个Eureka服务
&#64;SpringBootApplication
public class OrderApplication {&#64;Bean //向Spring微服务中定义RestTemplate对象&#64;LoadBalanced //开启负载均衡public RestTemplate restTemplate(){return new RestTemplate(new OkHttp3ClientHttpRequestFactory());}public static void main(String[] args){SpringApplication.run(OrderApplication.class,args);}}
application.yml源码&#xff1a;
server:port: 8082 #订单端口spring:application:name: springcloud-goods-order #指定服务名springcloud-goods:item:url: http://127.0.0.1:8081/item/eureka:client:registerWithEureka: false #是否将自己注册到Eureka服务中&#xff0c;默认为truefetchRegistry: true #是否从Eureka中获取注册信息&#xff0c;默认为trueserviceUrl: #Eureka客户端与Eureka服务端进行交互的地址defaultZone: http://root:root123&#64;127.0.0.1:6868/eureka/springcloud-goods-item: # 设置成随机访问ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
ItemServiceTest源码&#xff1a;
package com.lyc.service;import com.lyc.OrderApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;&#64;RunWith(SpringJUnit4ClassRunner.class)
&#64;SpringBootTest
&#64;Import(OrderApplication.class)
public class ItemServiceTest {&#64;Autowiredprivate LoadBalancerClient loadBalancerClient;&#64;Testpublic void test(){String serviceId &#61; "springcloud-goods-item";for (int i &#61; 0; i < 100; i&#43;&#43;){ServiceInstance serviceInstance &#61; this.loadBalancerClient.choose(serviceId);System.out.println("第" &#43; (i &#43; 1) &#43; "次&#xff1a;" &#43; serviceInstance.getHost() &#43; ": " &#43; serviceInstance.getPort());}}
}
pom.xml源码&#xff1a;
结果分析
启动项目&#xff0c;在浏览器中输入下面的地址访问订单微服务&#xff1a;
http://127.0.0.1:8082/order/13135351635
其显示的结果如下&#xff1a;
{"orderId": "13135351635","userId": 1,"createDate": 1544665690703,"updateDate": 1544665690703,"orderDetails": [{"orderId": "13135351635","item": {"id": 1,"title": "商品标题1","pic": "http://图片1","desc": "商品描述1","price": 1000}},{"orderId": "13135351635","item": {"id": 2,"title": "商品标题2","pic": "http://图片2","desc": "商品描述2","price": 2000}}]
}
当我们重复刷新上面的访问地址时&#xff0c;我们可以看到&#xff0c;在商品微服务springcloud-goods-item的控制台中输出下面的信息&#xff1a;
2018-12-13 09:48:31.826 INFO 7876 --- [nio-8081-exec-4] com.lyc.controller.ItemController : ----------springcloud-goods-item中的方法----------
2018-12-13 09:48:43.632 INFO 7876 --- [nio-8081-exec-5] com.lyc.controller.ItemController : ----------springcloud-goods-item中的方法----------
2018-12-13 09:48:45.164 INFO 7876 --- [nio-8081-exec-6] com.lyc.controller.ItemController : ----------springcloud-goods-item中的方法----------
2018-12-13 09:48:45.621 INFO 7876 --- [nio-8081-exec-7] com.lyc.controller.ItemController : ----------springcloud-goods-item中的方法----------
2018-12-13 09:48:45.626 INFO 7876 --- [nio-8081-exec-8] com.lyc.controller.ItemController : ----------springcloud-goods-item中的方法----------
2018-12-13 09:48:46.077 INFO 7876 --- [nio-8081-exec-9] com.lyc.controller.ItemController : ----------springcloud-goods-item中的方法----------
2018-12-13 09:48:47.390 INFO 7876 --- [a-EvictionTimer]
同时&#xff0c;我们在商品微服务springcloud-goods-item2的控制台中也可以看到类似的信息&#xff1a;
2018-12-13 09:48:43.747 INFO 25508 --- [nio-8083-exec-2] com.lyc.controller.ItemController : ----------springcloud-goods-item2中的方法----------
2018-12-13 09:48:44.527 INFO 25508 --- [nio-8083-exec-1] com.lyc.controller.ItemController : ----------springcloud-goods-item2中的方法----------
2018-12-13 09:48:44.534 INFO 25508 --- [nio-8083-exec-3] com.lyc.controller.ItemController : ----------springcloud-goods-item2中的方法----------
2018-12-13 09:48:45.157 INFO 25508 --- [nio-8083-exec-4] com.lyc.controller.ItemController : ----------springcloud-goods-item2中的方法----------
2018-12-13 09:48:46.072 INFO 25508 --- [nio-8083-exec-5] com.lyc.controller.ItemController : ----------springcloud-goods-item2中的方法----------
这说明&#xff0c;订单微服务springcloud-goods-order是以随机的方式在访问商品微服务springcloud-goods-item与商品微服务springcloud-goods-item2的。