迷你一个服务调用的场景,搭建两个工程:provider(服务提供方)和consumer(服务调用方)
服务提供方:使用mybatis操作数据库,实现对数据的查询,并对外提供rest接口服务
服务消费方:使用restTemplate远程调用服务提供方的rest接口,获取数据
服务提供者
创建springboot工程
编写application.yml配置文件
添加相关依赖
创建实体类
编写mapper
实现service
实现controller
启动并测试
springboot工程
application.yml配置文件
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/ssm_crud
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 1234
mybatis:
type-aliases-package: com.lifly.pojo
mapper-locations: classpath:/mapper/*.xml
# 配置Mybatis日志输出信息
logging:
level:
com.lifly.mapper: debug
相关依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<!-- SpringCloud的依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</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>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
创建实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
/**
* book的id
*/
private Integer BookId;
/**
* book的书名
*/
private String bookName;
/**
* book的书名
*/
private Integer bookCounts;
/**
* book的书名
*/
private String detail;
}
编写mapper
@Repository
@Mapper
public interface BooksMapper{
/**
* 查询所有图书
* @return
*/
public List<Books> findAllBooks();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lifly.mapper.BooksMapper">
<select id="findAllBooks" resultType="Books">
select * from books
</select>
</mapper>
实现service
public interface BooksService {
/**
* 查询所有图书
* @return
*/
public List<Books> findAllBooks();
}
@Service
public class BooksServiceImpl implements BooksService {
@Autowired
private BooksMapper booksMapper;
@Override
public List<Books> findAllBooks() {
return booksMapper.findAllBooks();
}
}
实现controller
@RestController
@RequestMapping("/books")
public class BooksController {
@Autowired
private BooksService booksService;
@GetMapping("/all")
public List<Books> findAllBooks(){
return booksService.findAllBooks();
}
}
启动并测试
输入http://localhost:8081/books/all
服务调用者
创建springboot工程
导入依赖
编写实体类
编写applicaiton.yml配置
编写controller调用服务提供者端口
测试
导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
编写实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
/**
* book的id
*/
private Integer BookId;
/**
* book的书名
*/
private String bookName;
/**
* book的书名
*/
private Integer bookCounts;
/**
* book的书名
*/
private String detail;
}
编写applicaiton.yml配置
server:
port: 8082
编写controller调用服务提供者端口
@RestController
@RequestMapping("/consumer")
public class BooksController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/book")
public List<Books>findAllBooks(){
//这种方式不好,硬编码,不利于维护
//远程调用其它项目
Books[] books = restTemplate.getForObject("http://localhost:8081/books/all", Books[].class);
return Arrays.asList(books);
}
}
测试
输入http://localhost:8082/consumer/book
这样一个简单的远程服务调用就实现了
问题
- 在consumer中,把url地址硬编码到了代码中,不利于后期维护
- consumer需要记忆provider的地址,如果出现变更,可能得不到通知,地址将失效
- consumer不清楚provider的状态,服务宕机也不知道
- provider只有1台服务,不具备高可用性
- 即便provider形成集群,consumer还需自己实现负载均衡
以上问题就是分布式必然要面临的问题
服务管理
- 如何实现注册和发现
- 如何实现状态监控
- 如何实现动态路由
服务如何实现负载均衡
服务如何解决容灾问题
服务如何实现统一配置
以上问题会在后面的springcloud中得到答案。