一. 服务注册与调用
业务描述
创建两个项目Module分别为服务提供者和服务消费者(假如已有则无需创建),两者都要注册到NacosServer中(这个server本质上就是一个web服务,端口默认为8848),然后服务提供者可以为服务消费者提供远端调用服务(例如支付服务为服务提供方,订单服务为服务消费方),如图所示
生产者服务创建及注册
第一步:创建服务提供者工程(module名为sca-provider,假如已有则无需创建),继承parent工程(01-sca),其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">
<parent>
<artifactId>01-sca</artifactId>
<groupId>com.jt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sca-provider</artifactId>
<dependencies>
<!--web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring-cloud-alibaba 中 nacos 服务注册,发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
第二步:创建并修改配置文件application.yml(或者application.properties),实现服务注册,关键代码如下:
server:
port: 8081
spring:
application:
name: sca-provider #服务名必须唯一,必须要有
cloud:
nacos:
discovery: #服务注册和发现配置
server-addr: localhost:8848
第三步:创建启动类(假如已有则无需定义),关键代码如下:
package com.jt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/***
* 确保mysql正常启动
* 确保nacos正常启动
*/
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class);
}
}
第四步:启动启动类,然后刷先nacos服务,检测是否服务注册成功,如图所示:
消费者服务发现及调用
第一步: 在sca-provider项目中创建服务提供方对象,基于此对象对外提供服务,例如:
package com.jt.provider.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProviderController {
@Value("${server.port:8080}")
private String server;
@GetMapping("/provider/echo/{msg}")
public String doRestEcho(@PathVariable("msg") String msg){
//return "say hello" + msg;
return String.format("%s say hello %s", server,msg);
}
}
第二步:创建服务消费者工程(module名为sca-consumer,假如已有则无需创建),继承parent工程(01-sca),其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">
<parent>
<artifactId>01-sca</artifactId>
<groupId>com.jt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sca-consumer</artifactId>
<dependencies>
<!--web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring-cloud-alibaba 中 nacos 服务注册,发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
第三步:创建sca-consumer服务中的配置文件application.yml,关键代码如下:
server:
port: 8090
spring:
application:
name: sca-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
第四步:创建消费端启动类并实现服务消费,关键代码如下:
package com.jt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
/***
* 创建RestTemplate对象,我们可以基于此对象进行
* 远程服务调用,此对象封装了远程服务的协议和相关方法
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
第五步:在sca-consumer启动类中添加如下方法,用于创建RestTemplate对象.
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
这里之所以在启动类里创建对象,是因为该对象在Spring容器中只创建一回,而如果放到方法中加入@Component注解,则会用一次创建一次对象,比较浪费空间
第六步:定义sca-consumer服务的消费端Controller,在此对象方法内部实现远端服务调用
package com.jt.consumer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Random;
@RestController
public class ConsumerController {
@Autowired //属性注入 属性不能使用final修饰
private RestTemplate restTemplate;
// @Autowired 构造注入 只有一个构造方法,autowired也可以不写
// public ConsumerController(RestTemplate restTemplate){
// this.restTemplate=restTemplate;
// }
// @Autowired set注入
// public void setRestTemplate(RestTemplate restTemplate) {
// this.restTemplate = restTemplate;
// }
@Value("${server.port:8080}")
private String serverPort;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/consumer/doRestEcho")
public String doRestEcho1(){
String url = "http://localhost:8081/provider/echo/123456";
return restTemplate.getForObject(url, String.class);
}
@GetMapping("/consumer/doRestEcho1")
public String doRestEcho2() {
//自己写负载均衡算法
String url1 = "http://localhost:8081/provider/echo/123456";
String url2 = "http://localhost:8082/provider/echo/123456";
String[] urlArray = {url1, url2};
String url = urlArray[new Random().nextInt(urlArray.length)];
return restTemplate.getForObject(url, String.class, serverPort);
}
}
第七步:启动消费者服务,并在浏览器输入http://localhost:8090/consumer/doRestEcho1地址进行访问测试。
关于注入问题的解释
@Autowired //属性注入 属性不能使用final修饰
private RestTemplate restTemplate;
// @Autowired 构造注入 只有一个构造方法,autowired也可以不写
// public ConsumerController(RestTemplate restTemplate){
// this.restTemplate=restTemplate;
// }
// @Autowired set注入
// public void setRestTemplate(RestTemplate restTemplate) {
// this.restTemplate = restTemplate;
// }
在本项目中,属性注入的方式idea会有警告,且属性不能被fianl修饰;
第二种注入方式,构造注入(也是使用最多的注入方式),写法如上所示,构造注入中,如果只有一个构造方法,autowired可以不写
第三种注入方式,set注入,一般不怎么用,写set关键词idea会自动提示写入