Spring Webflow: можно ли устанавливать валидаторы вручную для каждого потока?

В моем приложении настроено несколько потоков:

<flow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" >
    <flow:flow-location id="reservation1"   path="/WEB-INF/flows/flow1.xml" />
    <flow:flow-location id="reservation2"   path="/WEB-INF/flows/flow2.xml" />
</flow:flow-registry>

Эти два потока используют отдельные классы для своего атрибута модели, назовите их Flow1DTO.java и Flow2DTO.java. Однако они используют набор общих JSP/плиток для своего фактического интерфейса.

<form:form modelAttribute="reservationForm">
   <!-- etc -->
</form:form>

Можно ли определить отдельный класс Validator для каждого потока?


person Jason    schedule 23.04.2015    source источник


Ответы (2)


Вы можете определить несколько методов проверки для одного и того же класса модели для каждого конкретного идентификатора состояния представления. Где каждый пользовательский метод проверки сопоставляется с определенным идентификатором состояния просмотра веб-потока.

Имя вашего класса валидатора для вашей модели должно быть определено с именем «${model}Validator» (и иметь аннотацию @Component), и каждое имя метода проверки должно быть названо следующим образом: «validate${state} (модель [ModelClassType] , контекст ValidationContext)"

Итак, скажем, у вас есть класс модели под названием «Reservation.java» и два разных определения потоков, которые используют эту модель, и каждое определение потока, имеющее определения состояния представления

<!-- defined in your first flow file -->
<view-state id="ReservationSameDayViewState" view="sumting" model="reservationForm">
</view-state>
....
<!-- defined in your 2nd flow file -->
<view-state id="ReservationFutureViewState" view="sumting" model="reservationForm">
</view-state>

Класс валидатора для модели Reservation должен выглядеть следующим образом:

@Component
public class ReservationValidator {
    public void validateReservationSameDayViewState(Reservation reservation, ValidationContext context) {
         // perform custom validation for first flow
    }

    public void validateReservationFutureViewState(Reservation reservation, ValidationContext context) {
         // perform custom validation for 2nd flow
    }
}

http://docs.spring.io/autorepo/docs/webflow/2.4.x/reference/html/views.html#view-validation-programmatic-validator

Кроме того, это плохая практика — определять ваши потоки с целыми приращениями. Измените определение вашего потокового реестра, чтобы оно выглядело следующим образом. Таким образом, вам не нужно вручную добавлять к нему потоки каждый раз, когда вы создаете новые потоки.

<flow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" base-path="/WEB-INF/flows">
    <flow-location-pattern value="/**/*-flow.xml" />
</flow:flow-registry>

примечание: имена потоков заканчиваются на «-flow.xml». Это неофициальный стандартный способ определения реестра потоков и имен потоков.

person Selwyn    schedule 24.04.2015
comment
Возможно, я неправильно понял вопрос, являются ли классы моделей Flow1DTO и Flow2DTO. Тогда для решения вашей проблемы будет достаточно просто определить 2 класса валидаторов с именами Flow1DTOValidator и Flow2DTOValidator. - person Selwyn; 24.04.2015
comment
Да, это не сработает. Поскольку определение ‹form:form› всегда использовало одно и то же имя для атрибута модели, но не использовало типы DTO, это было непросто. В конце концов я решил, что сработает один валидатор с перегруженным методом, названным для каждого конкретного проверяемого типа. - person Jason; 24.04.2015
comment
Целые числа в потоке были примером, а не реальным способом, которым я это делал. его можно было заменить чем-то вроде vipReservation и EconomyReservation. - person Jason; 24.04.2015
comment
@ Джейсон, я рад, что ты нашел решение. О, хорошо, шаблон местоположения потока, вам не нужно вручную вводить имена :) - person Selwyn; 24.04.2015

Я нашел решение, которое позволило мне проверять несколько форм с помощью одной реализации валидатора форм.

Код выглядел примерно так:

public void validateMethodName(Flow1DTO dto, ValidationContext context) {
    valMethodName(dto, context);
}

public void validateMethodName(Flow2DTO dto, ValidationContext context) {
    valMethodName(dto, context);
}

private void valMethodName(CommonFlowDTO dto, ValidationContext context) {
    // do stuff
}

Включение методов проверки в сами классы DTO было невозможным. Для проверки требовались обращения к базе данных, что связало бы объекты DTO с бизнес-логикой и несколько усложнило бы создание DTO.

Я обнаружил, что методы проверки не могут указывать интерфейс, что приводит к дублированию методов для каждого конкретного класса DTO.

person Jason    schedule 24.04.2015