【Spring实战——构建Spring Web应用程序】1.10 处理表单

引言

Web应用功能

○ 提供内容</br>
○ 用户填写表单</br>
○ 提交数据</br>

Spring MVC的控制器提供了

○ 处理表单展示</br>
○ 用户提交数据的支持</br>

  1. 在Spittr应用中,需要一个注册表单供新用户使用。</br>
  2. SpitterController是一个新的控制器,目前只有一个请求处理方法用于展示注册表单。</br>
    程序清单5.13 SpitterController:展现一个表单,允许用户注册该 应用


    file

根据配置的InternalResourceViewResolver,将使用"/WEB-INF/views/registerForm.jsp"这个JSP来渲染注册表单。

  1. 尽管showRegistrationForm()方法很简单,但仍需要进行测试。
  2. 由于该方法简单,测试也相对简单。
    程序清单5.14 测试展现表单的控制器方法


    file

    注意

  3. 视图的名称为registerForm,因此JSP的名称应为registerForm.jsp。
  4. registerForm.jsp必须包含一个HTML 标签,用于用户输入注册应用的信息

程序清单5.15 渲染注册表单的JSP


file

在JSP中,有一个基础的HTML表单,其中包含用于记录用户的名字、姓氏、用户名和密码的表单域,以及一个提交按钮。
在该JSP中,<form>标签没有设置action属性。在这种情况下,当表单提交时,它会提交到与展示时相同的URL路径上,即"/spitter/register"。
这意味着需要在服务器端处理该HTTP POST请求。


file

现在,我们需要在Spitter-Controller中添加一个方法来处理这个表单的提交。

图5 .5 注册页提供了一个表单,这个表单会由SpitterController 进行处理,完成为应用添加新用户的功能

5.4.1 编写处理表单的控制器

当处理注册表单的POST请求时,控制器需要接收表单数据并将其保存为Spitter对象。 </br>
为了防止重复提交,应该将浏览器重定向到新创建用户的基本信息页面。 </br>
这些行为可以通过shouldProcessRegistration()方法进行测试。 </br>
程序清单5.16 测试处理表单的控制器方法


file
  1. 处理POST请求时,最好在请求处理完成后进行重定向,以防止浏览器刷新导致表单重复提交。
  2. 在这个测试中,预期请求会重定向到"/spitter/jbauer",即新创建用户的基本信息页面。
  3. 最后,测试会验证SpitterRepository的mock实现是否真正保存了表单提交的数据。
  4. 现在,我们需要实现处理表单提交的控制器方法。
  5. 通过shouldProcessRegistration()方法,我们可以看到新的SpitterController并没有做太多的事情。
    程序清单5.17 处理所提交的表单并注册新用户
file
  在之前创建的showRegistrationForm()方法的基础上,我们新增了一个processRegistration()方法。该方法接受一个Spitter对象作为参数,该对象具有firstName、lastName、username和password属性。这些属性将使用请求中的同名参数进行填充。
    当InternalResourceViewResolver看到视图格式中的"redirect:"前缀时,它知道要将其解析为重定向的规则,而不是视图的名称。在本例中,它会将视图重定向到用户基本信息的页面。例如,如果Spitter.username属性的值为"jbauer",那么视图将重定向到"/spitter/jbauer"。

根据程序清单5.16中的测试,我们的任务应该已经完成。然而,在SpitterController中,我们还需要添加一个处理器方法来处理基本信息页面的请求。showSpitterProfile()方法将完成这项任务。
file

SpitterRepository通过用户名获取一个Spitter对象,showSpitterProfile()方法将获取到的对象添加到模型中,并返回基本信息页面的逻辑视图名"profile"。和本章其他展示的视图一样,基本信息视图也非常简单。

图5.6展现了在Web浏览器中渲染的基本信息页面。
下面是对这段内容进行梳理和润色后的输出:
如果表单中没有发送username或password,会发生什么情况呢?又或者,如果firstName或lastName的值为空或过长,会有什么影响呢?接下来,让我们看一下如何为表单提交添加校验,以避免数据的不一致性。</br>

图5 .6 Spittr 的基本信息页展现了用户的情况,这些信息是 由SpitterController填充到模型中的

5.4.2 校验表单

如果用户在提交表单时,username或password文本域为空,将导致新建的Spitter对象中的username或password属性为空字符串。这种行为可能会导致安全问题,因为任何人只需提交一个空表单即可登录应用程序。</br>
为了保持一定程度的匿名性,我们应该阻止用户提交空的firstName和/或lastName。一种良好的方式是限制这些输入域的长度,以确保其值在合理的范围内,避免误用。</br>
为了处理验证,可以在processRegistration()方法中添加代码来检查值的合法性。如果值不合法,可以重新向用户显示注册表单。虽然这种方法很简短,但添加一些额外的if语句也不是什么大问题。</br>
与其让验证逻辑混淆处理器方法,不如利用Spring对Java验证API(JSR-303)的支持。从Spring 3.0开始,在Spring MVC中提供了对Java验证API的支持。</br>
使用Java验证API并不需要额外的配置,只需确保在类路径下包含该API的实现,如Hibernate Validator。</br>
Java校验API定义了多个注解,这些注解可以放到属性上,从而限制这些属性的值。所有的注解都位于javax.validation.constraints包中。表5.1列出了这些校验注解。</br>
表5.1 Java校验API所提供的校验注解

注 解 描 述

file

除了表5.1中的注解,Java校验API的实现可能还会提供额外的校验注解。同时,也可以定义自己的限制条件。但就我们来讲,将会关注于上表中的两个核心限制条件。</br>
请考虑要添加到Spitter域上的限制条件,似乎需要使用@NotNull和@Size注解。我们所要做的事情就是将这些注解添加到Spitter的属性上。下面的程序清单展现了Spitter类,它的属性已经添加了校验注解。 </br>
程序清单5.18 Spitter:包含了要提交到Spittle POST请求中的域


file

@NotNull注解,确保值不为null。
@Size注解,限制它们的长度在最大值和最小值之间。
对Spittr应用来说,这意味着用户必须要填完注册表单,并且值的长度要在给定的范围内。

我们已经为Spitter添加了校验注解,接下来需要修改processRegistration()方法来应用校验功能。
下面展示的是启用了校验功能的processRegistration()方法。
程序清单5.19 processRegistration():确保所提交的数据是合法的


file

与程序清单5.17中最初的processRegistration()方法相比,有了很大的变化。在Spitter参数上添加了@Valid注解,告知Spring需要对该对象进行校验。
添加校验限制仍旧不能阻止表单提交
在Spitter属性上添加校验限制并不能阻止表单提交。即使用户没有填写某个域或某个域的值超过了最大长度,processRegistration()方法仍然会被调用。

处理校验错误

因此,我们需要处理校验错误,就像在processRegistration()方法中所示。</br>
如果出现校验错误,这些错误可以通过Errors对象进行访问,该对象现在作为processRegistration()方法的参数。</br>
需要注意的是,Errors参数紧跟在带有@Valid注解的参数后面,@Valid注解所标注的是要进行校验的参数。</br>

processRegistration()方法

processRegistration()方法的第一件事是调用Errors.hasErrors()来检查是否有错误。

如果存在错误会怎么样?

如果存在错误,Errors.hasErrors()将返回到registerForm,即注册表单的视图。</br>
这使得用户的浏览器可以返回到注册表单页面,以便他们可以修正错误并重新尝试提交。</br>
现在,会显示一个空的表单,但在下一章中,我们将在表单中显示最初提交的值,并将校验错误反馈给用户。

如果没有错误会怎么样

如果没有错误的话,Spitter对象将会通过Repository进行保存,控 制器会像之前那样重定向到基本信息页面。

本文由博客一文多发平台 OpenWrite 发布!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,458评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,030评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,879评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,278评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,296评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,019评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,633评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,541评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,068评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,181评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,318评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,991评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,670评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,183评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,302评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,655评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,327评论 2 358

推荐阅读更多精彩内容