当前位置: 首页 > news >正文

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の拦截器全局异常处理

一、拦截器 我们在网上发贴子的时候如果没有登录&#xff0c;点击发送按钮会提示未进行登录&#xff0c;跳转到登录页面。这样的功能是如何实现的。 1、 拦截器的作用 Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter&#xff0c;用于对处理器进行预处理和后处理…...

JVM虚拟机的组成

一、为什么要学习 JVM &#xff1f; 1. “ ⾯试造⽕箭&#xff0c;⼯作拧螺丝” &#xff0c; JVM 属于⾯试官特别喜欢提问的知识点&#xff1b; 2. 未来在⼯作场景中&#xff0c;也许你会遇到以下场景&#xff1a; 线上系统突然宕机&#xff0c;系统⽆法访问&#xff0c;甚⾄直…...

探索CSS clip-path: polygon():塑造元素的无限可能

在CSS的世界里&#xff0c;clip-path 属性赋予了开发者前所未有的能力&#xff0c;让他们能够以非传统的方式裁剪页面元素&#xff0c;创造出独特的视觉效果。其中&#xff0c;polygon() 函数尤其强大&#xff0c;它允许你使用多边形来定义裁剪区域的形状&#xff0c;从而实现各…...

【华为OD机试B卷】单词接龙(C++/Java/Python)

题目 题目描述 单词接龙的规则是: 可用于接龙的单词首字母必须要前一个单词的尾字母相同;当存在多个首字母相同的单词时,取长度最长的单词,如果长度也相等,则取字典序最小的单词;已经参与接龙的单词不能重复使用。现给定一组全部由小写字母组成单词数组,并指定其中的一个…...

项目实训-vue(十七)

项目实训-vue&#xff08;十七&#xff09; 文章目录 项目实训-vue&#xff08;十七&#xff09;1.概述2.问诊类型3.问诊时间统计4.看诊时间统计 1.概述 本篇博客将记录我在数据统计页面中的工作。因为项目并未实际运行&#xff0c;因此我们拟定了一些数据&#xff0c;并构建了…...

Android10 SystemUI系列 需求定制(二)隐藏状态栏通知图标,锁屏通知,可定制包名,渠道等

一、前言 SystemUI 所包含的界面和模块比较多,这一节主要分享一下状态栏通知图标和通知栏的定制需求:隐藏状态栏通知图标,锁屏通知,可定制包名,渠道等 来熟悉一下Systemui。 二、准备工作 按照惯例先找到核心类。这里提前说一下,这个需求的修改方法更多,笔者这里也只…...

Linux:RAID磁盘阵列

目录 一、RAID&#xff08;磁盘阵列&#xff09; 1.1、概念 1.2、RAID 0&#xff08;条带化存储&#xff09; 1.3、RAID 1&#xff08;镜像存储&#xff09; 1.4、RAID 5 1.5、RAID 6 1.6、RAID 10 (先做镜像&#xff0c;再做条带) 二、创建RAID 2.1、建立RAID 0 …...

MongoDB和AI 赋能行业应用:零售

欢迎阅读“MongoDB 和 AI 赋能行业应用”系列的第三篇。 本系列重点介绍 AI 应用于不同行业的关键用例&#xff0c;涵盖制造业和汽车行业、金融服务、零售、电信和媒体、保险以及医疗保健行业。 利用生成式 AI 技术&#xff08;Gen AI&#xff09;&#xff0c;零售商可以创造…...

MQ~消息队列能力、AMQP协议、现有选择(Kafka、RabbitMQ、RocketMQ 、Pulsar)

消息队列 消息队列看作是一个存放消息的容器&#xff0c;当我们需要使用消息的时候&#xff0c;直接从容器中取出消息供自己使用即可。由于队列 Queue 是一种先进先出的数据结构&#xff0c;所以消费消息时也是按照顺序来消费的。 常⽤的消息队列主要这 五 种&#xff0c;分别…...

开源网安参与编制的《代码大模型安全风险防范能力要求及评估方法》正式发布

​代码大模型在代码生成、代码翻译、代码补全、错误定位与修复、自动化测试等方面为研发人员带来了极大便利的同时&#xff0c;也带来了对安全风险防范能力的挑战。基于此&#xff0c;中国信通院依托中国人工智能产业发展联盟&#xff08;AIIA&#xff09;&#xff0c;联合开源…...

【树状数组 队列】1505. 最多 K 次交换相邻数位后得到的最小整数

本文涉及知识点 树状数组 队列 LeetCode1505. 最多 K 次交换相邻数位后得到的最小整数 给你一个字符串 num 和一个整数 k 。其中&#xff0c;num 表示一个很大的整数&#xff0c;字符串中的每个字符依次对应整数上的各个 数位 。 你可以交换这个整数相邻数位的数字 最多 k 次…...

【附精彩文章合辑】当谈到程序的“通用性”与“过度设计”的困境时,我们可以通过一些具体的例子来更直观地阐述这些解决方案

当谈到程序的“通用性”与“过度设计”的困境时&#xff0c;我们可以通过一些具体的例子来更直观地阐述这些解决方案。以下是一些示例&#xff1a; 一、明确需求与目标 例子1&#xff1a;在线购物平台 需求分析&#xff1a;平台需要支持用户注册、登录、浏览商品、下单购买、…...

Word中删除空白页

① 文字后面出现的空白页 把鼠标放在空白页的位置&#xff0c;按住Ctrl Delete即可。 ② 表格后面的空白页 把鼠标放在空白页左侧&#xff0c;直到出现一个空白的箭头&#xff0c;点击一下选中空白页&#xff0c;然后再Ctrl D&#xff0c;打开字体选项卡&#xff0c;在效果中…...

30.Netty进阶-黏包半包解决方案-短链接

客户端发送一次完整的消息,然后就把与服务端的链接断开。服务端读到的结果就是-1。 服务器就知道 从链接建立到断开,发送的数据是一条完整的数据。 客户端代码 package com.xkj.nian;import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.net…...

斜堆(数据结构篇)

数据结构之斜堆 斜堆 概念&#xff1a; 斜堆是左式堆的自调节形式&#xff0c;斜堆和左式堆间的关系类似于伸展树和AVL树间的关系斜堆是具有堆序性的二叉树&#xff0c;但是不存在对树的结构限制不同于左式堆&#xff0c;关于任意节点的零路径长的任何信息都不保留&#xff…...

河南大学24计算机考研数据,有三个学院招收计算机相关专业,都是考的408!

河南大学&#xff08;Henan University&#xff09;&#xff0c;简称“河大”&#xff0c;是河南省人民政府与中华人民共和国教育部共建高校&#xff0c;国家“双一流”建设高校&#xff0c;入选国家“111计划”、中西部高校基础能力建设工程、卓越医生教育培养计划、卓越法律人…...

ubuntu离线安装docker导入镜像

docker安装包 准备工作 1.准备一个docker.service文件 内容如下&#xff1a; [Unit] DescriptionDocker Application Container Engine Documentationhttps://docs.docker.com Afternetwork-online.target firewalld.service Wantsnetwork-online.target[Service] Typenoti…...

鸿蒙原生应用元服务开发-位置服务申请权限

申请位置权限开发指导 场景概述 应用在使用位置服务系统能力前&#xff0c;需要检查是否已经获取用户授权访问设备位置信息。如未获得授权&#xff0c;可以向用户申请需要的位置权限。 系统提供的定位权限有&#xff1a; ohos.permission.LOCATION&#xff1a;用于获取精准位置…...

基于SpringBoot的“智慧食堂”管理系统设计与实现

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootVue 工具&#xff1a;IDEA/Eclipse、Navicat、Maven 系统展示 首页 用户管理界面 菜品…...

高效记录收支明细:揭秘如何通过曲线图精准分析每月开销

在理财的道路上&#xff0c;你是否曾感到迷茫和无力&#xff1f;每个月的开销如同流水般悄无声息地滑过指尖&#xff0c;但你却始终难以掌握自己的财务脉络。今天&#xff0c;我们为你揭秘一个全新的理财方法——通过曲线图精准分析每月开销&#xff0c;让你的财务生活焕发智慧…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...