在正式搭建 Gateway 服务之前,我们先搭建两个微服务,分别是:订单微服务、用户微服务,调用关系如下图:
上图中,用户发送请求获取订单信息,然后订单又调用用户服务获取订单的用户信息,然后将订单和用户信息统一返回给用户。
创建 cloud_order 数据库,执行如下 SQL:
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for t_order -- ---------------------------- DROP TABLE IF EXISTS `t_order`; CREATE TABLE `t_order` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单ID', `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '订单标题', `num` int(11) NULL DEFAULT NULL COMMENT '商品数量', `price` decimal(10, 2) NULL DEFAULT NULL COMMENT '订单总价格', `user_id` int(11) NOT NULL COMMENT '用户ID', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of t_order -- ---------------------------- INSERT INTO `t_order` VALUES (1, '海尔冰箱335升 法式多门四开门冰箱 一级能效 风冷无霜 双变频省电 节能净味 家用大容量超薄变温 多门推荐 BCD-335WLHFD9DS9', 1, 2598.00, 1); INSERT INTO `t_order` VALUES (2, '施耐德(Schneider)开关插座面板错位开关五孔插座10a86型二三插皓呈薄雾灰全屋套餐 斜五孔插座10A十只装', 1, 313.38, 1); INSERT INTO `t_order` VALUES (3, 'JRINKTEEA日本品牌高档焖茶杯保温杯闷泡杯陶瓷喷陶纯钛茶隔办公车载保暖杯 Toyama冰裂银480ml(陶瓷喷陶)', 2, 316.00, 2); INSERT INTO `t_order` VALUES (4, '倍哆氛 【同价双11】无线蓝牙耳机空气传导不入耳挂耳式超长续航运动跑步游戏音乐苹果华为oppo手机通用 黑色 全新蓝牙5.2 听歌12小时', 1, 59.90, 3); INSERT INTO `t_order` VALUES (5, '坚果(JMGO)N1 Ultra 4K超高清白天三色激光云台投影 投影仪家用投墙卧室家庭影院 游戏投影 240HZ高刷', 1, 8799.00, 4); SET FOREIGN_KEY_CHECKS = 1;
运行 SQL 后,数据库只存在 t_order 数据表,如下图:
数据表内容如下:
项目依赖如下,从父项目继承依赖:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.hxstrive.springcloud</groupId> <artifactId>springcloud_learn</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>service_order</artifactId> <name>service_order</name> <description>service_order</description> <dependencies> <!-- 从父项目继承版本信息 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
下面 bootstrap.yml 配置文件内容(注意配置文件名称):
server: port: 8081 spring: application: name: service-order # datasource datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/cloud_order?useUnicode=true&characterEncoding=utf-8 username: root password: aaaaaa cloud: # nacos 配置 nacos: # nacos 服务发现 discovery: server-addr: localhost:8848 username: nacos password: nacos # nacos 服务配置 config: server-addr: localhost:8848 username: nacos password: nacos refresh-enabled: true file-extension: yaml group: DEFAULT_GROUP logging: level: root: warn
package com.hxstrive.springcloud.order.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; /** * 配置类 * @author hxstrive.com */ @Configuration public class AppConfig { @LoadBalanced // 开启负载均衡 @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
package com.hxstrive.springcloud.order.entity; /** * 订单实体 * @author hxstrive.com */ public class OrderEntity { /** 订单ID */ private int id; /** 标题 */ private String title; /** 数量 */ private int num; /** 价格 */ private float price; /** 用户ID */ private int userId; /** 订单所属用户信息 */ private UserEntity user; // getter 和 setter }
package com.hxstrive.springcloud.order.entity; /** * 用户实体 * @author hxstrive.com */ public class UserEntity { /** 用户ID */ private int id; /** 姓名 */ private String name; /** 年龄 */ private int age; /** 电子邮件地址 */ private String email; // getter 和 setter }
package com.hxstrive.springcloud.order.mapper; import com.hxstrive.springcloud.order.entity.OrderEntity; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; /** * 订单 Mapper * @author hxstrive.com */ @Mapper public interface OrderMapper { /** 获取指定订单信息 */ @Select("select * from t_order where id=#{orderId}") @Results({ @Result(column = "id", property = "id"), @Result(column = "title", property = "title"), @Result(column = "num", property = "num"), @Result(column = "price", property = "price"), @Result(column = "user_id", property = "userId") }) OrderEntity getOrder(int orderId); }
package com.hxstrive.springcloud.order.service; import com.hxstrive.springcloud.order.entity.OrderEntity; import com.hxstrive.springcloud.order.entity.UserEntity; import com.hxstrive.springcloud.order.mapper.OrderMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; /** * 订单服务 * @author hxstrive.com */ @Service public class OrderService { @Autowired private OrderMapper orderMapper; @Autowired private RestTemplate restTemplate; public OrderEntity getOrder(int orderId) { // 1.查询订单信息 OrderEntity order = orderMapper.getOrder(orderId); if(null == order) { return null; } // 2.根据订单中的用户id,调用用户服务查询用户信息 // 问题: // (1)如果用户服务部署了多个,我们该怎么调用? // (2)如果用户服务地址变动了,我们是不是每次都要来修改改地址,非常麻烦! // (3)如果调用用户服务的地址参数较多,拼接 URL 地址同样非常麻烦! String url = "http://service-user/user/" + order.getUserId(); UserEntity user = restTemplate.getForObject(url, UserEntity.class); order.setUser(user); // 3.返回订单对象 return order; } }
package com.hxstrive.springcloud.order.controller; import com.hxstrive.springcloud.order.entity.OrderEntity; import com.hxstrive.springcloud.order.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.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 订单 Controller * @author hxstrive.com */ @RestController @RequestMapping("/order") public class OrderController { @Autowired private OrderService orderService; @GetMapping("/{id}") public OrderEntity getOrder(@PathVariable("id") int id) { System.out.println("## OrderController.getOrder() id=" + id); return orderService.getOrder(id); } }
package com.hxstrive.springcloud.order; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } }
到这里订单服务编写完成,继续查看下一章,编写用户服务。