JavaEE高阶---SpringBoot 统⼀功能处理

news2025/1/13 7:26:29

一:什么是SpringBoot 统⼀功能处理

SpringBoot统一功能处理是AOP的实战环节。我们主要学习三方面内容:

  1. 统一用户登录权限验证;
  2. 统一数据格式返回;
  3. 统一异常处理。

二:统一用户登录权限验证

Spring 中提供了具体的实现拦截器:HandlerInterceptor,拦截器的实现分为以下两个步骤:

  1. 创建⾃定义拦截器,实现 HandlerInterceptor 接⼝的 preHandle(执⾏具体⽅法之前的预处理)⽅法。
  2. 将⾃定义拦截器加⼊ WebMvcConfigurer 的 addInterceptors ⽅法中。

此处我创建一个新的项目:

在这里插入图片描述

在这里插入图片描述

  1. 创建⾃定义拦截器,实现 HandlerInterceptor 接⼝的 preHandle(执⾏具体⽅法之前的预处理)⽅法。
package com.example.demo.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 登录拦截器
 */
@Component
@Slf4j
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;
        }
        log.error("当前用户没有访问权限");
        response.setStatus(401);
        return false;
    }
}

  1. 将⾃定义拦截器加⼊ WebMvcConfigurer 的 addInterceptors ⽅法中。
package com.example.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/user/login") // 排除不拦截的url
                .excludePathPatterns("/user/reg"); // 排除不拦截的url
    }
}

查看UserController中的具体方法[这里写了三个方法]:

package com.example.demo.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.net.PasswordAuthentication;

@RestController
@RequestMapping("user")
@Slf4j
public class UserController {
    @RequestMapping("/login")
    public boolean login(HttpServletRequest request,
                         String username,String password) {
//        //1.非空判断
//        if(username != null && username != "" &&
//           password != null && password != "") {
//            //2.验证用户名和密码是否正确
//        }

        //1.非空判断[高端写法]
        if(StringUtils.hasLength(username) && StringUtils.hasLength(password)) {
            //2.验证用户名和密码是否正确
            if(username.equals("admin") && password.equals("admin")) {
                //登录成功
                HttpSession session = request.getSession();
                session.setAttribute("userinfo","admin");
                return true;
            } else {
                //用户名或密码输入错误
                return false;
            }
        }
        return false;
    }

    @RequestMapping("getinfo")
    public String getInfo() {
        log.debug("执行了 getinfo 方法");
        return " 执行了 getinfo 方法";
    }

    @RequestMapping("reg")
    public String reg() {
        log.debug("执行了 reg 方法");
        return " 执行了 reg 方法";
    }
}

根据我们设定的拦截规则,只有执行getinfo()时才会被拦截。

执行reg方法,成功执行;

在这里插入图片描述

执行getinfo方法,拦截器生效:

在这里插入图片描述

在这里插入图片描述

这就是拦截器的基本实现。正常情况下的调用顺序是:

在这里插入图片描述

有拦截器之后,会在调用Controller之前进行相应的业务处理:

在这里插入图片描述

实现原理源码分析:

所有的 Controller 执⾏都会通过⼀个调度器 DispatcherServlet 来实现,这⼀点可以从 Spring Boot 控制台的打印信息看出,如下图所示:

在这里插入图片描述

⽽所有⽅法都会执⾏ DispatcherServlet 中的 doDispatch 调度⽅法,而在doDispatch调度方法中开始执⾏ Controller 之前,会先调用预处理⽅法 applyPreHandle,在 applyPreHandle 中会获取所有的拦截器 HandlerInterceptor 并执⾏拦截器中的 preHandle ⽅法,这样就和我们前⾯定义的拦截器对应上了。

拦截器小结:

Spring 中的拦截器也是通过动态代理和环绕通知的思想实现的,⼤体的调⽤流程如下:

在这里插入图片描述

统一用户登录权限的验证步骤如下:

在这里插入图片描述
在这里插入图片描述

三:统一异常处理

统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执⾏某个通知,也就是执⾏某个⽅法事件,具体实现代码如下:

package com.example.demo.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;

/**
 * 统一异常处理
 */
@ControllerAdvice
public class ErrorAdvice {
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public HashMap<String,Object> exceptionAdvice(Exception e) {
        HashMap<String,Object> result = new HashMap<>();
        result.put("code",-1);
        result.put("msg","总异常信息为" + e.getMessage());
        return result;
    }

    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody
    public HashMap<String, Object> arithmeticAdvie(ArithmeticException e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", "-2");
        result.put("msg","算数运算异常" + e.getMessage());
        return result;
    }



}


此处设计一个算术运算异常用于检验:

    @RequestMapping("reg")
    public String reg() {
        int num = 10/0;
        log.debug("执行了 reg 方法");
        return " 执行了 reg 方法";
    }

在这里插入图片描述

再设计一个空指针异常:


    @RequestMapping("reg")
    public String reg() {
        Object obj = null;
        System.out.println(obj.hashCode());
        log.debug("执行了 reg 方法");
        return " 执行了 reg 方法";
    }

在这里插入图片描述

四:统一数据返回格式

首先,为什么需要统一数据的返回格式呢?

统⼀数据返回格式的优点有很多,⽐如以下⼏个:

  1. ⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据。
  2. 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就⾏了,因为所有接⼝都是这样返回的。
  3. 有利于项⽬统⼀数据的维护和修改。
  4. 有利于后端技术部门的统⼀规范的标准制定,不会出现稀奇古怪的返回内容。

统⼀的数据返回格式可以使⽤ @ControllerAdvice + ResponseBodyAdvice 的⽅式实现,具体实现代码如下:

package com.example.demo.config;

import org.springframework.beans.factory.parsing.ReaderEventListener;
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;

/**
 * 统一数据返回格式
 */
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Override
//    返回 true 表示重写
    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("code",200);
        result.put("msg","");
        result.put("data",body);
        return result;
    }
}

访问具体的方法:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

此时数据返回的格式就统一了!

注意,在自定义拦截器时,我们添加了@Configuration注解;在进行统一异常处理和统一数据格式返回时,我们添加了@ControllerAdvice注解。只有添加了这些注解,Spring项目才能在执行到相应的逻辑时感知到统一格式处理的存在,进而触发下面的代码。说白了,要想实现SpringBoot统一功能的处理,就要遵循官方的书写规范。

本节内容到此结束!

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

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

相关文章

通过后端代理实现Web搜索功能

大家好&#xff0c;才是真的好。 前面我们都在说使用Domino自带的视图搜索功能&#xff0c;这一篇也是&#xff0c;不过不是视图搜索&#xff0c;而是整个Notes数据库搜索&#xff0c;然后再将结果返回给浏览器网页呈现。 前提和前面两篇都是一样的&#xff0c;即Notes应用需…

Java 如何不使用 volatile 和锁实现共享变量的同步操作

前言 熟悉 Java 并发编程的都知道&#xff0c;JMM(Java 内存模型) 中的 happen-before(简称 hb)规则&#xff0c;该规则定义了 Java 多线程操作的有序性和可见性&#xff0c;防止了编译器重排序对程序结果的影响。 按照官方的说法&#xff1a; 当一个变量被多个线程读取并且至…

「数据密集型系统搭建」原理篇|数据类型不怕精挑细选

本篇围绕MySQL数据库的底层存储模型、列类型来聊聊数据库表设计及建模中要注意的事项&#xff0c;剖析最根源的底层物理存储文件&#xff0c;用最真实的数据剖析来证明和解答开发过程中的疑惑。 在一些技术谈资、面试沟通过程中&#xff0c;MySQL特别是我们常用的Innodb存储引擎…

JavaScript 作用域

文章目录JavaScript 作用域JavaScript 作用域JavaScript 局部作用域JavaScript 全局变量JavaScript 变量生命周期函数参数HTML 中的全局变量你知道吗?JavaScript 作用域 作用域可访问变量的集合。 JavaScript 作用域 在 JavaScript 中, 对象和函数同样也是变量。 在 JavaScr…

ONES X 海银财富|以敏捷流程管理,创新金融服务平台

近日&#xff0c;ONES 签约财富管理行业领跑者——海银财富&#xff0c;助力海银财富落地敏捷流程管理&#xff0c;打造从需求到交付的一体化平台&#xff0c;快速接受业务方的反馈&#xff0c;进行金融平台的迭代与优化。海银财富管理有限公司&#xff08;以下简称海银财富&am…

拆机详解:1968年军用集成电路计算机 高级货赢在做工

halo大家好&#xff0c;这里是一天更两篇的Eric。 今天我在网上偶然看到一个拆军用计算机的&#xff0c;正好给你们分享一下。这可是1970年左右为了F4战斗机敌我识别系统打造的&#xff0c;虽说比之前说的Macintosh更加的挤也更大&#xff0c;不过做工够扎实。 上图&#xff…

centos8安装RabbitMQ和erlang

RabbitMQ 消息队列MQ RabbitMQ简称MQ是一套实现了高级消息队列协议的开源消息代理软件&#xff0c;简单来说就是一个消息中间件。是一种程序对程序的通信方法&#xff0c;其服务器也是以高性能、健壮以及可伸缩性出名的Erlang语言编写而成为什么使用MQ 在项目中&#xff0c;…

QSyntaxHighlighter

一、描述 此类用于自定义语法高亮显示规则&#xff0c;是用于实现 QTextDocument 文本高亮显示的基类。 要自定义语法高亮显示&#xff0c;必须子类化 QSyntaxHighlighter 并重新实现 highlightBlock()。此函数将在合适的时机自动被调用。 highlightBlock() 函数将格式设置应…

SOFA Weekly|SOFANews、本周贡献 issue 精选

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展欢迎留言互动&#xff5e;SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&#…

Rasa 3.x 学习系列-Rasa [3.4.0] - 2022-12-14新版本发布

Rasa 3.x 学习系列-Rasa [3.4.0] - 2022-12-14新版本发布 任何人都可以学习Rasa之优秀Rasa学习资源推荐 欢迎同学们报名Gavin老师的Rasa系列课程,任何人都可以学习Rasa之优秀Rasa学习资源推荐: 1.NLP on Transformers高手之路137课 2 .Rasa 3.X 智能对话机器人案例开发硬核…

五、k8s pod详解

文章目录1 pod介绍1.1 pod 定义2 pod配置2.1 基本配置2.2 镜像拉取2.3 启动命令2.4 环境变量2.5 端口设置2.6 资源配额3 Pod生命周期3.1 创建和终止3.2 初始化容器3.3 钩子函数3.4 容器探测3.5 重启策略4 Pod调度4.1 定向调度4.2 亲和性调度5 污点和容忍5.1 污点&#xff08;Ta…

做短视频必须了解的6个问题,你知道几个答案呢?

做短视频必须了解的6个问题&#xff0c;你知道几个答案呢&#xff1f; 最近好多朋友问了视频运营和创作的问题&#xff0c;把其中六个有代表性的问题和答案汇总在一起&#xff0c;公开给大家&#xff0c;希望对大家有所帮助。 1、账号被限流了怎么办&#xff1f; 随手拍十条…

聚观早报 | 小米同时研发两款车;谷歌计划向印度最高法院上诉

小米同时研发两款车&#xff1a;谷歌计划向印度最高法院上诉&#xff1b;苹果AR/MR头显部件延迟发货&#xff1b;2022年特斯拉在德汽车销量激增&#xff1b;纽约市教育部门禁止访问 ChatGPT 小米同时研发两款车小米第一款车为中型溜背式轿车&#xff08;内部代号 Modena 摩德纳…

欧科云链任煜男:推动区块链创新,切忌陷入“过度金融化”的桎梏

FTX破产轰动全球&#xff0c;揭示的是监管出现问题。FTX作为行业龙头&#xff0c;持有多国牌照却依然“暴雷”&#xff0c;未来到底应如何监管加密资产行业&#xff1f;针对这一问题&#xff0c;欧科云链控股(01499.HK)公司执行董事、董事局主席兼行政总裁任煜男近日在接受香港…

【菜菜的CV进阶之路 - 深度学习环境搭建】windows+ubuntu20.04双系统安装

新学期&#xff0c;配了台新电脑&#xff08;双路2080ti5800x64GB内存500GB固态2TB机械&#xff09;&#xff0c;师兄忙于毕设&#xff0c;没给装ubuntu&#xff0c;自己装一下咯~ 一、前期准备 1、空U盘一个 2、Ubuntu 20.04 LTS镜像 3、启动U盘制作软件&#xff08;我用的…

STM51嵌入式开发入门软件安装-Keil、stc、驱动

STM51嵌入式开发入门软件安装-Keil、stc、驱动 STM51嵌入式开发入门软件安装-Keil、stc、驱动 1 Keil安装 1.1 百度进入官网 1.2 选择C51,点击后需要填的信息随便填 下载好的软件链接&#xff1a;https://pan.baidu.com/s/19wxkLD69QpmPNr27KYRAxw?pwdyihl 提取码&#xff1a…

【web】微信小程序笔记小结(简介)

准备参加计算机设计大赛owo 疯狂学习微信小程序ing js也在努力兼顾kkk 写完想搞个目录结果老是跳转有问题orz&#xff0c;所以这一篇没有目录了qwq 来源&#xff1a;黑马程序员前端微信小程序开发教程 I. 小程序与普通网页的区别 ① 运行环境 网页 → 浏览器环境 小…

自定义指令binding参数

除了核心功能默认内置的指令 (v-model 和 v-show)&#xff0c;Vue 也允许注册自定义指令。注意&#xff0c;在 Vue2.0 中&#xff0c;代码复用和抽象的主要形式是组件。然而&#xff0c;有的情况下&#xff0c;你仍然需要对普通 DOM 元素进行底层操作 如果想注册局部指令&#…

自定义viewGroup

案例分析&#xff1a;继承自extends LinearLayoutpublic class MainTabBarView extends LinearLayout实现3个方法public MainTabBarView(Context context) {this(context, null);}public MainTabBarView(Context context, Nullable AttributeSet attrs) {this(context, attrs, …

Kettle--MySQL生产数据库千万、亿级数据量迁移方案及性能优化

一、Kettle环境搭建 一、Windows主要用于可视化创建数据迁移用到的ktr转换脚本、kjb作业脚本&#xff0c;以及脚本需要配置的DB2信息、读写性能优化信息等&#xff0c;也可直接在客户端完成不同数据库之间的数据迁移。 测试库表及数据 &#xff08;1&#xff09;创建测试库表…