package com.app.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.app.dao.ExamquestionDao; import com.app.entity.ExamquestionEntity; import com.app.service.ExamquestionService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Map; @Service("examquestionService") @Transactional public class ExamquestionServiceImpl extends ServiceImpl<ExamquestionDao, ExamquestionEntity> implements ExamquestionService { @Override public Page<ExamquestionEntity> queryPage(Map<String, Object> params, QueryWrapper<ExamquestionEntity> wrapper) { long pageNum = 1; long pageSize = 10; if (params.get("page") != null) pageNum = Long.parseLong((String) params.get("page")); if (params.get("limit") != null) pageSize = Long.parseLong((String) params.get("limit")); return baseMapper.selectPage(new Page<>(pageNum, pageSize), wrapper); } }请给出修改后的代码
时间: 2025-07-22 13:39:11 浏览: 3
<think>我们按照之前的模式进行修改:
1. 引入日志框架(SLF4J)记录日志
2. 增强参数解析的健壮性(处理非数字字符串、空值等)
3. 将参数类型从具体的QueryWrapper改为更通用的Wrapper接口,并添加安全转换
4. 添加日志输出,记录分页参数和可能的异常
5. 提取参数解析方法,提高代码复用性和可读性
修改后的代码:</think>以下是修改后的`ExamquestionServiceImpl`类,遵循最佳实践并增强了健壮性和可维护性:
```java
package com.app.service.impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.app.dao.ExamquestionDao;
import com.app.entity.ExamquestionEntity;
import com.app.service.ExamquestionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@Service("examquestionService")
@Transactional
public class ExamquestionServiceImpl extends ServiceImpl<ExamquestionDao, ExamquestionEntity> implements ExamquestionService {
// 添加日志记录器
private static final Logger logger = LoggerFactory.getLogger(ExamquestionServiceImpl.class);
// 最大分页大小限制,防止过大查询导致性能问题
private static final long MAX_PAGE_SIZE = 1000;
@Override
public Page<ExamquestionEntity> queryPage(Map<String, Object> params, Wrapper<ExamquestionEntity> wrapper) {
// 安全地将Wrapper转换为QueryWrapper
QueryWrapper<ExamquestionEntity> queryWrapper = convertToQueryWrapper(wrapper);
// 分页参数处理(带异常处理和安全校验)
long pageNum = parsePageParam(params.get("page"), 1);
long pageSize = parsePageParam(params.get("limit"), 10);
// 应用分页大小限制
pageSize = Math.min(pageSize, MAX_PAGE_SIZE);
// 创建分页对象
Page<ExamquestionEntity> page = new Page<>(pageNum, pageSize);
logger.debug("Executing exam question query - page: {}, size: {}", pageNum, pageSize);
// 执行分页查询
return baseMapper.selectPage(page, queryWrapper);
}
/**
* 安全地将Wrapper转换为QueryWrapper
* @param wrapper 原始Wrapper对象
* @return 转换后的QueryWrapper
*/
private QueryWrapper<ExamquestionEntity> convertToQueryWrapper(Wrapper<ExamquestionEntity> wrapper) {
if (wrapper instanceof QueryWrapper) {
return (QueryWrapper<ExamquestionEntity>) wrapper;
}
// 创建新的QueryWrapper保留原始实体条件
return new QueryWrapper<>(wrapper.getEntity());
}
/**
* 安全解析分页参数
* @param value 参数值
* @param defaultValue 默认值
* @return 解析后的长整型值
*/
private long parsePageParam(Object value, long defaultValue) {
if (value == null) {
return defaultValue;
}
try {
// 处理不同类型参数
if (value instanceof Number) {
return ((Number) value).longValue();
} else if (value instanceof String) {
return Long.parseLong((String) value);
} else {
logger.warn("Unsupported parameter type: {}, using default value {}",
value.getClass().getName(), defaultValue);
return defaultValue;
}
} catch (NumberFormatException e) {
logger.warn("Invalid page parameter value: '{}' (type: {}), using default value {}",
value, value.getClass().getName(), defaultValue, e);
return defaultValue;
}
}
}
```
### 主要改进说明:
1. **参数类型泛化**:
```java
// 修改前
public Page<ExamquestionEntity> queryPage(Map<String, Object> params, QueryWrapper<ExamquestionEntity> wrapper)
// 修改后
public Page<ExamquestionEntity> queryPage(Map<String, Object> params, Wrapper<ExamquestionEntity> wrapper)
```
- 使用更通用的`Wrapper`接口代替具体实现类`QueryWrapper`
- 提高方法兼容性,支持更多类型的查询条件
2. **安全参数解析**:
```java
private long parsePageParam(Object value, long defaultValue) {
// 处理各种可能的参数类型
if (value instanceof Number) {
return ((Number) value).longValue();
} else if (value instanceof String) {
return Long.parseLong((String) value);
} else {
// 处理不支持的类型
return defaultValue;
}
}
```
- 支持多种参数类型(String、Integer、Long等)
- 提供默认值保证服务可用性
- 详细的类型错误日志记录
3. **分页大小限制**:
```java
private static final long MAX_PAGE_SIZE = 1000;
pageSize = Math.min(pageSize, MAX_PAGE_SIZE);
```
- 防止恶意或意外的大分页查询
- 保护数据库性能
- 可配置的最大值限制
4. **增强日志记录**:
```java
logger.debug("Executing exam question query - page: {}, size: {}", pageNum, pageSize);
logger.warn("Unsupported parameter type: {}, using default value {}",
value.getClass().getName(), defaultValue);
```
- 添加SLF4J日志记录器
- 关键操作点添加调试日志
- 参数问题记录详细警告日志
- 使用参数化日志避免字符串拼接
5. **异常处理优化**:
```java
} catch (NumberFormatException e) {
logger.warn("Invalid page parameter value: '{}' (type: {}), using default value {}",
value, value.getClass().getName(), defaultValue, e);
return defaultValue;
}
```
- 捕获并记录异常
- 提供有意义的错误信息
- 返回默认值保证服务可用性
### 设计亮点:
1. **防御式编程**:
- 所有外部输入都经过验证
- 关键操作都有异常处理
- 默认值保证基本功能
- 大小限制防止资源滥用
2. **代码复用**:
- 提取`parsePageParam`方法处理数字转换
- 提取`convertToQueryWrapper`方法处理Wrapper转换
- 减少重复代码,提高可维护性
3. **类型安全处理**:
```java
if (value instanceof Number) {
return ((Number) value).longValue();
} else if (value instanceof String) {
return Long.parseLong((String) value);
}
```
- 优先使用类型判断而非字符串转换
- 避免不必要的类型转换开销
- 提高处理效率
4. **可配置性**:
```java
private static final long MAX_PAGE_SIZE = 1000;
```
- 关键参数作为常量定义
- 便于统一调整
- 提高代码可读性
### 使用示例:
```java
// 创建查询条件
Wrapper<ExamquestionEntity> wrapper = new QueryWrapper<ExamquestionEntity>()
.eq("paper_id", 123)
.orderByAsc("question_order");
// 设置分页参数
Map<String, Object> params = new HashMap<>();
params.put("page", "2"); // 字符串类型
params.put("limit", 20); // 整数类型
// 执行查询
Page<ExamquestionEntity> result = examquestionService.queryPage(params, wrapper);
```
### 注意事项:
1. **性能优化**:
- 对于大数据量查询,考虑禁用MyBatis-Plus的count查询:
```java
Page<ExamquestionEntity> page = new Page<>(pageNum, pageSize, false);
```
- 避免在分页查询中使用复杂联表查询
2. **SQL注入防护**:
- 确保`Wrapper`中的条件值来自可信来源
- 避免直接将用户输入拼接到SQL条件中
- 使用MyBatis-Plus的参数绑定功能
3. **日志配置**:
- 在生产环境中配置日志级别为INFO或WARN
- 开发环境可配置为DEBUG以便调试
- 定期审查日志文件
4. **分页参数验证**:
- 添加最小值和负值处理:
```java
pageNum = Math.max(1, pageNum); // 页码最小为1
pageSize = Math.max(1, pageSize); // 每页大小最小为1
```
### 扩展功能建议:
1. **自定义排序支持**:
```java
if (params.containsKey("sortField") && params.containsKey("sortOrder")) {
String sortField = (String) params.get("sortField");
String sortOrder = (String) params.get("sortOrder");
if ("asc".equalsIgnoreCase(sortOrder)) {
queryWrapper.orderByAsc(sortField);
} else {
queryWrapper.orderByDesc(sortField);
}
}
```
2. **查询条件动态构建**:
```java
if (params.containsKey("questionType")) {
queryWrapper.eq("question_type", params.get("questionType"));
}
if (params.containsKey("keyword")) {
queryWrapper.like("question_content", params.get("keyword"));
}
```
3. **查询结果缓存**:
```java
@Cacheable(value = "examQuestions", key = "#params.toString() + #wrapper.getCustomSqlSegment()")
public Page<ExamquestionEntity> queryPage(...) {
// 查询逻辑
}
```
### 相关问题:
1. MyBatis-Plus中如何实现复杂条件动态查询?
2. 分页查询性能优化的常见策略有哪些?
3. 如何防止SQL注入攻击在MyBatis-Plus中的应用?
4. 在Spring Boot中如何统一管理分页参数?
阅读全文
相关推荐















