领先一步
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;
}
}
在控制器类中,我们可以添加一个action方法
@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,表单将回退到全页面刷新。
现在我们已经为验证规则实现了部分刷新,还有2点需要改进
<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,他与我一起为这篇博客文章构建了代码示例。