【Spring实战——构建Spring Web应用程序】1.10 处理表单
引言
Web应用功能
○ 提供内容
○ 用户填写表单
○ 提交数据
Spring MVC的控制器提供了
○ 处理表单展示
○ 用户提交数据的支持
- 在Spittr应用中,需要一个注册表单供新用户使用。
- SpitterController是一个新的控制器,目前只有一个请求处理方法用于展示注册表单。
程序清单5.13 SpitterController:展现一个表单,允许用户注册该 应用
根据配置的InternalResourceViewResolver,将使用"/WEB-INF/views/registerForm.jsp"这个JSP来渲染注册表单。
- 尽管showRegistrationForm()方法很简单,但仍需要进行测试。
- 由于该方法简单,测试也相对简单。
程序清单5.14 测试展现表单的控制器方法
注意 - 视图的名称为registerForm,因此JSP的名称应为registerForm.jsp。
- registerForm.jsp必须包含一个HTML 标签,用于用户输入注册应用的信息
程序清单5.15 渲染注册表单的JSP
在JSP中,有一个基础的HTML表单,其中包含用于记录用户的名字、姓氏、用户名和密码的表单域,以及一个提交按钮。
在该JSP中,标签没有设置action属性。在这种情况下,当表单提交时,它会提交到与展示时相同的URL路径上,即"/spitter/register"。
这意味着需要在服务器端处理该HTTP POST请求。
现在,我们需要在Spitter-Controller中添加一个方法来处理这个表单的提交。
图5 .5 注册页提供了一个表单,这个表单会由SpitterController 进行处理,完成为应用添加新用户的功能
5.4.1 编写处理表单的控制器
当处理注册表单的POST请求时,控制器需要接收表单数据并将其保存为Spitter对象。
为了防止重复提交,应该将浏览器重定向到新创建用户的基本信息页面。
这些行为可以通过shouldProcessRegistration()方法进行测试。
程序清单5.16 测试处理表单的控制器方法
- 处理POST请求时,最好在请求处理完成后进行重定向,以防止浏览器刷新导致表单重复提交。
- 在这个测试中,预期请求会重定向到"/spitter/jbauer",即新创建用户的基本信息页面。
- 最后,测试会验证SpitterRepository的mock实现是否真正保存了表单提交的数据。
- 现在,我们需要实现处理表单提交的控制器方法。
- 通过shouldProcessRegistration()方法,我们可以看到新的SpitterController并没有做太多的事情。
程序清单5.17 处理所提交的表单并注册新用户
在之前创建的showRegistrationForm()方法的基础上,我们新增了一个processRegistration()方法。该方法接受一个Spitter对象作为参数,该对象具有firstName、lastName、username和password属性。这些属性将使用请求中的同名参数进行填充。
当InternalResourceViewResolver看到视图格式中的"redirect:"前缀时,它知道要将其解析为重定向的规则,而不是视图的名称。在本例中,它会将视图重定向到用户基本信息的页面。例如,如果Spitter.username属性的值为"jbauer",那么视图将重定向到"/spitter/jbauer"。
根据程序清单5.16中的测试,我们的任务应该已经完成。然而,在SpitterController中,我们还需要添加一个处理器方法来处理基本信息页面的请求。showSpitterProfile()方法将完成这项任务。
SpitterRepository通过用户名获取一个Spitter对象,showSpitterProfile()方法将获取到的对象添加到模型中,并返回基本信息页面的逻辑视图名"profile"。和本章其他展示的视图一样,基本信息视图也非常简单。
图5.6展现了在Web浏览器中渲染的基本信息页面。
下面是对这段内容进行梳理和润色后的输出:
如果表单中没有发送username或password,会发生什么情况呢?又或者,如果firstName或lastName的值为空或过长,会有什么影响呢?接下来,让我们看一下如何为表单提交添加校验,以避免数据的不一致性。
图5 .6 Spittr 的基本信息页展现了用户的情况,这些信息是 由SpitterController填充到模型中的
5.4.2 校验表单
如果用户在提交表单时,username或password文本域为空,将导致新建的Spitter对象中的username或password属性为空字符串。这种行为可能会导致安全问题,因为任何人只需提交一个空表单即可登录应用程序。
为了保持一定程度的匿名性,我们应该阻止用户提交空的firstName和/或lastName。一种良好的方式是限制这些输入域的长度,以确保其值在合理的范围内,避免误用。
为了处理验证,可以在processRegistration()方法中添加代码来检查值的合法性。如果值不合法,可以重新向用户显示注册表单。虽然这种方法很简短,但添加一些额外的if语句也不是什么大问题。
与其让验证逻辑混淆处理器方法,不如利用Spring对Java验证API(JSR-303)的支持。从Spring 3.0开始,在Spring MVC中提供了对Java验证API的支持。
使用Java验证API并不需要额外的配置,只需确保在类路径下包含该API的实现,如Hibernate Validator。
Java校验API定义了多个注解,这些注解可以放到属性上,从而限制这些属性的值。所有的注解都位于javax.validation.constraints包中。表5.1列出了这些校验注解。
表5.1 Java校验API所提供的校验注解
注 解 描 述
除了表5.1中的注解,Java校验API的实现可能还会提供额外的校验注解。同时,也可以定义自己的限制条件。但就我们来讲,将会关注于上表中的两个核心限制条件。
请考虑要添加到Spitter域上的限制条件,似乎需要使用@NotNull和@Size注解。我们所要做的事情就是将这些注解添加到Spitter的属性上。下面的程序清单展现了Spitter类,它的属性已经添加了校验注解。
程序清单5.18 Spitter:包含了要提交到Spittle POST请求中的域
@NotNull注解,确保值不为null。
@Size注解,限制它们的长度在最大值和最小值之间。
对Spittr应用来说,这意味着用户必须要填完注册表单,并且值的长度要在给定的范围内。
我们已经为Spitter添加了校验注解,接下来需要修改processRegistration()方法来应用校验功能。
下面展示的是启用了校验功能的processRegistration()方法。
程序清单5.19 processRegistration():确保所提交的数据是合法的
与程序清单5.17中最初的processRegistration()方法相比,有了很大的变化。在Spitter参数上添加了@Valid注解,告知Spring需要对该对象进行校验。
添加校验限制仍旧不能阻止表单提交
在Spitter属性上添加校验限制并不能阻止表单提交。即使用户没有填写某个域或某个域的值超过了最大长度,processRegistration()方法仍然会被调用。
处理校验错误
因此,我们需要处理校验错误,就像在processRegistration()方法中所示。
如果出现校验错误,这些错误可以通过Errors对象进行访问,该对象现在作为processRegistration()方法的参数。
需要注意的是,Errors参数紧跟在带有@Valid注解的参数后面,@Valid注解所标注的是要进行校验的参数。
processRegistration()方法
processRegistration()方法的第一件事是调用Errors.hasErrors()来检查是否有错误。
如果存在错误会怎么样?
如果存在错误,Errors.hasErrors()将返回到registerForm,即注册表单的视图。
这使得用户的浏览器可以返回到注册表单页面,以便他们可以修正错误并重新尝试提交。
现在,会显示一个空的表单,但在下一章中,我们将在表单中显示最初提交的值,并将校验错误反馈给用户。
如果没有错误会怎么样
如果没有错误的话,Spitter对象将会通过Repository进行保存,控 制器会像之前那样重定向到基本信息页面。
共同学习,写下你的评论
评论加载中...
作者其他优质文章