在我们的后端系统中,更新对象的情况有很多,比如更新商品、更新商品价格、更新用户、更新状态、更新订单(取消、更新价格)等等。现在有些对象我们有一个专门的日志表,例如 order_update_log ,用于记录更新操作。一些只记录到文件,例如
logger.info("goods update: before: {}, after: {}", oldGoods, newGoods)
感觉处理这些琐碎的事情很烦人,是否存在一些更好的方式/工具来处理这样的记录器?
在我们的后端系统中,更新对象的情况有很多,比如更新商品、更新商品价格、更新用户、更新状态、更新订单(取消、更新价格)等等。现在有些对象我们有一个专门的日志表,例如 order_update_log ,用于记录更新操作。一些只记录到文件,例如
logger.info("goods update: before: {}, after: {}", oldGoods, newGoods)
感觉处理这些琐碎的事情很烦人,是否存在一些更好的方式/工具来处理这样的记录器?
如果您使用 ORM 来持久化您的数据,您可以使用 Hibernate 的 Listners/events 之类的东西来响应数据更新(并将它们记录到数据库或审计日志等)。对于 hibernate,信息在此处进行了详细说明:https ://docs.jboss.org/hibernate/orm/3.3/reference/en/html/events.html但显然您需要调查您的持久性工具提供给您的内容。
有一个很好的东西叫做 Aspects。您可以为您的项目编写只知道跟踪货物对象变化的方面。假设你有Goods
课:
public class Goods {
private Integer id;
private String name;
private BigDecimal cost;
// Getters, Setters
...
}
它映射到具有相应字段的数据库表货物:
CREATE TABLE `goods` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` varchar NOT NULL,
`cost` DECIMAL NOT NULL,
PRIMARY KEY (`id`)
);
假设你有GoodsService
:
public class GoodsService {
public Goods read(Integer id) {
Goods goods = /* Read goods from database */
return goods;
}
public void write(Goods goods) {
/* Write goods to database */
}
}
并且GoodsController
使用GoodsService
:
public class GoodsController {
private GoodsService goodsService;
public void updateGoods(Integer id, String name, BigDecimal cost) {
Goods goods = goodsService.read(id);
goods.setName(name);
goods.setCost(cost);
goodsService.write(goods);
}
}
因此,让我们为您的项目添加一些方面的魔法来跟踪商品的变化。现在创建另一个表,其中包含用于存储user
和datetime
更新goods
对象的附加字段:
CREATE TABLE `goods_log` (
`revision` INT NOT NULL AUTO_INCREMENT,
`id` INT NOT NULL,
`name` varchar NOT NULL,
`cost` DECIMAL NOT NULL,
`user` varchar NOT NULL,
`timestamp` DATETIME NOT NULL,
PRIMARY KEY (`revision`,`id`)
);
编写方面类:
@Aspect
public class GoodsLogger {
@Before(value = "execution(* org.antonu.service.GoodsService.write(..)) && args(goods)")
public void logWrite(Goods goods) {
// Get current user and timestamp,
// Write it to goods_log table, as well as goods data
}
}
而已!您的业务逻辑代码没有改变,读起来很清楚。但是每次调用 GoodsService 的 write 方法时,您都会在商品日志中记录新的商品状态。
为了使这段代码工作,它应该用 AJC 编译器编译,还应该包括 aspectjrt 库。它可以通过maven轻松完成:
<properties>
<aspectj.version>1.8.7</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
现代 IDE Intellij Idea 应该自动使用AJC
带有上述 maven 配置的编译器。如果没有,您必须通过File - Settings - 'Build, Execution, Deployment' - Compiler - Java Compiler - Use compiler: Ajc.
Path to AJC 编译器配置编译器:<path_to>/aspectjtools-1.8.7.jar