本文使用生产端与消费端两个工程来展示微服务之间的调用方式
具体内容详见代码注释
生产端工程:
pom.xml
<?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.cloud.demo</groupId> <artifactId>micro-provider</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>micro-provider</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <!--spring cloud依赖管理--> <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-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <!--引入zookeeper 测试时使用,只能连接本地的zookeeper--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-all</artifactId> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.12</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> </plugins> </build> </project>
application.yml配置
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///testdb?useSSL=true username: root password: 123 application: name: provider #配置服务名 cloud: zookeeper: connect-string: localhost:2181 #注册zookeeper地址 mybatis: configuration: map-underscore-to-camel-case: true # 配置mybatis字段与实体类属性映射 # 配置打印SQL的日志 logging: level: com.cloud.demo.microprovider.mapper: debug
UserInfo实体类
package com.cloud.demo.microprovider.domain; import lombok.Getter; import lombok.Setter; import java.util.Date; @Getter //lombok插件生成get方法 @Setter //lombok插件生成set方法 public class UserInfo { private Integer userId; private String userName; private int userAge; private Date userBirth; }
service接口
package com.cloud.demo.microprovider.service; import com.cloud.demo.microprovider.domain.UserInfo; public interface UserService { UserInfo getUserById(Integer userId); }
service实现类
package com.cloud.demo.microprovider.service; import com.cloud.demo.microprovider.domain.UserInfo; import com.cloud.demo.microprovider.mapper.UserInfoMapper; import org.springframework.stereotype.Service; import javax.annotation.Resource; @Service public class UserServiceImpl implements UserService { @Resource private UserInfoMapper userMapper; @Override public UserInfo getUserById(Integer userId) { return userMapper.getUser(userId); } }
Mapper
package com.cloud.demo.microprovider.mapper; import com.cloud.demo.microprovider.domain.UserInfo; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; public interface UserInfoMapper { @Select("SELECT USER_ID, " + "USER_NAME, USER_AGE, " + "USER_BIRTH FROM T_USER WHERE USER_ID=#{userId}") UserInfo getUser(@Param("userId") Integer userId); }
Controller
package com.cloud.demo.microprovider.controller; import com.cloud.demo.microprovider.domain.UserInfo; import com.cloud.demo.microprovider.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Autowired private UserService userService; @GetMapping("user/{id}") public UserInfo getUser(@PathVariable("id") Integer userId) { return userService.getUserById(userId); } }
服务启动类:
package com.cloud.demo.microprovider; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @MapperScan("com.cloud.demo.microprovider.mapper")//扫描Mapper到Spring容器中 @EnableDiscoveryClient //将服务注册到Zookeeper中管理 public class MicroProviderApplication { public static void main(String[] args) { SpringApplication.run(MicroProviderApplication.class, args); } }
消费端工程:
pom.xml
<?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.gerry.cloud.demo</groupId> <artifactId>micro-consumer</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>micro-consumer</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <!--spring cloud依赖管理--> <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-web</artifactId> </dependency> <!--引入zookeeper 测试时使用,只能连接本地zookeeper--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-all</artifactId> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.12</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> </plugins> </build> </project>
application.yml配置
server: port: 8888 #为了与生成端端口不同,设置端口号 spring: cloud: zookeeper: connect-string: localhost:2181 #注册zookeeper地址 discovery: register: false #设置为false代表不会注册进zookeeper
实体类
package com.gerry.cloud.demo.microconsumer.vo; import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Getter; import lombok.Setter; import java.util.Date; @Getter @Setter public class UserVo { private Integer userId; @JsonAlias("userName") // 配置json字段映射 private String personName; private int userAge; @JsonFormat(pattern = "yyyy-MM-dd") private Date userBirth; }
package com.gerry.cloud.demo.microconsumer.config; import org.springframework.boot.SpringBootConfiguration; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; /** * 把RestTemplate对象装配到spring容器管理 */ @SpringBootConfiguration public class RestTemplateConfiguration { @Bean @LoadBalanced //负载均衡 public RestTemplate restTemplate() { return new RestTemplate(); } }
Controller
package com.gerry.cloud.demo.microconsumer.controller; import com.gerry.cloud.demo.microconsumer.vo.UserVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class UserWarpController { @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; // 写死访问api方式测试 /*@GetMapping("warp/user/{version}/{id}") public UserVo getUser(@PathVariable("version") double version , @PathVariable("id") Integer userId, String name) { System.out.println(version); System.out.println(name); // url必须是rest风格路径 return restTemplate.getForObject("http://localhost:8080//user/"+userId, UserVo.class); }*/ /*@GetMapping("warp/user/{id}") public UserVo getUser(@PathVariable("id") Integer userId) { //可以实现负载均衡 ServiceInstance serviceInstance = loadBalancerClient.choose("provider"); String host = serviceInstance.getHost(); // 主机名 int port = serviceInstance.getPort(); // 端口号 String url = String.format("http://%s:%s/%s/%d",host, port, "user", userId); System.out.println(url); // url必须是rest风格路径 return restTemplate.getForObject(url, UserVo.class); }*/ @GetMapping("warp/user/{id}") //可以实现负载均衡 public UserVo getUser(@PathVariable("id") Integer userId) { // url必须是rest风格路径 return restTemplate.getForObject("http://provider/user/"+userId, UserVo.class); } }
服务启动类
package com.gerry.cloud.demo.microconsumer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class MicroConsumerApplication { public static void main(String[] args) { SpringApplication.run(MicroConsumerApplication.class, args); } }
注意:此篇文章只是测试时使用,只能连接本地zookeeper,不能连接远程zookeeper,原因是zookeeper依赖不对,应改为:
<!--Service Discovery with Zookeeper--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> </dependency>