`

SpringMVC杂记(三) 向导型Controller的实现(基于SpringMVC 3.1.1)

阅读更多
SpringMVC杂记(三) 向导型Controller的实现(基于SpringMVC 3.1.1)

1) 项目需要必须使用向导型Controller,Spring2.x时代的org.springframework.web.servlet.mvc.AbstractWizardFormController
已经在Spring 3.1中被标上了过时。只好自己动手,用标注实现同样的逻辑。

2) 首先是表单类,最终用户提交的数据都用这个保存起来。
public class UserRegistForm implements java.io.Serializable {

	private String username;
	private String sex;
	private String birthday;

	@Pattern(regexp = "\\d{3}-\\{d4}-\\d{4}")
	private String phoneNumber;			// 电话号码用JSR303标注验证,因为只是示例程序别字段的就不验证了。
	private String emailAddress;
	private List<String> interests = new ArrayList<String>();

	// 篇幅关系 getter 和 setter 就不写了
}


3) 设计表单
  3.1 第一个页面要求用户填写用户名,性别,生日
<%@ page language="java" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page isELIgnored="false" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<html>
	<head>
		<base href="<%=basePath%>" />
		<title>注册</title>
	</head>

	<body>
		<form action="" method="post">
			<input type="hidden" name="_page" value="1">
			<table>
				<tr>
					<td>用户名</td>
					<td><input type="text" name="username" value="${form.username}"></td>
				</tr>
				<tr>
					<td>性别</td>
					<td>
						<select name="sex">
							<option value="男" <c:if test="${form.sex == '男'}">selected="selected"</c:if>>男</option>
							<option value="女" <c:if test="${form.sex == '女'}">selected="selected"</c:if>>女</option>
						</select>
					</td>
				</tr>
				<tr>
					<td>生日</td>
					<td><input type="text" name="birthday" value="${form.birthday}"></td>
				</tr>
				<tr>
					<td colspan="2"><input type="submit" value="下一个" name="_next"></td>
				</tr>
			</table>
		</form>
	</body>
</html>



  3.2 第二个页面要求用户填写手机号和电子邮件地址
<%@ page language="java" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page isELIgnored="false" %>

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<html>
	<head>
		<base href="<%=basePath%>" />
		<title>注册</title>
	</head>

	<body>
		<form action="" method="post">
			<input type="hidden" name="_page" value="2">
			<table>
				<tr>
					<td>手机号</td>
					<td><input type="text" name="phoneNumber" value="${form.phoneNumber}"></td>
				</tr>
				<tr>
					<td>邮件地址</td>
					<td><input type="text" name="emailAddress" value="${form.emailAddress}"></td>
				</tr>
				<tr>
					<td><input type="submit" value="上一个" name="_prev"></td>
					<td><input type="submit" value="下一个" name="_next"></td>
				</tr>
			</table>
		</form>
	</body>
</html>



  3.3 第三个页面填写自己的兴趣爱好
<%@ page language="java" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page isELIgnored="false" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="mfn" uri="http://www.wicresoft.com/jsp/functions" %>

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<html>
	<head>
		<base href="<%=basePath%>" />
		<title>注册</title>
	</head>

	<body>
		<form action="" method="post">
			<input type="hidden" name="_page" value="3">
			<table>
				<tr>
					<td>兴趣</td>
					<td>
						<c:forEach items="${interestList}" var="interest">
							<input type="checkbox" name="interests" value="${interest}" <c:if test="${mfn:contains(form.interests, interest)}">checked="checked"</c:if>> ${interest} <br/>
						</c:forEach>
					</td>
				</tr>
				<tr>
					<td><input type="submit" value="上一个" name="_prev"></td>
					<td><input type="submit" value="完成" name="_finish"></td>
				</tr>
			</table>
		</form>
	</body>
</html>



4) Controller类的编写
  4.1 首先把页面需要的MasterData准备好,放在ModelMap中保存。
public class RegistWizardFormController {

	private static final Logger LOGGER = LoggerFactory.getLogger(RegistWizardFormController.class);

	// 三个页面分别对应的逻辑视图名
	private static final String[] VIEW_NAMES = new String[] {
		"regist1",
		"regist2",
		"regist3"
	};

	@ModelAttribute("form")
	public UserRegistForm initForm() {
		LOGGER.debug("initForm()");
		return new UserRegistForm();
	}

	// Master Data
	@ModelAttribute("interestList")
	public List<String> initInterests() {
		return Arrays.asList("吃,喝,嫖,赌".split(","));
	}
}


  4.2 跳到第一个视图的方法
public class RegistWizardFormController {
	// ...

	// 访问“http://localhost:8080/demo/user/regist”时,进入第一个页面
	@RequestMapping(value = "/regist", method = {RequestMethod.GET})
	public String go(@ModelAttribute("form") UserRegistForm form) {
		return VIEW_NAMES[0];
	}

	// ...
}


  4.3 注意,由于[上一个],[下一个],[完成]按钮都会触发submit动作,所以一个方法是不够的,三个按钮触发的提交必须区别对待。
public class RegistWizardFormController {

	// @RequestMapping标注的 params 参数来判断到底哪个按钮被点击引发了提交。

	@RequestMapping(value = "/regist", method = {RequestMethod.POST}, params = {"_next", "!_prev", "!_finish"})
	public String processNext(@RequestParam(value = "_page", required = true) int page, @ModelAttribute("form") UserRegistForm form) {
		LOGGER.debug("process 'next', next logic view name : {}", VIEW_NAMES[page]);

		return VIEW_NAMES[page];
	}

	@RequestMapping(value = "/regist", method = {RequestMethod.POST}, params = {"!_next", "_prev", "!_finish"})
	public String processPrev(@RequestParam(value = "_page", required = true) int page, @ModelAttribute("form") UserRegistForm form) {
		LOGGER.debug("process 'prev', previous logic view name : {}", VIEW_NAMES[page - 2]);

		return VIEW_NAMES[page - 2];
	}

	@ResponseBody
	@RequestMapping(value = "/regist", method = {RequestMethod.POST}, params = {"!_next", "!_prev", "_finish"})
	public UserRegistForm processFinish(@Valid @ModelAttribute("form") UserRegistForm form, BindingResult bindingResult, SessionStatus sessionStatus) {

		if (bindingResult.hasErrors()) {
			// 数据绑定有问题的话,仅仅用一条日志而已
			LOGGER.warn("Data-binding has errors.");
		}

		// 现在得到的是完整的表单了,怎么做就看业务啦。
		// 我这里只是把表单的数据用JSON的方式发给浏览器

		sessionStatus.setComplete();
		return form;
	}

	// ...
}
分享到:
评论
3 楼 yingzhor 2012-09-18  
第一个问题答案: 你试过就知道了,不过你也页面没有提交的话,当然不会帮你验证了。
第二个问题答案: 请参考我另一篇博客http://yingzhuo.iteye.com/blog/1455438最后也有一个Demo供你下载。 一看便知。
2 楼 bennet2009 2012-09-17  
还有, 如果在最后提交表单的时候, 验证没有通过, 怎么回填写有误的表单页呢?
1 楼 bennet2009 2012-09-17  
请问这种分步提交的表单, 如果验证的? 我使用 JSR 303 - Bean Validation 来进行验证, 但是第一个页面提交的时候,不仅只验证了第一个页面上的字段,后面的字段也要进行验证,但第一个页面上根本就没有这些字段。

相关推荐

Global site tag (gtag.js) - Google Analytics