Skip to content

SpringCloudAlibaba笔记整理

一,nacos(注册中心)

1,简介:nacos是阿里巴巴的产品,现在是Springcloud中的一个组件。,相比于Eureka的功能更加丰富(比如:所有项目统一管理配置,不需要单独创建eureka注册中心,方便多用户产看管理员可以统一管理配置)
2,如何下载安装nacos(目前只使用Windows版本):在官方网站下载GitHub 的 Release 下载⻚: https://github.com/alibaba/nacos/releases nacos-server-1.4.1.zip
3.如何启动nacos注册中心:进入解压后的bin目录下命令行输入cmd然后输入命令startup.cmd -m standalone(进行单机版启动)
4,启动成功之后进入nacos注册中心页面地址: http://127.0.0.1:8848/nacos 默认的账号密码均为nacos

二,如何将java项目程序注册到nacos注册中心

1,创建父工程SpringCloudAlibaba

在pom文件中导入依赖

plain
<!-- 1 SpringBoot的默认默认引用的父类 -->
 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <!-- <version>2.3.12.RELEASE</version> -->
 <version>2.6.8</version>
 <relativePath/>
 <!-- lookup parent from repository -->
 </parent>
 <!-- 配置当前项目的版本信息以及基础的参数 -->
 <properties>
 <maven.compiler.source>8</maven.compiler.source>
 <maven.compiler.target>8</maven.compiler.target>
 <!-- <spring-cloud.version>Hoxton.SR12</spring-cloud.version> -->
 <spring-cloud.version>2021.0.0</spring-cloud.version>
 <spring-cloud-alibaba>2021.0.1.0</spring-cloud-alibaba>
 <!-- MyBatis-plus系列 -->
 <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
 <mybatis-plus-generator.version>3.5.2</mybatis-plus-generator.version>
 <velocity-engine-core>2.3</velocity-engine-core>
 <!-- 数据库驱动版本 -->
 <mysql.version>8.0.16</mysql.version>
 <!-- 分页工具 -->
 <pagehelper.version>2.0.0</pagehelper.version>
 </properties>
 <!-- 父类工程专属 负责配置依赖的版本,但不影响子项目(依赖不向下传递)
 如果子项目使用其中某一个依赖,子项目可以不写版本号 -->
 <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>
 <dependency>
 <groupId>com.alibaba.cloud</groupId>
 <artifactId>spring-cloud-alibaba-dependencies</artifactId>
 <version>${spring-cloud-alibaba}</version>
 <!-- <spring-cloud-alibaba>2021.0.1.0</spring-cloud-alibaba> -->
 <type>pom</type>
 <scope>import</scope>
 </dependency>
 <!-- mybatis-plus -->
 <dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-boot-starter</artifactId>
 <version>${mybatis-plus.version}</version>
 </dependency>
 <!-- 代码生成工具 -->
 <dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-generator</artifactId>
 <version>${mybatis-plus-generator.version}</version>
 </dependency>
 <!-- 代码生成模板 -->
 <dependency>
 <groupId>org.apache.velocity</groupId>
 <artifactId>velocity-engine-core</artifactId>
 <version>${velocity-engine-core}</version>
 </dependency>
 <!-- 数据连接驱动 -->
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>${mysql.version}</version>
 </dependency>
 </dependencies>
 </dependencyManagement>
 <!-- 如果dependencies配置在父工程中,这里的依赖会传递到所有的字工程中 -->
 <dependencies>
 <!--单元测试-->
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 <!--lombok(日志)-->
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <optional>true</optional>
 </dependency>
 </dependencies>

2,创建pojo实体类子项目

(1)pom导入依赖:

plain
<dependencies>
 <!-- mybatis-plus因为要从数据库导出自动生成实体类 -->
 <dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-boot-starter</artifactId>
 </dependency>
 <!-- 代码生成工具 -->
 <dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-generator</artifactId>
 </dependency>
 </dependencies>

(2)创建数据库导出实体类

plain
package com.xja.application.generator;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class CodeGeneration {
 public static void main(String[] args) {
 /**
 * 先配置数据源
 */
 MySqlQuery mySqlQuery = new MySqlQuery() {
 `@Override`
 public String[] fieldCustom() {
 return new String[]{"Default"};
 }
 };

 DataSourceConfig dsc = new DataSourceConfig.Builder("jdbc:mysql://192.168.25.3:3306/cloud_demo?serverTimezone=Asia/Shanghai&useSSL=false","root","MySQL5.7#")
 .dbQuery(mySqlQuery).build();
 //通过datasourceConfig创建AutoGenerator
 AutoGenerator generator = new AutoGenerator(dsc);

 Scanner scanner = new Scanner(System.in);
 System.out.println("代码生成的绝对路径(右键项目->copy path):");
 String projectPath = scanner.next();
 System.out.println("请输入表名,多个英文逗号分隔,所有输入 all");
 String s = scanner.next();

 /**
 * 全局配置
 */
 //String projectPath = System.getProperty("user.dir"); //获取项目路径

 String filePath = projectPath + "/src/main/java"; //java下的文件路径
 GlobalConfig global = new GlobalConfig.Builder()
 .outputDir(filePath)//生成的输出路径
 .author("lizi")//生成的作者名字
 //.enableSwagger() //开启swagger,需要添加swagger依赖并配置
 .dateType(DateType.TIME_PACK)//时间策略
 .commentDate("yyyy年MM月dd日")//格式化时间格式
 .disableOpenDir()//禁止打开输出目录,默认false
 .fileOverride()//覆盖生成文件
 .build();

 /**
 * 包配置
 */
 PackageConfig packages = new PackageConfig.Builder()
 .entity("pojo")//实体类包名
 .parent("me.wanning")//父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
 .controller("web")//控制层包名
 .mapper("com/xja/application/mapper")//mapper层包名
 .xml("mapper.xml")//数据访问层xml包名
 .service("service")//service层包名
 .serviceImpl("service.impl")//service实现类包名
 //.other("output")//输出自定义文件时的包名
 .pathInfo(Collections.singletonMap(OutputFile.xml, projectPath + "/src/main/resources/mapper")) //路径配置信息,就是配置各个文件模板的路径信息,这里以mapper.xml为例
 .build();
 /**
 * 模板配置
 */

 // 如果模板引擎是 freemarker
// String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
 // String templatePath = "/templates/mapper.xml.vm";


 TemplateConfig template = new TemplateConfig.Builder()
// .disable()//禁用所有模板
 //.disable(TemplateType.ENTITY)禁用指定模板
// .service(filePath + "/service.java")//service模板路径
// .serviceImpl(filePath + "/service/impl/serviceImpl.java")//实现类模板路径
// .mapper(filePath + "/mapper.java")//mapper模板路径
// .mapperXml("/templates/mapper.xml")//xml文件模板路路径
// .controller(filePath + "/controller")//controller层模板路径
 .build();

 /**
 * 注入配置,自定义配置一个Map对象
 */
// Map<String,Object> map = new HashMap<>();
// map.put("name","young");
// map.put("age","22");
// map.put("sex","男");
// map.put("description","深情不及黎治跃");
//
// InjectionConfig injectionConfig = new InjectionConfig.Builder()
// .customMap(map)
// .build();


 /**
 * 策略配置开始
 */
 StrategyConfig strategyConfig = new StrategyConfig.Builder()
 .enableCapitalMode()//开启全局大写命名
 //.likeTable()模糊表匹配
 .addInclude(getTables(s))//添加表匹配,指定要生成的数据表名,不写默认选定数据库所有表
 .addTablePrefix("tb_", "sys_","bus_","rel_","dic_") //设置忽略表前缀
 //.disableSqlFilter()禁用sql过滤:默认(不使用该方法)true
 //.enableSchema()启用schema:默认false

 .entityBuilder() //实体策略配置
 //.disableSerialVersionUID()禁用生成SerialVersionUID:默认true
 .enableChainModel()//开启链式模型
 .enableLombok()//开启lombok
 .enableRemoveIsPrefix()//开启 Boolean 类型字段移除 is 前缀
 .enableTableFieldAnnotation()//开启生成实体时生成字段注解
 //.addTableFills()添加表字段填充
 .naming(NamingStrategy.underline_to_camel)//数据表映射实体命名策略:默认下划线转驼峰underline_to_camel
 .columnNaming(NamingStrategy.underline_to_camel)//表字段映射实体属性命名规则:默认null,不指定按照naming执行
 .idType(IdType.AUTO)//添加全局主键类型
 .formatFileName("%s")//格式化实体名称,%s取消首字母I
 .build()

 .mapperBuilder()//mapper文件策略
 .enableMapperAnnotation()//开启mapper注解
 .enableBaseResultMap()//启用xml文件中的BaseResultMap 生成
 .enableBaseColumnList()//启用xml文件中的BaseColumnList
 //.cache(缓存类.class)设置缓存实现类
 .formatMapperFileName("%sMapper")//格式化Dao类名称
 .formatXmlFileName("%sMapper")//格式化xml文件名称
 .build()

 .serviceBuilder()//service文件策略
 .formatServiceFileName("%sService")//格式化 service 接口文件名称
 .formatServiceImplFileName("%sServiceImpl")//格式化 service 接口文件名称
 .build()

 .controllerBuilder()//控制层策略
 //.enableHyphenStyle()开启驼峰转连字符,默认:false
 .enableRestStyle()//开启生成`@RestController`
 .formatFileName("%sController")//格式化文件名称
 .build();
 /*至此,策略配置才算基本完成!*/

 /**
 * 将所有配置项整合到AutoGenerator中进行执行
 */

 generator.global(global)
 .template(template)
// .injection(injectionConfig)
 .packageInfo(packages)
 .strategy(strategyConfig)
 .execute();
 }

 // 处理 all 情况
 protected static List<String> getTables(String tables) {
 return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
 }
}

3,创建user-server子项目

(1)pom文件导入依赖:(目前只需要将web项目注册到nacos中所以导入web启动器以及nacos依赖)

plain
<dependencies>
 <!--web启动器-->
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <!-- nacos -->
 <dependency>
 <groupId>com.alibaba.cloud</groupId>
 <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
 </dependency>
 </dependencies>

(2)application.yml中写当前项目端口号以及项目注册名以及注册nacos地址

plain
server:
 port: 8080
spring:
 application:
 name: user-server
 cloud:
 nacos:
 discovery:
 server-addr: 127.0.0.1:8848

(3)创建主启动类UserServerApp

plain
package com.xja.application;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

`@SpringBootApplication`
public class UserServerApp {
 public static void main(String[] args) {
 SpringApplication.run(UserServerApp.class, args);
 }
}

(4)启动项目在nacos注册中心页面中刷新查看是否注册成功

二,在所有微服务注册到nacos中实现项目之间调用

1,创建order-server子项目(实现远程调用)

pom中导入:(注!!!将user-server子项目pom文件中依赖更新成与此相同的)

plain
<dependencies>
 <!--web启动器-->
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <!-- nacos -->
 <dependency>
 <groupId>com.alibaba.cloud</groupId>
 <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
 </dependency>
 <!-- mybatis-plus -->
 <dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-boot-starter</artifactId>
 </dependency>
 <!-- 代码生成工具 -->
 <dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-generator</artifactId>
 </dependency>
 <!-- 代码生成模板 -->
 <dependency>
 <groupId>org.apache.velocity</groupId>
 <artifactId>velocity-engine-core</artifactId>
 </dependency>
 <!-- 数据连接驱动 -->
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 </dependency>
 <!-- 负载均衡器 -->
 <dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-loadbalancer</artifactId>
 </dependency>
 <!--实体类-->
 <dependency>
 <groupId>org.xja</groupId>
 <artifactId>pojo</artifactId>
 <version>1.0-SNAPSHOT</version>
 </dependency>
 <!--feign-->
 <dependency>
 <groupId>org.xja</groupId>
 <artifactId>feign</artifactId>
 <version>1.0-SNAPSHOT</version>
 </dependency>
 <!--引入sentinel依赖-->
 <dependency>
 <groupId>com.alibaba.cloud</groupId>
 <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
 </dependency>
 <dependency>
 <groupId>com.alibaba.csp</groupId>
 <artifactId>sentinel-datasource-nacos</artifactId>
 </dependency>
 <dependency>
 <groupId>org.xja</groupId>
 <artifactId>feign</artifactId>
 <version>1.0-SNAPSHOT</version>
 <scope>compile</scope>
 </dependency>
 </dependencies>

(2)application.yml中写当前项目端口号以及项目注册名以及注册nacos地址

plain
server:
 port: 8090
spring:
 application:
 name: order-server
 cloud:
 nacos:
 discovery:
 server-addr: 127.0.0.1:8848

(3)创建主启动类OrderServerApp

plain
package com.xja.application;

import com.xja.application.config.NacosSameClusterConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.cloud.openfeign.EnableFeignClients;

`@SpringBootApplication`//SpringBoot应用程序
`@EnableFeignClients`//开启Feign远程调用以及负载均衡
public class OrderServerApp {
 public static void main(String[] args) {
 SpringApplication.run(OrderServerApp.class, args);
 }
}

(4)启动项目在nacos注册中心页面中刷新查看是否注册成功

(5)创建OrderController

plain
package com.xja.application.web;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.xja.application.service.OrderService;
import com.xja.application.userserver.UserFeign;
import com.xja.pojo.Order;
import com.xja.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;

`@RestController`
`@RequestMapping`("/order")
public class OrderController {
 `@Autowired`
 private OrderService orderService;

 //利用openfeign远程调用
 `@GetMapping`("getUserById/{id}")
 private User getUserById(`@PathVariable`("id") Integer id) {
 return userFeign.getUserById(id);
 }

 `@GetMapping`("getOrderById/{id}")
 public Order getOrderById(`@PathVariable` Integer id, HttpServletRequest request){
 String lizi = request.getHeader("lizi");
 System.out.println(lizi);
 Order order = this.orderService.getOrderById(id);
 return order;
 }
}

(6)创建在config包下MyConfig//将http远程调用注入到Spring容器IOC中

plain
package com.xja.application.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`;

`@Configuration`
public class MyConfig {
 `@Bean`
 `@LoadBalanced`
 public `RestTemplate` restTemplate() {
 return new `RestTemplate`();
 }
}

(7)创建OrderService以及实现类OrderServiceImpl

plain
package com.xja.application.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xja.application.mapper.OrderMapper;
import com.xja.application.service.OrderService;
import com.xja.application.userserver.UserFeign;
import com.xja.pojo.Order;
import com.xja.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.`RestTemplate`;

`@Service`
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
 `@Autowired`
 private OrderMapper orderMapper;
 `@Autowired`
 private `RestTemplate` restTemplate;//http远程调用
 `@Autowired`
 private DiscoveryClient discoveryClient;//SpringCloud提供的抽象接口,能与注册中心交互,获取已注册的所有服务的信息

 `@Override`
 public Order getOrderById(Integer id) {
 Order order = this.orderMapper.selectById(id);
 //不加负载均衡
 List<ServiceInstance> instances = discoveryClient.getInstances("user-server");
 ServiceInstance instance = instances.get(0);
 User user = restTemplate.getForObject("http://" + instance.getHost() + ":" + instance.getPort() + "/user/getUserById/" + order.getUserId(), User.class);

 order.setUser(user);
 return order;
 }
}

(8)在user-server子项目中创建web三层架构创建在controller包下面的(UserController)

plain
package com.xja.application.web;

import com.xja.application.service.UserService;
import com.xja.pojo.User;
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;

`@RestController`
`@RequestMapping`("/user")
public class UserController {
 `@Autowired`
 private UserService userService;

 `@GetMapping`("getUserById/{id}")
 public User getUserById(`@PathVariable`("id") Integer id) {
 User user = this.userService.getById(id);
 return user;
 }

}

(9)启动程序访问http://localhost:8090/order/gerOrderById/101, 进行远程调用

2,升级远程调用利用OpenFengin(思路:将建立一个单独的子项目,进行打包将依赖添加到user-server以及order-server的pom文件中)

(1)创建openfengin子项目

(2)在pom文件中导入有关于OpenFengin远程调用的依赖

plain
<dependencies>
 <dependency>
 	<!--实体类-->
 <groupId>org.xja</groupId>
 <artifactId>pojo</artifactId>
 <version>1.0-SNAPSHOT</version>
 </dependency>
 <dependency>
 	<!--openfeign依赖-->
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>
 </dependencies>

(3)创建UserServerFengin的接口

plain
package com.xja.application.userserver;

import com.xja.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

`@FeignClient`(value = "user-server")
public interface UserFeign {

 `@GetMapping`("/user/getUserById/{id}")
 public User getUserById(`@PathVariable`("id") Integer id);

}

(4)修改UserServiceImpl中代码

plain
package com.xja.application.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xja.application.mapper.OrderMapper;
import com.xja.application.service.OrderService;
import com.xja.application.userserver.UserFeign;
import com.xja.pojo.Order;
import com.xja.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.`RestTemplate`;

`@Service`
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
 `@Autowired`
 private OrderMapper orderMapper;
 `@Autowired`
 private UserFeign userFeign;

 `@Override`
 public Order getOrderById(Integer id) {
 Order order = this.orderMapper.selectById(id);
 User user = userFeign.getUserById(Math.toIntExact(order.getUserId()));
 order.setUser(user);
 return order;
 }
}

(5)将此项目依赖引入到user-server以及order-server的pom文件中

(6)启动程序访问http://localhost:8090/order/gerOrderById/101, 进行远程调用