- 实用技术-校验框架
- SSM整合-视频
- 纯注解开发SSM
1 校验框架
1.1 入门
1.1.1 表单校验的重要性
表单校验保障了数据有效性、安全性
数据可以随意输入,导致错误的结果。
1.1.2 表单校验分类
- 按校验位置分类:
- 客户端校验:浏览器,手机APP
- 服务端校验:后端服务器代码校验
- 按校验内容分类:
- 格式校验:比如年龄是否为负数,邮箱是否符合规则
- 逻辑校验:比如用户名在当前项目中是否已注册(需要查询数据库或者业务校验)
1.1.3 格式校验规则
以下几种全部属于格式校验:
- 长度:例如用户名长度,评论字符数量
- 非法字符:例如用户名组成
- 数据格式:例如Email格式、 IP地址格式
- 边界值:例如转账金额上限,年龄上下限
1.1.4 表单校验框架
-
JSR(Java Specification Requests):Java 规范提案
303:提供bean属性相关校验规则
-
JCP(Java Community Process):提出JSR规范议案
- 一个开放性的国际技术标准组织,职责是发展和更新Java技术规范。
- 成员:Oracle、ARM、IBM、Intel、SAP、Twitter、阿里巴巴、亚马逊等
-
JSR规范列表
- 企业应用技术
Contexts and Dependency Injection for Java (Web Beans 1.0) (JSR 299)
Dependency Injection for Java 1.0 (JSR 330)@postConstruct, @PreDestroy
Bean Validation 1.0 (JSR 303)
Enterprise JavaBeans 3.1 (includes Interceptors 1.1) (JSR 318)
Java EE Connector Architecture 1.6 (JSR 322)
Java Persistence 2.0 (JSR 317)
Common Annotations for the Java Platform 1.1 (JSR 250)
Java Message Service API 1.1 (JSR 914)
Java Transaction API (JTA) 1.1 (JSR 907)
JavaMail 1.4 (JSR 919) - Web应用技术
Java Servlet 3.0 (JSR 315)
JavaServer Faces 2.0 (JSR 314)
JavaServer Pages 2.2/Expression Language 2.2 (JSR 245)
Standard Tag Library for JavaServer Pages (JSTL) 1.2 (JSR 52)
Debugging Support for Other Languages 1.0 (JSR 45)
模块化 (JSR 294)
Swing应用框架 (JSR 296)
JavaBeans Activation Framework (JAF) 1.1 (JSR 925)
Streaming API for XML (StAX) 1.0 (JSR 173) - 管理与安全技术
Java Authentication Service Provider Interface for Containers (JSR 196)
Java Authorization Contract for Containers 1.3 (JSR 115)
Java EE Application Deployment 1.2 (JSR 88)
J2EE Management 1.1 (JSR 77)
Java SE中与Java EE有关的规范
JCache API (JSR 107)
Java Memory Model (JSR 133)
Concurrency Utilitie (JSR 166)
Java API for XML Processing (JAXP) 1.3 (JSR 206)
Java Database Connectivity 4.0 (JSR 221)
Java Management Extensions (JMX) 2.0 (JSR 255)
Java Portlet API (JSR 286)
- 企业应用技术
-
Web Service技术
Java Date与Time API (JSR 310)
Java API for RESTful Web Services (JAX-RS) 1.1 (JSR 311)
Implementing Enterprise Web Services 1.3 (JSR 109)
Java API for XML-Based Web Services (JAX-WS) 2.2 (JSR 224)
Java Architecture for XML Binding (JAXB) 2.2 (JSR 222)
Web Services Metadata for the Java Platform (JSR 181)
Java API for XML-Based RPC (JAX-RPC) 1.1 (JSR 101)
Java APIs for XML Messaging 1.3 (JSR 67)
Java API for XML Registries (JAXR) 1.0 (JSR 93) -
JSR303实现:校验框架hibernate-validator
1.2 快速使用
导入hibernate-validator校验框架的坐标
<!--导入校验的jsr303规范:接口-->
<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.1.0.Final</version>
</dependency>
注意:
tomcat7 :搭配hibernate-validator版本5...Final
tomcat8.5↑ :搭配hibernate-validator版本6...Final ,必须使用外置tomcat
1. 开启校验
名称:@Valid 、 @Validated
类型:形参注解
位置:处理器类中的实体类类型的方法形参前方
作用:设定对当前实体类类型参数进行校验
范例:
@RequestMapping(value = "/addemployee")
public String addEmployee(@Valid Employee employee) {
System.out.println(employee);
return "success";
}
2.设置校验规则
名称:@NotNull, @NotBlank, @NotEmpty
类型:属性注解
位置:属性上方
作用:设定当前属性校验规则
范例:每个校验规则所携带的参数不同,根据校验规则进行相应的调整
public class Employee{
@NotBlank(message = "姓名不能为空")
private String name;//员工姓名
//添加getter,setter方法
}
易错点:必须给name,age等属性编写getter,setter方法
3.获取错误信息
通过形参Errors获取校验结果数据,通过Model接口将数据封装后传递到页面显示
@RequestMapping(value = "/addemployee")
public String addEmployee(@Valid Employee employee, Errors errors, Model model){
System.out.println(employee);
if(errors.hasErrors()){
for(FieldError error : errors.getFieldErrors()){
model.addAttribute(error.getField(),error.getDefaultMessage());
}
return "addemployee.jsp";
}
return "success.jsp";
}
在JSP页面中获取后台封装的校验结果信息
<form action="/addemployee" method="post">
员工姓名:<input type="text" name="name"><span style="color:red">${name}</span><br/>
员工年龄:<input type="text" name="age"><span style="color:red">${age}</span><br/>
<input type="submit" value="提交">
</form>
使用校验步骤小结
- 方法参数上开启校验:@Valid 、 @Validated
- Bean的属性上设置校验规则:@NotBlank(message = “姓名不能为空”)
- 通过参数Errors获取错误信息
- 获取所有错误:errors.getFieldErrors()
- 获取错误字段:error.getField()
- 获取错误提示:error.getDefaultMessage()
- 将错误信息放置到model中显示给用户 -> JSP页面中${name}
1.3 多规则校验
同一个字段有多个约束条件,比如对于年龄的校验:
if (age !=null && age >18 && age < 60)
@NotNull(message = "请输入您的年龄")
@Max(value = 60,message = "年龄最大值不允许超过60岁")
@Min(value = 18,message = "年龄最小值不允许低于18岁")
private Integer age;//员工年龄
1.4 嵌套校验
引用类型字段如何校验,比如Employee中有address属性记录地址
名称:@Valid
类型:属性注解
位置:实体类中的引用类型属性上方
作用:设定当前应用类型属性中的属性开启校验
1.在address属性上添加@Valid注解,开启嵌套属性校验
public class Employee {
//实体类中的引用类型通过标注@Valid注解,设定开启当前引用类型字段中的属性参与校验
@Valid
private Address address;
//添加address属性的get,set方法
}
2.开启嵌套校验后,被校验对象内部需要添加对应的校验规则,并添加嵌套属性的get,set方法
//嵌套校验的实体中,对每个属性正常添加校验规则即可
public class Address {
@NotBlank(message = "请输入省份名称")
private String provinceName;//省份名称
@NotBlank(message = "请输入城市名称")
private String cityName;//城市名称
@NotBlank(message = "请输入详细地址")
private String detail;//详细住址
@NotBlank(message = "请输入邮政编码")
@Size(max = 6, min = 6, message = "邮政编码由6位组成")
private String zipCode;//邮政编码
//添加get,set方法
}
@PostMapping(value = "/addemployee")
public String addEmployee(@Valid Employee employee, Errors errors, Model m) {
//Errors对象用于封装校验结果,如果不满足校验规则,对应的校验结果封装到该对象中,包含校验的属性名和校验不通过返回的消息
//判定Errors对象中是否存在未通过校验的字段
if (errors.hasErrors()) {
//获取所有未通过校验规则的信息
List<FieldError> fieldErrors = errors.getFieldErrors();
for (FieldError error : fieldErrors) {
//将校验结果信息添加到Model对象中,用于页面显示,后期实际开发中无需这样设定,返回json数据即可
//name = 姓名不能为空 -> ${name}
m.addAttribute(error.getField(), error.getDefaultMessage());
//address.cityName = 请输入城市名称 -> ${requestScope['address.provinceName']}
//m.addAttribute("address.provinceName", "请输入省份名称");
}
//el获取对象属性值
Address address = new Address();
address.setProvinceName("test省份不能为空");
//${address.provinceName}
m.addAttribute("address", address);
//当出现未通过校验的字段时,跳转页面到原始页面,进行数据回显
return "addemployee.jsp";
}
return "success.jsp";
}
3.在jsp页面中获取嵌套属性中的错误信息
${requestScope['address.cityName']}
<%--注意,引用类型的校验未通过信息不是通过对象进行封装的,直接使用对象名.属性名的格式作为整体属性字符串进行保存的,和使用者的属性传递方式有关,不具有通用性,仅适用于本案例--%>
省:<input type="text" name="address.provinceName"><span style="color:red">${requestScope['address.provinceName']}</span><br/>
市:<input type="text" name="address.cityName"><span
style="color:red">${requestScope['address.cityName']}</span><br/>
3种判定空校验器的区别
String 选择@NotBlank,底层会调用"字符串".trim()清除前后空格
int, double 选择@NotNull,不能使用@NotBlank
数组选择@NotEmpty
1.5 分组校验
根据业务不同需要调整是否参与校验,比如同一个模块,新增和修改时校验规则是不一致的
- 新增用户:新增时用户名不能为空
- 修改用户:修改时不能修改用户名,所以不用强制用户名不能为空
解决方案:对不同种类的属性进行分组,在校验时可以指定参与校验的字段所属的组类别
-
根据业务类型使用接口定义分组为Save, Update
public interface Save { }
public interface Update { }
-
在实体类Employee中为属性设置所属组,可以设置多个
姓名不能为空只在新增时校验
@NotEmpty(message = "姓名不能为空",groups = { Save.class}) private String name;//员工姓名
年龄校验新增和修改都需要校验
@NotEmpty(message = "年龄不能为空",groups = { Save.class, Update.class}) private Integer age;//员工年龄
-
在Controller的方法参数上开启分组校验,并指定使用哪一种分组:@Validated({Save.class})
//新增Employee @RequestMapping("/addemployee") public String addEmployee(@Validated({ Save.class}) Employee employee, Errors errors, Model m) { } //更新Employee @PostMapping(value = "/updateEmployee") public String updateEmployee(@Validated({ Update.class}) EmployeeGroup employee, Errors errors, Model m) { }
2 SSM整合
2.1 整合流程简介
整合步骤分析:SSM(Spring+SpringMVC+MyBatis)
2.2 项目结构搭建
**Part0:**项目基础结构搭建
-
创建项目,组织项目结构,创建包
-
创建表与实体类
-
创建三层架构对应的模块、接口与实体类,建立关联关系
- 数据层接口(代理自动创建实现类)
- 业务层接口+业务层实现类
- 表现层类
public interface UserDao {
/**
* 添加用户
* @param user
* @return
*/
public boolean save(User user);
/**
* 修改用户
* @param user
* @return
*/
public boolean update(User user);
/**
* 删除用户
* @param uuid
* @return
*/
public boolean delete(Integer uuid);
/**
* 查询单个用户信息
* @param uuid
* @return
*/
public User get(Integer uuid);
/**
* 查询全部用户信息
* @return
*/
public List<User> getAll();
/**
* 根据用户名密码查询个人信息
* @param userName 用户名
* @param password 密码信息
* @return
*/
//注意:数据层操作不要和业务层操作的名称混淆,通常数据层仅反映与数据库间的信息交换,不体现业务逻辑
public User getByUserNameAndPassword(String userName,String password);
}
public interface UserService {
/**
* 添加用户
* @param user
* @return
*/
public boolean save(User user);
/**
* 修改用户
* @param user
* @return
*/
public boolean update(User user);
/**
* 删除用户
* @param uuid
* @return
*/
public boolean delete(Integer uuid);
/**
* 查询单个用户信息
* @param uuid
* @return
*/
public User get