介绍
这里的服务提供与服务消费是基于Eureka注册中心。Eureka中有三个角色:服务注册中心、服务提供者、服务消费者。
服务提供者
新建一个springboot项目。
1.依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.dpf</groupId>
<artifactId>eureka-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-provider</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<dependencies>
<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.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.配置文件application.yml
spring:
application:
name: eureka-provider
server:
port: 1115
eureka:
client:
service-url:
defaultZone: http://localhost:1111/eureka
3.启动文件加@EnableDiscoveryClient注解
@SpringBootApplication
@EnableEurekaClient
public class EurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProviderApplication.class, args);
}
}
4.controller
@RestController
public class HelloController {
@Value("${server.port}")
Integer port;
@GetMapping("/hello")
public String hello(){
return "hello"+port;
}
@GetMapping("/hello2")
public String hello2(String name){
System.out.println(new Date()+">>"+name);
return "hello"+name;
}
@PostMapping("/user1")
public User add1(User user){
return user;
}
@PostMapping("/user2")
public User add2(@RequestBody User user){
return user;
}
@PutMapping("/user1")
public void updateUser1(User user){
System.out.println(user);
}
@PutMapping("/user2")
public void updateUser2(@RequestBody User user){
System.out.println(user);
}
@DeleteMapping("/user1")
public void deleteUser1(Integer id){
System.out.println(id);
}
@DeleteMapping("/user2/{id}")
public void deleteUser2(@PathVariable Integer id){
System.out.println(id);
}
}
@Controller
public class RegisterController {
/**
* 注意重定向的地址一定要写绝对地址,不要写相对地址,不然会出问题
* @param user
* @return
*/
@PostMapping("register")
public String register(User user){
return "redirect:http://provider/loginPage?username="+user.getUsername();
}
@GetMapping("/loginPage")
@ResponseBody
public String loginPage(String username){
return "loginPage:"+username;
}
}
服务消费者
1.依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.dpf</groupId>
<artifactId>eureka-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-consumer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<dependencies>
<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.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.配置文件
spring:
application:
name: eureka-consumer
server:
port: 1117
eureka:
client:
service-url:
defaultZone: http://localhost:1111/eureka
3.启动文件
@SpringBootApplication
@EnableEurekaClient
public class EurekaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
/**
* RestTemplate用于服务间的调用
* @return
*/
@Bean
RestTemplate restTemplateOne(){
return new RestTemplate();
}
/**
* 服务间调用,加上负载均衡
* @return
*/
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
4.控制层
@RestController
public class HelloController {
/**
* http调用,调用地址写死
* @return
*/
@GetMapping("/hello1")
public String hello1(){
HttpURLConnection con = null;
try {
URL url = new URL("http://localhost:1116/hello");
con = (HttpURLConnection) url.openConnection();
if(con.getResponseCode()==200){
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String s = br.readLine();
br.close();
return s;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "error";
}
@Autowired
DiscoveryClient discoveryClient;
/**
* 动态获取调用地址
* @return
*/
@GetMapping("/hello2")
public String hello2(){
HttpURLConnection con = null;
List<ServiceInstance> instances = discoveryClient.getInstances("eureka-provider");
ServiceInstance serviceInstance = instances.get(0);
String host = serviceInstance.getHost();
int port = serviceInstance.getPort();
StringBuilder sb = new StringBuilder();
sb.append("http://")
.append(host)
.append(":")
.append(port)
.append("/")
.append("hello");
try {
URL url = new URL(sb.toString());
con = (HttpURLConnection) url.openConnection();
if(con.getResponseCode()==200){
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String s = br.readLine();
br.close();
return s;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "error";
}
/**
* 实现线性负载均衡
*/
int count=0;
@GetMapping("/hello3")
public String hello3(){
HttpURLConnection con = null;
List<ServiceInstance> instances = discoveryClient.getInstances("eureka-provider");
ServiceInstance serviceInstance = instances.get((count++)%instances.size());
String host = serviceInstance.getHost();
int port = serviceInstance.getPort();
StringBuilder sb = new StringBuilder();
sb.append("http://")
.append(host)
.append(":")
.append(port)
.append("/")
.append("hello");
try {
URL url = new URL(sb.toString());
con = (HttpURLConnection) url.openConnection();
System.out.println(con);
if(con.getResponseCode()==200){
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String s = br.readLine();
br.close();
return s;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "error";
}
@Autowired
@Qualifier("restTemplateOne")
RestTemplate restTemplateOne;
/**
*
* 没有负载均衡的RestTemplate必须完整地址
* @return
*/
@GetMapping("/hello4")
public String hello4(){
HttpURLConnection con = null;
List<ServiceInstance> instances = discoveryClient.getInstances("eureka-provider");
ServiceInstance serviceInstance = instances.get(0);
String host = serviceInstance.getHost();
int port = serviceInstance.getPort();
StringBuilder sb = new StringBuilder();
sb.append("http://")
.append(host)
.append(":")
.append(port)
.append("/")
.append("hello");
String s = restTemplateOne.getForObject(sb.toString(), String.class);
return s;
}
@Autowired
@Qualifier("restTemplate")
RestTemplate restTemplate;
/**
* Ribbon实现负载均衡
*
* @return
*/
@GetMapping("/hello5")
public String hello5(){
return restTemplate.getForObject("http://eureka-provider/hello",String.class);
}
/**
* get方法
* RestTemplate 两种方法体验
* getForObject:返回具体值
* getForEntity:返回带Http响应头的具体值
* 两种方法都有三个不同的重载方法分别表示不同的传参方式
*
*/
@GetMapping("/hello6")
public void hello6(){
String s = restTemplate.getForObject("http://eureka-provider/hello2?name={1}", String.class, "runn");
System.out.println(s);
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://eureka-provider/hello2?name={1}", String.class, "runn");
HttpStatus statusCode = responseEntity.getStatusCode();
System.out.println("HttpStatus:"+statusCode);
int statusCodeValue = responseEntity.getStatusCodeValue();
System.out.println("statusCodeValue:"+statusCodeValue);
String body = responseEntity.getBody();
System.out.println("body:"+body);
HttpHeaders headers = responseEntity.getHeaders();
System.out.println("----------header---");
Set<String> keySet = headers.keySet();
for (String key : keySet){
System.out.println(key+"--"+headers.get(key));
}
}
/**
* get方法
* RestTemplate方法的三种传值方法
*/
@GetMapping("/hello7")
public void hello7(){
//占位符传值
String s1 = restTemplate.getForObject("http://eureka-provider/hello2?name={1}", String.class, "runn");
System.out.println(s1);
//map传值
Map<String ,Object> map = new HashMap<>();
map.put("name","runn");
String s2 = restTemplate.getForObject("http://eureka-provider/hello2?name={name}", String.class, map);
System.out.println(s2);
//uri传值
try {
//如果是中文需要转码,不然可能乱码
String url = "http://eureka-provider/hello2?name="+ URLEncoder.encode("张三","UTF-8");
URI uri = URI.create(url);
String s3 = restTemplate.getForObject(uri, String.class);
System.out.println(s3);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* post方法
* RestTemplate的post方法和get方法基本类似,多了一个postForLocation
*/
@GetMapping("/hello8")
public void hello8(){
//key/value传值
MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
map.add("username","runn");
map.add("password","123");
map.add("id",999);
User user1 = restTemplate.postForObject("http://eureka-provider/user1", map, User.class);
System.out.println(user1);
//json传值
user1.setId(998);
User user2 = restTemplate.postForObject("http://eureka-provider/user2", user1, User.class);
System.out.println(user2);
}
/**
* 测试postForLocation:用于页面重定向(注册后重定向到登录页面)
*/
@GetMapping("/hello9")
public void hello9(){
MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
map.add("username","runn");
map.add("password","123");
map.add("id",999);
URI uri = restTemplate.postForLocation("http://eureka-provider/register", map);
String s = restTemplate.getForObject(uri, String.class);
System.out.println(s);
}
/**
* 测试put请求
*/
@GetMapping("/hello10")
public void hello10(){
MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
map.add("username","runn");
map.add("password","123");
map.add("id",999);
restTemplate.put("http://eureka-provider/user1",map);
User user = new User();
user.setId(998);
user.setPassword("123");
user.setUsername("runn");
restTemplate.put("http://eureka-provider/user2",user);
}
/**
* 测试delete请求
*/
@GetMapping("/hello11")
public void hello11(){
restTemplate.delete("http://eureka-provider/user1?id={1}",998);
restTemplate.delete("http://eureka-provider/user2/{1}",999);
}
}
测试
启动注册中心eureka、两个provider服务、consumer服务,浏览器输入对应地址调用consumer接口进行调用测试。