浪花 - 主页开发

一、简易版主页

1. 主页展示用户列表





2. 抽取卡片组件

  • 搜索结果页和主页的组件重复,提取出 Card 卡片组件,方便后续统一修改样式等操作
  • 注意抽取出来的组件用到了哪些变量:将变量转化为属性,再通过父组件传递属性
  • 使用 withDefaults 添加默认值:增强健壮性(userList 为空时也能正常运行)




3. 后端返回所有用户

    /**
     * 用户推荐
     * @param request
     * @return 用户列表
     */
    @GetMapping("/recommend")
    public BaseResponse> recommendUsers(HttpServletRequest request) {
        log.info("推荐用户列表");
        QueryWrapper queryWrapper = new QueryWrapper<>();
        List userList = userService.list(queryWrapper);// 查询所有用户

        // 返回脱敏后的用户数据
        List list = userList.stream().map(user -> userService.getSafetyUser(user)).collect(Collectors.toList());
        return ResultUtils.success(list);
    }

4. 查看页面效果

浪花 - 主页开发_第1张图片

二、批量导入数据的几种方式

1. 用可视化界面

  • 适合一次性导入、数据量可控

浪花 - 主页开发_第2张图片

2. 执行 SQL 语句

  • 适用于数据量较小的

3. 编写程序控制导入

  • for 循环,建议分批,要保证可控、幂等性,注意线上数据库和测试数据库有区别
  • 一次性任务:在程序入口使用 @EnableScheduling 开启 SpringBoot 框架对定时任务的支持
  • 执行任务
    • 不能使用 main 方法来执行:SpringBoot 还没有加载这个 Bean,会报空指针异常
    • 使用定时任务框架:在定时任务上使用 @Scheduled 注解设置定时
    • initialDelay:第一次延时执行
    • fixedRate:下一次执行任务的延时时间(设置为 Long.MAX_VALUE 可视为只执行一次)
package com.example.usercenter.once;

import com.example.usercenter.mapper.UserMapper;
import com.example.usercenter.model.domain.User;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;

/**
 * 导入用户任务
 * @author Ghost
 * @version 1.0
 */
@Component
public class InsertUsers {

    @Resource
    private UserMapper userMapper;

    /**
     * 批量插入用户
     */
//    @Scheduled(initialDelay = 5000, fixedRate = Long.MAX_VALUE)
    public void doInsertUsers() {
        StopWatch stopWatch = new StopWatch();
        System.out.println("goodgoodgood");
        stopWatch.start();
        final int INSERT_NUM = 1000;
        for (int i = 0; i < INSERT_NUM; i++) {
            User user = new User();
            user.setUsername("假用户");
            user.setUserAccount("fakeghost");
            user.setAvatarUrl("https://636f-codenav-8grj8px727565176-1256524210.tcb.qcloud.la/img/logo.png");
            user.setGender(0);
            user.setUserPassword("12345678");
            user.setPhone("123");
            user.setEmail("[email protected]");
            user.setTags("[]");
            user.setUserStatus(0);
            user.setUserRole(0);
            user.setPlanetCode("11111111");
            userMapper.insert(user);
        }
        stopWatch.stop();
        System.out.println(stopWatch.getTotalTimeMillis());
    }
}
  • for 循环的缺点
    • 建立和释放数据库连接==>>批量插入解决
    • for 循环是绝对线性的==>>并发执行
  • 批量插入用户:使用 Mybatis-plus 提供的批量插入 saveBatch 方法,现将要插入的用户存储到一个集合里,再将集合批量插入到数据库
package com.example.usercenter.once;

import com.example.usercenter.model.domain.User;
import com.example.usercenter.service.UserService;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 导入用户任务
 * @author Ghost
 * @version 1.0
 */
@Component
public class InsertUsers {

    @Resource
    private UserService userService;

    /**
     * 批量插入用户
     */
    public void doInsertUsers() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        final int INSERT_NUM = 1000;
        List userList = new ArrayList<>();
        for (int i = 0; i < INSERT_NUM; i++) {
            User user = new User();
            user.setUsername("假用户");
            user.setUserAccount("fakeghost");
            user.setAvatarUrl("https://636f-codenav-8grj8px727565176-1256524210.tcb.qcloud.la/img/logo.png");
            user.setGender(0);
            user.setUserPassword("12345678");
            user.setPhone("123");
            user.setEmail("[email protected]");
            user.setTags("[]");
            user.setUserStatus(0);
            user.setUserRole(0);
            user.setPlanetCode("11111111");
            userList.add(user);
        }
        // 20 秒 10 万条
        userService.saveBatch(userList, 10000);
        stopWatch.stop();
        System.out.println(stopWatch.getTotalTimeMillis());
    }
}
  • 并发执行:将数据分成多组,开启多线程并发执行 
    • 注意:插入数据的顺序对应用没有影响才使用并发;不要用不支持并发的集合
    /**
     * 并发批量插入用户
     */
    @Test
    public void doConcurrencyInsertUsersTest() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 分十组
        int batchSize = 5000;
        int j = 0;
        List> futureList = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            List userList = new ArrayList<>();
            while (true) {
                j++;
                User user = new User();
                user.setUsername("假用户");
                user.setUserAccount("fakeghost");
                user.setAvatarUrl("https://636f-codenav-8grj8px727565176-1256524210.tcb.qcloud.la/img/logo.png");
                user.setGender(0);
                user.setUserPassword("12345678");
                user.setPhone("123");
                user.setEmail("[email protected]");
                user.setTags("[]");
                user.setUserStatus(0);
                user.setUserRole(0);
                user.setPlanetCode("11111111");
                userList.add(user);
                if (j % batchSize == 0) {
                    break;
                }
            }
            // 异步执行
            CompletableFuture 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();
        // 20 秒 10 万条
        stopWatch.stop();
        System.out.println(stopWatch.getTotalTimeMillis());
    }

三、分页查询

1. 开启分页

  • 接收前端传来的分页数量和每页展示数目
    /**
     * 用户推荐
     * @param request
     * @return 用户列表
     */
    @GetMapping("/recommend")
    public BaseResponse> recommendUsers(long pageSize, long pageNum, HttpServletRequest request) {
        log.info("推荐用户列表");
        QueryWrapper queryWrapper = new QueryWrapper<>();
        Page userList = userService.page(new Page<>((pageNum - 1) * pageSize, pageSize), queryWrapper);// 查询所有用户
        return ResultUtils.success(userList);
    }

2. 开启 Mybatis-plus 分页配置

/**
 * MyBatisPlus 配置
 * @author 乐小鑫
 * @version 1.0
 */
@Configuration
@MapperScan("com.example.usercenter.mapper")
public class MybatisPlusConfig {
    /**
     * 新的分页插件,一缓和二缓遵循 mybatis 的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

四、查看页面效果

  • 开启分页后后端响应封装到了 Page 中,前端接收时需要取出 response 中的 records

浪花 - 主页开发_第3张图片

你可能感兴趣的:(浪花,-,前端,浪花,-,后端,前端,后端,java)