微服务(三)-配置中心、迁移注册功能、创建问答模块
1 配置中心
所谓配置中心就是对微服务项目的配置信息进行统一管理的工具,这样多个模块需要相同配置时(例如:数据库连接配置),就不需要每个模块都编写同样的配置了,只需要在配置中心编写一次,所有模块引用即可。配置中心减少了配置冗余,提高了配置的维护性。
我们上次课学习的Nacos就拥有配置中心的功能,配置中心支持各种格式的配置文件:properties、yaml、txt、json、xml。
1.2 Nacos配置中心结构
-
Nacos通过namespace--->group--->dataId来定位数据
-
Nacos软件中可以定义多个namespace(命名空间),不同命名空间中的配置互不干扰,注意:Nacos有一个默认命名空间"public"不能删除。
-
每个namespace中可以定义多个group
-
每个group中可以定义多个DataId(类似:数据库、表、数据的关系)
1.3 将数据库配置保存到注册中心
打开Nacos,选择“配置管理”,进入“配置列表”,其中,public就是默认存在的命名空间(namespace),不可删除和编辑。
新建命名空间:
(1)如果需要新建命名空间,选择Nacos首页的“命名空间”,出现的public为默认存在的命名空间,不可删除和编辑,点击“新建命名空间”可以新建命名空间
(2)对命名空间进行参数设置:命名空间ID(可不填写,默认以UUID生成)、命名空间名、描述
(3)点击确认后,完成命名空间的创建,之后可对命名空间进行查看详情、删除、编辑等操作
回到“配置管理”的“配置列表”,可以看到刚才新建的命名空间:在上方可以进行命名空间的切换,现在处于public命名空间。
新建配置:
(1)点击右侧“+”号,可以新建配置
(2)指定Data ID(配置文件名称)、Group(可以不选,直接默认)、描述(可以不写)、选择对应的配置格式、编写配置内容(随配置格式调整格式,注意下面从knows-portal的application.properties文件中复制过来的配置信息需要把配置门槛下面的portal改为sys)
(3)填写完毕后,点击"发布",选择左侧的箭头返回主页,主页上出现新的配置,之后可对新建的配置进行编辑、删除等操作
1.4 SpringBoot 加载配置文件顺序
我们现在创建的项目都是以SpringBoot框架为基础的,SpringBoot在启动时会加载很多默认配置文件,简化程序员的操作,我们一直接触的就是application.properties可以修改配置,最近又接触了application.yml,知道了这两个配置文件中的内容都会进行加载,那么他俩的关系又是什么呢?
运行顺序上,SpringBoot启动时先解析加载yml文件,然后是properties文件。如果配置了相同的内容,properties会覆盖yml的配置。
实际上还有一组配置文件:
当我们的项目添加了SpringCloud依赖时,会出现一组新的配置文件,这组配置文件会先于application.yml / properties运行,它们的名字是bootstrap.yml / properties。
最终配置文件解析顺序如上图,在bootstrap配置运行时,application还没有运行,我们需要在bootstrap配置中配置注册中心的位置,以便于程序需要application读取时能够读取到。
1.5 添加配置读取配置中心的信息
为了在SpringBoot启动过程中,尽早的加载配置信息,我们要在knows-sys模块的bootstrap级别将nacos中的配置信息加载过来,在application级别来读取使用。
在knows-sys模块中的resources文件夹下创建bootstrap.yml配置文件:
server
SpringBoot启动类添加@EnableDiscoveryClient、@MapperScan注解:
现在可以启动knows-sys项目,观察注册中心是否注册成功,如果注册成功,表示现有启动的配置正常。
(1)启动注册中心nacos,只要不报错就可以,有些INFO信息较多也没关系
(2)启动网关gateway
(3)启动knows-sys项目
输入网址:http://localhost:8848/nacos,访问nacos首页,nacos第一次需要登录(用户名和密码都是nacos),之后再登录时时直接访问首页。
如上图所示,sys-service加载成功!
2 迁移注册功能
为了我们实现迁移注册功能的目标,上面做了一些准备工作。下面要想实现注册,要把knows-portal项目中相关的数据访问层、业务逻辑层和控制层的代码都复制到当前项目knows-sys中。
2.1 复制数据访问层代码
将knows-portal项目下mapper中的ClassroomMapper、UserMapper、UserRoleMapper和vo包中的RegisterVo、UserVo复制到knows-portal项目下新建的mapper、vo包中。
最终效果如下:
在IDEA中按下图添加设置,可以使idea自动导入需要的类或接口(自动导包):
在搜索栏中输入auto,选择Auto Import,在出现的页面选择Add unambiguous imports on the fly前面打√,OK即可,之后就会自动添加确定类的依赖了。
我们复制Vo类到vo包没有问题,但是复制Mapper接口到mapper包发生了异常,异常原因是没有找到对应的实体类,因此需要重新添加实体类。
2.2 创建通用项目knows-commons
像实体类一样,其实还有一些类也都是所有模块都需要的类型。我们可以将实体类和这些所有模块都需要的类型放在一个新建的项目中统一管理,需要的模块直接应用这个项目作为pom的依赖即可。
创建knows-commons:设置下面参数后,什么也不用勾选,直接创建项目
父子相认:父项目knows中添加子项目module:knows-commons
<module>knows-commons</module>
子项目knows-commons的pom.xml:进行父子相认,去除无关依赖和配置,添加mybatis-plus依赖(单纯使用,不启动)
这个项目无需配置其它内容,刷新maven。
将knows-portal项目的model包、exception包复制到knows-commons项目下,效果如下:
删除knows-commons项目下的SpringBoot启动类
删除knows-commons项目下的test测试文件夹
我们的commons项目现在就可以使用了,使用方式:在需要的模块中添加它的依赖就可以了。
转到knows:在pom.xml中添加对cn.tedu.knows.commons依赖的版本管理
转到knows-sys模块:解除pom.xml文件中对cn.tedu.knows.commons依赖的注释
处理mapper接口中的各种编译错误,绝大多数都是需要引入正确的包,先删除全部import导入的包,IDEA会自动加载相关类或接口,加载完毕后,对仍然报错的位置进行指定包重新导入即可。
2.3 测试导入的Mapper
Mapper接口已经迁移到knows-sys模块中,我们要测试调用其中的方法,保证所有配置在正常运作。
在knows-sys模块的test文件夹下,添加测试代码如下:
package cn.tedu.knows.sys;
import cn.tedu.knows.commons.model.User;
import cn.tedu.knows.sys.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
输出结果如下:
如果运行顺利,表示一切正常!
报错如下:每次测试均出现这个错误,可能是某些资源未关闭,但也不影响后面运行!!!
2.4 迁移控制层
在knows-sys项目下创建controller包,包中创建一个类用于测试,AuthController代码如下:
package cn.tedu.knows.sys.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
启动服务,输入上面控制器方法的路径,登录之后就可以显示返回的字符串了(登录时用户名:user、密码:idea控制台随机生成的密码)。(启动的服务有:nacos、gateway、knows-sys)
登录页面:
测试结果:
2.5 网关路由配置
我们上面的测试使用的是8002端口,正式开发时需要使用网关路由,下面配置网关路由:
转到gateway模块:在application.yml文件中修改如下:
server
经过这个配置,我们现在就可以通过localhost:9000来访问knows-sys模块中的控制器方法了。具体路径如下:http://localhost:9000/v1/auth/demo。如果要求登录,就继续输入用户名:user、密码:idea控制台中的密码,登录之后访问。
测试效果如下:(启动的服务有:nacos、gateway、knows-sys)
由于每次测试还要登录太麻烦了,我们可以编写一个Spring-Security框架的放行设置:
转到knows-sys模块:创建security包,包中创建SecurityConfig类,类中编写放行全部请求的代码如下:
package cn.tedu.knows.sys.security;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
再次启动服务,访问资源就不需要登录了!(启动的服务有:nacos、gateway、knows-sys)
2.6 迁移业务逻辑层
Mapper测试通过,控制器也路由配置也成功了,下面要开始迁移service,复制knows-portal项目中service包中UserServiceImpl、IUserService到knows-sys的对应路径,最终效果如下:
IUserService复制过来直接重新导包即可,UserServiceImpl类有些代码需要删除,最后保留方法如下:
package cn.tedu.knows.sys.service.Impl;
import cn.tedu.knows.commons.exception.ServiceException;
import cn.tedu.knows.commons.model.Classroom;
import cn.tedu.knows.commons.model.User;
import cn.tedu.knows.commons.model.UserRole;
import cn.tedu.knows.sys.mapper.ClassroomMapper;
import cn.tedu.knows.sys.mapper.UserMapper;
import cn.tedu.knows.sys.mapper.UserRoleMapper;
import cn.tedu.knows.sys.service.IUserService;
import cn.tedu.knows.sys.vo.RegisterVo;
import cn.tedu.knows.sys.vo.UserVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* <p>
* 服务实现类
* </p>
*
* @author tedu.cn
* @since 2021-08-23
*/