Spring @initbinder não invocado ao mostrar o formulário => Customeditores não definidos
-
26-09-2019 - |
Pergunta
Eu tenho o seguinte controlador (simplificado ao osso):
@Controller
public class TestController {
@RequestMapping(value = "/test.htm", method = RequestMethod.GET)
public String showForm(final ModelMap map) {
final TestFilter filter = new TestFilter();
filter.setStartDate(new Date(System.currentTimeMillis()));
map.addAttribute("reportPerResourceForm", filter);
return "test";
}
@InitBinder
public void initBinder(final WebDataBinder binder) {
binder.registerCustomEditor(Date.class, null, new CustomDateEditor(new SimpleDateFormat("dd/MM/yyyy"), true));
}
}
O JSP:
<form:form commandName="reportPerResourceForm" id="reportForm">
<form:input path="startDate" />
</form:form>
Este é um controlador que criei rapidamente para testar um problema que tive com outro controlador de visualização. Como você pode ver no controlador, um alfabetizado é definido. No meu controlador real, este editor está funcionando bem; Quando você entra, por exemplo, 11/01/2010 no campo Formulário, isso é bem convertido em uma data pelo editor; Além disso, ao voltar ao formulário, a data foi novamente bem convertida em uma corda.
No entanto, quando eu (como no testController) deseja definir uma data padrão no formulário, isso é simplesmente exibido uma data.ToString () no campo do formulário em vez de usar o valor retornado do customDateEditor.getastext ()! Após algumas depuração, aprendi que meu método Initbinder não é chamado quando requestMethod == Get. Isso é normal?
Tenho certeza de que poderia mudar isso por não usar
Obrigado pela ajuda,
Stijn
Solução
usar @ModelAttribute
Para configurar o domínio antes de encaminhar para a página.
com cuidado para usar new
Quando você lida com a primavera, ele apenas cria uma nova instância de objeto fora do contexto da primavera e você não pode usar nenhuma capacidade de mola (como encadernação na web, validação etc.).
exemplo :
@RequestMapping(value = "/test.htm", method = RequestMethod.GET)
public String showForm(@ModelAttribute yourDomain, final ModelMap map)
E em seu domínio você pode usar:
@DateTimeFormat(pattern="dd/MM/yyyy")
private Date balance = new Date(System.currentTimeMillis());
Outras dicas
Não tenho certeza, mas o segundo argumento no método RegisterCustomeditor está definido como NULL. Esse argumento é definir o nome do campo com o qual você deseja associar o editor, para que eu não sei exatamente o que vai acontecer quando estiver definido como nulo. Se você deseja usar este editor com todos os campos de um tipo específico, ele existe o mesmo método sem este parâmetro:
public void registerCustomEditor(Class requiredType, PropertyEditor propertyEditor)
Eu tentaria com isso, embora não tenha certeza de que isso resolverá o problema.
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("dd/MM/yyyy"), true));
Espero que ajude.
Para resolver isso, eu mesmo tenho o seguinte código no meu controlador:
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Category.class, new CategoryEditor(categoryService));
}
@ModelAttribute("categoryList") // Populate reference-data (EG select-lists) in the view. (p. 390-
391).
public List<Category> populateCategoryList() {
return categoryService.list();
}
// Note: without adding "BindingResult result" to the following prototype
// (and preceding it with a @ModelAttribute("categoryList") -
// my initBibder() method does not get called!
// I discovered and added this hokum in response to the following links:
// http://forum.springsource.org/showthread.php?46837-InitBinder-not-called
// http://forum.springsource.org/showthread.php?46876-Custom-date-format-on-GET-requests&p=154820
@RequestMapping("/site/list.htm")
@ModelAttribute("sites") // 20110819
public ModelAndView listSite(
@ModelAttribute("category") Category category,
BindingResult result
)
{
// List<Site> sites = siteService.list();
List<Site> sites = new ArrayList<Site>(); // = siteService.list();
return new ModelAndView("siteList", "sites", sites);
}
}
Meus problemas estavam com a minha classe de "categoria" não sendo reconhecida, porque o @initbinder não estava sendo chamado. O "segredo" aqui era modificar meu método "@RequestMapping" para incluir - em seu protótipo - 2 parâmetros que eu não preciso:
@Modelattribute ("categoria") categoria de categoria,
Resultado BindingResult
Isso resolveu tudo (eu sei que não é mágico, apenas fumaça, espelhos e reflexão de Java - mas gostaria que a literatura impressa e on -line abordasse casos de uso simples como esse adequadamente).
Aqui está o código relevante no meu arquivo JSP correspondente:
<div>
Select a category:
<form:select path="category">
<form:options items="${categoryList}" itemValue="id" itemLabel="name"
/>
</form:select>
</div>