Spittr应用有两个基本的领域概念:Spitter(应用的用户)和 Spittle(用户发布的简短状态更新)。

在笔记25中已经对Spittle进行了简单的构建,现在对Spitter进行实现。主要是用户的注册、用户基本信息的展示。

注册的时候就会涉及到对表单的处理,使用表单分为两个方面:展现表单以及处理用户通过表单提交的数据。在Spittr应用中,我们需要有个表单让新用户进行注册。SpitterController是一个新的控制器,目前只有一个请求处理的方法来展现注册表单。

1.首先构建数据访问的Repository。为了实现解耦以及避免 陷入数据库访问的细节之中,我们将Repository定义为一个接口,并在稍后实现它我们只需要一个能够获取Spitter对象的Repository,如下所示的SpitterRepositorys.java

1 package myspittr.data;
2
3 import myspittr.spitter.Spitter;
4
5 public interface SpitterRepositorys {
6     Spitter save(Spitter spitter);
7
8     Spitter findByUsername(String username);
9 }

2.然后创建它的实现类JdbcSpitterRepository2.java用来访问数据库,然后读取数据,但是目前还不需要对数据库进行操作,所以需要自己做一下假数据。

 1 package myspittr.data;
 2
 3 import org.springframework.stereotype.Service;
 4
 5 import myspittr.spitter.Spitter;
 6
 7 @Service
 8 public class JdbcSpitterRepository2 implements SpitterRepositorys {
 9
10     private Spitter savedSpitter;
11
12     public JdbcSpitterRepository2() {
13     }
14
15     public Spitter save(Spitter spitter) {
16         // TODO Auto-generated method stub
17         Spitter spitter2 = new Spitter(spitter.getUsername(), spitter.getPassword(), spitter.getFirstName(),
18                 spitter.getLastName());
19         this.savedSpitter = spitter2;
20         return spitter2;
21     }
22
23     public Spitter findByUsername(String username) {
24         // TODO Auto-generated method stub
25         if (username.equals(savedSpitter.getUsername())) {
26             return savedSpitter;
27         } else {
28             return null;
29         }
30
31     }
32
33 }

3.SpitterController.java  展现一个表单,允许用户注册该应用

 1 package spittr.web;
 2
 3 import javax.validation.Valid;
 4
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.stereotype.Controller;
 7 import org.springframework.ui.Model;
 8 import org.springframework.validation.Errors;
 9 import org.springframework.web.bind.annotation.PathVariable;
10 import org.springframework.web.bind.annotation.RequestMapping;
11 import org.springframework.web.bind.annotation.RequestMethod;
12
13 import spittr.data.SpitterRepository;
14 import spittr.spitter.Spitter;
15
16 @Controller
17 @RequestMapping("/spitter")
18 public class SpitterController {
19
20     @RequestMapping(value = "/register", method = RequestMethod.GET) // 处理对“/spitter/register”的GET请求
21     public String showRegistrationForm() {
22         return "registerForm";
23     }
24
25
26 }

showRegistrationForm()方法的@RequestMapping注解以及 类级别上的@RequestMapping注解组合起来,声明了这个方法要处 理的是针对“/spitter/register”的GET请求。这是一个简单的方法,没有 任何输入并且只是返回名为registerForm的逻辑视图。按照我们 配置InternalResourceViewResolver的方式,这意味着将会使 用“/WEB-INF/ views/registerForm.jsp”这个JSP来渲染注册表单。 

4.测试展现表单的控制器方法

1     @Test
2     public void shouldShowRegistration() throws Exception {
3         SpitterController controller = new SpitterController();
4         MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); // 构建MockMvc
5         mockMvc.perform(get("/spitter/register")).andExpect(view().name("registerForm")); // 断言registerForm视图
6     }

这个测试方法与首页控制器的测试非常类似。它对“/spitter/register”发 送GET请求,然后断言结果的视图名为registerForm。 

5.渲染注册表单的JSP   registerForm.jsp

 1 <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11
12     <title>Spitter</title>
13     <link rel="stylesheet" type="text/css" href="<c:url value="/respurces/style.css"/>">
14
15     <meta http-equiv="pragma" content="no-cache">
16     <meta http-equiv="cache-control" content="no-cache">
17     <meta http-equiv="expires" content="0">
18     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
19     <meta http-equiv="description" content="This is my page">
20     <!--
21     <link rel="stylesheet" type="text/css" href="styles.css">
22     -->
23
24   </head>
25
26   <body>
27     <h1>Register</h1>
28     <form action="" method="POST">
29         First Name:<input type="text" name="firstName"/><br>
30         Last Name:<input type="text" name="lastName"><br>
31         Username:<input type="text" name="username"><br>
32         Password:<input type="password" name="password"><br>
33         <input type="submit" value="Register"/>
34     </form>
35   </body>
36 </html>

需要注意的是:这里的<form>标签中并没有设置action属性。在这种情况下,当表单提交时,它会提交到与展现时相同的URL路径上。也就是说,它会提交到“/spitter/register”上。 

6.在SpitterController中再添加一个方法来处理这个表单提交,即处理所提交的表单并注册新用户。

 1 package spittr.web;
 2
 3 import javax.validation.Valid;
 4
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.stereotype.Controller;
 7 import org.springframework.ui.Model;
 8 import org.springframework.validation.Errors;
 9 import org.springframework.web.bind.annotation.PathVariable;
10 import org.springframework.web.bind.annotation.RequestMapping;
11 import org.springframework.web.bind.annotation.RequestMethod;
12
13 import spittr.data.SpitterRepository;
14 import spittr.spitter.Spitter;
15
16 @Controller
17 @RequestMapping("/spitter")
18 public class SpitterController {
19
20     private SpitterRepository spitterRepository;
21
22     public SpitterController() {
23
24     }
25
26     @Autowired // 注入SpitterRepository
27     public SpitterController(SpitterRepository spitterRepository) {
28         this.spitterRepository = spitterRepository;
29     }
30
31     @RequestMapping(value = "/register", method = RequestMethod.GET) // 处理对“/spitter/register”的GET请求
32     public String showRegistrationForm() {
33         return "registerForm";
34     }
35
36     @RequestMapping(value = "/register", method = RequestMethod.POST)
37     public String processRegistration(@Valid Spitter spitter, // 校验Spitter输入
38             Errors errors) {
39         if (errors.hasErrors()) {
40             return "registerForm"; // 如果校验出现错误,则重新返回表单
41         }
42         spitterRepository.save(spitter); //保存Spitter
43         return "redirect:/spitter/" + spitter.getUsername();  //重定向到基本信息页
44     }
45
46     @RequestMapping(value = "/{username}", method = RequestMethod.GET)
47     public String showSpitterProfile(@PathVariable String username, Model model) {
48         Spitter spitter = spitterRepository.findByUsername(username);
49         model.addAttribute(spitter);
50         return "profile";
51     }
52 }

之前创建的showRegistrationForm()方法依然还在,不过新创建的processRegistration()方法,它接受一 个Spitter对象作为参数。这个对象 有firstName、lastName、username和password属性,这些属性将会使用请求中同名的参数进行填充。 

当使用Spitter对象调用processRegistration()方法时,它会进而调用SpitterRepository的save()方 法,SpitterRepository是在SpitterController的构造器中 注入进来的。 

processRegistration()方法做的最后一件事就是返回一 个String类型,用来指定视图。但是这个视图格式和以前的视图有所不同。这里不仅返回了视图的名称供视图解析器查找目 标视图,而且返回的值还带有重定向的格式。 如果Spitter.username属性的值为“jbauer”,那么视图将会重 定向到“/spitter/jbauer”。

需要注意的是,除 了“redirect:”,InternalResourceViewResolver还能识 别“forward:”前缀。当它发现视图格式中以“forward:”作为前缀 时,请求将会前往(forward)指定的URL路径,而不再是重定向。 

并且在processRegistration()方法中启用校验功能,Spitter参数添加了@Valid注解,这会告知 Spring,需要确保这个对象满足校验限制。 在Spitter属性上添加校验限制并不能阻止表单提交。即便用户没 有填写某个域或者某个域所给定的值超出了最大长 度,processRegistration()方法依然会被调用。这样,我们就 需要处理校验的错误,就像在processRegistration()方法中所 看到的那样。 

如果有校验出现错误的话,那么这些错误可以通过Errors对象进行 访问,现在这个对象已作为processRegistration()方法的参 数。(很重要一点需要注意,Errors参数要紧跟在带有@Valid注 解的参数后面,@Valid注解所标注的就是要检验的参 数。)processRegistration()方法所做的第一件事就是调 用Errors.hasErrors()来检查是否有错误。

  • 如果有错误的话,Errors.hasErrors()将会返回 到registerForm,也就是注册表单的视图。这能够让用户的浏览 器重新回到注册表单页面,所以他们能够修正错误,然后重新尝试提 交。
  • 如果没有错误的话,Spitter对象将会通过Repository进行保存,控 制器会像之前那样重定向到基本信息页面。

7.Spitter类,在属性上添加校验注解

 1 package spittr.spitter;
 2
 3 import javax.validation.constraints.NotNull;
 4 import javax.validation.constraints.Size;
 5
 6 import org.apache.commons.lang3.builder.EqualsBuilder;
 7 import org.apache.commons.lang3.builder.HashCodeBuilder;
 8
 9 public class Spitter {
10
11     private Long id;
12
13     @NotNull
14     @Size(min = 5, max = 16)
15     private String username;
16
17     @NotNull
18     @Size(min = 5, max = 25)
19     private String password;
20
21     @NotNull
22     @Size(min = 2, max = 30)
23     private String firstName;
24
25     @NotNull
26     @Size(min = 2, max = 30)
27     private String lastName;
28
29     public Spitter() {
30     }
31
32     public Spitter(String username, String password, String firstName, String lastName) {
33         this(null, username, password, firstName, lastName);
34     }
35
36     public Spitter(Long id, String username, String password, String firstName, String lastName) {
37         this.id = id;
38         this.username = username;
39         this.password = password;
40         this.firstName = firstName;
41         this.lastName = lastName;
42     }
43
44     public String getUsername() {
45         return username;
46     }
47
48     public void setUsername(String username) {
49         this.username = username;
50     }
51
52     public String getPassword() {
53         return password;
54     }
55
56     public void setPassword(String password) {
57         this.password = password;
58     }
59
60     public Long getId() {
61         return id;
62     }
63
64     public void setId(Long id) {
65         this.id = id;
66     }
67
68     public String getFirstName() {
69         return firstName;
70     }
71
72     public void setFirstName(String firstName) {
73         this.firstName = firstName;
74     }
75
76     public String getLastName() {
77         return lastName;
78     }
79
80     public void setLastName(String lastName) {
81         this.lastName = lastName;
82     }
83
84     @Override
85     public boolean equals(Object that) {
86         return EqualsBuilder.reflectionEquals(this, that, "firstName", "lastName", "username", "password", "email");
87     }
88
89     @Override
90     public int hashCode() {
91         return HashCodeBuilder.reflectionHashCode(this, "firstName", "lastName", "username", "password", "email");
92     }
93
94 }

Spitter的所有属性都添加了@NotNull注解,以确保它们的 值不为null。类似地,属性上也添加了@Size注解以限制它们的长 度在最大值和最小值之间。对Spittr应用来说,这意味着用户必须 要填完注册表单,并且值的长度要在给定的范围内。 

Java校验API定义了多个注解,这些注解可以放到属性上,从而限制 这些属性的值。所有的注解都位于 javax.validation.constraints包中。

   

8.基本信息展示,profile.jsp 用来展示用户的username和firstName

 1 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 2 <%@ page session="false" %>
 3 <html>
 4   <head>
 5     <title>Spitter</title>
 6     <link rel="stylesheet" type="text/css" href="<c:url value="/resources/style.css" />" >
 7   </head>
 8   <body>
 9     <h1>Your Profile</h1>
10     <c:out value="${spitter.username}" /><br/>
11     <c:out value="${spitter.firstName}" /> <c:out value="${spitter.lastName}" /><br/>
12   </body>
13 </html>

9.测试

部署到服务器上会发生以下错误,即无法创建JdbcSpitterRepository2这个bean。

需要在JdbcSpitterRepository2和JdbcSpittleRepository2两个类前增加一个注解,@Service.

@Service用于标注业务层组件,@Controller用于标注控制层组件

主页:

点击Spittles,展示最近发布的20个spittle

返回点击Register:

填入个人信息,点击注册:

    

使用注解的方式进行表单校验时发生错误,一直未解决,现在给出另一种校验方式

1.spring中自带框架校验器

(1)spring 校验器接口

(2)spring 提供的校验类工具,可以提供相应的校验

2.代码示例

<1>Spitter.java  没有任何注解

 1 package myspittr.spitter;
 2
 3 import org.apache.commons.lang3.builder.EqualsBuilder;
 4 import org.apache.commons.lang3.builder.HashCodeBuilder;
 5
 6 public class Spitter {
 7
 8     private Long id;
 9
10     private String username;
11
12     private String password;
13
14     private String firstName;
15
16     private String lastName;
17
18     public Spitter() {
19     }
20
21     public Spitter(String username, String password, String firstName, String lastName) {
22         this(null, username, password, firstName, lastName);
23     }
24
25     public Spitter(Long id, String username, String password, String firstName, String lastName) {
26         this.id = id;
27         this.username = username;
28         this.password = password;
29         this.firstName = firstName;
30         this.lastName = lastName;
31     }
32
33     public String getUsername() {
34         return username;
35     }
36
37     public void setUsername(String username) {
38         this.username = username;
39     }
40
41     public String getPassword() {
42         return password;
43     }
44
45     public void setPassword(String password) {
46         this.password = password;
47     }
48
49     public Long getId() {
50         return id;
51     }
52
53     public void setId(Long id) {
54         this.id = id;
55     }
56
57     public String getFirstName() {
58         return firstName;
59     }
60
61     public void setFirstName(String firstName) {
62         this.firstName = firstName;
63     }
64
65     public String getLastName() {
66         return lastName;
67     }
68
69     public void setLastName(String lastName) {
70         this.lastName = lastName;
71     }
72
73     @Override
74     public boolean equals(Object that) {
75         return EqualsBuilder.reflectionEquals(this, that, "firstName", "lastName", "username", "password", "email");
76     }
77
78     @Override
79     public int hashCode() {
80         return HashCodeBuilder.reflectionHashCode(this, "firstName", "lastName", "username", "password", "email");
81     }
82
83 }

<2>自实现校验器SpitterValidator.java类

rejectIfEmpty函数由三个参数,第一个是返回错误,第二个是绑定的属性名,第三个是返回的错误信息(使用资源文件)。
 1 package myspittr.validates;
 2
 3 import org.springframework.validation.Errors;
 4 import org.springframework.validation.ValidationUtils;
 5 import org.springframework.validation.Validator;
 6
 7 import myspittr.spitter.Spitter;
 8
 9 public class SpitterValidator implements Validator {
10
11     @Override
12     public boolean supports(Class<?> arg0) {
13         // TODO Auto-generated method stub
14         return false;
15     }
16
17     @Override
18     public void validate(Object arg0, Errors errors) {
19         // TODO Auto-generated method stub
20         Spitter spitter = (Spitter) arg0;
21
22         // 非空校验
23         ValidationUtils.rejectIfEmpty(errors, "firstName", "spittr.firstName");
24         ValidationUtils.rejectIfEmpty(errors, "lastName", "spittr.lastName");
25         ValidationUtils.rejectIfEmpty(errors, "username", "spittr.username");
26         ValidationUtils.rejectIfEmpty(errors, "password", "spittr.password");
27     }
28
29 }

<3>调用  重写SpitterController.java中的processRegistration方法。

 1     @RequestMapping(value = "/register", method = RequestMethod.POST)
 2     public String processRegistration(@Validated Spitter spitter, BindingResult errors) {
 3
 4         SpitterValidator spitterValidator = new SpitterValidator();
 5         spitterValidator.validate(spitter, errors);
 6         if (errors.hasErrors()) {
 7             return "registerForm2"; // 如果校验出现错误,则重新返回表单
 8         } else {
 9             spitterRepository.save(spitter); // 保存Spitter
10             return "redirect:/spitter/" + spitter.getUsername(); // 重定向到基本信息页
11         }
12
13     }

<4>资源文件

<5>registerForm.jsp

 1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
 2 <%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf"%>
 3 <%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
 4
 5 <%
 6 String path = request.getContextPath();
 7 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 8 %>
 9
10 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
11 <html>
12 <head>
13 <base href="<%=basePath%>">
14
15 <title>注册</title>
16
17 <meta http-equiv="pragma" content="no-cache">
18 <meta http-equiv="cache-control" content="no-cache">
19 <meta http-equiv="expires" content="0">
20 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
21 <meta http-equiv="description" content="This is my page">
22 <!--
23     <link rel="stylesheet" type="text/css" href="styles.css">
24     -->
25
26 </head>
27
28 <body>
29 <h1>Register</h1>
30     <sf:form method="POST" modelAttribute="spitter">
31             First Name:<sf:input path="firstName" />
32         <br>
33         <sf:errors path="firstName">
34
35         </sf:errors>
36         <br>
37
38             Last Name:<sf:input path="lastName" />
39         <br>
40         <sf:errors path="lastName">
41
42         </sf:errors>
43         <br>
44             UserName:<sf:input path="username" />
45         <br>
46         <sf:errors path="username">
47
48         </sf:errors>
49         <br>
50             Password:<sf:password path="password" />
51         <br>
52         <sf:errors path="password">
53
54         </sf:errors>
55         <br>
56         <input type="submit" value="注册">
57     </sf:form>
58 </body>
59 </html>

<6>测试

表单为空时点击注册按钮:

    

某几个字段为空时:

转载于:https://www.cnblogs.com/lyj-gyq/p/8953511.html

笔记28 接受请求的输入 ——处理表单相关推荐

  1. 【Springboot学习笔记】SpringBoot+Mybatis+Thymeleaf+Layui数据表单从零开始实现按条件模糊分页查询的方法

    [Springboot学习笔记]SpringBoot+Mybatis+Thymeleaf+Layui数据表单从零开始实现按条件模糊分页查询的方法 目录 1.搭建环境 1.1直接从网上下载SpringB ...

  2. AJAX学习笔记——发送AJAX的POST请求,模拟from表单提交

    关于AJAX发送POST请求,首先演示一个小案例. 当输入用户名:张三,密码:123.点击发送请求按钮 这是用post请求模拟的表单提交.接下来看一下如何用AJAX发送POST请求 后端代码: @We ...

  3. 初学HTML代码笔记3终结篇之列表和表单(pink老师)

    一.代码部分 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF- ...

  4. IE兼容笔记(一):兼容IE9表单上传文件

    几年前做兼容IE8的pc端项目的时候就遇到文件上传的需求,当时也是查看文档来解决IE9以下不支持formData的问题.由于之前没有写博客的习惯,最近又遇到这样的需求,所以写出来想帮助需要用到的朋友. ...

  5. C# 后台发送Post Get请求 Json数据或表单数据

    Http请求类 public class HttpResponse{#region Static Fieldprivate static readonly string DefaultUserAgen ...

  6. Android json请求格式与from表单格式

    这2中请求,是我们请求中常见到的,在了解这2中请求的时候首先需要先了解下Content-Type, 1 json 请求 首先需要设置下Content-Type ,说明这个请求为json请求 一般这个都 ...

  7. JavaScript 笔记(2) -- 类型转换 正则表达 变量提升 表单验证

    目录:  typeof, null, undefined, valueOf() 类型转换 正则表达式 错误: try, catch, throw 调试工具 变量提升 strict 严格模式 使用误区 ...

  8. Web前端开发笔记——第二章 HTML语言 第八节 表单标签

    目录 一.表单的定义 二.输入标签 (一)文本框和密码框 (二)提交按钮和重置按钮 (三)数值选项菜单 (四)滑动条 (五)搜索框 (六)input标签的其它type属性 (七)单选框和复选框 (八) ...

  9. angularjs学习第四天笔记(第一篇:简单的表单验证)

    您好,我是一名后端开发工程师,由于工作需要,现在系统的从0开始学习前端js框架之angular,每天把学习的一些心得分享出来,如果有什么说的不对的地方,请多多指正,多多包涵我这个前端菜鸟,欢迎大家的点 ...

最新文章

  1. 线性代数:第二章 矩阵及其运算(上)
  2. sql server 2008 故障转移群集
  3. maven scala plugin 实现jvmArgs,执行过程原理解析笔记
  4. 【好程序员笔记分享】——下拉刷新和上拉加载更多
  5. PHP获取用户地址方法
  6. python unicodedecodeerror_如何解决python UnicodeDecodeError问题?
  7. 生成跨语言的类型声明和接口绑定的工具(Djinni )
  8. (原创总结) Quartus II 的在线调试方法
  9. 【Linux系统编程学习】 GCC编译器
  10. UVA10602 Editor Nottoobad【贪心】
  11. WebServic调用天气预报服务
  12. MSMS探针卡市场现状及未来发展趋势
  13. 《嵌入式C编程:PIC单片机和C编程技术与应用》一导读
  14. 人生是一场旅程,重要的不是终点,是自己路上的风景
  15. mcgs odbc mysql_MCGS构建实时数据库.doc
  16. 【教程】Ubuntu20.04 + VirtualBox 各种软件环境安装
  17. 【第三方互联】1、注册成为腾讯QQ开发者
  18. Android手机哪个悬浮好用,别羡慕苹果了,安卓悬浮神器比 iPhone 好用太多!
  19. 【开箱即用】VMware Win7虚拟机下载
  20. ArcGIS简单的三维演示

热门文章

  1. aapt2 适配之资源 id 固定
  2. Part 1 – Reverse engineering using Androguard
  3. 一起学设计模式-观察者模式
  4. 【问链-EOS公开课】第十课 EOS 错误码整理
  5. mysql 查询后怎么定位列_MySQL如何定位并优化慢查询sql
  6. ms17-010 php版本,那年MS17-010
  7. python列表切片得到的是列表还是字符串_python中列表的切片问题 python arry怎么取列切片...
  8. python词云代码简单_Python 简单实现标签词云
  9. mysql8 修改密码_最新版本mysql8.0.18windows x64部署手册
  10. 哪些人不适合去做科研(转)