分布式系统开发---订单服务分离SpringCloud(四)
订单服务
的分离其实跟商品服务
的分离差不多,但是为什么要进行单独的分析呢?因为之前在同一个服务器中,订单服务
和商品服务
都是可以接触到本服务器的数据的,但是,分离之后,商品服务
中的商品信息数据将不再能被订单服务
直接获取到,所以,当用户请求订单信息的时候,订单服务
要自己先去商品服务
中请求商品信息,然后把订单信息拼接上商品信息一并返回给用户。
好了,有了思路,那么下面我们按照这个思路对我们的项目进行改造。
首先,与商品服务
分离类似,我们把mall/src/main/java/com/felix
中的三个包拷贝粘贴到order
模块下的felix
包内,然后把三个包内和订单无关的内容全部删除(注意,这里不要删除Goods
模型,因为从商品服务
中请求回来的商品信息最终还要使用Goods
模型进行包装),最终只保留Goods
、Order
、OrderDetails
、OrderService
、GoodsService
、OrderController
,如图所示
接下来,我们模拟这种情况,在
订单服务
中,是没有商品信息的,所以,我们的GoodsService
中就不能也不允许有商品的数据了,所以,我们改造GoodsService
成如下代码
package com.felix.service;
import com.felix.model.Goods;
import org.springframework.stereotype.Service;
/**
* Created by weistekweistek on 2019/1/3.
*/
@Service
public class GoodsService {
public Goods findGoodsById(Long id){
return null;
}
}
这里的返回值我们暂时写成空值,后面我们再修改它为从商品服务
的服务器中获取商品信息并返回。
既然GoodsService
中已经没有了商品信息,那么响应的OrderService
中在初始化构造的假数据就不能再次使用了,我们直接在假数据中新建一个没有意义的商品数据(可以设置商品id,因为正常业务中订单信息中本身就可保存了商品id,只是没有商品的详细信息)。
package com.felix.service;
import com.felix.model.Goods;
import com.felix.model.Order;
import com.felix.model.OrderDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* Created by weistekweistek on 2019/1/3.
*/
@Service
public class OrderService {
@Autowired
private GoodsService goodsService;
private static final Map<Long,Order> order_map = new HashMap<Long,Order>();
static {
List<OrderDetails> orderDetailsList = new ArrayList<OrderDetails>();
for (Long i = 1L;i <= 10L;i++){
Goods goods = new Goods();
goods.setGoodsid(i);
orderDetailsList.add(new OrderDetails(i ,i,goods,5));
order_map.put(i,new Order(i,i,new Date(),new Date(),new ArrayList<OrderDetails>(orderDetailsList)));
System.out.println(order_map);
}
}
public Order findOrderById(Long id){
Order order = order_map.get(id);
for (OrderDetails orderDetails : order.getOrderDetailsList()){
Goods goods = goodsService.findGoodsById(orderDetails.getGoods().getGoodsid());
orderDetails.setGoods(goods);
}
return order;
}
}
上面代码中我们直接做了假的订单信息,并且添加了响应的商品id进去,也就是模拟了正常的订单信息,那么,GoodsDetails
中的goods
现在只有id,并没有其他的信息,如何使用id获取商品服务
服务器上面的商品信息呢?还记得刚才改造的GoodsService
吗,它可以帮助我们去获取商品信息,至于怎么获取,那是它的事情,我们只需要在OrderService
中使用GoodsService
去写就行了,所以,在查询订单的时候,我们先查看订单中有多少商品,然后使用商品id去查找商品就行了(记得要注入GoodsService
),也就是上面的
for (OrderDetails orderDetails : order.getOrderDetailsList()){
Goods goods = goodsService.findGoodsById(orderDetails.getGoods().getGoodsid());
orderDetails.setGoods(goods);
}
现在回到了订单服务
需要从商品服务
中获取商品信息的阶段,怎么实现呢,我们对order
模块中的GoodsService
做如下改造:
package com.felix.service;
import com.felix.model.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
/**
* Created by weistekweistek on 2019/1/3.
*/
@Service
public class GoodsService {
@Autowired
private RestTemplate restTemplate;
public Goods findGoodsById(Long id){
String url = "http://127.0.0.1:8000/goods/"+ id;
return restTemplate.getForObject(url,Goods.class);
}
}
在这段代码里面,我们注入了RestTemplate
,它帮助我们从指定的接口中请求数据,并且生成一个商品对象并返回。当然,我们需要在OrderApplication
中定义restTemplate
,下面是OrderApplication
改造后的代码
package com.felix;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class OrderApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
这样是否就可以了呢?不用怀疑,可以了!下面,我们分别启动商品服务GoodsApplication
、订单服务OrderApplication
,然后访问商品服务
的接口http://127.0.0.1:8000/goods/8
商品服务
正常,接下来访问订单服务
的接口http://127.0.0.1:8001/order/2
可见,
订单服务
已经可以正常的从商品服务
的服务器中取出数据并拼接成订单数据返回给用户了,为了验证订单服务
确实从商品服务
中自动进行了网络请求,我们在商品服务
中的GoodsController
打印日志来查看
@RequestMapping(value = "/{id}")
public Goods findGoodsById(@PathVariable("id") Long id){
System.out.println("收到商品信息请求");
return goodsService.findGoodsById(id);
}
然后重新启动商品服务
的服务器,再次请求订单服务
的接口http://127.0.0.1:8001/order/3
分别查看返回的JSON数据和log信息
切换到
商品服务
服务器查看log信息和我们想象的一样,我们只是访问了
订单服务
的接口,订单服务
自动为我们请求了商品服务
中的商品信息。
至此,我们完成了
订单服务
的分离,成功的将传统服务器中的多个服务拆分到了不同的服务器中。那么有个问题,每次进行商品信息请求的时候,难道我都要在订单服务
中修改商品服务
的地址吗,这样岂不是还是比较麻烦?是的,确实很麻烦,所以,下篇我们将使用SpringCloud中的Eureka
的服务注册和发现来解决我们的问题。
分布式系统开发---高可用业务服务器SpringCloud(五)
以上内容转载请注明出处,同时也请大家不吝你的关注和下面的赞赏
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓