linux环境搭建
首先下载并安装VirtualBox,要开启CPU虚拟化。即virtualBox进行安装需要cpu开启虚拟化,在开机启动的时候设置主板,CPU configuration,然后点击Intel Vitualization Technology。重启电脑。
vagrant安装
普通安装linux虚拟机太麻烦,可以利用vagrant可以帮助我们快速地创建一个虚拟机。主要装了virtualbox,vagrant可以帮助我们快速创建出一个虚拟机。他有一个镜像仓库。去www.vagrantup.com/ 下载vagrant安装,安装后重启电脑。cmd中输入vagrant有版本代表成功了。
打开window cmd窗口,输入vagrant init centos/7,即可初始化一个centos7系统(注意这个命令在哪个目录下执行的,他的Vagrantfile就生成在哪里),当然命令后面的centos/7是vagrant仓库中名字
运行vagrant up即可启动虚拟机环境,系统root用户的密码是vagrant,启动后出现default folder:/cygdrive/c/User/… =>/vagrant。就表示启动成功,接着ctrl+c退出。
vagrant ssh 自动使用
vagrant用户会连上虚拟机。可以使用exit退出。
如果想要关闭虚拟机的话,直接点virtualbox退出->正常关机即可
下次想要启动虚拟机时,可以直接打开virtualbox,右键启动
当然也可以使用cmd命令行,输入vagrant up(需要保证当前所在目录下有Vagrantfile文件),然后使用vagrant ssh连接虚拟机
虚拟机网络设置
一开始的网络是网络地址转换+端口转发的方式。
当我们在virtualbox上安装redis之后,需要跟windows主机做端口映射,即当windows主机上访问6666端口时,就会映射访问到virtualbox中的6379端口,访问到redis,当我们windows主机上访问3333端口时,就会映射访问到virtualbox中的3306端口,这种方式都需要我们在virtualbox中进行设置端口映射,比较繁琐。
我们希望windows中访问固定的virtualbox中虚拟机的ip地址,直接访问6379就能访问到redis,直接访问3306就能访问到mysql!并且由于默认虚拟机的ip地址不是固定ip,开发不方便,需要修改Vagrantfile我们想要给虚拟机一个固定的ip地址,windows和虚拟机可以互相ping通。 可以更改Vagrantfile更改虚拟机ip,修改其中的config.vm.network "private_network",ip:"192.168.56.10" ,这个ip需要在windows的ipconfig中查到vitualbox的虚拟网卡ip,然后更改下最后一个数字就行(不能是1,1是我们的主机)。
接着需要重启一下
vagrant,使用vagrant reload命令
虚拟机安装docker
docker可以启动一个容器,每一个容器相当于一个完整的Linux环境,在Docker中安装不同的软件,例如MySQL,Redis,启动两个容器分别安装,两个软件实现相互隔离的效果。
安装docker参照官方文档: docs.docker.com/engine/inst…,安装docker之前首先卸载之前的版本。
#卸载系统之前的docker
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
接着执行以下命令,下载一些配置
sudo yum install -y yum-utils
# 配置镜像
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
#启动docker
sudo systemctl start docker
#查看docker是否安装成功
docker -v
#查看docker镜像仓库
sudo docker images
设置docker开机自启动,只要linux启动之后docker就会启动,不需要执行上面的sudo systemctl start docker命令了
# 设置开机自启动
sudo systemctl enable docker
docker配置镜像加速
配置docker阿里云镜像加速,因为如果每次下载镜像都去国外的网站下载比较慢
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://9rzcevsn.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
docker安装MySQL
下载mysql镜像
sudo docker pull mysql:5.7
创建实例容器并启动
# --name指定容器名字 -v目录挂载 -p指定端口映射 -e设置mysql参数 -d后台运行
sudo docker run -p 3306:3306 --name mysql \
-v /mydata/mysql/log:/var/log/mysql \
-v /mydata/mysql/data:/var/lib/mysql \
-v /mydata/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
上面参数说明
-p 3306:3306将容器的3306端口映射到主机即192.168.56.10的3306端口-v /mydata/mysql/log:/var/log/mysql \: 将容器mysql日志文件夹/var/log/mysql挂载到主机即192.168.56.10的/mydata/mysql/log文件夹中,以后访问192.168.56.10的/mydata/mysql/log,就相当于访问容器mysql中的/var/log/mysql文件夹-v /mydata/mysql/data:/var/lib/mysql \:将容器mysql数据文件夹/var/lib/mysql挂载到主机即192.168.56.10的/mydata/mysql/data文件夹中,以后访问192.168.56.10的/mydata/mysql/data,就相当于访问容器mysql中的/var/lib/mysql文件夹-v /mydata/mysql/conf:/etc/mysql \:将容器mysql配置文件夹/etc/mysql挂载到主机即192.168.56.10的/mydata/mysql/conf文件夹中,以后访问192.168.56.10的/mydata/mysql/conf,就相当于访问容器mysql中的/etc/mysql文件夹-e MYSQL_ROOT_PASSWORD=root \:表示设置mysql中的root用户的密码为root-d mysql:5.7:表示以后台方式运行mysql:5.7镜像
执行上面的命令之前需要切换为root用户才有权限执行上面的命令,执行su root命令,接着输入密码vagrant
#切换为root用户
su root
接着执行上面的命令,然后查看docker正在运行中的容器
#查看docker正在运行中的容器
docker ps
因为每一个容器都是一个linux操作系统,所以可以进入到咱们刚刚启动的mysql容器中,执行以下命令,即可进入到对应的容器中。
#mysql为刚刚创建容器的名称 -it表示以交互发容方式,bin/bash表示运行bash
docker exec -it mysql bin/bash
接着修改mysql的字符集
#因为有目录映射,所以我们可以直接在镜像外执行
vi /mydata/mysql/conf/my.conf
#修改字符集
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
#重新启动
docker restart mysql
docker安装Redis
下载redis镜像
docker pull redis
创建redis容器
# 在虚拟机中
mkdir -p /mydata/redis/conf
touch /mydata/redis/conf/redis.conf
docker pull redis
#运行redis容器
docker run -p 6379:6379 --name redis \
-v /mydata/redis/data:/data \
-v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis redis-server /etc/redis/redis.conf
# 直接进去redis客户端。
docker exec -it redis redis-cli
默认是不持久化的,即数据只是存储在内存中,当redis重启启动之后,原先的数据会丢失。所以在配置文件中输入appendonly yes,设置redis持久化。
vim /mydata/redis/conf/redis.conf
# 插入下面内容
appendonly yes
修改完重启redisdocker restart redis,然后以bash交互方式进去redis容器中,即docker -it redis redis-cli
#重启redis
docker restart redis
#设置redis容器在docker启动的时候启动
docker update redis --restart=always
接着我们可以用redis可视化工具redis desktop manager连接redis
开发工具&环境安装配置
一、maven3.6.1
配置maven使用阿里云镜像
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus-aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
配置jdk1.8编译项目
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
接着打开idea配置maven
使用IDEA安装MyBatisX插件,该插件能够通过方法快速定位到MyBatis映射文件
使用VsCode安装如下插件
- Auto Close Tag
- Auto Rename Tag
- Chinese
- ESlint
- HTML CSS Support
- HTML Snippets
- JavaScript ES6
- Live Server
- open in brower
- Vetur
下载git并配置
首先下载git并安装,然后打开git bash,设置用户签名
# 配置用户名
git config --global user.name "username" //(名字,随意写)
# 配置邮箱
git config --global user.email "55333@qq.com" // 注册账号时使用的邮箱
接着需要设置ssh免密登录gitee,我们先把本地的.ssh目录删了
# 配置ssh免密登录,进入git bash
ssh-keygen -t rsa -C 自己的邮箱
#三次回车后生成了密钥:公钥私钥
cat ~/.ssh/id_rsa.pub
然后查看发现当前目录重新生成了.ssh目录了
接着打开gitee中的settings
复制公钥文件id_rsa.pub的内容,打开
项目结构创建
首先点击创建仓库
仓库信息如下
从码云中把项目克隆下来
首先在这个项目创建module
首先选择spring-web还有openfeign
依次创建出以下服务模块
- 商品服务
gulimall-product - 存储服务
gulimall-ware - 订单服务
gulimall-order - 优惠券服务
gulimall-coupon - 用户服务
gulimall-member
然后随意复制一个module中的pom.xml文件作为父项目gulimall_hs的pom文件
父项目的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hs.gulimall</groupId>
<artifactId>gulimall_hs</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gulimall_hs</name>
<description>聚合服务</description>
<packaging>pom</packaging>
<modules>
<module>gulimall-coupon</module>
<module>gulimall-member</module>
<module>gulimall-order</module>
<module>gulimall-product</module>
<module>gulimall-ware</module>
</modules>
</project>
然后将父项目添加到后侧的maven project管理中
接着修改父项目的.gitignore,把小项目里的垃圾文件在提交的时候忽略掉,比如HELP.md。。。
**/mvnw
**/mvnw.cmd
**/.mvn
**/target/
.idea
**/.gitignore
然后将新增的文件加入git管理
接着使用IDEA安装gitee插件,然后把上面初始化项目修改提交到远程仓库中
初始化数据库
设置MySQL与Redis自启动
docker update redis --restart=always
docker update mysql --restart=always
搭建后台管理系统
使用人人开源的两个项目,如下图
使用git bash将这两个项目克隆下来
`
git clone https://gitee.com/renrenio/renren-fast.git
git clone https://gitee.com/renrenio/renren-fast-vue.git
先把后台项目renren-fast中的.git文件删除掉
将后台项目renren-fast导入到gulimall_hs中
修改父项目的pom.xml文件,将renren-fast加入到其中
然后复制renren-fast中的mysql.sql文件,里面是后台管理系统的数据库信息
创建一个新的数据库名gulimall-admin,然后执行一下上面的mysql.sql脚本
接着修改renren-fast项目中的application-dev.yml文件中国的数据库连接信息
安装node(官网下载,傻瓜式安装即可),node需要配合npm使用,因为nom为包管理工具(简单理解就是通过npm下载包依赖),然后配置npm的镜像仓库地址。直接cmd执行如下脚本
npm config set registry http://registry.npm.taobao.org/
接着同样我们把项目renren-fast-vue中的.git文件删除掉,然后用VsCode打开
,然后去VScode的项目终端中输入 npm install,是要去拉取依赖(package.json类似于pom.xml的dependency)
然后运行renren-fast项目
接着使用npm install运行renren-fast-vue项目
访问http://localhost:8001/#/login,
前端项目账号跟密码都是admin
逆向工程搭建
我们可以通过renren-generator为我们的服务生成基本的增删改查代码
首先克隆人人开源中的renren-generator工程
git clone https://gitee.com/renrenio/renren-generator.git
下载到桌面后,同样把里面的.git文件删除,然后移动到我们IDEA项目目录中,同样配置好父项目pom.xml
<modules>
<module>gulimall-coupon</module>
<module>gulimall-member</module>
<module>gulimall-order</module>
<module>gulimall-product</module>
<module>gulimall-ware</module>
<module>renren-fast</module>
<module>renren-generator</module>
</modules>
在maven中刷新一下,让项目名变粗体,稍等下面进度条完成。在逆向工程
renren-generator中的application.yml中的数据库信息,可以设置我要给哪个数据库里面的表生成基本的增删改查代码。
首先我们先给gulimall-pms数据库生成增删改查代码,所以修改application.yml
url: jdbc:mysql://192.168.56.10:3306/gulimall-pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root
然后修改generator.properties(这里乱码的百度IDEA设置properties编码)
# 主目录
mainPath=com.hs
#包名
package=com.hs.gulimall
#模块名
moduleName=product
#作者
author=huangshuai
#email
email=1002124115@qq.com
#表前缀(类名不会包含表前缀) # 我们的pms数据库中的表的前缀都pms
# 如果写了表前缀,每一张表对于的javaBean就不会添加前缀了
tablePrefix=pms_
运行逆向工程 RenrenApplication 逆向工程,
访问
localhost:80,如下图所示
在网页上下方点击每页显示50个(pms库中的表),以让全部都显示,然后点击全部,点击生成代码。下载了压缩包。
接着进行解压
把复制main文件夹放到gulimall-product替换原有的main文件夹。
先删除掉
resource下生成的src目录
我们查看生成的一个
service实现类,发现还有些依赖没有
所以我们创建出一个公共的gulimall-common模块,以后需要的公共依赖或者公共的类都添加到该模块下,然后其他模块想要使用,就依赖该模块
添加
pom文件依赖如下:
<!-- mybatisPLUS-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
<!--简化实体类,用@Data代替getset方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<!-- httpcomponent包。发送http请求 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.13</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
然后在product项目中的pom.xml中加入下面内容, 依赖common模块
<dependency>
<groupId>com.atguigu.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
此时我们发现service实现类中还缺少几个工具类,这些工具类都在renren-fast项目中,我们复制出来放到gulimall-common中com.hs.common.utils包中(手动创建出包名)
此时还差一个Constant类和xss文件夹中的类,也是一样从renren-fast项目中复制到gulimall-common中
此时我们发现gulimall-product模块中只有controller中的注解报错了,先注释掉注解
注释掉gulimall-product模块中controller类的//import org.apache.shiro.authz.annotation.RequiresPermissions;,他是shiro的东西。可以修改逆向工程中的生成controller类的模板,生成controller类的时候不生成上面的shiro注解,全部注释掉该类注解,如下图所示
重新运行逆向工程,重新生成controller,替换掉之前的controller目录,替换之后的controller不再报错了。
测试逆向工程
测试与整合商品服务里的mybatisplus,mp.baomidou.com/guide/quick…配置
在common的pom.xml中导入
<!-- 数据库驱动 https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<!--tomcat里一般都带-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
删掉common里xss/xssfiler和XssHttpServletRequestWrapper,在gulimall-product项目的resources目录下新建application.yml
#配置数据源
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.56.10:3306/guli_pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.jdbc.Driver
# MapperScan
# sql映射文件位置
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
#配置主键自增
id-type: auto
然后在主启动类上加上注解@MapperScan() ,告诉mapper接口路径在哪儿
@MapperScan("com.atguigu.gulimall.product.dao")
@SpringBootApplication
public class gulimallProductApplication {
public static void main(String[] args) {
SpringApplication.run(gulimallProductApplication.class, args);
}
}
然后去测试,先通过下面方法给数据库添加内容
@SpringBootTest
public class gulimallProductApplicationTests {
@Autowired
BrandService brandService;
@Test
public void contextLoads() {
BrandEntity brandEntity = new BrandEntity();
brandEntity.setDescript("哈哈1哈");
brandEntity.setName("华为");
brandService.save(brandEntity);
System.out.println("保存成功");
}
}
同样的道理,依次生成其他微服务模块的增删改查代码
SpringCloud Alibaba
SpringCloud Alibaba致力于提供微服务开发的一站式解决方案,此项目包含开发分布式应用微服务的必需组件,方便开发者通过SpringCloud变成模型轻松使用这些组件开开发分布式应用服务。
依托SpringCloud Alibaba,您只需要添加一些注解和少量配置,就可以将SpringCloud应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
- 注册中心:
nacos - 配置中心:
nacos - 网关:
gateway - 远程调用:
netflix把feign闭源了,spring cloud开了个openFeign
因为我们所有的服务都是微服务项目,为了便于依赖管理,我们在gulimall-common模块中的pom.xml文件中加入如下内容:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Nacos注册中心
nacos是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,他是使用java编写,需要依赖java环境。nacos文档地址:nacos.io/zh-cn/docs/…
一、下载nacos-server
二、安装启动nacos
下载–解压安装nacos,双击bin/startup.cmd。http://localhost:8848/nacos/#/login 账号密码nacos
三、添加Nacos依赖:放到gulimall-common的pom.xml中,不写版本是因为里面有了版本管理
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
四、使用
@EnableDiscoveryClient 注解开启服务注册与发现功能
@SpringBootApplication
@EnableDiscoveryClient
public class GulimallCouponApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallCouponApplication.class, args);
}
}
五、最后application.yml内容,配置服务注册中心地址:127.0.0.1:8848和当前模块名字
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.56.10:3306/gulimall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
cloud:
nacos:
discovery:
#指定nacos地址,即注册中心地址
server-addr: 127.0.0.1:8848
#指定服务名称
application:
name: gulimall-coupon
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
server:
port: 7000
六、启动对应的模块,查看nacos中的服务列表信息,如下图所示
Feign(远程调用)
声明式远程调用,feign是一个声明式的HTTP客户端,他的目的就是让远程调用更加简单。给远程服务发的是HTTP请求。
例子:会员服务想要远程调用优惠券服务,只需要给会员服务里引入openfeign依赖,他就有了远程调用其他服务的能力。
一、首先引入feign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.我们之前在member的pom.xml已经引用过了(微服务)。在coupon中修改如下的内容,即添加一个测试接口用于其他服务的远程调用测试
@RequestMapping("coupon/coupon")
public class CouponController {
@Autowired
private CouponService couponService;
@RequestMapping("/member/list")
public R membercoupons(){ //全系统的所有返回都返回R
// 应该去数据库查用户对于的优惠券,但这个我们简化了,不去数据库查了,构造了一个优惠券给他返回
CouponEntity couponEntity = new CouponEntity();
couponEntity.setCouponName("满100-10");//优惠券的名字
return R.ok().put("coupons",Arrays.asList(couponEntity));
}
3.在member模块中编写Feign接口,如下:
@FeignClient("gulimall-coupon") //告诉spring cloud这个接口是一个远程客户端,要调用coupon服务(nacos中找到),具体是调用coupon服务的/coupon/coupon/member/list对应的方法
public interface CouponFeignService {
// 远程服务的url
@RequestMapping("/coupon/coupon/member/list")//注意写全优惠券类上还有映射//注意我们这个地方不是控制层,所以这个请求映射请求的不是我们服务器上的东西,而是nacos注册中心的
public R membercoupons();//得到一个R对象
}
4.在member的配置类上加注解@EnableDiscoveryClient,告诉member是一个远程调用客户端,member要调用东西的
/*
* 想要远程调用的步骤:
* 1 引入openfeign
* 2 编写一个接口,接口告诉springcloud这个接口需要调用远程服务
* 2.1 在接口里声明@FeignClient("gulimall-coupon")他是一个远程调用客户端且要调用coupon服务
* 2.2 要调用coupon服务的/coupon/coupon/member/list方法
* 3 开启远程调用功能 @EnableFeignClients,要指定远程调用功能放的基础包
* */
@EnableFeignClients(basePackages="com.atguigu.gulimall.member.feign")//扫描接口方法注解
@EnableDiscoveryClient
@SpringBootApplication
public class gulimallMemberApplication {
public static void main(String[] args) {
SpringApplication.run(gulimallMemberApplication.class, args);
}
}
5.然后我们在member的控制层写一个测试请求
@RestController
@RequestMapping("member/member")
public class MemberController {
@Autowired
private MemberService memberService;
@Autowired
CouponFeignService couponFeignService;
@RequestMapping("/coupons")
public R test(){
MemberEntity memberEntity = new MemberEntity();
memberEntity.setNickname("会员昵称张三");
R membercoupons = couponFeignService.membercoupons();//假设张三去数据库查了后返回了张三的优惠券信息
//打印会员和优惠券信息
return R.ok().put("member",memberEntity).put("coupons",membercoupons.get("coupons"));
}
6.重新启动服务,在浏览器中访问http://localhost:8000/member/member/coupons 响应的数据如下:
{
"msg":"success",
"code":0,
"coupons":[
{"id":null,"couponType":null,"couponImg":null,"couponName":"满100-10","num":null,"amount":null,"perLimit":null,"minPoint":null,"startTime":null,"endTime":null,"useType":null,"note":null,"publishCount":null,"useCount":null,"receiveCount":null,"enableStartTime":null,"enableEndTime":null,"code":null,"memberLevel":null,"publish":null}
],
"member":{"id":null,"levelId":null,"username":null,"password":null,"nickname":"会员昵称张三","mobile":null,"email":null,"header":null,"gender":null,"birth":null,"city":null,"job":null,"sign":null,"sourceType":null,"integration":null,"growth":null,"status":null,"createTime":null}
}
openFeign报错如下:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'memberController': Unsatisfied dependency expressed through field 'couponFeignService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.atguigu.gulimall.member.feign.CouponFeignService': Unexpected exception during bean creation; nested exception is java.lang.IllegalStateException: No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?
错误参考帖子:blog.csdn.net/weixin_4572…
nacos配置中心
我们还可以用nacos作为配置中心。配置中心的意思是不在application.properties等文件中配置了,而是放到nacos配置中心公用,这样无需每台机器都改。
1.common中添加依赖 nacos配置中心
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2.在coupons项目中创建/src/main/resources/bootstrap.properties ,这个文件是springboot里规定的,他优先级别application.properties高。
#指定微服务名称
spring.application.name=gulimall-coupon
#指定配置中心的地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
3.还是原来我们使用配置的方式,只不过优先级变了,所以匹配到了nacos的配置
还是配合@Value注解使用。读取工程中配置文件中的配置项的值
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
@Autowired
private CouponService couponService;
@Value("${coupon.user.name}")//从application.properties中获取//不要写user.name,他是环境里的变量
private String name;
@Value("${coupon.user.age}")
private Integer age;
@RequestMapping("/test")
public R test(){
return R.ok().put("name",name).put("age",age);
}
但是如果想要修改工程配置文件中配置项的值肿么办?实际生产中不能重启应用。在coupon的控制层上加@RefreshScope
@RefreshScope
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
@Autowired
private CouponService couponService;
@Value("${coupon.user.name}")//从application.properties中获取//不要写user.name,他是环境里的变量
private String name;
@Value("${coupon.user.age}")
private Integer age;
@RequestMapping("/test")
public R test(){
return R.ok().put("name",name).put("age",age);
}
4.浏览器去nacos里的配置列表,点击+号,data ID:gulimall-coupon.properties,配置
重启后(让注解生效),在nacos浏览器里修改配置,修改就可以观察到能动态修改了
nacos的配置内容优先于项目本地的配置内容。
综上nacos作为配置中心步骤总结如下:
/**
* nacos配置中心步骤
* 1)添加nacos作为配置中心的依赖
* 2)在工程中创建一个bootstrap.properties文件,该文件会优先加载于application.properties/yml
* 在该文件中配置微服务名称(nacos中的微服务名称),并且指定配置中心的地址
* spring.application.name=gulimall-coupon
* spring.cloud.nacos.config.server-addr=127.0.0.1:8848
*3)需要给配置文件中心添加一个叫数据集(Data Id)gulimall-coupon.properties,默认规则:应用名称.properties
*4)给应用.properties添加任何配置
*5)动态获取配置
* 在对应的Controller类上面添加注解 @RefreshScope:动态获取并且刷新配置
* @value("${配置项的名称}"),获取到配置
* 如果配置中心和当前的工程中的配置文件都配置了相同的配置项,优先使用配置中心中的配置
*/
@SpringBootApplication
@EnableDiscoveryClient
public class GulimallCouponApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallCouponApplication.class, args);
}
}
Nacos配置中心进阶
命名空间:用作配置隔离。(一般每个微服务一个命名空间)
- 默认public。默认新增的配置都在public空间下
- 开发、测试、开发可以用命名空间分割。properties每个空间有一份。
- 在bootstrap.properties里配置(测试完去掉,学习不需要) 简单演示如下:
接着在gulimall-coupon工程中的bootstrap.properties中指定上面新建的命名空间ID,项目启动就会从该命名空间下读取gulimall-coupon.properties配置文件的信息。注意指定namespace命名空间不能直接使用名称,例如prod,必须使用prod对应的唯一id
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=16c5c604-e1cf-4a45-89b4-12961e856e0c
controller中的测试代码如下:
@Value("${coupon.user.name}")//从application.properties中获取//不要写user.name,他是环境里的变量
private String name;
@Value("${coupon.user.age}")
private Integer age;
@RequestMapping("/test")
public R test(){
return R.ok().put("name",name).put("age",age);
}
启动项目,查看测试效果如下图所示
当然也可以为每个微服务配置一个命名空间,微服务互相隔离,看怎么设计
配置集:一组相关或不相关配置项的集合。即一个配置文件中会有很多的配置项,例如配置数据源的,配置跟mybatis整合的,这些就是配置集。
配置集ID:类似于配置文件名,即Data ID,配置集ID默认规则:应用名称.properties。即默认情况下,nacos会默认使用默认命名空间public下面DEFAULT_GROUP分组下面的应用名称.properties配置文件。
配置分组:默认所有的配置集都属于DEFAULT_GROUP。双十一,618的优惠策略改分组即可
简单演示如下:
修改gulimall-coupon工程中的bootstrap.properties文件,指定分组,如下
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=16c5c604-e1cf-4a45-89b4-12961e856e0c
spring.cloud.nacos.config.group=TEST_DROUP
启动项目测试结果如下:
一般设计的最终方案:每个微服务创建自己的命名空间,然后使用配置分组区分环境(dev/test/prod)
加载多配置集:很多时候咱们的配置文件中配置的东西太多,配置文件过于庞大,我们要把原来application.yml里的内容都分文件抽离出去。比如配置跟mybatis整合的分离出去mybatis.yml,配置数据源的datasource.yml等等,我们在nacos里创建好后,在coupons里指定要导入的配置即可bootstrap.properties修改如下:
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# 可以选择对应的命名空间 # 写上对应环境的命名空间ID
spring.cloud.nacos.config.namespace=b176a68a-6800-4648-833b-be10be8bab00
# 更改配置分组
spring.cloud.nacos.config.group=dev
#新版本不建议用下面的了
#spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml
#spring.cloud.nacos.config.ext-config[0].group=dev
#spring.cloud.nacos.config.ext-config[0].refresh=true
#spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml
#spring.cloud.nacos.config.ext-config[1].group=dev
#spring.cloud.nacos.config.ext-config[1].refresh=true
#spring.cloud.nacos.config.ext-config[2].data-id=other.yml
#spring.cloud.nacos.config.ext-config[2].group=dev
#spring.cloud.nacos.config.ext-config[2].refresh=true
spring.cloud.nacos.config.extension-configs[0].data-id=datasource.yml
spring.cloud.nacos.config.extension-configs[0].group=dev
spring.cloud.nacos.config.extension-configs[0].refresh=true
spring.cloud.nacos.config.extension-configs[1].data-id=mybatis.yml
spring.cloud.nacos.config.extension-configs[1].group=dev
spring.cloud.nacos.config.extension-configs[1].refresh=true
spring.cloud.nacos.config.extension-configs[2].data-id=other.yml
spring.cloud.nacos.config.extension-configs[2].group=dev
spring.cloud.nacos.config.extension-configs[2].refresh=true
上述配置中config是一个数组,数组中每一个元素就是一个配置集,即比如配置mybatis整合的就是config[0].配置数据源配置集的就是config[1]。
具体配置步骤略,启动项目,查看日志,输出内容有
2020-06-25 00:04:13.677 WARN 17936 --- [ main] c.a.c.n.c.NacosPropertySourceBuilder : Ignore the empty nacos configuration and get it based on dataId[gulimall-coupon] & group[dev]
2020-06-25 00:04:13.681 INFO 17936 --- [ main] b.c.PropertySourceBootstrapConfiguration :
Located property source: [
BootstrapPropertySource {name='bootstrapProperties-gulimall-coupon.properties,dev'},
BootstrapPropertySource {name='bootstrapProperties-gulimall-coupon,dev'},
BootstrapPropertySource {name='bootstrapProperties-other.yml,dev'},
BootstrapPropertySource {name='bootstrapProperties-mybatis.yml,dev'},
BootstrapPropertySource {name='bootstrapProperties-datasource.yml,dev'}]
网关gateway
动态上下线:发送请求需要知道商品服务的地址,如果商品服务器有123服务器,1号掉线后,还得改,所以需要网关动态地管理,他能从注册中心中实时地感知某个服务上线还是下线。【先通过网关,网关路由到服务提供者】
拦截:请求也要加上询问权限,看用户有没有权限访问这个请求,也需要网关。
所以我们使用spring cloud的gateway组件做网关功能。
网关是请求流量的入口,常用功能包括路由转发,权限校验,限流控制等。springcloud gateway取代了zuul网关。
参考手册:cloud.spring.io/spring-clou…
三大核心概念:
-
Route: 发一个请求给网关,网关要将请求路由到指定的服务。路由有id,目的地uri,断言的集合,匹配了断言就能到达指定位置,
-
Predicate断言: 就是java里的断言函数,匹配请求里的任何信息,包括请求头等。根据请求头路由哪个服务
-
Filter: 过滤器请求和响应都可以被修改。客户端发请求给服务端。中间有网关。先交给映射器,如果能处理就交给handler处理,然后交给一系列filer,然后给指定的服务,再返回回来给客户端。
一句话:当请求发送到网关时,首先根据断言判断是否能路由,如果可以路由,则将请求交给过滤器链,最终到达目标服务;请求的响应也要先经过过滤器链,然后才给返回
创建,使用initilizer,Group:com.atguigu.gulimall,Artifact: gulimall-gateway,package:com.atguigu.gulimall.gateway。 搜索gateway选中。pom.xml里加上common依赖, 修改jdk版本,
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>guli-mall</artifactId>
<groupId>com.zsy</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mall-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>API网关</description>
<name>mall-gateway</name>
<dependencies>
<dependency>
<groupId>com.zsy</groupId>
<artifactId>mall-common</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
主启动类,下面在@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})过滤掉数据源信息,这是因为guliall-gateway工程依赖common,common中存在mybatis依赖,需要配置数据源,如果不配置的话启动项目就会报错,所以把数据源信息去掉,项目启动就不会报错
@EnableDiscoveryClient
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MallGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(MallGatewayApplication.class, args);
}
}
配置文件application.yaml
spring:
application:
name: mall-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.163.131:8848
server:
port: 88
bootstrap.yaml,读取配置中心的配置,在配置中心为每个分组创建各自的命名空间。
spring:
application:
name: mall-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
namespace: 07abe11f-3ead-4ae4-add6-71e8f129bfb9
配置gateway路由规则
spring:
application:
name: mall-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.163.131:8848
gateway:
routes:
#Query A 参数有A就行,Query B,C 参数B的值为C即可
#实现针对于“http://localhost:88/hello?url=baidu”,转发到“https://www.baidu.com/hello”,
#针对于“http://localhost:88/hello?url=qq”的请求,转发到“https://www.qq.com/hello”
- id: baidu_route
uri: https://www.baidu.com
predicates:
- Query=url,baidu
- id: github_route
uri: https://www.github.com
predicates:
- Query=url,github
server:
port: 88
启动项目分别请求:
http://localhost:88/s?wd=Ep%E6%B5%81%E8%8B%8F&url=baidu
会分别跳转到百度和github 表示成功。
网关底层使用的是Netty