Реализация на чистом Java / JSF для предотвращения двойной отправки

Мы используем JSF 2.0 в WebSphere v8.5 с несколькими библиотеками компонентов PrimeFaces 4.0, Tomahawk 2.0, RichFaces и т. Д.

Я ищу общий механизм, чтобы избежать повторной отправки формы при обновлении страницы или при повторном нажатии кнопки отправки. У меня много приложений с разными сценариями.

На данный момент я подумал об отключении кнопки с помощью фрагмента JavaScript в атрибуте onclick, но это меня не устраивает. Я ищу для этой цели чистую реализацию Java, что-то вроде Struts2 <s:token>.


person Sarz    schedule 25.04.2014    source источник
comment
Решил ли Ajax проблему повторной отправки формы? поскольку отображается только часть страницы, а не вся страница или перенаправление   -  person Sarz    schedule 07.05.2014
comment
Отключение события onClick, вероятно, будет недостаточным, для этого потребуется таймер задержки.   -  person Nassim MOUALEK    schedule 07.05.2014
comment
Да @NassimMOUALEK, я отключу кнопку, пока ajax не завершит рендеринг   -  person Sarz    schedule 07.05.2014
comment
это не совсем проблема, о которой я думал, когда пользователь нажимает несколько раз и очень быстро на кнопку, требуется задержка перед отправкой, чтобы решить, следует ли вам отправлять или нет   -  person Nassim MOUALEK    schedule 07.05.2014
comment
Верно, но я считаю, что веб-страница JS намного быстрее, чем человек (щелкая снова и снова). Первое действие, выполняемое onclick, - это отключение кнопки, чем ajax включит эту кнопку, когда она завершит свой цикл. Таким образом, перекрытие не произойдет.   -  person Sarz    schedule 07.05.2014
comment
У нас проблема с клиентом BNP, они используют только браузер IE, и, полагая, что пользователь IE может щелкнуть дважды одновременно (какая бы страница ни была), мы решаем проблему на уровне транзакции Hibernate, но ее можно исправить с задержкой как я понимаю   -  person Nassim MOUALEK    schedule 07.05.2014


Ответы (3)


Я ищу общий механизм, чтобы избежать повторной отправки формы при обновлении страницы

Для этого есть как минимум 2 решения, которые нельзя комбинировать:

  1. Выполните редирект после синхронного поста. Таким образом, обновление будет повторно выполнять только перенаправленный запрос GET вместо первоначального запроса. Недостаток: вы больше не можете использовать область запроса для обратной связи с конечным пользователем. JSF 2.0 решил эту проблему, предложив новую вспышку. См. Также Как показать сообщение о лицах на перенаправленной странице.

  2. Выполняйте POST асинхронно в фоновом режиме (используя ajax). Таким образом, обновление будет повторно выполнять только первоначальный запрос GET, который открыл форму. Вам нужно только убедиться, что эти формы изначально открываются только запросом GET, т.е. вы никогда не должны выполнять переход от страницы к странице с помощью POST (что само по себе уже является плохим дизайном). См. Также Когда следует использовать h: outputLink вместо h: commandLink? < / а>


или при повторном нажатии кнопки отправки

Для этого есть как минимум 2 решения, которые при необходимости можно комбинировать:

  1. Просто заблокируйте возможность конечного пользователя нажимать кнопку отправки во время отправки и / или после успешной отправки. Для этого есть несколько способов, все в зависимости от конкретных функциональных и дизайнерских требований. Вы можете использовать JavaScript, чтобы отключить кнопку во время отправки. Вы можете использовать атрибуты JSF disabled или rendered, чтобы отключить или скрыть кнопку после отправки. См. Также Как предотвратить двойное нажатие в JSF 2 . Вы также можете использовать оверлейное окно во время обработки запросов ajax, чтобы заблокировать любое взаимодействие конечного пользователя. PrimeFaces имеет <p:blockUI> для этой цели.

  2. Проверить уникальность вновь добавленного объекта на стороне сервера. Это намного надежнее, если вы абсолютно хотите избежать дублирования по техническим причинам, а не по функциональным причинам. Это довольно просто: установите ограничение UNIQUE на рассматриваемый столбец БД. Если это ограничение нарушается, то БД (и структура взаимодействия с БД, такая как JPA) выдаст исключение нарушения ограничения. Лучше всего это делать в сочетании с настраиваемым валидатором JSF, который заранее проверяет ввод, выполняя SELECT именно в этом столбце и проверяя, не возвращается ли запись. Валидатор JSF позволяет отображать проблему в виде сообщения с дружественными лицами. См. Также среди прочего Проверка формата и уникальности электронной почты по базе данных.

person BalusC    schedule 11.05.2014
comment
Я использую <f:ajax /> во всех формах своих приложений, это FlashScope говорит на redirect/reload странице. Как я могу с этим справиться? - person Sarz; 20.05.2014
comment
Пример см. Также по ссылке. - person BalusC; 21.05.2014
comment
Проверка уникальности на стороне сервера может быть сложной. Например, я отправляю смс своему другу. В этом случае нет никакой логики или ограничения для проверки уникальности. Возможно, кеширование и сопоставление запроса дадут вам подсказку, но даже если мы проигнорируем стоимость сопоставления, могут возникнуть бизнес-ситуации, когда запросы с одинаковыми значениями являются частью нормы. - person Mashrur; 07.07.2015

Вместо того, чтобы создавать токен вручную, вы можете использовать решение BalusC. Он предложил шаблон Post-Redirect-GET в своем блоге < / а>

Альтернативные решения можно найти в этих ответах:

person Manuel    schedule 07.05.2014
comment
когда я помещаю ‹f: ajax /› в h: commandButton, теперь это не повторная отправка формы. Полностью ли это соответствует требованиям? - person Sarz; 07.05.2014
comment
Проблема в том, что нам нужно включить и отключить двойную отправку в соответствии с нашим сценарием. - person Sarz; 07.05.2014

person    schedule
comment
Это напечатает сообщение об успешном выполнении, а также сбросит форму. Не забудьте написать ‹p: growl id = messages /› перед запуском тега формы во внешнем интерфейсе. - person Vinod Chauhan; 07.09.2018
comment
Вы можете отредактировать свой ответ и добавить туда соответствующий комментарий - person Kukeltje; 09.09.2018