心链6----开发主页以及后端数据插入(多线程并发)定时任务
心链 — 伙伴匹配系统
开发主页
信息搜索页修改
主页开发(直接list用户)
在后端controller层编写接口去实现显示推荐页面的功能
/*** 推荐页面* @param request* @return*/@GetMapping("/recommend")public BaseResponse<List<User>> recommendUsers(HttpServletRequest request){QueryWrapper<User> queryWrapper = new QueryWrapper<>();List<User> userList = userService.list(queryWrapper);List<User> list = userList.stream().map(user -> userService.getSafetyUser(user)).collect(Collectors.toList());return ResultUtils.success(list);}
前端就先复制搜索结果的代码,在修改一个一些不需要的即可
<!--
User:Shier
CreateTime:14:47
-->
<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" image="search" description="数据为空"/>
</template><script setup>import {onMounted, ref} from "vue";import {useRoute} from "vue-router";import {showFailToast, showSuccessToast} from "vant/lib/vant.es";import myAxios from "../plugins/myAxios.ts";import qs from 'qs'const route = useRoute();const {tags} = route.query;const userList = ref([]); //用户列表onMounted(async () => {// 为给定 ID 的 user 创建请求const userListData = await myAxios.get('/user/recommend', {withCredentials: false,params: {},}).then(function (response) {console.log('/user/recommend succeed', response);showSuccessToast('请求成功');return response?.data;}).catch(function (error) {console.log('/user/recommend error', error);showFailToast('请求失败')});if (userListData) {userListData.forEach(user => {if (user.tags) {user.tags = JSON.parse(user.tags);}})userList.value = userListData;}})</script><style scoped></style>
修改一下页面边距
提取用户信息信息卡片
新建文件夹components和文件UserCardList.vue,将主页用户信息卡片提取出来。主页和用户信息搜索页进行引用。
<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 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 lang="ts">
import {UserType} from "../models/user";interface UserCardListProps{userList: UserType[];
}
// 给父组件设置默认值,保证数据不为空
const props= withDefaults(defineProps<UserCardListProps>(),{//@ts-ignoreuserList: [] as UserType[]
});</script>
<style scoped>/* 标签颜色*/.van-tag--danger.van-tag--plain {color: #002fff;}
</style>
然后在Index、SearchResultPage引入UserCardList
导入数据
模拟 1000 万个用户,再去查询
- 用可视化界面:适合一次性导入、数据量可控
- 写程序:for 循环,建议分批,不要一把梭哈(可以用接口来控制)要保证可
控、幂等,注意线上环境和测试环境是有区别的导入 1000 万条,for i 1000w
- 执行 SQL 语句:适用于小数据量
导入导出
(鱼皮这里应该是屏幕没有放大没有看见字段对应的列信息,idea是可以实现的。)
**导出 **
这里自己选择导出的文件类型和导出的地方路径。(尽量用CSV,exsl格式的话因为编码因为会乱码。)
导入
选择要导入的文件
(导入有风险,自己要想清楚用何种方式导入数据。鱼皮在视频里也重点说过的。)
定时任务
:::info
开启定时任务;注解。
新建InsertUser.java(鱼皮是在once文件夹,我这个是之前命名是起的,都可以无所谓的,自己记得就好。)
插件(idea里搜的)
编写定时任务代码并进行测试(这里的定时取巧,尽量别用,注释掉。)
:::
package com.yupi.usercenter.easyExcel;
import java.util.Date;import com.yupi.usercenter.mapper.UserMapper;
import com.yupi.usercenter.model.domain.User;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;import javax.annotation.Resource;@Component
public class InsertUsers {@Resourceprivate UserMapper userMapper;/*** 循环插入用户*/
// @Scheduled(initialDelay = 5000,fixedRate = Long.MAX_VALUE )public void doInsertUser() {StopWatch stopWatch = new StopWatch();stopWatch.start();final int INSERT_NUM = 1000;for (int i = 0; i < INSERT_NUM; i++) {User user = new User();user.setUsername("假用户");user.setUserAccount("sifsf");user.setAvatarUrl("https://raw.githubusercontent.com/RockIvy/images/master/img/avatar54.jpg");user.setProfile("阿尼亚");user.setGender(0);user.setUserPassword("12345678");user.setPhone("123456789108");user.setEmail("123861283@qq.com");user.setUserStatus(0);user.setUserRole(0);user.setPlanetCode("931");user.setTags("[]");userMapper.insert(user);}stopWatch.stop();System.out.println( stopWatch.getLastTaskTimeMillis());}
}
数据插入/并发插入
我们需要插入数据: 1.用可视化界面:适合一次性导入、数据量可控 由于编码,主键以及某些字段的问题
(id,createtime等),演示插入失败,这里不推荐 2.写程序:for 循环,建议分批,不要一把梭哈,这里
演示了两种插入数据的方法 首先创建测试方法文件InsertUsersTest,编写批量查询解决
并发执行,这里的线程可自定义或者用idea默认的,两种方法的区别是,自定义可以跑满线程,而默认的
只能跑CPU核数-1,代码区别:就是在异步执行处加上自定义的线程名
并发插入(这里数据量是100000)
并发要注意执行的先后顺序无所谓,不要用到非并发类的集合private ExecutorService executorService = new ThreadPoolExecutor(16, 1000, 10000, TimeUnit.MINUTES, new ArrayBlockingQueue<>(10000));
// CPU 密集型:分配的核心线程数 = CPU - 1
// IO 密集型:分配的核心线程数可以大于 CPU 核数
:::info
用户插入单元测试,注意打包时要删掉或忽略,不然打一次包就插入一次
:::
package com.ivy.usercenter.service;import com.ivy.usercenter.mapper.UserMapper;
import com.ivy.usercenter.model.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.StopWatch;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;/*** @author ivy* @date 2024/5/30 17:00*/
@SpringBootTest
public class InsertUsersTest {@Resourceprivate UserMapper userMapper;@Resourceprivate UserService userService;//线程设置private ExecutorService executorService = new ThreadPoolExecutor(16, 1000, 10000, TimeUnit.MINUTES, new ArrayBlockingQueue<>(10000));/*** 循环插入用户 10000 条耗时20000ms*/@Testpublic void doInsertUser1() {StopWatch stopWatch = new StopWatch();stopWatch.start();final int INSERT_NUM = 10000;for (int i = 0; i < INSERT_NUM; i++) {User user = new User();user.setUsername("假用户");user.setUserAccount("sifsf");user.setAvatarUrl("https://raw.githubusercontent.com/RockIvy/images/master/img/avatar54.jpg");user.setProfile("阿尼亚");user.setGender(0);user.setUserPassword("12345678");user.setPhone("123456789108");user.setEmail("123861283@qq.com");user.setUserStatus(0);user.setUserRole(0);user.setPlanetCode("931");user.setTags("[]");userMapper.insert(user);}stopWatch.stop();System.out.println(stopWatch.getLastTaskTimeMillis());}/*** 循环插入用户 耗时:20000ms* 批量插入用户 10000 耗时: 1817ms*/@Testpublic void doInsertUser2() {StopWatch stopWatch = new StopWatch();stopWatch.start();final int INSERT_NUM = 10000;List<User> userList = new ArrayList<>();for (int i = 0; i < INSERT_NUM; i++) {User user = new User();user.setUsername("假数据");user.setUserAccount("fakeaccount");user.setAvatarUrl("https://img0.baidu.com/it/u=3514514443,3153875602&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500");user.setGender(0);user.setUserPassword("231313123");user.setPhone("1231312");user.setEmail("12331234@qq.com");user.setUserStatus(0);user.setUserRole(0);user.setPlanetCode("213123");user.setTags("[]");userList.add(user);}userService.saveBatch(userList, 1000);stopWatch.stop();System.out.println(stopWatch.getLastTaskTimeMillis());}/*** 并发批量插入用户 100000 耗时: 4769ms*/@Testpublic void doConcurrencyInsertUser() {StopWatch stopWatch = new StopWatch();stopWatch.start();final int INSERT_NUM = 100000;// 分十组int j = 0;//批量插入数据的大小int batchSize = 5000;List<CompletableFuture<Void>> futureList = new ArrayList<>();// i 要根据数据量和插入批量来计算需要循环的次数。(鱼皮这里直接取了个值,会有问题,我这里随便写的)for (int i = 0; i < INSERT_NUM / batchSize; i++) {List<User> userList = new ArrayList<>();while (true) {j++;User user = new User();user.setUsername("假shier");user.setUserAccount("shier");user.setAvatarUrl("https://c-ssl.dtstatic.com/uploads/blog/202101/11/20210111220519_7da89.thumb.1000_0.jpeg");user.setProfile("fat cat");user.setGender(1);user.setUserPassword("12345678");user.setPhone("123456789108");user.setEmail("22288999@qq.com");user.setUserStatus(0);user.setUserRole(0);user.setPlanetCode("33322");user.setTags("[]");userList.add(user);if (j % batchSize == 0) {break;}}//异步执行 使用CompletableFuture开启异步任务CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {System.out.println("ThreadName:" + Thread.currentThread().getName());userService.saveBatch(userList, batchSize);}, executorService);futureList.add(future);}CompletableFuture.allOf(futureList.toArray(new CompletableFuture[]{})).join();stopWatch.stop();System.out.println(stopWatch.getLastTaskTimeMillis());}}
若使用默认线程池,删去
分页查询
现在启动前后端,查看主页,发现搜查不出,这是因为数据太多需要分页,修改后端接口方法
/*** 推荐页面* @param request* @return*/@GetMapping("/recommend")public BaseResponse<Page<User>> recommendUsers(long pageSize,long pageNum, HttpServletRequest request){QueryWrapper<User> queryWrapper = new QueryWrapper<>();Page<User> userList = userService.page(new Page<>(pageNum, pageSize), queryWrapper);return ResultUtils.success(userList);}
同时还要引入mybatis的分页插件配置,直接复制文档到config目录
主要不要忘了把扫包的路径改为自己的
package com.yupi.usercenter.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@MapperScan("com.yupi.usercenter.mapper")
public class MybatisPlusConfig {/*** 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));return interceptor;}
}
现在去修改前端主页
相关文章:

心链6----开发主页以及后端数据插入(多线程并发)定时任务
心链 — 伙伴匹配系统 开发主页 信息搜索页修改 主页开发(直接list用户) 在后端controller层编写接口去实现显示推荐页面的功能 /*** 推荐页面* param request* return*/GetMapping("/recommend")public BaseResponse<List<User>&…...

【Linux】日志管理
一、日志进程 1、处理日志的进程 rsyslogd:系统专职日志程序 观察rsyslogd程序: ps aux | grep rsyslogd 2、常见的日志文件 1、系统主日志文件: /var/log/messages 动态查看日志文件尾部: tail -f /var/log/messages 2、安全…...

AI 绘画爆火背后:扩散模型原理及实现
节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#x…...

详解智慧互联网医院系统源码:开发医院小程序教学
本篇文章,笔者将详细介绍智慧互联网医院系统的源码结构,并提供开发医院小程序的详细教学。 一、智慧互联网医院系统概述 智慧互联网医院系统涵盖了预约挂号、在线咨询、电子病历、药品管理等多个模块。 二、系统源码结构解析 智慧互联网医院系统的源码…...

【技术实操】银河高级服务器操作系统实例分享,数据库日志文件属主不对问题分析
1. 问题现象描述 2023 年 06 月 30 日在迁移数据库过程中,遇到数据库 crash 的缺陷,原因如下:在数据库启动时候生成的一组临时文件中,有 owner 为 root 的文件, 文件权限默认为 640, 当数据库需要使用的时…...

函数的创建和调用
自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 提到函数,大家会想到数学函数吧,函数是数学最重要的一个模块,贯穿整个数学学习过程。在Python中,函数…...

数模混合芯片设计中的修调技术是什么?
一、修调目的 数模混合芯片需要修调技术主要是因为以下几个原因: 工艺偏差(Process Variations): 半导体制造过程中存在不可避免的工艺偏差,如晶体管尺寸、阈值电压、电阻和电容值等,这些参数的实际值与…...

MySQL 自定义函数(实验报告)
一、实验名称: 自定义函数 二、实验日期: 2024年 6 月 1 日 三、实验目的: 掌握MySQL自定义函数的创建及调用; 四、实验用的仪器和材料: 硬件:PC电脑一台; 配置:内存&#…...

一次职业院校漏洞挖掘
这个是之前挖掘到的漏洞,目前网站进行重构做了全新的改版,但是这个漏洞特别经典,拿出来进行分享。看到src上面的很多敏感信息泄露,所以自己也想找一个敏感信息泄露,官网如图: 发现在下面有一个数字校园入口…...

洪师傅代驾系统开发 支持公众号H5小程序APP 后端Java源码
代驾流程图 业务流程图 管理端设置 1、首页装修 2、师傅奖励配置 师傅注册后,可享受后台设置的新师傅可得的额外奖励; 例:A注册了师傅,新人奖励可享受3天,第一天的第一笔订单完成后可得正常佣金佣金*奖励比例 完成第二笔/第三笔后依次可得正常佣金佣金*奖励比例 完成的第四…...

View->Bitmap缩放到自定义ViewGroup的任意区域(Matrix方式绘制Bitmap)
Bitmap缩放和平移 加载一张Bitmap可能为宽高相同的正方形,也可能为宽高不同的矩形缩放方向可以为中心缩放,左上角缩放,右上角缩放,左下角缩放,右下角缩放Bitmap中心缩放,包含了缩放和平移两个操作…...

Centos 7部署NTP
介绍 NTP是Network Time Protocol(网络时间协议)的简称,它是用来通过互联网或局域网将计算机时钟同步到世界协调时间(UTC)的协议。 安装 # yum安装 yum install -y ntp# 离线安装 #下载地址:https://mir…...

【前缀和】42. 接雨水
本文涉及知识点 C算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 LeetCode42. 接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入&am…...
我的名字叫大数据
第1章 大家好,我叫大数据 1.1 我的家族传统:从我小小的祖先到壮大的我 1.1.1 最初的我:原始部落里的计数石头 大家好,我是你们人类文明的“老朋友”——大数据。你们知道吗?在我还没有变成你们手机、电脑里飞速跑动的那些数字前,我最初的模样可是一块块“计数石头”。…...
数据库漫谈-infomix
infomix数据库知名度不高,主要跟它的定位有关,它主要用于unix操作系统:Informix便是取自Information和Unix的结合,它也是第一个支持linux系统的数据库。它其实在金融、电信行业使用率非常高。98年,当时我在做银行领域的…...

【Qt】Qt界面美化指南:深入理解QSS样式表的应用与实践
文章目录 前言:1. 背景介绍2. 基本语法3. QSS 设置方式3.1. 设置全局样式3.2. 从文件加载样式表3.3. 使用 Qt Designer 编辑样式 总结: 前言: 在当今这个视觉至上的时代,用户界面(UI)的设计对于任何软件产…...

七彩云南文化旅游网站的设计
管理员账户功能包括:系统首页,个人中心,管理员管理,游客管理,导游管理,旅游景点管理,酒店信息管理 前台账户功能包括:系统首页,个人中心,论坛,旅…...

7-zip安装教程
一、简介 7-Zip 是一款开源的文件压缩软件,由 Igor Pavlov 开发。它具有高压缩比、支持多种格式、跨平台等特点。使用 C语言编写,其代码在 Github 上开源。 7-Zip的官网: 7-Zip 7-zip官方中文网站: 7-Zip 官方中文网站 7-Zip 的 G…...

oracle 12c DB卸载流程
1.运行卸载程序 [rootprimary1 ~]# su - oracle [oracleprimary1 ~]$ cd $ORACLE_HOME/deinstall [oracleprimary1 deinstall]$ ./deinstall Checking for required files and bootstrapping ... Please wait ... 这里选择3 、回车、y、y、回车、ASM 这里输入y 2.删除相关目录…...

Docker学习笔记 - 创建自己的image
目录 基本概念常用命令使用docker compose启动脚本创建自己的image 使用Docker是现在最为流行的软件发布方式, 本系列将阐述Docker的基本概念,常用命令,启动脚本和如何生产自己的docker image。 在我们发布软件时,往往需要把我…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
js 设置3秒后执行
如何在JavaScript中延迟3秒执行操作 在JavaScript中,要设置一个操作在指定延迟后(例如3秒)执行,可以使用 setTimeout 函数。setTimeout 是JavaScript的核心计时器方法,它接受两个参数: 要执行的函数&…...

工厂方法模式和抽象工厂方法模式的battle
1.案例直接上手 在这个案例里面,我们会实现这个普通的工厂方法,并且对比这个普通工厂方法和我们直接创建对象的差别在哪里,为什么需要一个工厂: 下面的这个是我们的这个案例里面涉及到的接口和对应的实现类: 两个发…...