心链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。 在我们发布软件时,往往需要把我…...

java web爬虫
目录 读取本地文件 从网站读取文件 java爬虫 总结 读取本地文件 import java.io.File; import java.io.PrintWriter; import java.util.Scanner;public class ReplaceText {public static void main() throws Exception{File file new File("basic\\test.txt"…...

MySQL开发教程和具体应用案例
一、MySQL开发教程 初识数据库 定义:数据仓库,安装在操作系统之上,用于存储和管理数据。 分类:关系型数据库(如MySQL、Oracle、SQL Server)和非关系型数据库(如Redis、MongoDB)。 SQL:结构化查询语言,用于管理和操作关系型数据库。 操作数据库 创建、修改、删除…...

QT C++ 模型视图结构 QTableView 简单例子
在Qt中,MVC模式被广泛使用于各种用户界面框架中,包括Qt的模型视图结构。Qt的模型视图结构是基于MVC模式设计的,其中包括了Model、View和Delegate三个部分。 QTableView是Qt模型视图结构中的一种视图,它用于以表格形式显示数据。 …...

2024年3月电子学会Python编程等级考试(四级)真题题库
2024年3月青少年软件编程Python等级考试(四级)真题试卷 题目总数:38 总分数:100 选择题 第 1 题 单选题 运行如下Python代码,若输入整数3,则最终输出的结果为?( ÿ…...

深入分析 Android BroadcastReceiver (一)
文章目录 深入分析 Android BroadcastReceiver (一)1. Android BroadcastReceiver 设计说明1.1 BroadcastReceiver 的主要用途 2. BroadcastReceiver 的工作机制2.1 注册 BroadcastReceiver2.1.1 静态注册2.1.2 动态注册 3. BroadcastReceiver 的生命周期4. 实现和使用 Broadca…...

2024医美如何做抖音医美抖音号,本地团购、短视频直播双ip爆品引流,实操落地课
课程下载:https://download.csdn.net/download/m0_66047725/89307619 更多资源下载:关注我。 课程内容: 01-0-序.mp4 02-01-账号定位.mp4 03-02-误区.mp4 04-03-五件套.mp4 05-04-文案怎么来.mp4 06-05-对标怎么弄.mp4 07-06-人设怎…...

Debian常用指令指南:高效管理你的Linux系统
Debian作为Linux发行版中的佼佼者,以其稳定性和安全性而闻名。掌握Debian的常用指令对于系统管理员和开发人员来说至关重要。本文将介绍一系列Debian系统中的常用指令,帮助你高效地管理和维护你的系统。喜欢的话记得一键三连哦,方便找到它。 …...

什么是DELINS交货指示?
DELINS 是指 Delivery Instruction(交货指示)报文,用于在供应链管理中传递交货指令和相关信息。该报文用于在供应链中的不同合作伙伴之间交换关于交货的详细信息。 DELINS 报文的主要功能 交货指示:传达具体的交货指令ÿ…...

基于Open3D的点云处理24-ICP匹配cuda加速
参考:docs/jupyter/t_pipelines/t_icp_registration.ipynb 完整测试用例: import open3d as o3d import open3d.core as o3cif o3d.__DEVICE_API__ == cuda:import open3d.cuda.pybind.t.pipelines.registration as treg else:...

UE_地编教程_创建地形洞材质
个人学习笔记,不喜勿喷。侵权立删! 使用地形洞材质来遮罩地形上特定位置的可视性和碰撞。如要在山脉侧面创建进入洞穴的入口,此操作将非常有用。可使用地形材质和地形洞材质的相同材质,但注意:对比不使用不透明蒙版的…...