Экземпляры области приложения Struts2

Я унаследовал проект Struts2, который нуждается в добавлении некоторых функций. Когда я столкнулся с декодированием, чтобы угадать, как работал предыдущий парень, я обнаружил, что если он хочет, чтобы экземпляр класса создавался только один раз при запуске сервера Tomcat (поскольку он должен считывать большие объемы данных с диска, но только один раз для получить его конфиг, например), он сделал это следующим образом:

public class ExampleClass {
    public ExampleClass(){//Read files and stuff to initialize}
    public Object method(Object[] args){//The job to do}
}

А затем в действии struts, которое его использует, он создает его таким образом:

public class SomeAction extends ActionSupport {
    ExampleClass example = new ExampleClass()
    public String execute() {
        //Do stuff every time the action is called
        Object result = example.method(args);
        // Do stuff with results
    }
}

Со времен сервлета я знаю, что это работает, однако я чувствую, что парень, который занимался этим раньше, был таким же неопытным в Struts2, как и я, поэтому вот мой вопрос:

Правильно ли это делать в соответствии с рекомендациями по стилю и передовой практикой? Предоставляет ли struts2 более контролируемый способ сделать это?

Я нашел здесь несколько ответов, связанных с простыми параметрами, но я не уверен, что это правильный способ для таких объектов? Что произойдет, если экземпляр ExampleClass будет действительно тяжелым? Я не хочу, чтобы их копировали:

Как установить значение в области приложения в struts2?< /а>

Некоторые сведения о ExampleClass: при вызове конструктора он считывает большие наборы файлов и извлекает из них свои конфигурации, создавая сложные внутренние представления. Когда вызывается метод(), он анализирует свои параметры, используя правила, и выводит результаты пользователю. Этот процесс обычно занимает несколько секунд и не изменяет ранее инициализированные значения правила.

Это работает в Tomcat 7, однако я планирую перейти на Tomcat 8.5, когда все будет на месте. Я хотел бы знать, есть ли известные проблемы с этой настройкой (в коде нет других несовместимостей).

Кстати: он не проверяет, не сломан ли ExampleClass или что-то в этом роде, это определенно выглядит как рецепт катастрофы xD. На самом деле, если я удалю исходные файлы, он все равно попытается выполнить метод()... Бедняга...

В идеале мне нужен способ создания экземпляров всех моих объектов уровня приложения при запуске (это само приложение, остальное — просто интерфейс) таким образом, чтобы в случае сбоя Struts2 просил Tomcat не начать эту войну с соответствующей регистрацией ошибок и т. д.

Если Struts2 не поддерживает это, какой общепринятый обходной путь? Может быть, какой-нибудь перехватчик для проверки состояния объекта и возврата на страницу с ошибкой, если он не был правильно создан? Выполнить частичную остановку кота изнутри?

Все объекты этого проекта являются потокобезопасными (единственная операция записи внутри них выполняется при инициализации), но я хотел бы узнать лучшие практики для Struts2, когда объекты не так просты. Что произойдет, если пользователь действительно сможет сломать один из них? (Я знаю, что должен во что бы то ни стало избежать этого, и я это делаю, но ошибки случаются, поэтому мне нужен безопасный способ пройти через них и получить надлежащее предупреждение, и, конечно же, мне нужен способ безопасно восстановить его или остановить вся служба).

Прямо сейчас я могу вручную выполнить что-то вроде:

public class SomeAction extends ActionSupport {
    ExampleClass example = new ExampleClass();
    private boolean otherIsBuildingExample = false;
    public String execute() {
        if(otherIsBuildingExample) return '500 error';
        if(example==null || example.isBroken()){
            otherIsBuildingExample = true;
            example = new ExampleClass();
            otherIsBuildingExample = false;
        }
        Object result = example.method(args);
        // Do stuff with results
    }
}

Действительно, это было бы чище с Interceptors, или так, однако, это звучит как боль в *** для параллелизма, особенно принимая во внимание, что запуск этого примера занимает несколько секунд, и что может поступать больше запросов, поэтому больше проблем для принять во внимание, например: что, если два человека вызывают if(otherIsBuildingExample), а второй получает значение до того, как первый выполнит otherIsBuildingExample=true? Ничего хорошего... Если класс достаточно прост, оба будут создавать экземпляры, и более медленный будет преобладать, но если одно создание экземпляров блокирует ресурсы другого... ну, больше проблем.

Единственное чистое решение, которое я могу придумать, — это сделать ExampleClass достаточно надежным, чтобы вы могли восстановить его, используя его собственные методы (без повторного создания экземпляра), и сделать эти потоки безопасными обычным способом (если 10 человек попытаются его восстановить, только один продолжит, в то время как другие просто ждут окончания первого, чтобы продолжить, например).

Или, может быть, каждый раз, когда вы вызываете execute(), вы получаете копию примера, так что не беспокойтесь об этом?

Я копаюсь в документации по стойкам. Спасибо заранее.


person DGoiko    schedule 09.11.2018    source источник
comment
Есть множество способов справиться с этим; Обычно я делал это с помощью Spring, так как почти каждый проект использовал Spring. В любом случае, все, что вам на самом деле нужно, это синглтон, который кэширует ответ, так что только первое обращение несет затраты. Это не очень сложно.   -  person Dave Newton    schedule 13.11.2018
comment
да, я так и думал, спасибо @DaveNewton.   -  person DGoiko    schedule 14.11.2018