使用Spring 3 MVC处理表单验证

本文是有关Spring 3的系列文章的一部分。该系列的早期文章是使用Spring 3 MVC的Hello World和使用Spring 3 MVC的 Handling Forms 。

现在让我们更深入地研究Spring。 在本文中,我们将学习验证从表单中获取的数据。 让我们更仔细地看一下验证任务。

场景1 :我们可能需要验证,例如,所提供的电子邮件确实确实看起来像一封电子邮件(以简化的x @ xx格式显示)。 这可以通过仅在电子邮件字段本身上运行一些脚本来完成。 那应该很简单。 我们可以编写一些可在浏览器本身上运行JavaScript。 并且还要在服务器端写相同的验证[为什么? 在这里阅读 ]。 对于所有隔离的验证都是如此,例如,检查数据是否不为空,检查数据是否为一定长度等。

场景2 :希望生活如此简单。 由于我们正在讨论电子邮件验证,因此可以说其中一项验证要求我们检查电子邮件是否属于某些域(例如合作伙伴组织),以便系统也可以通过电子邮件发送某些特权信息。 假设我们需要检查电子邮件的格式为x @ partner1.com,x @ partner2.com或x@partner3.com。 可能很琐碎,这是无法仅对表单本身的数据进行验证的类型的示例。 无论验证代码是什么,它都需要知道哪些域有效。 并且此数据不存在于最终用户以表格形式提供的数据中。 如果您稍微发挥想象力,则可以轻松地创建用例,其中可能需要业务规则引擎(例如,规则过于灵活)和/或可以引入国际化元素(例如,所有国家/地区的成年人年龄都未满18岁) )或其他复杂性。 这些是非隔离的验证,需要访问同步可用的其他信息。 这些验证可以在服务器端和客户端都进行编码,尽管可以说它将更多地依赖于服务器端。

场景3 :同样,希望生活如此简单。 如果我们处于验证电子邮件的主题上,我们可能还需要检查电子邮件是否有效,即它不是thisemail@doesnot.exist(我不确定该电子邮件是否存在-或在其中不存在未来-但您希望我能想到)。 我们将需要向该电子邮件ID发送一封电子邮件,并可能要求用户单击并确认。 我们需要通过SMTP与其他系统进行异步交互。 同样,稍微依靠您的想象力,整个潘多拉盒子就会破裂。 很快,您将通过REST,SOAP,JMS,文件服务器进行集成,并通过分布式系统处理安全性和身份验证问题。 我敢打赌,大多数系统都将在该领域中进行服务器端验证,并且客户端验证(尽管在技术上是可行的)不会经常使用。

方案4 :而且我们还没有违反相同的领域对象的问题,这些领域对象不仅从基于Web的表单填充,而且还从Feed文件,JMS消息等填充,因此需要将相同的验证逻辑应用于多个渠道。 在本讨论开始时,它最初是一个微不足道的小形式,带有少量无辜的文本框,如今已演变为一个怪物。

幸运的是,JSR 303或Bean验证[ 此处 ]可以拯救。 它立即解决了上述情况1和4。 它支持您解决方案2和3。我建议您阅读标有“此标准对用户有何好处?”的部分。 它会解决什么问题?” 在此链接 。

该Java规范于2006年提出要求,并于2009年底发布。 换句话说,可用的实现已经有机会在一年中成熟。 作为一流的开源公民,Spring 3使您可以使用此标准解决方案,而不必重新发明轮子。 而且,如果您绝对需要重新发明轮子(所有专业应用程序都需要编写myAppSpecificKickAssValidator()),Spring也会允许这样做。 让我们一一看看这两种情况。

将JSR 303支持添加到任何基于Maven的项目

JSR 303是一个开放的api。 您可以在此链接中找到它。 任何人都可以实现。 有hibernate和apache bval的实现。 让我们一起进行Hibernate实现。 在此链接中,您可以在Maven Central看到他们的罐子。 在撰写本文时,最新的稳定版本是4.3.0.Final。 您只需要在pom中添加此依赖项即可。 该实现也捆绑了api,因此您无需添加任何一个。

档案:pom.xml

<properties>                                                                  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        [...]  
<hibernate.validation.version>4.3.0.Final</hibernate.validation.version>  [...]  
</properties>                                                            <!-- Hibernate validations -->  
<dependency>                                             <groupId>org.hibernate</groupId>                     <artifactId>hibernate-validator</artifactId>         <version>${hibernate.validation.version}</version>   
</dependency>

只需添加此依赖项,您就可以进入实体/表单类并声明约束。 JSR 303有一些标准约束( 在此处列出 ),涵盖了NotNull之类的标准检查。 Hibernate添加了一些非标准的自定义约束[ 此处列出 ]。 它们不是标准的,但是非常方便,例如检查有效的电子邮件。 让我们在ContactFrm.java中介绍这两项检查。 如果您不知道那是从哪里来的,那么您很可能没有阅读本系列的上一篇文章,即使用Spring 3 MVC处理表单 。

文件:/org/academy/ui/spring3/forms/ContactFrm.java

package org.academy.ui.spring3.forms;  import javax.validation.constraints.NotNull;  import org.hibernate.validator.constraints.Email;  public class ContactFrm {  @NotNull  private String firstname;  private String lastname;  @Email  private String email;  private String telephone;  // Getter and setters omitted for brevity.   [...]  
}

单元测试

到目前为止,我们的ContactFrm bean没有任何功能,因此我不费心进行单元测试(尽管TDD爱好者会对此表示怀疑)。 但是,现在仅通过添加几个注释,我们就为Bean添加了功能,并且可以进行单元测试(TDD爱好者可以从现在开始感到高兴)。 让我们添加一个单元测试。

文件:/src/test/java/org/academy/ui/spring3/forms/ContactFrmTest.java

package org.academy.ui.spring3.forms;  import static org.junit.Assert.*;  import java.util.Set;  import javax.validation.ConstraintViolation;  
import javax.validation.Validation;  
import javax.validation.Validator;  import org.junit.BeforeClass;  
import org.junit.Test;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  public class ContactFrmTest {  private final static Logger logger = LoggerFactory  .getLogger(ContactFrmTest.class);  private static Validator validator;  @BeforeClass  public static void init() {  validator = Validation.buildDefaultValidatorFactory().getValidator();  }  @Test  public void test() {  Set<ConstraintViolation<ContactFrm>> errors;  ContactFrm contactFrm = new ContactFrm();  errors = validator.validate(contactFrm);  printErrors(errors);  // We are expecting 1 error here.  // Just the NotNull.  assertEquals(1, errors.size());  errors.clear();  contactFrm.setFirstname("partha");  errors = validator.validate(contactFrm);  printErrors(errors);  // We are not expecting any errors here.  assertEquals(0, errors.size());  errors.clear();  contactFrm.setEmail("this can not be a valid email");  errors = validator.validate(contactFrm);  printErrors(errors);  // We are expecting 1 errors here.  assertEquals(1, errors.size());  errors.clear();  contactFrm.setEmail("this@mightbevalid.email");  errors = validator.validate(contactFrm);  printErrors(errors);  // We are not expecting any errors here.  assertEquals(0, errors.size());  errors.clear();  }  // Utility function to print out errors from validation.   private void printErrors(Set<ConstraintViolation<ContactFrm>> errors) {  if (errors.size() > 0) {  for (ConstraintViolation<ContactFrm> error : errors) {  logger.debug(error.getMessage());  }  } else {  logger.debug("There were no errors to print.");  }  }  }

您会发现我不需要使用任何Hibernate,Spring或JSR特定代码进行单元测试。 它只是一个简单的JUnit。 在我看来,只需添加几个批注就可以在POJO上添加验证,然后我可以使用标准的单元测试框架进行单元测试,而无需进行任何调整,这一事实是一个巨大的进步。 我们才刚刚开始。

单元测试–使用Spring功能。

当然,可以放心的是,我们可以在不依赖Spring的情况下完成完整的验证和单元测试。 但是,如果我们不探索在网站上使用Spring将这些功能整合在一起有多么容易,我们将完全错过本练习的重点。

首先,将所有必需的Spring依赖项添加到我们的项目中,并按照上一篇文章中的说明从公共记录中删除它们。

文件:/pom.xml

<dependency>                                           <groupId>org.springframework</groupId>             <artifactId>spring-context</artifactId>            <version>${org.springframework.version}</version>  <exclusions>                                       <exclusion>                                    <groupId>commons-logging</groupId>         <artifactId>commons-logging</artifactId>   </exclusion>                                   </exclusions>                                      
</dependency>                                          [...]  <dependency>                                           <groupId>org.springframework</groupId>             <artifactId>spring-test</artifactId>               <version>${org.springframework.version}</version>  <scope>test</scope>                                <exclusions>                                       <exclusion>                                    <groupId>commons-logging</groupId>         <artifactId>commons-logging</artifactId>   </exclusion>                                   </exclusions>                                      
</dependency>

现在, 如上一篇文章中所述,在单元测试中添加@RunWith和@ContextConfiguration魔术。

文件:/src/test/java/org/academy/ui/spring3/forms/ContactFrmTest.java

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration  
public class ContactFrmTest {  private final static Logger logger = LoggerFactory  .getLogger(ContactFrmTest.class);  @Autowired  private Validator validator;  // This is no more required as Spring does it for us.   // @BeforeClass  // public static void init() {  // validator = Validation.buildDefaultValidatorFactory().getValidator();  // }
[省略了其余代码,因为它仍然相同。]

现在,剩下的就是让我们告诉Spring应该在验证器中自动装配什么。 我们使用配置而不是代码来做到这一点。

文件:/src/test/resources/org/academy/ui/spring3/forms/ContactFrmTest-context.xml

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  xmlns:context="http://www.springframework.org/schema/context"  xsi:schemaLocation="http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
http://www.springframework.org/schema/context   
http://www.springframework.org/schema/context/spring-context-3.0.xsd">  <bean id="validator"  class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />  
</beans>

你们都准备好了。 您现在可以使用“ mvn -e clean install”来运行整个代码并对其进行单元测试。 如果您觉得要求太高,可以使用“ mvn -e网站”创建一个不错HTML网站,该网站将报告代码覆盖率。

  • JSR 303的主页
  • Hibernate Validator主页
  • Hibernate Validation首席开发人员访谈– Emmanuel Bernard
  • Spring关于验证的官方文档

参考:我们的JCG合作伙伴 Partho在Tech for Enterprise博客上使用Spring 3 MVC处理表单验证


翻译自: https://www.javacodegeeks.com/2012/08/handling-forms-with-spring-3-mvc.html

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

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

相关文章

当事人角色 变更映射策略引起的问题

IBeamMDAA V2版本中&#xff0c;由于变更了 当事人角色 的继承机制&#xff0c;在添加 当事人角色时&#xff0c;为了 构建 当事人-当事人角色之间的关系&#xff0c;代码如下&#xff1a;//if (party.PartyRoles ! null && !party.PartyRoles.Contains(sysUser))//{//…

vs xxxxx nuget配置无效

重启vs转载于:https://www.cnblogs.com/zinan/p/7080668.html

巡回沙龙_美浮特全国巡回沙龙第一期结束撒花!

科技美肤&#xff0c;无龄焕变。美浮特2019全国美肤巡回沙龙第一期活动圆满结束&#xff01;优秀的小伙伴&#xff0c;雅致的茶歇环境&#xff0c;精美的甜点小食&#xff0c;理论与体验并行的肤感测试课堂……不知道是哪一个环节给大家留下了深刻的印象呢&#xff1f;首先让我…

Spring与网关的集成

这是有关Spring Integration系列的第二篇文章。 本文以我们介绍Spring Integration的第一篇文章为基础。 上下文设置 在第一篇文章中&#xff0c;我们创建了一个简单的Java应用程序&#xff0c;其中 通过频道发送了一条消息&#xff0c; 它被服务&#xff08;即POJO&#xf…

UIAutomation识别UI元素

MS UI Automation&#xff08;Microsoft User Interface Automation&#xff1a;UIA&#xff09;是随.net framework3.0一起发布的&#xff0c;虽然在如今这个几乎每天都有各种新名词、新技术出来的所谓的21世纪&#xff0c;它显得已经有些过时了。前些日子&#xff0c;正好一个…

【C++第一个Demo】---控制台RPG游戏3【登陆菜单树】

【登陆系统--树结构】 1 首先我这里设计&#xff0c;由一个基类MainMenu构建树结构&#xff0c;并实现控制台上菜单之间的切换和返回操作 1 #ifndef _UI_BASE_H_2 #define _UI_BASE_H_3 4 #include <string>5 #include <vector>6 #include"..//Marco.h"7…

不存在_施文忠 | ”存在“与“不存在”——巴蜀文明概论

海德格尔有句名言&#xff1a;“存在者存在&#xff0c;不存在者不存在&#xff01;”四川&#xff0c;一个伟大的存在&#xff0c;偏偏存在于四川的口头禅却是“不存在”。在不存在中追求存在&#xff0c;在存在中摆脱存在。六月白鹿镇&#xff0c;书院学习了《李白与海德格尔…

Spring和JSF集成:异常处理

大多数JSF开发人员都会熟悉“发生错误”页面&#xff0c;当在他们的代码某处引发意外异常时&#xff0c;该页面就会显示。 该页面在开发时确实很有用&#xff0c;但对于生产应用程序通常不是您想要的。 通常&#xff0c;在用库存JSF替换此页面时&#xff0c;您有两种选择。 您可…

Altium 原理图出现元件“Extra Pin…in Normal of part ”警告的解决方法

转载于&#xff1a; http://blog.csdn.net/idoming/article/details/45575627 使用Altium Designer的时候编译完后&#xff0c;只关注过错误没有关注过警告&#xff0c;现在认真排查一下有哪些警告。 正在进行的项目原理图编译完成后提示标题中的警告信息。经过在网上搜索&…

XidianOJ 1087 浪漫的V8

题目描述 V8为了讨女朋友开心&#xff0c;给lx承包大活后面那个水塘。为了筹集资金&#xff0c;V8偷偷地溜进了一座古墓&#xff0c;发现在他面前有金光闪闪的若干小箱子&#xff0c;里面全都是金粉&#xff0c;作为横行于各种#&#xffe5;&场所的V8来说&#xff0c;辨别不…

curl php 模拟来源_php 使用curl模拟ip和来源进行访问的实现方法

对于限制了ip和来源的网站&#xff0c;使用正常的访问方式是无法访问的。本文将介绍一种方法&#xff0c;使用php的curl类实现模拟ip和来源&#xff0c;访问那些限制了ip和来源的网站。1.设置页面限制ip和来源访问server.php$client_ip getip();$referer getreferer();$allow…

堆栈C语言实现

堆栈的抽象数据类型描述&#xff1a; 类型名称&#xff1a; 堆栈&#xff08;Stack&#xff09;。数据对象集&#xff1a; 一个有 0 个或多个元素的又穷表。操作集&#xff1a; 长度为 max_size 的堆栈 S ∈ Stack&#xff0c; 堆栈元素 item ∈ ElementType。stack creatc_sta…

woocommerce 分类到菜单_Woocommerce商店显示分类

我是wordpress的新手, 所以如果我输入的语言错误, 请仍然为我提供帮助。我想使用woocommerce显示具有可变产品的商店, 我希望商店链接登录页面显示具有该类别特征图像的商店类别。我当前的商店页面显示所有产品, 并分页到其他产品页面, 我找不到所有产品的模板。当我进入wp-adm…

JBoss BRMS 5.3 –添加了业务活动监视(BAM)报告

自从JBoss BRMS 5.3产品发布以来&#xff0c;添加了jBPM 5 BPM组件的最常见问题之一是业务活动监视&#xff08;BAM&#xff09;和报告功能。 本文将引导您完成添加过程&#xff0c;但是请注意&#xff0c;在撰写本文时&#xff0c;这不是产品的受支持功能。 在JBoss BRMS 5.3上…

Zookeeper开源客户端框架Curator简介

Curator是Netflix开源的一套ZooKeeper客户端框架. Netflix在使用ZooKeeper的过程中发现ZooKeeper自带的客户端太底层, 应用方在使用的时候需要自己处理很多事情, 于是在它的基础上包装了一下, 提供了一套更好用的客户端框架. Netflix在用ZooKeeper的过程中遇到的问题, 我们也遇…

【树形DP】 HDU 2196 Computer

题意&#xff1a;求节点间的最大距离 先DFS一次 记录下 每一节点的子树下的最大距离&#xff08;DP[ u ] [ 0 ]&#xff09;和第二大距离&#xff08;DP[ u ] [ 1 ]&#xff09; 用DP[ v ] [ 2 ] 表示由v的父节点来的最大距离 再取DP[ u ] [ 0 ] 与 DP[ u ][ 2 ] 的最值 #inclu…

适当的Java堆大小的5个技巧

确定生产系统合适的Java堆大小不是一件容易的事。 在我的Java EE企业经验中&#xff0c;我发现由于Java堆容量和调整不足而导致的多个性能问题。 本文将为您提供5个技巧&#xff0c;这些技巧可以帮助您确定当前或新生产环境的最佳Java堆大小。 这些技巧中的一些对于预防和解决j…

pythondocumentation是什么_怎样阅读Python官方文档

如何阅读官方Python文档的初学者,因为他们没有相关的经验,学习语言通常是费时且劳动密集型和效果不是很好。下面简要介绍如何阅读官方文件。一旦你学会快速查询官方文件,学习效率会提高很多文档门户。如何阅读API文档中内容标准库,如何快速找到你想要的。第一种方法是先查找索引…

数据库过大无法导入

导SQL数据库结构数据时&#xff0c;如果数据是批量插入的话会报错&#xff1a;2006 - MySQL server has gone away。 解决办法&#xff1a;找到你的mysql目录下的my.ini配置文件&#xff0c;加入以下代码 max_allowed_packet500M wait_timeout288000 interactive_timeout 2880…

UVa 11475 - Extend to Palindrome

題目&#xff1a;給你一個字符串&#xff0c;在後面拼接一部分使得它變成回文串&#xff0c;使得串最短。輸出這個回文串。分析&#xff1a;KMP&#xff0c;dp。這裡利用KMP算法將串和它的轉置匹配&#xff0c;看結束時匹配的長度就可以。 因為串比较長。使用KMP比较合適&#…