数据校验:
重要数据提交之前,只做前端校验是不安全的;
(页面很有可能禁用掉js) |
---|
(绕过页面,提交表单,也发送相同的请求) |
重要数据一定要加上后端校验
1.把请求中员工的每一个属性给取出来,太累了 |
---|
按照规则校验 |
校验失败了,直接让它在再来到添加页面,提示重新填写。 |
SpringMvc 可以JSR303
2.javabean封装值的时候 |
---|
有个注解帮你校验 |
校验失败就不封装 |
@Email
private String email;
JSR303 :规范:- - - -用 Hibernate Validator (校验框架)
如何快速的进行后端校验:
- 导入Hibernate Validator 的jar包
2.只导入classmate,jboss,validation
Tomcat中有这些el jar包 免得跟项目jar包冲突。
3.只需要给javaBean的属性添加上校验注解
@NotEmpty
@Length(min=6,max=18)
private String lastName;
@Email
private String email;
@DateTimeFormat(pattern="yyyy-MM-dd")
@Past
private Date birth;
4.在SpringMVC封装自定义类型对象的时候(Employee对象)
告诉SpringMVC这个javabean需要校验 (@Valid)
@RequestMapping(value="/emp",method=RequestMethod.POST)
public String addEmp(@Valid Employee employee){
System.out.println(employee);
employeeDao.save(employee);
返回列表页面;可以直接重定向到查询所有员工的请求
return"redirect:/emps";
}
5.如何知道校验结果
给需要校验的自定义类型对象/javabean后面,紧跟着BindingResult,
BindingResult封装bean的校验结果
BindingResult封装bean的校验结果
BindingResult封装bean的校验结果
@RequestMapping(value="/emp",method=RequestMethod.POST)
public String addEmp(@Valid Employee employee,BindingResult result){
System.out.println(employee);
boolean hasError= result.hasErrors()
employeeDao.save(employee);
return"redirect:/emps";
}
6.根据不同的校验结果,怎么办?
@RequestMapping(value="/emp",method=RequestMethod.POST)
public String addEmp(@Valid Employee employee,BindingResult result){
System.out.println(employee);
boolean hasErrors = result.hasErrors();
if(hasErrors){
System.out.println("有检验错误");
return "add";
}else{
employeeDao.save(employee);
return"redirect:/emps";
}
7.来到页面的时候,用form:error取出错误信息
lastName:<form:input path="lastName"/><form:errors path="lastName"/><br/>
email:<form:input path="email"/><form:errors path="email"/><br/>
添加页面的数据会回显的原因:
Employee对象确定值的时候,先从隐含模型去拿。(看ModelAttribute就知道了)
隐含模型所有东西又放在请求域中。又到了页面。hhh
直接把查部门操作放在ModelAttributr方法里面
先查出所有部门
Collection<Department> department=departmentDao.getDepartments();
所有部门的集合放在隐含模型中(model.addAttribute)放在请求域中
model.addAttribute("depts", department);
带来几个问题?
1.原生的表单怎么办?将错误放在请求域中就行了
BindingResult
FieldErrors
FieldError
DefaultMessage Field
boolean hasErrors = result.hasErrors();
if(hasErrors){
List<FieldError> errors=result.getFieldErrors();
for(FieldError fieldError:errors){
System.out.println("错误消息提示"+fieldError.getDefaultMessage());
System.out.println("错误的字段"+fieldError.getField());
System.out.println(fieldError);
System.out.println("-----------------");
}
System.out.println("有检验错误");
return "add";
@RequestMapping(value="/emp",method=RequestMethod.POST)
public String addEmp(@Valid Employee employee,BindingResult result,Model model){
1.在SpringMVC封装自定义类型对象的时候(Employee对象)告诉SpringMVC这个javabean需要校验 (@Valid)
2.后端检验
boolean hasErrors = result.hasErrors();
创建一个HashMap (名字:errorsMap)
Map<String,Object> errorsMap = new HashMap<String,Object>();
if(hasErrors){
List<FieldError> errors=result.getFieldErrors();
for(FieldError fieldError:errors){
System.out.println("错误消息提示"+fieldError.getDefaultMessage());
System.out.println("错误的字段"+fieldError.getField());
System.out.println(fieldError);
System.out.println("-----------------");
Field作为HashMap的key,DefaultMessage作为HashMap的value
errorsMap.put(fieldError.getField(), fieldError.getDefaultMessage());
}
再把这个HashMap放给隐含模型model中,
隐含模型再带给请求域,页面取值就可以${}
model.addAttribute("errorInfo", errorsMap);
System.out.println("有检验错误");
return "add";
}else{
//保存这个自定义类型对象
employeeDao.save(employee);
return"redirect:/emps";
}
lastName:<form:input path="lastName"/>
<form:errors path="lastName"/>-->${errorInfo.lastName }
<br/>
email:<form:input path="email"/>
<form:errors path="email"/>-->->${errorInfo.email }
<br/>
birth:<form:input path="birth"/>
<form:errors path="birth"/>-->->${errorInfo.birth }
<br/>
后面是类型转换的错误,Springmvc类型转换的时候,是一个内部错误。
只要是hibernate旗下的校验注解,人家做好了国际化的功能
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
2.国际化定制自己的错误信息提示
编写国际化文件
errors_zh_CN.properties
errors_en_US.properties
key有规定
key=lastName between 6 and 18
Field error in object ‘employee’ on field ‘birth’:
rejected value [uu];
发生当前错误的错误代码
codes[typeMismatch.employee.birth,typeMismatch.birth,typeMismatch.java.util.Date,typeMismatch];
arguments[org.springframework.context.support.DefaultMessageSourceResolvable
Field error in object ‘employee’ on field ‘email’:
rejected value [88];
发生当前错误的错误代码
codes [Email.employee.email,Email.email,Email.java.lang.String,Email];
arguments[org.springframework.context.support.DefaultMessageSourceResolvable: codes [employee.email,email]; arguments []; default message [email],[Ljavax.validation.constraints.Pattern$Flag;@37984c29,.*];
default message [不是一个合法的电子邮件地址]
每个字段发生错误以后(Field error),都会自己的错误代码(codes);
国际化文件中这些错误信息的key必须对应一个错误代码
codes [
Email.employee.email, 校验规则.隐含模型中的这个对象的属性
Email.email, 校验规则.属性名
Email.java.lang.String, 校验规则.属性类型
Email
];
1.如果是隐含模型中employee对象的email属性发生了@Email校验错误,就会生成Email.employee.email;
2.所有的email属性只要发生了@Email校验错误,就会生成Email.email;
3.只要是String类型的属性只要发生了@Email校验错误,就会生Email.java.lang.String
4.只要发生了@Email校验错误,就会生Email;
1.编写国际化文件
Email.email=email incorrect~~
NotEmpty=must not empty~~
Length.java.lang.String= length incorrect~~
Past=must a past time~~
typeMismatch.birth=birth typeMismatch
2.让SpringMVC管理国际化资源文件
这个组件一定要叫做messageSource
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
指定你要管的国际化文件名(basename)
<property name="basename" value="errors"></property>
</bean>
3.来到页面取值 form:errors
4.高级国际化 动态取出错误消息
{0} {1} {2}
5.或者再校验注解后面直接加上 Message提示