请你重新给出DictionaryServiceImpl,应将e.printStackTrace()替换为日志框架记录,
时间: 2025-07-22 15:39:14 浏览: 6
<think>我们使用SLF4J作为日志框架,因此需要添加一个Logger对象。
修改点:
1. 在类中添加一个静态的Logger对象。
2. 将dictionaryConvert方法中的e.printStackTrace()替换为日志记录,记录错误信息。
3. 在分页参数转换异常时也可以记录日志(可选,根据需求)。
注意:确保项目已经引入了SLF4J的依赖(如logback-classic等)。
修改后的代码:</think>以下是修改后的`DictionaryServiceImpl`类,已将`e.printStackTrace()`替换为使用SLF4J日志框架记录错误信息:
```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.DictionaryDao;
import com.app.entity.DictionaryEntity;
import com.app.service.DictionaryService;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service("dictionaryService")
@Transactional
public class DictionaryServiceImpl extends ServiceImpl<DictionaryDao, DictionaryEntity> implements DictionaryService {
// 添加SLF4J日志记录器
private static final Logger logger = LoggerFactory.getLogger(DictionaryServiceImpl.class);
@Override
public Page<DictionaryEntity> queryPage(Map<String, Object> params, Wrapper<DictionaryEntity> wrapper) {
// 安全地将Wrapper转换为QueryWrapper
QueryWrapper<DictionaryEntity> queryWrapper = convertToQueryWrapper(wrapper);
// 分页参数处理(带异常处理)
long pageNum = 1;
long pageSize = 10;
if (params.get("page") != null) {
try {
pageNum = Long.parseLong(params.get("page").toString());
} catch (NumberFormatException e) {
// 使用日志记录异常
logger.warn("Invalid page parameter: {}, using default value 1", params.get("page"));
}
}
if (params.get("limit") != null) {
try {
pageSize = Long.parseLong(params.get("limit").toString());
} catch (NumberFormatException e) {
// 使用日志记录异常
logger.warn("Invalid limit parameter: {}, using default value 10", params.get("limit"));
}
}
// 创建分页对象
Page<DictionaryEntity> page = new Page<>(pageNum, pageSize);
return baseMapper.selectPage(page, queryWrapper);
}
/**
* 将Wrapper安全转换为QueryWrapper
* @param wrapper 原始Wrapper对象
* @return 转换后的QueryWrapper
*/
private QueryWrapper<DictionaryEntity> convertToQueryWrapper(Wrapper<DictionaryEntity> wrapper) {
if (wrapper instanceof QueryWrapper) {
return (QueryWrapper<DictionaryEntity>) wrapper;
}
// 创建新的QueryWrapper保留实体条件
return new QueryWrapper<>(wrapper.getEntity());
}
@Override
public void dictionaryConvert(Object obj, HttpServletRequest request) {
try {
if (obj == null) {
logger.debug("dictionaryConvert called with null object");
return;
}
// 获取所有以"Types"结尾的字段
List<String> fieldNameList = new ArrayList<>();
Class<?> tempClass = obj.getClass();
while (tempClass != null) {
for (Field f : tempClass.getDeclaredFields()) {
f.setAccessible(true);
if (f.getType().equals(Integer.class) && f.getName().endsWith("Types")) {
fieldNameList.add(f.getName());
logger.trace("Found dictionary field: {} in class {}", f.getName(), tempClass.getName());
}
}
tempClass = tempClass.getSuperclass();
}
// 获取ServletContext中的字典数据
ServletContext servletContext = request.getServletContext();
Map<String, Map<Integer, String>> dictionaryMap =
(Map<String, Map<Integer, String>>) servletContext.getAttribute("dictionaryMap");
if (dictionaryMap == null) {
logger.warn("Dictionary map not found in ServletContext");
return;
}
// 为每个字段赋值
for (String fieldName : fieldNameList) {
Field typesField = null;
// 查找对应的Value字段(假设命名规则为Types->Value)
try {
Field valueField = obj.getClass().getDeclaredField(fieldName.replace("Types", "Value"));
valueField.setAccessible(true);
// 获取Types字段(考虑父类)
if (hasField(obj.getClass(), fieldName)) {
typesField = obj.getClass().getDeclaredField(fieldName);
} else if (obj.getClass().getSuperclass() != null &&
hasField(obj.getClass().getSuperclass(), fieldName)) {
typesField = obj.getClass().getSuperclass().getDeclaredField(fieldName);
}
if (typesField == null) {
logger.debug("Types field not found: {}", fieldName);
continue;
}
typesField.setAccessible(true);
Integer typeValue = (Integer) typesField.get(obj);
// 转换字段名为下划线格式
String dictKey = toUnderScoreCase(fieldName);
// 赋值(带空值保护)
if (typeValue != null && dictionaryMap.containsKey(dictKey)) {
Map<Integer, String> dictItemMap = dictionaryMap.get(dictKey);
String dictValue = dictItemMap.getOrDefault(typeValue, "");
valueField.set(obj, dictValue);
logger.debug("Set dictionary value: {}={} for field {}", dictKey, dictValue, fieldName);
} else {
valueField.set(obj, "");
if (typeValue == null) {
logger.debug("Type value is null for field: {}", fieldName);
} else {
logger.warn("Dictionary key not found: {}", dictKey);
}
}
} catch (NoSuchFieldException e) {
logger.warn("Corresponding value field not found for: {}", fieldName.replace("Types", "Value"));
} catch (Exception e) {
logger.error("Error processing field: {}", fieldName, e);
}
}
} catch (Exception e) {
// 使用日志记录异常
logger.error("Error in dictionaryConvert", e);
}
}
private String toUnderScoreCase(String camelCase) {
StringBuilder sb = new StringBuilder();
for (char c : camelCase.toCharArray()) {
if (Character.isUpperCase(c)) {
sb.append('_').append(Character.toLowerCase(c));
} else {
sb.append(c);
}
}
return sb.toString();
}
private boolean hasField(Class<?> clazz, String fieldName) {
for (Field f : clazz.getDeclaredFields()) {
if (f.getName().equals(fieldName)) {
return true;
}
}
return false;
}
}
```
### 日志框架使用说明:
1. **日志记录器初始化**:
```java
private static final Logger logger = LoggerFactory.getLogger(DictionaryServiceImpl.class);
```
- 使用SLF4J接口创建日志记录器
- 静态final变量确保单例使用
2. **错误日志记录**:
```java
// 替换前
e.printStackTrace();
// 替换后
logger.error("Error in dictionaryConvert", e);
```
- 记录完整错误堆栈
- 包含自定义错误消息
- 支持日志级别过滤
3. **分级日志输出**:
```java
logger.trace("Found dictionary field: {} in class {}", f.getName(), tempClass.getName());
logger.debug("Set dictionary value: {}={} for field {}", dictKey, dictValue, fieldName);
logger.warn("Dictionary key not found: {}", dictKey);
logger.error("Error processing field: {}", fieldName, e);
```
- TRACE: 最详细的调试信息
- DEBUG: 开发调试信息
- WARN: 潜在问题警告
- ERROR: 错误和异常记录
4. **参数化日志**:
```java
logger.warn("Invalid page parameter: {}, using default value 1", params.get("page"));
```
- 使用占位符`{}`避免字符串拼接
- 延迟计算日志内容(只在需要输出时计算)
- 提高性能并减少内存占用
### 日志最佳实践:
1. **日志级别选择**:
- ERROR: 需要立即关注的问题(如系统崩溃)
- WARN: 非关键问题但需要关注(如配置缺失)
- INFO: 重要业务操作(如用户登录)
- DEBUG: 开发调试信息(如变量值)
- TRACE: 最详细信息(如循环内部状态)
2. **异常记录规范**:
```java
try {
// 可能出错的代码
} catch (SpecificException e) {
logger.error("Context message describing the error", e);
}
```
- 提供有意义的错误上下文
- 包含完整异常堆栈
- 避免吞没异常(catch后不处理)
3. **日志内容优化**:
- 避免日志中出现敏感信息(密码、token等)
- 使用toString()时注意可能抛出的异常
- 复杂对象使用JSON序列化记录
### 日志框架优势:
1. **灵活性**:
- 通过配置文件调整日志级别
- 支持控制台、文件、数据库等多种输出
- 可动态修改日志配置(无需重启)
2. **性能优化**:
- 异步日志避免阻塞主线程
- 日志分级减少不必要的输出
- 日志压缩和滚动归档管理
3. **统一管理**:
- 集成ELK等日志分析系统
- 支持分布式日志追踪
- 提供统一的日志查询界面
### 相关问题:
1. SLF4J与Log4j2的主要区别是什么?
2. 如何在Spring Boot中配置多环境日志级别?
3. 日志记录的最佳实践有哪些?
4. 如何实现日志的异步写入以提高性能?
阅读全文
相关推荐


















