1.引言
本文重点介绍如何将Thymeleaf与Spring框架集成。 这将使我们的MVC Web应用程序能够利用Thymeleaf HTML5模板引擎,而不会丢失任何Spring功能。 数据层使用Spring Data与mongoDB数据库进行交互。
该示例包含在酒店的单页Web应用程序中,从中我们可以发送两个不同的请求:
- 插入一个新来宾:一个同步请求,显示Thymeleaf如何与Spring的表单支持bean集成在一起。
- 列出来宾:异步请求,显示如何使用AJAX处理片段渲染。
本教程希望您了解Thymeleaf的基础知识。 如果不是,则应首先阅读本文 。
这是应用程序流程的示例:
本示例基于Thymeleaf 2.1和Spring 4版本。
- 源代码可以在github上找到。
2.配置
本教程采用JavaConfig方法来配置所需的bean。 这意味着不再需要xml配置文件。
web.xml
由于我们要使用JavaConfig,因此需要指定AnnotationConfigWebApplicationContext作为将配置Spring容器的类。 如果不指定,默认情况下它将使用XmlWebApplicationContext 。
在定义配置文件的位置时,我们可以指定类或包。 在这里,我要说明我的配置类。
<!-- Bootstrap the root context -->
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener><!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext -->
<context-param><param-name>contextClass</param-name><param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param><!-- @Configuration classes or package -->
<context-param><param-name>contextConfigLocation</param-name><param-value>xpadro.thymeleaf.configuration.WebAppConfiguration</param-value>
</context-param><!-- Spring servlet -->
<servlet><servlet-name>springServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextClass</param-name><param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value></init-param>
</servlet>
<servlet-mapping><servlet-name>springServlet</servlet-name><url-pattern>/spring/*</url-pattern>
</servlet-mapping>
弹簧配置
我的配置分为两类:百里香叶弹簧集成( WebAppConfiguration类)和mongoDB配置( MongoDBConfiguration类)。
WebAppConfiguration.java
@EnableWebMvc
@Configuration
@ComponentScan("xpadro.thymeleaf")
@Import(MongoDBConfiguration.class)
public class WebAppConfiguration extends WebMvcConfigurerAdapter {@Bean@Description("Thymeleaf template resolver serving HTML 5")public ServletContextTemplateResolver templateResolver() {ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();templateResolver.setPrefix("/WEB-INF/html/");templateResolver.setSuffix(".html");templateResolver.setTemplateMode("HTML5");return templateResolver;}@Bean@Description("Thymeleaf template engine with Spring integration")public SpringTemplateEngine templateEngine() {SpringTemplateEngine templateEngine = new SpringTemplateEngine();templateEngine.setTemplateResolver(templateResolver());return templateEngine;}@Bean@Description("Thymeleaf view resolver")public ThymeleafViewResolver viewResolver() {ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();viewResolver.setTemplateEngine(templateEngine());return viewResolver;}@Bean@Description("Spring message resolver")public ResourceBundleMessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("i18n/messages"); return messageSource; }@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");}
}
通过查看上面的代码可以突出显示以下内容:
- @EnableWebMvc :这将启用Spring MVC注释,例如@RequestMapping。 这将与xml名称空间<mvc:annotation-driven />相同
- @ComponentScan(“ xpadro.thymeleaf”) :激活xpadro.thymeleaf程序包和子程序包中的组件扫描。 用@Component和相关注释注释的类将被注册为bean。
- 我们正在注册三个bean,它们是配置Thymeleaf并将其与Spring框架集成所必需的。
- 模板解析器:解析模板名称并将其委托给servlet上下文资源解析器。
MongoDBConfiguration.java
@Configuration
@EnableMongoRepositories("xpadro.thymeleaf.repository")
public class MongoDBConfiguration extends AbstractMongoConfiguration {@Overrideprotected String getDatabaseName() {return "hotel-db";}@Overridepublic Mongo mongo() throws Exception {return new Mongo();}
}
此类扩展了AbstracMongoConfiguration ,它定义了mongoFactory和mongoTemplate bean。
@EnableMongoRepositories将扫描指定的包,以查找扩展MongoRepository的接口。 然后,它将为每个容器创建一个bean。 稍后,我们将在数据访问层部分看到这一点。
3.Thymeleaf – Spring MVC集成
酒店控制器
控制器负责访问服务层,根据结果构造视图模型并返回视图。 使用我们在上一节中设置的配置,现在MVC控制器将能够返回将被解析为Thymeleaf视图的视图ID。
在下面,我们可以看到控制器处理初始请求的片段(http:// localhost:8080 / th-spring-integration / spring / home):
@Controller
public class HotelController {@Autowiredprivate HotelService hotelService;@ModelAttribute("guest")public Guest prepareGuestModel() {return new Guest();}@ModelAttribute("hotelData")public HotelData prepareHotelDataModel() {return hotelService.getHotelData();}@RequestMapping(value = "/home", method = RequestMethod.GET)public String showHome(Model model) {prepareHotelDataModel();prepareGuestModel();return "home";}...
}
典型的MVC控制器返回一个“主”视图ID。 Thymeleaf模板解析器将在/ WEB-INF / html /文件夹中查找名为“ home.html”的模板,如配置中所示。 此外,名为“ hotelData”的视图属性将向Thymeleaf视图公开,其中包含需要在初始视图上显示的酒店信息。
主页视图的此片段显示了如何使用Spring表达式语言(Spring EL)访问view属性的某些属性:
<span th:text="${hotelData.name}">Hotel name</span><br />
<span th:text="${hotelData.address}">Hotel address</span><br />
Thymeleaf的另一个不错的功能是,它可以解析通过MessageSource接口配置的Spring托管消息属性。
<h3 th:text="#{hotel.information}">Hotel Information</h3>
错误处理
如果已经存在具有相同ID的用户,则尝试添加新用户将引发异常。 将处理异常,并使用错误消息呈现主视图。
由于我们只有一个控制器,因此无需使用@ControllerAdvice 。 我们将改为使用@ExceptionHandler注释的方法。 您会注意到,我们将国际化消息作为错误消息返回:
@ExceptionHandler({GuestFoundException.class})
public ModelAndView handleDatabaseError(GuestFoundException e) {ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("home");modelAndView.addObject("errorMessage", "error.user.exist");modelAndView.addObject("guest", prepareGuestModel());modelAndView.addObject("hotelData", prepareHotelDataModel());return modelAndView;
}
Thymeleaf将使用$ {}解析view属性,然后将解析消息#{}:
<span class="messageContainer" th:unless="${#strings.isEmpty(errorMessage)}" th:text="#{${errorMessage}}"></span>
th:除非Thymeleaf属性仅在返回错误消息后才呈现span元素。
4,服务层
服务层访问数据访问层并添加一些业务逻辑。
@Service("hotelServiceImpl")
public class HotelServiceImpl implements HotelService {@AutowiredHotelRepository hotelRepository;@Overridepublic List<Guest> getGuestsList() {return hotelRepository.findAll();}@Overridepublic List<Guest> getGuestsList(String surname) {return hotelRepository.findGuestsBySurname(surname);}@Overridepublic void insertNewGuest(Guest newGuest) {if (hotelRepository.exists(newGuest.getId())) {throw new GuestFoundException();}hotelRepository.save(newGuest);}
}
5,数据访问层
HotelRepository扩展了Spring Data类MongoRepository 。
public interface HotelRepository extends MongoRepository<Guest, Long> {@Query("{ 'surname' : ?0 }")List<Guest> findGuestsBySurname(String surname);
}
这只是一个接口,我们不会实现。 如果您还记得配置类,我们添加了以下注释:
@EnableMongoRepositories("xpadro.thymeleaf.repository")
由于这是存储库所在的包,因此Spring将创建一个bean并向其注入mongoTemplate。 扩展此接口可为我们提供通用的CRUD操作。 如果需要其他操作,则可以使用@Query注释添加它们(请参见上面的代码)。
六,结论
我们已经配置了Thymeleaf来解析Spring托管的Web应用程序中的视图。 这允许视图访问Spring Expression Language和消息解析。 本教程的下一部分将展示如何将表单链接到Spring表单支持bean,以及如何通过发送AJAX请求来重新加载片段。
翻译自: https://www.javacodegeeks.com/2014/02/thymeleaf-integration-with-spring-part-1.html