千家信息网

Spring Validator接口校验与全局异常处理器的示例分析

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要为大家展示了"Spring Validator接口校验与全局异常处理器的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Spring V
千家信息网最后更新 2026年11月02日Spring Validator接口校验与全局异常处理器的示例分析

这篇文章主要为大家展示了"Spring Validator接口校验与全局异常处理器的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Spring Validator接口校验与全局异常处理器的示例分析"这篇文章吧。

Spring Validator接口校验

日志使用Bean Validation校验机制,对基本数据类型进行校验,方法是在实体类属性上使用注解标识校验方式,最后在Controller类中具体方法的形参里添加@Vlidated注解。Bean Validation校验有一个缺点是,我们的数据校验是在Java实体类里进行约束的,如果我们有多个处理器方法需要用到同一个实体类,那么定义在实体类属性上的校验规则就不好划分了,有的处理器只需要校验一个属性,而有的处理器需要校验多个属性,我们不可能为每一个处理器都创建一个实体类。解决的方法在上一篇日志里也说到,使用分组校验方式,除此之外,还可以使用Spring的Validator接口校验,它允许我们在外部指定某一对象的校验规则。

校验器实现类

Spring的Validator是一个接口,我们自己的校验实现类必须实现这个接口,才可以通过重写方法完成自定义的校验规则,需要我们实现的方法有两个:supports()和validate()

public class UserValidator implements Validator {        @Override        public boolean supports(Class clazz) {                // 反射机制通过类的class静态变量获得该类的实例                return User.class.equals(clazz);        }         @Override        public void validate(Object obj, Errors errors) {                // 错误信息放入errors对象                ValidationUtils.rejectIfEmpty(errors, "username", "Username.is.empty",                                 "用户名不允许为空。");                User user = (User) obj;                if (user.getPassword() == null || user.getPassword().equals("")) {                        // rejectValue()参数:错误字段名,全局错误码,默认错误提示信息                        errors.rejectValue("password", "Password.is.empty", "密码不允许为空。");                } else if (user.getPassword().length() < 8) {                        errors.rejectValue("password", "Length.too.short", "密码长度不能小于八位。");                }        }}

Support()方法的功能是判断该校验类,是否支持被校验的实体类。例如我们这个校验类负责对User类进行校验,supports()方法传入被校验的实体类,通过反射机制获得User类实例,然后判断是否与传入的被校验实体类匹配。Validate()方法则是进行校验的具体实现方法,方法参数列表中有一个Errors对象,负责往里面存放校验的错误信息。下面就是具体的校验规则了,我们可以使用ValidationUtils校验工具类的方法进行校验,提供的参数依次为存放错误信息对象error,校验的字段名(对于校验实体类中的属性),全局错误码(类似于Bean Validation校验中根据错误码,使用外部properties的错误提示信息),最后一个参数是默认错误提示信息,当全局错误码没有找到对应的提示信息时,使用默认的错误提示信息。

除了使用ValidationUtils校验工具类外,第23行还也可以使用erroe对象的方法,设置获取校验错误信息,参数和ValidationUtils类的方法几乎一致。

Controller实现类

校验器类配置完后,在具体的业务逻辑处理部分,Controller类中使用。

@Controller@RequestMapping("user")public class InterfaceValidationController {        @InitBinder        public void initBinder(DataBinder binder) {                // 为DataBinder对象设置Validator校验接口                binder.setValidator(new UserValidator());        }                @RequestMapping("login")        public String login(Model model, @Valid User user, BindingResult result) {                List allErrors = null;                if (result.hasErrors()) {                        allErrors = result.getAllErrors();                        // 输出所有错误信息                        for(ObjectError objectError : allErrors) {                                System.out.println("code = " + objectError.getCode() +                                                 "DefaultMessage = " + objectError.getDefaultMessage());                                // 将错误信息发送到前端页面                                model.addAttribute("allErrors", allErrors);                        }                                                // 最后返回视图                        return "users/login";                } else {                        // 如果校验没有错误,跳转到成功登陆的页面                        return "users/successLogin";                }        }

首先需要通过initBinder()方法,在Controller类方法中进行校验器的绑定,方法需要DataBinder对象参数,DataBinder对象的功能是进行数据绑定,可以将数据进行类型转换,设置校验器等。DataBinder有一个成员变量BindingResult,进行了数据绑定了校验器绑定,当校验数据有错误信息时,就会将其放入到BindingResult对象中的Errors属性中,Errors对象集合前面说到,就是用来存放错误信息的。在Controller具体方法的参数列表中对要校验的数据对象User类添加@Valid注解,标识对该对象进行数据校验,接着添加BindingResult对象(这里有一点要注意,BindingResult参数位置必须紧跟在被校验的数据对象后面),当校验出现错误信息时,第15行我们就可以通过该对象的hasErrors()方法判断校验是否出错,然后使用getAllErrors()方法获取错误信息进行输出。最后第22行我们将错误信息传到前端页面上显示,给用户提示。

前端页面测试

最后,在前端页面进行简单的登陆测试:

<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>登录界面                        用户名:
密码:    

${error.defaultMessage}

第15行遍历后台发来的allErrors错误信息集合,如果出现校验出错,则显示错误信息。根据我们前面校验器的配置,对于User类对象的数据校验,用户名和密码都不允许为空:

当输入信息正确,用户名和密码都不为空,且密码长度不低于8位,便可成功跳转:

全局异常处理器Exception Resolver

对于程序运行时的错误信息,我们可以通过查看日志来排查错误,当我们把错误信息传到前端页面时,为了让用户能看懂错误原因,就需要对错误信息进行处理,在信息传送到前端页面前,将其捕获。完成错误信息捕获和加工处理,就需要配置我们的异常处理器。异常处理器用来自定义程序运行时如何解析异常,它需要自定义异常类,里面存储了对应异常的异常信息。还需要配置异常处理器,对于捕捉到的异常,如果是在自定义异常类中配置好的预期异常,则抛出相应的错误信息,否则,就进行其他显示。

自定义异常类

首先是自定义异常类,示例我们定义一个处理User类的异常类和异常处理器,在异常类中,设置对于User类出现异常时的错误信息存储。

package com.mvc.exception; public class UserException extends Exception {        private static final long serialVersionUID = 1L;        private String exceptionMessage;                public UserException(String exceptionMessage) {                super(exceptionMessage);                this.exceptionMessage = exceptionMessage;        }                public String getExceptionMessage() {                return exceptionMessage;        }        public void setExceptionMessage(String exceptionMessage) {                this.exceptionMessage = exceptionMessage;        }}

自定义异常类UserException专门负责处理User类异常,它怎么指定处理User类呢?这个是在异常处理器中完成,UserException继承了Exception类,这样我们就可以在具体Controller方法中将其throws抛出该异常。该类中定义了一个异常信息变量,用来存放异常信息,当异常处理器捕获到User类的异常时,通过UserException的构造方法设置异常信息,最后抛出UserException。

异常处理器

来到异常处理器的配置,异常处理器是捕获和处理异常的核心,在Spring MVC中,底层异常会一级一级往上抛,最后到达全局异常处理器,全局异常处理器的工作主要有四步:

  1. 捕获异常,解析出异常类型。

  2. 如果异常是预期异常(有定义好的异常类),则抛出相应的异常信息。

  3. 如果异常不是预期异常,则创建一个自定义异常类,抛出相应的异常信息(如:"未知异常信息")。

  4. 将异常信息绑定到前端页面,跳转到相应的异常信息页面中去。

结合上面的自定义异常类,来看看针对User类的异常处理器的配置:

package com.mvc.exception; import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerExceptionResolver;import org.springframework.web.servlet.ModelAndView; public class UserExceptionResolver implements HandlerExceptionResolver {        @Override        public ModelAndView resolveException(HttpServletRequest request,                         HttpServletResponse response, Object handler, Exception ex) {                // 首先解析出异常的类型                UserException userException = null;                if (ex instanceof UserException) {                        // 如果异常类型是UserException,则直接创建该类型的异常信息                        userException = (UserException) ex;                } else {                        // 否则创建一个自定义的异常类型                        userException = new UserException("发生未知错误。");                }                                // 取出错误信息                String errorMessage = userException.getExceptionMessage();                ModelAndView modelAndView = new ModelAndView();                // 错误信息传送到前端页面                modelAndView.addObject("errorMessage", errorMessage);                // 定向到错误提示页面                modelAndView.setViewName("errorPage/userError");                                return modelAndView;        }        }

Spring MVC中,异常信息最终通过DispatcherServlet交由全局异常处理器处理,需要全局异常处理器实现HandlerExceptionResolver接口接,重写里面的resolverException()方法完成异常处理。该方法中有两个参数要注意,object handler指定异常处理器要处理的对象,Exception ex显然就是接收底层抛出的异常。

在我们的异常处理器UserExceptionResolver中,第14行首先判断异常类型是否我们的定义的预期异常UserException,如果是,则抛出,否则,创建一个自定义异常类型,并给出错误提示"发生未知错误"。最后第26行,对异常信息处理完后,发送到前端页面进行展示,并跳转到错误提示界面。

测试用例

最后要使用我们的异常处理器,先要在Spring配置文件中添加这个异常处理器:

然后在Controller类方法中做相应的判断,如果出现预期异常,则抛出:

@Controller@RequestMapping("user")public class InterfaceValidationController {        @InitBinder        public void initBinder(DataBinder binder) {                // 为DataBinder对象设置Validator校验接口                binder.setValidator(new UserValidator());        }         @RequestMapping("login")        public String login(Model model, @Valid User user, BindingResult result)                         throws UserException {                boolean allowVisit = checkUser(user);                if (!allowVisit) {                        // 该用户没有访问权限,抛出异常                        throw new UserException("您没有权限访问!");                }                                List allErrors = null;                if (result.hasErrors()) {                        allErrors = result.getAllErrors();                        // 输出所有错误信息                        for(ObjectError objectError : allErrors) {                                System.out.println("code = " + objectError.getCode() +                                                 "DefaultMessage = " + objectError.getDefaultMessage());                                // 将错误信息发送到前端页面                                model.addAttribute("allErrors", allErrors);                        }                                                // 最后返回视图                        return "users/login";                } else {                        // 如果校验没有错误,跳转到成功登陆的页面                        return "users/successLogin";                }        }

可以看到第57行最后我们还要跳转到错误页面,将错误信息显示出来:

<%@ page language="java" import="java.util.*"         contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>错误提示        发生异常,错误信息如下:

${errorMessage}


以上是"Spring Validator接口校验与全局异常处理器的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

信息 错误 处理 处理器 方法 对象 页面 全局 接口 前端 数据 提示 参数 实体 类型 配置 用户 密码 属性 校验器 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 什么是科技互联网 百单网互联网科技有限公司怎么样 上海睿民互联网科技有限公司 广州淘业互联网络科技 互联网科技财经 北京互联网科技有限公司 顺玮阁互联网科技 互联网科技大会 四川狮子座互联网科技 哈尔滨新华互联网科技 深圳市运趣互联网科技有限公司 宁夏科技产业互联网案例 国大互联网教育科技有限公司工作 河南住房之家互联网科技 互联网行业科技股 深圳市罗太互联网科技有限公司 互联网领先科技活动 悟空问答互联网科技 互联网科技快速发展优美句子 武汉亿视互联网科技有限公司 互联网科技巨头监管 深圳恒合互联网络科技有限公司 互联网科技公司的优势 互联网科技的 互联网医疗科技 贵州叶脉互联网科技有限公司所属行业 用友工业互联网科技发展 中国互联网有什么科技 互联网时代科技型公司的机会 悟空问答互联网科技
0