Предполагая следующий класс действий.Выполнение операций CRUD в классе действия вместе с методом prepare() в Struts2
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value="struts-default")
public final class TestAction extends ActionSupport implements Serializable, ValidationAware, Preparable
{
private Long currentPage=1L;
//This method is called on page load.
//Validation is skipped, location is set to a valid action, not "redirectAction", the request is dispatched.
//It is mapped to an action of <s:form>.
public String load() throws Exception
{
//Nothing to see here. Leave it empty.
return ActionSupport.SUCCESS;
}
//Assuming necessary validators and action whose result type is set to "redirectAction".
//It is mapped to an action of <s:submit>.
public String insert()
{
//Do something to either add or update data in a model based on a conditional check.
return ActionSupport.SUCCESS;
}
//Assuming necessary validators and action whose loction is set to a valid action. not "redirectAction".
//The request is dispatched/forwarded.
//It is mapped to an action of <s:a>.
public String edit()
{
//Nothing to see here. Leave it empty.
return ActionSupport.SUCCESS;
}
//Assuming necessary validators and action whose result type is set to "redirectAction".
//It is mapped to an action of <s:submit>.
public String delete()
{
//Do something to delete data from a model.
return ActionSupport.SUCCESS;
}
@Override
public void prepare() throws Exception
{
list= service.getList((int)(currentPage-1)*pageSize, pageSize);
}
}
Я излагал аннотации и другие вещи, чтобы избежать шума кода. В действиях, сопоставленных с этими методами, используется перехватчик paramsPrepareParamsStack
.
Здесь, например, инициируется действие, связанное с методом insert()
(оно выполняется с помощью <s:submit>
), результатом будет действие перенаправления. Соответственно, будет создан новый экземпляр класса действия, который вызывает выполнение метода load()
, который, в свою очередь, снова вызывает метод prepare()
. То же самое произойдет при обновлении и удалении.
Метод prepare()
сначала выполняются, как только действия, связанных с <s:submit>
(или <s:link>
) срабатывает, а затем снова, когда запрос перенаправляется (это можно понять, потому что перенаправление на конкретных результатах запроса в создании нового экземпляра который вызывает действие, связанное с методом load()
, и prepare()
выполняется один раз при каждом действии).
Единственная линия внутри метода prepare()
имеет дорогостоящие операции. Чтобы предотвратить выполнение метода getList()
, я выполняю некоторые условные проверки следующим образом.
@Override
public void prepare() throws Exception
{
String actionName = ActionContext.getContext().getName();
if(actionName.equals("load")||actionName.equals("edit"))
{
list= service.getList((int)(currentPage-1)*pageSize, pageSize);
}
}
Там может быть более условной проверки и сложный код в этом методе.
Выполнение этого по-прежнему недостаточно. Список не будет инициализирован, если какие-либо ошибки (ошибки) проверки/преобразования произойдут из-за условия. Никакие из hasErrors()
, hasActionErrors()
и hasFieldErrors()
будут оцениваться как истинные в методе prepare()
после любых ошибок. Для этого необходимо, чтобы список загружался внутри метода validate()
, как описано ниже.
@Override
public void validate()
{
if(hasErrors())
{
list= service.getList((int)(currentPage-1)*pageSize, pageSize);
}
}
Теперь это соответствует требованиям, но выглядит очень некрасиво иметь такие условные проверки и не может рассматриваться как хороший подход.
Есть ли лучший способ иметь какой-либо механизм, гарантирующий, что извлечение списка из базы данных происходит только один раз после того, как будет выполнен запрос на выполнение таких операций, как вставка, обновление, удаление?
Он не зависит от количества действий, выполняемых за сценой за запрос. Список должен быть получен непосредственно перед завершением запроса только один раз, хотя есть некоторые ошибки преобразования/проверки.
Ничего из @Before
, @BeforeResult
, @After
аннотация, похоже, работает, чтобы обойти эту ситуацию.
Использование такого кода в validate()
метод, который предназначен для извлечения/инициализации списка, кажется, не будет хорошей практикой.
Я ожидаю, что есть способ получить этот список после CRUD операции.Поскольку получение этого списка из базы данных является дорогостоящим, этот список должен быть инициализирован только один раз после каждая операция (вставка, изменение, обновление, удаление) завершена.
Я не уверен, что понимаю. Если вы выполните перенаправление, вы получите новое действие и потребуете новых данных. Если есть ошибка проверки, выполняется метод 'input()'. Вы можете либо проверять жесткий код в 'prepare()', либо создавать методы 'prepareXxx()', где 'xxx' заменяется именами методов, в которых вам нужен этот список. Все это в стороне, рассмотрите кеширование. –
'prepare' вызывается для каждого действия,' validate' вызывается для проверки, оба выполняют разные задания. Кажется, вы застряли с предоставленными методами. Создайте свои собственные методы или свои собственные классы и вызовите эти методы или классы, когда это необходимо. –