> For the complete documentation index, see [llms.txt](https://potoyang.gitbook.io/spring-in-action-v4/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://potoyang.gitbook.io/spring-in-action-v4/di-5-zhang-gou-jian-spring-web-ying-yong-cheng-xu/untitled-3.md).

# 5.4　处理表单

Web 应用的功能通常并不局限于为用户推送内容。大多数的应用允许用户填充表单并将数据提交回应用中，通过这种方式实现与用户的交互。像提供内容一样，Spring MVC 的控制器也为表单处理提供了良好的支持。

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

{% code title="程序清单 5.13　SpitterController：展现一个表单，允许用户注册该应用" %}

```java
package spittr.web;

import static org.springframework.web.bind.annotation.RequestMethod.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import spittr.Spitter;
import spittr.data.SpitterRepository;

@Controller
@RequestMapping("/spitter")
public class SpitterController {
  
  @RequestMapping(value="/register", method=GET)
  public String showRegistrationForm() {
    return "registerForm";
  }

}
```

{% endcode %}

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

尽管 showRegistrationForm() 方法非常简单，但测试依然需要覆盖到它。因为这个方法很简单，所以它的测试也比较简单。

{% code title="程序清单 5.14 测试展现表单的控制器方法" %}

```java
@Test
public void shouldShowRegistration() throws Exception {
  SpitterController controller = new SpitterController();
  MockMvc mockMvc = standaloneSetup(controller).build();
  
  mockMvc.perform(get("/spitter/register")).andExpect(view().name("registerForm"));
}
```

{% endcode %}

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

现在，让我们回到视图上。因为视图的名称为 registerForm，所以 JSP 的名称需要是 registerForm.jsp。这个 JSP 必须要包含一个 HTML `<form>` 标签，在这个标签中用户输入注册应用的信息。如下就是我们现在所要使用的 JSP。

{% code title="程序清单 5.15　渲染注册表单的 JSP" %}

```markup
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
  <head>
    <title>Spitter</title>
    <link rel="stylesheet" type="text/css" 
          href="<c:url value="/resources/style.css" />" >
  </head>
  <body>
    <h1>Register</h1>

    <form method="POST">
      First Name: <input type="text" name="firstName" /><br/>
      Last Name: <input type="text" name="lastName" /><br/>
      Email: <input type="email" name="email" /><br/>
      Username: <input type="text" name="username" /><br/>
      Password: <input type="password" name="password" /><br/>
      <input type="submit" value="Register" />
    </form>
  </body>
</html>
```

{% endcode %}

可以看到，这个 JSP 非常基础。它的 HTML 表单域中记录用户的名字、姓氏、用户名以及密码，然后还包含一个提交表单的按钮。在浏览器渲染之后，它的样子大致如图 5.5 所示。

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

这就意味着需要在服务器端处理该 HTTP POST 请求。现在，我们在 SpitterController 中再添加一个方法来处理这个表单提交。

![图 5.5　注册页提供了一个表单，这个表单会由 SpitterController 进行处理，完成为应用添加新用户的功能](/files/-LmruB2cHQMfLzIBgGR2)
