Spring MVC 学习总结(四)——校验与文件上传

本文深入探讨SpringMVC框架的高级应用,包括JSR303的Bean验证和Servlet3.0的文件上传功能。详细介绍了如何使用注解进行数据验证,以及如何配置和实现文件上传。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring MVC不仅是在架构上改变了项目,使代码变得可复用、可维护与可扩展,其实在功能上也加强了不少。 验证与文件上传是许多项目中不可缺少的一部分。在项目中验证非常重要,首先是安全性考虑,如防止注入攻击,XSS等;其次还可以确保数据的完整性,如输入的格式,内容,长度,大小等。Spring MVC可以使用验证器Validator与JSR303完成后台验证功能。

一、JSR303验证器

JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。https://jcp.org/en/home/index

JSR 303 – Bean Validation 是一个数据验证的规范。JSR303只是一个标准,是一验证规范,对这个标准的实现有:

hibernate-validatorApache BVal等。这里我们使用hibernate-validator实现校验。

1.1、添加hibernate-validator依赖

修改配置pom.xml配置文件,添加依赖。

<!--JSR303 Bean校验-->
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-validator</artifactId>
	<version>5.2.2.Final</version>
</dependency>

1.2、注解Bean

 在bean中设置验证规则,示例代码如下:

package cn.liuw.domain;

import java.io.Serializable;

import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Range;

/**
 * 产品
 */
public class Product implements Serializable {
	private static final long serialVersionUID = 1L;
	/*
	 * 编号
	 */
	private int id;
	/*
	 * 名称
	 */
	@Size(min = 1, max = 50, message = "名称长度必须介于{2}-{1}之间")
	@Pattern(regexp = "^[\\w\\u4e00-\\u9fa5]{0,10}$", message = "格式错误,必须是字母数字与中文")
	private String name;
	/*
	 * 价格
	 */
	@Range(min = 0, max = 1000000, message = "价格只允许在{2}-{1}之间")
	private double price;

	
	public Product() {
	}
	
	public Product(String name, double price) {
		super();
		this.name = name;
		this.price = price;
	}

	public Product(int id, String name, double price) {
		super();
		this.id = id;
		this.name = name;
		this.price = price;
	}

	@Override
	public String toString() {
		return "编号(id):" + this.getId() + ",名称(name):" + this.getName() + ",价格(price):" + this.getPrice();
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}
}

更多的验证注解如下所示:

1.2.1、空值检查

@Null       验证对象是否为null

@NotNull    验证对象是否不为null, 无法查检长度为0的字符串

@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.

@NotEmpty 检查约束元素是否为NULL或者是EMPTY.

1.2.2、Booelan检查

@AssertTrue     验证 Boolean 对象是否为 true 

@AssertFalse    验证 Boolean 对象是否为 false 

1.2.3、长度检查

@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内 

@Length(min=, max=) Validates that the annotated string is between min and max included.

1.2.4、日期检查

@Past         验证 Date 和 Calendar 对象是否在当前时间之前 

@Future     验证 Date 和 Calendar 对象是否在当前时间之后 

1.2.5、正则

@Pattern    验证 String 对象是否符合正则表达式的规则

1.2.6、数值检查

建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为String为"",Integer为null

@Min            验证 Number 和 String 对象是否大等于指定的值 

@Max            验证 Number 和 String 对象是否小等于指定的值 

@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度

@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度

@Digits     验证 Number 和 String 的构成是否合法 

@Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。

1.2.7、范围

@Range(min=, max=) 检查被注解对象的值是否处于min与max之间,闭区间,包含min与max值

@Range(min=10000,max=50000,message="必须介于{2}-{1}之间")

1.2.8、其它注解

@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证),该注解使用在Action的参数上。

@CreditCardNumber信用卡验证

@Email  验证是否是邮件地址,如果为null,不进行验证,算通过验证。

@ScriptAssert(lang= ,script=, alias=)

@URL(protocol=,host=, port=,regexp=, flags=)

1.3、注解控制器参数

在需要使用Bean验证的参数对象上注解@Valid,触发验证,示例代码如下:

package cn.liuw.controller;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.liuw.domain.Product;

@Controller
@RequestMapping("/goods")
public class GoodsController {
    
    // 新增,渲染出新增界面
    @RequestMapping("/add")
    public String add(Model model) {
        // 与form绑定的模型
        model.addAttribute("product", new Product());
        return "product/addGoods";
    }

    // 新增保存,如果新增成功转回列表页,如果失败回新增页,保持页面数据
    @RequestMapping("/addGoodsSave")
    public String addSave(Model model, @Valid Product product, BindingResult bindingResult) {

        // 是否存在错误,如果没有,执行添加
        if (!bindingResult.hasErrors()) {
            return "redirect:/";
        } else {
            // 与form绑定的模型
            model.addAttribute("product", product);
            return "product/addGoods";
        }
    }
}

1.4、在UI中添加错误标签

这里与Spring MVC Validator基本一致,在product目录下新增一个名为addGoods.jsp的页面,脚本如下所示:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <title>新增产品</title>
    </head>
    <body>
        <div class="main">
            <h2 class="title"><span>新增产品</span></h2>
            <form:form action="addGoodsSave" modelAttribute="product">
            <fieldset>
                <legend>产品</legend>
                <p>
                    <label for="name">产品名称:</label>
                    <form:input path="name" />
                    <form:errors path="name" cssClass="error" style="color:red;"></form:errors>
                </p>
                <p>
                    <label for="price">产品价格:</label>
                    <form:input path="price"/>
                    <form:errors path="price" cssClass="error" style="color:red;"></form:errors>
                </p>
                <p>
                    <input type="submit" value="保存" />
                </p>
            </fieldset>
            </form:form>
            <p style="color: red">${message}</p>
        </div>
    </body>
</html>

1.5、测试运行

小结:从上面的示例可以看出这种验证更加方便直观,一次定义反复使用,以编辑更新时验证同样可以使用;另外验证的具体信息可以存放在配置文件中,如message.properties,这样便于国际化与修改。

二、文件上传

Servlet3.0以上的版本不再需要第三方组件Commons.io和commons-fileupload,可以使用@MultipartConfig注解在Servlet上进行配置上传,也可以在web.xml上进行配置。

1、修改web.xml配置上传参数

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 3.0//EN"
 "http://java.sun.com/dtd/web-app_3_0.dtd" >
<web-app>
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <!--Servlet3.0以上文件上传配置 -->
        <multipart-config>
            <max-file-size>5242880</max-file-size><!--上传单个文件的最大限制5MB -->
            <max-request-size>20971520</max-request-size><!--请求的最大限制20MB,一次上传多个文件时一共的大小 -->
            <file-size-threshold>0</file-size-threshold><!--当文件的大小超过临界值时将写入磁盘 -->
        </multipart-config>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
  • file-size-threshold:数字类型,当文件大小超过指定的大小后将写入到硬盘上。默认是0,表示所有大小的文件上传后都会作为一个临时文件写入到硬盘上。

  • location:指定上传文件存放的目录。当我们指定了location后,我们在调用Part的write(String fileName)方法把文件写入到硬盘的时候可以,文件名称可以不用带路径,但是如果fileName带了绝对路径,那将以fileName所带路径为准把文件写入磁盘,不建议指定。

  • max-file-size:数值类型,表示单个文件的最大大小。默认为-1,表示不限制。当有单个文件的大小超过了max-file-size指定的值时将抛出IllegalStateException异常。

  • max-request-size:数值类型,表示一次上传文件的最大大小。默认为-1,表示不限制。当上传时所有文件的大小超过了max-request-size时也将抛出IllegalStateException异常。

2、修改pom.xml依赖信息

3、修改springmvc.xml配置信息

将原有的文件上传通用解析器更换为标准解析器,修改后的配置如下所示:

<!--文件上传解析器 -->
<bean id="multipartResolver"
	class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>

定义了一个标准的文件上传解析器,更多属性可以查看这个类的源码。这步非常关键,否则上传会失败。另外id不要换成别的名称,更换后可能会上传失败。

4、定义视图

在views/up/下定义名称为file.jsp文件,内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>上传文件 - Servlet3.0</title>
    </head>
    <body>
        <h2>上传文件 - Servlet3.0</h2>
        <form action="fileSave" method="post"  enctype="multipart/form-data">
            <p>
                <label for="files">文件:</label>
                <input type="file" name="files" id="files" multiple="multiple" />
            </p>
            <p>
                <button>提交</button>
            </p>
            <p>
                ${message}
            </p>
        </form>
    </body>
</html>

multiple="multiple"这个属性是HTML5新增加的属性,一些旧版的浏览器可能不支持,使用JavaScript可以处理一下。

5、定义Action

在UpFileController中定义两个action,一个叫file用于展示上传页面,一个叫fileSave用于处理上传文,代码如下:

package cn.liuw.controller;

import java.io.File;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

@Controller
@RequestMapping("/up")
public class UpFileController {

	@RequestMapping("/file")
	public String file(Model model) {
		return "up/file";
	}

	@RequestMapping(value = "/fileSave", method = RequestMethod.POST)
	public String file3Save(Model model, MultipartFile[] files, HttpServletRequest request) throws Exception {

		// 文件存放的位置
		String path = request.getSession().getServletContext().getRealPath("/files");
		System.out.println(path);
		String msg = "";
		for (MultipartFile file : files) {
			// 保存文件
			File tempFile = new File(path, file.getOriginalFilename());
			file.transferTo(tempFile);
			msg += "<img src='../files/" + file.getOriginalFilename() + "' width='200' />";
		}
		model.addAttribute("message", msg);
		return "up/file";
	}

}

6、测试运行

转自:https://www.cnblogs.com/best/p/5709680.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值