心链 — 伙伴匹配系统
搜索详情页面
之前前端的代码写到了搜索页面可以挑选搜索标签,并没有去根据具体标签搜索用户。这里就开始实现。
新建SearchResultPage.vue,并添加相关路由。
在搜索页添加搜索按钮,和触发点击。搜索页选择标签,点击搜索。
<div style="padding: 16px">
<van-button block type="primary" @click="doSearchResult">搜索</van-button>
</div>
import {useRouter} from 'vue-router';
const router = useRouter();
const doSearchResult = () => {
router.push({
path: '/user/list',
query: {
tags: activeIds.value
}
})
}
修改SearchResultPage.vue页面相关信息。
在idea中添加个人简介字段;注意前端也要修改添加。
<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 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 = ref({
id: 931,
username: '阿尼亚',
userAccount: 'aniya',
profile: '间谍过家家,我哭我哭我哭我哭我哭',
gender: 0,
phone: '123456789101',
email: 'isdafhiusahf@qq.com',
planetCode: '1273',
avatarUrl: 'https://raw.githubusercontent.com/RockIvy/images/master/img/avatar42.jpg',
tags: ['java', 'emo', '打工中', 'emo', '打工中'],
createTime: new Date(),
})
const userList = ref({mockUser});
</script>
<style scoped>
</style>
题外话:banner.txt
Ascii艺术字实现个性化Spring Boot启动banner图案,轻松修改更换banner.txt文件内容,收集了丰富的banner艺术字和图,并且支持中文banner下载,让你的banner好玩儿更有意思。
后端搜索接口
/**
* 根据标签搜索用户
* @param tagList 用户拥有的标签
* @return
*/
@GetMapping("/search/tags")
public BaseResponse<List<User>> searchUsersByTags(@RequestParam(required = false) List<String> tagList){
if (CollectionUtils.isEmpty(tagList)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
List<User> userList = userService.searchUsersByTags(tagList);
return ResultUtils.success(userList);
}
前后端联调
axios中文网|axios API 中文文档
跟着官方文档走
使用 npm:
npm install axios
使用 bower:
bower install axios
使用 yarn
yarn add axios
使用 cdn:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
新建plugins文件夹,新建myAxios.js文件。
// Set config defaults when creating the instance
//自定义实例默认值
import axios from "axios";
const myAxios = axios.create({
baseURL: 'http://localhost:8080/api'
});
//拦截器
// 添加请求拦截器
myAxios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
console.log("请求发送了",config)
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
myAxios.interceptors.response.use(function (response) {
// 对响应数据做点什么
console.log("请求收到了了",response)
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
export default myAxios;
然后是用户根据标签搜素,要去调用后端的数据。就需要axios接受和发送请求。
(http://www.axios-js.com/zh-cn/docs/#案例)
在searchResultPage.vue页面添加axios。并测试访问,会报错,因为跨域了。
访问了这个路径 console.log(‘/user/search/tags error’,error);
Toast.fail(‘请求失败’);
后端允许一下,前端端口访问。修改usercontroller。在运行访问一下。(前后端都要启动)
虽然请求还是失败,但请求地址改变了。下面是下面是参数序列化。(这边应该是后端相应的问题。)
主要的问题是,参数传递的问题。前端传入的是string类型,后端要的是数组类型。(也就是上面我们测试遇到的问题。)
<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 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" description="搜索结果为空" />
</template>
<script setup >
import {onMounted, ref} from "vue";
import {useRoute} from "vue-router";
import {Toast} from "vant";
import myAxios from "../plugins/myAxios.js";
import qs from 'qs'
const route = useRoute();
const {tags} = route.query;
const mockUser = ref({
id: 931,
username: '沙鱼',
userAccount: 'shayu',
profile: '一条咸鱼',
gender: 0,
phone: '123456789101',
email: 'shayu-yusha@qq.com',
planetCode: '931',
avatarUrl: 'https://xingqiu-tuchuang-1256524210.cos.ap-shanghai.myqcloud.com/shayu931/shayu.png',
tags: ['java', 'emo', '打工中', 'emo', '打工中'],
createTime: new Date(),
})
const userList = ref([]);
onMounted( async () =>{
// 为给定 ID 的 user 创建请求
const userListData = await myAxios.get('/user/search/tags',{
withCredentials: false,
params: {
tagNameList: tags
},
//用鱼皮的这个我的头像不会显示。
// paramsSerializer: params =>{
// return qs.stringify(params,{indices: false})
// }
//序列化
paramsSerializer: {
serialize: params => 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.log('/user/search/tags error',error);
Toast.fail('请求失败');
});
if (userListData){
userListData.forEach(user =>{
if (user.tags){
user.tags = JSON.parse(user.tags);
}
})
userList.value = userListData;
}
})
</script>
<style scoped>
</style>
分布式session
:::danger
种 session 的时候注意范围,cookie.domain
比如两个域名:
aaa.yupi.com
bbb.yupi.com
如果要共享 cookie,可以种一个更高层的公共域名,比如 yupi.com
为什么服务器 A 登录后,请求发到服务器 B,不认识该用户?
用户在 A 登录,所以 session(用户登录信息)存在了 A 上
结果请求 B 时,B 没有用户信息,所以不认识。
:::
:::danger
解决方案:共享存储 ,而不是把数据放到单台服务器的内存中
:::
Session 共享实现Redis
:::warning
如何共享存储?
- Redis(基于内存的 K / V 数据库)此处选择 Redis,因为用户信息读取 / 是否登录的判断极其频繁 ,Redis 基于内存,读写性能很高,简单的数据单机 qps
5w - 10w
- MySQL
- 文件服务器 ceph
官网:https://redis.io/
windows 下载:
Redis 5.0.14 下载:
链接:https://pan.baidu.com/s/1XcsAIrdeesQAyQU2lE3cOg
提取码:vkoi
redis 管理工具 quick redis:https://quick123.net/
- 引入 redis,能够操作 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>
- 引入 spring-session 和 redis 的整合,使得自动将 session 存储到 redis 中:
<!-- session-data-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>
- 修改 spring-session 存储配置 spring.session.store-type
默认是 none,表示存储在单台服务器
store-type: redis,表示从 redis 读写 session
打包并分开运行。
再去他们对应的swagger-ui接口测试。
在8080端口登录了,可以在8081端口获取到用户信息。
JWT 的优缺点:https://zhuanlan.zhihu.com/p/108999941