目标:
每个系统都会有相应的日志,那么在这里就和大家分享一下,我做过的项目里,异常日志都是怎么记录入库的
首先我们记录的异常日志都是需要落库保存的,所以需要数据库表的支持。然后在每次捕捉异常的时候,都需要调用方法,记录落库,然后在后台的管理系统中就可以展示对应的异常日志数据了。
分享一下数据设计:
#创建表的sql
create table exception_log
(
id bigint not null auto_increment comment '主键id(自增)',
operator_code varchar(64) not null default '' comment '操作人id',
operator varchar(50) not null default '' comment '操作人',
uri varchar(500) not null default '' comment '请求路径',
operator_ip varchar(64) not null default '' comment '操作人ip',
description varchar(200) not null default '' comment '错误描述',
host_name varchar(64) not null default '' comment '主机',
detail text not null default '' comment '错误详细',
brower_message varchar(200) not null default '' comment '浏览器信息',
create_time datetime not null default CURRENT_TIMESTAMP comment '创建时间',
primary key (id)
);
然后创建对应的实体类、业务层接口和实现类、持久化层的接口和xml文件,提供新增和查询的方法就可以了。
在方法里面调用方法,具体下面举例说明
//日志的业务接口
@Autowired
private ExceptionLogService exceptionLogService;
@PostMapping("add")
public void add(HttpServletRequest request){
try{
System.out.println("正常的逻辑代码");
} catch(Exception e){
exceptionLogService.add("异常描述(比如:添加***异常)", e, request);
}
}
//ExceptionLogService接口
//入参:异常描述,异常信息,请求
void handler(String exceptionMsg, Exception e, HttpServletRequest request);
//ExceptionLogServiceImpl实现类方法
public class ExceptionServiceImpl implements ExceptionService {
protected static final Logger LOGGER = LoggerFactory.getLogger(ExceptionServiceImpl.class);
@Value("${chuxin.example.serverName}")
private String serverName;
@Override
public void handler(String exceptionMsg, Exception e, HttpServletRequest request) {
User user = new User();//这里是获取当前登录人信息
try {
// 如果异常时用来提示的,那么什么都不做
if(e instanceof ExampleException){
return;
}
ExceptionLog exceptionLog = new ExceptionLog();
exceptionLog.setServerName(serverName);
exceptionLog.setOperator(serverName);
exceptionLog.setDescription(exceptionMsg);
if (request != null) {
exceptionLog.setOperatorIp(NetUtils.getIpAddr(request));
exceptionLog.setUri(request.getRequestURI());
exceptionLog.setBrowerMessage(request.getHeader("User-Agent"));
}
if (user != null) {
exceptionLog.setOperatorCode(StringUtils.defaultString(user.getEmplId()));
}
//输出错误堆栈
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(outputStream);
e.printStackTrace(ps);
exceptionLog.setDetail(outputStream.toString());
exceptionLog.setCreateTime(new Date());
exceptionLog.setHostName(InetAddress.getLocalHost().getHostName());
exceptionLogService.insert(exceptionLog);
} catch (Exception e1) {
LOGGER.warn("存储异常日志失败");
}
}
}
解释:
ExampleException是自定义异常,一般这种自定义异常都是用来提示的,所以不需要记录落库的。
User是获取当前用户信息,记录当前谁操作的
serverName是操作系统(比如,ecm、web、app等),在配置文件中配置的
#配置文件中的serverName写法
chuxin:
example:
serverName: ECM
自定义异常类:
public class ExampleException extends RuntimeException {
private int code;
public ExampleException(String message) {
super(message);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
这样我们就可以完成异常日志的记录工作了。。。
上述代码中使用到的工具类如下:
import javax.servlet.http.HttpServletRequest;
/**
* <p>Description: [网络工具类]</p>
* Created on 2018/3/28
* @version 1.0
*/
public class NetUtils {
/**
* 获取真实的ip
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
网友评论