【Spring MVC】统一功能处理

news2024/11/27 8:44:02

一、登录验证

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

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

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

  1. 创建拦截器类

    • 拦截器类要实现拦截器接口HanderInterCeptor
    • 重写里面的preHandle方法,这个preHandle方法就是拦截器在拦截到http请求后做的事情。
      • 返回值是Boolean类型,返回true代表通过拦截,继续向深层代码执行
      • 返回false代表请求不合规,被拦截了,直接返回响应。
    @Component
    public class LoginInterceptor implements HandlerInterceptor {
    
        @Override
        public 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 {
    @Autowired
    private LoginInterceptor interceptor;
    @Override
    public 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 {
          @Override
          public boolean supports(MethodParameter returnType, Class converterType) {
              return true;
          }
      
          @Override
          public 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 {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    public 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);
       //判断是否是String
       if(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.coloradmin.cn/o/978242.html

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

相关文章

自旋锁和读写锁

目录 一、自旋锁 1.自旋锁和挂起等待锁 2.自旋锁的接口 二、读写锁 1.读者写者模型与读写锁 2.读写锁接口 3.加锁的原理 4.读写优先级 一、自旋锁 1.自旋锁和挂起等待锁 互斥锁的类型有很多&#xff0c;我们之前使用的锁实际上是互斥锁中的挂起等待锁。互斥锁比较有代…

JMeter(三十九):selenium怪异的UI自动化测试组合

文章目录 一、背景二、JMeter+selenium使用过程三、总结一、背景 题主多年前在某社区看到有人使用jmeter+selenium做UI自动化测试的时候,感觉很是诧异、怪异,为啥?众所周知在python/java+selenium+testng/pytest这样的组合框架下,为啥要选择jmeter这个东西[本身定位是接口测…

基于微信小程序的智能垃圾分类回收系统,附源码、教程

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 1 简介 视频演示地址&#xff1a; 基于微信小程序的智能垃圾分类回收系统&#xff0c;可作为毕业设计 小…

《C++ Primer》第2章 变量(一)

参考资料&#xff1a; 《C Primer》第5版《C Primer 习题集》第5版 2.1 基本内置类型&#xff08;P30&#xff09; C 定义的基本类型包括算术类型&#xff08;arithmetic type&#xff09;和空类型&#xff08;void&#xff09;&#xff0c;其中算术类型包括字符、整型、布尔…

postgresql-类型转换函数

postgresql-类型转换函数 简介CAST 函数to_date函数to_timestampto_charto_number隐式类型转换 简介 类型转换函数用于将数据从一种类型转换为另一种类型。 CAST 函数 CAST ( expr AS data_type )函数用于将 expr 转换为 data_type 数据类型&#xff1b;PostgreSQL 类型转 换…

《86盒应用于家居中控》——实现智能家居的灵动掌控

近年来&#xff0c;智能家居产品受到越来越多消费者的关注&#xff0c;其便捷、舒适的生活方式让人们对未来生活充满期待。作为智能家居方案领域的方案商&#xff0c;启明智显生产设计的86盒凭借出色的性能和良好的用户体验&#xff0c;成功应用于家居中控系统&#xff0c;让家…

Gof23设计模式之策略模式

1.概述 该模式定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以相互替换&#xff0c;且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式&#xff0c;它通过对算法进行封装&#xff0c;把使用算法的责任和算法的实现分割开来&#xff0c;…

剑指 Offer 43. 1~n 整数中 1 出现的次数(困难)

题目&#xff1a; class Solution { public:int countDigitOne(int n) {// mulk 表示 10^k// 在下面的代码中&#xff0c;可以发现 k 并没有被直接使用到&#xff08;都是使用 10^k&#xff09;// 但为了让代码看起来更加直观&#xff0c;这里保留了 klong long mulk 1;int…

Text Workflow for Mac,简单易用的文本转换工具

如果你需要一个能够将文本转换成多种语言和文件格式的工具&#xff0c;那么Text Workflow for Mac将是你的不二之选。 这个软件支持多种语言翻译和多种文件格式转换&#xff0c;让你可以轻松地将文本转换成你需要的形式。而且&#xff0c;它的操作非常简单&#xff0c;只需要几…

精讲算法的时间复杂度

目录 一、算法效率 1.算法效率 1.1如何衡量一个算法的好坏 1.2算法的复杂度 二、时间复杂度 1.时间复杂度的概念 2.大O的渐进表示法 3.常见时间复杂度的计算举例 三、空间复杂度 一、算法效率 1.算法效率 1.1如何衡量一个算法的好坏 long long Fib(int N) {if(N <…

Day6:浅谈useState

「目标」: 持续输出&#xff01;每日分享关于web前端常见知识、面试题、性能优化、新技术等方面的内容。 Day6-今日话题 谈谈react hooks中的useState &#xff0c;将从以下七个角度介绍&#xff1a; 用法 参数 返回值 作用 工作原理 优缺点 注意点 用法 useState 是一个函数&a…

Hugging News #0904: 登陆 AWS Marketplace

每一周&#xff0c;我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新&#xff0c;包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等&#xff0c;我们将其称之为「Hugging News」。本期 Hugging News 有哪些有趣的消息&#xff0…

VMware虚拟机安装CentOS7设置静态ip

vim /etc/sysconfig/network-scripts/ifcfg-ens33修改BOOTPROTO的值为static 增加最后那四项&#xff0c;参数在编辑&#xff0c;虚拟网络编辑器里面看

合宙Air724UG LuatOS-Air LVGL API控件-滑动条 (Slider)

滑动条 (Slider) 滑动条看起来和进度条是有些是有些像&#xff0c;但不同的是滑动条可以进行数值选择。 示例代码 -- 回调函数 slider_event_cb function(obj, event)if event lvgl.EVENT_VALUE_CHANGED then local val (lvgl.slider_get_value(obj) or "0")..&…

手写bind方法

<script>/** 手写bind方法* */Function.prototype.myBind function (thisArg, ...args) {return (...newArgs) > {return this.call(thisArg, ...args, ...newArgs)}}const obj {name: zs,age: 18,}function fn (a, b, c) {console.log(this)console.log(a b c)re…

《数据出境安全评估办法》解读

一、数据出境的统一评估体系正式确立 自我国《网络安全法》规定了关键信息基础设施运营者的重要数据与个人信息出境评估制度后&#xff0c;至今历时五年&#xff0c;关于数据出境及个人信息出境安全评估的立法体例、评估机制一直在探索过程中。 其后&#xff0c;国家互联网信…

PYTHON知识点学习-字典

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由 Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

java IO流(三) 转换流 打印流

转换流 前面我们学习过FileReader读取文件中的字符&#xff0c;但是FileReader默认只能读取UTF-8编码格式的文件。如果使用FileReader读取GBK格式的文件&#xff0c;可能存在乱码&#xff0c;因为FileReader遇到汉字默认是按照3个字节来读取的&#xff0c;而GBK格式的文件一个…

如何写一个sh脚本将一个本地文件通过 scp命令上传到远程的 centos服务器?

如何写一个sh脚本将一个本地文件通过 scp命令上传到远程的 centos服务器&#xff1f; 1.1 背景需求1.2 解决方案1.3 附录1.3.1 scp命令用法与示例1.3.1.1 scp命令用法与解释1.3.1.2 scp 命令用法示例1.3.1.2.1 示例一&#xff1a;从本地复制文件到远程计算机1.3.1.2.2 示例二&a…

Sqlserver 在 SELECT 语句中显示来自 GROUP BY 子句中未涉及的列

在SQL Server中&#xff0c;如果您在GROUP BY子句中对某些列进行了分组&#xff0c;但想在SELECT语句中同时显示未涉及到的其他列&#xff0c;您可以使用聚合函数和子查询的方法来实现。这可以通过在GROUP BY子查询中获取需要的聚合值&#xff0c;并在外部查询中选择其他列来完…