1.订单模块业务分析
- 全端页面数据校验
- 获取商品信息,调用订单模块API
- 计算总价
- 扣库存,调用订单模块API
- 入库
2.线程通信和负载均衡
- 线程通信
@RestController
@Slf4j
public class ClientController {
//SpringCloud内置对象,用来获取其他项目的URl,POST,地址信息
//@Autowired
//private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/getProductMsg")
public String getProductMessage() {
//1.获取服务端信息 缺点
// a.地址写死 部署的时候不知对方地址
// b.假如有多个服务,不能获取想要的服务
//RestTemplate restTemplate = new RestTemplate();
//String response=restTemplate.getForObject("http://localhost:8080/msg",String.class);
//log.info(response);
//2.获取服务端信息 利用loadBalancerClient获取用户名和端口
//ServiceInstance serviceInstance = loadBalancerClient.choose("product"); //获取对应项目的名称
//String url = String.format("http://%s:%s", serviceInstance.getHost(), serviceInstance.getPort())+"/msg";
//String response=restTemplate.getForObject("http://localhost:8080/msg",String.class);
//log.info("response={}",response);
//3.详情见RestTemplateConfig
//因为此处的项目端口的可能有多个,需要考虑负载均衡策略
String response = restTemplate.getForObject("http://product/msg", String.class);
log.info("response={}",response);
return response;
}
}
配置
@Component
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 负载均衡
负载均衡分为服务端和客户端负载均衡
SpringCloud的负载均衡是Ribbon组件:restful风格
4. 服务调用 注意事项
一、问题描述
由于项目是前后端分离,因此后台使用的是spring boot,做成微服务,只暴露接口。接口设计风格为restful的风格,在get请求下,后台接收参数的注解为RequestBody时会报错;在post请求下,后台接收参数的注解为RequestParam时也会报错。
二、问题原因
由于spring的RequestParam注解接收的参数是来自于requestHeader中,即请求头,也就是在url中,格式为xxx?username=123&password=456,而RequestBody注解接收的参数则是来自于requestBody中,即请求体中。
三、解决方法
因此综上所述,如果为get请求时,后台接收参数的注解应该为RequestParam,如果为post请求时,则后台接收参数的注解就是为RequestBody。附上两个例子,截图如下:
调用服务代码
1.服务端
/**
*@Author XuWeiZhi
*@Description 用于扣库存
*@Date 2018/10/8 22:52
**/
@PostMapping("/decreaseStock")
public void decreaseStock(@RequestBody List<CartDTO> cartDTOList){
productService.decreaseStock(cartDTOList);
};
2.客户端
@FeignClient(name = "product")
@RequestMapping("/product")
public interface ProductClient {
//对应项目的路径地址
@GetMapping("/msg")
String productMsg();
//调用项目资源
@PostMapping("/listForOrder")
public List<ProductInfo> listForOrder(List<String> productIdList);
//扣库存
@PostMapping("/decreaseStock")
public void decreaseStock(List<CartDTO> cartDTOList);
}```
3.调用
```java
@RestController
@Slf4j
public class ClientController {
//SpringCloud内置对象,用来获取其他项目的URl,POST,地址信息
//@Autowired
//private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@Autowired
private ProductClient productClient;
@GetMapping("/getProductMsg")
public String getProductMessage() {
//1.获取服务端信息 缺点
// a.地址写死 部署的时候不知对方地址
// b.假如有多个服务,不能获取想要的服务
//RestTemplate restTemplate = new RestTemplate();
//String response=restTemplate.getForObject("http://localhost:8080/msg",String.class);
//log.info(response);
//2.获取服务端信息 利用loadBalancerClient获取用户名和端口
//RestTemplate restTemplate = new RestTemplate();
//ServiceInstance serviceInstance = loadBalancerClient.choose("product"); //获取对应项目的名称
//String url = String.format("http://%s:%s", serviceInstance.getHost(), serviceInstance.getPort())+"/msg";
//String response=restTemplate.getForObject("http://localhost:8080/msg",String.class);
//log.info("response={}",response);
//3.详情见RestTemplateConfig 本质上和第二种方式相同
//因为此处的项目端口的可能有多个,需要考虑负载均衡策略
//默认使用轮询的方式 改动负载均衡策略那啥自己想办法
String response = restTemplate.getForObject("http://PRODUCT/product/msg", String.class);
log.info("response={}", response);
return response;
}
@GetMapping("/getFeign")
public String getFeignMehtohd() {
String response = productClient.productMsg();
log.info("response={}", response);
return response;
}
@GetMapping("/getOrderList")
public String getOrderTest() {
List<ProductInfo> list = productClient.listForOrder(Arrays.asList("157875196366160022"));
log.info("response={}", list);
return list.toString();
}
@GetMapping("/decrease")
public String decrease() {
productClient.decreaseStock(Arrays.asList(new CartDTO("157875196366160022", 211)));
return "xxxx";
}
}```