SpringCloud介绍:
1. 什么是微服务?
微服务架构(Microservice Architecture)是一种架构概念,旨在将功能点进行比较细粒度的拆分,
拆成一个个可以独立运行和发布部署的独立系统。这些系统我们就称为微服务系统。微服务系统近乎完全解耦。
2. 微服务架构的实现技术:
dubbo、spring cloud等;
3. spring cloud是什么?
Spring Boot基于spring,擅长的是集成,把世界上最好的框架集成到自己项目中。而Spring Cloud是基于SpringBoot
开发而来,SpringCloud是一系列框架的有序集合,是把非常流行的微服务的技术整合到一起,是微服务架构的一站式技术解决方案。
4. spring cloud常用的组件:
注册中心:Eureka、consul、Zookeeper
负载均衡:Ribbon
熔断器:Hystrix
服务通信:Feign
网关:Gateway
配置中心 :config
消息总线:Bus、集成rabbitmq
5. spring boot和spring cloud的版本要对应。
6. RestTemplate:
spring家族的RestTemplate,是一种实现系统之间通信的技术。spring cloud支持http协议,而RestTemplate内部封装了http客户端工具,
所以RestTemplate支持http协议。
7. RestTemplate使用场景演示,微服务中没有消费者和提供者,为了便于理解,这里使用消费者和提供者;
1.创建provider
1.pom文件
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.it</groupId>
<artifactId>it-restTemplate-provider</artifactId>
<version>1.0-SNAPSHOT</version>
<!--微服务架构中并没有provider和consumer,这里是为了便于理解-->
<!--父工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<!--web起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
</project>
2.启动类:
package com.it;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/2
*/
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}
3. pojo
package com.it.pojo;
import java.io.Serializable;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/2
*/
public class User implements Serializable {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4. Controller类
package com.it.controller;
import com.it.pojo.User;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/2
*/
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/getById/{id}")
public User getById(@PathVariable(name = "id") Integer id){
User user = new User();
user.setId(id);
user.setName("东方不败");
return user;
}
}
5. 配置文件:无,默认端口8080;
2.创建consumer
1.pom文件
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.it</groupId>
<artifactId>it-restTemplate-consumer</artifactId>
<version>1.0-SNAPSHOT</version>
<!--微服务架构中并没有provider和consumer,这里是为了便于理解-->
<!--父工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<!--web起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
</project>
2.启动类:
package com.it;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/2
*/
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
3. pojo
package com.it.pojo;
import java.io.Serializable;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/2
*/
public class User implements Serializable {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4. Controller类
package com.it.controller;
import com.it.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/2
*/
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/getInfo")
public String getInfo(){
//调用provider,获取用户的数据
//自动发送请求,并将数据转成pojo
User user = restTemplate.getForObject("http://localhost:8080/user/getById/123", User.class);
System.out.println(user.getId()+":"+user.getName());
System.out.println("获取到了数据。。。。");
return "ok";
}
}
5. 配置文件:application.yml
server:
port: 8081
8. Spring Data JPA:
spring data jpa是一种持久层技术框架,内部封装了基本的CRUD,使用jpa,不需要写XML文件就可以实现基本的CRUD功能;
spring data jpa的使用:
1. 使用注解,使pojo和数据库表建立映射:
在pojo类上加上如下注解:
@Entity:表示这个POJO是和数据库表建立映射的POJO
@Table(name = "tb_user"):指定数据库中对应的表,建立映射
在pojo的属性上加上如下注解:
@Id:标记该属性为主键
@GeneratedValue(strategy = GenerationType.IDENTITY):标记主键自增策略
@Column(name = "username"):建立pojo属性和数据库表中列的映射,若属性名和数据库一致,可以不写
2. 创建Dao接口继承JpaRepository<>接口:
如下:
User为数据库表对应的pojo;
Integer为主键类型;
无需写基本的CRUD,因为JpaRepository内部封装了;
@Repository
public interface UserDao extends JpaRepository<User,Integer> {
}
9. 模拟微服务使用场景:微服务中没有消费者和提供者,为了便于理解,这里使用消费者和提供者;
在上面的RestTemplate的使用中,尽管实现了系统之间的通信,但是实现时,却将URL写死了,这样可扩展性和可维护性都受限,
因此,类似zookeeper一样,我们使用spring cloud eureka作为注册中心,使用推拉机制实现动态获取IP和端口。
1. 创建父工程parent,用于统一管理springboot和springcloud依赖的版本;
1. pom文件
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.it</groupId>
<artifactId>it-springcloud-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<description>父工程,管理springboot和springcloud的版本</description>
<modules>
<module>user-provider</module>
<module>user-consumer</module>
</modules>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<!--SpringCloud包版本依赖管理-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2. 创建eureka-server作为Eureka的服务端:
1. pom文件:导入eureka-server依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>it-springcloud-parent</artifactId>
<groupId>com.it</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>it-eureka-server</artifactId>
<description>eureka服务端</description>
<dependencies>
<!--eureka-server依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
2. 创建启动类,并使用注解@EnableEurekaServer表明这是Eureka的服务端
package com.it;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/3
*/
@SpringBootApplication
@EnableEurekaServer//表明这是Eureka的服务端
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class,args);
}
}
3. 配置文件:application.yml:
server:
port: 7001
eureka:
client:
register-with-eureka: false #是否将自己注册到Eureka中
fetch-registry: false #是否从eureka中获取服务信息
service-url:
defaultZone: http://localhost:7001/eureka # EurekaServer的注册地址,Eureka的客户端通过改地址进行注册
spring:
application:
name: eureka-server # 应用名称,会在Eureka中作为服务的id标识(serviceId)
2. 创建微服务user-provider,为了便于理解,可以理解为服务端:
1. pom文件:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>it-springcloud-parent</artifactId>
<groupId>com.it</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-provider</artifactId>
<!--假设该系统为用户系统,提供用户的相关信息-->
<dependencies>
<!--JPA包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--web起步包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--MySQL驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--测试包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--eureka客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
2. 创建启动类,并使用注解@EnableEurekaClient表明这是Eureka的客户端
package com.it;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/3
*/
@SpringBootApplication
@EnableEurekaClient//表示该服务是Eureka的客户端
public class UserProviderApplication {
public static void main(String[] args) {
SpringApplication.run(UserProviderApplication.class,args);
}
}
3. 创建pojo并与数据库表建立映射:
package com.it.pojo;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/3
*/
@Entity//表示这个POJO是和数据库表建立映射的POJO
@Table(name = "tb_user")//指定数据库中对应的表,建立映射
public class User implements Serializable {
@Id//标记该属性为主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//标记主键自增策略
private Integer id;//主键id
@Column(name = "username")//若属性名和数据库一致,可以不写
private String username;//用户名
private String password;//密码
private String name;//姓名
private Integer age;//年龄
private Integer sex;//性别 1男性,2女性
private Date birthday; //出生日期
private Date created; //创建时间
private Date updated; //更新时间
private String note;//备注
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getUpdated() {
return updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
4. 创建Controller类:
package com.it.controller;
import com.it.pojo.User;
import com.it.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/3
*/
@RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "findAll")
public List<User> findAll(){
return userService.findAll();
}
@RequestMapping(value = "findByUser")
public User findByUser(){
return userService.findAll().get(0);
}
}
5. 创建service接口及实现类:
接口:
package com.it.service;
import com.it.pojo.User;
import java.util.List;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/3
*/
public interface UserService {
List<User> findAll();
}
实现类:
package com.it.service.impl;
import com.it.dao.UserDao;
import com.it.pojo.User;
import com.it.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/3
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public List<User> findAll() {
return userDao.findAll();
}
}
6. 创建Dao接口继承JpaRepository
package com.it.dao;
import com.it.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/3
*/
@Repository
public interface UserDao extends JpaRepository<User,Integer> {
}
3. 创建微服务user-consumer,为了便于理解,可以理解为消费端:
1. pom文件:导入eureka-client依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>it-springcloud-parent</artifactId>
<groupId>com.it</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-consumer</artifactId>
<!--假设该系统为电影微服务系统,需要获取用户信息-->
<dependencies>
<!--web起步包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--eureka客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
2. 创建启动类,并使用注解@EnableEurekaClient表明这是Eureka的客户端
package com.it;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/3
*/
@SpringBootApplication
@EnableEurekaClient
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class,args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
3. 配置文件:application.yml
server:
port: 18082
spring:
application:
name: user-consumer
eureka:
client:
register-with-eureka: true #是否将自己注册到Eureka中,可以不配,默认为true
fetch-registry: true #是否从eureka中获取服务信息,可以不配,默认为true
service-url:
defaultZone: http://localhost:7001/eureka # 注册到EurekaServer端的地址
4. 创建Controller类:向微服务user-provider发送请求,获取user-provider查询到的信息:
package com.it.controller;
import com.it.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* ToDo
*
* @author Lyle
* @date 2020/4/3
*/
@RestController
@RequestMapping("/movie")
public class MovieController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping("/look/{username}")
public String look(@PathVariable(name = "username") String username){
//接收用户信息
// User user = restTemplate.getForObject("http://localhost:18081/user/findByUser", User.class);
List<ServiceInstance> instances = discoveryClient.getInstances("user-provider");
ServiceInstance serviceInstance = instances.get(0);
User user = restTemplate.getForObject("http://"
+serviceInstance.getHost()+":"+serviceInstance.getPort()
+"/user/findByUser", User.class);
System.out.println(username+"===========>"+user.getName());
return "success";
}
}