先创建一个总项目
1.导入依赖
2.创建子模块
1.导入依赖
总项目的依赖
<!--项目分模块管理--> <packaging>pom</packaging> <!--公共的一些配置--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <!--1.管理 SpringBoot的jar包--> <!--SpringBoot--> <parent> <groupId> org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> </parent> <!--2.管理 SpringCloud的jar包 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!--3.这里是所有子项目都可以用的jar包--> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies>
2.创建子模块
创建eureka,它是注册中心,可以让其他的子程序注册在上面,获得它们的ip与端口号。
2.1导入依赖
<dependencies> <!--spring-cloud-starter-netflix-eureka-server --> <!--服务器的依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <!--web的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
2.2application.yml
server: port: 10100 eureka: client: registerWithEureka: false #表明自己不能被eureka注册 fetchRegistry: false #表明自己不能发现eureka的注册信息 serviceUrl: defaultZone: http://localhost:10100/eureka/ server: enable-self-preservation: false #关闭自我保护
2.3启动类
@SpringBootApplication//springboot的启动类 @EnableEurekaServer//作为Eureka服务器 public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class,args); } }
3.创建其他子程序,首先我们需要一个用户模块与订单模块,订单模块运行时需要获得用户的信息,所以我们要从order的接口根据userId获得user的controller里面查找用户信息接口的返回值,因为用户模块和订单模块相关接口的返回值都是User,所以我们要创建一个common模块来创建User的domain,然后在用户模块和订单模块导入common的依赖(它们需要用到User,而User在common模块,所以要导入依赖才能用)
首先从common开始
@Data @AllArgsConstructor //全参构造器 @NoArgsConstructor //无参构造器 @Builder /**Student.builder().sno( "001" ).sname( "admin" ).sage( 18 ).sphone( "110" ).build(); 可以用这种方式来创建对象 */ public class User { private Long id; private String name; private String intro; }
然后是user模块
导入依赖
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--依赖common--> <dependency> <groupId>cn.itsource</groupId> <artifactId>springCloud-test02-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
application.yml
#注册到EurekaServer eureka: client: serviceUrl: defaultZone: http://localhost:10100/eureka/ #默认区域 #无影响 只是改下注册服务的格式 instance: prefer-ip-address: true #使用ip地址进行注册 spring: application: name: user-server server: port: 10200
启动类
@SpringBootApplication @EnableEurekaClient//作为Eureka客户端 public class UserApplication { public static void main(String[] args) { SpringApplication.run(UserApplication.class,args); } }
controller //通过userid获取用户信息
@RestController//返回json格式 public class UserController { @Value("${server.port}") //从application.yml获取信息 private Integer port; @GetMapping("/getUserById/{id}") public User getUserById(@PathVariable(value = "id") Long userId){ return User.builder().id(userId).name("小泽玛刘亚").intro("我在拍电影" + port).build(); } }
user模块完毕,开始order模块
我们order模块除了能去user模块里面获取用户信息,我们还想给它增添一个负载均衡算法,它可以在几个启动了的user模块里面根据均衡算法选择一个user模块,也就是说order的多次请求每次请求的user服务器端口号可能都不同
我们要用均衡负载算法,我们就要导入ribbon包,还要在创建的restTemplat上加一个@loadbalance注解才能开启负载均衡算法
导入依赖
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--依赖common--> <dependency> <groupId>cn.itsource</groupId> <artifactId>springCloud-test02-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--依赖ribbon--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> </dependencies>
yml
#注册到EurekaServer eureka: client: serviceUrl: defaultZone: http://localhost:10100/eureka/ #默认区域 #无影响 只是改下注册服务的格式 instance: prefer-ip-address: true #使用ip地址进行注册 spring: application: name: order-server server: port: 10300yml
启动类
@SpringBootApplication @EnableEurekaClient public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class,args); } //在bean里注入restTemplate,也可以直接在controller里面new一个也行 @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } //负载均衡算法 @Bean public RandomRule randomRule(){ return new RandomRule(); } }
controller
@RestController public class OrderController { @Autowired private RestTemplate restTemplate; //使用了负载均衡过后就只能用端口名,而不能使用端口号(ribbon包加上启动类那里的loadbalance注解) @GetMapping("getUser/{id}") public User getUser(@PathVariable("id") Long userId){ //应该发请求到user的controller 拿到用户的信息 // User user = restTemplate.getForObject("http://localhost:10020/getUserById/" + userId, User.class); // User user = restTemplate.getForObject("http://user-server/getUserById/" + userId, User.class);return user; User user = restTemplate.getForObject("http://user-server/getUserById/" + userId, User.class); return user; } }
上面的业务已经完成,但是我们觉得太麻烦了,因为我们从ordercontorller去获取用户模块信息时,我们发送的消息
需要拼接字符串,例如("http://user-server/getUserById/" + userId, User.class);
所以我们换了一种技术,叫作feign,feign里面自带负载均衡算法,更简单了
为了演示feign,我将会写一个支付服务的模块,同样它要去用户模块获取用户信息。
导入依赖
<dependencies> <!--依赖common--> <dependency> <groupId>cn.itsource</groupId> <artifactId>springCloud-test02-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--2.导入Feign的包--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies>
yml
#注册到EurekaServer eureka: client: serviceUrl: defaultZone: http://localhost:10100/eureka/ #默认区域 #无影响 只是改下注册服务的格式 instance: prefer-ip-address: true #使用ip地址进行注册 spring: application: name: pay-server server: port: 10400
启动类
@SpringBootApplication @EnableEurekaClient //可写可不写,client自动实现它的作用,为了谨慎写一个吧 @EnableFeignClients //告诉框架要扫描feignclient注解,扫描到了就放进spring容器里面 public class PayApplication { public static void main(String[] args) { SpringApplication.run(PayApplication.class,args); } }
feign
@FeignClient(name = "user-server")//name用于服务发现 public interface UserFeign { //下面的方法直接去controller里面拷贝过来,再把方法体删了就ok @GetMapping("/getUserById/{id}") public User getUserById(@PathVariable(value = "id") Long userId); }
controller
@RestController public class PayController { @Autowired private UserFeign userFeign; @GetMapping("/getUserById/{id}") public User getUserById(@PathVariable(value = "id") Long userId){ return userFeign.getUserById(userId); } }