SpringMVC其他扩展

一、全局异常处理机制:

1.异常处理两种方式:

开发过程中是不可避免地会出现各种异常情况的,例如网络连接异常、数据格式异常、空指针异常等等。异常的出现可能导致程序的运行出现问题,甚至直接导致程序崩溃。因此,在开发过程中,合理处理异常、避免异常产生、以及对异常进行有效的调试是非常重要的。

对于异常的处理,一般分为两种方式:

(1).编程式异常处理:是指在代码中显式地编写处理异常的逻辑。它通常涉及到对异常类型的检测及其处理,例如使用try-catch块来捕获异常,然后在catch块中编写特定的处理代码,或者在finally块中执行一些清理操作。在编程式异常处理中,开发人员需要显式地进行异常处理,异常处理代码混杂在业务代码中,导致代码可读性较差。

(2).声明式异常处理:则是将异常处理的逻辑从具体的业务逻辑中分离出来,通过配置等方式进行统一的管理和处理。在声明式异常处理中,开发人员只需要为方法或类标注相应的注解(如@Throws或@ExceptionHandler),就可以处理特定类型的异常。相较于编程式异常处理,声明式异常处理可以使代码更加简洁、易于维护和扩展。

站在宏观角度来看待声明式事务处理:整个项目从架构这个层面设计的异常处理的统一机制和规范。一个项目中会包含很多个模块,各个模块需要分工完成。如果张三负责的模块按照 A 方案处理异常,李四负责的模块按照 B 方案处理异常……各个模块处理异常的思路、代码、命名细节都不一样,那么就会让整个项目非常混乱。使用声明式异常处理,可以统一项目处理异常思路,项目更加清晰明了

2.基于注解异常声明异常处理:

(1).声明异常处理控制器类:

异常处理控制类,统一定义异常处理handler方法

/**
 * projectName: com.atguigu.execptionhandler
 * 
 * description: 全局异常处理器,内部可以定义异常处理Handler!
 */

/**
 * @RestControllerAdvice = @ControllerAdvice + @ResponseBody
 * @ControllerAdvice 代表当前类的异常处理controller! 
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

  
}

(2).声明异常处理hander方法:

异常处理handler方法和普通的handler方法参数接收和响应都一致

只不过异常处理handler方法要映射异常,发生对应的异常会调用

普通的handler方法要使用@RequestMapping注解映射路径,发生对应的路径调用

/**
 * 异常处理handler 
 * @ExceptionHandler(HttpMessageNotReadableException.class) 
 * 该注解标记异常处理Handler,并且指定发生异常调用该方法!
 * 
 * 
 * @param e 获取异常对象!
 * @return 返回handler处理结果!
 */
@ExceptionHandler(HttpMessageNotReadableException.class)
public Object handlerJsonDateException(HttpMessageNotReadableException e){
    
    return null;
}

/**
 * 当发生空指针异常会触发此方法!
 * @param e
 * @return
 */
@ExceptionHandler(NullPointerException.class)
public Object handlerNullException(NullPointerException e){

    return null;
}

/**
 * 所有异常都会触发此方法!但是如果有具体的异常处理Handler! 
 * 具体异常处理Handler优先级更高!
 * 例如: 发生NullPointerException异常!
 *       会触发handlerNullException方法,不会触发handlerException方法!
 * @param e
 * @return
 */
@ExceptionHandler(Exception.class)
public Object handlerException(Exception e){

    return null;
}

(3).配置文件扫描控制器类配置:

确保异常处理控制类被扫描

 <!-- 扫描controller对应的包,将handler加入到ioc-->
 @ComponentScan(basePackages = {"com.atguigu.controller",
 "com.atguigu.exceptionhandler"})

二、拦截器的使用:

1.拦截器的概念:拦截器和过滤器解决问题

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

拦截器Springmvc VS 过滤器javaWeb:

(1).相似点:

a.拦截:必须先把请求拦住,才能执行后续操作

b.过滤:拦截器或过滤器存在的意义就是对请求进行统一处理

c.放行:对请求执行了必要操作后,放请求过去,让它访问原本想要访问的资源

(2).不同点:

a.工作平台不同:

过滤器工作在Servlet容器中

拦截器工作在SpringMVC的基础上

b.拦截的范围:

过滤器能够拦截到的最大范围是整个Web应用

拦截器能够拦截到的最大范围是整个SpringMVC负责的请求

c.IOC容器支持:

过滤器想得到IOC容器需要调用专门的工具方法,是间接的

拦截器它自己就在IOC容器中,所以可以直接从IOC容器中装配组件,也就是可以直接得到IOC容器的支持

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

2.拦截器的使用:

(1).创建拦截器类:

public class Process01Interceptor implements HandlerInterceptor {

    // if( ! preHandler()){return;}
    // 在处理请求的目标 handler 方法前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("request = " + request + ", response = " + response + ", handler = " + handler);
        System.out.println("Process01Interceptor.preHandle");
         
        // 返回true:放行
        // 返回false:不放行
        return true;
    }
 
    // 在目标 handler 方法之后,handler报错不执行!
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("request = " + request + ", response = " + response + ", handler = " + handler + ", modelAndView = " + modelAndView);
        System.out.println("Process01Interceptor.postHandle");
    }
 
    // 渲染视图之后执行(最后),一定执行!
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("request = " + request + ", response = " + response + ", handler = " + handler + ", ex = " + ex);
        System.out.println("Process01Interceptor.afterCompletion");
    }
}

拦截器方法拦截位置:

(2).修改配置类添加拦截器:

@EnableWebMvc  //json数据处理,必须使用此注解,因为他会加入json处理器
@Configuration
@ComponentScan(basePackages = {"com.atguigu.controller","com.atguigu.exceptionhandler"}) //TODO: 进行controller扫描
//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {

    //配置jsp对应的视图解析器
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        //快速配置jsp模板语言对应的
        registry.jsp("/WEB-INF/views/",".jsp");
    }

    //开启静态资源处理 <mvc:default-servlet-handler/>
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    //添加拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) { 
        //将拦截器添加到Springmvc环境,默认拦截所有Springmvc分发的请求
        registry.addInterceptor(new Process01Interceptor());
    }
}

(3).修改配置:

a.默认拦截全部:

@Override
public void addInterceptors(InterceptorRegistry registry) {
    //将拦截器添加到Springmvc环境,默认拦截所有Springmvc分发的请求
    registry.addInterceptor(new Process01Interceptor());
}

b.精准配置:

@Override
public void addInterceptors(InterceptorRegistry registry) {
    
    //将拦截器添加到Springmvc环境,默认拦截所有Springmvc分发的请求
    registry.addInterceptor(new Process01Interceptor());
    
    //精准匹配,设置拦截器处理指定请求 路径可以设置一个或者多个,为项目下路径即可
    //addPathPatterns("/common/request/one") 添加拦截路径
    //也支持 /* 和 /** 模糊路径。 * 任意一层字符串 ** 任意层 任意字符串
    registry.addInterceptor(new Process01Interceptor()).addPathPatterns("/common/request/one","/common/request/tow");
}

c.排除配置:

//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
    
    //将拦截器添加到Springmvc环境,默认拦截所有Springmvc分发的请求
    registry.addInterceptor(new Process01Interceptor());
    
    //精准匹配,设置拦截器处理指定请求 路径可以设置一个或者多个,为项目下路径即可
    //addPathPatterns("/common/request/one") 添加拦截路径
    registry.addInterceptor(new Process01Interceptor()).addPathPatterns("/common/request/one","/common/request/tow");
    
    
    //排除匹配,排除应该在匹配的范围内排除
    //addPathPatterns("/common/request/one") 添加拦截路径
    //excludePathPatterns("/common/request/tow"); 排除路径,排除应该在拦截的范围内
    registry.addInterceptor(new Process01Interceptor())
            .addPathPatterns("/common/request/one","/common/request/tow")
            .excludePathPatterns("/common/request/tow");
}

(4).多个拦截器执行顺序:

a.preHandle()方法:SpringMVC会把所有拦截器收集到一起,然后按照配置顺序调用各个 preHandle()方法。

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

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

三、参数校验:

在Web应用三层架构体系中,表述层负责接收浏览器提交的数据,业务逻辑层负责数据的处理。为了能够让业务逻辑层基于正确的数据进行处理,我们需要在表述层对数据进行检查,将错误的数据隔绝在业务逻辑层之外

1.校验概述:

JSR 303是Java为Bean数据合法性校验提供的标准框架,它已经包含在JavaEE 6.0标准中。JSR 303通过在Bean属性上标注类似于@NotNull、@Max等标准的注解指定校验规则,并通过标准的验证接口对Bean进行验证

注解规则
@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)标注值必须符合指定的正则表达式

JSR 303只是一套标准,需要提供其实现才可以使用。Hibernate Validator是JSR 303的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解:

注解规则
@Email标注值必须是格式正确的 Email 地址
@Length标注值字符串大小必须在指定的范围内
@NotEmpty标注值字符串不能是空字符串
@Range标注值必须在指定的范围内

Spring 4.0版本已经拥有自己独立的数据校验框架,同时支持JSR 303标准的校验框架。Spring在进行数据绑定时,可同时调用校验框架完成数据校验工作。在SpringMVC 中,可直接通过注解驱动@EnableWebMvc的方式进行数据校验。Spring 的LocalValidatorFactoryBean既实现了Spring 的Validator接口,也实现了JSR 303的Validator接口。只要在Spring容器中定义了一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的Bean中。Spring本身并没有提供JSR 303的实现,所以必须将JSR 303的实现者的jar包放到类路径下。

配置@EnableWebMvc后,SpringMVC会默认装配好一个LocalValidatorFactoryBean,通过在处理方法的入参上标注@Validated注解即可让SpringMVC在完成数据绑定后执行数据校验的工作。

2.操作演示:

导入依赖:

<!-- 校验注解 -->
<dependency>
    <groupId>jakarta.platform</groupId>
    <artifactId>jakarta.jakartaee-web-api</artifactId>
    <version>9.1.0</version>
    <scope>provided</scope>
</dependency>
        
<!-- 校验注解实现-->        
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>8.0.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-annotation-processor</artifactId>
    <version>8.0.0.Final</version>
</dependency>

应用校验注解:

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Min;
import org.hibernate.validator.constraints.Length;

/**
 * projectName: com.atguigu.pojo
 */
public class User {
    //age   1 <=  age < = 150
    @Min(10)
    private int age;

    //name 3 <= name.length <= 6
    @Length(min = 3,max = 10)
    private String name;

    //email 邮箱格式
    @Email
    private String email;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

handler标记和绑定错误收集:

@RestController
@RequestMapping("user")
public class UserController {

    /**
     * @Validated 代表应用校验注解! 必须添加!
     */
    @PostMapping("save")
    public Object save(@Validated @RequestBody User user,
                       //在实体类参数和 BindingResult 之间不能有任何其他参数, BindingResult可以接受错误信息,避免信息抛出!
                       BindingResult result){
       //判断是否有信息绑定错误! 有可以自行处理!
        if (result.hasErrors()){
            System.out.println("错误");
            String errorMsg = result.getFieldError().toString();
            return errorMsg;
        }
        //没有,正常处理业务即可
        System.out.println("正常");
        return user;
    }
}

测试效果:

3.易混总结:

@NotNull、@NotEmpty、@NotBlank都是用于在数据校验中检查字段值是否为空的注解,但是它们的用法和校验规则有所不同。

(1).@NotNull(包装类型不为null)

@NotNull注解是JSR 303规范中定义的注解,当被标注的字段值为null时,会认为校验失败而抛出异常。该注解不能用于字符串类型的校验,若要对字符串进行校验,应该使用@NotBlank或 @NotEmpty注解。

(2).@NotEmpty(集合类型长度大于0)

@NotEmpty注解同样是JSR 303规范中定义的注解,对于CharSequence、Collection、Map或者数组对象类型的属性进行校验,校验时会检查该属性是否为Null或者size()==0,如果是的话就会校验失败。但是对于其他类型的属性,该注解无效。需要注意的是只校验空格前后的字符串,如果该字符串中间只有空格,不会被认为是空字符串,校验不会失败。

(3).@NotBlank(字符串,不为null,不为"  "字符串)

@NotBlank注解是Hibernate Validator附加的注解,对于字符串类型的属性进行校验,校验时会检查该属性是否为Null或“”或者只包含空格,如果是的话就会校验失败。需要注意的是,@NotBlank 注解只能用于字符串类型的校验。

总之,这三种注解都是用于校验字段值是否为空的注解,但是其校验规则和用法有所不同。在进行数据校验时,需要根据具体情况选择合适的注解进行校验。

SpringMVC总结:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/929644.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Cesium 6 ,Cesium 全局注册,Cesium 常用事件解析与应用,全局注册Cesium事件

目录 前言 一. 全局注册事件 1.1 事件机制介绍 1.2 this.Cesium 和 this.viewer 1.3 全局注册 二. 常见事件分类 2.1 鼠标事件 2.1.1 点击事件 (click) 2.1.2 双击事件 (doubleClick) 2.1.3 鼠标移动事件 (mouseMove) 2.1.4 鼠标滚轮事件 (mouseWheel) 2.2 视图与摄…

matlab2024a安装

1.开始安装 2.点击安装 3.选择安装密钥 4.接受条款 5.安装密钥 21471-07182-41807-00726-32378-34241-61866-60308-44209-03650-51035-48216-24734-36781-57695-35731-64525-44540-57877-31100-06573-50736-60034-42697-39512-63953 6 7.选择许可证文件 8.找许可证文件 9.选…

在玩“吃鸡”的时候游戏崩溃要如何解决?游戏运行时崩溃是什么原因?

“吃鸡”游戏崩溃问题深度解析与解决方案&#xff1a;原因、修复与预防 在紧张刺激的“吃鸡”&#xff08;即《绝地求生》&#xff09;游戏中&#xff0c;突然遭遇游戏崩溃无疑会让玩家倍感沮丧。作为一名经验丰富的软件开发从业者&#xff0c;我深知游戏崩溃可能由多种因素引…

学习threejs,通过设置纹理属性来修改纹理贴图的位置和大小

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️Texture 贴图 二、&#x1…

【开源安全保护】如何安装JumpServer堡垒机

【开源安全保护】如何安装JumpServer堡垒机 什么是堡垒机 大家好&#xff0c;我是星哥&#xff0c;今天我以前来认识堡垒机 堡垒机&#xff08;Bastion Host&#xff09;&#xff0c;也称为跳板机&#xff08;Jump Server&#xff09;&#xff0c;是指在计算机网络中&#x…

JSP知识点总结

jsp九大对象 在jsp中内置了9个对象&#xff0c;无需创建该对象即可使用。其名称为固定名称。 1.out输出对象 - 属于JspWriter print(): 输出 flush(): 刷新 close(): 关闭 2.request请求对象 - 属于HttpServletRequest getParameter(): 获取请求的参数 setCharacterEncodin…

微信小程序全屏显示地图

微信小程序在界面上显示地图&#xff0c;只需要用map标签 <map longitude"经度度数" latitude"纬度度数"></map>例如北京的经纬度为&#xff1a;116.407004,39.904595 <map class"bgMap" longitude"116.407004" lati…

(软件测试文档大全)测试计划,测试报告,测试方案,压力测试报告,性能测试,等保测评,安全扫描测试,日常运维检查测试,功能测试等全下载

1. 引言 1.1. 编写目的 1.2. 项目背景 1.3. 读者对象 1.4. 参考资料 1.5. 术语与缩略语 2. 测试策略 2.1. 测试完成标准 2.2. 测试类型 2.2.1. 功能测试 2.2.2. 性能测试 2.2.3. 安全性与访问控制测试 2.3. 测试工具 3. 测试技术 4. 测试资源 4.1. 人员安排 4.2. 测试环境 4.2.…

2024 阿里云Debian12.8安装apach2【图文讲解】

1. 更新系统&#xff0c;确保您的系统软件包是最新的 sudo apt update sudo apt upgrade -y 2. 安装 Apache Web 服务器 apt install apache2 -y 3. 安装 PHP 及常用的扩展 apt install php libapache2-mod-php -y apt install php-mysql php-xml php-mbstring php-curl php…

golang实现单例日志对象

原文地址&#xff1a;golang实现单例日志对象 – 无敌牛 欢迎参观我的个人博客&#xff1a;无敌牛 – 技术/著作/典籍/分享等 介绍 golang有很多日志包&#xff0c;通过设置和修改都能实现日志轮转和自定义日志格式。例如&#xff1a;log、zap、golog、slog、log4go 等等。 …

git回退到某个版本git checkout和git reset命令的区别

文章目录 1. git checkout <commit>2. git reset --hard <commit>两者的区别总结推荐使用场景* 在使用 Git 回退到某个版本时&#xff0c; git checkout <commit> 和 git reset --hard <commit> 是两种常见的方式&#xff0c;但它们的用途和影响有很…

Spring Boot + MySQL 多线程查询与联表查询性能对比分析

Spring Boot MySQL: 多线程查询与联表查询性能对比分析 背景 在现代 Web 应用开发中&#xff0c;数据库性能是影响系统响应时间和用户体验的关键因素之一。随着业务需求的不断增长&#xff0c;单表查询和联表查询的效率问题日益凸显。特别是在 Spring Boot 项目中&#xff0…

人工智能学习用的电脑安装cuda、torch、conda等软件,版本的选择以及多版本切换

接触人工智能的学习三个月了&#xff0c;每天与各种安装包作斗争&#xff0c;缺少依赖包、版本高了、版本低了、不兼容了、系统做一半从头再来了。。。这些都是常态。三个月把单位几台电脑折腾了不下几十次安装&#xff0c;是时候总结一下踩过的坑和积累的经验了。 以一个典型的…

Vue工程化开发中各文件的作用

1.main.js文件 main.js文件的主要作用&#xff1a;导入App.vue&#xff0c;基于App.vue创建结构渲染index.html。

本地运行打包好的dist

首先输入打包命令 每个人设置不一样 一般人 是npm run build如果不知道可以去package.json里去看。 打包好文件如下 命令行输入 :npm i -g http-server 进入到dist目录下输入 命令cmd 输入 http-server 成功

华为HCIE-Datacom认证笔试+实验考试介绍

华为HCIE数通认证考试是面向那些希望成为数通网络领域专家的人员&#xff0c;考试通常两部分&#xff1a;笔试和实验考试。 考试科目&#xff1a; HCIE-Datacom笔试考试内容&#xff1a; HCIE-Datacom V1.0考试覆盖数据通信领域路由交换高阶技术、企业网络架构全景、园区网络…

【组件封装】uniapp vue3 封装一个完整的Tabs(标签页)组件教程,功能由简到杂实现讲解。

文章目录 前言一、简单版Tabs代码实现&#xff1a; 二、下划线带动画的TabsAPI回顾&#xff1a;代码实现&#xff1a; 三、内容区域滑动切换切换动画代码实现&#xff1a;&#xff08;2&#xff09;禁用手势滑动切换&#xff08;3&#xff09;内容区域换为插槽 四、标签栏可滚动…

相对路径和绝对路径与链接标签

一.相对路径 相对路径&#xff1a;以引用文件所在位置为参考基础&#xff0c;而建立出的目录路径。 即图片相对于你写的html页面的位置 相对路径分类符号说明同一级路径图片与html文件处于同一级&#xff0c;如<img src"baidu.gif">下一级路径/图片位于html…

【Java】Switch语句、循环语句(for、while、do...while)

Switch语句&#xff1a;针对某个表达式的值进行判断&#xff0c;从而决定执行哪一段代码 语法格式&#xff1a; switch(表达式){ case 目标值1: 执行语句1 break; case 目标值2: …

P3916 图的遍历(Tarjan缩点和反向建边)

P3916 图的遍历 - 洛谷 | 计算机科学教育新生态 写法一&#xff1a;Tarjan 思路&#xff1a;先运用Tarjan算法得到每个连通块中最大的编号&#xff0c;然后对每个连通块进行缩点重新建图&#xff0c;进行dfs&#xff0c;得到缩点后的连通块能够达到的最大编号。 Code: conste…