JSR303是Java为Bean数据合法性校验提供给的标准框架
,已经包含在 JavaEE6.0中、JSR303通过在Bean 属性中标注类似 @NotNull @Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean进行验证
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.7.Final</version>
</dependency>
2.1 给校验对象的指定属性添加校验规则
public class User {
private Long userId;
@NotBlank(message = "用户名不能为空")
private String userName;
@NotBlank(message = "密码不能为空")
private String password;
@NotBlank(message = "确认密码不能为空")
private String password2;
}
2.2 在请求处理方法中,使用@Validated或@Valid注解要验证的对象,并根据BindingResult判断校验是否通过
另外,验证参数后必须紧跟BindingResult参数,否则spring会在校验不通过时直接抛出异常
@RequestMapping("/toreg")//注册验证消息
public String toreg(@Validated User user,BindingResult bindingResult,HttpServletRequest req) {
if(bindingResult.hasErrors()){
req.setAttribute("msg","注册失败,验证未通过");
}
req.setAttribute("msg","注册成功");
return "";
}
注1:@Valid和Validated的区别,随便使用哪个都行
@Valid是使用hibernate validation的时候使用
@Validated 是只用spring Validator校验机制使用
2.3 在JSP页面上通过form标签显示消息
<form:errors path="*" /> 显示表单所有错误
<form:errors path="user* /> 显示所有以user为前缀的属性对应的错误
<form:errors path="username"/> 显示特定表单对象属性的错误
delimiter:如果一个属性有多个错误,错误信息的分隔符。默认是换行
注1:errors标签要放到form标签中才能显示错误消息
注2:如果使用form:errors标签不显示错误消息,请检查Model中是否已经添加了命令对象,没有是不会显示错误消息的
@ModelAttribute
public String reg(Model model) {
User user = new User();
model.addAttribute("user",user);
return "reg";//注册页面
}
2.4 通过BindingResult和form:errors标签在JSP页面显示非验证消息
public String login(@Valid @ModelAttribute Yh yh, BindingResult bindingResult, Model model){
bindingResult.rejectValue("yhzh", null, "帐号错误");
...
}
bindingResult.rejectValue("email", "validate.email.empty", "邮箱不能为空");
//这个函数有好几个重载的变体
它们是可以支持国际化的。 比如,上面这个例子表示, 错误的字段(filed)是“email”, errorCode是“validate.email.empty”, 与资源文件对应, 第三个是defaultMessage
3.1 通过接口定义若干个分组
3.2 给校验对象的指定属性添加校验规则,并指定校验组
3.3 在请求处理方法中,使用@Validated标记要验证的对象,并指定校验组
@Validated(value=User.ValidateGroups.login.class) User user
还可以对验证进行分组(@Validated)
User.java:
package com.zking.ssm.model;
import lombok.Data;
import org.springframework.stereotype.Repository;
import javax.validation.constraints.NotBlank;
@Repository
@Data
public class User {
public static interface ValidateGroups {
//登陆
public static interface login {
}
//注册
public static interface reg {
}
}
private Long userId;
@NotBlank(message = "用户名不能为空",groups = {User.ValidateGroups.login.class,User.ValidateGroups.reg.class})
private String userName;
@NotBlank(message = "密码不能为空",groups = {User.ValidateGroups.login.class,User.ValidateGroups.reg.class})
private String password;
@NotBlank(message = "确认密码不能为空",groups = {User.ValidateGroups.reg.class})
private String password2;
}
xxxController.java:
package com.zking.ssm.controller;
import com.zking.ssm.model.User;
import org.springframework.http.HttpRequest;
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.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequestMapping("/user")
public class UserController {
@ModelAttribute
public String reg(Model model) {
User user = new User();
model.addAttribute("user",user);
return "reg";
}
@RequestMapping("/tologin")//初始化登陆页面
public String tologin() {
return "login";
}
@RequestMapping("/toreg")//初始化注册页面
public String toreg() {
return "reg";
}
@RequestMapping("/toreg1")//注册验证消息
public String toreg1(@Validated(value = User.ValidateGroups.reg.class) User user,
BindingResult bindingResult,HttpServletRequest req) {
if(bindingResult.hasErrors()){
req.setAttribute("msg","注册失败,验证未通过");
return "reg";
}
req.setAttribute("msg","注册成功");
return "login";
}
@RequestMapping("/tologin1")//登陆校验
public String tologin1(@Validated(value=User.ValidateGroups.login.class) User user,
BindingResult bindingResult, HttpServletRequest req) {
if(bindingResult.hasErrors()){
req.setAttribute("msg","验证失败请重新输入");
return "login";
}
req.setAttribute("msg","登陆成功");
return "login";
}
}
登陆页面:
Login.jsp:
<%@ taglib prefix="p" uri="http://www.springframework.org/tags/form" %>
<%--
Created by IntelliJ IDEA.
User: zjjt
Date: 2020/7/2
Time: 22:50
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSR303</title>
<%@include file="/common/head.jsp"%>
<style>
.err{
color: red;
}
</style>
</head>
<body>
<h1>JSR303登陆<%=System.currentTimeMillis()%></h1>
<div>
<c:if test="${msg!=null}">
${msg}
<c:remove var="msg"></c:remove>
</c:if>
</div>
<div>
<f:form modelAttribute="user" action="${ctx}/user/tologin1" method="post" enctype="multipart/form-data">
<p>
<f:errors path="*"></f:errors>
</p>
账号:<f:input path="userName" ></f:input><f:errors path="userName" cssClass="err"></f:errors><br>
密码:<f:password path="password" ></f:password><f:errors path="password" cssClass="err"></f:errors><br>
<input type="submit" value="登陆">
</f:form>
</div>
</body>
</html>
注册页面:
Reg.jsp:
<%--
Created by IntelliJ IDEA.
User: zjjt
Date: 2020/7/2
Time: 22:50
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSR303</title>
<%@include file="/common/head.jsp"%>
<style>
.err{
color: red;
}
</style>
</head>
<body>
<h1>JSR303注册<%=System.currentTimeMillis()%></h1>
<div>
<c:if test="${msg!=null}">
${msg}
<c:remove var="msg"></c:remove>
</c:if>
</div>
<div>
<f:form modelAttribute="user" action="${ctx}/user/toreg1" method="post" enctype="multipart/form-data">
<p>
<f:errors path="*"></f:errors>
</p>
账号:<f:input path="userName" autocomplete="off"></f:input><f:errors path="userName" cssClass="err"></f:errors> <br>
密码:<f:password path="password" autocomplete="off"></f:password><f:errors path="password" cssClass="err" ></f:errors> <br>
确认密码:<f:password path="password2" autocomplete="off"></f:password><f:errors path="password2" cssClass="err"></f:errors> <br>
<input type="submit" value="确认">
</f:form>
</div>
</body>
</html>
@GroupSequence({First.class, Second.class, User.class})
实例结果:
如果输入失败则不会跳页面:
如果输入成功跳页面:
5. 其它
bindingResult.getFieldErrors();
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.3</version>
</dependency>
<!--但是,从spring3.1开始DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter的使用已经过时-->
<!--spring3.1开始我们应该用RequestMappingHandlerMapping来替换DefaultAnnotationHandlerMapping,-->
<!--spring3.1开始我们应该用用RequestMappingHandlerAdapter来替换AnnotationMethodHandlerAdapter-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<!--处理中文乱码以及避免IE执行AJAX时,返回JSON出现下载文件-->
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>text/json;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
JsonData:
package com.zking.ssm.util;
import java.io.Serializable;
import java.util.HashMap;
/**
* 服务器返回给客户端的JSON格式的数据
*
*/
public class JsonData extends HashMap<String, Object> implements Serializable {
private static final long serialVersionUID = -8855960778711040221L;
private static final String CODE_KEY = "code";// 操作代码 0 成功 非0 失败
private static final String MESSAGE_KEY = "message";// 操作消息
private static final String RESULT_KEY = "result";// 结果集
private static final String PAGE_KEY = "page";// 页码
private static final String ROWS_KEY = "rows";// 每页行数/页大小
private static final String TOTAL_KEY = "total";// 总记录数
public JsonData() {
super();
this.put(CODE_KEY, 0);// 默认操作成功
}
public void setCode(Integer code) {
this.put(CODE_KEY, code);
}
public void setMessage(String message) {
this.put(MESSAGE_KEY, message);
}
public void setResult(Object result) {
this.put(RESULT_KEY, result);
}
public void setPage(Integer page) {
this.put(PAGE_KEY, page);
}
public void setRows(Integer rows) {
this.put(ROWS_KEY, rows);
}
public void setTotal(Integer total) {
this.put(TOTAL_KEY, total);
}
}
@GetMapping("/get/{bookId}")
@ResponseBody
public JsonData get(@PathVariable Integer bookId) {
JsonData jsonData = new JsonData();
Book book = bookService.selectByPrimaryKey(bookId);
jsonData.setResult(book);
return jsonData;
}
注:此请求处理方法返回的已经不是视图了
BookController:
package com.zking.ssm.controller;
import com.zking.ssm.model.Book;
import com.zking.ssm.service.IBookService;
import com.zking.ssm.util.JsonData;
import com.zking.ssm.util.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Controller
@RequestMapping("/Book")
public class BookController {
@Autowired
private IBookService bookService;
@RequestMapping("/BookList")
public String BookList(Book book, HttpServletRequest rsq){
System.out.println(book.getBookName());
PageBean pageBean = new PageBean();
pageBean.setRequest(rsq);
List<Book> list = bookService.list(book, pageBean);
rsq.setAttribute("list",list);
rsq.setAttribute("page",pageBean);
return "BookList";
}
@GetMapping("/get/{bookId}")
@ResponseBody
public JsonData get(@PathVariable Integer bookId) {
JsonData jsonData = new JsonData();
Book book = bookService.selectByPrimaryKey(bookId);
jsonData.setResult(book);
return jsonData;
}
@GetMapping("/getlist")
@ResponseBody
public JsonData get(Book book,HttpServletRequest req) {
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
JsonData jsonData = new JsonData();
List<Book> list = bookService.list(book, pageBean);
jsonData.setResult(list);
return jsonData;
}
}
@JsonIgnore | 标在Javabean的属性上,作用是在将ResponseBody中的Javabean返回前端过程中,被springmvc自带的jackson转化成json字符串时,忽略这个属性。对序列化也有影响。 |
---|
public class Xxx {
private String attr1;
@JsonIgnore
private String attr2;
public void setAttr1(String attr){
this.attr1 = attr;
}
public void setAttr2(String attr){
this.attr2 = attr;
}
}
@JsonFormat
**日期格式化**
1:一定要加入依赖,否则不生效:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
2:在实体类get方法上加入注解:
private Date createTime;
@JsonFormat(pattern = "yyyy年MM月dd日 HH:mm:ss", timezone = "GMT+8")
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
注:pattern = “yyyy年MM月dd日 HH:mm:ss”,还可以是其他格式
@JsonProperty(“error_code”)
@JsonProperty | 此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,@JsonProperty(value=“name”)。 |
---|
import com.fasterxml.jackson.annotation.JsonProperty;
public class Student {
@JsonProperty(value = "real_name")
private String realName;
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
@Override
public String toString() {
return "Student{" +
"realName='" + realName + '\'' +
'}';
}
}
测试:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws JsonProcessingException {
Student student = new Student();
student.setRealName("zhangsan");
System.out.println(new ObjectMapper().writeValueAsString(student));
}
}
结果:
{"real_name":"zhangsan"}