0、整体
整体项目概览
整体服务概览
1、新建父工程demo-nacos
删除src ,切记 packaging:pom
<?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>
<artifactId>spring-boot-dependencies</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.3.2.RELEASE</version>
<relativePath />
</parent>
<packaging>pom</packaging>
<groupId>com.example</groupId>
<artifactId>demo-nacos</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-nacos</name>
<description>demo-nacos</description>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<alibaba-cloud.version>2.2.5.RELEASE</alibaba-cloud.version>
<springcloud.version>Hoxton.SR8</springcloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${springcloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.19</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、新建通用模块demo-nacos-common
<?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>
<artifactId>demo-nacos</artifactId>
<groupId>com.example</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-nacos-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-nacos-common</name>
<description>demo-nacos-common</description>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip> <!-- 防止编译出错 -->
</configuration>
</plugin>
</plugins>
</build>
</project>
添加响应web实体类:
package com.example.demonacoscommon.entity;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* 类描述: 返回前端的消息封装
*
* @author Administrator
*/
@Data
@AllArgsConstructor
public class RestApiResponse<T> implements Serializable {
private static final long serialVersionUID = 1L;
private static final String DEFAULT_MSG_SUC = "成功";
private Object data;
private String message;
private int status;
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<>();
if (data != null) {
map.put("data", this.getData());
}
if (message != null) {
map.put("message", this.getMessage());
}
map.put("code", this.getStatus());
return map;
}
protected RestApiResponse() {
super();
}
protected RestApiResponse(Object data) {
this.setStatus(200);
this.data = data;
}
protected RestApiResponse(int code, Object data) {
this.setStatus(code);
this.message = DEFAULT_MSG_SUC;
this.data = data;
}
public Object getData() {
return data;
}
public RestApiResponse<T> setData(Object data) {
this.data = data;
return this;
}
@Override
public String toString() {
return JSON.toJSONStringWithDateFormat(this, "yyyy-MM-dd HH:mm:ss");
}
public static RestApiResponse<?> fromJson(String json) {
return JSON.parseObject(json, RestApiResponse.class);
}
public String getMessage() {
return message;
}
@SuppressWarnings("rawtypes")
public RestApiResponse setMessage(String message) {
this.message = message;
return this;
}
@SuppressWarnings("rawtypes")
public static RestApiResponse ok() {
return ok(null);
}
@SuppressWarnings("rawtypes")
public static RestApiResponse ok(Object data) {
return new RestApiResponse(200, data);
}
@SuppressWarnings("rawtypes")
public static RestApiResponse error(String message) {
return new RestApiResponse(500, null).setMessage(message);
}
@SuppressWarnings("rawtypes")
public static RestApiResponse error(String message, int status) {
return new RestApiResponse().setStatus(status).setMessage(message);
}
@SuppressWarnings("rawtypes")
public static RestApiResponse error(String message, int status, Object data) {
return new RestApiResponse(data).setStatus(status).setMessage(message);
}
@SuppressWarnings("rawtypes")
public static RestApiResponse error(ResultStatus resultStatus) {
return new RestApiResponse().setStatus(resultStatus.getCode()).setMessage(resultStatus.getMessage());
}
public int getStatus() {
return status;
}
@SuppressWarnings("rawtypes")
public RestApiResponse setStatus(int status) {
this.status = status;
return this;
}
}
自定义请求状态码:
package com.example.demonacoscommon.entity;
/**
* 类描述:自定义请求状态码
*/
public enum ResultStatus {
USERNAME_OR_PASSWORD_ERROR(-1001, "用户名或密码错误"),
USER_NOT_FOUND(-1002, "用户不存在"),
USER_NOT_LOGIN(-1003, "用户未登录"),
/**************** 修改密码 (-8000) ***************************/
MODIFY_PASSWORD_SUCCESS(-8001, "密码修改成功!"),
MODIFY_PASSWORD_FAIL(-8002, "密码修改失败!"),
MODIFY_PASSWORD_NULL(-8003, "旧密码为空或者旧密码填写不正确!"),
/**************** 参数 (-10000) ***************************/
PARAM_NULL(100001, "参数不能为空"),
PARAM_INCORRECT(100002, "参数不正确"),
PC_CURRENT_ACTIVITY_CODE(100003, "节点不能为空"),
/**************** 异常(90001) ***************************/
CODE_EXCEPTION(90001, "代码异常");
/**
* 返回码
*/
private int code;
/**
* 返回结果描述
*/
private String message;
ResultStatus(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
实体类:最好手动加上getter、setter
package com.example.demonacoscommon.entity;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Administrator
*/
@Data
public class User {
private Integer id;
private String name;
private String money;
public User() {
}
public User(Integer id, String name, String money) {
this.id = id;
this.name = name;
this.money = money;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMoney() {
return money;
}
public void setMoney(String money) {
this.money = money;
}
}
3、生产者模块demo-nacos-provider
<?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>
<artifactId>demo-nacos</artifactId>
<groupId>com.example</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-nacos-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-nacos-provider</name>
<description>demo-nacos-provider</description>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- nacos依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 健康管理依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 我们创建的公共模块 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>demo-nacos-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
application.yml
server:
port: ${port:9001}
spring:
application:
name: provider-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: 3fcf3501-1f2e-46e7-8bb0-501c1b3f9db3
# jackson:
# serialization:
# FAIL_ON_EMPTY_BEANS: false
启动类加注解:
package com.example.demonacosprovider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient // nacos客户端注解
public class DemoNacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DemoNacosProviderApplication.class, args);
}
}
新建controller:
package com.example.demonacosprovider.controller;
import com.example.demonacoscommon.entity.User;
import com.example.demonacoscommon.entity.RestApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @author Administrator
*/
@RestController
@RequestMapping("/provider")
@Slf4j
public class ProviderController {
public static HashMap<Integer, User> users = new HashMap<>(6);
static {
users.put(1, new User(1, "冷风扇1号", "111"));
users.put(2, new User(2, "冷风扇2号", "222"));
users.put(3, new User(3, "冷风扇3号", "333"));
users.put(4, new User(4, "冷风扇4号", "444"));
users.put(5, new User(5, "冷风扇5号", "555"));
users.put(6, new User(6, "冷风扇6号", "666"));
}
@Value("${server.port}")
private String serverPort;
@GetMapping("/get")
public RestApiResponse<User> executePay(@RequestParam("userId") Integer userId) {
System.out.println("come in provider service port: " + serverPort);
Map<String, User> resultMap = new HashMap(1);
resultMap.put(serverPort, users.get(userId));
return RestApiResponse.ok(resultMap);
}
}
启动服务:允许多个实例(测试nacos的负载均衡):以及第二个启动的add vm options加上 -Dport=9002
可看到:
4、消费者模块demo-nacos-consumer
<?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>
<artifactId>demo-nacos</artifactId>
<groupId>com.example</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-nacos-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-nacos-consumer</name>
<description>demo-nacos-consumer</description>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 我们创建的公共模块 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>demo-nacos-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
application.yml:
server:
port: ${port:9101}
spring:
application:
name: consumer-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: 3fcf3501-1f2e-46e7-8bb0-501c1b3f9db3
toserver:
name: http://provider-service
启动类加注解:@EnableDiscoveryClient
负载均衡配置:
package com.example.demonacosconsumer.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author Administrator
*/
@Configuration
public class RibbonConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
新建controller:
package com.example.demonacosconsumer.controller;
import com.example.demonacoscommon.entity.RestApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Value("${toserver.name}")
private String toServerName;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/get/{userId}")
public RestApiResponse<Object> consumer(@PathVariable("userId") Integer userId) {
return restTemplate.getForObject(toServerName + "/provider/get?userId=" + userId, RestApiResponse.class, userId);
}
}
启动:访问接口 http://localhost:9101/consumer/get/1
刷新:
5、通过feign调用provider:
新建模块 demo-nacos-consumer-feign:
<?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>
<artifactId>demo-nacos</artifactId>
<groupId>com.example</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>demo-nacos-consumer-feign</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-nacos-consumer-feign</name>
<description>demo-nacos-consumer-feign</description>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 我们创建的公共模块 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>demo-nacos-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>
application.yml:
server:
port: ${port:9101}
spring:
application:
name: consumer-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: 3fcf3501-1f2e-46e7-8bb0-501c1b3f9db3
#toserver:
# name: http://provider-service
启动类加注解:@EnableDiscoveryClient
@EnableFeignClients
负载均衡配置类:
package com.example.demonacosconsumerfeign.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author Administrator
*/
@Configuration
public class RibbonConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
service:
package com.example.demonacosconsumerfeign.service;
import com.example.demonacoscommon.entity.RestApiResponse;
import com.example.demonacoscommon.entity.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "provider-service")
public interface ProviderService {
@GetMapping("/provider/get")
RestApiResponse<User> executeProvider(@RequestParam("userId") Integer userId);
}
controller:
package com.example.demonacosconsumerfeign.controller;
import com.example.demonacoscommon.entity.RestApiResponse;
import com.example.demonacoscommon.entity.User;
import com.example.demonacosconsumerfeign.service.ProviderService;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private ProviderService providerService;
@GetMapping("/get/{userId}")
public RestApiResponse<User> consumer(@PathVariable("userId") Integer userId) {
return providerService.executeProvider(userId);
}
}
命名空间: