Статьи

Log2j — Как конвертировать файл журнала в POJO с помощью аннотации


Недавно у меня была работа по созданию статистики по взаимодействию между нашими посетителями и нашей целевой страницей.
Когда посетитель 
загружает наш продукт, требует лицензии или покупает продукт, новая строка вставляется в файл журнала веб-сервера.


Все, что у меня есть, это большой файл журнала с большим количеством информации.

Например, DownloadServlet для каждого запроса на загрузку записывает в журнал контейнера строку в формате
[webapp 2008/10/06 16:12:16] - 192.168.12.124, /download/next-reports-setup-1.7-jre.exe
Я хочу посмотреть статистику по загрузкам. 



Моя идея состоит в том, чтобы преобразовать файл журнала в коллекцию бизнес-объектов (в моем случае это Скачать) и сделать какой-либо запрос 
с помощью 
josql  
или 
cqengine  и
извлечь необходимую информацию. Я также могу вставить все загрузки в 
таблицу базы данных и использовать sql для извлечения необходимой информации. 


С 
Log2j  я могу конвертировать строки журнала в Java-объектах одной строкой:
new Log2j()
    .map(Download.class)
    .addEntityHandler(new DownloadHandler())
    .parse(new InputStreamReader(input));
Что такое Log2j?

Log2j — это крошечный (приблизительно 15 КБ) файл журнала с открытым исходным кодом (около 15 КБ) для преобразования в POJO, с нулевыми зависимостями и быстрой кривой обучения. 
Нет XML, только Java.


Мой первый шаг — создать простой класс POJO с именем Download, имеющим некоторые свойства.
@RegexEntity(pattern = "PATTERN")
public class Download {

    // [webapp 2008/10/06 16:12:16] - 192.168.12.124, /download/next-report-setup-1.7-jre.exe, f13dfc7fe609480297a0b15d611676b4    

    public static final String PATTERN = "\\[webapp\\s"
        + "(20[0-1][0-9]/\\d{2}/\\d{2}\\s\\d{2}:\\d{2}:\\d{2})" // date
        + "\\]\\s-\\s<\\$>\\s"
        + "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})" // ip
        + ",\\s/download/"
        + "([^,]*)" // file 
        + ".*";

    @RegexField(group = 1, converter = MyDateConverter.class)
    private Date date;

    @RegexField(group = 3)
    private String ip;

    @RegexField(group = 4)
    private String file;

    // getters and setters

}
Я добавил аннотацию @RegexEntity (pattern = «PATTERN») в класс Download. @RegexEntity аннотации могут иметь 
параметр с именем шаблон , который представляет собой постоянное имя , которое возвращает регулярное выражение строки. 


Значением по умолчанию является PATTERN (в классе загрузки я добавил значение шаблона для прозрачности). 


Эта аннотация сообщает Log2j, что все строки журнала, соответствующие шаблону, будут преобразованы в 
объекты Download.


Второй шаг — указать, как Log2j будет преобразовывать текстовые фрагменты из строк журнала в свойствах Download. 


Для этого я использовал
аннотацию
@RegexField . Эта аннотация принимает обязательный параметр с именем group, который представляет 
групповой индекс из объекта Matcher java-regex, и необязательный параметр с именем converter, который будет использоваться 
Log2j для преобразования фрагмента текста в значение свойства.

Третий шаг — создать
DownloadHandler для обработки объектов Download.
public class DownloadHandler implements EntityHandler<Download> {

    private int count;

    @Override
    public void beforeFirstEntity() {
        count = 0;
    }

    @Override
    public void handleEntity(Download entity) {
        count++;
        // only display the entity 
        System.out.println(entity);    
    }

    @Override
    public void afterLastEntity() {
        System.out.println("Handled " + count + " Download entities");
    }
}

Методы beforeFirstEntity () и afterLastEntity () являются методами обратного вызова. 

Log2j будет вызывать эти методы один раз в начале / конце разбора журнала. 


Например, вы можете запустить транзакцию базы данных, очистить таблицу сущностей в beforeFirstEntity () 
и зафиксировать транзакцию базы данных в afterLastEntity ().


В приведенном выше примере переменная счетчика инициализации DownloadHandler равна нулю в beforeFirstEntity (), печатает все 
загружаемые объекты в System.out в handleEntity () и печатает счет с сущностями загрузки в afterLastEntity ().


Другая важная концепция в Log2j — это Converter.

Преобразователь используется Log2j для преобразования фрагмента текста в значение свойства Pojo в. 
Log2j поставляется со встроенными преобразователями для всех примитивных значений (Boolean, Byte, Short, …). 

Log2j также позволяет регистрировать новые общие конвертеры (для каждого типа поля) или вы можете зарегистрировать конвертер только для определенного поля.
public class MyDateConverter implements Converter<Date> {

    @Override
    public Date convert(String text) {
        try {
            return new SimpleDateFormat("yyyy/MM/dd").parse(text);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return null;
    }

}
Например, MyDateConverter используется в классе Download Log2j для преобразования фрагмента текста в объект Date. Если вы хотите использовать MyDateConverter для всех полей POJO с типом Date, вы можете сделать это с:

new Log2j()
    ...
    registerConverter(new MyDateConverter();

В моей следующей статье о Log2j я расскажу о проверках и о том, как вы можете опросить коллекцию POJO.