企业为啥要做网站/站长工具在线查询
文章目录
- 前言
- 1. 拦截器
- 1.1 什么是拦截器
- 1.2 拦截器的使用
- 1.2.1 自定义拦截器
- 1.2.2 注册配置拦截器
- 1.3 拦截器详解
- 1.3.1 拦截路径
- 1.3.2 拦截器执行流程
- 1.3.3 适配器模式
- 2. 统一数据返回格式
- 3. 统一异常处理
前言
在日常使用 Spring 框架进行开发的时候,对于一些板块来说,可能需要实现一个相同的功能,这个功能可以是验证你的登录信息,也可以是其他的,但是由于各个板块实现这个功能的代码逻辑都是相同的,如果一个板块一个板块进行添加的话,开发效率就会很低,所以 Spring 也想到了这点,为我们程序员提供了 SpringBoot 统一功能处理的方法实现,我们是可以直接使用的。这篇文章我将带大家一起学习 SpringBoot 统一功能的处理。
1. 拦截器
正常的判断用户是否登录的逻辑就是通过 session 来判断,对于一些网站来说,很多的功能都是需要用户进行登录之后才可以使用的,如果此时通过 session 判断出来用户处于未登录状态的话,咱们的服务器会强制用户进行登录,通过代码来显示就是这样的:
//检验用户是否登录
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("userInfo") == null) {return "您未登录,请登录后再试试该功能吧";
}
我们想要在哪个功能前判断用户的登录信息,就需要在该功能的模块中添加上面这些代码,如果需要添加的功能较少还好,如果很多,那么就需要花费很多的时间,那么有人就说了:我是否可以将这些代码封装成函数,然后哪个模块需要使用只需要调用这些函数就可以了呢?可以是可以,但是使用函数封装代码还是需要在原代码的基础上调用这个函数,并且显得也不是那么优雅。那么是否有方法既不需要更改原代码,也可以使得我们写的代码很优雅呢?SpringBoot 为我们提供了一种功能——拦截器。
1.1 什么是拦截器
在 Spring Boot 中,拦截器是一种用于在处理请求之前或之后执行特定操作的组件。拦截器通常用于实现一些通用的功能,比如权限验证、日志记录等。拦截器可以拦截通过Controller的请求,并在请求处理前后执行特定的操作。
拦截器的思想正好符合我们执行其他功能之前进行身份验证验证,并且不仅在方法执行之前拦截器可以起作用,方法执行之后。我们的拦截器也可以起到作用。
1.2 拦截器的使用
拦截器的使用分为两个步骤:
- 定义拦截器
- 注册配置拦截器
1.2.1 自定义拦截器
我们自定义的拦截器需要实现 HandlerInterceptor 接口,并且重写这个接口中的方法。
package com.example.springbootbook2.interceptor;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("目标方法执行前执行...");HttpSession session = request.getSession(false);if (session == null || session.getAttribute("userInfo") == null) {response.setStatus(401);return false;}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("目标方法执行后执行...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("视图渲染完毕之后执行,最后执行...");}
}
- preHandle() 方法是在目标方法执行之前执行的,返回 true,继续执行后面的代码;返回 false,中断后续的操作
- postHandle() 方法是在目标方法执行之后执行的
- afterCompletion() 方法是在视图渲染之后才执行的,它还在 postHandle() 方法之后执行,并且现在因为前后端分离,我们后端基本上接触不到视图的渲染,所以这个方法使用的较少
1.2.2 注册配置拦截器
注册配置拦截器需要实现 WebMvcConfiguer 接口,并实现 addInterceptors 方法。
package com.example.springbootbook2.config;import com.example.springbootbook2.interceptor.LoginInterceptor;
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 WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**") //指定路径配置拦截器.excludePathPatterns("/user/login"); //指定路径不配置拦截器}
}
在添加拦截器进行身份校验之前,我们可以直接通过对应的 url 访问到指定功能页面。
而在我们添加拦截器之后,再看是否能直接访问某些功能。
我们启动添加了拦截器之后的代码之后,点击刷新就发现不能够直接访问到某些功能了,再搭配着前端我们就可以实现强制登录的功能了。
1.3 拦截器详解
拦截器的⼊⻔程序完成之后,接下来我们来介绍拦截器的使⽤细节。拦截器的使⽤细节我们主要介绍两个部分:
- 拦截器的拦截路径配置
- 拦截器实现原理
1.3.1 拦截路径
拦截路径是指我们定义的这个拦截器,对哪些请求生效,我们在注册配置拦截器的时候,通过 addPathPatterns()
方法指定要拦截哪些 HTTP 请求,也可以通过 excludePathPatterns()
方法指定不拦截哪些请求,上面我们的 /**
表示拦截所有的 HTTP 请求,除了可以设置拦截所有请求外,还有一些其他的拦截设置:
拦截路径 | 含义 | 举例 |
---|---|---|
/* | ⼀级路径 | 能匹配/user,/book,/login,不能匹配 /user/login |
/** | 任意级路径 | 能匹配/user,/user/login,/user/reg |
/book/* | /book下的⼀级路径 | 能匹配/book/addBook,不能匹配/book/addBook/1,/book |
/book/** | /book下的任意级路径 | 能匹配/book,/book/addBook,/book/addBook/2,不能匹配/user/login |
这些拦截规则可以拦截此项⽬中的使⽤ URL,包括静态⽂件(图⽚⽂件、JS、和 CSS 等⽂件)。
知道了如何配置拦截路径之后,我们就可以解决网页上身份验证的问题了。因为 /**
会拦截所有的请求,包括前端页面请求,所以我们需要将前端页面请求排除在拦截之外。
如果我们不讲前端页面请求在外的话机会出现这种情况:
然后我们将前端页面请求不添加拦截器的话,就可以实现完整的身份校验强制登录功能了。
@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;private List<String> excludePath = Arrays.asList("/user/login","/css/**","/js/**","/pic/**","/**/*.html"); // /**/*html中的/**表示所有路径下的所有以html结尾的文件 * 表示通配符@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(excludePath);}
}
当我们未登录,然后访问其他功能的话,就会强制跳转到登录页面:
1.3.2 拦截器执行流程
正常的调用顺序是这样的:
有了拦截器之后,会在调⽤ Controller 之前进⾏相应的业务处理,执⾏的流程如下图:
- 当我们添加拦截器之后,在执行 Controller 方法之前,请求会先被拦截器拦截,执行
preHandle()
方法,这个方法会返回一个布尔类型的值,如果返回的是 true,那么会继续执行后面的操作;如果返回的是 false,则不会执行后面的操作 - Controller 当中的方法执行完毕之后,会继续执行
postHandle()
方法以及afterHandle()
方法,执行完毕之后,返回给浏览器响应数据。
在源码中的 DispatcherServlet 类中的 doDispatch 方法中可以看到这三个方法的执行流程:
1.3.3 适配器模式
在拦截器执行的过程中还使用了适配器模式:
适配器模式(Adapter Pattern)在计算机编程中是一种常用的设计模式,主要用于解决两个不兼容的类之间的接口匹配问题。通过将一个类的接口转换成客户端所期望的另一种接口,原本因为接口不匹配而无法一起工作的两个类现在可以一起工作。
适配器模式的优点在于它能够使原本由于接口不兼容而无法一起工作的类一起工作,提高了系统的灵活性和可扩展性。同时,它也能够减少代码的重复性,因为多个源可以共享同一个适配器。
HandlerAdapter 主要⽤于⽀持不同类型的处理器(如 Controller、HttpRequestHandler 或者
Servlet 等),让它们能够适配统⼀的请求处理流程。这样,SpringMVC可以通过⼀个统⼀的接⼝
来处理来⾃各种处理器的请求。
本来 target 和 adaptee 是两个无法正常对接的事物,但是通过适配器 adapter,这两者之间就可以进行对接,也就类似于下面这个情况:
适配器模式⻆⾊:
- Target:⽬标接口(可以是抽象类或接口)客户希望直接⽤的接口
- Adaptee:适配者,但是与Target不兼容
- Adapter:适配器类,此模式的核⼼。通过继承或者引⽤适配者的对象,把适配者转为⽬标接⼝
- client:需要使⽤适配器的对象
前⾯学习的 slf4j 就使⽤了适配器模式,slf4j 提供了⼀系列打印⽇志的 api,底层调⽤的是 log4j 或者logback 来打⽇志,我们作为调⽤者,只需要调⽤ slf4j 的 api 就⾏了。
/**
* slf4j接⼝
*/
interface Slf4jApi{void log(String message);
}/**
* log4j 接⼝
*/
class Log4j{void log4jLog(String message){System.out.println("Log4j打印:"+message);}
}/**
* slf4j和log4j适配器
*/
class Slf4jLog4JAdapter implements Slf4jApi{private Log4j log4j;public Slf4jLog4JAdapter(Log4j log4j) {this.log4j = log4j;}@Overridepublic void log(String message) {log4j.log4jLog(message);}
}/**
* 客⼾端调⽤
*/
public class Slf4jDemo {public static void main(String[] args) {Slf4jApi slf4jApi = new Slf4jLog4JAdapter(new Log4j());slf4jApi.log("使⽤slf4j打印⽇志");}
}
可以看出,我们不需要改变 log4j 的api,只需要通过适配器转换下,就可以更换⽇志框架,保障系统的平稳运行。
⼀般来说,适配器模式可以看作⼀种"补偿模式",⽤来补救设计上的缺陷。应⽤这种模式算是"⽆奈之举",如果在设计初期,我们就能协调规避接⼝不兼容的问题,就不需要使⽤适配器模式了。
所以适配器模式更多的应⽤场景主要是对正在运⾏的代码进⾏改造,并且希望可以复⽤原有代码实现新的功能.。⽐如版本升级等。
2. 统一数据返回格式
如果我们完成了一个项目的开发,但是这时候,我们突然觉得后端的各个功能的返回值返回的信息不够全面,我们需要补充一些返回信息,那么这时候就意味着所有方法的返回值都需要做出修改,这也是一个不小的工作量。这时 SpringBot 又为我们提供了解决方法——统一数据返回格式。
SpringBoot 统一数据返回格式会在各个方法进行 return 返回值之前插入一些代码逻辑,从而达到改变返回值的功能。
统一的数据返回格式使用 @ControllerAdvice
和 ResponseBodyAdvice
的方式实现。ControllerAdvice
表示控制器通知类。
我们先定义一个统一的返回类型:
public enum ResultCode {SUCCESS(0),FAIL(-1),UNLOGIN(-2);//0-成功 -1 失败 -2 未登录private int code;ResultCode(int code) {this.code = code;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}
}
@Data
public class Result<T> {/*** 业务状态码*/private ResultCode code; //0-成功 -1 失败 -2 未登录/*** 错误信息*/private String errMsg;/*** 数据*/private T data;public static <T> Result<T> success(T data){Result result = new Result();result.setCode(ResultCode.SUCCESS);result.setErrMsg("");result.setData(data);return result;}public static <T> Result<T> fail(String errMsg){Result result = new Result();result.setCode(ResultCode.FAIL);result.setErrMsg(errMsg);result.setData(null);return result;}public static <T> Result<T> fail(String errMsg,Object data){Result result = new Result();result.setCode(ResultCode.FAIL);result.setErrMsg(errMsg);result.setData(data);return result;}public static <T> Result<T> unlogin(){Result result = new Result();result.setCode(ResultCode.UNLOGIN);result.setErrMsg("用户未登录");result.setData(null);return result;}}
package com.example.springbootbook2.config;import com.example.springbootbook2.model.Result;
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;@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {return Result.success(body);}
}
继承 ResponseBodyAdvice
接口后,需要实现该接口下的 supports
方法和 beforeBodyWrite
方法,supports 方法只需要更改返回值为 true 就可以了,表示是否要执行 beforeBodyWrite 方法,返回 true 表示执行,false 表示不执行,beforeBodyWrite 方法中的 body 参数就是我们原方法的返回值。
当我们关闭拦截器,访问图书列表页之后,就发现我们的返回类型发生了变化:
但是这个统一数据返回格式也存在问题,当我们的返回值为 String 类型的话机会出现错误:
这是为什么呢?SpringMVC默认会注册⼀些⾃带的 HttpMessageConverter (从先后顺序排列分别为
ByteArrayHttpMessageConverter ,StringHttpMessageConverter , SourceHttpMessageConverter ,AllEncompassingFormHttpMessageConverter )
其中 AllEncompassingFormHttpMessageConverter 会根据项⽬依赖情况添加对应的
HttpMessageConverter
在依赖中引⼊jackson包后,容器会把 MappingJackson2HttpMessageConverter ⾃动注册到
messageConverters 链的末尾。Spring会根据返回的数据类型,从 messageConverters 链选择合适的 HttpMessageConverter。当返回的数据是⾮字符串时,使⽤的MappingJackson2HttpMessageConverter 写⼊返回对象。当返回的数据是字符串时, StringHttpMessageConverter 会先被遍历到,这时会认为
StringHttpMessageConverter 可以使用。
然⽽⼦类 StringHttpMessageConverter 的addDefaultHeaders⽅法定义接收参数为String,此
时t为Result类型,所以出现类型不匹配"Result cannot be cast to java.lang.String"的异常。
那么如何解决返回类型为 String 类型的问题呢?如果返回结果为String类型, 使⽤SpringBoot内置提供的Jackson来实现信息的序列化。
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Autowiredprivate ObjectMapper objectMapper;@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@SneakyThrows@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {if (body instanceof String) {return objectMapper.writeValueAsString(Result.success(body));}else if (body instanceof Result) {return body;}else {return Result.success(body);}}
}
- @SneakyThrows 的主要目的是解决 Java 的异常处理问题。当我们在代码中抛出一个异常时,如果这个异常被包裹在一个方法中,并且这个方法没有 throws 关键字来声明会抛出这个异常,那么编译器会报错。通过使用 @SneakyThrows,你可以告诉编译器:“我知道这个方法可能会抛出异常,但我保证在 catch 块中处理它。” 这样编译器就不会报错了。
通过这个处理,当返回的数据类型为 String 的时候就不会出现错误了。
统一数据返回格式的优点:
- ⽅便前端程序员更好的接收和解析后端数据接口返回的数据
- 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就可以了,因为所有接口都是这样返回的
- 有利于项目统⼀数据的维护和修改
- 有利于后端技术部⻔的统⼀规范的标准制定,不会出现稀奇古怪的返回内容
3. 统一异常处理
当我们的程序中出现异常的时候,我们需要解决这些异常,因为前面做了统一数据返回格式的处理,所以这里的异常也可以进行统一的处理。
统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表⽰控制器通知类, @ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执行某个通知,也就是执⾏某个⽅法事件。
package com.example.springbootbook2.config;import com.example.springbootbook2.model.Result;
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;@ControllerAdvice
@Slf4j
@ResponseBody //因为返回的数据都不是视图类型,所以加上这个注解防止出现问题
public class ErrorHandler {@ExceptionHandlerpublic Result<String> exception(Exception e) {log.error("发生异常:e{}",e);return Result.fail("内部异常");}@ExceptionHandlerpublic Result<String> exception(NullPointerException e) {log.error("发生异常:e{}",e);return Result.fail("NullPointerException异常,请联系管理员");}@ExceptionHandlerpublic Result<String> exception(ArithmeticException e) {log.error("发生异常:e{}",e);return Result.fail("ArithmeticException异常,请联系管理员");}
}
@Controller
@RequestMapping("/test")
public class TestController {@RequestMapping("/t1")public Integer test1() {return 10/0;}
}
这个 Exception 和 ArithmeticException 的先后顺序可以不考虑,这个不会因为 Exception 在前面捕获就报的 Exception 异常,而是会根据自己出现的最接近的异常来捕获。
相关文章:

【Spring】SpringBoot 统一功能处理
文章目录 前言1. 拦截器1.1 什么是拦截器1.2 拦截器的使用1.2.1 自定义拦截器1.2.2 注册配置拦截器 1.3 拦截器详解1.3.1 拦截路径1.3.2 拦截器执行流程1.3.3 适配器模式 2. 统一数据返回格式3. 统一异常处理 前言 在日常使用 Spring 框架进行开发的时候,对于一些板…...

拦截器HandlerInterceptor | springmvc系列
拦截器,通俗来来将,就是我们将访问某个路径的请求给拦截下来,然后可以对这个请求做一些操作 基本使用 创建拦截器类 让类实现HandlerInterceptor接口,重写接口中的三个方法。 Component //定义拦截器类,实现Handle…...

【SQL server】DML触发器监控数据库字段值改变
文章目录 前言DML触发器基本思路创建触发器固定字段触发示例完整示例代码变量声明查询新旧值插入数据到日志表效果视频动态字段触发示例完整代码示例触发器基本信息变量声明定义游标打开游标临时表创建循环处理字段...

Docker容器(二)安装与初体验wordpress
一、安装 1.1关闭SeLinux SeLinux(Security-Enhanced Linux)是一种基于Linux内核的安全模块,旨在提供更严格的访问控制和安全策略。它通过强制实施安全策略来限制系统资源的访问,从而保护系统免受恶意软件和未经授权的访问。 在…...

Odrive 学习系列二:将烧录工具从ST-Link V2修改为JLink
一、背景: 通过观察odrive解压后的内容,可以看到在下面配置文件及makefile文件中的配置设置的均为openOCD + stlink v2,例如makefile中: # This is only a stub for various commands. # Tup is used for the actual compilation.BUILD_DIR = build FIRMWARE = $(BUILD_DI…...

ffmpeg api-codec-param-test.c源码讲解
try_decode_video_frame /*** 尝试解码视频帧** param codec_ctx 解码器上下文* param pkt 待解码的视频数据包* param decode 是否解码标志,如果为1,则进行解码,如果为0,则不解码* return 返回0表示成功,否则表示出错…...

Hive学习(14)json解析get_json_object()函数
一、语法 目的:在一个标准JSON字符串中,按照指定方式抽取指定的字符串。 string get_json_object(string <json>, string <path>) 参数说明 json:必填。STRING类型。标准的JSON格式对象,格式为{Key:Value, Key:Val…...

sqlilabs第五十五五十六关
Less-55(GET - challenge - Union- 14 queries allowed -Variation 2) 手工注入 结束 自动注入 想到一个办法能绕过需要用到IP池就可以(但是我没有) Less-56(GET - challenge - Union- 14 queries allowed -Variation 3) 手工注入...

Vue2 实现带输入的动态表格,限制el-input输入位数以及输入规则(负数、小数、整数)
Vue2 实现el-input带输入限制的动态表格,限制输入位数以及输入规则(负数、小数、整数) 在这个 Vue2 项目中,我们实现一个限制输入位数(整数16位,小数10位)以及输入规则(负数、小数、…...

反爬虫策略:使用FastAPI限制接口访问速率
目录 引言 一、网络爬虫的威胁 二、FastAPI 简介 三、反爬虫策略 四、具体实现 五、其他反爬虫策略 六、总结 引言 在当今的数字时代,数据已经成为了一种宝贵的资源。无论是商业决策、科学研究还是日常生活,我们都需要从大量的数据中获取有价值的…...

响应式编程初探-自定义实现Reactive Streams规范
最近在学响应式编程,这里先记录下,响应式编程的一些基础内容 1.名词解释 Reactive Streams、Reactor、WebFlux以及响应式编程之间存在密切的关系,它们共同构成了在Java生态系统中处理异步和响应式编程的一系列工具和框架。 Reactive Streams…...

如何使用LightPicture+cpolar搭建个人云图床随时随地公网访问
文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进,功能也越来越多,而手机…...

华媒舍:高效率的新闻资讯新闻媒体宣发套餐内容推广计划方案
怎样让自己的新闻资讯可以被大众孰知,变成了每一个新闻媒体宣发者一同存在的困难。下面我们就给大家介绍一套高效率的新闻资讯新闻媒体宣发套餐内容推广计划方案,致力于帮助新闻媒体宣发者提升宣发高效率,提高新闻资讯的传播性。 1.新闻媒体宣…...

MySQL使用通配符进行数据搜索以及过滤
目录 1.什么是通配符? 2.通配符之→百分号(%) 3.通配符之→下划线(_) 4.通配符使用注意事项 *本文涉及概念来源于图灵程序设计丛书,数据库系列——《MySQL必知必会》 1.什么是通配符? 通配符(wildcard) :用来匹配值的一部分…...

Overleaf IEEE白嫖即将失效!
之前白嫖Overleaf用IEEE的,最长只能到一月份了!(官方回复) 翻译一下: IEEE不支持这种Collaboratec白嫖了已经白嫖的,到2024年1月份过期没有白嫖的,已经无法获得了...

条件控制生成---相关论文集合
1. IP-Adapter 论文地址 解决问题: 如何将图片作为prompt输入网络,并无需更改开源模型参数 解决思路: 新增一个cross-attention layers,结果与text prompt的cross-attention layers结果相加后输入网络,只需要训练Wk, …...

揭秘亚马逊、ebay测评系统:从稳定环境搭建到防关联技术
在亚马逊、ebay平台上进行测评、lu卡和lu货、采退等活动,首要问题是确保环境的安全性和稳定性。一个稳定的环境是进行测评和lu卡、lu货、采退的基础,如果无法解决安全性问题,那么从事这些项目就不值得。我们在环境技术研发领域已经有l七年的经…...

街机模拟游戏逆向工程(HACKROM)教程:[3]街机的ROM与RAM
简介 在街机模拟器中运行一个街机游戏,我们除了需要一个模拟器工具 ,也需要有一个街机的ROM文件。街机的ROM文件,称之为Read-Only Memory,可以理解为只读存储器。在 ROM文件中,包括了游戏运行所需要的指令代码&#x…...

Element UI CascaderPanel级联组件使用和踩坑总结
Element UI CascaderPanel级联组件使用和踩坑总结 问题背景 需求中需要用到Element UI的 CascaderPanel组件,并且支持多选,定制化需求,比如某节点被选择,等价于该节点下面所有子节点都被选择, CascaderPanel组件返回…...

Oracle全系列版本官网下载保姆及教程
Oracle全系列版本官网下载方法 下面以下载Oracle12cR2为例说明下载的整个过程。 基本步骤如下: 先注册一个Oracle账号并登录;进入到客户下载页面搜索要下载的数据库版本;得到Oracle下载器(Oracle_SSN_DML_xxxxx.exe),注意…...

漏洞扫描是最该被防范的安全问题
在当今的网络环境中,漏洞扫描是一项至关重要的任务。随着技术的不断进步,网络攻击的威胁也在持续增长,而漏洞扫描是防范这些威胁的关键手段之一。 在某平台发起的“网络安全从业人员现状调查”中,在“哪些与网络安全息息相关&…...

Unity 工具 之 Azure 微软连续语音识别ASR的简单整理
Unity 工具 之 Azure 微软连续语音识别ASR的简单整理 目录 Unity 工具 之 Azure 微软连续语音识别ASR的简单整理 一、简单介绍 二、实现原理 三、注意实现 四、实现步骤 五、关键脚本 一、简单介绍 Unity 工具类,自己整理的一些游戏开发可能用到的模块&#x…...

MLP-Mixer: An all-MLP Architecture for Vision
Abstract 在计算机视觉领域,卷积神经网络(CNNs)是首选的模型。最近,基于注意力机制的网络,如Vision Transformer,也变得流行起来。在这篇论文中,我们展示了卷积和注意力虽然都足以实现良好的性能,但它们两者都不是必需的。我们提出了MLP-Mixer,这是一种仅基于多层感知…...

redis前缀匹配数据迁移数据
背景: 阿里云的dts不支持前缀匹配迁移。 调研发现RedisShake可以前缀匹配迁移。 https://github.com/tair-opensource/RedisShake proxy 代理模式 阿里云的redis cluster 默认是proxy 代理模式, 不支持增量迁移。 如果要支持增量迁移需要开启 redis clu…...

云贝教育 |【技术文章】存储对象的LIBRARY CACHE LOCK/PIN实验(一)
注: 本文为云贝教育 刘峰 原创,请尊重知识产权,转发请注明出处,不接受任何抄袭、演绎和未经注明出处的转载。 实验环境 操作系统:Red Hat Enterprise Linux release 8.8 (Ootpa) 数据库:oracle Version 19.3.0.0.0 …...

C# 快速模指数运算 快速求余运算
此方法解决这样一个问题,就是a^b mod m 的余数是多少。 如果直接计算a^b,方次很大的时候,会溢出,而且时间很长。 当然指数很小的时候直接用自带的Math函数就行,如果指数很大的时候,可以用以下的方法。 原…...

Chisel入门初步0
注:以下所有配置在Ubuntu22.04笔记本中运行 chisel模板构建 复制项目模板文件 git clone https://github.com/schoeberl/chisel-examples.git安装vscode插件Metals 打开顶层目录,并设置为项目文件夹 打开终端输入 tree -L 3 # 查看三层目录结构得到…...

MySQL 8.0中移除的功能(一)
以下项目已经过时并在MySQL 8.0中被删除。如果有替代方案,请务必更新应用程序以使用这些替代方案。 对于在MySQL 8.0中被删除的功能,如果从MySQL 5.7源复制到MySQL 8.0副本时,可能会导致语句失败,或者在源和副本上产生不同的效果…...

可抓取性和可索引性:它们是什么以及如何影响搜索引擎优化
什么是可抓取性? 网页的可抓取性是指搜索引擎(如谷歌)发现网页的难易程度。 谷歌发现网页的过程称为爬行。它使用称为网络爬虫(也称为机器人或蜘蛛)的计算机程序。这些程序会跟踪网页之间的链接,以发现新…...

Django教程第4章 | Web开发实战-三种验证码实现
系列:Django学习教程 验证码的存在是为了防止系统被暴力破解攻击,几乎每个系统都有验证码。下面将介绍三种生成验证码方式。 您可以根据你自己的需要进行学习。 手动生成验证码 安装绘图依赖,利用的是画图模块 PIL 以及随机模块 random 在后…...