- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个小型应用程序,我可以将其指向 Apache HTTP 服务器日志,跟踪日志(Linux 中的“tail -f”),并将条目写入 Oracle 数据库表。
我设置了 Spring Boot/Spring Data JPA 应用程序,并为我的实体创建了类、CrudRepository 接口(interface)、该接口(interface)的服务(尽管我认为这在技术上对于此实现来说是不必要的)以及一个运行者启动该过程。我还设置了 TailerListenerAdapter
来完成日志文件解析的提升。我将在下面发布所有这些代码。
问题是我可以在启动 Tailer 监听器之前成功地将测试记录写入数据库。但是,当监听器运行时,TailerListenerAdapter
中的 Autowired Service 为 null 并引发异常。
java.lang.NullPointerException
at sbx.demo.logauditor.util.AccessListener.handle(AccessListener.java:49)
at org.apache.commons.io.input.Tailer.readLines(Tailer.java:525)
at org.apache.commons.io.input.Tailer.run(Tailer.java:457)
at sbx.demo.logauditor.LogAuditRunner.run(LogAuditRunner.java:40)
{... more stack trace ...}
这是使用的类(我可能在实验中留下了一些不必要的注释)-
LogAuditRunner.java
package sbx.demo.logauditor;
import java.io.File;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import javax.transaction.Transactional;
import org.apache.commons.io.input.Tailer;
import org.apache.commons.io.input.TailerListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import lombok.var;
import sbx.demo.logauditor.model.AccessRecord;
import sbx.demo.logauditor.service.AccessService;
import sbx.demo.logauditor.util.AccessListener;
@Component
public class LogAuditRunner implements CommandLineRunner {
@Autowired
AccessService accServ;
final String datePattern = "dd/MMM/yyyy:HH:mm:ss Z";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(datePattern);
@Override
@Transactional
public void run(String... args) throws Exception {
// This test code works if uncommented
//LocalDateTime TS = LocalDateTime.from(formatter.parse("31/Jan/2020:14:28:32 -0500"));
//var logTest = new AccessRecord("10.154.103.2",Timestamp.valueOf(TS),"/cs/resources/layouts/Top%20Menus/Oracle/tree_T_collection_closed.gif","304");
//System.out.println("Testing repository with " + logTest.toString());
//accServ.save(logTest);
TailerListener listener = new AccessListener();
Tailer tailer = new Tailer(new File("D:\\access_log"), listener);
tailer.run();
}
}
AccessService.java
package sbx.demo.logauditor.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Service;
import sbx.demo.logauditor.model.AccessRecord;
import sbx.demo.logauditor.repository.AccessRepository;
@Service
@Configurable
public class AccessService {
@Autowired(required = true)
AccessRepository accessRepo;
public void save(AccessRecord ar) {
try {
System.out.println("Writing record to database: " + ar.toString());
accessRepo.save(ar);
} catch (Exception e) {
e.printStackTrace();
}
}
public List<AccessRecord> findAll() {
List<AccessRecord> recList = new ArrayList<AccessRecord>();
try {
System.out.println("Searching database for all access records");
for(AccessRecord ar : accessRepo.findAll()) {
recList.add(ar);
}
} catch (Exception e) {
e.printStackTrace();
}
return recList;
}
}
AccessRepository.java
package sbx.demo.logauditor.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import sbx.demo.logauditor.model.AccessRecord;
@Repository
public interface AccessRepository extends CrudRepository<AccessRecord, Long>{
}
AccessRecord.java
package sbx.demo.logauditor.model;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Table(name="ACCESS_LOG")
@Data
public class AccessRecord {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
@Column(name="PROXY_AGENT")
private String agent;
@Column(name="SOURCE_IP")
private String sourceip;
@Column(name="ACCESS_TS")
private Timestamp reqts;
@Column(name="URI")
private String requri;
@Column(name="HTTP_STATUS")
private String respcode;
public AccessRecord() {}
public AccessRecord(String source, Timestamp ts, String uri, String status) {
this.sourceip = source;
this.reqts = ts;
this.requri = uri;
this.respcode = status;
try {
InetAddress ip = InetAddress.getLocalHost();
String hostname = ip.getHostName();
this.agent = hostname;
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public String toString() {
String record = "Record: [" + agent + "] [" + sourceip + "] [" + reqts + "] [" + requri + "] [" + respcode + "]";
return record;
}
}
AccessListener.java
package sbx.demo.logauditor.util;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.transaction.Transactional;
import org.apache.commons.io.input.TailerListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import lombok.var;
import sbx.demo.logauditor.model.AccessRecord;
import sbx.demo.logauditor.repository.AccessRepository;
import sbx.demo.logauditor.service.AccessService;
@Component
public class AccessListener extends TailerListenerAdapter {
final String regex = "^(\\S+) (\\S+) (\\S+) " +
"\\[([\\w:/]+\\s[+\\-]\\d{4})\\] \"(\\S+)" +
" (\\S+)\\s*(\\S+)?\\s*\" (\\d{3}) (\\S+)";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final String datePattern = "dd/MMM/yyyy:HH:mm:ss Z";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(datePattern);
@Autowired
AccessService accServ;
@Override
@Transactional
public void handle(String line) {
LogRecorder lr = new LogRecorder();
try {
final Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
String IP = matcher.group(1);
//String TS = matcher.group(4);
String URL = matcher.group(6);
String STATUS = matcher.group(8);
LocalDateTime TS = LocalDateTime.from(formatter.parse(matcher.group(4)));
var ar = new AccessRecord(IP,Timestamp.valueOf(TS),URL,STATUS);
accServ.save(ar);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
最后是LogauditorApplication.java
package sbx.demo.logauditor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LogauditorApplication {
public static void main(String[] args) {
SpringApplication.run(LogauditorApplication.class, args);
}
}
旁注,我注意到,如果我手动实例化 AccessService
(而不是依赖 Autowiring ),我可以调用它,但随后 NullPointerException
发生在 Autowired 上AccessRepository
接口(interface)。我很清楚这与 Autowiring 有关,我只是不明白为什么。
我知道有一些方法可以通过命令行跟踪和发送日志(这将在 Linux 环境中运行),但我想确保它足够强大,例如,如果死机则重新启动,处理日志翻转另外,我计划编写一些额外的验证,以确保条目不重叠(即,如果应用程序重新启动并重新读取整个文件)。但是,我想先让它工作。我认为这会很简单,因为 Tailer 只需要很少的代码,而且我已经对 Spring 感到满意了。
最佳答案
我可以通过将 AccessService
作为 AccessListener
构造函数的参数传递来实现此功能。然后,我必须将 @Transactional
注释添加到 AccessService
中的 save 方法,以便在线程内处理完每一行后提交事务.
新建AccessListener.java
package sbx.demo.logauditor.util;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.input.TailerListenerAdapter;
import sbx.demo.logauditor.model.AccessRecord;
import sbx.demo.logauditor.service.AccessService;
public class AccessListener extends TailerListenerAdapter {
final String regex = "^(\\S+) (\\S+) (\\S+) " +
"\\[([\\w:/]+\\s[+\\-]\\d{4})\\] \"(\\S+)" +
" (\\S+)\\s*(\\S+)?\\s*\" (\\d{3}) (\\S+)";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final String datePattern = "dd/MMM/yyyy:HH:mm:ss Z";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(datePattern);
private AccessService accServ;
public AccessListener(AccessService as) {
this.accServ = as;
}
// @Autowired
// AccessService accServ;
@Override
public void handle(String line) {
try {
final Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
String IP = matcher.group(1);
String URL = matcher.group(6);
String STATUS = matcher.group(8);
LocalDateTime TS = LocalDateTime.from(formatter.parse(matcher.group(4)));
AccessRecord ar = new AccessRecord(IP,Timestamp.valueOf(TS),URL,STATUS);
accServ.save(ar);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
关于java - Spring JPA CrudRepository Autowired 对象与 Apache Commons Tailer 一起使用时为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60118421/
我有以下情况要解决,但无法正常工作(尝试了Hibernate和EclipseLink): Table_1: Column_A is Primary Key ... some other
我是 JPA 的新手,但必须在该技术中实现我的项目 我想做的是通过 CriteriaQuery 构建一些数据库查询,但不知道如何将参数列表传递给下面的代码: CriteriaBuilder qb =
我是 JPA 新手,注意到可以通过使用 @Version 注释实体中的字段来使用乐观锁定。我只是好奇,如果之前不存在,持久性提供程序是否会创建一个隐式版本字段。例如网站objectdb状态: "Whe
我有一个 JPA 查询 @Query(value = "SELECT SUM(total_price) FROM ... WHERE ...", nativeQuery = true) 当有匹配的记录
JPA 是否会尝试在已经持久(和非分离)的实体上级联持久化? 为了清楚起见,这是我的情况:我想保留一个新用户: public void addUser(){ //User is an enti
显然,OpenJPA。我也看到提到过 EclipseLink 和 Hibernate,但是在功能上有显着差异吗? 最佳答案 大多数差异来自提供者对 OSGi 的感知程度。例如,您可能需要自己将 Hib
我想将 JPA 用于 micronaut。为此,我使用 io.micronaut.data:micronaut-data-hibernate-jpa:1.0.0.M1 库。每当我运行应用程序并点击端点
我正准备为我的应用实现后端,现在我正在投影数据层。我期待着 Spring 。 最佳答案 Spring Data JPA 不是 JPA 实现。它提供了将数据访问层构建到底层 JPA 顶部的方法。您是否应
假设我有一个表 Item,其中包含一个名为 user_id 的列和一个表 User 以及另一个名为 Superuser 的列: CREATE TABLE Item(id int, user_id in
JPA 2.1 规范说: The entity class must not be final. No methods or persistent instance variables of the
我正在从事一个具有一些不寻常实体关系的项目,我在使用 JPA 时遇到了问题。有两个相关对象;用户,让我们称另一个 X。用户与 X 具有一对多和两个一对一的关系。它基本上看起来像这样 [用户实体] @O
我说的是 JavaEE 中的 JPA。在我读过的一本书中谈到: EntityManager em; em.find(Employee.class, id); “这是实体管理器在数据库中查找实例所需的所
我有 JPA 支持的 Vaadin 应用程序。此应用程序中的组件绑定(bind)到 bean 属性(通过独立的 EL 实现)。一些组件绑定(bind)到外部对象(或其字段),由@OneToOne、@O
是否可以使表中的外键唯一?假设我有实体 A 和 B。 答: @Entity class A extends Serializable { @Id private long id; @OneToOne
我在使用 JPA 时遇到了一点问题。考虑这种情况: 表 A (id_a) | 表 B (id_b, id_a) 我需要的是这样的查询: Select a.*, c.quantity from A as
我有一个由 JPA 管理的实体类,我有一个实体需要在其属性中记录更改。 JPA 是否提供任何方法来处理这种需求? 最佳答案 如果您使用 Hibernate 作为 JPA 提供程序,请查看 Hibern
我想实现以下架构: Table A: a_id (other columns) Table B: b_id (other columns) Table C: c_id (other columns)
我有一个愚蠢的问题。如果能做到的话那就太好了,但我并没有屏住呼吸。 我需要链接到我的 JPA 实体的表中的单个列作为所述 JPA 实体中的集合。有什么方法可以让我单独取回与该实体相关的列,而不必取回整
我有一个 Open JPA 实体,它成功连接了多对多关系。现在我成功地获取了整个表,但我实际上只想要该表中的 ID。我计划稍后调用数据库来重建我需要的实体(根据我的程序流程)。我只需要 ID(或该表中
这是我的一个实体的复合主键。 public class GroupMembershipPK implements Serializable{ private static final long
我是一名优秀的程序员,十分优秀!