当前位置: 首页 > news >正文

【JavaEE进阶】拦截器与统一功能处理

文章目录

  • 一. 用户登录权限效验
    • 1. 最初用户登录验证
    • 2. Spring AOP 用户统一登录的验证
    • 3. Spring拦截器
      • 3.1 自定义拦截器
      • 3.2 将自定义拦截器设置到当前的项目中
    • 4. 拦截器实现的原理
  • 二. 统一的异常处理
    • 1. 统一的异常处理优点
    • 2. 统一的异常处理实现
  • 三. 统一数据返回格式
    • 1. 统一数据返回格式的优点
    • 2. 统一数据返回格式的实现
    • 3. 统一移除处理在遇到String返回时报错问题
  • 小结

AOP思想的体现主要分为两个方面:

  1. Spring AOP用于分离功能性需求和非功能性需求,使得开发人员可以集中处理某一个关注点,减少对业务代码的侵入,增强代码的可读性和可维护性.
  2. SpringBoot的统一功能处理模块.

一. 用户登录权限效验

1. 最初用户登录验证

我们最初对用户登录验证的实现是这样的:

package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;@RestController
@RequestMapping("/user")
public class UserController {//执行的方法1@RequestMapping("/m1")public Object method1(HttpServletRequest request){//有 session 就创建,没有 session 就不会创建HttpSession session = request.getSession(false);if(session != null && session.getAttribute("userinfo") != null){//说明已经登录,执行业务处理return true;}else {//未登录return false;}}//执行的方法2@RequestMapping("/m1")public Object method2(HttpServletRequest request){//有 session 就创建,没有 session 就不会创建HttpSession session = request.getSession(false);if(session != null && session.getAttribute("userinfo") != null){//说明已经登录,执行业务处理return true;}else {//未登录return false;}}//其他需要执行的方法...
}

从上述代码可以看出,每个方法的执行都有用户登录验证权限,它的缺点如下:

  1. 每个方法中都单独写用户登录验证的方法,即使封装成公共方法,也是一样要传参调用和在方法中进行判断.
  2. 添加控制器越多,调用用户登录验证的方法就越多,这样就增加了后期的修改成本和维护成本.
  3. 这些用户登录验证的方法和下面要执行的业务代码没有什么关系,但是在每个方法中都实现了一遍.

所以接下来我们提供一个公共的AOP方法来进行统一的用户登录权限验证.

2. Spring AOP 用户统一登录的验证

使用SpringAOP的具体实现代码如下:

package com.example.demo.common;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
public class UserAspect {// 定义切点⽅法 controller 包下、⼦孙包下所有类的所有⽅法@Pointcut("execution(* com.example.demo.controller..*.*(..))")public void pointcut(){ }// 前置⽅法@Before("pointcut()")public void doBefore(){}// 环绕⽅法@Around("pointcut()")public Object doAround(ProceedingJoinPoint joinPoint){Object obj = null;System.out.println("Around 方法开始执行");try {// 执⾏拦截⽅法obj = joinPoint.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println("Around 方法结束执行");return obj;}
}

如果要在以上 Spring AOP的切面中实现用户登录权限效验的功能,有以下两个问题:

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

那么我们应该如何解决呢?

3. Spring拦截器

针对以上问题,Spring中提供了具体的实现拦截器:HandlerInterceptor.拦截器的实现分为两个部分:

  1. 创建自定义拦截器,实现HandlerInterceptor接口的preHandle(执行具体方法之前的预处理)方法.
  2. 将自定义拦截器加入WebMvcConfigureraddInterceptors方法中.

具体实现如下:

3.1 自定义拦截器

实现一个UserInterceptor用户拦截器类,在该类中实现HandlerInterceptor接口,再重写preHandle方法
在这里插入图片描述

package com.example.demo.interceptor;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
public class UserInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//业务方法//从请求中取session,如果有session,直接获取到,但是没有,这里设置为false,也不会新创建一个session。HttpSession session  = request.getSession(false);//这里添加false表示不会新创建session。方法中默认的是true。if(session!=null && session.getAttribute("userinfo")!=null){return true;}response.setStatus(401);//返回一个404return false;}
}

getAttribute方法是Object类中的方法,用于获取对象的指定属性值,它接受一个参数,即要获取的属性的名称,并返回该属性的值,如果对象中不存在指定名称的属性,则返回null。该方法可以用于获取对象的任意属性,包括实例变量和静态变量。

3.2 将自定义拦截器设置到当前的项目中

实现一个AppConfig类用来配置,实现WebMvcConfigurer接口,然后重写其中的addInterceptor方法.
在这里插入图片描述

package com.example.demo.config;import com.example.demo.interceptor.UserInterceptor;
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;@Configuration
public class AppConfig implements WebMvcConfigurer {@Autowiredprivate UserInterceptor userInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(userInterceptor).addPathPatterns("/**")// 表示拦截所有的请求.excludePathPatterns("/user/reg")//排除不拦截的url.excludePathPatterns("/user/login")//排除不拦截的url;}
}

这里的addInterceptor方法接受一个参数,就是要添加的拦截器对象。可以通过该方法添加一个或多个拦截器。
我们可以写一个UserController1测试类看一下运行结果:

package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/reg")public String reg(){return "do reg.";}@RequestMapping("/login")public String login(){return "do login.";}@RequestMapping("/test")public String test(){return "do Test.";}
}

由于我们的拦截器中拦截了所有的请求但是除了/user/reg /user/login方法,所以这两个方法可以执行成功.而我们的Test方法则被拦截,返回401状态码.
在这里插入图片描述
当我们想要排除所有的静态文件,静态文件包含图片文件,前端的JS和CSS等文件,这个时候我们不可能将每种格式的文件都手动进行排除,这样工作量也太大了(图片文件存在几十种格式),想要将这些文件排除掉我们可以将这个静态文件放入项目的static目录中,然后针对这个目录中的子目录(图片,css文件,js文件)进行排除。

excludePathPatterns("/image/**")//表示排除image目录下的所有图片

在这里插入图片描述

4. 拦截器实现的原理

没有实现拦截器的时候,用户发送的请求直接被控制层接收到,进而在相应的URL中进行登录校验,这种方式代码的可维护性较低。

但是使用拦截器,用户发送的请求首先会被拦截器接收到,拦截器进行预处理,符合条件才会进一步调用Controller层的方法。
在这里插入图片描述

二. 统一的异常处理

我们之前处理异常的方法就是使用try-catch,或者是将异常抛出去给更上一层处理,这种方式处理异常的方式通常是分散在代码的各个部分中的,当应用程序出现异常时,开发需要在每个可能抛出异常的地方编写相应的异常处理代码,这样做会导致代码冗余,可读性差,并且难以维护。

1. 统一的异常处理优点

而使用统一的异常处理就可以:

  1. 集中处理异常:通过使用统一的异常处理机制,可以集中处理应用程序中的异常。这意味着无论在哪个控制器方法或服务方法中抛出异常,都可以在统一的地方进行处理,从而减少代码冗余。
  2. 统一错误响应:统一的异常处理机制可以确保应用程序返回一致的错误响应给客户端。这样做可以提高用户体验,让客户端能够更容易地理解和处理错误情况。
  3. 异常日志记录:通过统一的异常处理,可以方便地实现异常的日志记录。可以在异常处理器中添加日志记录的逻辑,记录异常的详细信息、发生时间和相关的上下文信息,以便后续的错误分析和故障排查。
  4. 异常转换和封装:统一的异常处理机制还可以进行异常的转换和封装。例如,可以将底层框架或第三方库的异常转换为应用程序定义的自定义异常,以简化异常的处理和管理。
  5. 统一的异常处理策略:通过统一的异常处理,可以定义全局的异常处理策略。可以根据不同的异常类型采取不同的处理方式,例如返回特定的错误码、跳转到指定的错误页面或执行其他自定义逻辑。

2. 统一的异常处理实现

在Spring Boot中,可以使用@RestControllerAdvice注解和@ExceptionHandler注解来实现统一异常处理。这两个注解搭配使用表示的是全局异常处理,可以捕获并处理全局范围内的异常。当控制器中抛出异常时,会根据异常类型匹配对应的@ExceptionHandler方法进行处理。
Exception类是Java中所有异常类的父类。

  • @RestControllerAdvice注解用在一个类上,表示该类是一个全局的控制器增强器,可以对所有的控制器进行统一的处理。这个注解提供了一种集中管理和统一处理全局范围内操作的方式,在引用程序中起到了很好的代码复用和统一管理的作用。
  • @ExceptionHandler注解,用于定义一个方法,**该方法用于处理控制器中发生的异常。**当控制器中的方法抛出异常时,@ExceptionHandler注解标记的方法将被调用来处理该异常。这样可以集中处理控制器中的异常。
  1. 创建一个异常处理类
    在这里插入图片描述
  2. 创建异常检测的类和处理业务方法:
package com.example.demo;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
@ResponseBody
public class MyExpectionAdvice {@ExceptionHandler(NullPointerException.class)public HashMap<String,Object> doNullPointerExpection(NullPointerException e){HashMap<String,Object> result = new HashMap<>();result.put("code",-1);result.put("msg","空指针"+e.getMessage());result.put("data",null);return result;}
}

写个UserController测试一下:

package com.example.demo.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/login")public int login() {//空指针异常Object obj = null;System.out.println(obj.hashCode());return 1;}
}

在这里插入图片描述
此时我们就可以告诉前端异常的类型.上述代码我们处理了空指针异常,通常情况下,我们无法预测代码会抛出什么异常.所以我们可以使用所有异常的父类Expection来处理:

    //默认的异常处理@ExceptionHandler(Exception.class)public HashMap<String, Object> doException(Exception e) {HashMap<String, Object> result = new HashMap<>();result.put("code", -300);result.put("msg", "Exception:" + e.getMessage());result.put("data", null);return result;}

那么上述doException方法也可以处理空指针异常,当上述两个处理异常的方式同时存在时,首先采用的是doNullPointerExpection:(有子类先开始处理子类,再处理父类)
在这里插入图片描述

三. 统一数据返回格式

1. 统一数据返回格式的优点

  • 方便前端程序员更好的接收和解析后端数据接口返回的数据。
  • 降低前端程序员和后端程序员的沟通成本,按照某个个格式实现就行了,因为所有返回接口都是这样返回的
  • 有利于项目统一数据的维护和修改
  • 有利于后端技术部门的统一规范的标准指定,不会出现稀奇古怪的返回内容。

总结起来,统一数据返回格式可以提高接口的规范性、可读性和可维护性,方便异常处理,支持扩展和版本控制,并增强系统的兼容性。这些优点都有助于提高开发效率、减少错误和提升用户体验。

2. 统一数据返回格式的实现

统一的数据返回格式可以使用@ControllerAdvice+ResponseBodyAdvice的方式实现,实现步骤如下:
实现ResponseBodyAdvice接口.并重写其中的方法supports beforeBodyWrite方法:
值得注意的是在此类中不需要加入@ResponseBody注解,这是因为在该类中只是对返回值进行转换.

package com.example.demo.controller;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 {//是否执行 beforeBodyWrite 方法,true=执行,重写返回结果@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}//返回数据之前进行数据重写//@param body :原始返回值@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {// HashMap<String,Object>  ->  code,msg,dataif (body instanceof HashMap) {return body;}// 重写返回结果,让其返回一个统一的数据格式HashMap<String, Object> result = new HashMap<>();result.put("code", 200);result.put("data", body);result.put("msg", "");return result;}
}

写个测试方法测试一下:

    @RequestMapping("/test")public int test(){return 666;}

在这里插入图片描述
可以看到,上述结果返回的是我们指定的数据格式.

3. 统一移除处理在遇到String返回时报错问题

但是上述返回值有一个问题,即如果返回的类型是String类型时会报错:
测试方法:

    @RequestMapping("/test1")public String test1(){return "dotest1";}

运行结果:
在这里插入图片描述

要注意其返回的流程:

  1. 方法返回的是String
  2. 统一数据返回之前处理-> String Convert HashMap
  3. 将 HashMap 转换成 application/json 字符串给前端(接口)

显然,Exception:java.util.HashMap cannot be cast to java.lang.String是第三步出现了问题.第三步在执行的时候会判断Body的类型,如果是String类型,那么执行StringHttpMessageConverter进行类型转换;如果不是String类型,那么执行HttpMessageConverter进行类型转换.问题就出在了将HashMap 转换成 application/json 字符串给前端(接口).针对以上问题,有两种解决方式:

  1. StringHttpMessageConverter去掉:
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;@Configuration
public class MyConfig implements WebMvcConfigurer {//移除 StringHttpMessageConverter@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.removeIf(converter -> converter instanceof StringHttpMessageConverter);}
}
  1. 在统一数据重写时,单独处理String 类型,让其返回一个String 字符串,而非 HashMap
 @Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {// HashMap<String,Object>  ->  code,msg,dataif (body instanceof HashMap) {return body;}// 重写返回结果,让其返回一个统一的数据格式HashMap<String, Object> result = new HashMap<>();result.put("code", 200);result.put("data", body);result.put("msg", "");if(body instanceof String){// 返回一个 将对象转换成 JSON String 字符串try {return objectMapper.writeValueAsString(result);} catch (JsonProcessingException e) {e.printStackTrace();}}return result;}

注意在上述代码中使用import com.fasterxml.jackson.databind.ObjectMapper包下的objectMapper方法需要引入Maven-jackson依赖:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId>
</dependency>

在这里插入图片描述

小结

自定义拦截器的实现:使用HandlerInterceptor接口+WebMvcConfigurer接口实现。
统一异常的处理:使用@RestControllerAdvice注解+@ExceptionHandler注解实现。
统一数据返回格式:使用@ControllerAdvice注解+ResponseBodyAdvice接口实现。

相关文章:

【JavaEE进阶】拦截器与统一功能处理

文章目录 一. 用户登录权限效验1. 最初用户登录验证2. Spring AOP 用户统一登录的验证3. Spring拦截器3.1 自定义拦截器3.2 将自定义拦截器设置到当前的项目中 4. 拦截器实现的原理 二. 统一的异常处理1. 统一的异常处理优点2. 统一的异常处理实现 三. 统一数据返回格式1. 统一…...

2023年智慧政务一网通办云平台顶层设计与建设方案PPT

导读&#xff1a;原文《2023年智慧政务一网通办云平台顶层设计与建设方案PPT》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 部分内容&#xff1a; 喜欢文章&#…...

安防监控/视频汇聚平台EasyCVR调用rtsp地址返回的IP不正确是什么原因?

安防监控/云存储/磁盘阵列存储/视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RT…...

媒体服务器与视频服务器有什么区别

媒体服务器与视频服务器有什么区别 流媒体服务器用在远程教育&#xff0c;视频点播、网络电台、网络视频等方面。 直播过程中就需要使用流媒体服务器&#xff0c;一个完整的直播过程&#xff0c;包括采集、处理、编码、封包、推流、传输、转码、分发、解码、播放等过程&#xf…...

菜鸟教程《Python 3 教程》笔记(11):循环语句

菜鸟教程《Python 3 教程》笔记&#xff08;11&#xff09; 11 循环语句11.1 while 循环11.1.1 while 循环使用 else 语句 11.2 for 语句11.2.1 for...else 11.3 break 和 continue 语句及循环中的 else 子句 11 循环语句 出处&#xff1a; 菜鸟教程 - Python3 循环语句 11.1…...

【DevOps视频笔记】8. Jenkins 配置

一、Jenkins 入门配置 1. 工具 / 插件 介绍 二、插件和工具配置 1. 配置 JDK 和 Maven Stage 1&#xff1a;将服务器中 JDK 和 Maven 映射到 jenkins 容器中 Stage 2&#xff1a;jenkins 全局配置中 -- 指定JAVA_HOME目录 Stage 3&#xff1a;jenkins 全局配置中 -- 指定…...

C# 在Color[] colorTable中快速找到Color的索引位置

C# 在Color[] colorTable中快速找到Color的索引位置 第一种方法&#xff1a; 如果您需要在Color[] colorTable中快速查找特定Color的索引位置&#xff0c;可以使用C#的Array.FindIndex方法。这个方法接受一个回调函数作为参数&#xff0c;该函数定义了如何判断数组元素是否与…...

go学习笔记 炒土豆丝

今天的主菜是土豆&#xff0c;就来个土豆丝吧。我的大致流程如下&#xff1a; 1.挑选白瓤土豆&#xff0c;洗它 2.土豆去皮 3.土豆切片&#xff0c;切丝&#xff0c;丝要粗细均匀 4.清洗几遍土豆丝&#xff0c;去除上面的淀粉&#xff0c;在清水中泡一小会 5.起锅&#xff0c;放…...

FPGA VR摄像机-拍摄和拼接立体 360 度视频

本文介绍的是 FPGA VR 相机的第二个版本&#xff0c;第一个版本是下面这样&#xff1a; 第一版地址&#xff1a; ❝ https://hackaday.io/project/26974-vr-camera-fpga-stereoscopic-3d-360-camera ❞ 本文主要介绍第二版本&#xff0c;第二版本的 VR 摄像机&#xff0c;能够以…...

vue集成mars3d后,basemaps加不上去

首先&#xff1a; <template> <div id"centerDiv" class"mapcontainer"> <mars-map :url"configUrl" οnlοad"onMapload" /> </div> </template> <script> import MarsMap from ../component…...

油管视频直接生成PPT的AI工具!剖析c.ai和Pi的用户需求;独立创业者的操作指南;广告大佬的三个AI绘画实战 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 2023 CCF BDCI 数字安全公开赛&#xff0c;大模型安全竞赛等你「码」力全开 网站&#xff1a;https://www.datafountain.cn/special/B…...

WebSocket- 前端篇

官网代码 // 为了浏览器兼容websocketconst WebSocket window.WebSocket || window.MozWebSocket// 创建连接 this.socket new WebSocket(ws://xxx)// 连接成功this.socket.onopen (res)>{console.log(websocket 连接成功)this.socket.send(入参字段) // 传递的参数字段}…...

如何在 Python 中将图像转换为 PDF

一、说明 如何使得图像转化成pdf文件&#xff0c; 想要将一个或多个图像转换为 PDF 文档&#xff1f;看看img2pdf和PyPDF2软件包就是您的最佳选择。 二、需要哪些程序包&#xff1f; 首先&#xff0c;您只需要一个 Python 环境&#xff0c;最好是 3.10 或更高版本。本教程中的代…...

使用python编写脚本测试目标主机的TCP端口连通性

使用Python的Socket模块的connect()函数来尝试连接目标主机的特定端口。如果连接成功&#xff0c;则说明该端口是打开的&#xff1b;否则&#xff0c;该端口是关闭的。 下面是一个示例脚本&#xff0c;可以检测目标IP的22端口是否开启&#xff1a; import socket def check_po…...

华为云云服务器评测|基于华为云云耀云服务器L实例开展性能评测,例如 MySQL、Clickhouse、Elasticsearch等等

在当今云计算时代&#xff0c;越来越多的企业和个人开始选择将应用部署在云服务器上&#xff0c;以便更好地满足高性能、可靠性和可扩展性等需求。而华为云云耀云服务器L实例不仅提供了高性能和可靠性的计算和存储资源&#xff0c;而且具有灵活和高效的成本控制&#xff0c;深受…...

Git分布式版本控制系统与github

第四阶段提升 时 间&#xff1a;2023年8月29日 参加人&#xff1a;全班人员 内 容&#xff1a; Git分布式版本控制系统与github 目录 一、案例概述 二、版本控制系统 &#xff08;一&#xff09; 本地版本控制 &#xff08;二&#xff09;集中化的版本控制系统 &…...

基于Java+SpringBoot+Vue前后端分离中国陕西民俗网设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…...

CSS3D+动画

CSS3D 1.css3D 给父元素设置 perspective:景深:近大远小的效果900-1200px这个范围内 transform-style:是否设置3D环境 flat 2D环境 默认值 perserve-3D环境 3D功能函数 1.位移: translateZ()translate3D(x,y,z) <!DOCTYPE html> <html lang"en"><h…...

list对象中如何根据对象中某个属性去重使用Java8流实现

list对象中如何根据对象中某个属性去重使用Java8流实现? 在 Java 8 的流操作中&#xff0c;可以使用 distinct 方法来对一个对象流进行去重&#xff0c;但是默认情况下它会使用对象的 equals() 方法来判断重复。如果你希望根据对象的某个属性进行去重&#xff0c;则可以使用 …...

2023 在Windows上的安装Faiss-GPU(使用anaconda)

该方法安装完 faiss-gpu 之后&#xff0c;不仅会装这个库&#xff0c;还会装很多依赖库。为了防止自己本地一些同名库的版本被修改&#xff0c;建议新建一个虚拟环境来安装。如果本地库版本修改对自己没影响&#xff0c;也可以忽略。 你好&#xff0c;我是悦创。 登录网站&…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

TCP/IP 网络编程 | 服务端 客户端的封装

设计模式 文章目录 设计模式一、socket.h 接口&#xff08;interface&#xff09;二、socket.cpp 实现&#xff08;implementation&#xff09;三、server.cpp 使用封装&#xff08;main 函数&#xff09;四、client.cpp 使用封装&#xff08;main 函数&#xff09;五、退出方法…...