Предполагая следующий класс действий.
@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
заменяется именами методов, в которых вам нужен список. Все это в стороне, рассмотрите кеширование. - person Dave Newton   schedule 08.01.2014prepare
вызывается для каждого действия,validate
вызывается для проверки, оба выполняют разные задачи. Кажется, вы застряли с предоставленными методами. Создавайте свои собственные методы или классы и вызывайте эти методы или классы при необходимости. - person Roman C   schedule 08.01.2014