在 微服务 中最基本最基本的两个角色是服务提供者与服务消费者。
之前所有代码都在同一个框架的时候,比如 Controller 调用 Service 的,直接注入 Service bean 即可进行调用了。现在做成微服务之后,那么我们就需要有一个工程专门提供相应的服务功能,对应的有相应的工程消费这个功能,这就是服务提供者和服务消费者最基本的概念。
目录大纲:
(1)服务提供者与服务消费者概念
(2)编码思路
(3)服务提供者编码
(4)服务消费者编码
(5)存在问题
接下来看下具体的内容:
(1)服务提供者与服务消费者概念
服务提供者:服务的被调用方(即,为其他服务提供服务的服务);
服务消费者:服务的调用方(即,依赖其他服务的服务);
(2)编码思路
这里我们使用最基本的方式实现服务提供者和服务消费者。
(1)两个项目,一个服务提供者,一个是服务消费者;
(2)服务提供者从内存数据库 H2 中查询数据, Controller 进行调用获取;
(3)服务消费者调用服务提供者的 Controller 进行获取数据,然后返回给浏览器。
(3)服务提供者编码
新建工程
新建一个提供用户信息的工程,取名为:microservie-provider-user
在 pom.xml 添加依赖包
Xml 代码
- <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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.kfit</groupId>
- <artifactId>ms-provider-user</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>ms-provider-user</name>
- <url>http://maven.apache.org</url>
- <!-- spring boot parent节点,引入这个之后,在下面和spring boot相关的就不需要引入版本了; -->
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.4.1.RELEASE</version>
- </parent>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
- <dependencies>
- <!-- web支持: 1、web mvc; 2、restful; 3、jackjson支持; 4、aop ........ -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <!-- 内存数据库h2 -->
- <dependency>
- <groupId>com.h2database</groupId>
- <artifactId>h2</artifactId>
- <scope>runtime</scope>
- </dependency>
- <!-- spring data jpa -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- </dependency>
- </dependencies>
- </project>
在 src/main/resources 下新建 schema.sql 添加建表语句
创建了一张 User 表:
Sql 代码
- drop table user if exists;
- create table user(
- id bigint generated bydefaultas identity,
- username varchar(40),
- name varchar(20),
- age int(3),
- balance decimal(10,2),
- primarykey(id)
- );
在 src/main/resources / 新建 data.sql 插入数据
在 User 表插入几条数据进行测试:
Sql 代码
- insert into user(id,username,name,age,balance) values(1,'user1','张三',20,100.00);
- insert into user(id,username,name,age,balance) values(2,'user2','李四',20,100.00);
- insert into user(id,username,name,age,balance) values(3,'user3','王五',20,100.00);
- insert into user(id,username,name,age,balance) values(4,'user4','赵六',20,100.00);
创建实体类 User
Java 代码
- @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
- @Entity
- public class User implements Serializable{
- private static final long serialVersionUID = 1L;
- @Id@GeneratedValue
- private long id; //主键.
- private String username;//用户名.
- private String name; //姓名
- private int age; //年龄.
- private BigDecimal balance;//余额.
- }
为什么要加 @JsonIgnoreProperties 呢?
问题在于,使用 load 方法,您只需要一个代理,而不是真正的对象。代理对象没有已经加载的属性,所以当序列化发生时,没有要序列化的属性。使用 get 方法,您实际上可以获得真正的对象,这个对象实际上可以被序列化。
具体可以参考文章: https://my.oschina.net/lieefu/blog/680098
创建 Dao 类 UserRepository
Java 代码
- public interface UserRepository extends JpaRepository < User,
- Long > {
- }
创建 Service 类 UserService
Java 代码
- @Service
- public class UserService {
- @Autowired
- private UserRepository userRepository;
- public User getById(longid){
- return userRepository.getOne(id);
- }
- }
创建 Controller 类 UserController
Java 代码
- @RestController
- public class UserController {
- @Autowired
- private UserService userService;
- @GetMapping("/user/{id}")
- public User getById(@PathVariablelongid){
- User user = userService.getById(id);
- System.out.println(user);
- return user;
- }
- }
在 src/main/resources 新建 application.properties
主要是配置端口号和 jpa 配置:
Properties 代码
- server.port=7900
- spring.jpa.generate-ddl=false
- spring.jpa.show-sql=true
- spring.jpa.hibernate.ddl-auto=none
- spring.datasource.platform=h2
- spring.datasource.schema=classpath:schema.sql
- spring.datasource.data=classpath:data.sql
- logging.level.root=INFO
- logging.level.org.hibernate=INFO
编写启动类
Java 代码
- @SpringBootApplication
- public class App {
- public staticv oid main(String[] args) {
- SpringApplication.run(App.class, args);
- }
- }
启动 App 测试
启动访问: http://127.0.0.1:7900/user/1 可以在浏览器中看到返回信息:
- {"id":1,"username":"user1","name":"张三","age":20,"balance":100.00}
到此服务提供者就编写完毕了,这个代码没有什么特别之处,和我们常规代码编写是一样的!。
(4)服务消费者编码
新建工程
新建一个服务消费者项目,取名为:microservice-consumer-movice
在 pom.xml 添加依赖包
Xml 代码
- <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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.kfit</groupId>
- <artifactId>ms-consumer-movice</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>ms-consumer-movice</name>
- <url>http://maven.apache.org</url>
- <!-- spring boot parent节点,引入这个之后,在下面和spring boot相关的就不需要引入版本了; -->
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.8.RELEASE</version>
- </parent>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
- <dependencies>
- <!-- web支持: 1、web mvc; 2、restful; 3、jackjson支持; 4、aop ........ -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- </dependencies>
- </project>
新建实体类 User
Java 代码
- public class User implements Serializable{
- private static final longserialVersionUID = 1L;
- private long id; //主键.
- private String username;//用户名.
- private String name; //姓名
- private int age; //年龄.
- private BigDecimal balance;//余额.
- }
新建 Controller 类 MoviceController
Java 代码
- @RestController
- public class MoviceController {
- @Autowired
- private RestTemplate restTemplate;
- @GetMapping("/user/{id}")
- public User getById(longid){
- String url = "http://127.0.0.1:7900/user/"+id;
- return restTemplate.getForObject(url, User.class);
- }
- }
在 src/main/resources 新建 application.properties
这里只配置了端口号:
- server.port = 7901
新建启动类 App.java
Java 代码
- @SpringBootApplication
- public class App {
- @Bean
- public RestTemplate restTemplate(){
- returnnew RestTemplate();
- }
- publicstaticvoid main(String[] args) {
- SpringApplication.run(App.class, args);
- }
- }
这里将 RestTemplate 进行初始化,交给 Spring 进行管理。
启动测试
启动访问: http://127.0.0.1:7901/user/2 ,返回给浏览器信息:
- {"id":2,"username":"user2","name":"李四","age":20,"balance":100.00}
(5)存在问题
该例子简单易理解,但是存在很多的问题,比如:
(1)请求地址(http://127.0.0.1:7900/user/)硬编码了;
(2)当有多个提供者节点的时候,怎么进行负载,基本想法可以在提供者和消费者中间加一个反向代理,但是服务太多的时候不利于管理。
来源: http://www.roncoo.com/article/detail/131479