zoukankan      html  css  js  c++  java
  • [沫沫金]JavaWeb企业信息系统,增加操作记录、数据库记录

    背景

    系统出现数据莫名丢失,业务人员的反馈无法复现问题。纠结了很久,最终老板发话要记录操作,通过日志进行分析重现

    环境

    SSH框架

    目标

    1、记录访问了那个方法,使用的参数及返回的内容

    2、记录新增、修改、删除的数据持久化记录

    关键

    监听器(Interceptor)

    实现

    1、访问记录,使用Struts的MethodFilterInterceptor监听器

    import org.apache.log4j.Logger;
    import org.apache.struts2.ServletActionContext;
    import org.codehaus.jackson.map.ObjectMapper;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
    /**
     * Action方法监听
     * @author ZhangLi
     * @date 2018年8月28日 下午4:42:57
     */
    public class MethodInterceptor extends MethodFilterInterceptor {
    
        private static final long serialVersionUID = 1L;
    
        @SuppressWarnings("rawtypes")
        @Override
        protected String doIntercept(ActionInvocation AI) throws Exception {
            String result  = null;
            Logger logger = null;
            try{
                result = AI.invoke();
                String methodName = AI.getProxy().getMethod();
                if (methodName.length() > 0) {
                    Object action = AI.getAction();
                    Class clazz = action.getClass();
                    logger = Logger.getLogger(clazz);
                    ObjectMapper mapper = new ObjectMapper();
                    
                    StringBuilder sbInfo = new StringBuilder();
                    sbInfo.append("[ Log ] 操作记录 (Start)");
                    sbInfo.append("
    ");
                    sbInfo.append(String.format("访问后台:%s访问[%s]类[%s]方法",ServletActionContext.getRequest().getRemoteAddr(),clazz.getName(),methodName));
                    sbInfo.append("
    ");
                    sbInfo.append(String.format("访问URL:%s",ServletActionContext.getRequest().getRequestURI()));
                    sbInfo.append("
    ");
                    sbInfo.append(String.format("访问参数:%s",mapper.writeValueAsString(ServletActionContext.getRequest().getParameterMap())));
                    sbInfo.append("
    ");
                    sbInfo.append(String.format("返回结果:%s",result));
                    sbInfo.append("
    ");
                    sbInfo.append("[ Log ] 操作记录 (End)");
                    
                    logger.warn(sbInfo);
                }
            }catch(Exception e){
                logger.error("Log - 访问错误", e);
            }
            return result;
        }
    
    }

    struts.xml配置

    <package name="default" extends="json-default" namespace="/">
            <!-- 配置拦截器和拦截器栈 -->
            <interceptors>
                <interceptor name="methodInterceptor"    class="com.ytforever.interceptor.MethodInterceptor">
                </interceptor>
                <interceptor-stack name="methodStack">
                    <interceptor-ref name="methodInterceptor"></interceptor-ref>
                </interceptor-stack>
            </interceptors>
            <!-- 默认拦截器 -->
            <default-interceptor-ref name="methodStack"></default-interceptor-ref>
    </package>
    <!-- 假如多个package,每个首行拷贝默认拦截器,不然,方法不被监听,无法记录 -->
            <!-- 默认拦截器 -->
            <default-interceptor-ref name="methodStack"></default-interceptor-ref>

    2、数据库持久化记录,使用hibernate的EventListener事件监听

    import org.apache.log4j.Logger;
    import org.codehaus.jackson.map.ObjectMapper;
    import org.hibernate.event.PostDeleteEvent;
    import org.hibernate.event.PostDeleteEventListener;
    import org.hibernate.event.PostInsertEvent;
    import org.hibernate.event.PostInsertEventListener;
    import org.hibernate.event.PostUpdateEvent;
    import org.hibernate.event.PostUpdateEventListener;
    /**
     * HIBERNATE删除、修改监听
     * @author ZhangLi
     * @date 2018年8月28日 下午4:44:26
     */
    public class UpdateDeleteListener  implements PostInsertEventListener,PostUpdateEventListener, PostDeleteEventListener {
    
        private static final long serialVersionUID = 1L;
        Logger logger = null;
        ObjectMapper mapper = new ObjectMapper();
    
        @Override
        public void onPostDelete(PostDeleteEvent PD) {
            try {
                logger = Logger.getLogger(PD.getEntity().getClass());
                
                StringBuffer sbInfo = new StringBuffer();
                sbInfo.append("[ Data ] 删除数据 (Start)");
                sbInfo.append("
    ");
                sbInfo.append(String.format("实体名:%s", PD.getEntity().getClass().getName()));
                sbInfo.append("
    ");
                sbInfo.append(String.format("主键值:%s", PD.getId()));
                sbInfo.append("
    ");
                sbInfo.append(String.format("表字段:%s", mapper.writeValueAsString(PD.getPersister().getPropertyNames())));
                sbInfo.append("
    ");
                sbInfo.append(String.format("删数据:%s",mapper.writeValueAsString(PD.getDeletedState())));
                sbInfo.append("
    ");
                sbInfo.append("[ Data ] 删除数据 (End)");
                
                logger.warn(sbInfo);
            } catch (Exception e) {
                logger.error("[ Data ] 删除数据失败", e);
            }
            
        }
    
        @Override
        public void onPostUpdate(PostUpdateEvent PU) {
            try {
                logger = Logger.getLogger(PU.getEntity().getClass());
                
                StringBuffer sbInfo = new StringBuffer();
                sbInfo.append("[ Data ] 修改数据 (Start)");
                sbInfo.append("
    ");
                sbInfo.append(String.format("实体名:%s", PU.getEntity().getClass().getName()));
                sbInfo.append("
    ");
                sbInfo.append(String.format("修改前:%s",mapper.writeValueAsString(PU.getOldState())));
                sbInfo.append("
    ");
                sbInfo.append(String.format("修改后:%s",mapper.writeValueAsString(PU.getEntity())));
                sbInfo.append("
    ");
                sbInfo.append("[ Data ] 修改数据 (End)");
                
                logger.warn(sbInfo);
            } catch (Exception e) {
                logger.error("[ Data ] 数据修改失败", e);
            }
        }
    
        @Override
        public void onPostInsert(PostInsertEvent PI) {
            try {
                logger = Logger.getLogger(PI.getEntity().getClass());
                
                StringBuffer sbInfo = new StringBuffer();
                sbInfo.append("[ Data ] 新增数据 (Start)");
                sbInfo.append("
    ");
                sbInfo.append(String.format("实体名:%s", PI.getEntity().getClass().getName()));
                sbInfo.append("
    ");
                sbInfo.append(String.format("表字段:%s", mapper.writeValueAsString(PI.getPersister().getPropertyNames())));
                sbInfo.append("
    ");
                sbInfo.append(String.format("新增的数据:%s",mapper.writeValueAsString(PI.getState())));
                sbInfo.append("
    ");
                sbInfo.append("[ Data ] 新增数据 (End)");
                
                logger.warn(sbInfo);
            } catch (Exception e) {
                logger.error("[ Data ] 新增数据失败", e);
            }
        }
    
        
    }

    applicationContext.xml文件配置

    <bean id="auditlogEvent" class="com.ytforever.interceptor.UpdateDeleteListener"></bean>
    <bean id="sessionFactory"
            class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <!-- 注入数据源 -->
            <property name="dataSource" ref="dataSource" />
            <!-- 设置Spring取那个包中查找相应的实体类 -->
            <property name="packagesToScan">
                <value>com.ytforever.bean,com.ytforever.workflow.bean</value>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                    <!-- 开发环境下需要,部署环境删除 -->
                    <prop key="hibernate.show_sql">false</prop>
                    <prop key="hibernate.format_sql">true</prop>
                    <prop key="javax.persistence.validation.mode">none</prop>
                    <prop key="hibernate.jdbc.fetch_size">100</prop>
                    <prop key="hibernate.jdbc.batch_size">50</prop>
                </props>
            </property>
            <property name="eventListeners">
                <map>
                    <entry>
                        <key>
                            <value>post-insert</value>
                        </key>
                        <ref bean="auditlogEvent" />
                    </entry>
                    <entry>
                        <key>
                            <value>post-update</value>
                        </key>
                        <ref bean="auditlogEvent" />
                    </entry>
                    <entry>
                        <key>
                            <value>post-delete</value>
                        </key>
                        <ref bean="auditlogEvent" />
                    </entry>
                </map>
            </property>
        </bean>

    效果

     

    小结

    想完成系统访问记录、数据操作记录,重现操作过程。选用框架监听,完成记录,非常好使。

  • 相关阅读:
    LSTM模型与前向反向传播算法
    循环神经网络(RNN)模型与前向反向传播算法
    卷积神经网络(CNN)反向传播算法
    卷积神经网络(CNN)前向传播算法
    卷积神经网络(CNN)模型结构
    深度神经网络(DNN)的正则化
    深度神经网络(DNN)损失函数和激活函数的选择
    ubuntu下如何编译openthread?
    linux下如何删除空行?
    vi下什么快捷键可以完成大小写转换?
  • 原文地址:https://www.cnblogs.com/zl0828/p/9565631.html
Copyright © 2011-2022 走看看