SpringMvcの拦截器全局异常处理
一、拦截器
我们在网上发贴子的时候如果没有登录,点击发送按钮会提示未进行登录,跳转到登录页面。这样的功能是如何实现的。
1、 拦截器的作用
Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。 用户可以自己定义一些拦截器来实现特定的功能。拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器和过滤器的区别:过滤器是servlet规范中的一部分,任何java web工程都可以使用。 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。 过滤器在url-pattern中配置了"/*"之后,可以对所有要访问的资源拦截。 拦截器它是只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或者js是不会进行拦截的。 它也是AOP思想的具体应用。
2、拦截器使用步骤
-
自定义类 implements HandlerInterceptor
-
重写拦截器接口三个方法
/*** 实现拦截器的步骤:* 1. 自定义类实现拦截器接口* 2. 重写接口所有方法* 弄清楚重写三个方法执行顺序【拦截器执行流程】* 3. springmvc配置类:配置拦截器,指定拦截策略*/ @Component public class MyInterceptor implements HandlerInterceptor {/*** 请求到达控制器之间,就会进入preHandle,这个方法如果返回值true,请求就进入控制器执行,* 返回值false,请求就不会进入控制器执行,直接返回,页面就没有控制器查询结果* 几乎大部分功能,我们都是借助preHandle处理。*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle执行了....");return true;//不放行请求}/*** postHandle在控制器执行完毕,进入jsp之前*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle执行了....");}/*** afterCompletion:jsp渲染完毕,在浏览器看到数据之前*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion执行了....");} } -
sprinmvc的配置类:配置拦截器拦截策略,
/*** 配置自定义拦截器,使自己拦截器的代码可以工作* 基于上面方法已经配置不拦截所有的静态资源,springmvc只拦截去控制器的请求,不拦截静态资源* @param registry 注册中心*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/**") //拦截的url地址配置 拦截多级目录,比如:/building/list /edit}
注意:拦截器拦截的是controller请求,所以只有提交请求到controller中时才会进行拦截
HelloController.java编写控制器代码
@Controller
public class HelloController {@RequestMapping("/hello") //任意类型的请求list都可以public String hello(){System.out.println("Controller接收到客户端发送的请求并处理");return "hello";}
}
-hello.jsp编写jsp代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head><body>
<h1>ooooooooooooooooooooooooooooooooooooook</h1>
<%System.out.println("hello.jsp代码执行了");
%>
</body>
</html>
-
启动服务器,在浏览器输入以下地址
http://localhost:8989/hello,控制台输出以下结果preHandle执行了…
Controller接收到客户端发送的请求并处理
postHandle执行了…
hello.jsp代码执行了
afterCompletion执行了…
根据输出结果我们可以得出以下结论:所有的发给控制器的请求都会先进入preHandle方法进行处理,preHandle返回true,请求才会被放行到Controller执行,控制器Controller代码执行完毕后再次进入拦截器执行postHandle,执行完毕后才能进入JSP执行代码,而JSP代码执行完毕后,请求会再一次进入afterCompletion执行,最终响应处理完毕,浏览器看到响应结果。图解如下:
3、案例:利用拦截器完成用户登录认证
案例:使用拦截器处理登录认证,登录成功,可以进入主页;没有登录过,直接导向到login.html进行登录
创建自定义拦截器,验证用户登录情况
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle执行了....");if (request.getSession().getAttribute("loginUser") != null) {//登录过return true;//true放行 false:不放行}//没有登录,则响应错误消息码,便于判断后进入登录页面response.getWriter().write(new ObjectMapper().writeValueAsString(new ResponseResult<>(401, "尚未登录,请先登录")));return false;
}
在springmvc配置类中注册自定义拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/**") //拦截的url地址配置 拦截多级目录,比如:/building/list /edit.excludePathPatterns("/user/dologin");//排除不需要拦截的url地址,不能拦截处理登录的控制器
}
building-list.html发起请求测试拦截器
//查询所有的楼栋分类信息
loadAllTypes(){axios.get("/type/list",{params:{}}).then(resp=>{if(resp.data.status===200){//请求处理成功的码this.types=resp.data.data;}else if(resp.data.status===401){ //尚未登录this.$message({message: resp.data.msg,type: 'warning'});setTimeout(()=>{window.parent.location.href="/login.html";},1000);}else{ //其他错误情况,直接弹窗提示消息this.$message({message: resp.data.msg,type: 'error'});}})
},
登录页面代码略
登录控制器代码:使用session保存登录结果
@PostMapping("/dologin")
@ResponseBody
public ResponseResult<User> doLogin(@RequestBody User user, HttpSession session){System.out.println(user);try {User loginUser = userService.doLogin(user.getPhone(), user.getPassword());//session保存session.setAttribute("loginUser",loginUser);return new ResponseResult<User>(200,"登录成功",loginUser);} catch (Exception e) {e.printStackTrace();return new ResponseResult<>(505,e.getMessage(),null);}
}
因为前面配置拦截器是拦截了所有的请求,如果将登录请求也拦截会造成永远登录不成功,所 以要将登录请求设置为不拦截
启动服务器,直接访问http://localhost:8989/main.html页面的“楼栋列表”,页面会弹出提示“尚未登录,请先登录”
细节:框架集页面如何实现浏览器地址栏显示登录页面
window.parent.location.href="/login.html";
二、全局异常处理
异常处理的作用就是当程序在运行过程中出现异常的时候给用户显示一个友好提示。
细节:全局异常只监视控制器发生的异常。所以,一般来说,dao和service发生的异常,我们一般就会抛出到controller,由全局异常处理
springmvc全局异常处理使用步骤
1 添加创建全局异常处理类
/*** 全局异常处理类,其实本质:aop切面*/
@ControllerAdvice //aop切面
public class MyGlobalException {@ExceptionHandler(ArithmeticException.class)@ResponseBodypublic ResponseResult<Void> handleArithmeticException(ArithmeticException e){//控制台:异常消息还是要输出的!!给自己看e.printStackTrace();return new ResponseResult<>(501,"算术异常,异常原因:"+e.getMessage());}@ExceptionHandler(NullPointerException.class)@ResponseBodypublic ResponseResult<Void> handleArithmeticException(NullPointerException e){//e作用用来接收控制器实际抛出异常//控制台:异常消息还是要输出的!!给自己看e.printStackTrace();return new ResponseResult<>(501,"空指针异常,异常原因:"+e.getMessage());}
}
2 springmvc配置类中开启全局异常处理类所在包扫描
/*** springmvc配置类,作用:取代springmvc.xml*/
@Configuration
@ComponentScan({"com.woniu.controller","com.woniu.interceptor","com.woniu.exception"})
@EnableWebMvc //启用springmvc的内置配置,对WebMvcConfigurer接口实现
public class SpringWebConfig implements WebMvcConfigurer {//其他代码略
}
3 如果要根据不同的异常出现不同的提示,直接在全局异常类中补充对应异常的处理方法即可,参考代码如下:
@ControllerAdvice
public class GlobalException {/*** 400 - Bad Request*/@ExceptionHandler(HttpMessageNotReadableException.class)@ResponseBodypublic ResponseResult<Void> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {return new ResponseResult<>(400,"参数解析失败");}/*** 405 - Method Not Allowed*/@ExceptionHandler(HttpRequestMethodNotSupportedException.class)@ResponseBodypublic ResponseResult<Void> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {return new ResponseResult<>(405,"不支持当前请求的方法");}/*** 415 - Unsupported Media Type*/@ExceptionHandler(HttpMediaTypeNotSupportedException.class)@ResponseBodypublic ResponseResult<Void> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {return new ResponseResult<>(415,"不支持当前媒体类型");}/*** 500 - Internal Server Error*/@ExceptionHandler(HttpServerErrorException.class)@ResponseBodypublic ResponseResult<Void> handleServerErrorException(HttpServerErrorException e) {return new ResponseResult<>(500,"服务器异常");}/*** 5001* @param e* @return*/@ExceptionHandler(ArithmeticException.class)@ResponseBodypublic ResponseResult<Void> handleArithmeticException(ArithmeticException e){return new ResponseResult<>(5001,"除数不能为0");}
}
启动服务器,浏览器输入URL地址,和以前一样发送请求,控制器处理请求的过程中,只要遇到异常,就会去全局异常中找对应的方法执行。
案例:利用全局异常处理登录失败的情况
-
自定义异常LoginException
public class LoginException extends RuntimeException{
public LoginException() {
}public LoginException(String message) {super(message);}public LoginException(String message, Throwable cause) {super(message, cause);}public LoginException(Throwable cause) {super(cause);}public LoginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);} } -
UserServiceImpl中遇到登录问题,就抛出LoginException对象
//登录业务
public User doLogin(String phone, String password) {
try {
User user = userDao.selectUserByPhone(phone);
if(!user.getPassword().equals(password)){
//抛出业务异常
throw new LoginException(“密码错误!”);
}
return user;
} catch (Exception e) {
if(e instanceof EmptyResultDataAccessException){
throw new LoginException(“账号不存在!”);
}
throw new RuntimeException(e);
}
} -
在GlobalException中添加LoginException的处理方法
相关文章:
SpringMvcの拦截器全局异常处理
一、拦截器 我们在网上发贴子的时候如果没有登录,点击发送按钮会提示未进行登录,跳转到登录页面。这样的功能是如何实现的。 1、 拦截器的作用 Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理…...
JVM虚拟机的组成
一、为什么要学习 JVM ? 1. “ ⾯试造⽕箭,⼯作拧螺丝” , JVM 属于⾯试官特别喜欢提问的知识点; 2. 未来在⼯作场景中,也许你会遇到以下场景: 线上系统突然宕机,系统⽆法访问,甚⾄直…...
探索CSS clip-path: polygon():塑造元素的无限可能
在CSS的世界里,clip-path 属性赋予了开发者前所未有的能力,让他们能够以非传统的方式裁剪页面元素,创造出独特的视觉效果。其中,polygon() 函数尤其强大,它允许你使用多边形来定义裁剪区域的形状,从而实现各…...
【华为OD机试B卷】单词接龙(C++/Java/Python)
题目 题目描述 单词接龙的规则是: 可用于接龙的单词首字母必须要前一个单词的尾字母相同;当存在多个首字母相同的单词时,取长度最长的单词,如果长度也相等,则取字典序最小的单词;已经参与接龙的单词不能重复使用。现给定一组全部由小写字母组成单词数组,并指定其中的一个…...
项目实训-vue(十七)
项目实训-vue(十七) 文章目录 项目实训-vue(十七)1.概述2.问诊类型3.问诊时间统计4.看诊时间统计 1.概述 本篇博客将记录我在数据统计页面中的工作。因为项目并未实际运行,因此我们拟定了一些数据,并构建了…...
Android10 SystemUI系列 需求定制(二)隐藏状态栏通知图标,锁屏通知,可定制包名,渠道等
一、前言 SystemUI 所包含的界面和模块比较多,这一节主要分享一下状态栏通知图标和通知栏的定制需求:隐藏状态栏通知图标,锁屏通知,可定制包名,渠道等 来熟悉一下Systemui。 二、准备工作 按照惯例先找到核心类。这里提前说一下,这个需求的修改方法更多,笔者这里也只…...
Linux:RAID磁盘阵列
目录 一、RAID(磁盘阵列) 1.1、概念 1.2、RAID 0(条带化存储) 1.3、RAID 1(镜像存储) 1.4、RAID 5 1.5、RAID 6 1.6、RAID 10 (先做镜像,再做条带) 二、创建RAID 2.1、建立RAID 0 …...
MongoDB和AI 赋能行业应用:零售
欢迎阅读“MongoDB 和 AI 赋能行业应用”系列的第三篇。 本系列重点介绍 AI 应用于不同行业的关键用例,涵盖制造业和汽车行业、金融服务、零售、电信和媒体、保险以及医疗保健行业。 利用生成式 AI 技术(Gen AI),零售商可以创造…...
MQ~消息队列能力、AMQP协议、现有选择(Kafka、RabbitMQ、RocketMQ 、Pulsar)
消息队列 消息队列看作是一个存放消息的容器,当我们需要使用消息的时候,直接从容器中取出消息供自己使用即可。由于队列 Queue 是一种先进先出的数据结构,所以消费消息时也是按照顺序来消费的。 常⽤的消息队列主要这 五 种,分别…...
开源网安参与编制的《代码大模型安全风险防范能力要求及评估方法》正式发布
代码大模型在代码生成、代码翻译、代码补全、错误定位与修复、自动化测试等方面为研发人员带来了极大便利的同时,也带来了对安全风险防范能力的挑战。基于此,中国信通院依托中国人工智能产业发展联盟(AIIA),联合开源…...
【树状数组 队列】1505. 最多 K 次交换相邻数位后得到的最小整数
本文涉及知识点 树状数组 队列 LeetCode1505. 最多 K 次交换相邻数位后得到的最小整数 给你一个字符串 num 和一个整数 k 。其中,num 表示一个很大的整数,字符串中的每个字符依次对应整数上的各个 数位 。 你可以交换这个整数相邻数位的数字 最多 k 次…...
【附精彩文章合辑】当谈到程序的“通用性”与“过度设计”的困境时,我们可以通过一些具体的例子来更直观地阐述这些解决方案
当谈到程序的“通用性”与“过度设计”的困境时,我们可以通过一些具体的例子来更直观地阐述这些解决方案。以下是一些示例: 一、明确需求与目标 例子1:在线购物平台 需求分析:平台需要支持用户注册、登录、浏览商品、下单购买、…...
Word中删除空白页
① 文字后面出现的空白页 把鼠标放在空白页的位置,按住Ctrl Delete即可。 ② 表格后面的空白页 把鼠标放在空白页左侧,直到出现一个空白的箭头,点击一下选中空白页,然后再Ctrl D,打开字体选项卡,在效果中…...
30.Netty进阶-黏包半包解决方案-短链接
客户端发送一次完整的消息,然后就把与服务端的链接断开。服务端读到的结果就是-1。 服务器就知道 从链接建立到断开,发送的数据是一条完整的数据。 客户端代码 package com.xkj.nian;import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.net…...
斜堆(数据结构篇)
数据结构之斜堆 斜堆 概念: 斜堆是左式堆的自调节形式,斜堆和左式堆间的关系类似于伸展树和AVL树间的关系斜堆是具有堆序性的二叉树,但是不存在对树的结构限制不同于左式堆,关于任意节点的零路径长的任何信息都不保留ÿ…...
河南大学24计算机考研数据,有三个学院招收计算机相关专业,都是考的408!
河南大学(Henan University),简称“河大”,是河南省人民政府与中华人民共和国教育部共建高校,国家“双一流”建设高校,入选国家“111计划”、中西部高校基础能力建设工程、卓越医生教育培养计划、卓越法律人…...
ubuntu离线安装docker导入镜像
docker安装包 准备工作 1.准备一个docker.service文件 内容如下: [Unit] DescriptionDocker Application Container Engine Documentationhttps://docs.docker.com Afternetwork-online.target firewalld.service Wantsnetwork-online.target[Service] Typenoti…...
鸿蒙原生应用元服务开发-位置服务申请权限
申请位置权限开发指导 场景概述 应用在使用位置服务系统能力前,需要检查是否已经获取用户授权访问设备位置信息。如未获得授权,可以向用户申请需要的位置权限。 系统提供的定位权限有: ohos.permission.LOCATION:用于获取精准位置…...
基于SpringBoot的“智慧食堂”管理系统设计与实现
你好呀,我是计算机学姐码农小野!如果有相关需求,可以私信联系我。 开发语言:Java 数据库:MySQL 技术:SpringBootVue 工具:IDEA/Eclipse、Navicat、Maven 系统展示 首页 用户管理界面 菜品…...
高效记录收支明细:揭秘如何通过曲线图精准分析每月开销
在理财的道路上,你是否曾感到迷茫和无力?每个月的开销如同流水般悄无声息地滑过指尖,但你却始终难以掌握自己的财务脉络。今天,我们为你揭秘一个全新的理财方法——通过曲线图精准分析每月开销,让你的财务生活焕发智慧…...
企业内网系统通过Taotoken安全调用外部大模型API的方案
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 企业内网系统通过Taotoken安全调用外部大模型API的方案 对于有严格数据安全与合规要求的企业IT部门而言,如何安全、可控…...
NotebookLM文化遗产研究不可逆断层预警:当AI开始“发明”不存在的碑刻铭文(含3类幻觉检测SOP)
更多请点击: https://intelliparadigm.com 第一章:NotebookLM文化遗产研究 NotebookLM 是 Google 推出的基于 AI 的研究协作者工具,其核心能力在于对用户上传的私有文档进行深度语义理解与上下文关联推理。在文化遗产研究领域,该…...
别让电流倒灌毁了你的MCU!手把手教你用肖特基二极管和MOS管搞定电平转换电路
嵌入式系统电平转换电路设计实战:阻断电流倒灌的5种硬件方案 当3.3V单片机需要驱动5V传感器时,或者5V逻辑器件要与1.8V处理器通信时,电平转换电路就成了系统稳定的关键屏障。去年我在工业控制器项目中就曾遇到一个典型问题:当5V外…...
2026春招AI人才争夺战白热化!小白程序员如何抓住13万高薪机遇?速收藏!
2026年春招显示AI领域岗位量同比增长8.7倍,成为职场新风口。具身智能岗位薪资暴增,AI科学家月薪高达13.2万元。高薪AI岗位紧缺,程序员需拥抱AI工具提升竞争力,否则面临被替代风险。AI能力已成为职场基础设施,不学AI可能…...
Taotoken Token Plan套餐为高频用户带来的长期成本优势感知
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Taotoken Token Plan套餐为高频用户带来的长期成本优势感知 对于高频使用大模型API的开发者或团队而言,项目开发中的模…...
在 Simulink 中实现并网双向 DC/AC 逆变器的无功补偿(SVG)功能仿真
目录 🛠️ 第一步:系统架构设计与模块搭建 ⚙️ 第二步:SVG 核心控制策略设计(双闭环控制) 📊 第三步:仿真运行与结果分析 手把手教你在 Simulink 中实现并网双向 DC/AC 逆变器的无功补偿(SVG)功能仿真。 在现代电力系统中,并网逆变器(如光伏、储能逆变器)不…...
吵翻了!龙虾之父晒天价账单,一个月烧了 130 万美元,消耗 6030 亿 Token
前段时间,昆仑万维董事长方汉的一次访谈引发热议,他自曝“一个月才用 20 多亿,有点惭愧。” 他有位 CTO 朋友每月烧 600 亿 token,3 个月完成百名程序员七八年写的 800 万行代码。不过呢,今天小程程刷到一个更绝的案例…...
助力销售会议转任务,识别准整理快,任务清晰更省心
2026年做销售,若仍靠手写整理销售会议转任务,很容易面临客户信息漏记、整理效率偏低的问题,管理层要求提效并提供可量化改善方案时,也难以快速响应。AI助力销售会议转任务,可有效解决这类困扰,提升识别准确…...
Claude Code安装+配置国产大模型+CC Switch
Claude Code 是一个运行在终端(Terminal)里的 AI 程序员。 它不仅仅是一个聊天框,它拥有操作你电脑文件的权限 https://code.claude.com/docs/en/setup 安装 前提条件 需要 Node.js 18 或更新版本 macOS 用户推荐使用 nvm 或 Homebrew 安装…...
AI智能体集群如何革新代码审查:架构、实现与CI/CD集成
1. 项目概述:一个为代码审查提效的智能体集群如果你是一名团队的技术负责人或资深开发者,肯定对代码审查(Code Review)这个环节又爱又恨。爱的是,它是保证代码质量、促进知识共享的关键闸门;恨的是…...
