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

spring mvc源码学习笔记之十一

  • pom.xml 内容如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.qs.demo</groupId><artifactId>test-011</artifactId><version>1.0.0</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.3.30.RELEASE</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring4</artifactId><version>3.0.11.RELEASE</version></dependency></dependencies></project>
  • src/main/webapp/WEB-INF/web.xml 内容如下
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><servlet><servlet-name>app</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet><servlet-mapping><servlet-name>app</servlet-name><!-- / 表示除了 xxx.jsp 之外的所有请求 --><!-- /* 表示所有请求 --><url-pattern>/</url-pattern></servlet-mapping>
</web-app>
  • src/main/webapp/WEB-INF/app-servlet.xml 内容如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 这个文件的名字是有讲究的 --><!-- springmvc 的配置 --><mvc:annotation-driven/><!-- 开启组件扫描 --><context:component-scan base-package="com.qs.demo"/><!-- 配置视图解析器 --><bean id="thymeleafViewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver"><property name="characterEncoding" value="UTF-8"/><property name="order" value="1"/><property name="templateEngine"><bean class="org.thymeleaf.spring4.SpringTemplateEngine"><property name="templateResolver"><bean class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver"><property name="prefix" value="/WEB-INF/templates/"/><property name="suffix" value=".html"/><property name="templateMode" value="HTML"/><property name="characterEncoding" value="UTF-8"/></bean></property></bean></property></bean></beans>
  • src/main/webapp/WEB-INF/templates/t01.html 内容如下
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>t01</title>
</head>
<body>
<a th:href="@{/t02}">hello</a>
</body>
</html>
  • src/main/webapp/WEB-INF/templates/t02.html 内容如下
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>t01</title>
</head>
<body><h1>Peter</h1>
</body>
</html>
  • com.qs.demo.A_ControllerAdvice 内容如下
package com.qs.demo;import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;import java.beans.PropertyEditorSupport;
import java.util.Date;/*** @author qs* @date 2025/01/10*/
@ControllerAdvice(basePackages = "com.qs.demo.controller")
public class A_ControllerAdvice {@InitBinder({"time"})public void a(WebDataBinder webDataBinder) {webDataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() {@Overridepublic void setAsText(String text) throws IllegalArgumentException {setValue(new Date(Long.parseLong(text) / 1000));}});}}
  • com.qs.demo.controller.FirstController 内容如下
package com.qs.demo.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @author qs* @date 2024/12/20*/
@Controller
public class FirstController {@InitBinder({"date"})public void a(WebDataBinder webDataBinder) {webDataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() {@Overridepublic void setAsText(String text) throws IllegalArgumentException {setValue(new Date(Long.parseLong(text)));}});}@RequestMapping("/t01")public String t01() {return "t01";}@RequestMapping("/t02")public String t02() {return "t02";}@RequestMapping("/t03")@ResponseBodypublic String t03(@RequestParam Date date) {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);}@RequestMapping("/t04")@ResponseBodypublic String t04(@RequestParam Date time) {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);}}

以上就是全部代码。需要注意的是代码里边有跟本文无关的内容。本文只需要关注 /t03 和 /t04 这2个接口即可。

写这个例子,主要是为了讲解 @InitBinder 注解。
在例子中,我们展示了 @InitBinder 的两种用法:一种局部的(或者说本地的,此处的本地指的是controller内部)和一种全局的。
不管是本地的还是全局的,代码所做的事情都是我们编码中常见的将前端传过来的 long 格式的日期转换为 Java 中的Date。无非是这里为了区分,全局的 @InitBinder 对前端传过来的 long 格式的时间先除以1000然后转为 Date,而本地的 @InitBinder 则直接将前端传来的 long 格式的时间转换为 Date
当然,还有一个点需要注意,在全局的 @InitBinder 上,我们将它的 value 值设置为 {"time"} 意思是只转换名字为 time 的参数,对应的就是接口 /t04,同样的,本地的 @InitBindervalue 值是 {"date"} 意思是只转换名字为 date 的参数,对应的就是接口 /t03。

测试 /t03 接口

http://localhost:8080/test_011/t03?date=1736501024000

结果是

2025-01-10 17:23:44

测试 /t04 接口

http://localhost:8080/test_011/t04?time=1736501024000

结果是

1970-01-21 10:21:41

以上是对代码的解释,下面开始分析 @InitBinder 的源码

  • 第一点就是看 @InitBinder 这个注解是在哪里被解析的
@Overridepublic void afterPropertiesSet() {// Do this first, it may add ResponseBody advice beansSystem.out.println("这个方法仔细看");System.out.println("这个方法仔细看");System.out.println("这个方法仔细看");initControllerAdviceCache();if (this.argumentResolvers == null) {System.out.println("初始化默认的参数解析器");System.out.println("初始化默认的参数解析器");System.out.println("初始化默认的参数解析器");List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.initBinderArgumentResolvers == null) {List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.returnValueHandlers == null) {System.out.println("初始化默认的返回值处理器");System.out.println("初始化默认的返回值处理器");System.out.println("初始化默认的返回值处理器");List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);}}

上面的代码是 RequestMappingHandlerAdapter 中的 afterPropertiesSet 方法。我们只需要关注第一行的 initControllerAdviceCache();

private void initControllerAdviceCache() {if (getApplicationContext() == null) {return;}System.out.println("寻找 @ControllerAdvice 注解。");if (logger.isInfoEnabled()) {logger.info("Looking for @ControllerAdvice: " + getApplicationContext());}List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());AnnotationAwareOrderComparator.sort(adviceBeans);List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();for (ControllerAdviceBean adviceBean : adviceBeans) {Class<?> beanType = adviceBean.getBeanType();if (beanType == null) {throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);}Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);if (!attrMethods.isEmpty()) {this.modelAttributeAdviceCache.put(adviceBean, attrMethods);if (logger.isInfoEnabled()) {logger.info("Detected @ModelAttribute methods in " + adviceBean);}}Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);System.out.println("@InitBinder 方法有 " + binderMethods.size() + " 个");if (!binderMethods.isEmpty()) {this.initBinderAdviceCache.put(adviceBean, binderMethods);if (logger.isInfoEnabled()) {logger.info("在 ControllerAdviceBean ---> " + adviceBean+ " 中检测到了 @InitBinder 方法。 Detected @InitBinder methods in " + adviceBean);}}if (RequestBodyAdvice.class.isAssignableFrom(beanType)) {requestResponseBodyAdviceBeans.add(adviceBean);if (logger.isInfoEnabled()) {logger.info("Detected RequestBodyAdvice bean in " + adviceBean);}}if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {requestResponseBodyAdviceBeans.add(adviceBean);if (logger.isInfoEnabled()) {logger.info("Detected ResponseBodyAdvice bean in " + adviceBean);}}}if (!requestResponseBodyAdviceBeans.isEmpty()) {this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);}}

这里边我们只需要关注跟 @InitBinder 相关的部分。它所做的事情就是先找到被 @ControllerAdvice 注解标记的 bean,然后遍历这些 bean,找到被 @InitBinder 注解标记的方法,把这些方法缓存到成员变量 initBinderAdviceCache 里边。这其实就是全局的 @InitBinder 被解析的过程。

  • 接下来看本地的 InitBinder 是在哪里被解析的
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {System.out.println("获取数据绑定工厂 WebDataBinderFactory ");Class<?> handlerType = handlerMethod.getBeanType();Set<Method> methods = this.initBinderCache.get(handlerType);if (methods == null) {System.out.println("找标记了 InitBinder 注解的方法");System.out.println("找标记了 InitBinder 注解的方法");System.out.println("找标记了 InitBinder 注解的方法");methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);this.initBinderCache.put(handlerType, methods);}List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();// Global methods firstSystem.out.println("全局的 @InitBinder 方法优先");System.out.println("全局的 @InitBinder 方法优先");System.out.println("全局的 @InitBinder 方法优先");this.initBinderAdviceCache.forEach((clazz, methodSet) -> {if (clazz.isApplicableToBeanType(handlerType)) {Object bean = clazz.resolveBean();for (Method method : methodSet) {initBinderMethods.add(createInitBinderMethod(bean, method));}}});for (Method method : methods) {Object bean = handlerMethod.getBean();initBinderMethods.add(createInitBinderMethod(bean, method));}return createDataBinderFactory(initBinderMethods);}

上面的代码是 RequestMappingHandlerAdaptergetDataBinderFactory 方法。可以注意下这个方法的入参 HandlerMethod,也就是我们写的 controller 里边处理请求的方法。这段代码的逻辑就是先获取 HandlerMethod 所在的类,也就是我们的 controller 类,然后找 controller 类中的 @InitBinder 方法,把这些方法解析完了以后放到成员变量 initBinderCache 里边。

到这里,我们就知道不管是全局的 @InitBinder 还是本地的 @InitBinder ,最终都是在被解析后放到了 RequestMappingHandlerAdapter 的成员变量里边。

  • 第二点就是看 InitBinder 方法是在哪里被调用的
	/*** Initialize a WebDataBinder with {@code @InitBinder} methods.* If the {@code @InitBinder} annotation specifies attributes names, it is* invoked only if the names include the target object name.* @throws Exception if one of the invoked @{@link InitBinder} methods fail.*/@Overridepublic void initBinder(WebDataBinder binder, NativeWebRequest request) throws Exception {System.out.println("循环调用所有 @InitBinder 方法");System.out.println("循环调用所有 @InitBinder 方法");for (InvocableHandlerMethod binderMethod : this.binderMethods) {if (isBinderMethodApplicable(binderMethod, binder)) {Object returnValue = binderMethod.invokeForRequest(request, null, binder);System.out.println("@InitBinder methods should return void ----> @InitBinder 方法应该返回 void");System.out.println("@InitBinder methods should return void ----> @InitBinder 方法应该返回 void");if (returnValue != null) {throw new IllegalStateException("@InitBinder methods should return void: " + binderMethod);}}}}

上面这段代码是 InitBinderDataBinderFactory 中的。它的逻辑就是遍历成员变量 binderMethods 并依次调用。关于这个成员变量是在哪里被赋值的,其实是在构造方法中

	public InitBinderDataBinderFactory(@Nullable List<InvocableHandlerMethod> binderMethods,@Nullable WebBindingInitializer initializer) {super(initializer);this.binderMethods = (binderMethods != null ? binderMethods : Collections.emptyList());}

而这个构造方法又被子类 ServletRequestDataBinderFactory 的构造方法调用了

	public ServletRequestDataBinderFactory(@Nullable List<InvocableHandlerMethod> binderMethods,@Nullable WebBindingInitializer initializer) {super(binderMethods, initializer);}

子类 ServletRequestDataBinderFactory 的构造方法又被 RequestMappingHandlerAdapter 调用了

	protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods)throws Exception {return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());}

调用的地方恰恰就是上面讲的 getDataBinderFactory 方法。

到这里,不要迷糊,只是追踪了 InitBinderDataBinderFactory 的成员变量 binderMethods 的赋值链路,并没有追踪 binderMethods 的调用链路。
直接说结论,binderMethods的是在参数解析的阶段被调用的,可以以 RequestResponseBodyMethodProcessorresolveArgument 为例看下

@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {parameter = parameter.nestedIfOptional();System.out.println("HttpMessageConverter 是在这里用的 ------");System.out.println("HttpMessageConverter 是在这里用的 ------");System.out.println("HttpMessageConverter 是在这里用的 ------");Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());System.out.println("获取参数对应的变量名");System.out.println("获取参数对应的变量名");String name = Conventions.getVariableNameForParameter(parameter);System.out.println("获取参数对应的变量名,得到的值是 " + name);if (binderFactory != null) {System.out.println("创建 WebDataBinder -----> 开始");WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);System.out.println("创建 WebDataBinder -----> 结束");if (arg != null) {// 参数校验是在这里做的// 参数校验是在这里做的// 参数校验是在这里做的System.out.println("----- 参数校验是在这里做的 ---- 开始");System.out.println("----- 参数校验是在这里做的 ---- 开始");System.out.println("----- 参数校验是在这里做的 ---- 开始");validateIfApplicable(binder, parameter);System.out.println("----- 参数校验是在这里做的 ---- 结束");if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {System.out.println("参数校验失败的话就抛出 MethodArgumentNotValidException 。");throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());}}if (mavContainer != null) {mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());}}return adaptArgumentIfNecessary(arg, parameter);
}

@InitBinder 方法就是在如下这段代码中被调用的

WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);

多说一嘴,方法的调用链很长,可以根据本文的线索自己追踪。还有一点,RequestMappingHandlerAdapter 是一个很重要的处理器适配器,需要深入仔细研究。

相关文章:

spring mvc源码学习笔记之十一

pom.xml 内容如下 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/P…...

小结:路由器和交换机的指令对比

路由器和交换机的指令有一定的相似性&#xff0c;但也有明显的区别。以下是两者指令的对比和主要差异&#xff1a; 相似之处 基本操作 两者都支持类似的基本管理命令&#xff0c;比如&#xff1a; 进入系统视图&#xff1a;system-view查看当前配置&#xff1a;display current…...

ffmpeg7.0 aac转pcm

#pragma once #define __STDC_CONSTANT_MACROS #define _CRT_SECURE_NO_WARNINGSextern "C" { #include "libavcodec/avcodec.h" }//缓冲区大小&#xff08;缓存5帧数据&#xff09; #define AUDIO_INBUF_SIZE 40960 /*name depthu8 8s16 …...

C#读取本地网络配置信息全攻略

一、引言 在当今数字化时代&#xff0c;网络已深度融入我们生活与工作的方方面面。对于软件开发而言&#xff0c;掌握本地计算机的网络配置信息显得尤为关键。想象一下&#xff0c;你正在开发一款网络诊断工具&#xff0c;需要精准定位网络连接问题&#xff0c;此时 IP 地址、…...

解决aerich init -t xx 报错ModuleNotFoundError: No module named ‘tomli_w‘

今天在学习fastapi的时候&#xff0c;发现一款数据库迁移工具&#xff0c;通过这个工具可以根据模型类来对数据库做出改变。 随跟着学: 在执行 aerich init -t settings.TORTOISE_ORM的时候&#xff0c; 彼其娘之。。 报了一些错误&#xff1a; Traceback (most recent ca…...

python检测gitlab中某个标签在一个月内添加和移除了多少次

可以通过 Python 脚本和 GitLab API 检测一个标签在一个月内被添加和移除的次数。以下是实现的步骤和示例代码&#xff1a; 步骤 获取 GitLab API 访问令牌&#xff1a;在 GitLab 中生成一个 Personal Access Token。设置时间范围&#xff1a;确定一个月的时间范围。调用 Git…...

学习模板之一

学习目标&#xff1a; 提示&#xff1a;这里可以添加学习目标 例如&#xff1a; 一周掌握 Java 入门知识 学习内容&#xff1a; 提示&#xff1a;这里可以添加要学的内容 例如&#xff1a; 搭建 Java 开发环境掌握 Java 基本语法掌握条件语句掌握循环语句 学习时间&#x…...

2025-微服务—SpringCloud-1~3

2025-微服务—SpringCloud 第一章、从Boot和Cloud版本选型开始说起1、Springboot版本2、Springcloud版本3、Springcloud Alibaba4、本次讲解定稿版 第二章 关于Cloud各种组件的停更/升级/替换1、微服务介绍2、SpringCloud是什么&#xff1f;能干吗&#xff1f;产生背景&#xf…...

centos7.6 安装nginx 1.21.3与配置ssl

1 安装依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel2 下载Nginx wget http://nginx.org/download/nginx-1.21.3.tar.gz3 安装目录 mkdir -p /data/apps/nginx4 安装 4.1 创建用户 创建用户nginx使用的nginx用户。 #添加www组 # groupa…...

PL/SQL语言的数据库交互

PL/SQL语言的数据库交互 引言 在当今的信息化时代&#xff0c;数据库管理系统&#xff08;DBMS&#xff09;在各行各业中扮演着至关重要的角色。为了高效地与数据库进行交互&#xff0c;许多程序员、数据库管理员和系统分析师选择使用PL/SQL&#xff08;Procedural Language/…...

ARP欺骗

文章目录 ARP协议ARP欺骗原理断网攻击ARP欺骗(不断网) ARP协议 在局域网中&#xff0c;网络传输的是帧&#xff0c;帧里面有目标主机的MAC地址。arp协议负责将IP地址解析成对应的MAC地址 ARP欺骗原理 即通过伪造IP地址和MAC地址实现ARP欺骗&#xff0c;能够在网络中产生大量…...

Genymotion配套VirtualBox所在地址

在 Genymotion打开虚拟机前需要先打开VirtualBox中的虚拟机 C:\Program Files\Oracle\VirtualBox\VirtualBox.exe 再开启genymotion中的虚拟机开关...

TPS61022 PFM的机制以及TPS61xxx转换器的PFM与PWM之间的负载阈值

引言 TI 的大多数 TPS61xxx 低压升压转换器都配备了 PSM&#xff08;省电模式&#xff09;&#xff0c;以帮助提高轻负载效率。但是&#xff0c;当它处于重负载状态时&#xff0c;输出纹波通常会高于 PWM。此外&#xff0c;PSM 和 PWM 之间的负载电流阈值不会直观地写入数据表中…...

1. npm 常用命令详解

npm 常用命令详解 npm&#xff08;Node Package Manager&#xff09;是 Node.js 的包管理工具&#xff0c;用于安装和管理 Node.js 应用中的依赖库。下面是 npm 的一些常用命令及其详细解释和示例代码。 镜像源 # 查询当前使用的镜像源 npm get registry# 设置为淘宝镜像源 …...

黑马linux入门笔记(01)初始Linux Linux基础命令 用户和权限 实用操作

B站 黑马程序员 的视频 BV1n84y1i7td 黑马程序员新版Linux零基础快速入门到精通&#xff0c;全涵盖linux系统知识、常用软件环境部署、Shell脚本、云平台实践、大数据集群项目实战等 增强自控力 冥想慢呼吸绿色锻炼充分休息减少决策次数优先做重要的事情(早晨)融入强自控群控…...

Markdown中甘特图的使用

Markdown中甘特图的使用 1. 前言2. 语法详解2.1 甘特图语法 3. 使用场景及实例4. 小结5. 其他文章快来试试吧&#x1f58a;️ Markdown中甘特图的使用 &#x1f448;点击这里也可查看 1. 前言 Markdown 的原生语法不支持绘制图形&#xff0c;但通过扩展模块&#xff0c;我们可…...

Django创建数据表、模型、ORM操作

1、创建项目 django-admin startproject PersonInfosProject 2、创建项目应用&#xff0c;进入PersonInfosProject文件夹&#xff0c;新建index应用&#xff0c;使用命令 cd PersonInfosProject python manage.py startapp 新建完成之后的目录结构 3、新建数据模型&#xf…...

No. 31 笔记 | Web安全-SQL手工注入技术学习 Part 2

一、研究背景 背景介绍 SQL注入是一种常见且高危的Web安全漏洞。攻击者可以通过构造恶意SQL查询语句来绕过验证机制&#xff0c;执行未授权操作&#xff0c;如获取敏感信息、篡改数据库内容甚至控制服务器。 研究内容 本笔记探讨以下数据库的手工注入技术&#xff1a; MySQLAc…...

Spring Boot中的扫描注解如何使用

在 Spring Boot 中&#xff0c;扫描注解是指通过注解来告诉 Spring 框架应该扫描哪些包、哪些类或哪些特定的组件&#xff0c;并将其作为 Spring 容器中的 bean 进行管理。Spring Boot 主要通过以下几种注解来实现自动扫描&#xff1a; ComponentScanSpringBootApplicationCom…...

用 Python 从零开始创建神经网络(十九):真实数据集

真实数据集 引言数据准备数据加载数据预处理数据洗牌批次&#xff08;Batches&#xff09;训练&#xff08;Training&#xff09;到目前为止的全部代码&#xff1a; 引言 在实践中&#xff0c;深度学习通常涉及庞大的数据集&#xff08;通常以TB甚至更多为单位&#xff09;&am…...

深入探讨 Vue.js 的动态组件渲染与性能优化

Vue.js 作为一款前端领域中备受欢迎的渐进式框架&#xff0c;以其简单优雅的 API 和灵活性受到开发者的喜爱。在开发复杂应用时&#xff0c;动态组件渲染是一项极其重要的技术&#xff0c;它能够在页面中动态地加载或切换组件&#xff0c;从而显著提升应用的灵活性与用户体验。…...

qml TextArea、TextEdit、TextField、TextInput的区别于联系

在 QML 中&#xff0c;TextArea、TextEdit、TextField 和 TextInput 都是用来接收用户输入的控件&#xff0c;但它们之间有一些区别和联系。 区别&#xff1a; TextArea&#xff1a;用于多行文本输入&#xff0c;可以接收多行文本输入。TextEdit&#xff1a;也用于多行文本输入…...

《探索 PC 端的开源神经网络多模态模型宝藏》

《探索 PC 端的开源神经网络多模态模型宝藏》 一、多模态模型&#xff1a;开启智能交互新纪元二、主流 PC 端开源多模态模型大赏1. Obsidian&#xff1a;轻量级多模态先锋2. GLM-Edge 系列&#xff1a;移动端与 PC 端的全能选手3. Minicpm-llama3-v2.6&#xff1a;紧凑高效的多…...

centos 搭建nginx+配置域名+windows访问

准备工作&#xff1a;一个完整的centos环境&#xff0c;nginx安装包(可以从官网下载)nginx: download 一&#xff1a;centos可能有精简版&#xff0c;部分环境没有相关依赖包&#xff0c; 需要检查以下项&#xff1a; 1.gcc检查&#xff1a;gcc -v&#xff08;回车后应当有版…...

docker的数据卷和自定义镜像

docker的数据卷&#xff1a; 容器与宿主机之间&#xff0c;或者容器和容器之间的数据共享&#xff08;目录&#xff09;。 创建容器的时间&#xff0c;通过指定目录&#xff0c;实现容器于宿主机之间&#xff0c;或者容器和容器之间的数据共享。 容器的生命周期有限&#xff0c…...

在 Linux 下Ubuntu创建同权限用户

我是因为不小心把最开始创建的用户的文件夹颜色搞没了&#xff0c;再后来全白用习惯了&#xff0c;就不想卸载了&#xff0c;像创建一个和最开始创建的用户有一样的权限可以执行sudo -i进入root一样的用户 如图这是最原始的样子 第一步 创建新用户&#xff0c;我这里是因为之前…...

计算机视觉算法实战——面部特征点检测

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​ ​​​​​​​​​​​​​​​​​​ 1. 领域介绍✨✨ 面部特征点检测&#xff08;Facial Landmark Detection&#xff09;是计算机视觉中…...

电力场景红外测温图像均压环下的避雷器识别分割数据集labelme格式2436张1类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;2436 标注数量(json文件个数)&#xff1a;2436 标注类别数&#xff1a;1 标注类别名称:["arrester"] 每个类别标注的框数&am…...

4种革新性AI Agent工作流设计模式全解析

文章目录 导读&#xff1a;AI Agent的四种关键设计模式如下&#xff1a;1. 反思2. 工具使用3. 规划4. 多Agent协作 总结内容简介&#xff1a; 导读&#xff1a; AI Agent是指能够在特定环境中自主执行任务的人工智能系统&#xff0c;不仅接收任务&#xff0c;还自主制定和执行…...

C#基础 枚举 Enumeration从基础到进阶

目录 一、入门篇&#xff1a;枚举基础1. 枚举类型的定义2. 枚举类型的优点3. 枚举的基本使用3.1 枚举的类型转换3.2 遍历枚举成员3.3 判断枚举值是否有效3.4枚举的比较 4. 枚举的设计规范 二、深入底层篇&#xff1a;存储、值与继承限制1. 枚举的存储与表示2. 枚举底层类型选择…...

SOME/IP 协议详解——服务发现

文章目录 1. Introduction &#xff08;引言&#xff09;2. SOME/IP Service Discovery (SOME/IP-SD)2.1 General&#xff08;概述)2.2 SOME/IP-SD Message Format2.2.1 通用要求2.2.2 SOME/IP-SD Header2.2.3 Entry Format2.2.4 Options Format2.2.4.1 配置选项&#xff08;Co…...

android studio使用DataBinding

DataBinding 是谷歌官方发布的在android上对MVVM设计模式的一个实现框架&#xff0c;其作用是实现数据绑定。 Android DataBinding主要实现了View和ViewModel的双向绑定&#xff0c;包括用户的响应。并且实现了自动更新。 DataBinding优点&#xff1a; 1.大量减少Act…...

记一次学习skynet中的C/Lua接口编程解析protobuf过程

1.引言 最近在学习skynet过程中发现在网络收发数据的过程中数据都是裸奔&#xff0c;就想加入一种数据序列化方式&#xff0c;json、xml简单好用&#xff0c;但我就是不想用&#xff0c;于是就想到了protobuf&#xff0c;对于protobuf C/C的使用个人感觉有点重&#xff0c;正好…...

JavaSE面试

final和static对比 static知识点介绍static代码块当JVM加载类时&#xff0c;static代码块会且只会被执行一次。可用于优化程序性能。实例代码块在每次创建对象时&#xff0c;都会自动执行。static方法static方法中不能使用this和super关键字。静态内部类静态内部类的创建不需要…...

【Rust自学】11.10. 集成测试

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.10.1. 什么是集成测试 在Rust里&#xff0c;集成测试完全位于被测试库的外部。集成测试调用库的方式和其他代码一样&#xff0c;这也…...

Redis :redis的大Key问题

问题 &#xff1a; 什么是redis 的大key 呢&#xff1f; redis 是一个单线程应用程序。他的请求类似于队列处理&#xff0c;命令排队执行&#xff0c;逐个处理。 这样就会出现一个问题&#xff0c;一旦队列前面的命令请求处理时间过程&#xff0c;那么后续执行命令就会被迫的等…...

IntelliJ IDEA中Maven项目的配置、创建与导入全攻略

大家好&#xff0c;我是袁庭新。 IntelliJ IDEA是当前最流行的Java IDE&#xff08;集成开发环境&#xff09;之一&#xff0c;也是业界公认最好用的Java开发工具之一。IntelliJ IDEA支持Maven的全部功能&#xff0c;通过它我们可以很轻松地实现创建Maven项目、导入Maven项目、…...

如何确保获取的淘宝详情页数据的准确性和时效性?

要确保获取的淘宝详情页数据的准确性和时效性&#xff0c;可从以下几个方面着手&#xff1a; 合法合规获取数据 遵守平台规则&#xff1a;在获取淘宝详情页数据之前&#xff0c;务必仔细阅读并严格遵守淘宝平台的使用协议和相关规定。明确哪些数据可以获取、以何种方式获取以及…...

如何将json字符串格式化

文章目录 如何对json字符串进行格式化显示hutool方案的示例和不足使用fastjson的方案 如何对json字符串进行格式化显示 将json字符串内容进行格式化的输出显示。本文介绍 hutool的方案和alibaba 的fastjson方案 hutool方案的示例和不足 引入依赖 <dependency><grou…...

【Vue + Antv X6】可拖拽流程图组件

使用事项&#xff1a; ❗先放个组件上来&#xff0c;使用手册有空会补全 ❗需要下载依赖 “antv/x6”: “^2.18.1”, “antv/x6-plugin-dnd”: “^2.1.1”, 组件&#xff1a; 组件使用&#xff1a; <flowChart :key"flowChartKey" ref"flowChart" lef…...

反转链表题目

文章目录 反转链表题目链接&#xff1a;[在线OJ](https://leetcode.cn/problems/reverse-linked-list/description/)题目详解思路1&#xff1a;思路1算法复杂度 思路2代码实现思路2算法复杂度 结语 欢迎大家来到我的博客&#xff0c;给生活来点impetus 让我们进入《题海探骊》…...

利用Python爬虫获取义乌购店铺所有商品列表:技术探索与实践

在当今数字化时代&#xff0c;数据的重要性不言而喻。对于采购商而言&#xff0c;能够快速、准确地获取供应商店铺内的所有商品信息&#xff0c;是提升采购效率、优化采购决策的关键。义乌购作为国内知名的在线批发平台&#xff0c;汇聚了海量的商品资源&#xff0c;为采购商提…...

基于FPGA的多功能数字钟设计

基于FPGA的多功能数字钟设计 前言基础知识按键数码管 系统概述按键使用说明模块描述模块设计button_debouncebutton_controllerclock_controllerdigital_tube 整体资源用量测试视频 前言 本工程主要是数码管、按键、LED的应用开发。 注&#xff1a;本工程所有IP均使用源码开发…...

nginx-lua模块安装

一.简述 安装 Nginx 的 Lua 模块&#xff08;通常指的是 ngx_lua 模块&#xff09;可以显著增强 Nginx 的功能&#xff0c;使其能够执行 Lua 脚本。这使得 Nginx 可以处理更复杂的逻辑和动态内容生成。以下是详细的安装步骤&#xff0c;包括安装 OpenResty 或从源码编译 Nginx…...

poi处理多选框进行勾选操作下载word以及多word文件压缩

一、场景 将数据导出word后且实现动态勾选复选框操作 eg: word模板 导出后效果&#xff08;根据数据动态勾选复选框&#xff09; 二、解决方案及涉及技术 ① 使用poi提供的库进行处理&#xff08;poi官方文档&#xff09; ② 涉及依赖 <!-- excel工具 --><depen…...

centos7.3安装部署freeswitch

centos7.3安装部署freeswitch 切换yum源为阿里镜像源安装 FreeSWITCH 的 YUM 软件仓库配置文件和 EPEL安装相关工具安装cmake源码编译安装依赖安装 freeswitch 切换yum源为阿里镜像源 cp -r /etc/yum.repos.d /etc/yum.repos.d.bakcurl -o /etc/yum.repos.d/CentOS-Base.repo …...

C# 迭代,递归,回调--13

目录 一.迭代 迭代器示例: 关键点: 优势: 二.递归 递归示例: 关键点: 优势: 注意: 三.回调 回调示例: 关键点: 优势: 应用场景: 4.三种模式的特点对比: 迭代: 递归: 回调: 一.迭代 在C#中迭代通常指重复执行一系列指令 在C#中,迭代器是一种特殊的结构,允许…...

MOS管为什么会有夹断,夹断后为什么会有电流?该电流为什么是恒定的?

以下是对MOS管MOS管为什么会有夹断&#xff0c;夹断后为什么还会有电流&#xff1f;该电流为什么是恒定的&#xff1f;的一些心得体会。 1. MOS管为什么会有夹断&#xff1f; 可以认为D极加压使得D极的耗尽层增大(原因是N极接正极&#xff0c;P极接负极&#xff0c;电子被吸引…...

3D可视化产品定制,应用于哪些行业领域?

3D可视化定制服务已广泛渗透至众多行业领域&#xff0c;包括汽车、家居、时尚鞋服、珠宝配饰以及数码电器等&#xff1a; 汽车行业&#xff1a; 借助Web全景技术与3D模型&#xff0c;我们高保真地再现了汽车外观&#xff0c;为用户带来沉浸式的车型浏览体验。用户可在展示界面自…...

Golang 简要概述

文章目录 1. Golang 的学习方向2. Golang 的应用领域2.1 区块链的应用开发2.2 后台的服务应用2.3 云计算/云服务后台应用 1. Golang 的学习方向 Go 语言&#xff0c;我们可以简单的写成 Golang 2. Golang 的应用领域 2.1 区块链的应用开发 2.2 后台的服务应用 2.3 云计算/云服…...