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

引言

Web应用功能

○ 提供内容
○ 用户填写表单
○ 提交数据

Spring MVC的控制器提供了

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

  1. 在Spittr应用中,需要一个注册表单供新用户使用。
  2. SpitterController是一个新的控制器,目前只有一个请求处理方法用于展示注册表单。
    程序清单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中,

标签没有设置action属性。在这种情况下,当表单提交时,它会提交到与展示时相同的URL路径上,即"/spitter/register"。 这意味着需要在服务器端处理该HTTP POST请求。 file 现在,我们需要在Spitter-Controller中添加一个方法来处理这个表单的提交。

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

5.4.1 编写处理表单的控制器

当处理注册表单的POST请求时,控制器需要接收表单数据并将其保存为Spitter对象。
为了防止重复提交,应该将浏览器重定向到新创建用户的基本信息页面。
这些行为可以通过shouldProcessRegistration()方法进行测试。
程序清单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的值为空或过长,会有什么影响呢?接下来,让我们看一下如何为表单提交添加校验,以避免数据的不一致性。

图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所提供的校验注解

注 解 描 述

file

除了表5.1中的注解,Java校验API的实现可能还会提供额外的校验注解。同时,也可以定义自己的限制条件。但就我们来讲,将会关注于上表中的两个核心限制条件。
请考虑要添加到Spitter域上的限制条件,似乎需要使用@NotNull和@Size注解。我们所要做的事情就是将这些注解添加到Spitter的属性上。下面的程序清单展现了Spitter类,它的属性已经添加了校验注解。
程序清单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()方法中所示。
如果出现校验错误,这些错误可以通过Errors对象进行访问,该对象现在作为processRegistration()方法的参数。
需要注意的是,Errors参数紧跟在带有@Valid注解的参数后面,@Valid注解所标注的是要进行校验的参数。

processRegistration()方法

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

如果存在错误会怎么样?

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

如果没有错误会怎么样

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/183069.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CoDeSys系列-4、基于Ubuntu的codesys运行时扩展包搭建Profinet主从环境

CoDeSys系列-4、基于Ubuntu的codesys运行时扩展包搭建Profinet主从环境 文章目录 CoDeSys系列-4、基于Ubuntu的codesys运行时扩展包搭建Profinet主从环境一、前言二、资料收集三、Ubuntu18.04从安装到更换实时内核1、下载安装Ubuntu18.042、下载安装实时内核,解决编…

基于单片机的语音存储与回放系统设计

博主主页:单片机辅导设计 博主简介:专注单片机技术领域和毕业设计项目。 主要内容:毕业设计、简历模板、学习资料、技术咨询。 文章目录 主要介绍一、控制系统设计1.1 系统方案设计1.2 系统工作原理 二、硬件电路设计总电路设计图 三、 软件设…

SoftwareTest4 - 咋设计一个好的测试用例

咋设计一个好的测试用例 一 . 设计测试用例的万能公式功能测试性能测试界面测试兼容性测试易用性测试安全测试案例案例1 : 对水杯设计测试用例案例 2 : 对登录页面设计测试用例 二 . 具体设计测试用例的方法2.1 等价类等价类的概念等价类的用例编写 2.2 边界值2.3 判定表2.4 场…

MinIO 分布式文件(对象)存储

简介 MinIO是高性能、可扩展、云原生支持、操作简单、开源的分布式对象存储产品。 在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品 官网地址:http://www.minio.org.cn/ 下载 官网下载(8.4.3版本)&#x…

在Flask中实现文件上传七牛云中并下载

在Flask中实现文件上传和七牛云集成 文件上传是Web应用中常见的功能之一,而七牛云则提供了强大的云存储服务,使得文件存储和管理变得更加便捷。在本篇博客中,我们将学习如何在Flask应用中实现文件上传,并将上传的文件保存到七牛云…

十大排序算法C++实现

分类 复杂度 排序稳定性定义: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,A1A2,且A1在A2之前,而在排序后的序…

Pytorch 快速参数权重初始化

定义一个函数: 这里比如要初始化2维卷积权重值,采用xaiver 数据分布,还有很多其他的数据分布可以探索 def weights_init(m):if isinstance(m, nn.Conv2d):xavier(m.weight.data)xavier(m.bias.data) 然后定义一个含2维卷积的网络&#xff…

HTB——introduction to active directory

文章目录 一、Active directory structure二、Active Directory Terminology 一、Active directory structure Active Directory (AD) 是用于 Windows 网络环境的目录服务。它是一种分布式分层结构,允许集中管理组织的资源,包括用…

Pytorch 里面torch.no_grad 和model.eval(), model.train() 的作用

torch.no_grad: 影响模型的自微分器,使得其停止工作;这样的话,数据计算的数据就会变快,内存占用也会变小,因为没有了反向梯度计算,当然,我哦们也无法做反向传播。 model.eval() 和model.train()…

开源项目管理工具Helper的安装及汉化

什么是 Helper ? Helper 是基于 Laravel 和 Filament 的开源项目管理工具。 官方提供了在线演示:https://project-helper.net 安装 在群晖上以 Docker 方式安装。 数据库理论上是可以使用群晖自带的 MariaDB 的,但老苏为了省事&#xff0c…

类和对象(一)

类和对象(一) 一:类的实例化1:什么是实例化2:类和对象的关系 二:类的初始化1:就地初始化2:默认初始化 三:this引用1:先看一个日期类的例子2:什么是this引用3&…

基于单片机的智能饮水机系统

收藏和点赞,您的关注是我创作的动力 文章目录 概要 一、系统设计方案分析2.1 设计功能及性能分析2.2设计方案分析 二、系统的硬件设计3.1 系统设计框图系统软件设计4.1 总体介绍原理图 四、 结论 概要 现在很多学校以及家庭使用的饮水机的功能都是比较单一的&#…

【Mac开发环境搭建】JDK安装、多JDK安装与切换

文章目录 JDK下载与安装下载安装 配置环境变量安装多个JDK共存 JDK下载与安装 下载 Oracle官网提供了非常多个版本的JDK供下载,可以点击如下链接重定向到JDK下载页面 ORACLE官网JDK下载 安装 下面的官方文档可以点开收藏到浏览器的收藏夹,这样后续在开…

高性能三防工业平板电脑 防摔防爆电容屏工控平板

HT1000是一款高性能工业三防平板,10.1英寸超清大屏,厚度仅14.9mm,超薄机身,可轻松插入袋中,方便携带,搭载8核2.0GHz高性能CPU,行业领先的Android 11.0,设备性能大幅提升,…

leetcode2054

leetcode 2054 #include <iostream> #include <vector> #include <tuple> #include <algorithm>using namespace std;struct Event {// 时间戳int ts;// op 0 表示左边界&#xff0c;op 1 表示右边界int op;int val;Event(int _ts, int _op, int _v…

本周三商店更新:多款套装下线,四款升级武器带异色皮肤返厂

本周三将迎来26.2版本更新与11商店大更新&#xff0c;版本更新可点击26.2版本更新公告进行查看&#xff0c;这里不一一赘述了&#xff0c;下面大概罗列一下商店更新&#xff0c;有皮肤下架&#xff0c;大家还能趁最后时间入手&#xff0c;最重要的是四款升级武器返厂咯。 危险玩…

Git 安全警告修复手册:解决 `fatal: detected dubious ownership in repository at ` 问题 ️

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Unity meta的一些常见属性

Unity会项目文件夹中的每个文件分配一个同名后缀为.meta的文件。 我们可以将meta文件理解不同文件之间的桥梁&#xff0c;通过它引擎可以管理不同文件之间的依赖关系。 使用TXT文本文件打开之后&#xff0c;大致属性如下&#xff1a; 其中常用的属性有guid、 assetBundleName以…

MYSQL:主从复制简述

&#xff08;图片来自于马士兵教育&#xff09; 从节点的I/O线程会请求主节点的Binlog&#xff0c;并且将得到的Binlog写入到本地relay_log&#xff08;中继日志&#xff09;中&#xff0c;SQL线程会读取realy_log中的日志文件&#xff0c;并且解析成SQL逐行执行。 主库会生成…

C-DS二叉树_另一棵树的子树

Description 给你两棵二叉树tree1和tree2&#xff0c;检验tree1中是否包含和tree2具有相同结构和结点值的子树。如果存在&#xff0c;输出true&#xff1b;否则&#xff0c;输出false。 Input 第一行输入t&#xff0c;表示有t个测试样例。 第二行首先输入n1&#xff0c;接着…