SpringBoot 跨域请求处理全攻略:从原理到实践
文章目录
- SpringBoot 如何处理跨域请求?你能说出几种方法?
- 跨域请求概述
- 跨域解决方案
- 1. 使用@CrossOrigin注解
- 2. 使用WebMvcConfigurer配置类
- 3. 使用过滤器(Filter)
- 4. 使用Spring Security处理CORS
- 5.使用Spring Cloud Gateway处理CORS
- 补充
- 1. 预检请求(Preflight Requests)
- 2. 其他注意事项
- 总结
- 思考
- 1. 如何区分简单请求和复杂请求?
- 2. 在实际项目中,如何选择合适的跨域请求解决方案?
- 3. 如何处理凭证(Credentials)在跨域请求中的应用?
SpringBoot 如何处理跨域请求?你能说出几种方法?
在现代的Web开发中,跨域请求(Cross-Origin Resource Sharing,CORS)是一个常见的挑战。随着前后端分离架构的流行,前端应用通常运行在一个与后端 API 不同的域名或端口上,这就导致了浏览器的同源策略(Same-Origin Policy)的限制,从而出现了跨域请求问题。
Spring Boot 作为一种流行的 Java 后端框架,提供了多种处理跨域请求的方法,使得开发人员能够灵活地配置和管理跨域资源共享。本文将深入探讨几种常见的解决方案,帮助开发人员理解如何在 Spring Boot 应用中有效地处理跨域请求问题。
跨域请求概述
-
什么是跨域请求?
跨域请求(Cross-Origin Request)指的是在浏览器环境下,前端代码发起的请求与当前页面的域名(或端口、协议)不同。浏览器的同源策略(Same-Origin Policy)限制了从一个源(域名、协议、端口组成的组合)加载的文档或脚本如何与来自另一个源的资源进行交互。具体来说,如果一个页面加载自 http://domain1.com,则它的同源策略默认限制了对 http://domain2.com 发起的请求。
跨域问题是浏览器的一种安全策略,访问需要遵循同源策略:
| URL | 说明 | 是否允许通信 |
|---|---|---|
http://www.a.com/a.js http://www.a.com/b.js | 同一域名下 | 允许 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js | 同一域名下不同文件夹 | 允许 |
http://www.a.com:8000/a.js http://www.a.com/b.js | 同一域名,不同端口 | 不允许 |
http://www.a.com/a.js https://www.a.com/b.js | 同一域名,不同协议 | 不允许 |
http://www.a.com/a.js http://192.168.110.11/b.js | 域名和域名对应ip | 不允许 |
http://www.a.com/a.js http://script.a.com/b.js | 主域相同,子域不同 | 不允许 |
http://www.a.com/a.js http://a.com/b.js | 同一域名,不同二级域名(同上) | 不允许(cookie这种情况下也不允许访问) |
http://www.cnblogs.com/a.js http://www.a.com/b.js | 不同域名 | 不允许 |
-
为什么会出现跨域问题?
跨域问题的出现主要是为了保护用户数据和用户隐私安全。如果没有同源策略的限制,恶意网站可以利用当前用户的身份在其他网站上进行操作,如发送请求、读取数据,这可能导致信息泄露或潜在的安全威胁。
-
可能会导致的安全风险
- 信息泄露:允许恶意网站读取其他网站的敏感数据。
- CSRF(跨站请求伪造)攻击:如果没有适当的防护措施,允许攻击者伪造用户的请求并在用户不知情的情况下执行操作。
- 恶意脚本注入:通过跨域请求注入恶意脚本,影响其他域上的安全性。
跨域解决方案
1. 使用@CrossOrigin注解
Spring 框架提供了@CrossOrigin注解,可以直接在 Controller 类或方法上使用,以声明允许来自特定源的请求。例如:
@RestController
@RequestMapping("/api")
public class MyController {@CrossOrigin(origins = "http://allowed-origin.com")@GetMapping("/data")public ResponseEntity<String> getData() {// 处理逻辑}
}
优点:简单直接,适用于简单的跨域场景。
缺点:无法进行更细粒度的配置,如请求方法、请求头等。
2. 使用WebMvcConfigurer配置类
通过自定义WebMvcConfigurer配置类,可以更灵活地配置跨域请求。例如:
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("http://allowed-origin.com").allowedMethods("GET", "POST").allowedHeaders("header1", "header2").exposedHeaders("header3").allowCredentials(true).maxAge(3600);}
}
优点:可以精确控制允许的源、方法、头部等。
缺点:需要编写额外的配置类,相对比较复杂。
3. 使用过滤器(Filter)
通过自定义过滤器来处理跨域请求,这种方法可以在请求到达 Controller 之前进行处理。例如:
@Component
public class CorsFilter implements Filter {@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {HttpServletResponse response = (HttpServletResponse) res;HttpServletRequest request = (HttpServletRequest) req;response.setHeader("Access-Control-Allow-Origin", "http://allowed-origin.com");response.setHeader("Access-Control-Allow-Methods", "GET,POST");response.setHeader("Access-Control-Allow-Headers", "header1,header2");response.setHeader("Access-Control-Expose-Headers", "header3");response.setHeader("Access-Control-Allow-Credentials", "true");response.setHeader("Access-Control-Max-Age", "3600");chain.doFilter(req, res);}
}
优点:可以完全自定义跨域请求处理逻辑。
缺点:需要更多的Java编程经验,并且可能需要处理更复杂的跨域场景。
在使用Spring Security和Spring Cloud Gateway时,处理跨域请求(CORS)可以通过不同的方式实现。对于Spring Security,你可以在安全配置中添加CORS配置;而对于Spring Cloud Gateway,你可以使用全局过滤器或者特定的路由过滤器来处理CORS。
4. 使用Spring Security处理CORS
在Spring Security中,你可以在WebSecurityConfigurerAdapter的配置类中添加一个CorsConfigurationSource来指定CORS策略。但是,如果你使用的是Spring Security 5.3及以上版本,推荐使用WebSecurityCustomizer来配置CORS。
示例代码如下:
@Configuration
@EnableWebSecurity
public class SecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// ... your authorization rules here.anyRequest().authenticated();http.addFilterBefore(new JWTAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);return http.build();}@BeanCorsConfigurationSource corsConfigurationSource() {CorsConfiguration configuration = new CorsConfiguration();configuration.setAllowedOrigins(Arrays.asList("*"));configuration.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", configuration);return source;}
}
5.使用Spring Cloud Gateway处理CORS
在Spring Cloud Gateway中,你可以在全局过滤器中添加CORS处理逻辑,或者在每个路由上单独配置CORS。这里是一个使用全局过滤器的例子:
@Configuration
public class CorsConfig {@Beanpublic GatewayFilter globalCorsFilter() {CorsConfiguration corsConfig = new CorsConfiguration();corsConfig.setAllowCredentials(true);corsConfig.addAllowedOriginPattern("*");corsConfig.addAllowedHeader(HttpHeaders.AUTHORIZATION);corsConfig.addAllowedHeader(HttpHeaders.CONTENT_TYPE);corsConfig.addAllowedMethod(HttpMethod.GET.name());corsConfig.addAllowedMethod(HttpMethod.POST.name());corsConfig.addAllowedMethod(HttpMethod.PUT.name());corsConfig.addAllowedMethod(HttpMethod.DELETE.name());corsConfig.addAllowedMethod(HttpMethod.OPTIONS.name());List<String> allowedMethods = corsConfig.getAllowedMethods();corsConfig.setExposedHeaders(allowedMethods.stream().map(method -> "X-Permitted-Cross-Domain-Policies").collect(Collectors.toList()));CorsGatewayFilterFactory corsGatewayFilterFactory = new CorsGatewayFilterFactory(corsConfig);return corsGatewayFilterFactory.apply(new CorsConfig().new CorsConfigCustomizer());}public static class CorsConfigCustomizer implements CorsGatewayFilterFactory.CorsConfigurationCustomizer {@Overridepublic void customize(CorsConfiguration corsConfiguration) {corsConfiguration.setMaxAge(3600L);}}
}
请注意,这些示例代码需要根据你的具体需求进行调整。例如,你可能需要限制允许的源,或者修改其他CORS设置。
补充
1. 预检请求(Preflight Requests)
跨域请求中,某些复杂请求(如带有自定义头部的请求、使用某些特殊方法如PUT、DELETE等的请求)会触发浏览器先发送一个预检请求(OPTIONS请求)到服务器,以确定是否允许实际的请求。预检请求包含以下头部信息:
Origin:表明发起请求的源。Access-Control-Request-Method:实际请求将使用的HTTP方法。Access-Control-Request-Headers:实际请求将使用的自定义头部。
服务器需要正确响应预检请求,以确保浏览器安全地执行实际请求。
处理预检请求的方法:
-
使用
@CrossOrigin注解处理:@CrossOrigin(origins = "http://allowed-origin.com", methods = {RequestMethod.GET, RequestMethod.POST}, allowedHeaders = {"header1", "header2"})@RequestMapping(value = "/api/data", method = RequestMethod.OPTIONS)public ResponseEntity<Void> preflight() {return ResponseEntity.ok().build();}在
Controller中定义一个处理OPTIONS请求的方法,并使用@CrossOrigin注解指定允许的源、方法和头部。 -
通过
WebMvcConfigurer配置类处理:@Configuration public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("http://allowed-origin.com").allowedMethods("GET", "POST").allowedHeaders("header1", "header2").exposedHeaders("header3").allowCredentials(true).maxAge(3600);}@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("http://allowed-origin.com").allowedMethods("GET", "POST").allowedHeaders("header1", "header2").exposedHeaders("header3").allowCredentials(true).maxAge(3600);} }在
WebMvcConfigurer配置类中,通过重写addCorsMappings方法来定义预检请求的处理方式。
2. 其他注意事项
Credentials(凭证)的处理:
如果请求需要使用凭证(如使用Cookie、HTTP认证信息等),需要确保在跨域请求中设置Access-Control-Allow-Credentials为true,并在客户端请求中设置withCredentials为true。
暴露自定义头部:
如果需要在响应中暴露某些自定义头部供客户端访问,可以通过Access-Control-Expose-Headers头部指定。
缓存控制:
可以通过Access-Control-Max-Age头部指定预检请求的缓存时间,减少重复发送预检请求的次数,提升性能。
总结
避免跨域请求问题不仅仅是简单地允许跨域请求,还需要正确处理预检请求及相关细节。通过使用@CrossOrigin注解、自定义WebMvcConfigurer配置类或过滤器来处理跨域请求,可以有效地保证跨域请求的安全性和可靠性。同时,要特别注意凭证的处理及其他相关头部信息的配置,确保跨域请求能够在安全、可控的环境下完成。
思考
1. 如何区分简单请求和复杂请求?
跨域资源共享(CORS)规范将跨域请求分为两类:简单请求和预检请求(复杂请求)。区分这两类请求主要基于以下几个因素:
简单请求:
- 方法:请求方法必须是以下之一:
GET,HEAD,POST。 - 头信息:请求头中的字段不能包含除了
Accept,Accept-Language,Content-Language,Last-Event-ID,Content-Type之外的自定义头部,且Content-Type的值只能是以下几种之一:application/x-www-form-urlencoded,multipart/form-data, 或者text/plain。 - 数据类型:如果是
POST请求,发送的数据必须符合上述Content-Type的规定。
复杂请求(预检请求):
- 如果请求不符合上述简单请求的标准,则被视为复杂请求。浏览器会先发送一个
OPTIONS请求到服务器,这个请求称为预检请求,用于确认服务器是否支持跨域请求以及具体的请求方法和头部信息。
预检请求包含了实际请求的所有关键信息,包括请求方法、请求头部等,服务器通过预检请求响应告知客户端是否可以继续发送实际的请求。
2. 在实际项目中,如何选择合适的跨域请求解决方案?
选择跨域请求解决方案主要考虑以下几个方面:
- 安全性:确保跨域访问不会导致安全漏洞,比如XSS攻击或CSRF攻击。
- 性能:预检请求会增加额外的网络延迟,因此在设计API时应尽量避免不必要的复杂请求。
- 功能需求:根据API的功能需求确定哪些HTTP方法和头信息是必要的,这将影响请求的类型。
- 易用性:为开发者提供清晰的文档和示例,说明哪些资源可以被跨域访问,以及如何正确地设置请求头。
在Spring框架下,可以采用以下策略:
- 使用Spring Security或Spring MVC的内置CORS支持,通过配置类来指定CORS策略。
- 在Spring Cloud Gateway中,通过全局过滤器或路由级过滤器来处理CORS,这样可以更细粒度地控制跨域策略。
3. 如何处理凭证(Credentials)在跨域请求中的应用?
凭证通常指的是Cookie和HTTP认证信息(如Basic Auth),它们在跨域请求中默认是不会被发送的。如果需要发送凭证,需要在CORS策略中显式地允许:
- 在服务器端,需要在CORS响应头中添加
Access-Control-Allow-Credentials: true。 - 在客户端,当发起请求时,需要将
withCredentials属性设置为true。
示例代码:
服务端配置(Spring Security):
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowCredentials(true); // 允许发送凭证
客户端调用(JavaScript/AJAX):
fetch('http://example.com/api', {method: 'GET',credentials: 'include', // 发送凭证
});
请注意,一旦允许了凭证的发送,所有跨域请求都必须遵循CORS策略,并且不能缓存预检请求的结果。此外,由于凭证的发送增加了安全风险,因此在配置时要格外小心,确保只对可信的源开放凭证权限。
Nginx 作为一款高性能的 HTTP 和反向代理服务器,可以用来处理跨域请求(CORS),关于Nginx相关的知识可以去看这篇文章:《Nginx——高性能Web服务器的基石,解锁Nginx的超级技能:从基础到实战的全方位指南》
相关文章:
SpringBoot 跨域请求处理全攻略:从原理到实践
文章目录 SpringBoot 如何处理跨域请求?你能说出几种方法?跨域请求概述跨域解决方案1. 使用CrossOrigin注解2. 使用WebMvcConfigurer配置类3. 使用过滤器(Filter)4. 使用Spring Security处理CORS5.使用Spring Cloud Gateway处理CO…...
vulnhub——Ai-Web1靶机渗透
Ai-Web1靶机渗透 靶机下载: 官网地址:https://www.vulnhub.com/entry/ai-web-1,353/ 攻击机:kali2024 一、信息收集 发下目标主机的IP为:192.168.201.141 用nmap工具扫描一下对方主机和服务 发现他打开了80端口 发现搜不到于是…...
sqlalchemy事件监听
sqlalchemy事件监听 SQLAlchemy 中的事件监听允许您在特定事件发生时执行自定义的 Python 代码。这些事件可以是与ORM(对象关系映射)或核心组件相关的操作,比如表、类、会话或事务的插入、更新、删除等操作。通过事件监听,您可以实现日志记录、审计或执行业务规则等功能。…...
【Django+Vue3 线上教育平台项目实战】Celery赋能:优化订单超时处理与自动化定时任务调度
文章目录 前言⭐✨💫🔥📖一、Celery⭐1.基本概念及介绍:✨2.使用步骤💫 二、订单超时 取消订单(Celery)🔥具体实现流程📖 前言⭐✨💫🔥📖 在构建复…...
CSS3 教程
CSS3 教程 引言 CSS3,即层叠样式表的第三代,是网页设计和开发中不可或缺的技术之一。它为HTML元素提供了丰富的样式定义,使得网页不仅内容丰富,而且外观美观、交互性强。本教程将详细介绍CSS3的基础知识、高级特性以及最佳实践&…...
树与二叉树学习笔记
树与二叉树 计算机中的树树的概念树的类型 什么是二叉树二叉树:定义与特点二叉树:前序、中序、后序遍历二叉树:深度、广度优先遍历二叉树:线索化二叉树:序列化与反序列化 haffman树平均编码长度构建haffman树haffman树…...
消费金融系统开发回忆录
架构设计图 整个支付链路上的功能 支付系统应该有:账户管理、渠道管理、支付管理、对账管理、清算管理、结算管理 一笔支付订单,在支付系统侧就是要记录清楚,谁发起的、对哪个商品进行支付、通过哪个渠道支付、支付时间、支付结果等…...
org.springframework.context.ApplicationContext发送消息
1、创建消息的实体类 package com.demo;/*** 监听的实体类**/ public class EventMessage {private String name;public EventMessage(String name) {this.name name;}public String getName() {return name;}public void setName(String name) {this.name name;} }2、创建消…...
Java8-21新特性
简介 由于Java官方最近更新越来越频繁,而长期支持维护的版本LTS版每隔几年才推出一个,大规模商用的JDK只可能选择LTS版,因此这里只简单记录JDK8,11,17,21。 jdk8 Lambda表达式: Lambda表达式…...
NodeJS系列面试题
大家好,我是有用就扩散,有用就点赞。 有没有写过Koa中间件,说一下中间件原理,介绍下自己写过的中间件 koa本来就是一个轻量级框架,本身支持的功能并不多,功能都是通过中间件来实现不同的需求。开发者可以通…...
QXlsx读写excel
QXlsx读写excel 安装 QXlsx使用 qmake使用 CMake 基本用法1. 写入 Excel 文件2. 读取 Excel 文件 详细用法1. 设置单元格样式2. 合并单元格3. 创建图表4. 设置列宽和行高 完整示例 QXlsx 是一个用于在 Qt 应用中读写 Excel 文件的第三方库。它提供了丰富的 API,可以…...
昇思25天学习打卡营第13天 | mindspore 实现 ShuffleNet 图像分类
1. 背景: 使用 mindspore 学习神经网络,打卡第 13 天;主要内容也依据 mindspore 的学习记录。 2. 迁移学习介绍: mindspore 实现 ShuffleNet 图像分类; ShuffleNet 基本介绍: ShuffleNetV1 是旷视科技提…...
C语言超市管理系统UI界面
以下是部分代码。需要源码的私信 #include<easyx.h> #include<stdio.h> #include<stdlib.h>#define width 1280 #define height 840 #define font_w 35 //字体宽度 #define font_h 90 //字体高度typedef struct node {char name[100];//名字char number[1…...
BUUCTF逆向wp [MRCTF2020]Xor
第一步 查壳,该题是32位,无壳。 第二步 跟进main,发现反汇编不了 通过下图我们可以发现一串类似字符串的东西 第三步 我们看一下汇编 我们可以得到这些信息:flag的长度为27(下面是对本条指令cmp edx 27指令的应用…...
Windows版MySQL5.7解压直用(如何卸载更换位置重新安装)
文章目录 停止mysql进程及服务迁移整个mysql文件夹删除data重启计算机重新安装 停止mysql进程及服务 net stop mysql mysqld -remove mysql迁移整个mysql文件夹 删除data 重启计算机 shutdown -r -t 0重新安装 https://blog.csdn.net/xzzteach/article/details/137723185...
详解数据结构之二叉树(堆)
详解数据结构之二叉树(堆) 树 树的概念 树是一个非线性结构的数据结构,它是由 n(n>0)个有限节点组成的一个具有层次关系的集合,它的外观形似一颗倒挂着的树,根朝上,叶朝下,所以称呼为树。每颗子树的根节点有且只…...
Linux----Mplayer音视频库的移植
想要播放视频音乐就得移植相关库到板子上 Mplayer移植需要依赖以下源文件:(从官网获取或者网上) 1、zlib-1.2.3.tar.gz :通用的内存空间的压缩库。 2、libpng-1.2.57.tar.gz :png格式图片的压缩或解压库 3、Jpegsrc.v9b.tar.gz : jpeg格式图片的压…...
STM32测测速---编码电机读取速度的计算
1、首先先了解一下计算的公式 速度计算: 轮胎每转一圈的脉冲数取决于编码器的分辨率,可由下面公式进行计算: PPR是电机的线数 以GA25-370电机为例。 图片来源:第四节:STM32定时器(4.JGA25-370霍尔编码器…...
【已解决】服务器无法联网与更换镜像源
目录 问题描述: 1.修改网卡的 DNS1 和 DNS2 2.修改DNS列表 3.重启网络服务 4.切换镜像源 4.1备份原镜像源 4.2下载阿里云镜像源 4.3替换无法使用的域名 4.4刷新软件包缓存 4.5其他镜像源 5.阿里云镜像源开发者社区说明 6.阿里云DNS网址 7.DNS域名服务器…...
android11 屏蔽usb通过otg转接口外接鼠标设备
硬件平台:QCS6125 软件平台:Android11 需求:Android设备通过接usb转接线连接鼠标功能屏蔽。 考虑到屏蔽的层面可以从两个层面去做,一个是驱动层面不识别,一个就是Android系统层面不识别加载,本篇只讲后者。…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
