JAVA代码优化:记录日志
登录中的一条日志记录代码:
//异步任务管理器(详见文章异步任务管理器)
//me() 初始化线程池
AsyncManager.me()
.execute(
//异步工厂记录登录信息
AsyncFactory.recordLogininfor
(
//使用者姓名
username,
//常量登录失败public static final String LOGIN_FAIL = "Error";
Constants.LOGIN_FAIL,
//简单的静态方法,可以根据消息键和参数从国际化资源文件中获取对应的国际化翻译值。
MessageUtils.message("user.jcaptcha.expire")
)
);
日志的数据库:
1.MessageUtil
这个工具类提供了一个简单的静态方法,可以根据消息键和参数从国际化资源文件中获取对应的国际化翻译值。
获取消息的静态方法:
- 该工具类包含一个静态方法
message
,用于根据消息键和参数获取国际化翻译值。 - 方法接收消息键(code)和可变数量的参数(args)作为输入。
- 内部通过
SpringUtils.getBean(MessageSource.class)
方式获取MessageSource
对象,MessageSource
是Spring框架用于支持国际化的接口。 - 调用
messageSource.getMessage(code, args, LocaleContextHolder.getLocale())
方法来获取具体的国际化消息值,其中code
为消息键,args
为参数,LocaleContextHolder.getLocale()
用于获取当前的Locale信息。
package com.muyuan.common.utils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import com.muyuan.common.utils.spring.SpringUtils;
/**
* 获取i18n资源文件
*
*
*/
public class MessageUtils {
/**
* 根据消息键和参数 获取消息 委托给spring messageSource
*
* @param code 消息键
* @param args 参数
* @return 获取国际化翻译值
*/
public static String message(String code, Object... args) {
//SpringUtils细节查看Spring工具类
MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}
2.异步工厂类(AsyncFactory)
AsyncFactory类提供了两个静态方法,用于生成记录登录信息和操作日志的任务。这些任务会在后台异步执行,并将相关信息插入到数据库中。
-
方法recordLogininfor用于记录登录信息。它接收用户名(username)、状态(status)、消息(message)和其他参数(args)作为输入,并返回一个TimerTask对象作为任务。
首先,代码通过ServletRequestUtils.getRequest()方法获取HttpServletRequest对象,再通过HttpServletRequest对象的getHeader("User-Agent")方法获取User-Agent头部信息,然后使用UserAgent.parseUserAgentString()方法解析User-Agent字符串,得到UserAgent对象。
接着,通过IpUtils.getIpAddr()方法获取客户端的IP地址,并使用AddressUtils.getRealAddressByIP()方法获取IP地址对应的物理地址。
然后,使用StringBuilder拼接日志信息,包括IP地址、物理地址、用户名、状态和消息。
最后,根据登录状态设置SysLogininfor对象的状态属性,并调用ISysLogininforService接口的insertLogininfor()方法插入数据。
-
方法recordOper用于记录操作日志。它接收SysOperLog对象作为输入,并返回一个TimerTask对象作为任务。
该方法通过SysOperLog对象的getOperIp()方法获取操作IP地址,并使用AddressUtils.getRealAddressByIP()方法获取IP地址对应的物理地址。
最后,调用ISysOperLogService接口的insertOperlog()方法插入操作日志数据。
package com.muyuan.framework.manager.factory; import java.util.TimerTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.muyuan.common.constant.Constants; import com.muyuan.common.utils.LogUtils; import com.muyuan.common.utils.ServletUtils; import com.muyuan.common.utils.ip.AddressUtils; import com.muyuan.common.utils.ip.IpUtils; import com.muyuan.common.utils.spring.SpringUtils; import com.muyuan.clues.domain.SysLogininfor; import com.muyuan.clues.domain.SysOperLog; import com.muyuan.clues.service.ISysLogininforService; import com.muyuan.clues.service.ISysOperLogService; import eu.bitwalker.useragentutils.UserAgent; /** * 异步工厂(产生任务用) * * */ public class AsyncFactory { //Logger是用于在应用程序中记录和输出日志信息的类。 //sys-user是Logger的名称,用于标识该日志记录器的名称空间。 // 通过LoggerFactory.getLogger()方法,可以根据名称获取相应的Logger实例。 //用来记录与系统用户相关的日志信息。通过调用Logger的方法(如error、info、debug等) // 可以将日志信息输出到不同的目标(如控制台、文件、数据库等)以便进行查看和分析。 private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user"); /** * 记录登录信息 * * @param username 用户名 * @param status 状态 * @param message 消息 * @param args 列表 * @return 任务task */ public static TimerTask recordLogininfor(final String username, final String status, final String message, final Object... args) { final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); final String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); return new TimerTask() { @Override public void run() { //根据IP地址获取真实的物理地址(详见文章地址工具类) String address = AddressUtils.getRealAddressByIP(ip); StringBuilder s = new StringBuilder(); //追加消息 //LogUtils处理并记录日志文件 //public class LogUtils //{ // public static String getBlock(Object msg) // { // if (msg == null) // { // msg = ""; // } // return "[" + msg.toString() + "]"; // } //} s.append(LogUtils.getBlock(ip)); s.append(address); s.append(LogUtils.getBlock(username)); s.append(LogUtils.getBlock(status)); s.append(LogUtils.getBlock(message)); // 打印信息到日志 sys_user_logger.info(s.toString(), args); // 获取客户端操作系统 String os = userAgent.getOperatingSystem().getName(); // 获取客户端浏览器 String browser = userAgent.getBrowser().getName(); // 封装对象(登录消息的一个参数) SysLogininfor logininfor = new SysLogininfor(); logininfor.setUserName(username); logininfor.setIpaddr(ip); logininfor.setLoginLocation(address); logininfor.setBrowser(browser); logininfor.setOs(os); logininfor.setMsg(message); // 日志状态 //常量public static final String LOGIN_SUCCESS = "Success"; //常量public static final String LOGOUT = "Logout"; if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status)) { //常量成功标识 public static final String SUCCESS = "0"; logininfor.setStatus(Constants.SUCCESS); } else if (Constants.LOGIN_FAIL.equals(status)) { //常量失败标识 public static final String FAIL = "1"; logininfor.setStatus(Constants.FAIL); } // 插入数据(SpringUtil详见) //ISysLogininforService见下方 SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor); } }; } /** * 操作日志记录 * * @param operLog 操作日志信息 * @return 任务task */ public static TimerTask recordOper(final SysOperLog operLog) { return new TimerTask() { @Override public void run() { // 远程查询操作地点(详见通过ip获取地址) operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog); } }; } }
日志记录服务层(ISysOperLogService)
package com.muyuan.clues.service;
import java.util.List;
import com.muyuan.clues.domain.SysOperLog;
/**
* 操作日志 服务层
*
*
*/
public interface ISysOperLogService
{
/**
* 新增操作日志
*
* @param operLog 操作日志对象
*/
public void insertOperlog(SysOperLog operLog);
/**
* 查询系统操作日志集合
*
* @param operLog 操作日志对象
* @return 操作日志集合
*/
public List<SysOperLog> selectOperLogList(SysOperLog operLog);
/**
* 批量删除系统操作日志
*
* @param operIds 需要删除的操作日志ID
* @return 结果
*/
public int deleteOperLogByIds(Long[] operIds);
/**
* 查询操作日志详细
*
* @param operId 操作ID
* @return 操作日志对象
*/
public SysOperLog selectOperLogById(Long operId);
/**
* 清空操作日志
*/
public void cleanOperLog();
}
日志记录服务层处理(SysOperLogServiceImpl)
package com.muyuan.clues.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.muyuan.clues.domain.SysOperLog;
import com.muyuan.clues.mapper.SysOperLogMapper;
import com.muyuan.clues.service.ISysOperLogService;
/**
* 操作日志 服务层处理
*
*
*/
@Service
public class SysOperLogServiceImpl implements ISysOperLogService {
@Autowired
private SysOperLogMapper operLogMapper;
/**
* 新增操作日志
*
* @param operLog 操作日志对象
*/
@Override
public void insertOperlog(SysOperLog operLog) {
operLogMapper.insertOperlog(operLog);
}
/**
* 查询系统操作日志集合
*
* @param operLog 操作日志对象
* @return 操作日志集合
*/
@Override
public List<SysOperLog> selectOperLogList(SysOperLog operLog) {
return operLogMapper.selectOperLogList(operLog);
}
/**
* 批量删除系统操作日志
*
* @param operIds 需要删除的操作日志ID
* @return 结果
*/
@Override
public int deleteOperLogByIds(Long[] operIds) {
return operLogMapper.deleteOperLogByIds(operIds);
}
/**
* 查询操作日志详细
*
* @param operId 操作ID
* @return 操作日志对象
*/
@Override
public SysOperLog selectOperLogById(Long operId) {
return operLogMapper.selectOperLogById(operId);
}
/**
* 清空操作日志
*/
@Override
public void cleanOperLog() {
operLogMapper.cleanOperLog();
}
}
日志记录数据层(SysOperLogMapper)
package com.muyuan.clues.mapper;
import java.util.List;
import com.muyuan.clues.domain.SysOperLog;
/**
* 操作日志 数据层
*
*
*/
public interface SysOperLogMapper
{
/**
* 新增操作日志
*
* @param operLog 操作日志对象
*/
public void insertOperlog(SysOperLog operLog);
/**
* 查询系统操作日志集合
*
* @param operLog 操作日志对象
* @return 操作日志集合
*/
public List<SysOperLog> selectOperLogList(SysOperLog operLog);
/**
* 批量删除系统操作日志
*
* @param operIds 需要删除的操作日志ID
* @return 结果
*/
public int deleteOperLogByIds(Long[] operIds);
/**
* 查询操作日志详细
*
* @param operId 操作ID
* @return 操作日志对象
*/
public SysOperLog selectOperLogById(Long operId);
/**
* 清空操作日志
*/
public void cleanOperLog();
}
日志记录SQL语句层
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.muyuan.clues.mapper.SysOperLogMapper">
<resultMap type="SysOperLog" id="SysOperLogResult">
<id property="operId" column="oper_id" />
<result property="title" column="title" />
<result property="businessType" column="business_type" />
<result property="method" column="method" />
<result property="requestMethod" column="request_method" />
<result property="operatorType" column="operator_type" />
<result property="operName" column="oper_name" />
<result property="deptName" column="dept_name" />
<result property="operUrl" column="oper_url" />
<result property="operIp" column="oper_ip" />
<result property="operLocation" column="oper_location" />
<result property="operParam" column="oper_param" />
<result property="jsonResult" column="json_result" />
<result property="status" column="status" />
<result property="errorMsg" column="error_msg" />
<result property="operTime" column="oper_time" />
</resultMap>
<sql id="selectOperLogVo">
select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time
from sys_oper_log
</sql>
<insert id="insertOperlog" parameterType="SysOperLog">
insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time)
values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, sysdate())
</insert>
<select id="selectOperLogList" parameterType="SysOperLog" resultMap="SysOperLogResult">
<include refid="selectOperLogVo"/>
<where>
<if test="title != null and title != ''">
AND title like concat('%', #{title}, '%')
</if>
<if test="businessType != null and businessType != ''">
AND business_type = #{businessType}
</if>
<if test="businessTypes != null and businessTypes.length > 0">
AND business_type in
<foreach collection="businessTypes" item="businessType" open="(" separator="," close=")">
#{businessType}
</foreach>
</if>
<if test="status != null">
AND status = #{status}
</if>
<if test="operName != null and operName != ''">
AND oper_name like concat('%', #{operName}, '%')
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
and date_format(oper_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(oper_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
</if>
</where>
order by oper_id desc
</select>
<delete id="deleteOperLogByIds" parameterType="Long">
delete from sys_oper_log where oper_id in
<foreach collection="array" item="operId" open="(" separator="," close=")">
#{operId}
</foreach>
</delete>
<select id="selectOperLogById" parameterType="Long" resultMap="SysOperLogResult">
<include refid="selectOperLogVo"/>
where oper_id = #{operId}
</select>
<update id="cleanOperLog">
truncate table sys_oper_log
</update>
</mapper>
日志记录表
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.muyuan.clues.mapper.SysOperLogMapper">
<resultMap type="SysOperLog" id="SysOperLogResult">
<id property="operId" column="oper_id" />
<result property="title" column="title" />
<result property="businessType" column="business_type" />
<result property="method" column="method" />
<result property="requestMethod" column="request_method" />
<result property="operatorType" column="operator_type" />
<result property="operName" column="oper_name" />
<result property="deptName" column="dept_name" />
<result property="operUrl" column="oper_url" />
<result property="operIp" column="oper_ip" />
<result property="operLocation" column="oper_location" />
<result property="operParam" column="oper_param" />
<result property="jsonResult" column="json_result" />
<result property="status" column="status" />
<result property="errorMsg" column="error_msg" />
<result property="operTime" column="oper_time" />
</resultMap>
<sql id="selectOperLogVo">
select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time
from sys_oper_log
</sql>
<insert id="insertOperlog" parameterType="SysOperLog">
insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time)
values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, sysdate())
</insert>
<select id="selectOperLogList" parameterType="SysOperLog" resultMap="SysOperLogResult">
<include refid="selectOperLogVo"/>
<where>
<if test="title != null and title != ''">
AND title like concat('%', #{title}, '%')
</if>
<if test="businessType != null and businessType != ''">
AND business_type = #{businessType}
</if>
<if test="businessTypes != null and businessTypes.length > 0">
AND business_type in
<foreach collection="businessTypes" item="businessType" open="(" separator="," close=")">
#{businessType}
</foreach>
</if>
<if test="status != null">
AND status = #{status}
</if>
<if test="operName != null and operName != ''">
AND oper_name like concat('%', #{operName}, '%')
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
and date_format(oper_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(oper_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
</if>
</where>
order by oper_id desc
</select>
<delete id="deleteOperLogByIds" parameterType="Long">
delete from sys_oper_log where oper_id in
<foreach collection="array" item="operId" open="(" separator="," close=")">
#{operId}
</foreach>
</delete>
<select id="selectOperLogById" parameterType="Long" resultMap="SysOperLogResult">
<include refid="selectOperLogVo"/>
where oper_id = #{operId}
</select>
<update id="cleanOperLog">
truncate table sys_oper_log
</update>
</mapper>