Spring MVC处理表单的实例分析


Web 应用的功能通常不局限于给用户推送内容,大多数应用允许用户填充表单并将数据提交回应用中,通过这种方式与用户进行交互。使用表单分为展现表及和处理用户通过表单提交的数据。

关于注册的一个小例子


控制器:

SpitterController.java用来处理展示表单、处理用户提交的数据并且展示用户注册信息功能。

package XiyouLinux.controller;

import XiyouLinux.data.Spitter;
import XiyouLinux.data.SpitterRepository;
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.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.Valid;


@Controller
@RequestMapping("/")
public class SpitterController {

    private SpitterRepository spitterRepository;

    // 注入SpitterRepository
    @Autowired
    public SpitterController(SpitterRepository spitterRepository) {
        this.spitterRepository = spitterRepository;
    }

    //处理表单
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public String processRegistration(@ModelAttribute("command") @Valid Spitter spitter, Errors errors) {
        if(errors.hasErrors()){
            return "registerForm";
        }
        // 保存Spitter
        spitterRepository.save(spitter);
        // 重定向到新的页面
        return "redirect:/" + spitter.getUsername();
    }

    //展示表单
    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public ModelAndView student() {
        return new ModelAndView("registerForm", "command", new Spitter());
    }

    //展现某个用户的注册信息
    @RequestMapping(value = "/{username}", method = RequestMethod.GET)
    public String showSpitterProfile(@PathVariable("username") String username, Model model) {
        Spitter spitter = spitterRepository.findByUsername(username);
        model.addAttribute(spitter);
        return "profile";
    }
}

用来渲染的JSP

registerForm.jsp展示表单和响应的错误信息,modelAttribute表明该表单和model里对象对应;form:labelform:passwordform:input等标签的中的path表明其和model里的对象的属性对应。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<jsp:useBean id="command" class="XiyouLinux.data.Spitter" scope="request"></jsp:useBean>
<html>
<head>
  <title>Register</title>
  <style type="text/css">
    span.error {
      color: red;
    }

    label.error {
      color: red;
    }

    input.error {
      background-color: #ffcccc;
    }

    div.errors {
      background-color: #ffcccc;
      border: 1px;
    }
  </style>
</head>
<body>

<h2>Register</h2>
<form:form method="POST" action="/register" modelAttribute="command">
  <form:errors path="firstname"  element="div" cssClass="errors" />
  <form:errors path="lastname"   element="div" cssClass="errors" />
  <form:errors path="username"   element="div" cssClass="errors" />
  <form:errors path="password"   element="div" cssClass="errors" />

  <table>
    <tr>
      <td><form:label path="firstname" cssErrorClass="error">First name</form:label></td>
      <td><form:input path="firstname" cssErrorClass="error"/></td>
    </tr>
    <tr>
      <td><form:label path="lastname" cssErrorClass="error">Last name</form:label></td>
      <td><form:input path="lastname" cssErrorClass="error"/></td>
    </tr>
    <tr>
      <td><form:label path="username" cssErrorClass="error">Username</form:label></td>
      <td><form:input path="username" cssErrorClass="error"/></td>
    </tr>
    <tr>
      <td><form:label path="password" cssErrorClass="error">Password</form:label></td>
      <td><form:password path="password"  cssErrorClass="error"/></td>
    </tr>
    <tr>
      <td colspan="2">
        <input type="submit" value="register"/>
      </td>
    </tr>
  </table>
</form:form>
</body>
</html>

profile.jsp用来展示某个用户的注册信息,” ${ } “可以用来取的model中属性对应的值。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>Your Profile</title>
</head>
<body>
  <h1>Your profile</h1>
  Username: <c:out value="${spitter.username}" /> <br/>
  Firstname:<c:out value="${spitter.firstname}" /> <br/>
  Lastname:<c:out value="${spitter.lastname}" /> <br/>
</body>
</html>

关于Spring的配置

configuration.java

package XiyouLinux.configuration;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;


@Configuration
@ComponentScan(basePackages = "XiyouLinux")

public class configuration extends WebMvcConfigurationSupport{

    //视图解析器
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        return viewResolver;
    }

    @Bean
    public LocalValidatorFactoryBean localValidatorFactoryBean()
    {
        LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
        localValidatorFactoryBean.setValidationMessageSource(ResourceBundleMessageSource());
        return localValidatorFactoryBean;
    }

    @Bean
    public ResourceBundleMessageSource ResourceBundleMessageSource()
    {
        ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
        resourceBundleMessageSource.setBasename("ValidationMessages");
        resourceBundleMessageSource.setCacheSeconds(60);
        resourceBundleMessageSource.setDefaultEncoding("UTF-8");
        return resourceBundleMessageSource;
    }

    //处理静态资源
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
    {
        configurer.enable();
    }
}

Initializer.java

package XiyouLinux.configuration;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class Initializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { configuration.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

pom.xml要添加相应的依赖

<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: pom.xml 642118 2008-03-28 08:04:16Z reinhard $ -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <packaging>war</packaging>

  <name>register</name>
  <groupId>XiyouLinux.org</groupId>
  <artifactId>register</artifactId>
  <version>1.0-SNAPSHOT</version>

  <build>
    <plugins>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.7</version>
        <configuration>
          <connectors>
            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
              <port>8888</port>
              <maxIdleTime>30000</maxIdleTime>
            </connector>
          </connectors>
          <webAppSourceDirectory>${project.build.directory}/${pom.artifactId}-${pom.version}</webAppSourceDirectory>
          <contextPath>/</contextPath>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>zhi

    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.7</version>
    </dependency>

    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>2.0.1.Final</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.9.Final</version>
    </dependency>

  </dependencies>

</project>

所需要的model

Spitter.java用户类,并且定义了校验信息。

package XiyouLinux.data;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Spitter {

    @NotNull
    @Size(min = 5, max = 16, message = "{firstname.size}")
    private String firstname;

    @NotNull
    @Size(min = 5, max = 25, message = "{lastname.size}")
    private String lastname;

    @NotNull
    @Size(min = 2, max = 30, message = "{username.size}")
    private String username;

    @NotNull
    @Size(min = 2, max = 30, message = "{password.size}")
    private String password;

    public Spitter(){

    }

    public Spitter(String firstname,String lastname,String username,String password){
        this.firstname = firstname;
        this.lastname = lastname;
        this.username = username;
        this.password = password;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getFirstname() {
        return firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }
}

SpitterRepository.java

package XiyouLinux.data;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.utSpitterRepositoryil.ArrayList;

@Component("spitterRepository")
public class SpitterRepository {
    private ArrayList<Spitter> spitterRepository = new ArrayList<Spitter>();

    public SpitterRepository(){}

    public ArrayList<Spitter> getSpitterRepository() {
        return spitterRepository;
    }

    public void save(Spitter spitter){
        spitterRepository.add(spitter);
    }

    public Spitter findByUsername(String username){
        for(int i =0;i<spitterRepository.size();i++){
            if(spitterRepository.get(i).getUsername().equals(username))
                return spitterRepository.get(i);
        }
        return new Spitter();
    }
}

校验表单时遇到的一些小问题

  • 校验表单首先要在pom.xml中添加如下依赖
<dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>2.0.1.Final</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.9.Final</version>
    </dependency>
  • 然后在Spring配置文件中定义如下两个Bean
@Bean
    public LocalValidatorFactoryBean localValidatorFactoryBean()
    {
        LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
        localValidatorFactoryBean.setValidationMessageSource(ResourceBundleMessageSource());
        return localValidatorFactoryBean;
    }

    @Bean
    public ResourceBundleMessageSource ResourceBundleMessageSource()
    {
        ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
        resourceBundleMessageSource.setBasename("ValidationMessages");
        resourceBundleMessageSource.setCacheSeconds(60);
        resourceBundleMessageSource.setDefaultEncoding("UTF-8");
        return resourceBundleMessageSource;
    }
  • 接着在用户类中定义要校验的字段,如:
@NotNull
    @Size(min = 5, max = 16, message = "{firstname.size}")
    private String firstname;

@NotNull表示非空,@Size表示长度要在5~16间,如果验证不通过就将错误信息收集到Error中。

  • 可以在ValidationMessages.properties定义了校验失败相应的错误信息,配置中文件名要与上面定义ResourceBundleMessageSource()中文件名称相对应。
firstname.size=First name must be between {min} and {max} characters long.
lastname.size=Last name must be between {min} and {max} characters long.
username.size=Username must be between {min} and {max} characters long.
password.size=Password must be between {min} and {max} characters long.
email.valid=The email address must be valid.
  • 控制器处理时,要加上@Vaild注解,检测是否有错误产生,采取不同的操作。
@RequestMapping(value = "/register", method = RequestMethod.POST)
    public String processRegistration(@ModelAttribute("command") @Valid Spitter spitter, Errors errors) {
        if(errors.hasErrors()){
            return "registerForm";
        }
        // 保存Spitter
        spitterRepository.save(spitter);
        // 重定向到新的页面
        return "redirect:/" + spitter.getUsername();
    }

运行测试:

表单界面

校验失败返回错误信息

校验成功返回注册用户的信息

参考:
《Spring实战(第4版)》


原文链接:https://blog.csdn.net/ldx19980108/article/details/80315700