上篇文章已经看到第六集了,第七集开始
SpringMVC模型数据解析
- session
@RequestMapping("/session")
public String session(HttpServletRequest request){
HttpSession session = request.getSession();
User user = new User();
user.setId(1);
user.setName("Adger");
session.setAttribute("user",user);
return "view";
}
jsp视图更改
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
request:${
requestScope.user}
session:${
sessionScope.user}
</body>
</html>
浏览器访问测试:http://localhost:8080/view/session
只存进session里面,但是request为什么也有值,是因为一个注解@ModelAttribute注释掉,就可以了
直接创建好的session
@RequestMapping("/session2")
public String session2(HttpSession httpSession){
User user = new User();
user.setId(1);
user.setName("Adger");
httpSession.setAttribute("user",user);
return "view";
}
直接访问测试:http://localhost:8080/view/session2
@SessionAttributes
这个注解不是给方法添加而是给类添加的,这个注解添加之后每个注解都生效,在类定义上只要加上@SessionAttributes(value = “user”)就都会有
测试map方法:http://localhost:8080/view/map
发现成功
上面是根据名字来添加的,下面是根据类型来添加的
@SessionAttributes(types = User.class)
上述两种方式是针对全局的,访问测试发现有数据:http://localhost:8080/view/map
添加多个的形式@SessionAttributes(value = {“user”,“address”})或者@SessionAttributes(types = {User.class, Address.class})
application
将模型数据绑定到application对象中,这个范围大小,使用起来没什么意义
SpringMVC自定义数据转换器
数据转换器是指:将客户端的HTTP请求中的参数直接转换为业务方法中定义的形参,自定义表示开发者可以自主设计转换的方式,HandlerAdapter已经提供了通用的转换,String转int,String转double,表单数据的封装,在特殊的业务场景下HandlerAdapter无法进行转换,就需要开发者自定义转换器
客户端输入String类型的数据"2020-03-03,自定义数据转换器,该数据转为Date类型的对象"
- 创建DataConverter接口,名字可以自定义,实现Convertr接口
package club.adger.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/27/10:58
* 注意 不要 倒错包
* 实现这个接口的方法
* 这个接口 是有一个泛型的 只需要定义需要转的类型 就比如 String 转 Data类型 只需要 按下面 定义非常方便 扩展性很好
*/
public class DateConverter implements Converter<String, Date> {
//按照怎样的格式去转换
private String pattern;
public DateConverter(String pattern) {
this.pattern = pattern;
}
@Override
public Date convert(String s) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(this.pattern);
Date date = null;
//有异常
try {
date = simpleDateFormat.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
有了自定义的转换器之后,需要在自己的springmvc.xml配置转换器
<!-- 配置自定义转换器 id自定义 但是下面使用的id必须一样-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<!-- 自己的转换器传进来 -->
<bean class="club.adger.converter.DateConverter">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd"></constructor-arg>
</bean>
</list>
</property>
</bean>
<!-- 上面步骤完了之后 还需要注册 -->
<mvc:annotation-driven conversion-service="conversionService">
<!-- 消息转换器 -->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8"></property>
</bean>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"></bean>
</mvc:message-converters>
</mvc:annotation-driven>
新建一个jsp页面。方便测试
![](/qrcode.jpg)
<%--
Created by IntelliJ IDEA.
User: Adger
Date: 2020/8/27
Time: 11:40
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/converter/date" method="post">
<%-- name属性跟 方法中的参数对应 服务器端的控制器 --%>
请输入日期: <input type="text" name="date">(年-月-日)<br>
<input type="submit" value="提交">
</form>
</body>
</html>
新建一个Handler或者controller
package club.adger.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/27/11:40
*/
@RestController
@RequestMapping("/converter")
public class ConverterHandler {
@RequestMapping("/date")
public String date(Date date){
//返回到客户端
return date.toString();
}
}
运行测试访问浏览器:http://localhost:8080/addDate.jsp
发现成功
Spring MVC RESTful架构
RESTful风格开发的项目结构清晰,RESTful风格在前后端分离的项目我觉得还是蛮多的,是目前比较主流的互联网软件架构,REST是资源表现层状态转换
REST简写解释
-
R Resources(资源)
存在的一个具体信息,列如,一段文本,一张图片 -
E Representation(表现层)
资源具体呈现出来的形式,比如文本可以用txt文本表示,也可以用HTML,JSON或者XML形式表示 -
ST State Transfer (状态转换)
客户端如果希望操作服务器的某个资源,就会让服务端发生状态转换,而这种转换是建立在表现层之上的
如何使用
REST具体操作就是HTTP协议中四个表示操作的方式的动词分别对应CRUD基本操作
- GET 用来表示获取资源
- POST 用来表示新建资源
- PUT 用来表示修改资源
- DELETE 用来表示删除资源
值得注意的是,get请求自己浏览器能测一测,其他的请求方式得借助于第三方工具了,如PostMan
新建一个RESTHandler,作增删改查操作,额视频上面叫的respository,也有人叫dao或者mapper的,我这里就叫mapper吧
新建一个Student实体类
package club.adger.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/27/15:49
* @AllArgsConstructor 这个表示添加 有参构造函数
* @NoArgsConstructor 这个表示添加的 无参构造函数
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private long id;
private String name;
private int age;
}
新建一个StudentMapper,由于视频没有用到持久层的框架,也没有真正用到数据库,所以用了map集合模拟下,怎么看lombok呢,直接点击idea的Structure,就可以看到你的实体类有哪些东西了
StudentMapper持久层Java文件,这是一个接口
package club.adger.mapper;
import club.adger.entity.Student;
import java.util.Collection;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/27/15:46
* 请注意这是一个接口
*/
public interface StudentMapper {
/**
* 这是查找所有学生的方法
* @return
*/
public Collection<Student> findAll();
/**
* 这是查找 单个学生的方法
* @param id
* @return
*/
public Student findById(long id);
/**
* 这是保存或者修改单个学生的方法
* @param student
*/
public void saveOrUpdate(Student student);
/**
* 这是删除某个学生的方法
* @param id
*/
public void deleteById(long id);
}
新建一个impl的包,建在mapper下面,里面的类全是实现mapper接口的
package club.adger.mapper.impl;
import club.adger.entity.Student;
import club.adger.mapper.StudentMapper;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/27/15:55
* @controller 控制器(注入服务)
*
* @service 服务(注入dao)
* 主要用来进行业务的逻辑处理
*
* @repository(实现dao访问)
* 即DAO组件
*/
@Repository
public class StudentMapperImpl implements StudentMapper {
private static Map<Long,Student> studentMap;
static {
studentMap = new HashMap<>();
studentMap.put(1L,new Student(1L,"Adger",20));
studentMap.put(2L,new Student(2L,"刘杰",21));
studentMap.put(3L,new Student(3L,"Adger",22));
}
@Override
public Collection<Student> findAll() {
return studentMap.values();
}
@Override
public Student findById(long id) {
return studentMap.get(id);
}
@Override
public void saveOrUpdate(Student student) {
studentMap.put(student.getId(),student);
}
@Override
public void deleteById(long id) {
studentMap.remove(id);
}
}
控制器方法
package club.adger.controller;
import club.adger.entity.Student;
import club.adger.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/27/15:42
*/
@RestController
@RequestMapping("/rest")
public class RESTHandler {
@Autowired
private StudentMapper studentMapper;
/**
* 查找是发送get请求
* @RequestMapping(value = "/findAll",method = RequestMethod.GET) 是等于 @GEtMapping的,就相当于简写形式吧
* 由于中文放在了对象里面,会出现中文乱码
* @return
*/
@GetMapping("/findAll")
public Collection<Student> findAll(HttpServletResponse response){
response.setContentType("text/json;charset=UTF-8");
return studentMapper.findAll();
}
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") long id){
return studentMapper.findById(id);
}
@PostMapping("/save")
public void save(@RequestBody Student student) {
studentMapper.saveOrUpdate(student);
}
@PutMapping("/update")
public void update(@RequestBody Student student){
studentMapper.saveOrUpdate(student);
}
@DeleteMapping("/deleteById/{id}")
public void deleteById(@PathVariable("id") long id){
studentMapper.deleteById(id);
}
}
访问测试:http://localhost:8080/rest/findAll
由于是@RestController所以是json格式形式返回,你们可能不一样,我这里用了json-view插件
http://localhost:8080/rest/findById/1
get的请求还好测试,但是删除跟跟修改呢对吧还有post用一下postman
在postMan测试保存:http://localhost:8080/rest/save
浏览器测试访问:http://localhost:8080/rest/findAll
测试put请求:http://localhost:8080/rest/update
发现成功
测试Delete请求:http://localhost:8080/rest/deleteById/1
发现成功
Spring MVC 文件上传 下载
上传跟下载这个功能用的还是比较多的,底层是通过IO流上传下载的
单文件上传
底层使用Apache fileupload组件完成上传,SpringMVC对这种方式进行了封装,只需要在pom.xml加入依赖,就相当于先引入文件上传的jar包
<!-- 这里更改下servlet-api 版本不一样有些方法没有-->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
SpringMVC.xml配置,里面还可以配置文件上传的大小等
<!-- 配置文件上传下载的组件 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
JSP页面
<%--
Created by IntelliJ IDEA.
User: Adger
Date: 2020/8/28
Time: 10:41
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
这个method一定是post而不是文件本身 get有大小限制
一定需要这个不然只能上传文件名字
enctype="multipart/form-data
--%>
<form action="/file/upload" method="post" enctype="multipart/form-data">
<input type="file" name="img">
<input type="submit" value="上传">
</form>
</body>
</html>
后台方法
package club.adger.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/28/10:44
*/
@Controller
@RequestMapping("/file")
public class FileHandler {
/**
* MultipartFile img 接受 客户端 传进来的参数 就是文件
* @param img
* @return
*/
@PostMapping("/upload")
public String upload(MultipartFile img, HttpServletRequest request){
if(img.getSize() > 0){
//获取保存文件的路径
String path = request.getServletContext().getRealPath("file");
//获取上传的文件名
String name = img.getOriginalFilename();
File file = new File(path, name);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
System.out.println("创建目录" + file);
}
try {
img.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(img);
return "upload";
}
}
浏览器访问测试:http://localhost:8080/upload.jsp
发现成功
上传后的文件显示
服务器端方法更改
package club.adger.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/28/10:44
*/
@Controller
@RequestMapping("/file")
public class FileHandler {
/**
* MultipartFile img 接受 客户端 传进来的参数 就是文件
* @param img
* @return
*/
@PostMapping("/upload")
public String upload(MultipartFile img, HttpServletRequest request){
if(img.getSize() > 0){
//获取保存文件的路径
String path = request.getServletContext().getRealPath("file");
//获取上传的文件名
String name = img.getOriginalFilename();
File file = new File(path, name);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
System.out.println("创建目录" + file);
}
try {
img.transferTo(file);
//保存上传之后的文件路径
request.setAttribute("path",name);
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(img);
return "upload";
}
}
jsp页面更改
<%--
Created by IntelliJ IDEA.
User: Adger
Date: 2020/8/28
Time: 10:41
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
这个method一定是post而不是文件本身 get有大小限制
一定需要这个不然只能上传文件名字
enctype="multipart/form-data
--%>
<form action="/file/upload" method="post" enctype="multipart/form-data">
<input type="file" name="img">
<input type="submit" value="上传">
</form>
<img src="${path}">
</body>
</html>
由于文件也是资源,所以会被SpringMVC拦截,所以web.xml中也要放行
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
浏览器测试访问:http://localhost:8080/upload.jsp
发现成功
多文件上传
服务器端增加方法
@PostMapping("/uploads")
public String uploads(MultipartFile[] imgs,HttpServletRequest request){
List<String> files = new ArrayList<>();
for (MultipartFile img : imgs){
if(img.getSize() > 0){
//获取保存文件的路径
String path = request.getServletContext().getRealPath("file");
//获取上传的文件名
String name = img.getOriginalFilename();
File file = new File(path, name);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
System.out.println("创建目录" + file);
}
try {
img.transferTo(file);
files.add(name);
} catch (IOException e) {
e.printStackTrace();
}
}
}
request.setAttribute("files",files);
return "uploads";
}
pom.xml引入el表达式,因为是多文件,用遍历的形式,到时候回显上去
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
新建uploads.jsp页面
<%--
Created by IntelliJ IDEA.
User: Adger
Date: 2020/8/28
Time: 11:35
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
<%-- 控制图片的大小 --%>
<style>
img{
width: 300px;
height: 300px;
}
</style>
</head>
<body>
<form action="/file/uploads" method="post" enctype="multipart/form-data">
file1:<input type="file" name="imgs"><br>
file2:<input type="file" name="imgs"><br>
file3:<input type="file" name="imgs"><br>
<input type="submit" value="上传">
</form>
<c:forEach items="${files}" var="file">
<img src="${file}">
</c:forEach>
</body>
</html>
浏览器访问测试:http://localhost:8080/uploads.jsp
发现成功
注意的是你服务器关闭文件就没了,多文件上传就是传了一个数组的形式过去
文件的下载
上传的话就是把客户端的资源上传到服务器端,下载的话就是一个反向过程,但是你的服务器端必须有这个资源才能下载
新建一个download.jsp页面,这里是Get请求,因为是超链接
<%--
Created by IntelliJ IDEA.
User: Adger
Date: 2020/8/28
Time: 11:52
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="/file/download/14">14.gif</a>
<a href="/file/download/15">15.gif</a>
<a href="/file/download/16">16.gif</a>
</body>
</html>
新建后端方法
/**
* rest风格 加映射 @PathVariable
* @param name
* @param request
* @param response
*/
@GetMapping("/download/{name}")
public void download(@PathVariable("name") String name, HttpServletRequest request, HttpServletResponse response){
if(name != null){
name += ".gif";
String path = request.getServletContext().getRealPath("file");
File file = new File(path, name);
OutputStream outputStream = null;
if(file.exists()){
// 响应的设置
response.setContentType("application/forc-download");
response.setHeader("Content-Disposition","attachment;filename="+name);
try {
outputStream = response.getOutputStream();
outputStream.write(FileUtils.readFileToByteArray(file));
} catch (IOException e) {
e.printStackTrace();
}finally {
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
我先把文件传上去,去download页面测试:http://localhost:8080/download.jsp
就下载成功了
SpringMVC表单 标签库
新建后端方法跟文件
package club.adger.controller;
import club.adger.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/28/12:19
*/
@Controller
@RequestMapping("/tag")
public class TagController {
@GetMapping("/get")
public ModelAndView get(){
ModelAndView modelAndView = new ModelAndView("show");
Student student = new Student(1L, "Adger", 22);
modelAndView.addObject("student", student);
return modelAndView;
}
}
新建show.jsp页面
<%--
Created by IntelliJ IDEA.
User: Adger
Date: 2020/8/28
Time: 12:25
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>学生信息</h1>
学生ID: <input type="text" name="id" value="${student.id}">
学生姓名:<input type="text" name="name" value="${student.name}">
学生年龄:<input type="text" name="age" value="${student.age}">
</body>
</html>
浏览器测试访问:http://localhost:8080/tag/get
上面不是用了表单标签库,下面的代码是用了表单标签库,后端方法改下视图就可以了
package club.adger.controller;
import club.adger.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/28/12:19
*/
@Controller
@RequestMapping("/tag")
public class TagController {
@GetMapping("/get")
public ModelAndView get(){
ModelAndView modelAndView = new ModelAndView("tag");
Student student = new Student(1L, "Adger", 22);
modelAndView.addObject("student", student);
return modelAndView;
}
}
新建tag.jsp页面
<%--
Created by IntelliJ IDEA.
User: Adger
Date: 2020/8/28
Time: 12:30
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>学生信息表单标签库</h1>
<%-- modelAttribute是后端的key值 注意闭合标签--%>
<form:form modelAttribute="student">
学生ID: <form:input path="id"/>
学生姓名:<form:input path="name"/>
学生年龄:<form:input path="age"/>
</form:form>
</body>
</html>
浏览器测试访问:http://localhost:8080/tag/get
发现成功,发现变的只是视图界面的代码
jsp页面需要导入表单标签库,前缀名字按照自己喜好
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
后端方法中与模型数据绑定
modelAndView.addObject("student", student);
最后通过path属性绑定,对应实体类的属性
path="id"
常用的表单标签
- modelAttribute
modelAttribute属性绑定模型数据
<form:form modelAttribute="student"></form:form>
- input
渲染的是input标签,这两个是结合起来使用的,支持级联操作
<form:input path="id"/>
- password
与上面用法一样,值不会再页面显示,有值不显示
还有很多就没写了。感觉不怎么常使用
SpringMVC数据校验
SpringMVC提供了两种数据校验的方式:1.基于Validator接口、2.使用Annotation-JSR-303标准进行校验
基于Validator接口的方式需要自定义Validator验证器,每一条的数据验证需要开发者手动完成,使用JSR-303则不需要,通过注解的方式可以在实体类中添加每个属性的验证规则
基于Validator 接口
实体类Account
package club.adger.entity;
import lombok.Data;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/28/13:27
*/
@Data
public class Account {
private String name;
private String password;
}
- 自定义验证器AccountValidator接口,实现Validator接口
新建一个validator包
package club.adger.validator;
import club.adger.entity.Account;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/28/13:30
* 如果 supports 是 true validate 方法是执行的,如果不是就不执行
*/
public class AccountValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return Account.class.equals(clazz);
}
/**
* 第一个参数为实体类的属性哪个属性需要验证
* 第二个参数为 验证状态
* 第三个参数为 错误信息
* @param target
* @param errors
*/
@Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmpty(errors,"name",null,"姓名不能为空");
ValidationUtils.rejectIfEmpty(errors,"password",null,"密码不能为空");
}
}
新建ValidatorHandler
package club.adger.controller;
import club.adger.entity.Account;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/28/13:34
*/
@Controller
@RequestMapping("/validator")
public class ValidatorHandler {
/**
* 这个方法只是为了绑定模型
* @param model
* @return
*/
@GetMapping("/login")
public String login(Model model){
model.addAttribute("account",new Account());
return "login";
}
/**
* @Validated 注解 代表验证器 验证
* @param account
* @param result
* @return
*/
@PostMapping("/login")
public String login(@Validated Account account, BindingResult result){
//是否有错
if (result.hasErrors()){
return "login";
}
return "index";
}
}
新建login.jsp页面
<%--
Created by IntelliJ IDEA.
User: Adger
Date: 2020/8/28
Time: 13:36
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form:form modelAttribute="account" action="/validator/login" method="post">
姓名:<form:input path="name"></form:input><br><form:errors path="name"></form:errors>
密码:<form:input path="password"></form:input><form:errors path="password"></form:errors>
<input type="submit" value="登录">
</form:form>
</body>
</html>
最重要的一步:springmvc.xml还需要配置
<!-- 基于Validtor验证器 配置 -->
<bean id="accountValidator" class="club.adger.validator.AccountValidator"></bean>
<mvc:annotation-driven validator="accountValidator"></mvc:annotation-driven>
浏览器访问测试:http://localhost:8080/validator/login
首先get请求,访问页面,也携带模型数据为空
发送post请求,校验成功
JSR-303
使用JSR-303标准进行验证,需要导入依赖的jar文件,这里使用的是Hibernate的Validator
pom.xml
<!-- JSR-303 -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.4.1.Final</version>
</dependency>
通过注解的方式直接在实体类中添加相关的验证规则,person实体类
package club.adger.entity;
import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/28/14:12
*/
@Data
public class Person {
/**
* 不为空判断
*/
@NotEmpty(message = "用户名不能为空")
private String name;
@Size(min = 6,max = 12,message = "密码为6-12位")
private String password;
/**
* 下面两个为正则表达式的
*/
@Email(regexp = "^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\\\.[a-zA-Z0-9-]+)*\\\\.[a-zA-Z0-9]{2,6}$",message = "请输入正确的邮箱格式")
private String email;
@Pattern(regexp = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\\\\\\\d{8}$",message = "请输入正确的电话")
private String phone;
}
ValidatorHandler方法\
/**
* 就是模仿数据库
* @param model
* @return
*/
@GetMapping("/register2")
public String register(Model model){
model.addAttribute("person",new Person());
return "register2";
}
@PostMapping("/register2")
public String register(@Valid Person account, BindingResult result){
//是否有错
if (result.hasErrors()){
return "register2";
}
return "index";
}
springmvc.xml配置。因为是基于注解的所有要让注解生效,这个必须单独配置一个,不管上面有没有
<mvc:annotation-driven></mvc:annotation-driven>
浏览器测试访问:http://localhost:8080/validator/register2
提交之后呢,发现成功
校验规则详解:
@Null 被注解的元素必须为null
@Min(value) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值
@Email 被注解的元素必须是电子邮箱地址
@Pattern 被注解的元素必须符合对应的正则表达式
@Length 被注解的元素的大小必须在指定的范围内
@NotEmpty 被注解的字符串的值必须非空
Null 和 Empty 是不同的结果,String str = null,str 是 null,String str = “”,str 不是 null,其值为空。
@Max(value) 被注解的元素必须是一个数字,其值必须小于于等于指定的最大值