- 添加分页插件以及xml相关配置
- 添加用户服务
- 添加PageParam类
- 添加MyBatisPlusConfig类
- 添加/users分页接口
This commit is contained in:
yulinling 2025-06-09 22:08:44 +08:00
parent 3e3eded4ab
commit 84c77b0b50
22 changed files with 257 additions and 183 deletions

10
.idea/.gitignore vendored
View File

@ -1,10 +0,0 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# 依赖于环境的 Maven 主目录路径
/mavenHomeManager.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="workflow@122.152.201.90 [2]" uuid="a3d85aef-f993-4fcd-8b75-c4caadf67022">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://122.152.201.90:9912/workflow</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.resource.type" value="Deployment" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="ms-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/src/main/java/asia/yulinling/workflow/mapper/UserMapper.java" dialect="GenericSQL" />
<file url="file://$PROJECT_DIR$/src/main/resources/db/data.sql" dialect="MySQL" />
<file url="file://$PROJECT_DIR$/src/main/resources/db/schema.sql" dialect="MySQL" />
<file url="file://$PROJECT_DIR$/src/main/resources/mapper/UserMapper.xml" dialect="MySQL" />
<file url="PROJECT" dialect="MySQL" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -91,6 +91,11 @@
<artifactId>mybatis-plus-boot-starter-test</artifactId>
<version>3.5.12</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser</artifactId>
<version>3.5.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

31
qodana.yaml Normal file
View File

@ -0,0 +1,31 @@
#-------------------------------------------------------------------------------#
# Qodana analysis is configured by qodana.yaml file #
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
#-------------------------------------------------------------------------------#
version: "1.0"
#Specify inspection profile for code analysis
profile:
name: qodana.starter
#Enable inspections
#include:
# - name: <SomeEnabledInspectionId>
#Disable inspections
#exclude:
# - name: <SomeDisabledInspectionId>
# paths:
# - <path/where/not/run/inspection>
projectJDK: "17" #(Applied in CI/CD pipeline)
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
#bootstrap: sh ./prepare-qodana.sh
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
#plugins:
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
linter: jetbrains/qodana-jvm:2025.1

View File

@ -0,0 +1,32 @@
package asia.yulinling.workflow.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;
/**
* <p>
* MybatisPlus配置类
* </p>
*
* @author YLL
* @since 2025/6/9
*/
@Configuration
@MapperScan("asia.yulinling.workflow.mapper")
public class MyBatisPlusConfig {
/**
* 添加分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
// 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
return interceptor;
}
}

View File

@ -1,20 +1,18 @@
package asia.yulinling.workflow.controller;
import asia.yulinling.workflow.constant.Status;
import asia.yulinling.workflow.dto.request.PageParam;
import asia.yulinling.workflow.exception.JsonException;
import asia.yulinling.workflow.exception.PageException;
import asia.yulinling.workflow.model.ApiResponse;
import asia.yulinling.workflow.model.PageResult;
import asia.yulinling.workflow.dto.response.PageResult;
import asia.yulinling.workflow.model.vo.user.UserVO;
import asia.yulinling.workflow.service.UserService;
import cn.hutool.core.lang.Dict;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@ -71,7 +69,7 @@ public class TestController {
}
@GetMapping("/users")
public ApiResponse<PageResult<UserVO>> usersPage() {
return userService.getUserList();
public ApiResponse<PageResult<UserVO>> usersPage(PageParam pageParam) {
return userService.getUserListByPage(pageParam);
}
}

View File

@ -0,0 +1,22 @@
package asia.yulinling.workflow.dto.request;
import lombok.Data;
/**
* <p>
* 分页请求参数
* </p>
*
* @author YLL
* @since 2025/6/9
*/
@Data
public class PageParam {
private int pageNum;
private int pageSize;
public PageParam() {
this.pageNum = 1;
this.pageSize = 10;
}
}

View File

@ -1,4 +1,4 @@
package asia.yulinling.workflow.model;
package asia.yulinling.workflow.dto.response;
import lombok.Data;
@ -27,6 +27,9 @@ public class PageResult<T> {
private int from; // 当前页第一条数据在总数据中的位置从1开始
private int to; // 当前页最后一条数据在总数据中的位置
// 无参构造器
public PageResult() {}
// 构造方法可选传参
public PageResult(long total, int currentPage, int pageSize, List<T> list) {
this.total = total;
@ -42,39 +45,5 @@ public class PageResult<T> {
this.lastPage = currentPage == totalPage;
this.from = (currentPage - 1) * pageSize + 1;
this.to = Math.min(currentPage * pageSize, (int) total);
// 可选导航页码生成逻辑需要时可扩展
navigatePageNums = calculateNavigatePageNumbers(currentPage, totalPage, navigatePages);
}
private int[] calculateNavigatePageNumbers(int currentPage, int totalPage, int navigatePages) {
int[] navigatePageNums;
int startPage = 1;
int endPage = totalPage;
// 中间页码计算逻辑
if (totalPage > navigatePages) {
int half = navigatePages / 2;
startPage = currentPage - half;
endPage = currentPage + half;
if (startPage < 1) {
startPage = 1;
endPage = navigatePages;
}
if (endPage > totalPage) {
endPage = totalPage;
startPage = endPage - navigatePages + 1;
if (startPage < 1) startPage = 1;
}
}
navigatePageNums = new int[endPage - startPage + 1];
for (int i = 0; i < navigatePageNums.length; i++) {
navigatePageNums[i] = startPage + i;
}
return navigatePageNums;
}
}

View File

@ -7,8 +7,6 @@ import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* <p>
* 用户Mapper

View File

@ -4,7 +4,7 @@ import lombok.Data;
/**
* <p>
* 用户信息VO
* 用户信息VO
* </p>
*
* @author YLL

View File

@ -4,7 +4,7 @@ import jakarta.mail.MessagingException;
/**
* <p>
* 邮件接口
* 邮件接口
* </p>
*
* @author yulinling
@ -14,20 +14,20 @@ public interface MailService {
/**
* 发送文本邮件
*
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param cc 抄送地址
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param cc 抄送地址
*/
void sendSimpleMail(String to, String subject, String content, String... cc);
/**
* 发送HTML邮件
*
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param cc 抄送地址
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param cc 抄送地址
* @throws MessagingException 邮件发送异常
*/
void sendHtmlMail(String to, String subject, String content, String... cc) throws MessagingException;
@ -36,11 +36,11 @@ public interface MailService {
/**
* 发送带附件邮件
*
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param filePath 附件地址
* @param cc 抄送地址
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param filePath 附件地址
* @param cc 抄送地址
* @throws MessagingException 邮件发送异常
*/
void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) throws MessagingException;
@ -48,12 +48,12 @@ public interface MailService {
/**
* 发送正文带静态资源的邮件
*
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param rscPath 静态资源地址
* @param rscId 静态资源id
* @param cc 抄送地址
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param rscPath 静态资源地址
* @param rscId 静态资源id
* @param cc 抄送地址
* @throws MessagingException 邮件发送异常
*/
void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) throws MessagingException;

View File

@ -1,16 +1,14 @@
package asia.yulinling.workflow.service;
import asia.yulinling.workflow.dto.request.PageParam;
import asia.yulinling.workflow.model.ApiResponse;
import asia.yulinling.workflow.model.PageResult;
import asia.yulinling.workflow.model.entity.User;
import asia.yulinling.workflow.dto.response.PageResult;
import asia.yulinling.workflow.model.vo.user.UserVO;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* <p>
* 用户接口
* 用户接口
* </p>
*
* @author YLL
@ -20,4 +18,6 @@ import java.util.List;
public interface UserService {
ApiResponse<PageResult<UserVO>> getUserList();
ApiResponse<PageResult<UserVO>> getUserListByPage(PageParam pageParam);
}

View File

@ -12,11 +12,12 @@ import org.springframework.stereotype.Service;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.MessagingException;
import java.io.File;
/**
* <p>
* 邮件接口
* 邮件接口
* </p>
*
* @author yulinling
@ -29,13 +30,14 @@ public class MailServiceImpl implements MailService {
private final JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String from;
/**
* 发送文本邮件
*
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param cc 抄送地址
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param cc 抄送地址
*/
@Override
public void sendSimpleMail(String to, String subject, String content, String... cc) {
@ -55,10 +57,10 @@ public class MailServiceImpl implements MailService {
/**
* 发送HTML邮件
*
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param cc 抄送地址
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param cc 抄送地址
* @throws MessagingException 邮件发送异常
*/
@Override
@ -80,11 +82,11 @@ public class MailServiceImpl implements MailService {
/**
* 发送带附件邮件
*
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param filePath 附件地址
* @param cc 抄送地址
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param filePath 附件地址
* @param cc 抄送地址
* @throws MessagingException 邮件发送异常
*/
@Override
@ -108,12 +110,12 @@ public class MailServiceImpl implements MailService {
/**
* 发送正文带静态资源的邮件
*
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param rscPath 静态资源地址
* @param rscId 静态资源id
* @param cc 抄送地址
* @param to 收件人地址
* @param subject 邮件主题
* @param content 邮件内容
* @param rscPath 静态资源地址
* @param rscId 静态资源id
* @param cc 抄送地址
* @throws MessagingException 邮件发送异常
*/
public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) throws MessagingException {

View File

@ -1,18 +1,20 @@
package asia.yulinling.workflow.service.impl;
import asia.yulinling.workflow.dto.request.PageParam;
import asia.yulinling.workflow.mapper.UserMapper;
import asia.yulinling.workflow.model.ApiResponse;
import asia.yulinling.workflow.model.PageResult;
import asia.yulinling.workflow.dto.response.PageResult;
import asia.yulinling.workflow.model.entity.User;
import asia.yulinling.workflow.model.vo.user.UserVO;
import asia.yulinling.workflow.service.UserService;
import asia.yulinling.workflow.utils.PageUtils;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
@ -55,4 +57,25 @@ public class UserServiceImpl implements UserService {
return ApiResponse.ofSuccess(null);
}
@Override
public ApiResponse<PageResult<UserVO>> getUserListByPage(PageParam pageParam) {
Page<User> page = new Page<>(pageParam.getPageNum(), pageParam.getPageSize());
Page<User> users = userMapper.selectPage(page, null);
List<UserVO> userVOList = new ArrayList<>();
if (users.getRecords() != null && !users.getRecords().isEmpty()) {
for (User user : users.getRecords()) {
UserVO userVO = new UserVO();
BeanUtils.copyProperties(user, userVO);
userVOList.add(userVO);
}
}
PageResult<UserVO> pageResult = PageUtils.buildPageResult(users, userVOList);
return ApiResponse.ofSuccess(pageResult);
}
}

View File

@ -0,0 +1,72 @@
package asia.yulinling.workflow.utils;
import asia.yulinling.workflow.dto.response.PageResult;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.util.List;
/**
* <p>
* 分页工具类
* </p>
*
* @author YLL
* @since 2025/6/9
*/
public class PageUtils {
public static <T> PageResult<T> buildPageResult(IPage<?> iPage, List<T> list) {
PageResult<T> result = new PageResult<>();
result.setTotal(iPage.getTotal());
result.setCurrentPage((int) iPage.getCurrent());
result.setPageSize((int) iPage.getSize());
result.setTotalPage((int) iPage.getPages());
result.setList(list);
// 可选字段
int navigatePages = 5;
result.setNavigatePages(navigatePages);
result.setNavigatePageNums(calculateNavigatePageNumbers((int) iPage.getCurrent(), (int)iPage.getPages(), navigatePages));
result.setHasNext(iPage.getCurrent() < iPage.getPages());
result.setHasPrev(iPage.getCurrent() > 1);
result.setFirstPage(iPage.getCurrent() == 1);
result.setLastPage(iPage.getCurrent() == iPage.getPages());
result.setFrom((int) ((iPage.getCurrent() - 1) * iPage.getSize() + 1));
result.setTo((int) (Math.min(iPage.getCurrent() * iPage.getSize(), iPage.getTotal())));
return result;
}
private static int[] calculateNavigatePageNumbers(int currentPage, int totalPage, int navigatePages) {
int[] navigatePageNums;
int startPage = 1;
int endPage = totalPage;
// 中间页码计算逻辑
if (totalPage > navigatePages) {
int half = navigatePages / 2;
startPage = currentPage - half;
endPage = currentPage + half;
if (startPage < 1) {
startPage = 1;
endPage = navigatePages;
}
if (endPage > totalPage) {
endPage = totalPage;
startPage = endPage - navigatePages + 1;
if (startPage < 1) startPage = 1;
}
}
navigatePageNums = new int[endPage - startPage + 1];
for (int i = 0; i < navigatePageNums.length; i++) {
navigatePageNums[i] = startPage + i;
}
return navigatePageNums;
}
}

View File

@ -1,7 +1,6 @@
# ????
server.port=8080
server.servlet.context-path=/demo
# mysql??
spring.datasource.url=jdbc:mysql://122.152.201.90:9912/workflow?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
spring.datasource.username=root
@ -11,7 +10,7 @@ spring.sql.init.mode=always
spring.sql.init.continue-on-error=true
spring.sql.init.schema-locations=classpath:db/schema.sql
spring.sql.init.data-locations=classpath:db/data.sql
# ?????
# ???????
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.maximum-pool-size=20
@ -20,16 +19,9 @@ spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=MyAppHikariCP
spring.datasource.hikari.max-lifetime=300000
spring.datasource.hikari.connection-timeout=30000
# mybatis??
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=asia/yulinling/workflow/entity
# log??
logging.level.asia.yulinling=debug
logging.level.asia.yulinling.workflow.mapper=trace
# mail??
spring.mail.host=smtp.qq.com
spring.mail.port=587
@ -43,6 +35,5 @@ spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.ssl.enable=false
spring.mail.properties.mail.display.sendmail=spring-boot-demo
# Jasypt ??
# Jasypt??
jasypt.encryptor.password=abc

View File

@ -9,12 +9,10 @@ import com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTest;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
@ -38,13 +36,6 @@ public class UserMapperTest {
@Autowired
private UserMapper userMapper;
// @Test
// public void selectAllUser() {
// List<User> users = userMapper.selectAllUser();
// Assert.assertTrue(CollUtil.isNotEmpty(users));
// log.info("users={}", users);
// }
@Test
public void selectAllUser2() {
List<User> users = userMapper.selectList(null);

View File

@ -1,16 +1,14 @@
package asia.yulinling.workflow.service;
import asia.yulinling.workflow.WorkFlowMainTests;
import asia.yulinling.workflow.dto.request.PageParam;
import asia.yulinling.workflow.model.ApiResponse;
import asia.yulinling.workflow.model.PageResult;
import asia.yulinling.workflow.model.entity.User;
import asia.yulinling.workflow.dto.response.PageResult;
import asia.yulinling.workflow.model.vo.user.UserVO;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/**
* <p>
* 用户测试类
@ -25,8 +23,15 @@ public class UserServiceTest extends WorkFlowMainTests {
@Test
public void getUserList() {
ApiResponse<PageResult<UserVO>> users =userService.getUserList();
ApiResponse<PageResult<UserVO>> users = userService.getUserList();
Assert.assertEquals(200, users.getCode().intValue());
}
Assert.assertEquals(200,users.getCode().intValue());
@Test
public void getUserListByPage() {
PageParam pageParam = new PageParam();
ApiResponse<PageResult<UserVO>> users = userService.getUserListByPage(pageParam);
Assert.assertEquals(200, users.getCode().intValue());
}
}