Documentação originalSegunda parteTerceira parteSumário:
1. Integração do timelo com o Spring
2. Dialeto SpringStandard
3. Exibições e exibições de resolvedores
3.1 Exibições e exibições de resolvedores no Spring MVC
3.2 Exibições e exibições de resolvedores no Thymeleaf
4. Gerente de iniciação de sementes de tomilho de primavera
4.1 Conceito
4.2 Camada de negócios
4.3 Configuração do Spring MVC
4.4 Controlador
4.5 Configurando o serviço de conversão
5 Exibir dados iniciais de sementes
6 Criando formulários
6.1 Processando um objeto de comando
6.2 Entradas
6.3 Campos da caixa de seleção
6.4 Campos dos botões de opção
6.5 Seletores suspensos / lista
6.6 Campos dinâmicos
7 Mensagens de verificação e erro
7.1 Erros de campo
7.2 Todos os erros
7.3 Erros globais
7.4 Exibindo erros fora dos formulários
7.5 Objetos de erro avançados
8 Este ainda é um protótipo!
9 O serviço de conversão
9.1 Configuração
9.2 Sintaxe de colchetes duplos
9.3 Uso em formulários
9.4 #conversions objeto de conversão
10 Fragmentos de renderização do modelo Fragmentos de modelo (AJAX etc)
10.1 Definindo fragmentos em um bean de exibição
10.2 Definindo fragmentos no valor de retorno do controlador
11 Recursos avançados de integração
11.1 Integração com RequestDataValueProcessor
11.1 Criando URIs para controladores
12 Integração do Spring WebFlow
12.2 Snippets AJAX no Spring WebFlow
Este guia explica como o
Thymeleaf pode ser integrado ao Spring Framework, especialmente (mas não apenas) o Spring MVC.
Observe que o Thymeleaf possui integrações para as versões 3.xe 4.x do Spring Framework e superior, fornecidas por duas bibliotecas separadas chamadas thymeleaf-spring3 e thymeleaf-spring4. Essas bibliotecas são empacotadas em arquivos .jar separados (thymeleaf-spring3- {version} .jar e thymeleaf-spring4- {version} .jar) e devem ser adicionadas ao caminho da sua classe para usar as integrações do Thymeleaf Spring em seu aplicativo.
As amostras de código e aplicativos de amostra neste guia usam o Spring 4.xe suas integrações Thymeleaf correspondentes, mas o conteúdo deste texto também se aplica ao Spring 3.x. Se seu aplicativo usa o Spring 3.x, tudo o que você precisa fazer é substituir o pacote org.thymeleaf.spring4 por org.thymeleaf.spring3 nos exemplos de código.
1. Integração do timelo com o Spring
O Thymeleaf oferece um conjunto de integrações do Spring que permitem que ele seja usado como uma substituição JSP com todos os recursos nos aplicativos Spring MVC.
Essas integrações permitem:
- Faça um mapeamento para os métodos nos objetos do Spring MVC Controller de padrões gerenciados pelo Thymeleaf, assim como o JSP.
- Use Spring Expression Language (Spring EL) em vez de OGNL em seus modelos.
- Crie formulários em seus modelos totalmente integrados aos componentes e beans de suporte a seu formulário, incluindo o uso de editores de propriedades, serviços de conversão e tratamento de erros de validação.
- Exibir mensagens de internacionalização de arquivos de mensagens gerenciados pelo Spring (por meio de objetos regulares MessageSource).
- Encontre seus padrões usando mecanismos nativos de resolução de recursos do Spring.
Observe que, para entender completamente este tutorial, você deve primeiro passar pelo
tutorial "
Usando o Thymeleaf ", que explica o dialeto padrão em detalhes.
2. Dialeto SpringStandard
Para obter uma integração mais fácil e melhor, o Thymeleaf fornece um dialeto que implementa especificamente todas as funções necessárias para trabalhar corretamente com o Spring.
Esse dialeto específico é baseado no dialeto Thymeleaf padrão e é implementado na classe org.thymeleaf.spring4.dialect.SpringStandardDialect, que na verdade deriva de org.thymeleaf.standard.StandardDialect.
Além de todas as funções já presentes no dialeto padrão e, portanto, herdadas, o SpringStandard Dialect oferece as seguintes funções específicas:
- Usando Spring Expression Language (Spring EL ou SpEL) como uma linguagem de expressão variável, não OGNL. Portanto, todas as expressões $ {...} e * {...} serão avaliadas pelo mecanismo da linguagem de expressões Spring. Observe também que o suporte ao compilador Spring EL (Spring 4.2.4+) está disponível.
- Acesse qualquer componente no contexto do seu aplicativo usando a sintaxe SpringEL: $ {@ myBean.doSomething ()}
- Novos atributos para processar o formulário: th: field , th: errors e th: errorclass , exceto para a nova implementação do th: object , que permite usá-lo para selecionar o comando do formulário.
- O método de objeto e expressão é # themes.code (...) , que é equivalente à tag customizada JSP spring: theme .
- O método de objeto e expressão, # mvc.uri (...) , que é equivalente à função customizada JSP spring: mvcUrl (...) (apenas no Spring 4.1+).
Observe que, na maioria dos casos, você não deve usar esse dialeto diretamente em um objeto TemplateEngine regular como parte de sua configuração. Se você não tiver necessidades especiais de integração com o Spring, crie uma instância de uma nova classe de modelo que execute automaticamente todas as etapas de configuração necessárias:
org.thymeleaf.spring4.SpringTemplateEngine .
Exemplo de configuração do bean:
@Bean public SpringResourceTemplateResolver templateResolver(){
Ou usando a configuração Spring baseada em XML:
<bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/templates/" /> <property name="suffix" value=".html" /> <property name="templateMode" value="HTML" /> <property name="cacheable" value="true" /> </bean> <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine"> <property name="templateResolver" ref="templateResolver" /> <property name="enableSpringELCompiler" value="true" /> </bean>
3. Exibições e exibições de resolvedores
3.1 Exibições e exibições de resolvedores no Spring MVC
O Spring MVC possui duas interfaces que correspondem ao núcleo do seu sistema de modelos:
- org.springframework.web.servlet.View
- org.springframework.web.servlet.ViewResolver
Visualiza as páginas de modelo em nossos aplicativos e permite alterar e predeterminar o comportamento delas, definindo-as como componentes do bean. As visualizações são responsáveis por renderizar a interface HTML real, como regra, pela execução de algum tipo de mecanismo de modelo, por exemplo, Thymeleaf.
ViewResolvers são objetos responsáveis pela obtenção de objetos
View para uma operação e localidade específicas. Normalmente, os controladores solicitam ao ViewResolvers que encaminhe a visualização com um nome específico (a sequência retornada pelo método do controlador) e, em seguida, todos os meios de resolver a visualização no aplicativo são executados em uma cadeia ordenada até que um deles possa resolver essa visualização. Nesse caso, o objeto View é retornado e o controle é transferido para ele para renderizar HTML.
Observe que nem todas as páginas em nossos aplicativos devem ser definidas como visualizações, mas apenas aquelas cujo comportamento queremos que não seja padrão ou personalizado de uma maneira especial (por exemplo, conectando alguns componentes especiais). Se um ViewResolver for solicitado para uma visualização que não possua um bean correspondente (que é um caso comum), uma nova Visualização será criada ad hoc e retornada.Uma
configuração típica
JSP + JSTL ViewResolver em um aplicativo Spring MVC do passado era assim:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsps/" /> <property name="suffix" value=".jsp" /> <property name="order" value="2" /> <property name="viewNames" value="*jsp" /> </bean>
Uma rápida olhada em suas propriedades é suficiente para descobrir como foi configurado:
- viewClass define a classe de instâncias de exibição. Isso é necessário para o reconhecedor JSP, mas não quando estamos trabalhando com o Thymeleaf.
- O prefixo e o sufixo funcionam de maneira semelhante aos atributos com o mesmo nome nos objetos Thymeleaf TemplateResolver.
- order define a ordem em que o ViewResolver será solicitado na cadeia.
- O viewNames permite definir (com caracteres curinga) os nomes das visualizações que este ViewResolver resolverá.
3.2 Exibições e exibições de resolvedores no Thymeleaf
O Thymeleaf oferece implementações para as duas interfaces mencionadas acima:
- org.thymeleaf.spring4.view.ThymeleafView
- org.thymeleaf.spring4.view.ThymeleafViewResolver
Essas duas classes serão responsáveis pelo tratamento de modelos Thymeleaf como resultado da execução dos controladores.
A configuração da Resolver Thymeleaf View é muito semelhante ao JSP:
@Bean public ThymeleafViewResolver viewResolver(){ ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setTemplateEngine(templateEngine());
... ou em XML:
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver"> <property name="templateEngine" ref="templateEngine" /> <property name="order" value="1" /> <property name="viewNames" value="*.html,*.xhtml" /> </bean>
O parâmetro
templateEngine , é claro, é o objeto SpringTemplateEngine que definimos no capítulo anterior. Os outros dois (
order e
viewNames ) são opcionais e têm o mesmo significado que no JSP ViewResolver, que vimos anteriormente.
Observe que não precisamos de parâmetros de prefixo ou sufixo, porque eles já estão especificados no resolvedor de modelos (que, por sua vez, são passados para o mecanismo de modelos).
Mas e se quisermos definir um
bean View e
adicionar algumas variáveis estáticas ? Fácil, basta definir um protótipo para ele:
@Bean @Scope("prototype") public ThymeleafView mainView() { ThymeleafView view = new ThymeleafView("main");
Feito isso, você pode solicitar esse componente selecionando-o pelo nome (neste caso, mainView).
4. Gerente de iniciação de sementes de tomilho de primavera
O código fonte dos exemplos mostrados neste e nos capítulos subseqüentes deste guia pode ser encontrado no repositório do
GitHub Spring Seyme Seed Starter Manager .
4.1 Conceito
Em relação ao Thymeleaf, somos grandes fãs de tomilho, e a cada primavera preparamos nossos kits iniciais com bom solo e nossas sementes favoritas, plantamos sob o sol espanhol e esperamos pacientemente que nossas novas plantas cresçam.
Mas este ano, estávamos cansados de colar etiquetas nos contêineres iniciais para descobrir o que havia em cada célula do contêiner, por isso decidimos preparar o aplicativo usando o Spring MVC e o
Thymeleaf para nos ajudar a catalogar nossos iniciantes:
Spring Thyme SeedStarter Manager .

Semelhante ao aplicativo Good Thymes Virtual Grocery, desenvolvido no tutorial Usando o Thymeleaf, o STSM nos permite demonstrar os aspectos mais importantes da integração do Thymeleaf como um mecanismo de modelo para o Spring MVC.
4.2 Camada de negócios
Vamos precisar de uma camada de negócios muito simples para nosso aplicativo. Primeiro de tudo, vamos olhar para nossos objetos de modelo:

Algumas classes de serviço muito simples fornecerão os métodos de negócios necessários. Como:
@Service public class SeedStarterService { @Autowired private SeedStarterRepository seedstarterRepository; public List<SeedStarter> findAll() { return this.seedstarterRepository.findAll(); } public void add(final SeedStarter seedStarter) { this.seedstarterRepository.add(seedStarter); } }
E:
@Service public class VarietyService { @Autowired private VarietyRepository varietyRepository; public List<Variety> findAll() { return this.varietyRepository.findAll(); } public Variety findById(final Integer id) { return this.varietyRepository.findById(id); } }
4.3 Configuração do Spring MVC
Em seguida, precisamos
definir a configuração do Spring MVC para o aplicativo, que incluirá não apenas artefatos padrão do Spring MVC, como processamento de recursos ou varredura de anotações, mas também instanciação do
Template Engine e do
View Resolver .
@Configuration @EnableWebMvc @ComponentScan public class SpringWebConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware { private ApplicationContext applicationContext; public SpringWebConfig() { super(); } public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); registry.addResourceHandler("/images/**").addResourceLocations("/images/"); registry.addResourceHandler("/css/**").addResourceLocations("/css/"); registry.addResourceHandler("/js/**").addResourceLocations("/js/"); } @Bean public ResourceBundleMessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("Messages"); return messageSource; } @Override public void addFormatters(final FormatterRegistry registry) { super.addFormatters(registry); registry.addFormatter(varietyFormatter()); registry.addFormatter(dateFormatter()); } @Bean public VarietyFormatter varietyFormatter() { return new VarietyFormatter(); } @Bean public DateFormatter dateFormatter() { return new DateFormatter(); } @Bean public SpringResourceTemplateResolver templateResolver(){
4.4 Controlador
Obviamente, também precisamos de um controlador para nossa aplicação. Como o STSM conterá apenas uma página da web com uma lista de valores iniciais e um formulário para adicionar novos, escreveremos apenas uma classe de controlador para todas as interações do servidor:
@Controller public class SeedStarterMngController { @Autowired private VarietyService varietyService; @Autowired private SeedStarterService seedStarterService; ... }
Agora vamos ver o que podemos adicionar a essa classe de controlador.
Atributos do modeloPrimeiro, adicionaremos alguns atributos de modelo que precisaremos na página:
@ModelAttribute("allTypes") public List<Type> populateTypes() { return Arrays.asList(Type.ALL); } @ModelAttribute("allFeatures") public List<Feature> populateFeatures() { return Arrays.asList(Feature.ALL); } @ModelAttribute("allVarieties") public List<Variety> populateVarieties() { return this.varietyService.findAll(); } @ModelAttribute("allSeedStarters") public List<SeedStarter> populateSeedStarters() { return this.seedStarterService.findAll(); }
Métodos mapeadosE agora a parte mais importante do controlador, os métodos mapeados: um para exibir a página do formulário e o outro para lidar com a adição de novos objetos
SeedStarter .
@RequestMapping({"/","/seedstartermng"}) public String showSeedstarters(final SeedStarter seedStarter) { seedStarter.setDatePlanted(Calendar.getInstance().getTime()); return "seedstartermng"; } @RequestMapping(value="/seedstartermng", params={"save"}) public String saveSeedstarter( final SeedStarter seedStarter, final BindingResult bindingResult, final ModelMap model) { if (bindingResult.hasErrors()) { return "seedstartermng"; } this.seedStarterService.add(seedStarter); model.clear(); return "redirect:/seedstartermng"; }
4.5 Configurando o serviço de conversão
Para fornecer formatação simples para objetos
Date e objetos
Variety em nossa camada de visualização, configuramos nosso aplicativo para que o objeto Spring
ConversionService fosse criado e inicializado (
WebMvcConfigurerAdapter extensível) usando alguns dos objetos de formatação necessários.
Olhe novamente:
@Override public void addFormatters(final FormatterRegistry registry) { super.addFormatters(registry); registry.addFormatter(varietyFormatter()); registry.addFormatter(dateFormatter()); } @Bean public VarietyFormatter varietyFormatter() { return new VarietyFormatter(); } @Bean public DateFormatter dateFormatter() { return new DateFormatter(); }
Os
formatadores Spring são implementações da interface
org.springframework.format.Formatter . Para obter mais informações sobre como a infraestrutura de conversão do Spring funciona, consulte os documentos em
spring.io .
Vejamos um
DateFormatter que formata datas de acordo com a string de formato presente na chave
date.format do nosso
Messages.properties :
public class DateFormatter implements Formatter<Date> { @Autowired private MessageSource messageSource; public DateFormatter() { super(); } public Date parse(final String text, final Locale locale) throws ParseException { final SimpleDateFormat dateFormat = createDateFormat(locale); return dateFormat.parse(text); } public String print(final Date object, final Locale locale) { final SimpleDateFormat dateFormat = createDateFormat(locale); return dateFormat.format(object); } private SimpleDateFormat createDateFormat(final Locale locale) { final String format = this.messageSource.getMessage("date.format", null, locale); final SimpleDateFormat dateFormat = new SimpleDateFormat(format); dateFormat.setLenient(false); return dateFormat; } }
VarietyFormatter converte automaticamente entre nossos objetos
Variety e a maneira como queremos usá-los em nossos formulários (principalmente pelos valores de seus campos de
identificação ):
public class VarietyFormatter implements Formatter<Variety> { @Autowired private VarietyService varietyService; public VarietyFormatter() { super(); } public Variety parse(final String text, final Locale locale) throws ParseException { final Integer varietyId = Integer.valueOf(text); return this.varietyService.findById(varietyId); } public String print(final Variety object, final Locale locale) { return (object != null ? object.getId().toString() : ""); } }
Aprenderemos mais sobre como essas ferramentas de formatação afetam a maneira como exibimos nossos dados no futuro.