【SpringMVC】全局异常处理 拦截器 参数校验 扩展总结第四期


一、全局异常处理机制

1

1.1 异常处理两种方式

  • 编程式异常处理
    • 代码中显式地编写处理异常的逻辑
    • try-catch-finally
  • 声明式异常处理
    • 将异常处理的逻辑从具体的业务逻辑中分离出来
    • 通过配置等方式进行统一的管理和处理
    • @Throws@ExceptionHandler

1.2 基于注解异常声明异常处理

  1. 声明异常处理控制器类
    统一定义异常处理handler方法!
// 全局异常发生,会走这个类的handler

//@ControllerAdvice // 可以返回逻辑视图 转发和重定向
@RestControllerAdvice // @ResponseBody 直接返回json字符串
public class GlobalExceptionHandler {
}
  1. 声明异常处理hander方法
    @ExceptionHandler(异常.class)
    @ExceptionHandler(ArithmeticException.class)
    public Object ArithmeticExceptionHandler(ArithmeticException e){
        // 算术异常
        String message = e.getMessage();
        System.out.println("message : " + message);
        return message;
    }

    @ExceptionHandler(Exception.class)
    public Object ExceptionHandler(Exception e){
        // 全局异常
        String message = e.getMessage();
        System.out.println("message : " + message);
        return message;
    }
  • 普通的handler方法要使用@RequestMapping注解映射路径,发生对应的路径调用!
  • 异常处理handler方法要@ExceptionHandler映射异常,发生对应的异常会调用!
  • 异常处理handler方法和普通的handler方法参数接收和响应都一致!
  1. 配置文件扫描控制器类配置
    确保异常处理控制类被扫描
 <!-- 扫描controller error对应的包,将handler加入到ioc-->
@ComponentScan({"com.wake.controller","com.wake.error"})

1

  1. 结果 result :
    1
    1

1.3 实战

  • 定义全局异常处理器非常简单,就是定义一个类,在类上加上一个注解@RestControllerAdvice,加上这个注解就代表我们定义了一个全局异常处理器
  • 在全局异常处理器当中,需要定义一个方法来捕获异常,在这个方法上需要加上注解@ExceptionHandler。通过@ExceptionHandler注解当中的value属性来指定我们要捕获的是哪一类型的异常。
    1
@RestControllerAdvice
public class GlobalExceptionHandler {

    //处理异常
    @ExceptionHandler(Exception.class) //指定能够处理的异常类型
    public Result ex(Exception e){
        e.printStackTrace();//打印堆栈中的异常信息

        //捕获到异常之后,响应一个标准的Result
        return Result.error("对不起,操作失败,请联系管理员");
    }
}

@RestControllerAdvice = @ControllerAdvice + @ResponseBody
处理异常的方法返回值会转换为json后再响应给前端

以上就是全局异常处理器的使用,主要涉及到两个注解:

  • @RestControllerAdvice //表示当前类为全局异常处理器
  • @ExceptionHandler //指定可以捕获哪种类型的异常进行处理

二、拦截器使用

2.1 拦截器概念

使用拦截器在请求到达具体 handler 方法前,统一执行检测。
1

2.2 拦截器使用

1

  • 创建拦截器
    • 创建自定义拦截器类 实现 HandlerInterceptor 接口
    • 实现 三个方法 [拦截前 拦截后 整体结束后]
public class MyInterceptor implements HandlerInterceptor {

    // 执行handler方法前 调用拦截方法
    // 编码格式设置,登录保护,权限处理

    /**
     * filter - doFilter
     * @param request 请求对象
     * @param response 响应对象
     * @param handler 这个就是我们要调用的方法对象
     * @return true 放行 ; false 拦截
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("request : " + request + " response : " + response + " handler : " + handler);
        return true;
    }

    /**
     * 当handler执行完毕之后,执行此方法!此时已经没有拦截机制了!
     *
     * 此方法 只有当 preHandle方法 return为TRUE 放行后才会执行
     *
     * 可以对结果进行处理 , 敏感词检测等
     * @param request 请求
     * @param response 响应
     * @param handler 方法
     * @param modelAndView 返回的视图和共享域数据对象
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor.postHandle! handler方法执行完毕!执行此方法!");
    }

    /**
     * 整体处理完毕
     * @param request
     * @param response
     * @param handler
     * @param ex handler报错了 异常对象
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor.afterCompletion! 整体处理完毕!结束!");
    }
}
  • 修改配置类 添加 拦截器
    • 全局拦截
@EnableWebMvc   // HandlerAdapter配置JSON转换器
@Configuration
@ComponentScan({"com.wake.controller","com.wake.error"})
public class MvcConfig implements WebMvcConfigurer {

    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //这个设置是 : 拦截全部请求(默认全拦了)
        registry.addInterceptor(new MyInterceptor());
    }
}

1

2.3 拦截配置细节和源码分析

  • 精准拦截
    • 指定 拦截地址
    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // * 任意一层字符串
        // ** 任意多层字符串
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/error/**");
    }
  • 排除拦截
    • 排除拦截的地址应该在拦截地址的内部
    @Override
    public void addInterceptors(InterceptorRegistry registry) {   
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/error/**").excludePathPatterns("/error/data1");
    }
  • 多个拦截器 先后顺序
    1
    1

三、 参数校验

1

注解规则
@Null标注值必须为 null
@NotNull标注值不可为 null
@AssertTrue标注值必须为 true
@AssertFalse标注值必须为 false
@Min(value)标注值必须大于或等于 value
@Max(value)标注值必须小于或等于 value
@DecimalMin(value)标注值必须大于或等于 value
@DecimalMax(value)标注值必须小于或等于 value
@Size(max,min)标注值大小必须在 max 和 min 限定的范围内
@Digits(integer,fratction)标注值值必须是一个数字,且必须在可接受的范围内
@Past标注值只能用于日期型,且必须是过去的日期
@Future标注值只能用于日期型,且必须是将来的日期
@Pattern(value)标注值必须符合指定的正则表达式
注解规则
@Email标注值必须是格式正确的 Email 地址
@Length标注值字符串大小必须在指定的范围内
@NotEmpty标注值字符串不能是空字符串
@Range标注值必须在指定的范围内

步骤一:实体类中添加校验注解
步骤二:handler(@Validated 实体类 对象)

细节:
param | json 校验注解都有效果
json参数 - @RequestBody

  • 实体类 添加注解校验
/**
 * @Description:
 *  1. name 不为Null 和 空字符串
 *      字符串 @NotBlank
 *      集合 @NotEmpty
 *      包装 @NotNull
 *  2. 长度大于6
 *  3. age  大于 1
 *  4. 邮箱
 *  5. 必须是过去的时间
 */
@Data
public class User {

    @NotBlank
    private String name;

    @Length(min = 6)
    private String password;

    @Min(1)
    private int age;

    @Email
    private String email;

    @Past
    private Date birthday;
}
  • controller handler 方法 设置
@RestController
@RequestMapping("user")
public class UserController {
    /**
     * 接收用户数据,用户有检验注解
     * @param user
     * @param result
     * @return
     */
    @PostMapping("register")
    public Object register(@Validated @RequestBody User user, BindingResult result){
        if (result.hasErrors()){
            HashMap data = new HashMap();
            data.put("code",400);
            data.put("msg","参数校验异常!");
            return data;
        }
        System.out.println("user : " + user);
        return user;
    }
}

如果不符合校验规则,会直接向前端发出异常。

所以,需要添加 BindingResult result 参数。
来接收错误绑定信息,自定义返回结果。

约定:参数错误 -> {code : 400} -> 前端

细节:
handler(校验对象,BindingResult result)
要求:BindingResult 需要紧挨着校验对象,中间插入一个参数就会失效。

结果:

  • 符合校验格式:成功
    1
  • 不符合校验格式
    1

总结

核心点掌握目标
springmvc框架主要作用、核心组件、调用流程
简化参数接收路径设计、参数接收、请求头接收、cookie接收
简化数据响应模板页面、转发和重定向、JSON数据、静态资源
restful风格设计主要作用、具体规范、请求方式和请求参数选择
功能扩展全局异常处理、拦截器、参数校验注解

拦截器 Springmvc VS 过滤器 javaWeb:

1

  • 相似点
    • 拦截:必须先把请求拦住,才能执行后续操作
    • 过滤:拦截器或过滤器存在的意义就是对请求进行统一处理
    • 放行:对请求执行了必要操作后,放请求过去,让它访问原本想要访问的资源
  • 不同点
    • 工作平台不同
      • 过滤器工作在 Servlet 容器中
      • 拦截器工作在 SpringMVC 的基础上
    • 拦截的范围
      • 过滤器:能够拦截到的最大范围是整个 Web 应用
      • 拦截器:能够拦截到的最大范围是整个 SpringMVC 负责的请求
    • IOC 容器支持
      • 过滤器:想得到 IOC 容器需要调用专门的工具方法,是间接的
      • 拦截器:它自己就在 IOC 容器中,所以可以直接从 IOC 容器中装配组件,也就是可以直接得到 IOC 容器的支持

选择:

功能需要如果用 SpringMVC 的拦截器能够实现,就不使用过滤器。

多个拦截器执行顺序

  1. preHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置顺序调用各个 preHandle() 方法。
  2. postHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置相反的顺序调用各个 postHandle() 方法。
  3. afterCompletion() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置相反的顺序调用各个 afterCompletion() 方法。

1

@Length注解 不成功

导入hibernate依赖:

    <dependency>
      <groupId>org.hibernate.validator</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>8.0.1.Final</version>
    </dependency>
  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道格维克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值