【Spring MVC】统一功能处理

一、登录验证

登录验证通过拦截器实现,拦截器就是在用户访问服务器时,预先拦截检查一下用户的访问请求。

  • 没有拦截器时,用户访问服务器的流程是:用户–>controller–>service–>Mapper。
  • 有拦截器时,用户访问服务器流程是:用户–>拦截器–>controller–>service–>Mapper。

拦截器起到了预先帮助Controller层检查请求是否合规的作用,让Controller层的代码更加专注于核心的业务逻辑。
登录验证就是拦截器的一种应用。在请求没Controller层处理前,先判断发出请求的用户是否是登录状态。

  1. 创建拦截器类

    • 拦截器类要实现拦截器接口HanderInterCeptor
    • 重写里面的preHandle方法,这个preHandle方法就是拦截器在拦截到http请求后做的事情。
      • 返回值是Boolean类型,返回true代表通过拦截,继续向深层代码执行
      • 返回false代表请求不合规,被拦截了,直接返回响应。
    @Component
    public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session=request.getSession(false);if(session!=null && session.getAttribute("userinfo")!=null){return true;}return false;}
    }
    
  2. 配置拦截器拦截的url

    • 重新创建一个配置类,并且这个类要加上@Configuration注释交给Spring容器托管。
    • 继承WebMvcConfigurer接口,并且重写addInterceptor方法
      • 参数InterceptorRegistry就是拦截器的注册列表,要将拦截器添加到列表中拦截器才能在url访问时候调用。
      • registry的addInterceptor方法就是将传入的拦截器对象注册加入拦截器列
      • addPathPatterns方法就是添加拦截器的拦截路径,/※代表这一级的所有路径,/** 代表所有的多级路径。
      • excludePathPatterns方法就是在已添加的路径中剔除路径
@Configuration
public class LoginConfiguration implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor interceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(interceptor).addPathPatterns("/**").excludePathPatterns("/image/**").excludePathPatterns("/sayhi");}
}

拦截器的工作原理:
为了理解拦截器源码实现,首先要知道一件事,一个http请求访问到项目,项目进行处理的时候,是有一个调度器(DispatcherServlet)来调度程序执行的先后顺序的.这个调度器是SpringMVC框架实现的。

当spring boot项目启动后,控制台没有DispatcherServlet启动的日志
在这里插入图片描述

但是当首个http请求发出后,DispatcherServlet就会被初始化
在这里插入图片描述

调度器在收到http请求后的首先就会执行拦截器列表中的拦截器对象的方法,只有列表中的所有方法都返回true后,拦截器才会调度深层代码继续执行。有一个返回false都会直接返回响应。

二、统一异常处理

当前端传入的某些特殊数据时,可能会导致后端程序在执行时抛出异常,如果不对这个异常做出处理,后端会直接返回500的错误页面,破坏前后端交互的正常进行,异常处理的作用就是就算后端抛出了异常,响应也要按照正确格式返回,只是在返回的时候说明后端发生了错误。

  1. 自定义异常处理类
    • 这个类要用@ControllerAdvice和@ResponseBody修饰

    • 类内的方法要指定是针对哪个异常进行处理,使用@ExceptionHandeler注解指定异常,注解参数是异常类的class对象

    • 处理方法的返回值就是响应的body返回值(要将按正常格式返回)

      @ControllerAdvice
      @ResponseBody
      public class MyExceptionController {@ExceptionHandler(Exception.class)public HashMap<String,Object> handException(Exception e){HashMap<String,Object> map=new HashMap<>();map.put("data",e.getMessage());return map;}
      }

      上面的代码指定的异常类的class是所有异常的父类Exception,这样指定是起到一个保底的作用,因为异常是不可预知的,你在写代码的时候,并不知道代码会抛出什么异常,针对特定异常的处理是极少的,直接使用父类异常接受可以兜底保证异常抛出时,会被正确的处理。
      抛出异常时,处理方法的匹配原则是先匹配对应异常的处理方法,如果没有才会匹配父类异常的处理方法。

三、统一数据格式

  1. 要定义一个格式处理类,使用@ControllerAdvice类修饰
  2. 然后这个类要继承ResponseBodyAdvice接口,重写supports方法和beforeBodyWrite方法
    • Support方法的返回值就是设置是否要调用beforeBodyWrite方法的,true表示要调用,false表示不调用

    • beforeBodyWrite就是修改body的数据格式的方法,可以根据自带的object参数body获取判断参数格式是否符合要求。(用instanceof方法判断Object是否是约定要返回的对象类型)

      @ControllerAdvice
      public class ResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {if(body instanceof HashMap){//格式正确return body;}HashMap<String,Object> map=new HashMap();map.put("code",1);map.put("data",body);return map;}
      }
      

注意:如果body是String类型的数据,将这个hashMap最终转换成json格式的时候,会报错。
原因就是在hashmap转换成json字符串的时候会判断Value的类型,如果HashMap中的value是Object,并且原类型是String就是使用的StringHttpMessageConverter进行转换,这个转换就会出错。
解决办法就是,在统一格式转换方法里,将body为String的HashMap直接转换成Json格式字符串

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {if(body instanceof HashMap){//格式正确return body;}HashMap<String,Object> map=new HashMap();map.put("code",1);map.put("data",body);//判断是否是Stringif(body instanceof String){ObjectMapper objectMapper=new ObjectMapper();String result= null;try {result = objectMapper.writeValueAsString(map);} catch (JsonProcessingException e) {e.printStackTrace();}return result;}return map;}
}

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

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

相关文章

RouterOS-配置PPPoEv4v6 Server

1 接口 ether3 出接口 ether4 内网接口 2 出接口 出接口采用PPPoE拨号SLAAC获取前缀&#xff0c;手动配置后缀 2.1 选择出接口interface&#xff0c;配置PPPoE client模式 2.2 配置PPPoE client用户名和密码 2.3 从PPPoE client获取前缀地址池 2.4 给出接口选择前缀并配置…

第10章_索引优化与查询优化(覆盖索引, 索引下推等)

4. 子查询优化 MySQL 从 4.1 版本开始支持子查询&#xff0c;使用子查询可以进行 SELECT 语句的嵌套查询&#xff0c;即一个 SELECT 查询的结果作为另一个SELECT 语句的条件。 子查询可以一次性完成很多逻辑上需要多个步骤才能完成的 SQL 操作 。 子查询是 MySQL 的一项重…

Vue + Element UI 前端篇(七):功能组件封装

组件封装 为了避免组件代码的臃肿&#xff0c;这里对主要的功能部件进行封装&#xff0c;保证代码的模块化和简洁度。 组件结构 组件封装重构后&#xff0c;试图组件结构如下图所示 代码一览 Home组件被简化&#xff0c;包含导航、头部和主内容三个组件。 Home.vue <te…

vue优化首屏加载时间优化-cdn引入第三方包

前言 为什么要进行首屏加载优化&#xff0c;因为随着我们静态资源和第三方包和代码增加&#xff0c;压缩之后包会越来越大 随着网络的影响&#xff0c;在我们第一输入url请求资源时候&#xff0c;网络阻塞&#xff0c;加载时间长&#xff0c;用户体验不好 仔细观察后就会发现…

YOLOV8实例分割——详细记录环境配置、自定义数据处理到模型训练与部署

前言 Ultralytics YOLOv8是一种前沿的、最先进的&#xff08;SOTA&#xff09;模型&#xff0c;它在前代YOLO版本的成功基础上进行了进一步的创新&#xff0c;引入了全新的特性和改进&#xff0c;以进一步提升性能和灵活性。作为一个高速、精准且易于操作的设计&#xff0c;YO…

【计算机网络】http协议

目录 前言 认识URL URLEncode和URLDecode http协议格式 http方法 GET POST GET与POST的区别 http状态码 http常见header 简易的http服务器 前言 我们在序列化和反序列化这一章中&#xff0c;实现了一个网络版的计算器。这个里面设计到了对协议的分析与处…

STL常用容器 (C++核心基础教程之STL容器详解)String的API

在C的标准模板库&#xff08;STL&#xff09;中&#xff0c;有多种容器可供使用。以下是一些常见的容器类型&#xff1a; 序列容器&#xff08;Sequential Containers&#xff09;&#xff1a; std::vector&#xff1a;动态数组&#xff0c;支持快速随机访问。 std::list&…

宠物电商Chewy第二季度销售额28亿美元,同比增长14.3%

美国宠物电商Chewy公布2023年第二季度财报。报告显示&#xff0c;其Q2季度销售额同比增长14.3%至28亿美元&#xff0c;超出市场预期。 以下为Chewy期内业绩概要&#xff1a; 1.毛利率28.3%&#xff0c;同比增长20个基点 2.净利润有所收窄&#xff0c;同比下降15.2%至1890万美…

9.2.tensorRT高级(4)封装系列-自动驾驶案例项目self-driving-深度估计

目录 前言1. 深度估计总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-自动驾驶案例项目self-driving-深度估…

Mybatis学习|Mybatis缓存:一级缓存、二级缓存

Mybatis缓存 MyBatis包含一个非常强大的查询缓存特性&#xff0c;它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。 MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存 默认情况下&#xff0c;只有一级缓存开启。(SqlSession级别的缓存&#xff0c;也称为本地…

Leetcode 1572.矩阵对角线元素之和

给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;25 解释&#xff1a;对角线的和为&#xff…

qt.qpa.plugin:找不到Qt平台插件“wayland“|| (下载插件)Ubuntu上解决方案

相信大家也都知道这个地方应该做什么&#xff0c;当然是下载这个qt平台的插件wayland,但是很多人可能不知道怎么下载这个插件。 那么我现在要说的这个方法就是针对这种的。 sudo apt install qtwayland5完事儿了奥兄弟们。 看看效果 正常了奥。

JVM类的加载相关的问题

JVM类的加载相关的介绍 学习类的加载的加载过程对深入理解JVM有十分重要的作用&#xff0c;下面就跟我一起学习JVM类的加载过程吧&#xff01; 文章目录 JVM类的加载相关的介绍一、类的加载过程二、双亲委派机制1、类加载器的种类2、为什么JVM要分成不同的类的加载器3、类的加…

机器人中的数值优化(十)——线性共轭梯度法

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…

HDFS 架构剖析

目录 一、HDFS 架构整体概述 二、HDFS 集群角色介绍 2.1 整体概述 2.2 主角色&#xff1a;namenode 2.3 从角色&#xff1a;datanode 2.4 主角色辅助角色&#xff1a; secondarynamenode 三、HDFS 重要特性 3.1 主从架构 3.2 分块存储机制 3.3 副本机制 3.4 …

JVM详细教程

JVM 前言 还在完善中先发布 JVM虚拟机厂家多钟多样&#xff0c;具体实现细节可能不一样&#xff0c;这里主要讲的是虚拟机的规范&#xff0c;以下内容融合了各个平台发布的内容和周志明老师的《深入理解java虚拟机》 JVM概述 如何理解jvm跨平台&#xff1f; 编译成汇编代码…

Vue+elementUI 导出word打印

import JSZipUtils from "jszip-utils"; import JSZip from "pizzip"; import Docxtemplater from "docxtemplater"; npm安装以上依赖 首先维护个word模板 导出方法 //导出wordskipOutWord(row) {var printData rowconst data JSON.parse(JS…

SpringMVC <url-pattern/>解读

1. < url-pattern/>的值 (1).使用拓展名的方式&#xff0c;语法*.xxx&#xff0c;xxx是自定义的拓展名&#xff0c;常用的方式*.do&#xff0c;*.action,不能使用*.jsp. (2).使用斜杠 "/"当项目中使用了 / &#xff0c;他会替代tomcat中的default。导致所有的…

前端需要学习哪些技术?

前端工程师岗位缺口一直很大&#xff0c;符合岗位要求的人越来越少&#xff0c;所以学习前端的同学要注意&#xff0c;一定要把技能学到扎实&#xff0c;做有含金量的项目&#xff0c;这样在找工作的时候展现更大的优势。 缺人才&#xff0c;又薪资高&#xff0c;那么怎样才能…

C#-抽象类与接口

文章目录 一、抽象类和接口总结总结补充说明主要区别 二、抽象类2.1 抽象类概述与声明2.2 抽象方法2.3 抽象类与抽象方法的使用 三、接口3.1 接口概述概述特征声明示例 3.2 接口的实现和继承说明示例 3.3 显式接口成员实现说明注意示例 一、抽象类和接口总结 总结 抽象类和接…