搭建springcloud项目
- Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉取注册表,从而知道其他服务在哪里
- Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从一个服务的多台机器中选择一台
- Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
- Hystrix:发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题
- Zuul:如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务
- GateWay:和zuul的作用相同,都是用来管理授权、访问控制和流量限制等,由于网飞公司已经停更Zuul(落后就淘汰),所以springcloud自己继承了个网关,俗称网管二代
- SpringcloudConfig:配置中心的作用就在于可以在项目启动时加载远程或本地的配置文件,将配置文件集中管理,默认实现的是git
- SpringcloudBus:消息总线,当Config服务端并不能动态的感知Git上配置文件的变化,当git上配置文件更新后,如果不采取其它措施,就只能重启相关应用,SpringcloudBus可以做到配置的自动更新
pom方式:
1.父类导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<mysql.version>5.1.47</mysql.version>
</properties>
<!--约束版本号-->
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.创建eureka注册中心
- Eureka Client:负责将这个服务的信息注册到Eureka Server中
- Eureka Server:注册中心,里面有一个注册表,保存了各个服务所在的机器和端口号
2.2 导入依赖
<!--eureka服务端,用来保存ip和端口号-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
2.3编写配置文件application.yml
server:
port: 10086
spring:
application:
name: eureka-server # 应用名称,会在Eureka中作为服务的id标识(serviceId)
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
2.4编写启动器
package cn.itcast;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @Author: 天下乌鸦我最白
* @Date: 2020/11/25 22:07
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class);
}
}
结构图:
3.创建提供者provider
3.1导入依赖
<dependencies>
<!--这是一个web项目,俗称war-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatisplus,里面集成了HikariCP数据源和jdbc-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>
<!--这是网飞公司的注册中心客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
3.2编写配置文件application.yml
server:
port: 8081 #设置微服务的端口号
spring:
datasource:
url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka # EurekaServer地址,注意:是服务器的地址
3.3编写pojo
package cn.itcast.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data //注意要记得添加lombok的依赖
@TableName("tb_user") //指定对象和数据库表名映射
public class User {
/**
* AUTO(0), //自增
* NONE(1), //plus不参与
* INPUT(2), //手动输入
* ID_WORKER(3), //雪花算法
* UUID(4), //uuid
* ID_WORKER_STR(5); //雪花算法转str字符串
*/
// id
@TableId(type = IdType.AUTO)//自增
private Long id;
// 用户名
private String userName;
// 密码
private String password;
// 姓名
private String name;
// 年龄
private Integer age;
// 性别,1男性,2女性
private Integer sex;
// 出生日期
private Date birthday;
// 创建时间
private Date created;
// 更新时间
private Date updated;
// 备注
private String note;
}
3.4编写mapper
package cn.itcast.mapper;
import cn.itcast.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper//包扫描也可以在启动类里@MapperScan(“里面是路径”)
public interface UserMapper extends BaseMapper<User> {
}
3.5编写service
package cn.itcast.service;
import cn.itcast.mapper.UserMapper;
import cn.itcast.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List<User> findAll() {
return userMapper.selectList(null);//条件
}
}
3.6编写controller
package cn.itcast.controller;
import cn.itcast.pojo.User;
import cn.itcast.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user")
public List<User> findAll(){
return userService.findAll();
}
}
3.7编写启动器
package cn.itcast;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @Author: 天下乌鸦我最白
* @Date: 2020/11/25 22:20
*/
@SpringBootApplication
@EnableDiscoveryClient//开启注册中心客户端,相当于往服务端里注册服务
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class);
}
}
结构图:
4.创建消费者,毕竟有提供就有消费嘛!
4.1第一肯定是导入依赖
<dependencies>
<!--不用说了吧,web项目-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--网飞公司的注册中心客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--远程调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
4.2编写配置文件 application.yml
server:
port: 8080
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:10086/eureka
spring:
application:
name: consumer-service #name不能用_划线,有通配符的作用
4.3编写启动器
package cn.itcast;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableDiscoveryClient//开启注册中心的客户端,向注册中心服务端注册
@SpringBootApplication//boot启动注解
@EnableFeignClients//开启远程调用客户端
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
}
4.4编写pojo,主要是服务端没pojo,所以写一个,不过注意他不需要数据库那些
package cn.itcast.pojo;
import lombok.Data;
import java.util.Date;
@Data //注意要记得添加lombok的依赖,看情况,也可以自己写
public class User {
private Long id;
// 用户名
private String userName;
// 密码
private String password;
// 姓名
private String name;
// 年龄
private Integer age;
// 性别,1男性,2女性
private Integer sex;
// 出生日期
private Date birthday;
// 创建时间
private Date created;
// 更新时间
private Date updated;
// 备注
private String note;
}
4.5 编写client接口
package cn.itcast.client;
import cn.itcast.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@FeignClient("user-service")//我们要调谁的服务就写谁,根据应用名(id)
public interface UserClient {
@GetMapping("/user")//这里一定要写服务端的请求路径
List<User> findAll();
}
4.6编写controller
package cn.itcast.controller;
import cn.itcast.client.UserClient;
import cn.itcast.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class ConsumerController {
@Autowired
UserClient userClient;
@GetMapping("/consumer")
public List<User> findAll(){
return userClient.findAll();
}
}
- 首先,如果你对某个接口定义了@FeignClient注解,Feign就会针对这个接口创建一个动态代理
- 接着你要是调用那个接口,本质就是会调用 Feign创建的动态代理,这是核心中的核心
- Feign的动态代理会根据你在接口上的@RequestMapping等注解,来动态构造出你要请求的服务的地址
- 最后针对这个地址,发起请求、解析响应
5.创建网关zuul
5.1创建模块,导入依赖
<dependencies>
<!--不用说,肯定是网关依赖,里面有ribbon和hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!--注册服务,毕竟要通过负载均衡掉-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
5.2编写配置文件application.yml
server:
port: 10010 #服务端口
spring:
application:
name: api-gateway #指定服务名
zuul:
routes:
consumer-service: /consumer-service/**
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:10086/eureka
5.3编写拦截器
package cn.itcast;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class MyFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";//前置拦截器
//还有路由拦截器,后置拦截器,error拦截器
}
@Override
public int filterOrder() {
return 0;//-1-10都是前置拦截器
}
@Override
public boolean shouldFilter() {
return true;//开启拦截
}
@Override
public Object run() throws ZuulException {
//获取上下文信息
RequestContext ctx = RequestContext.getCurrentContext();
//创建请求
HttpServletRequest request = ctx.getRequest();
String token = request.getParameter("token");
if(StringUtils.isEmpty(token)){
//报错状态码
ctx.setResponseStatusCode(403);
//拦截
ctx.setSendZuulResponse(false);
}
return null;//null是放行
}
}
5.4编写启动器
package cn.itcast;
import com.netflix.zuul.ZuulFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy//开启zuul网关
@SpringBootApplication
@EnableDiscoveryClient//注册服务
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class);
}
}
6路径访问测试
http://localhost:10010/consumer-service/consumer/?token=1