Spring Boot系列(五)、SpringBoot全局异常处理、数据校验

五、SpringBoot全局异常处理、数据校验

    • 5.1 SpringBoot异常处理
      • 5.1.1 Controller层局部异常处理
      • 5.1.2 基于@ControllerAdvice注解的Controller层的全局异常处理
      • 5.1.3 HandlerExceptionResolver处理异常解析器
    • 5.2 SpringBoot数据校验

5.1 SpringBoot异常处理

我们知道在做SpingBoot时,难免会出现很多异常,想要快速解决这些异常必须要知道异常出在何处,又是何种错误,SpringBoot内置的已经有了一些异常处理,例如:RuntimeException、ArithmeticException、NullPointerException等等异常,但是仅仅这些异常是远远不够我们对于异常的断定和处理,所以才会延伸出局部异常处理、全局异常和深度异常处理等等,中心思想还是为了能够更加方便的了解出现异常时,知道是何种错误并快速处理,这样才不会盲目的去改bug。

SpringBoot默认的处理异常的机制,一旦程序中出现了异常会像/error 的 url 发送请求。默认BasicExceptionController 来处理/error 请求,然后跳转到默认显示异常的页面,也可以自定义error.html 页面。

5.1.1 Controller层局部异常处理

先看一段局部异常处理:

package com.kdcrm.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

@Controller
public class ToIndexController {


    @RequestMapping("/testException")
    public void testException(){
        //制造运行时异常
        System.out.println(1/0);
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Map exceptionHandler(Exception ex)
    {
        Map map=new HashMap<>();
        map.put("code",101);
        map.put("msg",ex.toString());
        return map;
    }
 
}

Spring Boot系列(五)、SpringBoot全局异常处理、数据校验_第1张图片

5.1.2 基于@ControllerAdvice注解的Controller层的全局异常处理

上述类中定义的异常处理,只能处理当前类中的异常,其他类中的捕获不到,所以我们引入了基于 @ControllerAdvice注解 的Controller层的全局异常处理:

package com.kdcrm.controller;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.util.HashMap;
import java.util.Map;


@ControllerAdvice
public class GlobalExceptionHandlerController {

	/**
     * 捕获Controller层的所有异常信息
     * @param ex
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Map exceptionHandler(Exception ex)
    {
        Map map=new HashMap<>();
        map.put("code",203);
        map.put("msg",ex.toString());
        return map;
    }
}

Spring Boot系列(五)、SpringBoot全局异常处理、数据校验_第2张图片
也可以将异常信息跳转到指定页面内,便于管理:
error.html:


<html lang="en" mlns:th="http://www.thymeleaf.org" xmlns:mlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>error页面title>
head>
<body>

<h1 th:text="${msg}">h1>
body>
html>

Controller层全局异常处理GlobalExceptionHandlerController:

package com.kdcrm.controller;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandlerController {
 
    /**
     * 将异常信息跳转值指定error页面
     * @param ex
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public ModelAndView exceptionHandler2(Exception ex){
        ModelAndView mav = new ModelAndView();
        mav.addObject("msg",ex.toString());
        mav.setViewName("error");
        return mav;
    }
}

Spring Boot系列(五)、SpringBoot全局异常处理、数据校验_第3张图片

5.1.3 HandlerExceptionResolver处理异常解析器

上述是通过@ControllerAdvice注解的方式实现的全局异常处理,还有一种是实现HandlerExceptionResolver处理异常解析器接口的方式,两者原理是一样的,根据出现的是何种异常跳转至相应的页面,更加精准些:

package com.kdcrm.controller;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class GlobalExceptionHandlerController implements HandlerExceptionResolver {
    
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception ex) {
        ModelAndView mav = new ModelAndView();
        //判断不同异常类型,做不同的视图跳转
        if(ex instanceof ArithmeticException) {
            mav.setViewName("ArithmeticError");
        }else if (ex instanceof NullPointerException){
            mav.setViewName("NullpointerError");
        }else if (ex instanceof IllegalAccessException){
            mav.setViewName("IllegalAccessError");
        }

        mav.addObject("msg",ex.toString());

        return mav;

    }

}

5.2 SpringBoot数据校验

我们可能会经常需要对传入的参数进行校验,如果数据比较少的时候还比较容易处理,但当数据比较多的时候会显得比较麻烦,而且处理不当的时候,还会代码重复。这时候就需要对参数进行校验了,而Spring Boot采用的是Validation对数据进行校验。

  • SpringBoot对表单数据校验的技术特点,使用了Hibernate-validation校验框架。

首先引入校验包依赖文件:

<dependency>
	<groupId>org.hibernate.validatorgroupId>
	<artifactId>hibernate-validatorartifactId>
	<version>7.0.0.Finalversion>
dependency>	            

JSR 303 是Bean验证的规范 ,Hibernate Validator 是该规范的参考实现,它除了实现规范要求的注解外,还额外实现了一些注解。
包括一下注解:

注解 说明
@AsserrtFalse 元素必须为false
@AssertTrue 元素必须为true
@DecimalMax(value) 元素必须为数字,最大值为指定value
@DecimalMin(value) 元素必须为数字,最小值为指定value
@Digits(integer,fraction) 元素必须为数字,其值必须在可接受的范围内
@Null 元素必须为null
@NotNull 元素必须不为null
@Min(value) 元素必须为数字,其值大于等于指定value
@Max(value) 元素必须为数字,其值小于等于指定value
@Size(min,max,message) 元素大小必须在指定范围内,message加以说明
@Past 元素必须是一个过去的日期
@Furture 元素必须是一个将来的日期
@Pattern 元素符合指定的正则表达式
@Email 元素必须为电子邮箱格式
@Length(min,max,message) 必须是字符串,其值在指定范围内,message加以说明
@NotBlank(message) 字符串不能为null,且trim后不能为空字符串(长度非0),message加以说明
@NotEmpty 被注释的字符串、集合、数组不能为空(长度非0)
@Range 元素在合适的范围内
@SafeHtml 元素必须是安全Html
@URL 元素必须是有效URL

上述注解只是其中一部分,高亮注解是常用于Bean属性的校验,通过 @ConfigurationProperties(prefix = “user”) 引入配置文件并自动绑定属性:
User类:

package com.kdcrm.pojo;

import org.hibernate.validator.constraints.Length;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.*;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Configuration
@ConfigurationProperties(prefix = "user")
@Validated
public class User {

    /**
     * @notNull 限制不能为空
     * @NotEmpty 元素不能为null,且不为空(字符串和集合的长度不能为0)
     * @NotBlank(message = "XXX不能为空"),判断字符串是否为null,或者去掉首尾空格是否为空串
     * @Length(min = 6,max = 10,message = "最短为6位,最大为10位")
     * @Min(value = "6") 限制最小值
     * @Max(value = "10") 限制最大值
     * @Email 判断邮箱是否合法
     * @NotEmpty 字符串、集合、数组不能为空(长度非0)
     */

    @NotNull
    @Length(min = 1,max = 3,message = "名字长度最小为1,最大为3")
    private String name;

    @NotNull
    @Min(value = 6)
    @Max(value = 16)
    private String password;

    @NotNull
    @Size(min = 1,max = 100,message = "最小1岁,最大100岁")
    private int age;

    @NotBlank(message = "性别不能为空")
    private String sex;

    @Email
    private String email;

    @NotEmpty
    private List list;

    @NotEmpty
    private Set set;

    @NotEmpty
    private Map map;

}

application.yml配置文件

user:
  name: wbs
  password: 123456
  age: 21222
  sex: 男男男男
  email: [email protected]
  list:
    - dog
    - cat
    - pig
  set:
    - dog
    - cat
    - pig
  map:
    k1: zs
    k2: ls
    k3: ww

Controller层进行对象数据校验,用@Valid注解,通过BindingResult接收校验结果:

package com.kdcrm.controller;

import com.kdcrm.pojo.User;
import com.kdcrm.service.UserService;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ResponseHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;


/**
 * @author 一宿君(CSDN : qq_52596258)
 * @date 2021-08-06 08:52:36
 */
@Controller
public class PeopleController {

    @ResponseBody
    @RequestMapping("/addUser")
    public ModelAndView addUser(@Valid User user, BindingResult result, ModelAndView mav){
        if(result.hasErrors()){
            //如果有错误,跳转至添加页面
            mav.setViewName("addUser");
            return mav;
        }
        //如果没有错误,则将数据存入到request作用域中
        mav.addObject("user",user);
        mav.setViewName("UserIndex");
        return mav;
    }

}

你可能感兴趣的:(Java编程技术,SpringBoot,SpringBoot数据校验,SpringBoot异常处理)