心链 — 伙伴匹配系统
搜索详情页面
之前前端的代码写到了搜索页面可以挑选搜索标签,并没有去根据具体标签搜索用户。这里就开始实现。
新建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-cardv-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使用 yarnyarn 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-cardv-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