Spring统一功能处理
1. AOP存在的问题
- 获取参数复杂
- AOP的规则相对简单
2. 拦截器
2.1. 应用(以登录为例)
2.1.1. 自定义拦截器
新建interceptor文件夹
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;@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("username")!=null){//通过return true;}else {//没登录response.setStatus(401);return false;}}
}
2.1.2. 将自定义拦截器加入到系统配置
新建config文件夹
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springaop.interceptor.LoginInterceptor;@Configuration
public class AppConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**") //"/**"表示拦截所有.excludePathPatterns("/user/login") //除了登录.excludePathPatterns("/user/reg"); //除了注册}
}
2.1.3. 业务代码
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;@Slf4j
@RequestMapping("/user")
@RestController
public class UserController {//获取用户信息@RequestMapping("/getInfo")public String getInfo(){log.info("log.getInfo");return "get info...";}//注册@RequestMapping("/reg")public String reg(){log.info("log.reg");return "reg...";}//登录@RequestMapping("/login")public boolean login(HttpServletRequest request,String username,String password){log.info("log.login");//判断username和password是否为空
// if (username!=null && username.equals("") && password!=null && password.equals("")){
// //
// }if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){return false;}if (!"admin".equals(username) || !"admin".equals(password)){return false;}HttpSession session = request.getSession(true);session.setAttribute("username",username);return true;}
}
2.2. 排除所有静态资源方法
方法1
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") // 拦截所有接口.excludePathPatterns("/**/*.js").excludePathPatterns("/**/*.css").excludePathPatterns("/**/*.jpg").excludePathPatterns("/login.html").excludePathPatterns("/**/login"); // 排除接口
方法2
private final List<String> excludePaths = //注意List的这种方式的初始化赋值不允许再追加元素Arrays.asList("/**/*.html","blog-editormd","/css/**","/js/**","/pic/**","/user/login","/user/res");@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(excludePaths);}
2.3. 实现原理
2.3.1. 总体思路
2.3.2. 部分源码分析
拦截器是基于AOP实现的
(AOP基于动态代理(JDK|CGLIB))
3. 统一功能处理
3.1. 统一登录处理
参考上一节 拦截器的应用
3.2. 统一异常处理
对于下面的异常, 我们在访问页面的时候,不希望让用户看到
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/exception")
public class ExceptionController {//算数异常@RequestMapping("/test1")public boolean test1(){int a = 10/0;return true;}//空指针异常@RequestMapping("/test2")public boolean test2(){String str = null;System.out.println(str.length());return true;}//手动异常@RequestMapping("/test3")public boolean test3(){throw new RuntimeException("手动异常");}
}
可能出现的问题:
类上面的@RequestMapping("/ex")
访问的时候会有未知的问题,改成@RequestMapping("/exception")
比较好
3.2.1. 配置ErrorHandler
针对不同的异常,进行不同的操作
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;@Slf4j
@ControllerAdvice
@ResponseBody
public class ErrorHandler {@ExceptionHandlerpublic Object error(Exception e){HashMap<String,Object> result = new HashMap<>();log.info("内部异常:",e);result.put("success",0);result.put("code",-1);result.put("msg","内部异常");return result;}@ExceptionHandlerpublic Object error(ArithmeticException e){HashMap<String,Object> result = new HashMap<>();log.info("算数异常:",e);result.put("success",0);result.put("code",-2);result.put("msg","算术异常");return result;}@ExceptionHandlerpublic Object error(NullPointerException e){HashMap<String,Object> result = new HashMap<>();log.info("空指针异常:",e);result.put("success",0);result.put("code",-3);result.put("msg","空指针异常");return result;}
}
3.2.1.1. 可能会遇到的问题
①写完代码访问的时候,会是错误404, 而且异常是返回的不是一个视图, 需要添加@ResponseBody
注解,让程序意识到返回的就是数据, 而不是视图
②分辨不出来异常
之前在切面的@Around环绕通知里有一段代码
要是遇到了异常都会抛出RuntimeException, 从而掩盖了真正的异常, 需要改成下面的样子, 抛出真正的异常
3.3. 统一数据返回格式
3.3.1. 好处
统一数据返回格式的优点有很多. 比如以下几个:
- 方便前端程序员更好的接收和解析后端数据接口返回的数据
- 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就行了,因为所有接口都是这样返回的
- 有利于项目统一数据的维护和修改
- 有利于后端技术部门的统一规范的标准制定,不会出现稀奇古怪的返回内容
3.3.2. 代码
新建ResponseHandler
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 ResponseHandler implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true; //一定要改成true}@SneakyThrows@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {HashMap<String,Object> result = new HashMap<>();result.put("success",1);result.put("data",body);result.put("errMsg","");//对字符串进行特殊处理if (body instanceof String){ObjectMapper mapper = new ObjectMapper();return mapper.writeValueAsString(result);}return result;}
}
添加这段代码之前, 访问成功了,得到的是true, 加上这段代码就变成了{"data":true,"success":1,"errMsg":""}
3.3.2.1. 可能出现的问题
①supports()的返回值一定要改成true
②getInfo()的业务代码的返回值是String, 会引发java.util.HashMap cannot be cast to java.lang.String
错误. 由于内部的数据类型转换问题导致, 解决方法是加一步验证.
这段代码会有异常, 用@SneakyThrows
处理. 这个注解的作用就是自动生成一个try-catch, 直接抛出异常
相关文章:

Spring统一功能处理
1. AOP存在的问题 获取参数复杂AOP的规则相对简单 2. 拦截器 2.1. 应用(以登录为例) 2.1.1. 自定义拦截器 新建interceptor文件夹 import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest; import javax.servlet.http…...

搭建CFimagehost私人图床,实现公网远程访问的详细指南
文章目录 1.前言2. CFImagehost网站搭建2.1 CFImagehost下载和安装2.2 CFImagehost网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道(云端设置)3.3.Cpolar稳定隧道(本地设置) 4.公网访问测…...
Python的logging.config模块
要使用Python的logging.config模块记录一个月的日志数据,你可以按照以下步骤进行操作: 首先,导入必要的模块: import logging import logging.config import datetime创建一个配置文件,例如logging.ini,用…...
【2023】LeetCode HOT 100——滑动窗口子串
目录 1. 无重复字符的最长子串1.1 C++实现1.2 Python实现1.3 时空分析2. 找到字符串中所有字母异位词2.1 C++实现2.2 Python实现2.3 时空分析3. 和为 K 的子数组3.1 C++实现3.2 Python实现3.3 时空分析4. 滑动窗口最大值4.1 C++实现4.2 Python实现4.3 时空分析5. 最小覆盖子串5…...

【云卓笔记】mavlink java文件
根据飞控提供的xml文件来生成的 生成的就是这样的java文件 准备工作: Mavlink协议生成 参考 1.安装mavlink : 使用MAVLink工具的要求是 Python 3.3 (recommended) or Python 2.7 Python future模块 (可选) PythonTklnter模块(如果需要使用图形用户界面)。 环境变量PYTHO…...

电机控制软件框架
应用层包括main 主函数模块,ISR 中断处理函数模块、时基Systick 模块和BLDC 应用接口模块;算法层包括BLDC Algorithm 模块和PID control 模块;驱动层(Driver layer):包括GD32Fxx_Standard_peripheral libra…...

SCCB与IIC的异同及FPGA实现的注意事项
文章目录 前言一、信号线二、SCCB数据传输格式三、SCCB写(与IIC完全一致)四、SCCB读五、SCCB和IIC的区别 前言 IIC接口有比较广泛的应用,而SCCB(Serial Camera Control Bus,串行摄像头控制总线)是由OV&…...

【开发】安防监控视频智能分析平台新功能:安全帽/反光衣/安全带AI识别详解
人工智能技术已经越来越多地融入到视频监控领域中,近期我们也发布了基于AI智能视频云存储/安防监控视频AI智能分析平台的众多新功能,该平台内置多种AI算法,可对实时视频中的人脸、人体、物体等进行检测、跟踪与抓拍,支持口罩佩戴检…...

数据结构 - 线性表的顺序存储
一、顺序存储定义: 把逻辑上相邻的数据元素存储在物理上相邻的存储单元中。简言之,逻辑上相邻,物理上也相邻顺序表中,任一元素可以随机存取(优点) 二、顺序表中元素存储位置的计算 三、顺序表在算法中的实…...

栈和队列在数据结构中的应用
文章目录 理解栈和队列的概念及其特点栈的应用和操作队列的应用和操作结论 🎉欢迎来到数据结构学习专栏~探索栈和队列在数据结构中的应用 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客🎈该系列文章专栏:…...

AndroidStudio升级后总是Read Time Out的解决办法
AndroidStudio升级后在gradle的时候总是Time out,遇到过多次,总结一下解决办法 1、gradle下载超时 在工程目录../gradle/wrapper/gradle-wrapper.properties中找到gradle版本的下载链接,如下图: 将其复制到迅雷里下载࿰…...

升级Go 版本到 1.19及以上,Goland: file.Close() 报错: Unresolved reference ‘Close‘
错误截图 解决方法 File -> Settings -> Go -> Build Tags & Vendoring -> Custom tags -> 添加值 “unix” 原因 Go 1.19 引入了unix构建标签。因此,需要添加unix到自定义标签。 参考 https://blog.csdn.net/weixin_43940592/article/det…...
进程,线程,协程
1、进程 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下…...

车联网技术介绍
上图是目前车联网架构图,基于“云-管-端”的车联网系统架构以支持车联网应用的实现, “云”是指 V2X 基础平台、高基于精度定位平台等基础能力,可实现车辆动态厘米级定位,这将满足现阶段以及未来车联网应用场景的定位精度需求。 “…...

并发-线程池
阻塞队列 笔记地址 点击进入 队列:先进先出 限定在一端进行插入,一端进行删除 出队为队头,入队为队尾 阻塞队列 BlockingQueue Queue接口继承Collection接口添加元素:add(),队列满了对抛出异常offer(),队…...

openCV实战-系列教程5:边缘检测(Canny边缘检测/高斯滤波器/Sobel算子/非极大值抑制/线性插值法/梯度方向/双阈值检测 )、原理解析、源码解读
打印一个图片可以做出一个函数: def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 1、Canny边缘检测流程 Canny是一个科学家在1986年写了一篇论文,所以用自己的名字来命名这个检测算法,Canny边缘检测算法…...

【数据仓库】Linux、CentOS源码安装Superset
Linux、CentOS源码安装Superset步骤,遇到的各种问题。 报错问题: Linux下pip版本问题 You are using pip version 8.1.2, however version 22.2.2 is available. 解决办法: 安装python3的pip yum install python3-pip再升级 pip3 install…...
高并发网站的负载均衡设计
大型高并发网站的负载均衡设计通常包含以下方面: 1. 硬件负载均衡器 在入口使用专业的硬件F5等负载均衡器,实现流量分发,并承担第一层保护。 2. DNS轮询/一致性哈希 结合DNS,使用轮询或一致性哈希方式将请求分散到后端不同的真实服务器。 3. CDN负载均衡 针对静态资源,使用C…...

Unity C# 之 Task、async和 await 、Thread 基础使用的Task的简单整理
Unity C# 之 Task、async和 await 、Thread 基础使用的Task的简单整理 目录 Unity C# 之 Task、async和 await 、Thread 基础使用的Task的简单整理 一、Task、async和 await 、Thread 基础概念 1、线程,多线程 2、Task 3、async (await )…...
介绍 Docker 的基本概念和优势,以及在应用程序开发中的实际应用。
Docker是一个开放源代码的容器化平台,可以将应用程序及其依赖项打包到一个轻量级的容器中,以便在任何地方运行。以下是Docker的基本概念和优势: 基本概念: 镜像(image):Docker的基本构建块&am…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...