Spring Boot 系列4 -- 统一功能处理

目录

前言

1. Spring AOP 用户统⼀登录验证的问题

1.1 自定义拦截器

1.2 配置拦截器并配置拦截的规则

1.3 拦截器的原理源码分析

2. 统一异常处理

2.1 实现统一异常处理

2.2 测试统一异常处理

3. 统一的数据格式返回

3.1 统⼀数据返回格式的实现

3.2 测试统一的数据返回


前言

        Spring AOP是一个面向切面编程的框架,可以同设置要做处理的类为切面,设置切点进行设置拦截规则,然后定义通知,实现一定的拦截规则.但是我们原生的Spring AOP的框架使用起来比较繁琐.为了解决如此之类的Spring AOP的问题.对于Spring AOP的实战,本文将介绍三种功能.

1. 统一用户登录权限验证

2. 统一数据返回格式

3. 统一异常处理

1. Spring AOP 用户统⼀登录验证的问题

假设我们要实现这样一个功能,在多个页面进行判断用户的登录状态,然后发现当前用户的登录状态为空的时候进行跳转到登录页.

        我们之前的做法是,在每个页面的路由中进行判断用户的登录状态,显然这些操作是重复的,后来我们又学习了Spring AOP,我们试想可以将需要进行验证的类进行设置为切面,在需要地方进行配置拦截的规则,然后进行设置前置通知.这个思想是可以的,但是我们实现起来会遇到两个问题.

1.  没办法获取到 HttpSession 对象(我们需要对Session进行判断当前的用户登录状态)

2.  我们要对⼀部分方法进行拦截,而另⼀部分方法不拦截,如注册⽅法和登录方法是不拦截的,这样的话排除⽅法的规则很难定义,甚至没办法定义。

针对一以上的问题,Spring 框架为我们提供了一个具体实现的拦截器:HandlerInterceptor

而我们要使用这个拦截器实现自己的功能,可以具体分为两步:

 下面我们使用代码进行实现上述的功能:

1.1 自定义拦截器

具体代码:

public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 此方法返回一个boolean类型的值,返回true表示验证成功,继续执行后续流程
     */
    //  重写preHandle方法实现自己的业务代码
    @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;
        }
        // 没有登录,可以进行跳转到登录页面,或者返回一个401 或者403 没有权限码
        response.sendRedirect("/login1.html");
//        response.setStatus(403);
        // 上面两者取一个即可
        return false;
    }

}

1.2 配置拦截器并配置拦截的规则

红色部分就是将自定义的拦截器添加到项目中,然后绿色是一个扩展,就是在路由前面加前缀.

 具体代码:

package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Created with IntelliJ IDEA.
 * Description:将自定义拦截器加入到WebMvcConfigurer中,重写addInterceptors方法进行设置拦截规则
 * User: YAO
 * Date: 2023-07-14
 * Time: 15:04
 */
@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")  // 拦截规则设置,此处进行拦截所有请求
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/user/reg")
                .excludePathPatterns("/user/get-num")
                .excludePathPatterns("/user/get-string")
                .excludePathPatterns("/img/**")
                .excludePathPatterns("/**/*.html");
    }

    // 所有的接⼝添加 api 前缀
      // 给路由进行添加前缀 ,设置为 true 表示启动前缀
//    @Override
//    public void configurePathMatch(PathMatchConfigurer configurer) {
//        configurer.addPathPrefix("api", c -> true);
//    }
}

我们对上述实现的拦截器进行验证

 当进行点击的时候,因为没有Session所以直接跳转到我们设置的登录页面了.

可以看出没有进行设置过Cookie的,就是没有Session连接. 

1.3 拦截器的原理源码分析

所有的方法都会执行 DispatcherServlet 中的 doDispatch 调度方法,观察源码发现:

  点击这个applyPreHandle,applyPreHandle 中会获取所有拦截器 HandlerInterceptor 并执行拦截器中的 preHandle 方法,这与之前我们实现拦截器的步骤对应.

2. 统一异常处理

        统一异常处理是指 在应用程序中定义一个公共的异常处理机制,用来处理所有的异常情况。 这样可以避免在应用程序中分散地处理异常,降低代码的复杂度和重复度,提高代码的可维护性和可扩展性.\

        统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执行某个通知,也就是执行某个方法事件.

2.1 实现统一异常处理

2.2 测试统一异常处理

我们自己创建一个路由,其中内容出现一个空指针异常,我们查看是否能进行返回给前端处理. 

我们设置的异常处理起到作用了.那么如果不设置,异常的处理,会出现什么样的现象?

就会直接将控制台打印的异常返回给前端,前端拿到数据就很懵.所以统一的异常处理还是很有必要的.

3. 统一的数据格式返回

3.1 统⼀数据返回格式的实现

下述是我们一般的统一返回的数据的格式

实现统一的数据返回格式可以使用 @ControllerAdvice + ResponseBodyAdvice 的方式实现,具体步骤如下:

  1. 创建一个类,并添加 @ControllerAdvice 注解;
  2. 实现 ResponseBodyAdvice 接口,并重写 supports 和 beforeBodyWrite 方法.

 上述部分就是记性统一的数据格式返回.

其中需要注意的是,当返回的类型为String类型的时候,我们需要使用Jackson将String转换成json再进行返回.也就是绿色的部分.

package com.example.demo.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.HashMap;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: YAO
 * Date: 2023-07-14
 * Time: 17:25
 */
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    @Autowired
    private ObjectMapper objectMapper;
    @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) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("state",1);
        result.put("msg", "");
        result.put("data", body);
        if (body instanceof String){
            // 需要特殊进行处理,因为String比较特殊,既不是基础类型也不是对象,进行重写的时候String用的格式化工具是自己独有的
            // 在body返回之前没有加载好.需要将String进行单独进行处理.使用Jackson将String转换成json再进行返回.
            try {
                return objectMapper.writeValueAsString(result);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}

3.2 测试统一的数据返回

可以看出返回的格式是我们规定好的格式.这就变得更加统一.


 好啦本文就总结到这了,点个赞吧,谢谢!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智慧水务和物联网智能水表在农村供水工程中的应用

摘 要&#xff1a;随着社会的进步和各项事业的飞速发展&#xff0c;人民生活水平的逐步提升&#xff0c;国家对农村饮水安全有了更高的要求&#xff0c;为了进一步提升农村供水服务的质量&#xff0c;利用现代化、信息化科学技术提升农村供水服务质量&#xff0c;提高用水管理效…

GB28181智能安全帽方案探究及技术实现

什么是智能安全帽&#xff1f;​ 智能安全帽是一种集成先进科技的安全帽&#xff0c;可基于GB28181规范&#xff0c;适用于铁路巡检、电力、石油化工等高风险行业的作业人员&#xff0c;以及消防、救援等紧急情况下的安全防护。 智能安全帽通常具有以下功能&#xff1a; 实时…

RocketMQ发送消息超时异常

说明&#xff1a;在使用RocketMQ发送消息时&#xff0c;出现下面这个异常&#xff08;org.springframework.messging.MessgingException&#xff1a;sendDefaultImpl call timeout……&#xff09;&#xff1b; 解决&#xff1a;修改RocketMQ中broke.conf配置&#xff0c;添加下…

git使用(由浅到深)

目录流程图 1. 分布式版本控制与集中式版本控制 1.1 集中式版本控制 集中式版本控制系统有:CVS和SVN它们的主要特点是单一的集中管理的服务器&#xff0c;保存所有文件的修订版本&#xff1b;协同开发人员通过客户端连接到这台服务器&#xff0c;取出最新的文件或者提交更新…

天气API强势对接

&#x1f935;‍♂️ 个人主页&#xff1a;香菜的个人主页&#xff0c;加 ischongxin &#xff0c;备注csdn ✍&#x1f3fb;作者简介&#xff1a;csdn 认证博客专家&#xff0c;游戏开发领域优质创作者,华为云享专家&#xff0c;2021年度华为云年度十佳博主 &#x1f40b; 希望…

“苏豪 x 莱佛士”再度携手,惊艳亮相上海发型师节!

2023年6月28日&#xff0c;以“为爱启航”为主题的第16届AHF亚洲发型师节在上海跨国采购中心盛大开幕。继上次在施华蔻专业2023春夏新季风发布会上&#xff0c;苏豪x莱佛士合作的大秀&#xff0c;赢得了现场观众阵阵掌声。这次“Kraemer苏豪x莱佛士”再度携手&#xff0c;惊艳亮…

【雕爷学编程】MicroPython动手做(25)——语音合成与语音识别

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

Linux 入侵痕迹清理技巧(仅限学习安全知识)

vim ~/.bash_history 查看历史操作命令&#xff1a;history history记录文件&#xff1a;more ~/.bash_history history -c echo " " > ~/.bash_history #使用vim打开一个文件 vi test.txt # 设置vim不记录命令&#xff0c;Vim会将命令历史记录&#xff0c;保存…

2023年华数杯B题

B 题 不透明制品最优配色方案设计 日常生活中五彩缤纷的不透明有色制品是由着色剂染色而成。因此&#xff0c;不透明 制品的配色对其外观美观度和市场竞争力起着重要作用。然而&#xff0c;传统的人工配色 存在一定的局限性&#xff0c;如主观性强、效率低下等。因此&#xff0…

Django实现音乐网站 ⑷

使用Python Django框架制作一个音乐网站&#xff0c;在系列文章3的基础上继续开发&#xff0c; 本篇主要是后台歌曲类型表、歌单表模块功能开发。 目录 表结构设计 歌曲类型表结构 歌单表结构 创建表模型 创建表 后台注册表模型 引入表模型 后台自定义 总结 表结构设计…

为Stable Diffusion web UI开发自己的插件实战

最近&#xff0c;Stable Diffusion AI绘画受到了广泛的关注和热捧。它的Web UI提供了了一系列强大的功能&#xff0c;其中特别值得一提的是对插件的支持&#xff0c;尤其是Controlnet插件的加持&#xff0c;让它的受欢迎程度不断攀升。那么&#xff0c;如果你有出色的创意&…

Jmeter远程服务模式运行时引用csv文件的路径配置

问题 在使用jmeter过程中&#xff0c;本机的内存等配置不足&#xff0c;启动较多的线程时&#xff0c;可以采用分布式运行。 在分布式运行的时候&#xff0c;jmeter会自动将脚本从master主机发送到remote主机上&#xff0c;所以不需要考虑将脚本拷贝到remote主机。但是jmeter…

【图论】强连通分量进阶

一.作用 强连通分量可以判断环和进行缩点。还有一系列作用.... 这篇文章介绍缩点 二.题目 https://www.luogu.com.cn/problem/P2341 三.思路 我们分析可以知道当一个点没有出度时&#xff0c;则为最受欢迎的牛。但如果有多个出度&#xff0c;则没有最受欢迎的牛。 这是只有…

工厂模式详解与应用场景

摘要&#xff1a; 工厂模式是一种常见的设计模式&#xff0c;它可以帮助我们在面向对象的程序设计中更好地组织和管理对象的创建过程。本文将详细介绍工厂模式的概念、三种常见的工厂模式应用场景&#xff0c;并提供高质量的C代码示例&#xff0c;旨在帮助初学者更好地理解和应…

【练】创建两个线程:其中一个线程拷贝图片的前半部分,另一个线程拷贝后半部分

方法一&#xff1a; 先在主函数创建并清空拷贝的目标文件&#xff0c;再创建两个线程&#xff0c;在两个线程内部同时打开要读取的文件以及要拷贝的目标文件&#xff08;两个线程不共用同一份资源&#xff09;。 使用到的函数&#xff1a; 标准IO函数&#xff08;fprintf&…

C++模板

目录 一.泛型编程 二.模板 1.函数模板 1.1函数模板格式&#xff1a; 1.2函数模板的原理 1.3 函数模板的实例化 隐式实例化 显式实例化 &#xff1a; 模板参数的匹配原则&#xff1a; 2.类模板 2.1类模板格式 一.泛型编程 如何实现一个通用的交换函数呢&#xff1f;…

主动带宽控制工具

停机和带宽过度使用是任何组织都无法避免的两个问题。随着企业采用 BYOD 文化&#xff0c;通过网络的流量负载可能很重&#xff0c;导致网络拥塞并使网络容易受到网络攻击。为了解决这个问题&#xff0c;企业需要全面的监控策略来保护网络&#xff0c;当看似大量的流量进入网络…

C++学习——模板

目录 &#x1f349;一&#xff1a;什么是模板 &#x1f34e;二&#xff1a;普通模板的定义 &#x1f34d;三&#xff1a;类模板的定义 &#x1f34c;四&#xff1a;模板的实例化 &#x1f347;1.当普通模板定义存在可修改返回值产生的分歧 &#x1f348;2&#xff1a;类模板实例…

一文读透时区和时间戳以及基于Java的操作

重要概念 1. UTC 和 UTC8 UTC 是世界标准时间&#xff0c; UTC8 是东八区标准时间&#xff0c;中国就属于东八区&#xff0c; 也就是北京时间。 8 就是加8个小时。 时区的划分图示如下&#xff1a; 也就是说&#xff1a; 假如现在是UTC时间是 2023-08-08 01:00:00 &#xff0…

MySQL数据库——多表操作

文章目录 前言多表关系一对一关系一对多/多对一关系多对多关系 外键约束创建外键约束插入数据删除带有外键约束的表的数据删除外键约束 多表联合查询数据准备交叉连接查询内连接查询外连接查询左外连接查询右外连接查询满外连接查询 子查询子查询关键字ALL 关键字ANY 和 SOME 关…