gpt4 book ai didi

java - Spring JPA CrudRepository Autowired 对象与 Apache Commons Tailer 一起使用时为 null

转载 作者:行者123 更新时间:2023-12-02 09:01:38 25 4
gpt4 key购买 nike

我正在开发一个小型应用程序,我可以将其指向 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com