[沫沫金]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("\n");
                sbInfo.append(String.format("访问后台:%s访问[%s]类[%s]方法",ServletActionContext.getRequest().getRemoteAddr(),clazz.getName(),methodName));
                sbInfo.append("\n");
                sbInfo.append(String.format("访问URL:%s",ServletActionContext.getRequest().getRequestURI()));
                sbInfo.append("\n");
                sbInfo.append(String.format("访问参数:%s",mapper.writeValueAsString(ServletActionContext.getRequest().getParameterMap())));
                sbInfo.append("\n");
                sbInfo.append(String.format("返回结果:%s",result));
                sbInfo.append("\n");
                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("\n");
            sbInfo.append(String.format("实体名:%s", PD.getEntity().getClass().getName()));
            sbInfo.append("\n");
            sbInfo.append(String.format("主键值:%s", PD.getId()));
            sbInfo.append("\n");
            sbInfo.append(String.format("表字段:%s", mapper.writeValueAsString(PD.getPersister().getPropertyNames())));
            sbInfo.append("\n");
            sbInfo.append(String.format("删数据:%s",mapper.writeValueAsString(PD.getDeletedState())));
            sbInfo.append("\n");
            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("\n");
            sbInfo.append(String.format("实体名:%s", PU.getEntity().getClass().getName()));
            sbInfo.append("\n");
            sbInfo.append(String.format("修改前:%s",mapper.writeValueAsString(PU.getOldState())));
            sbInfo.append("\n");
            sbInfo.append(String.format("修改后:%s",mapper.writeValueAsString(PU.getEntity())));
            sbInfo.append("\n");
            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("\n");
            sbInfo.append(String.format("实体名:%s", PI.getEntity().getClass().getName()));
            sbInfo.append("\n");
            sbInfo.append(String.format("表字段:%s", mapper.writeValueAsString(PI.getPersister().getPropertyNames())));
            sbInfo.append("\n");
            sbInfo.append(String.format("新增的数据:%s",mapper.writeValueAsString(PI.getState())));
            sbInfo.append("\n");
            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>

效果

 

 

 

小结

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

 

转载于:https://www.cnblogs.com/zl0828/p/9565631.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于JavaWeb网上购物系统的需求分析和数据库设计,我可以为您提供一些建议。首先,我们需要明确系统的功能和目标。 需求分析: 1. 用户注册与登录:用户可以通过注册账号并登录系统,以便进行购物和管理个人信息。 2. 商品浏览与搜索:用户可以浏览系统中的商品,通过关键字搜索或者按照分类进行筛选。 3. 购物车管理:用户可以将商品加入购物车,随时查看购物车中的商品,并进行数量的调整和删除操作。 4. 下单与支付:用户可以选择商品并生成订单,选择支付方式进行支付。 5. 订单管理:用户可以查看自己的订单记录,并进行订单的取消、确认收货等操作。 6. 个人信息管理:用户可以修改个人信息,包括用户名、密码、收货地址等。 7. 后台管理:管理员可以对商品、订单、用户等进行管理和操作数据库设计: 1. 用户表(User):存储用户的基本信息,包括用户ID、用户名、密码、邮箱、电话等。 2. 商品表(Product):存储商品的信息,包括商品ID、名称、价格、库存、图片等。 3. 购物车表(Cart):存储用户购物车中的商品信息,包括购物车ID、用户ID、商品ID、数量等。 4. 订单表(Order):存储用户的订单信息,包括订单ID、用户ID、商品ID、数量、金额、下单时间等。 5. 支付表(Payment):存储用户的支付信息,包括支付ID、订单ID、支付方式、支付金额、支付时间等。 这只是一个简单的需求分析和数据库设计示例,实际项目中还需要根据具体需求进行调整和完善。希望对您有所帮助!如果您有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值