Spring MVC 3.2 Thymeleaf Ajax 片段
Posted
技术标签:
【中文标题】Spring MVC 3.2 Thymeleaf Ajax 片段【英文标题】:Spring MVC 3.2 Thymeleaf Ajax Fragments 【发布时间】:2014-01-25 18:54:51 【问题描述】:我正在使用 Spring MVC 3.2 和 Thymeleaf 模板引擎构建应用程序。我是 Thymeleaf 的初学者。
我的一切正常,包括 Thymeleaf,但我想知道是否有人知道关于如何向控制器执行简单的 Ajax 请求并最终渲染模板(片段)的一部分的简单而清晰的教程。
我的应用程序已配置所有内容(Spring 3.2、spring-security、thymeleaf,...)并按预期工作。现在我想做 Ajax 请求(用 jQuery 很简单,但我不想使用,因为 Thymeleaf 在其教程第 11 章:渲染模板片段(link)提到它可以用片段来完成。
目前我的控制器中有
@RequestMapping("/dimensionMenuList")
public String showDimensionMenuList(Model model)
Collection<ArticleDimensionVO> articleDimensions;
try
articleDimensions = articleService.getArticleDimension(ArticleTypeVO.ARTICLE_TYPE);
catch (DataAccessException e)
// TODO: return ERROR
throw new RuntimeException();
model.addAttribute("dimensions", articleDimensions);
return "/admin/index :: dimensionMenuList";
我想替换<ul></ul>
菜单项的视图部分:
<ul th:fragment="dimensionMenuList" class="dropdown-menu">
<li th:unless="$#lists.isEmpty(dimensions)" th:each="dimension : $dimensions">
<a href="#" th:text="$dimension.dimension"></a>
</li>
</ul>
非常感谢任何线索。特别是如果我不必包含更多框架。对于 java web 应用程序来说,它已经太多了。
【问题讨论】:
【参考方案1】:这是我在blog post 中遇到的一种方法:
我不想使用这些框架,所以在本节中,我使用 jQuery 向服务器发送 AJAX 请求,等待响应并部分更新视图(片段渲染)。
表格
<form>
<span class="subtitle">Guest list form</span>
<div class="listBlock">
<div class="search-block">
<input type="text" id="searchSurname" name="searchSurname"/>
<br />
<label for="searchSurname" th:text="#search.label">Search label:</label>
<button id="searchButton" name="searchButton" onclick="retrieveGuests()" type="button"
th:text="#search.button">Search button</button>
</div>
<!-- Results block -->
<div id="resultsBlock">
</div>
</div>
</form>
此表单包含一个带有搜索字符串 (searchSurname) 的输入文本,该文本将被发送到服务器。还有一个区域(resultsBlock div)将使用从服务器收到的响应进行更新。
当用户点击按钮时,retrieveGuests() 函数将被调用。
function retrieveGuests()
var url = '/th-spring-integration/spring/guests';
if ($('#searchSurname').val() != '')
url = url + '/' + $('#searchSurname').val();
$("#resultsBlock").load(url);
jQuery load 函数在指定的 url 向服务器发出请求,并将返回的 html 放入指定的元素(resultsBlock div)中。
如果用户输入一个搜索字符串,它将搜索所有具有指定姓氏的客人。否则,它将返回完整的客人列表。这两个请求将到达以下控制器请求映射:
@RequestMapping(value = "/guests/surname", method = RequestMethod.GET)
public String showGuestList(Model model, @PathVariable("surname") String surname)
model.addAttribute("guests", hotelService.getGuestsList(surname));
return "results :: resultsList";
@RequestMapping(value = "/guests", method = RequestMethod.GET)
public String showGuestList(Model model)
model.addAttribute("guests", hotelService.getGuestsList());
return "results :: resultsList";
由于 Spring 与 Thymeleaf 集成,它现在能够返回 HTML 片段。在上面的示例中,返回字符串“results :: resultsList”指的是位于结果页面中名为 resultsList 的片段。我们来看看这个结果页面:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
</head>
<body>
<div th:fragment="resultsList" th:unless="$#lists.isEmpty(guests)" id="results-block">
<table>
<thead>
<tr>
<th th:text="#results.guest.id">Id</th>
<th th:text="#results.guest.surname">Surname</th>
<th th:text="#results.guest.name">Name</th>
<th th:text="#results.guest.country">Country</th>
</tr>
</thead>
<tbody>
<tr th:each="guest : $guests">
<td th:text="$guest.id">id</td>
<td th:text="$guest.surname">surname</td>
<td th:text="$guest.name">name</td>
<td th:text="$guest.country">country</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
片段,它是一个注册客人的表格,将被插入到结果块中。
【讨论】:
【参考方案2】:仅渲染 Thymeleaf fragments
也适用于 ModelAndView
。
您的控制器
@RequestMapping(value = "/feeds", method = RequestMethod.GET)
public ModelAndView getFeeds()
LOGGER.debug("Feeds method called..");
return new ModelAndView("feeds :: resultsList");
您的观点
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
<div th:fragment="resultsList" id="results-block">
<div>A test fragment</div>
<div>A test fragment</div>
</div>
</body>
</html>
实际渲染的内容
<div id="results-block">
<div>A test fragment</div>
<div>A test fragment
</div>
</div>
【讨论】:
它会刷新页面吗? 取决于你如何称呼它。如果它是一个 ajax 调用,则页面不会刷新,否则它会。 我真的很喜欢这个。我尝试返回视图名称方法,它也可以。像这样:public String getFeeds() return "feeds :: resultsList";
如何返回多个片段?? @AbdullahKhan【参考方案3】:
作为 Sohail 出色答案的替代版本,我想提供一个使用 javascript 可以将整个 th:object 发送到控制器的版本,将 Thymeleaf 集成到您的表单中,而不必使用会变得混乱或不可用的 @PathVariable当您的表单包含许多字段时,根本就没有。
对于表单(使用一个示例,该示例返回一个对象,该对象具有一个 id 和一个名称 Strings,并提供一个带有 Map 的组合框,其中一些对象作为值)我们有:
<form method="post" th:action="@/yourMapping" th:object="$object" id="yourFormId">
<select th:field="*mapOfObjects">
<option
th:each="entry: $mapOfObjects"
th:value="$entry.value.id"
th:text="$entry.value.name" >
</option>
</select>
<p>Name:
<input type="text" th:field="*name" />
</p>
</form>
提交此表单时(例如,使用类型为 submit 的按钮)整个文档将被替换。但是,我们可以使用 javascript 拦截这个提交并以 ajax 方式进行。为了实现这一点,我们将使用一个函数向我们的表单添加一个拦截器。首先在表单后面调用添加拦截器的函数:
<script>formInterceptor("yourFormId");</script>
函数看起来像这样(将它放在文档的头部或任何适合您需要的地方):
<script>
function formInterceptor(formName)
var $form = $("#" + formName);
$form.on('submit', function(e)
e.preventDefault();
$.ajax(
url : $form.attr('action'),
type : 'post',
data : $form.serialize(),
success : function(response)
if ($(response).find('.has-error').length)
$form.replaceWith(response);
else
$("#ajaxLoadedContent").replaceWith(response);
);
);
;
</script>
现在只要提交表单,就会触发这个函数,它会:
阻止原始表单提交 使用表单的 th:action 中定义的 url 进行 ajax 调用 序列化表单数据。您的控制器将能够在对象中接收此信息 用返回的片段替换部分 html 代码替换后的部分应该是这样的
<div id="ajaxLoadedContent"></div>
并且控制器可以接收表单中的 th:object,并填充它的值,如下所示(将 Object 替换为您的对象的类型,将“object”替换为正确的名称):
@PostMapping(value = /yourMapping)
public String ajaxCtrlExample(@ModelAttribute("object") Object object, Model model)
return yourFragmentPath;
这就是一切。在 ajax-version 中调用每个表单后添加拦截器的函数。
【讨论】:
以上是关于Spring MVC 3.2 Thymeleaf Ajax 片段的主要内容,如果未能解决你的问题,请参考以下文章
spring mvc 整合jsp和thymeleaf两个模板引擎
Thymeleaf 和 Spring MVC 的表单参数为空