SpringMVC(2)

目录

  • SSM整合
    • 统一异常处理
    • 项目异常处理方案
    • 异常解决方案
    • 前后端协议联调
    • 拦截器

SSM整合

统一异常处理

  • 异常的种类及出现异常的原因:

    • 框架内部抛出的异常:因使用不合规导致
    • 数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)
    • 业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)
    • 表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
    • 工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)
  • 各个层级均出现异常,异常处理代码写在哪一层

    • 所有的异常均抛出到表现层进行处理
  • 异常的种类很多,表现层如何将所有的异常都处理到呢?

    • 异常分类
  • 表现层处理异常,每个方法中单独书写,代码书写量巨大且意义不强,如何解决?

    • AOP

  • 异常处理器 : 集中统一的处理项目中出现的异常
//@RestControllerAdvice用于标识当前类为REST风格对应的异常处理器
@RestControllerAdvice
public class ProjectExceptionAdvice {//除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常@ExceptionHandler(Exception.class)public void doException(Exception ex){System.out.println("嘿嘿,异常你哪里跑!")}
}

项目异常处理方案

  • 项目异常分类
    • 业务异常(BusinessException)

      • 规范的用户行为产生的异常
        • 用户在页面输入内容的时候未按照指定格式进行数据填写,如在年龄框输入的是字符串
      • 不规范的用户行为产生的异常
        • 用户故意传递错误数据
    • 系统异常(SystemException)

      • 项目运行过程中可预计但无法避免的异常
        • 比如数据库或服务器宕机
    • 其他异常(Exception)

      • 编程人员未预期到的异常,如:用到的文件不存在

异常解决方案

  • 业务异常(BusinessException)
    • 发送对应消息传递给用户,提醒规范操作
      • 大家常见的就是提示用户名已存在或密码格式不正确等
  • 系统异常(SystemException)
    • 发送固定消息传递给用户,安抚用户
      • 系统繁忙,请稍后再试
      • 系统正在维护升级,请稍后再试
      • 系统出问题,请联系系统管理员等
    • 发送特定消息给运维人员,提醒维护
      • 可以发送短信、邮箱或者是公司内部通信软件
    • 记录日志
      • 发消息和记录日志对用户来说是不可见的,属于后台程序
  • 其他异常(Exception)
    • 发送固定消息传递给用户,安抚用户
    • 发送特定消息给编程人员,提醒维护(纳入预期范围内)
      • 一般是程序没有考虑全,比如未做非空校验等
    • 记录日志

前后端协议联调

  • 添加了静态资源,SpringMVC会拦截,所有需要在SpringConfig的配置类中将静态资源进行放行。
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");registry.addResourceHandler("/css/**").addResourceLocations("/css/");registry.addResourceHandler("/js/**").addResourceLocations("/js/");registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");}
}
在SpringMvcConfig中扫描SpringMvcSupport
@Configuration
@ComponentScan({"com.itheima.controller","com.itheima.config"})
@EnableWebMvc
public class SpringMvcConfig {
}
  • 异步请求
    在这里插入图片描述
<script>var vue = new Vue({el: '#app',data:{pagination: {},dataList: [],//当前页要展示的列表数据formData: {},//表单数据dialogFormVisible: false,//控制表单是否可见dialogFormVisible4Edit:false,//编辑表单是否可见rules: {//校验规则type: [{ required: true, message: '图书类别为必填项', trigger: 'blur' }],name: [{ required: true, message: '图书名称为必填项', trigger: 'blur' }]}},//钩子函数,VUE对象初始化完成后自动执行created() {this.getAll();},methods: {//列表getAll() {// 发送 ajax 请求axios.get("/books").then((res) => {this.dataList = res.data.data;});},//弹出添加窗口handleCreate() {this.dialogFormVisible = true;this.resetForm();},//重置表单resetForm() {this.formData = {};},//添加handleAdd () {axios.post("/books",this.formData).then((res)=>{console.log(res.data);// 如果操作成功,关闭弹层,显示数据if (res.data.code == 20011) {this.dialogFormVisible = false;this.$message.success("添加成功");} else if (res.data.code == 20010) {this.$message.error("添加失败");} else {this.$message.error(res.data.msg);}}).finally(()=>{this.getAll();});},//弹出编辑窗口handleUpdate(row) {// console.log(row);// 根据 id 查询数据// 展示弹层,加载数据axios.get("/books/" + row.id).then((res) => {// console.log(res.data.data);if (res.data.code == 20041) {this.formData = res.data.data;this.dialogFormVisible4Edit = true;} else {this.$message.error(res.data.msg);}})},//编辑handleEdit() {axios.put("/books",this.formData).then((res)=>{// 如果操作成功,关闭弹层,显示数据if (res.data.code == 20031) {this.dialogFormVisible4Edit = false;this.$message.success("编辑成功");} else if (res.data.code == 20030) {this.$message.error("编辑失败");} else {this.$message.error(res.data.msg);}}).finally(()=>{this.getAll();});},// 删除handleDelete(row) {// 1. 弹出提示框this.$confirm("此操作永久删除当前数据,是否继续","提示",{type:'info'}).then(()=>{// 2. 做删除业务axios.delete("/books/" + row.id).then((res) => {if (res.data.code == 20021) {this.$message.success("删除成功");} else {this.$message.error("删除失败");}}).finally(()=>{this.getAll();});}).catch(()=>{// 3. 取消删除操作this.$message.info("取消删除操作");});}}})</script>

拦截器

在这里插入图片描述

  • 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行

  • 作用:

    • 在指定的方法调用前后执行预先设定的代码
    • 阻止原始方法的执行
    • 总结:拦截器就是用来做增强
  • 拦截器和过滤器的区别

    • 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
    • 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
  • 让类实现HandlerInterceptor接口,重写接口中的三个方法。

@Component
//定义拦截器类,实现HandlerInterceptor接口
//注意当前类必须受Spring容器控制
public class ProjectInterceptor implements HandlerInterceptor {@Override//原始方法调用前执行的内容public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle...");return true;}@Override//原始方法调用后执行的内容public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...");}@Override//原始方法调用完成后执行的内容public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...");}
}

注意:拦截器类要被SpringMVC容器扫描到。

  • 配置拦截器类
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Autowiredprivate ProjectInterceptor projectInterceptor;@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");}@Overrideprotected void addInterceptors(InterceptorRegistry registry) {//配置拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books" );}
}
  • SpringMVC添加SpringMvcSupport包扫描
@Configuration
@ComponentScan({"com.itheima.controller","com.itheima.config"})
@EnableWebMvc
public class SpringMvcConfig{}
  • 拦截器的访问路径可以通过可变参数设置多个

  • 最后说一件事,就是拦截器中的preHandler方法,如果返回true,则代表放行,会执行原始Controller类中要请求的方法,如果返回false,则代表拦截,后面的就不会再执行了。

  • 使用标准接口 WebMvcConfigurer 简化开发(侵入式较强)

@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {@Autowiredprivate ProjectInterceptor projectInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//配置多拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");}
}

在这里插入图片描述

  • 拦截器参数

    • handler: 被调用的处理器对象,本质上是一个方法对象,对反射中的Method对象进行了再包装
    • modelAndView: 如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整
    • ex: 如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理
  • 拦截器执行的顺序是和配置顺序有关。就和前面所提到的运维人员进入机房的案例,先进后出。

    • 当配置多个拦截器时,形成拦截器链
    • 拦截器链的运行顺序参照拦截器添加顺序为准
    • 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
    • 当拦截器运行中断,仅运行配置在前面的拦截器的 afterCompletion 操作

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

疫情物资智能管理:Java与SpringBoot的实践

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

如何进行写作的刻意练习

写作从来不可能一蹴而就&#xff0c;而是一件需要我们持续坚持、努力的事情。 人如果没有目标就会迷失方向&#xff0c; 既然需要长期的坚持&#xff0c;就需要我们根据自身情况制定每一阶段的目标。 目标的制定要清晰可达&#xff0c;不能模棱两可&#xff0c;要认证对待。 …

Py2neo查询neo4j周杰伦数据库中的节点、关系和路径教程

文章目录 py2neo介绍连接Neo4j数据库py2neo查询图数据库neo4j数据概览使用NodeMatcher查询节点使用RelationshipMatcher查询关系 通过执行Cypher语句查询 py2neo介绍 Neo4j是一款开源图数据库&#xff0c;Py2neo提供了使用Python语言访问Neo4j的接口。本文介绍了使用Py2neo的N…

Python学习 day05(异常、模块导入、包)

异常 为什么要捕获异常 当程序遇到了BUG&#xff0c;如果不对BUG进行手动捕获&#xff0c;那么整个程序就会因为一个BUG而停止运行&#xff0c;这在有些情况下是会造成很大的损失&#xff0c;但是如果我们进行了手动捕获&#xff0c;那么整个程序会继续运行捕获异常的作用在于&…

第三百七十二回

文章目录 1. 概念介绍2. 实现方法2.1 maskFilter2.2 shader 3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"两种阴影效果"相关的内容&#xff0c;本章回中将介绍如何绘制阴影效果.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概…

分布式存储 ZBS 的 RoCE 技术支持与大数据应用场景性能评测

作者&#xff1a;深耕行业的 SmartX 金融团队 闫海涛 在《解决 SAN 交换机“卡脖子”并升级存储架构&#xff1f;一文解析 RoCE 与相关存储方案趋势》文章中&#xff0c;我们分析了如何利用支持 RoCE 技术的分布式存储&#xff0c;同步实现 IT 基础架构的信创转型与架构升级&a…

Soul App发布春节特产社交报告,全面解析当代年轻人的社交新趋势

近日,社交平台Soul App发布了《2024年春节“特产社交”趋势洞察报告》,深入剖析了年轻用户在春节期间的特产消费新习惯和社交新方式。这份报告基于平台内容和2395份调研样本,重点关注18-34岁用户群体,特别是00后用户,为我们呈现了一系列有趣的趋势。 年轻人的过年选择:看世界,却…

数据结构系列-通讯录项目

&#x1f308;个人主页: 会编辑的果子君 &#x1f4ab;个人格言:“成为自己未来的主人~” #pragma once#define NAME_MAX 100 #define GENDER_MAX 10 #define TEL_MAX 12 #define ADDR_MAX 100//通讯录数据类型 typedef struct PersonInfo {char name[NAME_MAX];int age;cha…

修改Qt生成iOS应用的原生底层,编译QtBase下的ios子模块

1.下载Qt源码 2.找到ios.pro子工程 3.使用QtCreaor12打开ios.pro工程 4.出现工程下只有一个.pro文件解决 复制修改好的toolchain.prf文件进行替换. 修改方法:

更改elementui的箭头图片以及位置

//更改箭头位置 .el-tree-node__content > .el-tree-node__expand-icon {position: absolute;right: 12px; }//更改箭头图片 .el-tree-node__expand-icon {transform: rotate(-90deg); } .el-tree-node__expand-icon.expanded {transform: rotate(0deg); } // 有子节点 且已…

协议-http协议-基础概念01-发展历程-http组成-http是什么-相关的应用-相关的协议

发展历程-http组成-http是什么-相关的应用-相关的协议 参考来源&#xff1a; 极客时间-透视HTTP协议(作者&#xff1a;罗剑锋)&#xff1b; 01-HTTP的发展历程 1989 年&#xff0c;任职于欧洲核子研究中心&#xff08;CERN&#xff09;的蒂姆伯纳斯 - 李&#xff08;Tim Ber…

【C++】类和对象之常引用与运算符重载

个人主页 &#xff1a; zxctscl 文章封面来自&#xff1a;艺术家–贤海林 如有转载请先通知 文章目录 1. 前言2. 常引用3. 运算符重载 1. 前言 在之前的文章中提到了常引用&#xff0c;再来看运算符重载之前&#xff0c;先来看看常引用的使用。 2. 常引用 在使用引用的时候可…