亮,有一计

文章 分类 评论
52 17 10

站点介绍

这是一个热爱和别人一起交流学习的程序员所建立的个人博客 欢迎大家交流讨论

SpringBoot全局异常处理和javax参数校验

liang 2021-11-11 242 7条评论 SpringBoot 参数校验全局异常处理

首页 / 正文
本站的文章若无特殊标明转载的话均为原创,有些文章在我的csdn个人站也有,两者基本上是同步的 博客地址

发布于2022-07-08

前言

今天给大家介绍一下SpringBoot(Spring也可以)项目中如何优雅的整合==JSR-303==进行参数校验 以及对全局的异常进行处理封装

什么是JSR-303

JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,Bean Validation 是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回.Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint.

添加依赖

SpringBoot项目可以用starter组件

<dependency>
    <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

老点的spring项目可以用下面这个(同样适用于springBoot项目)

        <!-- 参数校验 -->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.1.Final</version>
        </dependency>

SpringBoot项目设置全局异常处理

参数在校验失败的时候会抛出的==MethodArgumentNotValidException==异常,可以在全局的异常处理器中捕捉这个异常,将报错信息同一封装之后返回给客户端。

全局异常处理器代码如下

注意: 此控制器为接口形式 处理异常的方法均为接口的default方法 此举不同于其他博客的注解形式和继承形式 注解形式是直接控制全局灵活性欠佳(比如你有一个三方回调的控制器类不想被监控) 而继承的方式又绑定的太死 所以采用了接口和default方法
/**
 * <p>
 *     全局异常处理的基础类 必须实现此类
 * </p>
 * @author liang
 * @date 2021/5/28 17:46
 */
public interface HandleExceptionController {


    /**
     * 处理实现此类的所有程序抛出的业务代码异常
     * @param e 业务代码自定义异常
     * @return 封装好的统一返回结果
     */
    @ExceptionHandler(ServiceException.class)
    @ResponseBody
    default ResponseResult handleException(ServiceException e) {
        ResponseResult result = new ResponseResult();
        result.setCode(e.getCode());
        result.setMessage(e.getMessage());
        result.setData(e.getData());
        return result;
    }


    /**
     * 处理实现此类的所有程序抛出的参数绑定异常
     * @param e 参数绑定异常
     * @return 封装好的统一返回结果
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    default ResponseResult methodArgumentNotValidException(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return new ResponseResult(ResultEnum.REQUIRED_MISSING.getCode(), message,null);
    }


    /**
     * 处理实现此类的所有程序抛出的未知异常
     * @param e 程序抛出来的异常
     * @return 封装好的统一返回结果
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    default ResponseResult handleException(Exception e) {
        return new ResponseResult(ResultEnum.ERROR, e.getMessage());
    }

}

示例Controller代码

@Validated注解是用来标识这个参数类需要进行参数校验的

@RestController
@RequestMapping("/api/test")
@Api(value = "TestController", tags = { "测试类" })
public class TestController implements HandleExceptionController {

    @ApiOperation(value = "测试查询", notes = "测试查询")
    @PostMapping(value = "/queryTest")
    public ResponseResult queryTest(@RequestBody @Validated QueryTestParam param){
        JSONObject result = new JSONObject();
        return new ResponseResult(ResultEnum.SUCCESS,result);
    }

}

参数类

省略get和set方法

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 * @author liang
 * @date 2021年12月29日 14:23
 */
public class QueryTestParam {

    @NotNull(message = "integer不能为空")
    private Integer integer;

    @NotBlank(message = "string不能为空")
    private String string;
}
如果参数类中的integer为null或者string为空字符串则会抛出MethodArgumentNotValidException异常,紧接着此异常会被HandleExceptionController接口的methodArgumentNotValidException方法捕获到 注意这行代码: @ExceptionHandler(MethodArgumentNotValidException.class)这个注解表示你的方法要捕获处理的异常是什么 如果你要捕获的异常有继承关系 他会优先捕获子类的详细类型的异常 所以接口中有一个handleException方法来捕获最终的异常exception

javax参数校验

内嵌的注解列表

注释解释
@Null被注释的元素必须为 null
@NotNull被注释的元素必须不为 null
@NotBlank被注释的元素必须为字符串而且不能为空
@AssertTrue被注释的元素必须为 true
@AssertFalse被注释的元素必须为 false
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min)被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期
@Pattern(value)被注释的元素必须符合指定的正则表达式
@Email被注释的元素必须是电子邮箱地址
@Length被注释的字符串的大小必须在指定的范围内
@NotEmpty被注释的字符串的必须非空
@Range被注释的元素必须在合适的范围内
如何使用

get和set方法省略

import javax.validation.constraints.Future;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;

/**
 * @author liang
 * @date 2021年12月29日 14:23
 */
public class QueryTestParam {

    @NotNull(message = "文章id不能为空")
    @Min(value = 1,message = "文章ID不能为负数")
    private Integer id;

    @NotBlank(message = "文章内容不能为空")
    private String content;

    @NotBlank(message = "作者Id不能为空")
    private String authorId;

    @Future(message = "提交时间不能为过去时间")
    private Date submitTime;
}

分组校验

举例说明 新增和修改一篇文章 修改只比新增接口多传一个主键id,这时候很明显不想要建立两个非常相似的实体类去分别接收,这时候该怎么办呢?
答案显而易见,就是进行分组校验 新增是一个分组 修改是一个分组

所有的校验注解都有一个groups属性用来指定分组,Class<?>[]类型,没有实际意义,因此只需要定义一个或者多个接口用来区分即可。
/**
 * @author liang
 * @date 2021年12月29日 14:23
 */
public class QueryTestParam {

    /**
     *添加的校验分组接口
     */
    public interface add{}

    /**
     * 修改的校验分组接口
     */
    public interface update{}

    @NotNull(message = "文章id不能为空",groups = update.class)
    @Min(value = 1,message = "文章ID不能为负数",groups = update.class)
    private Integer id;

    @NotBlank(message = "文章内容不能为空",groups = {add.class,update.class})
    private String content;

    @NotBlank(message = "作者Id不能为空",groups = {add.class,update.class})
    private String authorId;

    @Future(message = "提交时间不能为过去时间",groups = {add.class,update.class})
    private Date submitTime;

}
JSR303本身的@Valid并不支持分组校验,但是Spring在其基础提供了一个注解@Validated支持分组校验。@Validated这个注解value属性指定需要校验的分组。
@RestController
@RequestMapping("/api/test")
@Api(value = "TestController", tags = { "测试类" })
public class TestController implements HandleExceptionController {
    @ApiOperation(value = "测试查询", notes = "测试查询")
    @PostMapping(value = "/queryTest")
    public ResponseResult queryTest(@RequestBody @Validated(value =QueryTestParam.add.class ) QueryTestParam param){
        JSONObject result = new JSONObject();
        return new ResponseResult(ResultEnum.SUCCESS,result);
    }

}

嵌套校验

嵌套校验 就是一个实体中包含了另一个实体 而这两个实体都需要校验

嵌套校验很简单,只需要在嵌套的实体属性标注@Valid注解,则其中的属性也将会得到校验,否则不会校验。
/**
 * @author liang
 * @date 2021年12月29日 14:23
 */
public class QueryTestParam {

    @Valid
    private AddParam addParam;
}

最后附赠一个校验工具类 可以在代码里随时对对象进行javax的校验

import org.hibernate.validator.HibernateValidator;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

/**
 * @author liang
 */
public class ValidatorUtils {

    private static final Validator VALIDATOR_ALL = Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator();

    /**
     * 校验不通过则抛出去自定义异常 {@link ServiceException}
     * @param obj 需要校验的对象
     * @param groups 需要校验的分组(可变长参数列表)
     * @param <T> 对象类型
     */
    public static <T> void validatorByGroups(T obj, Class<?>... groups) {
        Set<ConstraintViolation<T>> constraintViolations = VALIDATOR_ALL.validate(obj, groups);
        // 抛出检验异常
        if (constraintViolations.size() > 0) {
            throw new ServiceException(ResultEnum.REQUIRED_MISSING.getCode(),constraintViolations.iterator().next().getMessage());
        }
    }

    /**
     * 校验不通过则抛出去自定义异常 {@link ServiceException}
     * @param obj 需要校验的对象
     * @param <T> 对象类型
     */
    public static <T> void validatorObject(T obj) {
        Set<ConstraintViolation<T>> constraintViolations = VALIDATOR_ALL.validate(obj);
        // 抛出检验异常
        if (constraintViolations.size() > 0) {
            throw new ServiceException(ResultEnum.REQUIRED_MISSING.getCode(),constraintViolations.iterator().next().getMessage());
        }
    }

}

评论(7)

  1. manchester united tøj 游客 2022-12-14 11:14 回复

    Araofclmh australia vm barn Drakt KaseyTls

    Kristieif real madrid drakt ThadHilly
    RhysHorns liverpool tröja barn DedraNett
    AlissaGal Maglia Chile Mondiali 2022 MilanFait
    OnitaSass chelsea drakt AlannahEa
    NaomiLev liverpool tröja barn JuanTregu
    AdrieneBe Brasilien VM 2022 Landsholdstrøje MilfordNe
    SimonJsh maglie napoli 2022 JuliaLayt
    EzraPouli marseille tröja LinoldDi
    JannieSpr chelsea matchtröja GlendaMes
    CraigTasm Atalanta Drakt LenaBella
    LashondaB Maglia Armenia Mondiali 2022 JermaineE
    RicoLeona danmark VM tröja Shananwsw
    Gildaohft VM fotbollstrojör VM CaryBrans
    TrenavcZ Portugal VM 2022 Landsholdstrøje JewelJano
    Jacquetta Island VM 2022 Landsholdstrøje FreyaYdyr
    TobiasHer Portugal VM 2022 Landsholdstrøje AzucenaVe
    BeatriceV australia VM 2022 Drakt VeronaTul
    MoseButtr Maglia Wales Mondiali 2022 StacyHytt
    TobiasHer Portugal VM 2022 Landsholdstrøje AzucenaVe

  2. il: Clark11370 游客 2022-10-31 08:19 回复

    Margenemh 357 fotballdrakter til bedriftslag Coreyc – Coin Media – журнал о заработке в интернете
    Francesco
    CasieDalu maglia argentina AbbieLand
    JessRoman Website Darrellie
    PaulinaRu Profile of ChristieRy SidneyMgw
    ToneyKrog Liverpool Tøj - Blog Profile - iotaJots JaimieChe
    TriciaBri Wolearn: GregoryEmelia: Magliette Calcio Poco
    Prezzo SheltonTh
    WayneHone 438 Chile Tröja Barn Leopol – Profile – Primescool Forum CharlineC
    VitoHartf norge bortedrakt to receive adulation, always
    insists the result is most important and will therefore be
    thoroughly disheartened by this display.

    As is often the case in friendly matches, there was a lack FedericoW صفحه اصلی – Maglia Porto KurtBrise of urgency for large periods during this
    match, though Wales did link play promisingly in attack through
    Wilson and Brooks. Italy will be among the nations in pot one
    for the Euro 2020 qualifying draw in Dublin on 2 December having drawn 0-0 against Portugal
    in their previous match to ensure a second-place finish in Nations League Group 3A.
    TanjaFitz
    Elizabeth manchester city tröjor KenPoulin
    CarenWhar Maglia Juventus Bambino EmeliaBow
    Stephaine liverpool drakt DarlaFulm
    FerneSuvg barcelona FC drakt Meaganold
    EmilyEise arsenal drakt KourtneyS
    Kellyejoh inter trøje JamaalWor
    Loisniyet psg drakt MaricelaS
    CecileSwa lavora come produttore esecutivo della serie CharissaC
    ChastityF Home - Liverpool Drakt EmilGmvut
    CasieDalu maglia argentina AbbieLand
    UrsulaLof rashford numero maglia KareemCap
    SSNGilber arsenal drakt 2022 MelodeePe

  3. arsenal trøjer 游客 2022-10-12 15:35 回复

    BrittnyFo atletico madrid tröja ClaritaBu
    ZJRBridge magliette psg JosephDur
    Valentina real madrid drakt MarionTol
    NevaLangt manchester united drakt BraydenBo
    RodolfoCa Real Madrid Tröja KelliefjL
    BettinaMi Notenbrood op top niveau MillardMh

    RichardMo arsenal drakt Bradleyjo
    TanyaNuge Spanien landsholdstrøje AprilBuck
    JoannaShe Billige Polen Fotballdrakter NiklasWes
    Maryellen terza maglia milan PrincessN
    AnhGiffen real madrid tröja FredricAu
    JoannaShe Billige Polen Fotballdrakter NiklasWes
    EssieOate juventus matchtröja PreciousF
    EdnaTippe sabinahogan447 EffieOcon
    MichaelaH liverpool tröja barn KayleighM
    JonnieHoc nuova maglia roma 2021/22 CortezSha
    YDZClaire ac milan drakt KathleneH
    CedricBac manchester united drakt Peterysjl
    HaicoQcmw Maglia Brasile Femmina ThereseJu
    DoreenMes napoli trøje JadaLanni

  4. maglie hellas verona 2022 游客 2022-09-30 02:14 回复

    Your style is very unique in comparison to other folks I have read stuff from.
    Many thanks for posting when you have the opportunity, Guess I'll just bookmark
    this blog. maglie hellas verona 2022
    IlanaGxrn frankrike tröja JaneenZtt

  5. inter milan tröja 游客 2022-09-29 18:00 回复

    I truly love your site.. Pleasant colors & theme.
    Did you make this website yourself? Please reply back as I'm hoping to create my own website and would like to learn where you got this
    from or just what the theme is named. Cheers! inter milan tröja
    LilianaCz Frankrike Tröja Barn NganRjpfi

  6. atletico madrid trøje 游客 2022-09-29 13:40 回复

    Thank you for the good writeup. It in fact was a amusement account it.
    Look advanced to far added agreeable from you! However,
    how could we communicate? atletico madrid trøje
    TrishaBil nuove magliette napoli WarrenUlv

  7. liverpool bortedrakt 游客 2022-09-28 22:04 回复

    Whats up are using Wordpress for your site platform? I'm new to the blog world but I'm trying to get
    started and set up my own. Do you require any html coding knowledge to make your own blog?
    Any help would be greatly appreciated! liverpool bortedrakt
    Marcelino Kjøp Russland Landslagsdrakt RachaelBe

最新评论

  • manchester united tøj

    Araofclmh australia vm barn Drakt KaseyTls Kristieif real madrid drakt ThadHilly RhysHorns liverpool tröja barn DedraNett AlissaGal Maglia Chile Mondiali 2022 MilanFait OnitaSass chelsea drakt AlannahEa NaomiLev liverpool tröja barn JuanTregu AdrieneBe Brasilien VM 2022 Landsholdstrøje MilfordNe SimonJsh maglie napoli 2022 JuliaLayt EzraPouli marseille tröja LinoldDi JannieSpr chelsea matchtröja GlendaMes CraigTasm Atalanta Drakt LenaBella LashondaB Maglia Armenia Mondiali 2022 JermaineE RicoLeona danmark VM tröja Shananwsw Gildaohft VM fotbollstrojör VM CaryBrans TrenavcZ Portugal VM 2022 Landsholdstrøje JewelJano Jacquetta Island VM 2022 Landsholdstrøje FreyaYdyr TobiasHer Portugal VM 2022 Landsholdstrøje AzucenaVe BeatriceV australia VM 2022 Drakt VeronaTul MoseButtr Maglia Wales Mondiali 2022 StacyHytt TobiasHer Portugal VM 2022 Landsholdstrøje AzucenaVe

  • Hello Word !

    我发现我的评论功能,加载不了头像!朋友圈和相册也加载不了,音乐播放器也不显示,求解!

  • il: Clark11370

    Margenemh 357 fotballdrakter til bedriftslag Coreyc – Coin Media – журнал о заработке в интернете Francesco CasieDalu maglia argentina AbbieLand JessRoman Website Darrellie PaulinaRu Profile of ChristieRy SidneyMgw ToneyKrog Liverpool Tøj - Blog Profile - iotaJots JaimieChe TriciaBri Wolearn: GregoryEmelia: Magliette Calcio Poco Prezzo SheltonTh WayneHone 438 Chile Tröja Barn Leopol – Profile – Primescool Forum CharlineC VitoHartf norge bortedrakt to receive adulation, always insists the result is most important and will therefore be thoroughly disheartened by this display. As is often the case in friendly matches, there was a lack FedericoW صفحه اصلی – Maglia Porto KurtBrise of urgency for large periods during this match, though Wales did link play promisingly in attack through Wilson and Brooks. Italy will be among the nations in pot one for the Euro 2020 qualifying draw in Dublin on 2 December having drawn 0-0 against Portugal in their previous match to ensure a second-place finish in Nations League Group 3A. TanjaFitz Elizabeth manchester city tröjor KenPoulin CarenWhar Maglia Juventus Bambino EmeliaBow Stephaine liverpool drakt DarlaFulm FerneSuvg barcelona FC drakt Meaganold EmilyEise arsenal drakt KourtneyS Kellyejoh inter trøje JamaalWor Loisniyet psg drakt MaricelaS CecileSwa lavora come produttore esecutivo della serie CharissaC ChastityF Home - Liverpool Drakt EmilGmvut CasieDalu maglia argentina AbbieLand UrsulaLof rashford numero maglia KareemCap SSNGilber arsenal drakt 2022 MelodeePe

  • arsenal trøjer

    BrittnyFo atletico madrid tröja ClaritaBu ZJRBridge magliette psg JosephDur Valentina real madrid drakt MarionTol NevaLangt manchester united drakt BraydenBo RodolfoCa Real Madrid Tröja KelliefjL BettinaMi Notenbrood op top niveau MillardMh RichardMo arsenal drakt Bradleyjo TanyaNuge Spanien landsholdstrøje AprilBuck JoannaShe Billige Polen Fotballdrakter NiklasWes Maryellen terza maglia milan PrincessN AnhGiffen real madrid tröja FredricAu JoannaShe Billige Polen Fotballdrakter NiklasWes EssieOate juventus matchtröja PreciousF EdnaTippe sabinahogan447 EffieOcon MichaelaH liverpool tröja barn KayleighM JonnieHoc nuova maglia roma 2021/22 CortezSha YDZClaire ac milan drakt KathleneH CedricBac manchester united drakt Peterysjl HaicoQcmw Maglia Brasile Femmina ThereseJu DoreenMes napoli trøje JadaLanni

  • maglie hellas verona 2022

    Your style is very unique in comparison to other folks I have read stuff from. Many thanks for posting when you have the opportunity, Guess I'll just bookmark this blog. maglie hellas verona 2022 IlanaGxrn frankrike tröja JaneenZtt

日历

2023年02月

   1234
567891011
12131415161718
19202122232425
262728    

友情链接

文章目录

推荐关键字:

站点公告
本站的文章若无特殊标明转载的话均为原创,有些文章在我的csdn个人站也有,两者基本上是同步的 博客地址
点击小铃铛关闭