领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多我很高兴看到最近zeroturnaround 的一项调查显示,Spring MVC 被评为最受欢迎的 Java Web 框架。
这个框架非常灵活,有几十种使用方法。与所有具有许多选项的灵活框架一样,讨论常见实践非常重要。
我为这篇博文创建的项目使用了许多 Spring MVC 应用程序中常见的特性。你会发现类似这样的情况
在控制器中,你会发现用于映射请求、通过注解提取请求数据、数据绑定、文件上传……的典型 Spring MVC 特性。
另一方面,在 JSP 中,大部分 HTML 代码都是原生编写的(而不是由 Spring MVC 标签生成的)。此外,Spring MVC 标签库不会生成任何 Javascript 代码。
我们首先将讨论如何将 Spring MVC 与 jQuery 和 Bean Validation 集成。然后我们将看看如何使这些 JSP 代码更简洁。
public class DiningForm {
@Pattern(regexp="\\d{16}")
private String creditCardNumber;
@Size(1)
private String merchantNumber;
@Min(0)
private double monetaryAmount;
@NotNull
private Date date;
...
}
调用验证时,DiningForm 的实例将根据上述注解进行验证。
从 Spring 3.0 开始,Spring MVC 与 Bean Validation 集成以进行验证规则验证(这并不是在 Spring @MVC 中进行验证的唯一方法,但它显然正成为最常见的方法)。
在控制器方法中,我们可以使用 @Valid,如下所示
@RequestMapping(value="/update", method=RequestMethod.POST)
public String update(@Valid DiningForm diningForm, BindingResult result) {
if (result.hasErrors()) {
return “rewards/edit”;
}
// continue on success...
}
}
在 JSP 层面,可以使用 <form:errors /> 显示错误消息。
<form:form modelAttribute="diningForm">
<form:input path="firstName"/>
<form:errors path="firstName"/>
…
</form:form>
上面的代码相当简单,而且运行良好。但它不会生成任何 Javascript 代码。因此,它不允许部分渲染或客户端验证。让我们看看如何改进它!
在前面的例子中,每次提交表单时都会刷新整个页面。这是 HTML 响应的摘录
我们的目标是最大限度地减少响应大小。我们应该能够获得这样的响应(使用 json 语法)
{"status":"FAIL","result":[{"fieldName":"firstName","message":"firstName may not be empty"}]}
首先,我们将使用 jQuery 表单提交来验证表单。当表单被认为有效时,将使用常规 HTML 表单提交触发表单提交(这样我们就可以重定向到不同的页面)。
让我们首先创建一个简单的 ValidationResponse 类,如下所示
public class ValidationResponse {
private String status;
private List errorMessageList;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public List getErrorMessageList() {
return this.errorMessageList;
}
public void setErrorMessageList(List errorMessageList) {
this.errorMessageList = errorMessageList;
}
}
在控制器类中,我们可以添加一个操作方法
@RequestMapping(value="/user.json")
public @ResponseBody ValidationResponse processForm (Model model, @Valid User user, BindingResult result ) {
ValidationResponse res = new ValidationResponse();
if(!result.hasErrors()){
res.setStatus("SUCCESS");
}
// …
return res;
}
借助 @ResponseBody 注解,返回的对象将被转换为 JSON,如下所示
在 JSP 中,如果合适,会解析并显示错误消息。您可以浏览Javascript 代码以了解更多详情。
根据渐进增强最佳实践,所有 Javascript 代码都放置在 HTML 表单之外。如果客户端浏览器禁用了 Javascript,则表单将回退到全页刷新。
现在我们已经为验证规则实现了部分刷新,但还有两点需要改进
<html:form modelAttribute="user" id="add-user-form" formUrl="/userAjaxCustomTag.htm">
<html:inputField name="firstName" label="Enter your first name:" />
<html:inputField name="lastName" label="Enter your last name:" />
<div>
<button type="submit">Save changes</button>
<button type="reset">Cancel</button>
</div>
</html:form>
自定义标签是 Java EE 的一部分,在 Apache Tomcat 上也能很好地工作。创建自定义标签非常容易。让我们来看一个表单输入字段的简单例子。我们目前使用这种语法(8 行)
<div id="firstName">
<label>Enter your first name:</label>
<div>
<form:input path="firstName" />
<span>
<form:errors path="firstName" />
</span>
</div>
</div>
我们的目标是改为使用这个(1 行)
<html:inputField name="firstName" label="Enter your first name:" />
在 WEB-INF 文件夹中,我可以创建一个新的标签文件,如下所示
其内容如下
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ attribute name="name" required="true" rtexprvalue="true" %>
<%@ attribute name="label" required="true" rtexprvalue="true" %>
<div id="${name}">
<label>${label}</label>
<div>
<form:input path="${name}"/>
<span><form:errors path="${name}"/></span>
</div>
回到 userForm.jsp,我只需要声明标签文件夹
<%@ taglib prefix="html" tagdir="/WEB-INF/tags/html" %>
我可以像这样使用这个新创建的标签
<html:inputField name="firstName" label="Enter your first name:" />
自定义标签与 Eclipse/STS 很好地集成,我甚至可以访问代码完成:
同样,我也可以将 JavaScript 代码外部化到一个标签中,这样我只需要一行代码来调用它
<ajax:formPartialRefresh validateUrl="/userAjaxBootstrap.json" formName="add-user-form"/>
欢迎查看相应的github 上的示例应用程序。
致谢:我要感谢我的朋友 Nicholas Ding,他与我一起为这篇博文构建了代码示例。