续 迁移注册功能
迁移sys模块的Mapper
上次课我们完成了knows-commons项目的编写和sys模块对它依赖的添加
也就是当前sys模块可以使用commons中的异常类和实体类了
下面我们开始迁移代码
在迁移过程中,有很多类需要重新导包
为了快速完成导包操作,我们可以开启Idea自动导包的功能
勾选java列表中Add unambiguous … 这个选择
这样的话就能自动导入能够确定的类的包了
将VO类和Mapper接口复制到当前sys模块的过程中
需要我们为Mapper接口的内容进行编译错误的修改
有些实体类需要我们手动导入(UserMapper中的三个实体类)
测试Mapper
为了验证我们的迁移和连接数据库的功能
我们在sys模块的测试代码中编写测试代码如下
@Autowired
UserMapper userMapper;
@Test
void contextLoads() {
User user=userMapper.findUserByUsername("st2");
System.out.println(user);
}
保证Nacos启动
如果能够输出学生信息,表示当前所有配置都在正常工作
控制层创建类用于测试
在正式迁移控制层之前,我们先创建一个控制器类
来用于相关前置配置
knows-sys模块创建controller包
包中创建一个类AuthController代码如下
@RestController
@RequestMapping("/v1/auth")
public class AuthController {
// /v1/auth/demo
@GetMapping("/demo")
public String demo(){
return "hello Demo!!!";
}
}
重启服务测试这个路径是否能运行
http://localhost:8001/v1/auth/demo
因为我们添加了Spring-Security的依赖,所以访问这个路径必须登录
用户名是user,密码是启动服务器控制台随机生成的uuid
使用它们登录之后访问即可显示控制器返回的内容
Spring-Security放行设置
因为sys模块添加了Spring-Security的依赖,所以所有医院都需要先登录才能访问
而我们在后面的学习过程中,会专门学习新的微服务版本的验证身份的登录方式, 所以之前单体的Spring-Security登录就不需要使用了
我们可以设置当前项目全部资源全部放行
创建一个security包,包中创建SecurityConfig类
配置代码如下
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 设置全部放行的配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() // 禁用防跨域攻击功能
.authorizeRequests() // 开始设置网站资源授权
.anyRequest().permitAll(); // 任何请求,全部放行
}
}
重启服务sys
当我们再次访问 localhost:8001/v1/auth/demo时就不需要登录了
网关配置sys模块的路由
网关作为外界访问微服务的唯一入口
任何访问我们微服务控制器的请求必须由网关完成路由去访问
像我们的静态资源服务器一样,sys模块也需要配置网关路由设置
转到gateway模块
修改网关的application.yml
routes: #开始路由配置
- id: gateway-sys
uri: lb://sys-service
predicates:
- Path=/v1/**
- id: gateway-resource # 设置路由名称,和其它任何配置无关
# 配置路由目标服务器的名称resource-server
# 必须和nacos中注册的服务器名称一致
# lb:Load Balance的缩写,意思是负载均衡
uri: lb://resource-server
# 下面来定义路由特征:"什么样的路径是访问静态资源服务器的?"
# 下面的定义就是一个通配,凡是满足通配的就是访问静态资源服务器的
predicates:
- Path=/image/**
# 经过了上面的配置效果为:
# 当访问localhost:9000/image/a.jpg时
# 相当于访问了静态资源服务器的同路径资源:
# localhost:8899/image/a.jpg
重启\启动gateway项目
同时保证Nacos和Sys项目正在启动状态
http://localhost:9000/v1/auth/demo查看是否能显示同样的字符串结果
迁移注册的业务逻辑层代码
portal项目中复制注册需要的相关业务逻辑层接口和实现类
IUserService接口中的内容需要手动导入User和Map两个类\接口
UserServiceImpl类比较复杂
暂时无法使用之前编写好的获得问题数和收藏数的功能
现在只能将无法实现的代码暂时删除,今后在寻求解决方案
最终代码如下
@Override
public UserVO getUserVO(String username) {
// 根据用户名查询用户对象
User user=userMapper.findUserByUsername(username);
// 根据用户id查询用户的问题数
// (作业)根据用户id查询用户的收藏数
// 实例化UserVO对象 赋值然后返回
UserVO userVO=new UserVO()
.setId(user.getId())
.setUsername(user.getUsername())
.setNickname(user.getNickname());
// 千万别忘了返回userVO
return userVO;
}
迁移控制层
上图中的两个类
通过导包解决编译错误
还需要将SystemController类的注册代码复制到UserController里
sys模块的UserController没有添加@Slf4j注解
可能导致log对象报错,添加上@Slf4j注解即可
到此为止当前sys模块能够实现注册的路径为
以post方式访问localhost:9000/v1/users/register
注册的发起一定是通过页面来请求的,我们之前编写好的异步注册功能的页面现在在knows-client前端项目中
所以需要将前端项目的axios路径修改一下
前端项目发送注册请求
转到knows-client项目
js文件夹中register.js文件
异步axios请求注册的路径修改为
axios({
method:'post',
url:'http://localhost:9000/v1/users/register',
data:form
})
重启knows-sys模块重启\启动knows-client
保证Nacos和网关gateway正在运行
下面就可以进行注册
访问注册页面并提交注册信息,会发生下面的错误
(可有可能因为页面缓存发生404错误,需要强制清缓存刷新)
但是注册的学生是可以新增到数据库
为什么会有这个现象,原因是前后端分离之后出现的跨域问题
跨域问题
什么是跨域
浏览器为了保证用户在访问网络资源时的安全,都是遵守"同源策略"的
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。目的是出于安全考虑,防止js脚本随意调用其他网站的资源。
如果发起请求的服务器,和做出响应的服务器不"同源",响应是无法返回的
"同源"的示例
前端访问发起的页面为:http://localhost:8080/register.html
我们请求的目标是: http://localhost:9000/v1/users/register
因为端口号不同,所以浏览器视为他们不同源
所以会发送访问限制,浏览器会报错
如何实现跨域
我们简单了解"同源策略"
和现在遇到的"跨域问题"
如果我们想将不同源情况下的请求还能获得响应,就需要使用"跨域"技术
因为当前业界中项目的前后端分离是常态,只要前后端分离,那么前端和后端两个项目一定是不同源的,要想实现正常的访问,一定要跨域,所以跨域操作也属于基本操作了
实现跨域的方式:
- 前端可以通过编写特定代码实现跨域
- 后端可以通过编写特定代码实现跨域
我们作为后端程序员,主要从后端代码给大家完成跨域效果
即使只考虑后端,解决的方式也是多样的
- SpringMvc跨域配置
- 控制器跨域注解
- 过滤器实现跨域
- 拦截器实现跨域
- 其它跨域方式…
实现跨域注册
我们先使用SpringMvc框架提供的跨域配置实现跨域
转到knows-sys模块
security包中,创建一个WebConfig类,来配置跨域
代码如下
// 配置Spring的类都需要添加下面注解
// SpringMvc也是Spring衍生出的框架,也要添加这个注解
@Configuration
public class WebConfig implements WebMvcConfigurer {
// 重写设置跨域的方法
@Override
public void addCorsMappings(CorsRegistry registry) {
// 配置当前项目所有请求都允许跨域
registry.addMapping("/**") // 匹配访问任何资源路径
.allowedOrigins("*") // 允许任何访问源跨域
.allowedMethods("*") // 允许任何方法(get\post)
.allowedHeaders("*"); // 允许任何请求头
}
}
到此为止,跨域设置完成
我们启动所有需要的服务(Nacos\gateway\sys\client)
上面修改了sys,sys需要重启!
再次执行注册,观察是否能够获得响应
创建问答模块
我们上面章节结束完成了第一个小目标:注册
下面我们开始要完成第二个小目标:显示首页标签列表
而显示标签的信息的业务应该编写在问答模块中
创建问答模块knows-faq
这个项目的主要业务就是问题\标签\回答\评论等
什么都不需要勾选直接确认
父子相认
<module>knows-faq</module>
knows-faq子项目依赖
<?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>
<groupId>cn.tedu</groupId>
<artifactId>knows</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>knows-faq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>knows-faq</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>knows-commons</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 验证框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
appliocation.properties配置内容如下
spring.datasource.url=jdbc:mysql://localhost:3306/knows?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
spring.datasource.username=root
spring.datasource.password=root
# ↓↓↓
logging.level.cn.tedu.knows.faq=debug
server.port=8002
spring.application.name=faq-service
spring.cloud.nacos.discovery.server-addr=localhost:8848
最后是SpringBoot启动类
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("cn.tedu.knows.faq.mapper")
public class KnowsFaqApplication {
public static void main(String[] args) {
SpringApplication.run(KnowsFaqApplication.class, args);
}
}
迁移显示标签列表功能
迁移数据访问层
从portal项目中复制上图中的四个接口
除了TagMapper需要手动导包,其它的自动导包就能解决所有编译错误
迁移完成也可以测试一下
@Resource
TagMapper tagMapper;
@Test
void contextLoads() {
// 全查所有标签
List<Tag> tags=tagMapper.selectList(null);
for(Tag t:tags){
System.out.println(t);
}
}
迁移业务逻辑层
只需要导包就可以解决编译错误
迁移控制层
复制之后,除了导包之外
还需要将控制器路径由之前的v1修改为v2
@RequestMapping("/v2/tags")
因为我们要匹配后面配置的路由设置
启动faq项目,保证启动Nacos
输入地址localhost:8002/v2/tags
观察浏览器是否能够显示所有标签(这次访问也是需要先登录的)
设置faq项目的放行和跨域
和sys模块一样,faq模块也是需要将所有路径放行的
同时也是需要支持前端跨域访问
所以可以直接将sys模块的security包直接复制过来
直接复制到faq模块,不需要进行任何修改,直接使用
重启faq模块
刷新浏览器localhost:8002/v2/tags
这次就不需要登录了!
网关路由配置
转到gateway项目
添加faq模块的路由配置信息
application.yml添加配置如下
- id: gateway-faq
uri: lb://faq-service
predicates:
- Path=/v2/**
启动\重启网关gateway
Nacos和Faq也要启动
浏览器访问localhost:9000/v2/tags
观察浏览器是否能够显示所有标签
修改前端请求路径
faq模块配合网关已经实现了访问所有标签的功能
下面要在页面上显示,需要修改knows-client项目请求正确的url路径
js文件夹下tags_nav.js代码中axios请求的url修改为:
axios({
url:'http://localhost:9000/v2/tags',
method:'GET'
})
重启knows-client项目
同时保证Nacos\gateway\faq正在运行
访问学生首页index_student.html
观察问题列表
如果测试出现问题,首先考虑清空浏览器缓存
Redis概述
Redis下载
什么是Redis
Redis是一个缓存数据库
它并不是SpringCloud的组件,和微服务也没有直接关系
是一个能够将数据保存在内存中,并对数据进行高效读写的数据库软件
Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。目前Redis的开发由Redis Labs赞助。根据月度排行网站DB-Engines.com的数据,Redis是最流行的键值对存储数据库。
Redis也是一个软件,和mysql\mariaDB类似,也需要安装后启动才能使用
他们都是数据库,但是Redis把数据保存在内存中
Redis特征
-
Redis是一个缓存数据库,数据保存在内存中,所以处理速度快
经过测试,Redis支持每秒10万次读写操作
-
虽然Redis是内存数据库,但是它支持将内存中的数据备份(保存)到硬盘
如果服务器遇到突发情况(例如断电),内存中的数据会丢失,但是我们仍然从硬盘中将备份的数据恢复到Redis中,尽量减少损失
同时大家要知道,Redis将数据备份到硬盘上的策略有两种AOF和RDB它们可以同时开启,具体的工作原理和效果同学们可以自己查阅相关资料
- Redis使用key-value来保存数据,这样的结构可以让我们将它看作一个java中的Map对象,在业界中还有一些使用key-value保存数据的数据库,我们将这种数据结构的数据库统称为"非关系型数据库"英文:no-sql
- Redis支持保存各种数据类型:
我们会使用到的还是string比较多
- Redis支持分布式的部署,以达到高并发,高可用,高性能的目的
- Redis的竞品软件:memcached
mem:memory cache
为什么需要Redis
之前我们使用java代码定义集合实现了缓存效果
为什么还需要Redis来缓存信息呢
当我们的faq项目并发比较高时,可能需要多台服务器来完成,也就是集群
完成业务时,每个服务器都要保存一个缓存信息,这样的缓存的信息就重复而冗余了,信息越多冗余的越严重
我们希望Redis中只保存一份缓存数据,在服务器需要时,从Redis中获得
这样就减少了内存的冗余,提升了内存的使用效率
Redis的解压安装和运行
将我们下载的压缩包解压后,得到内容如图
redis-server.exe\redis-start.bat这两个文件双击其中任何一个都可以达到启动Redis的效果
但是这个打开的界面一旦关闭Redis就停止了
上面的启动方式每次开机都要运行,而且打开的窗口如果不小心关掉了Redis就停止了
比较麻烦,我们希望Redis能够像mysql一样,每次开机自动启动
-
service-installing.bat 双击能够将Redis进行安装,到当前系统中
-
service-start.bat 双击能够启动当前Redis的服务,默认每次开机
自动启动
-
service-stop.bat 停止服务
-
service-uninstalling.bat 卸载程序
我们只需要运行1,2两个文件
就可以实现每次开机自动启动Redis的效果
我们可以启动redis-cli.exe进行测试
Redis默认端口号:6379
测试方法,在redis-cli.exe运行的窗口中输入指令"info"
观察输出结果
Redis的基本使用
Redis软件支持多种数据类型
我们实际使用Redis的情况,只会使用string类型
string类型可以使用json格式表示对象或集合等信息,足够我们的需求
下面我们就展示一下string类型的基本操作
打开redis-cli.exe文件,在界面中输入
127.0.0.1:6379> set mystr "hello world!!!"
OK
127.0.0.1:6379> get mystr
"hello world!!!"
英文
Origins:源头
memcached:和Redis一样的另一款缓存数据库