笔记28 接受请求的输入 ——处理表单

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

1.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来渲染注册表单。 

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

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。 

3.渲染注册表单的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="fistName"/><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”上。 

4.在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进行保存,控 制器会像之前那样重定向到基本信息页面。

5.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包中。

   

6.测试

猜你喜欢

转载自www.cnblogs.com/lyj-gyq/p/8953511.html
今日推荐