外观
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, 进行远程调用