- 浏览: 167089 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
mengyue0477:
最后还不忘吐槽一下 哈哈 太逗了
spring容器的懒加载lazy-init设置 -
comet0515:
不是maven工程能不能用checkstyle插件?job是一 ...
jenkins 配置checkstyle -
xfxlch:
http://docs.spring.io/spring-bo ...
NoteBook -
With_Me_Forever:
太浅了。我最近也在看着方面的资料,一起进步把。
互联网金融定义 -
xfxlch:
在http://r.m.baidu.com/6pmxgig
NoteBook
需求:
对所有操作数据库的事件,添加audit log, 此log持久化到一张单独的audit_log表,以供操作人员可以查阅跟踪。
方案:
Hibernate Interceptor 提供了一个拦截器,使用切面的方法,拦截所有对DB的操作,like:persist, merge, remove event。
实现:
首先是创建一个AuditlogInterceptor,来实现对数据库操作的拦截。 这个Interceptor要继承Hibernate的EmptyInterceptor, 然后我们同时重写onsave,ondelete,onFlushDirty, postFlush等方法来实现我们自己的需求:
其次把这个拦截器配置到我们的事务里去。
配置文件:比如数据源配置文件:datasource-context.xml:
添加:
由于这里是我自己去创建了一个PersistenceUnit,所以Hibernate会要求有一个persistence.xml文件,在META-INFO 文件夹下面,我们只要创建这个文件,并不需要指定,Hibernate会自动到该目录下去查找这个文件,文件名不能写错:
最后就是要去创建Entity来保持audit log, 比如AuditEntity.java
--EOF--
对所有操作数据库的事件,添加audit log, 此log持久化到一张单独的audit_log表,以供操作人员可以查阅跟踪。
方案:
Hibernate Interceptor 提供了一个拦截器,使用切面的方法,拦截所有对DB的操作,like:persist, merge, remove event。
实现:
首先是创建一个AuditlogInterceptor,来实现对数据库操作的拦截。 这个Interceptor要继承Hibernate的EmptyInterceptor, 然后我们同时重写onsave,ondelete,onFlushDirty, postFlush等方法来实现我们自己的需求:
public class AuditLogInterceptor extends EmptyInterceptor { /** * serialVersionUID */ private static final long serialVersionUID = -4829761117655964386L; private static final Logger logger = LoggerFactory.getLogger(AuditLogInterceptor.class); private static final String EMPTY_STRING = ""; private static final String DELETE = "postFlush - delete"; private static final String INSERT = "postFlush - insert"; private static final String UPDATE = "postFlush - update"; private static EntityManager entityManager = null; static { entityManager = Persistence.createEntityManagerFactory("auditLog").createEntityManager(); } //FIXME thread local private Set<IAuditable> inserts = new HashSet<IAuditable>(); private Set<IAuditable> updates = new HashSet<IAuditable>(); private Set<IAuditable> deletes = new HashSet<IAuditable>(); @Override public synchronized boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException { logger.info("onSave"); if (entity instanceof IAuditable) { inserts.add((IAuditable)entity); } return false; } @Override public synchronized boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) throws CallbackException { logger.info("onFlushDirty"); if (entity instanceof IAuditable) { updates.add((IAuditable)entity); } return false; } @Override public synchronized void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { logger.info("onDelete"); if (entity instanceof IAuditable) { deletes.add((IAuditable)entity); } } /** * called before commit into database */ @SuppressWarnings("rawtypes") @Override public void preFlush(Iterator iterator) { logger.info("preFlush"); } /** * called after committed into database */ @SuppressWarnings("rawtypes") @Override public synchronized void postFlush(Iterator iterator) { logger.info("postFlush"); String username = SecurityContextHolder.getContext().getAuthentication().getName(); Collection collection = SecurityContextHolder.getContext() .getAuthentication() .getAuthorities(); String role = collection.toString(); if (inserts.isEmpty() && updates.isEmpty() && deletes.isEmpty()) { return; } try { if (!entityManager.getTransaction().isActive()) { entityManager.getTransaction().begin(); } for (IAuditable entity : inserts) { persistenceEntity(entity, entityManager, username, role, INSERT, null); } for (IAuditable entity : updates) { IAuditable preStateEntity = null; preStateEntity = entityManager.find(entity.getClass(), entity.getId()); List<String> valueList = getNewOldValues(entity, preStateEntity); String oldValues = valueList.get(0); String changeValues = valueList.get(1); if (!oldValues.equals(changeValues)) { persistenceEntity(entity, entityManager, username, role, UPDATE, valueList); } } for (IAuditable entity : deletes) { persistenceEntity(entity, entityManager, username, role, DELETE, null); } } catch (Exception e) { e.printStackTrace(); } finally { updates.clear(); inserts.clear(); deletes.clear(); if (entityManager.isOpen() && entityManager.getTransaction().isActive()) { logger.info("finally cause"); entityManager.getTransaction().commit(); } } } private void persistenceEntity(IAuditable entity, EntityManager em, String username, String role, String comments, List<String> changeValueslist) { logger.info(comments); AuditLogEntity logEntity = new AuditLogEntity(); logEntity.setComments(comments); logEntity.setOperator(StringUtils.isEmpty(username) ? "default" : username); logEntity.setRole(StringUtils.isEmpty(role) ? "default" : role); logEntity.setCreatedOn(new Date()); //sql date? logEntity.setUpdatedOn(new Date()); if (changeValueslist == null && DELETE.equals(comments)) { logEntity.setNewvalue(EMPTY_STRING); logEntity.setOldvalue(entity.getLogDeatil()); } else if (changeValueslist == null && INSERT.equals(comments)) { logEntity.setNewvalue(entity.getLogDeatil()); logEntity.setOldvalue(EMPTY_STRING); } else if (UPDATE.equals(comments)) { String newvalue = changeValueslist.get(1); String oldvalue = changeValueslist.get(0); logEntity.setNewvalue(newvalue); logEntity.setOldvalue(oldvalue); } logEntity.setEntity(entity.getClass().getName()); em.persist(logEntity); } }
其次把这个拦截器配置到我们的事务里去。
配置文件:比如数据源配置文件:datasource-context.xml:
添加:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="auditLog" /> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="com.statestreet.fcm.cfd" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> <!-- new added <property name="persistenceXmlLocation" value="classpath:persistence.xml" /> --> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.cache.use_second_level_cache">false</prop> <prop key="hibernate.cache.use_query_cache">false</prop> <prop key="hibernate.use_sql_comments">false</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop> <!-- by clu --> <prop key="hibernate.ejb.interceptor">com.statestreet.fcm.cfd.interceptor.AuditLogInterceptor</prop> </props> </property> </bean>
由于这里是我自己去创建了一个PersistenceUnit,所以Hibernate会要求有一个persistence.xml文件,在META-INFO 文件夹下面,我们只要创建这个文件,并不需要指定,Hibernate会自动到该目录下去查找这个文件,文件名不能写错:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="auditLog" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.archive.autodetection" value="class"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/> <property name="hibernate.connection.url" value="jdbc:oracle:thin:@"/> <property name="hibernate.connection.password" value="123"/> <property name="hibernate.connection.username" value="123"/> <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/> <property name="hibernate.c3p0.min_size" value="5"/> <property name="hibernate.c3p0.max_size" value="20"/> <property name="hibernate.c3p0.timeout" value="300"/> <property name="hibernate.c3p0.max_statements" value="50"/> <property name="hibernate.c3p0.idle_test_period" value="3000"/> </properties> </persistence-unit> </persistence>
最后就是要去创建Entity来保持audit log, 比如AuditEntity.java
@Entity @Table(name = "AUDIT_LOG_DETAIL") public class AuditLogEntity implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = -1275702854046959229L; @Id @GeneratedValue private Long id; @Column(nullable = false ) private String operator; @Column(nullable = false ) private String role; @Column private String entity; @Column private String oldvalue; @Column private String newvalue; @Column private String comments; @Column(nullable = false) private Date createdOn; @Column(nullable = false) private Date updatedOn; }
--EOF--
发表评论
-
eclipse project .setting
2016-08-24 11:30 602有一个文件在.setting的目录下面: 文件名:org.ec ... -
jar命令工具
2016-01-23 20:29 688背景: 今天介绍两个jar的命令工具,对我个人来说,还是比较好 ... -
Java的按值传递
2016-01-23 19:30 555问题: 最近在看Mar ... -
Mac OS 安装java 开发环境
2016-01-03 13:00 1771我的机器是: 1. jdk1.7下载安装 jdk7:h ... -
记一次Java Rest Service Hang住的经历
2015-12-28 20:08 2698背景: 在前后端分开开发的过程中,前段的页面要调用后台Java ... -
一个String字符串的问题2
2015-12-14 14:22 609背景: 今天遇到个问题: String str = & ... -
我读重构这本书
2015-12-01 22:30 0第一点:关注变量命名。好的变量名能让读者更快更好的理解程序到底 ... -
系统log的编写
2015-11-16 09:41 0log很关键,一定要记录好对追踪问题有帮助的日志。 -
CAS 授权问题
2015-11-16 09:40 0CAS 授权问题 -
Caused by: java.lang.UnsupportedOperationException 解决方案
2015-10-21 22:09 4062背景: 今天在跑一个UnitTest,跑的过程中想在list ... -
LogBack 框架里log-access的使用
2015-10-18 16:05 7096背景: 想通过配置log-access来实现直接使用浏览器来访 ... -
how to fix "org.hamcrest.CoreMatchers.containsString cannot be resolved"
2015-09-23 23:12 3025背景: 山姆大叔比较喜欢用一些新的技术和新的特性,最近在jun ... -
java 打印金字塔
2015-08-24 00:53 781背景: 一个同事,面试应聘者喜欢用学校里学过的一个书本或者课后 ... -
纯jsp servlet 实现 upload file功能
2015-08-17 20:35 738本篇主要是简单的实现jsp servlet 的上传文件的功能, ... -
dos 命令窗口執行java 命令,帶包路徑
2015-07-26 12:16 532記錄一下,是為了自己下次再run java命令的時候,可以很快 ... -
tomcat 远程调试
2015-07-23 18:41 489背景: 我们在项目开发过程中,很多时候会遇到这样的情况:项目在 ... -
使用android studio 来开发hello world app的时候,遇到的一些坑。
2015-07-13 01:38 2160使用android studio 来开发h ... -
ThreadLocal
2015-05-11 07:22 422Java线程:深入ThreadLocal ThreadLo ... -
eclipse 加入tomcat 包
2015-03-24 01:09 430... -
Transforming XML with XSLT
2014-10-11 19:14 524public static void catalog() ...
相关推荐
为了更好地控制持久化行为,Hibernate 提供了一个强大的事件处理机制,其中就包括了拦截器(Interceptor)。拦截器允许开发者在对象状态变化时执行自定义逻辑,比如更新时间戳、记录审计日志等。 #### 定义拦截器 ...
拦截器 interceptor 过滤器 filter web.xml implements filter filterchain arg2.doFilter(req,resp); 监听器 servlet application /session /request 6/8 个 1、拦截器 定义拦截器的包 定义拦截器的...
Struts1 框架是Java Web开发中的一个经典MVC框架,它的核心组件之一就是拦截器(Interceptor)。拦截器在Struts1中扮演着重要角色,它允许开发者在动作执行前后插入自定义的逻辑,比如日志记录、权限验证、事务管理...
例如,可以创建一个名为`LoginInterceptor`的拦截器,然后在`<package>`标签内使用`<interceptors>`和`<interceptor>`来声明和配置它。 2. **拦截器实现**:创建一个实现`Interceptor`接口的类,重写`intercept()`...
1. **定义拦截器**:在Struts2中,我们需要创建一个实现了`com.opensymphony.xwork2.interceptor.Interceptor`接口的类。这个类将包含拦截逻辑,例如检查session中是否存在登录信息。 2. **配置拦截器**:在`struts....
**拦截器(Interceptor)**是Struts2框架的核心特性之一,它允许开发者在Action执行前后插入自定义逻辑。拦截器可以用来实现日志记录、权限检查、事务处理等跨切面的功能。在登录场景中,拦截器通常用于验证用户的...
在Java Web开发中,拦截器(Interceptor)是一种重要的设计模式,尤其在框架如Spring MVC或Struts2中,用于在请求处理之前或之后执行特定逻辑。在这个“拦截器登陆权限验证案例”中,我们将深入探讨如何在Struts2...
在SSH(Struts2、Spring、Hibernate)框架中,权限管理和日志拦截器是两个重要的概念,它们在大型企业级应用开发中起到了关键作用。SSH框架允许开发者通过拦截器(Interceptor)来增强或修改默认的请求处理流程。...
Struts2的核心组件包括Action(业务逻辑处理)、Result(展示结果)、Interceptor(拦截器)和配置文件(struts.xml)。开发者可以通过定义Action类来实现业务逻辑,然后通过配置Action和Result来定义请求和响应的...
在Java Web开发中,过滤器(Filter)和拦截器(Interceptor)是两种常见的处理请求和响应的机制,它们各自有着不同的特性和应用场景。下面将详细解释这两种技术的区别以及它们在SSH(Spring、Struts和Hibernate)...
在Struts2中,拦截器(Interceptor)扮演着核心角色,它们允许开发者插入自定义的逻辑来扩展或增强Action执行的流程。在这个“Struts2拦截器的简单登录应用”中,我们将深入理解如何利用拦截器实现用户登录验证。 ...
在SSH2框架中,拦截器(Interceptor)是非常重要的组件之一,它可以用来增强Action的功能,比如权限检查、日志记录等。为了更好地利用Spring的依赖注入功能,可以通过以下步骤在拦截器中注入Spring管理的对象: 1. ...
在SSH(Struts2、Spring、Hibernate)系统中,拦截器用于增强应用程序的功能,比如权限检查、日志记录、事务管理等。在本场景中,我们关注的是如何利用Struts拦截器来实现一个等待页面,以提升用户体验。 当系统...
2. **拦截器(Interceptor)**:Hibernate提供了一个非常强大的扩展点——拦截器,它可以用来拦截实体的各种生命周期事件。通过实现`org.hibernate.event.spi.Interceptor`接口,可以自定义拦截器逻辑,比如修改SQL...
使用Hibernate拦截器检测Persistence Context中的实体更改 使用Hibernate拦截器对数据库中的实体更改做出React 使用观察者设计模式来监视实体持久性更改并对其做出React 使用命令设计模式提供一种通用方法,可将...
**三、拦截器(Interceptor)与事件监听器(Listener)** Hibernate提供拦截器和事件监听器来扩展其行为。Interceptor是在特定操作(如保存、更新、删除等)执行前后被调用的接口,允许用户自定义行为。Listener则是...
拦截器(Interceptor)是Struts2框架中的关键组件之一,用于在执行Action之前或之后进行一系列的预处理或后处理任务。例如,它可以用于身份验证、日志记录、数据校验等。拦截器的设计遵循AOP(面向切面编程)思想,...
- **拦截器定义**: 拦截器可以是实现了 Interceptor 接口的类,也可以是继承了 AbstractInterceptor 或 MethodFilterInterceptor 抽象类的类。 - **自定义拦截器**: 可以通过实现 Interceptor 接口或继承 ...
在实际应用中,Struts2与Hibernate的集成通常通过拦截器(Interceptor)实现。例如,我们可以创建一个自定义的登录拦截器,该拦截器在Action执行之前检查用户的登录状态。如果用户未登录,拦截器会重定向到登录页面...
Struts 2是Struts 1的升级版,它基于MVC设计模式,提供了强大的动作(Action)和结果(Result)管理,以及强大的拦截器(Interceptor)机制。Struts 2的核心组件包括: 1. **Action类**:处理用户请求的业务逻辑。 ...