У меня есть приложение Spring MVC, использующее формы.Форма содержит динамический список фильтров, которые можно добавлять или удалять.Мой объект формы просто выглядит следующим образом:
public class RequestForm {
@Valid
List<Filter> filters = new LinkedList<>();
}
Filter
является базовым классом и имеет другие подклассы для возможности пользовательской проверки значения:
public class Filter {
String type;
String value;
boolean ignoreFilter;
}
public IntFilter extends Filter {
@ValueIsInteger
String getValue() {...}
}
public DateFilter extends Filter {
@ValueIsDate
String getValue() {...}
}
В моем контроллере яиспользование @InitBinder
для приведения объектов Filter
в правый подкласс на основе атрибута type
и игнорирования фильтра на основе другого атрибута.Код выглядит так:
@InitBinder
public void initBinder(WebDataBinder webDataBinder, HttpServletRequest httpServletRequest) {
// Filter out all request when we have nothing to do
Object nonCastedTarget = webDataBinder.getTarget();
// TODO: Better cache this in static final field instead
Pattern pattern = Pattern.compile("filters\\[(\\d+)]\\.filterType");
Map<Integer, String> types = new HashMap<>();
Enumeration<String> parameterNames = httpServletRequest.getParameterNames();
while (parameterNames.hasMoreElements()) {
String element = parameterNames.nextElement();
Matcher matcher = pattern.matcher(element);
if (!matcher.matches()) {
continue;
}
types.put(
Integer.parseInt(matcher.group(1)),
httpServletRequest.getParameter(element)
);
}
RequestForm target = (RequestForm) nonCastedTarget;
types.keySet().stream().sorted().forEach(key -> {
//remove disabled filter if("false".equals(httpServletRequest.getParameter("filters["+key+"].ignoreFilter"))) {
switch (types.get(key)) {
case "int":
target.getFilters().add(new IntFilter(httpServletRequest.getParameter("filters["+key+"].value")));
break;
case "date":
target.getFilters().add(new DateFilter(httpServletRequest.getParameter("filters["+key+"].value")));
break;
default:
throw new IllegalStateException("Unknown type: " + types.get(key));
}
}
});
}
А в контроллере:
public ModelAndView postPage(@Valid @ModelAttribute("requestForm") RequestForm requestForm, BindingResult bindingResult, Locale locale) {
ModelAndView mav;
// errors in the selection
if (bindingResult.hasErrors()) {
mav = new ModelAndView("requestmanagement/view");
addRequestFormParameters(mav, requestForm, locale);
return mav;
}
...
}
Моя проблема:
Приведение и проверка подфильтровработает.Однако игнорируемые фильтры все еще добавляются в RequestForm в контроллере.Если моя форма содержит IntFilter
, который следует игнорировать, моя RequestForm в контроллере все еще содержит фильтр, но не преобразуется в подтип.
Кто может удалить фильтр из RequestForm?