ssm框架操作日志实现步骤
1.创建日志表
CREATE TABLE `log_message` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '操作日志id', `operationUser` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作人', `path` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求路径', `time` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作时间', `parameter` varchar(10000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数', `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求模块', `action` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求内容', `ip` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作人IP地址', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 38 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
2.逆向工程生成pojo,mapper接口,mapper.xml
pojo
package com.df.pojo.po; import java.io.Serializable; public class LogMessage implements Serializable { private Integer id; private String operationuser; //操作人 private String path; //请求方法 private String time; //请求时间 private String parameter; //请求参数 private String title; //title private String action; //操作内容 private String ip; //操作人员ip private String start_time; //用于输入框时间查询 private String end_time; //用于输入框时间查询 public String getStart_time() { return start_time; } public void setStart_time(String start_time) { this.start_time = start_time; } public String getEnd_time() { return end_time; } public void setEnd_time(String end_time) { this.end_time = end_time; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getOperationuser() { return operationuser; } public void setOperationuser(String operationuser) { this.operationuser = operationuser == null ? null : operationuser.trim(); } public String getPath() { return path; } public void setPath(String path) { this.path = path == null ? null : path.trim(); } public String getTime() { return time; } public void setTime(String time) { this.time = time == null ? null : time.trim(); } public String getParameter() { return parameter; } public void setParameter(String parameter) { this.parameter = parameter == null ? null : parameter.trim(); } public String getTitle() { return title; } public void setTitle(String title) { this.title = title == null ? null : title.trim(); } public String getAction() { return action; } public void setAction(String action) { this.action = action == null ? null : action.trim(); } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip == null ? null : ip.trim(); } public LogMessage(String operationuser, String path, String time, String parameter, String title, String action, String ip) { super(); this.operationuser = operationuser; this.path = path; this.time = time; this.parameter = parameter; this.title = title; this.action = action; this.ip = ip; } public LogMessage() { super(); } @Override public String toString() { return "LogMessage [id=" + id + ", operationuser=" + operationuser + ", path=" + path + ", time=" + time + ", parameter=" + parameter + ", title=" + title + ", action=" + action + ", ip=" + ip + ", start_time=" + start_time + ", end_time=" + end_time + "]"; } }
mapper.java接口
package com.df.base.dao.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; import com.df.pojo.po.LogMessage; import com.df.pojo.po.LogMessageExample; import com.df.pojo.vo.LogMessageQueryVo; public interface LogMessageMapper { int countByExample(LogMessageExample example); int deleteByExample(LogMessageExample example); int deleteByPrimaryKey(Integer id); int insert(LogMessage record); int insertSelective(LogMessage record); List<LogMessage> selectByExample(LogMessageExample example); LogMessage selectByPrimaryKey(Integer id); int updateByExampleSelective(@Param("record") LogMessage record, @Param("example") LogMessageExample example); int updateByExample(@Param("record") LogMessage record, @Param("example") LogMessageExample example); int updateByPrimaryKeySelective(LogMessage record); int updateByPrimaryKey(LogMessage record); List<LogMessage> findLogMessageList(LogMessageQueryVo logMessageQueryVo); int findLogMessageListCount(LogMessageQueryVo logMessageQueryVo); }
mapper.xml
<?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.df.dao.mapper.LogMessageMapper" > <resultMap id="BaseResultMap" type="yycg.base.pojo.po.LogMessage" > <id column="id" property="id" jdbcType="INTEGER" /> <result column="operationUser" property="operationuser" jdbcType="VARCHAR" /> <result column="path" property="path" jdbcType="VARCHAR" /> <result column="time" property="time" jdbcType="VARCHAR" /> <result column="parameter" property="parameter" jdbcType="VARCHAR" /> <result column="title" property="title" jdbcType="VARCHAR" /> <result column="action" property="action" jdbcType="VARCHAR" /> <result column="ip" property="ip" jdbcType="VARCHAR" /> </resultMap> <sql id="Example_Where_Clause" > <where > <foreach collection="oredCriteria" item="criteria" separator="or" > <if test="criteria.valid" > <trim prefix="(" suffix=")" prefixOverrides="and" > <foreach collection="criteria.criteria" item="criterion" > <choose > <when test="criterion.noValue" > and ${criterion.condition} </when> <when test="criterion.singleValue" > and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue" > and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue" > and ${criterion.condition} <foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," > #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <sql id="Update_By_Example_Where_Clause" > <where > <foreach collection="example.oredCriteria" item="criteria" separator="or" > <if test="criteria.valid" > <trim prefix="(" suffix=")" prefixOverrides="and" > <foreach collection="criteria.criteria" item="criterion" > <choose > <when test="criterion.noValue" > and ${criterion.condition} </when> <when test="criterion.singleValue" > and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue" > and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue" > and ${criterion.condition} <foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," > #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql> <sql id="Base_Column_List" > id, operationUser, path, time, parameter, title, action, ip </sql> <select id="selectByExample" resultMap="BaseResultMap" parameterType="yycg.base.pojo.po.LogMessageExample" > select <if test="distinct" > distinct </if> <include refid="Base_Column_List" /> from log_message <if test="_parameter != null" > <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null" > order by ${orderByClause} </if> </select> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" > select <include refid="Base_Column_List" /> from log_message where id = #{id,jdbcType=INTEGER} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" > delete from log_message where id = #{id,jdbcType=INTEGER} </delete> <delete id="deleteByExample" parameterType="yycg.base.pojo.po.LogMessageExample" > delete from log_message <if test="_parameter != null" > <include refid="Example_Where_Clause" /> </if> </delete> <insert id="insert" parameterType="yycg.base.pojo.po.LogMessage" > insert into log_message (id, operationUser, path, time, parameter, title, action, ip) values (#{id,jdbcType=INTEGER}, #{operationuser,jdbcType=VARCHAR}, #{path,jdbcType=VARCHAR}, #{time,jdbcType=VARCHAR}, #{parameter,jdbcType=VARCHAR}, #{title,jdbcType=VARCHAR}, #{action,jdbcType=VARCHAR}, #{ip,jdbcType=VARCHAR}) </insert> <insert id="insertSelective" parameterType="yycg.base.pojo.po.LogMessage" > insert into log_message <trim prefix="(" suffix=")" suffixOverrides="," > <if test="id != null" > id, </if> <if test="operationuser != null" > operationUser, </if> <if test="path != null" > path, </if> <if test="time != null" > time, </if> <if test="parameter != null" > parameter, </if> <if test="title != null" > title, </if> <if test="action != null" > action, </if> <if test="ip != null" > ip, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides="," > <if test="id != null" > #{id,jdbcType=INTEGER}, </if> <if test="operationuser != null" > #{operationuser,jdbcType=VARCHAR}, </if> <if test="path != null" > #{path,jdbcType=VARCHAR}, </if> <if test="time != null" > #{time,jdbcType=VARCHAR}, </if> <if test="parameter != null" > #{parameter,jdbcType=VARCHAR}, </if> <if test="title != null" > #{title,jdbcType=VARCHAR}, </if> <if test="action != null" > #{action,jdbcType=VARCHAR}, </if> <if test="ip != null" > #{ip,jdbcType=VARCHAR}, </if> </trim> </insert> <select id="countByExample" parameterType="yycg.base.pojo.po.LogMessageExample" resultType="java.lang.Integer" > select count(*) from log_message <if test="_parameter != null" > <include refid="Example_Where_Clause" /> </if> </select> <update id="updateByExampleSelective" parameterType="map" > update log_message <set > <if test="record.id != null" > id = #{record.id,jdbcType=INTEGER}, </if> <if test="record.operationuser != null" > operationUser = #{record.operationuser,jdbcType=VARCHAR}, </if> <if test="record.path != null" > path = #{record.path,jdbcType=VARCHAR}, </if> <if test="record.time != null" > time = #{record.time,jdbcType=VARCHAR}, </if> <if test="record.parameter != null" > parameter = #{record.parameter,jdbcType=VARCHAR}, </if> <if test="record.title != null" > title = #{record.title,jdbcType=VARCHAR}, </if> <if test="record.action != null" > action = #{record.action,jdbcType=VARCHAR}, </if> <if test="record.ip != null" > ip = #{record.ip,jdbcType=VARCHAR}, </if> </set> <if test="_parameter != null" > <include refid="Update_By_Example_Where_Clause" /> </if> </update> <update id="updateByExample" parameterType="map" > update log_message set id = #{record.id,jdbcType=INTEGER}, operationUser = #{record.operationuser,jdbcType=VARCHAR}, path = #{record.path,jdbcType=VARCHAR}, time = #{record.time,jdbcType=VARCHAR}, parameter = #{record.parameter,jdbcType=VARCHAR}, title = #{record.title,jdbcType=VARCHAR}, action = #{record.action,jdbcType=VARCHAR}, ip = #{record.ip,jdbcType=VARCHAR} <if test="_parameter != null" > <include refid="Update_By_Example_Where_Clause" /> </if> </update> <update id="updateByPrimaryKeySelective" parameterType="yycg.base.pojo.po.LogMessage" > update log_message <set > <if test="operationuser != null" > operationUser = #{operationuser,jdbcType=VARCHAR}, </if> <if test="path != null" > path = #{path,jdbcType=VARCHAR}, </if> <if test="time != null" > time = #{time,jdbcType=VARCHAR}, </if> <if test="parameter != null" > parameter = #{parameter,jdbcType=VARCHAR}, </if> <if test="title != null" > title = #{title,jdbcType=VARCHAR}, </if> <if test="action != null" > action = #{action,jdbcType=VARCHAR}, </if> <if test="ip != null" > ip = #{ip,jdbcType=VARCHAR}, </if> </set> where id = #{id,jdbcType=INTEGER} </update> <update id="updateByPrimaryKey" parameterType="yycg.base.pojo.po.LogMessage" > update log_message set operationUser = #{operationuser,jdbcType=VARCHAR}, path = #{path,jdbcType=VARCHAR}, time = #{time,jdbcType=VARCHAR}, parameter = #{parameter,jdbcType=VARCHAR}, title = #{title,jdbcType=VARCHAR}, action = #{action,jdbcType=VARCHAR}, ip = #{ip,jdbcType=VARCHAR} where id = #{id,jdbcType=INTEGER} </update> </mapper>
自定义注解,log
package com.df.common.log; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Log { /** 方法模块 操作日志类*/ String title() default ""; /** 功能 */ String action() default ""; }
定义类用来记录日志,使用aop后置通知原理
package com.df.common.log; import java.lang.reflect.Method; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.CodeSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import yycg.base.dao.mapper.LogMessageMapper; import yycg.base.pojo.po.LogMessage; import yycg.base.pojo.vo.ActiveUser; import yycg.util.DateUtils; /** * @author Administrator * @Description 日志记录 */ public class LogAspect { @Autowired private LogMessageMapper logMessageMapper;//日志 mapper private String requestPath = null ; // 请求地址 private long startTimeMillis = 0; // 开始时间 private long endTimeMillis = 0; // 结束时间 private String user = null; // 操作人 private HttpServletRequest request = null;//请求 /** * @param joinPoint * @Description 气质通知 方法调用前触发 记录开始时间,从session中获取操作人 */ public void before(JoinPoint joinPoint){ startTimeMillis = System.currentTimeMillis(); } /** * @param joinPoint * @Description 获取入参方法参数 * @return */ public Map<String, Object> getNameAndValue(JoinPoint joinPoint) { Map<String, Object> param = new HashMap<>(); Object[] paramValues = joinPoint.getArgs(); String[] paramNames = ((CodeSignature)joinPoint.getSignature()).getParameterNames(); for (int i = 0; i < paramNames.length; i++) { // if(paramValues[i] instanceof Integer || paramValues[i] instanceof String) { // param.put(paramNames[i], paramValues[i]); // } param.put(paramNames[i], paramValues[i]); } return param; } /** * @param joinPoint * @Description 后置通知 方法调用后触发 记录结束时间 ,操作人 ,入参等 */ public void after(JoinPoint joinPoint) { request = getHttpServletRequest(); String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class<?> targetClass = null; try { targetClass = Class.forName(targetName); } catch (ClassNotFoundException e) { e.printStackTrace(); } Method[] methods = targetClass.getMethods(); //获取该类下所有方法 String title; String action; Class<?>[] clazzs; for (Method method : methods) { if (method.getName().equals(methodName)) { clazzs = method.getParameterTypes(); //获取改方法的参数 if (clazzs!=null&&clazzs.length == arguments.length &&method.getAnnotation(Log.class)!=null) { request = getHttpServletRequest(); requestPath=request.getServletPath(); //请求路径 //user = (String) request.getSession().getAttribute("activeUser"); //用户登录时存session的键 ActiveUser activeUser = (ActiveUser)request.getSession().getAttribute("activeUser"); user=activeUser.getUsername(); title = method.getAnnotation(Log.class).title(); action = method.getAnnotation(Log.class).action(); String currnetDayParamMill = DateUtils.getCurrnetDayParamMill(new Date()); String ipAddress = request.getHeader("x-forwarded-for"); if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("Proxy-Client-IP"); } if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("WL-Proxy-Client-IP"); } if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getRemoteAddr(); if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){ //根据网卡取本机配置的IP InetAddress inet=null; try { inet = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); } ipAddress= inet.getHostAddress(); } } //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15 if(ipAddress.indexOf(",")>0){ ipAddress = ipAddress.substring(0,ipAddress.indexOf(",")); } } LogMessage log=new LogMessage(user, requestPath, currnetDayParamMill, getNameAndValue(joinPoint).toString(), title, action,ipAddress); logMessageMapper.insertSelective(log); break; } } } } /** * @Description: 获取request */ public HttpServletRequest getHttpServletRequest(){ RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes)ra; HttpServletRequest request = null; try { request = sra.getRequest(); } catch (Exception e) { // TODO Auto-generated catch block //e.printStackTrace(); } return request; } /** * @param joinPoint * @return 环绕通知 * @throws Throwable */ public Object around(ProceedingJoinPoint joinPoint) throws Throwable { return null; } /** * @param joinPoint * @Description 异常通知 */ public void throwing(JoinPoint joinPoint) { System.out.println("异常通知"); } }
applicationContext.xml配置文件
<!-- 操作日志配置 指定扫描aop执行操作的类 --> <aop:aspectj-autoproxy proxy-target-class="true" /> <!--将日志类注入到bean中。--> <bean id="logAspect" class="com.df.common.log.LogAspect"></bean> <aop:config> <aop:aspect ref="logAspect"> <aop:pointcut id="log" expression="execution(* com.*.service.impl.*.*(..))"/> <aop:after pointcut-ref="log" method="after"/> </aop:aspect> </aop:config>
在实现类需要加日志业务加上注解即可
@Log(title="增加日志",action="增加用户信息") @Override public void insertSysuser(SysuserCustom sysuserCustom) throws Exception { }