目标
1.页面改造和功能开发(搜索页面,用户信息,用户修改页面)
2.单机登录改为分布式登录
3.标签的整理,细节的优化
1.前端页面跳转传值
1.query => url searchParams ,url后附加参数,传递的值长度有限
2.vuex(全局状态管理)搜索页将关键词塞到状态中,搜索结果页从状态中取值
首先新建一个搜索结果页面,并在config/route.ts
中配置好路由
import SearchResultPage from "../pages/SearchResultPage.vue";
const routes = [ { path: '/user/list', component:SearchResultPage }]
在SearchPage.vue
页面中定义一个按钮,添加一个点击事件,并添加对应的事件的方法
<van-button type="primary" @click="doSearchResult">搜索</van-button>
//执行搜索后
const doSearchResult = () =>{
router.push({
path:'/user/list',
query:{
tags:activeIds.value
}
})
}
选择标签,然后点击按钮测试
发现选中的标签参数已经被获取到
优化搜索按钮
2.初步实现标签搜索功能
2.1当我们点击搜索时需要获取到所搜索的用户列表,先做一个模板,展示一下搜索结果页面在Page文件夹下添加SearchResultPage.vue
<template>
<van-card
v-for="user in userList"
:desc="user.profile"
:title="`${user.username} (${user.planetCode})`"
:thumb="user.avatarUrl"
>
<template #tags>
<van-tag plain type="danger" v-for="tag in user.tags" style="margin-right: 8px;margin-top: 8px">
{{ tag }}
</van-tag>
</template>
<template #footer>
<van-button size="mini">联系我</van-button>
</template>
</van-card>
</template>
<script setup>
import {ref} from "vue";
import {useRoute} from "vue-router";
const route =useRoute();
const { tags }=route.query;
const mockUser={
id: 12345,
username: 'coderhyx',
userAccount: '12312',
profile:'是ikun,也是精神小伙,原神启动,原来你也玩原神。',
avatarUrl: 'http://images/2023/07/31/pic.md.jpg',
gender:0,
phone: 12122223333,
email: '455dssds@qq.com',
userRole: 0,
planetCode: '1234',
tags:['java','emo','打工中','python','开心'],
createTime: new Date(),
}
const userList = ref([mockUser])
</script>
<style scoped>
</style>
效果展示
2.2在UserController添加接口
@GetMapping("/search/tags")
public BaseResponse<List<User>> searchUserByTags(@RequestParam(required = false) List<String> tagsNameList){
List<User> userList = userService.searchUsersByTags(tagsNameList);
if(CollectionUtils.isEmpty(tagsNameList)){
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
return ResultUtils.success(userList);
}
2.3测试一下
2.4现在开始让前端发请求,先整合axios
npm install axios
自定义axios
当我们点击搜索按钮之后需要跳转到搜索结果页面并发出请求,获取到后端传来的数据
定义搜索结果页面的钩子函数,在页面加载完成就发请求
onMounted(()=>{
myAxios.get('/user/search/tags', {
params: {
tagNameList: tags
}
})
.then(function (response) {
console.log('/user/search/tags===>succeed',response);
Toast.success('请求成功')
})
.catch(function (error) {
console.error('/user/search/tags===>error',error);
Toast.fail('请求失败')
});
})
后端接口上添加注解
@CrossOrigin(origins = { "http://localhost:3000" })
跨域问题解决
新问题,参数格式不对
1:28
请求格式不对 axios get数组传数组后端不认识,需要序列化
更新搜索结果页面添加代码
<template>
<van-card
v-for="user in userList"
:desc="user.profile"
:title="`${user.username} (${user.planetCode})`"
:thumb="user.avatarUrl"
>
<template #tags>
<van-tag plain type="danger" v-for="tag in user.tags" style="margin-right: 8px;margin-top: 8px">
{{ tag }}
</van-tag>
</template>
<template #footer>
<van-button size="mini">联系我</van-button>
</template>
</van-card>
</template>
<script setup>
import {onMounted, ref} from "vue";
import {useRoute} from "vue-router";
import myAxios from "../plugins/myAxios";
import {Toast} from "vant";
import qs from 'qs';
const route =useRoute();
const { tags }=route.query;
onMounted(()=>{
myAxios.get('/user/search/tags', {
params: {
tagsNameList: tags
},
paramsSerializer:params => {
return qs.stringify(params,{indices:false})
}
})
.then(function (response) {
console.log('/user/search/tags===>succeed',response);
Toast.success('请求成功')
})
.catch(function (error) {
console.error('/user/search/tags===>error',error);
Toast.fail('请求失败')
});
})
const mockUser={
id: 12345,
username: 'coderhyx',
userAccount: '12312',
profile:'是ikun,也是精神小伙,原神启动,原来你也玩原神。',
avatarUrl: 'http://2023/07/31/pic.md.jpg',
gender:0,
phone: 12122223333,
email: '455dssds@qq.com',
userRole: 0,
planetCode: '1234',
tags:['java','emo','打工中','python','开心'],
createTime: new Date(),
}
const userList = ref([mockUser])
</script>
<style scoped>
</style>
重新测试
后台也能接受到参数
优化代码
发现标签太丑了
再次进行优化
当搜索结果为空时需要展示空界面
添加一行
<van-empty v-if="!userList||userList.length<1" image="search" description="搜索结果为空" />
最终优化效果
SearchResult.vue完整代码
<template>
<van-card
v-for="user in userList"
:desc="user.profile"
:title="`${user.username} (${user.planetCode})`"
:thumb="user.avatarUrl"
>
<template #tags>
<van-tag plain type="danger" v-for="tag in user.tags" style="margin-right: 8px;margin-top: 8px">
{{ tag }}
</van-tag>
</template>
<template #footer>
<van-button size="mini">联系我</van-button>
</template>
</van-card>
<van-empty v-if="!userList||userList.length<1" image="search" description="搜索结果为空" />
</template>
<script setup >
import {onMounted, ref} from "vue";
import {useRoute} from "vue-router";
import myAxios from "../plugins/myAxios";
import {Toast} from "vant";
import qs from 'qs';
const route =useRoute();
const { tags }=route.query;
const userList = ref([])
onMounted(async () =>{
const userListData= await myAxios.get('/user/search/tags', {
params: {
tagsNameList: tags
},
paramsSerializer:params => {
return qs.stringify(params,{indices:false})
}
})
.then(function (response) {
console.log('/user/search/tags===>succeed',response);
Toast.success('请求成功')
return response.data?.data;
})
.catch(function (error) {
console.error('/user/search/tags===>error',error);
Toast.fail('请求失败')
});
if (userListData){
userListData.forEach(user=>{
if (user.tags){
user.tags = JSON.parse(user.tags);
}
})
userList.value = userListData;
}
})
const mockUser={
id: 12345,
username: 'coderhyx',
userAccount: '12312',
profile:'是ikun,也是精神小伙,原神启动,原来你也玩原神。',
avatarUrl: 'http://images/2023/07/31/pic.md.jpg',
gender:0,
phone: 12122223333,
email: '455dssds@qq.com',
userRole: 0,
planetCode: '1234',
tags:['java','emo','打工中','python','开心'],
createTime: new Date(),
}
</script>
<style scoped>
</style>
ps:展示不了profile个人介绍?别忘了后端的脱敏方法,要添加哦
1:43
3.Session共享
种Session的时候注意范围
比如两个域名
aaa.coderhyx.com
bbb.coderhyx.com
如果要共享cookie,可以种一个更高层的公共域名 coderhyx.com
4.为什么服务器A登录之后,请求发送到服务器B, 不认识该用户?(分布式)
用户在A登录,所以Session(用户登录信息)存在了A上,结果请求B时,B没有用户信息,所以不认识。
如何解决:共享存储,而不是把数据存到单台服务器的内存中
整一个公共存储区去存登录信息
5.如何共享存储Session?
1.Redis(基于内存的K/V数据库),
2.MySQL
3.文件服务器ceph
这里我们选择Redis,因为用户信息的读取,是否登录的判断,及其频繁
5.1.安装redis
电脑安装Redis
安装教程看以前的文档
SpringBoot 引入Redis包
https://mvnrepository.com/
在仓库去找
找与springBoot相匹配的包
5.2.引入redis:能够操作redis
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.6.4</version>
</dependency>
redis管理工具:quickRedis
yml中添加redis配置
5.3.引入spring -session-redis的整合,使得自动将 Session存储到redis中
<!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.6.3</version>
</dependency>
修改SpringSession存储配置spring.session.store-type
默认是nono,表示存储在服务器
我们选择redis,表示在redis中读写
5.4简简单单测试一手
打开terminal命令行
运行一手刚才打包的
java -jar .\get-friend-backend-0.0.1-SNAPSHOT.jar --server.port=8081
mysql连接驱动的问题看下面的
https://stackoverflow.com/questions/76305054/mysql-connector-j-vs-mysql-connector-java-maven-dependency-differences
测试一下,同时启动两个项目
这样我们就完成了多个服务器之间共享一个session数据,也就是最简单的分布式
在redis中也能看到刚才存储的数据