深入理解 Spring Boot 中的 Starters

一、引言

在 Spring Boot 开发中,Starters 是一个非常重要的概念。它们为开发者提供了一种便捷的方式来集成各种功能和技术,大大简化了项目的配置和开发过程。理解 Spring Boot 中的 Starters 对于提高开发效率、降低项目复杂度以及实现快速迭代至关重要。本文将深入探讨如何理解 Spring Boot 中的 Starters。

二、Starters 的概念与作用

(一)概念解析

  1. 定义
    • Spring Boot Starters 是一组预配置的依赖项集合,用于快速启动特定功能或技术的开发。它们封装了相关的库和配置,使得开发者可以轻松地引入所需的功能,而无需手动管理多个依赖项的版本和配置。
  2. 与传统依赖管理的区别
    • 与传统的依赖管理方式相比,Starters 提供了更高层次的抽象和封装。传统方式下,开发者需要手动查找、选择和配置各个依赖项,而 Starters 则将相关的依赖项整合在一起,并提供了默认的配置,使得开发过程更加简洁高效。

(二)作用概述

  1. 快速启动项目
    • Starters 使得开发者可以快速启动一个具有特定功能的项目。例如,通过引入 spring-boot-starter-web,可以快速创建一个基于 Spring MVC 的 Web 应用程序,无需手动配置 Servlet 容器、Spring MVC 框架等依赖项。
  2. 简化依赖管理
    • 它们帮助开发者简化了依赖管理的过程。开发者只需在项目的构建文件中添加相应的 Starter,就可以自动引入所需的依赖项,并且这些依赖项的版本通常是经过测试和兼容的,减少了版本冲突的风险。
  3. 提供默认配置
    • Starters 通常会提供一些默认的配置,使得开发者可以在不进行大量配置的情况下快速使用相关功能。例如,spring-boot-starter-data-jpa 会自动配置数据库连接和 JPA 实体管理器等。

三、Starters 的工作原理

(一)自动配置机制

  1. 基于条件注解
    • Spring Boot 的自动配置机制是 Starters 工作的核心。自动配置是通过使用条件注解(如 @ConditionalOnClass@ConditionalOnProperty 等)来实现的。这些注解会根据类路径中的内容、系统属性等条件来决定是否进行特定的配置。
  2. 自动配置类
    • 每个 Starter 通常会包含一个或多个自动配置类,这些类会在项目启动时被加载,并根据条件进行自动配置。例如,spring-boot-starter-web 中的自动配置类会根据类路径中是否存在 Servlet 容器等条件来自动配置 Spring MVC 和嵌入式 Servlet 容器。
  3. 配置优先级
    • 自动配置的优先级通常是可以调整的。开发者可以通过在自己的配置类中使用 @EnableAutoConfiguration 的 exclude 属性来排除特定的自动配置类,或者通过在 application.properties 或 application.yml 文件中设置属性来覆盖默认的配置。

(二)依赖传递与版本管理

  1. 依赖传递
    • Starters 不仅包含了直接依赖的库,还会传递性地引入相关的依赖项。例如,spring-boot-starter-data-jpa 不仅包含了 JPA 实现库(如 Hibernate),还会引入数据库驱动、连接池等相关的依赖项。
  2. 版本管理
    • Spring Boot 对 Starters 中的依赖项进行了版本管理,确保不同的依赖项之间能够兼容。开发者无需手动管理依赖项的版本,只需关注 Starter 的版本即可。Spring Boot 团队会定期更新 Starter 的版本,以确保其包含的依赖项是最新的、稳定的。

四、常见的 Spring Boot Starters

(一)Web 开发相关的 Starters

  1. spring-boot-starter-web
    • 功能介绍
      • 这个 Starter 用于构建基于 Spring MVC 的 Web 应用程序。它包含了 Spring MVC、嵌入式 Servlet 容器(如 Tomcat、Jetty 或 Undertow)等依赖项。
    • 示例应用
      • 以下是一个使用 spring-boot-starter-web 创建的简单 Web 应用程序:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class WebApplication {public static void main(String[] args) {SpringApplication.run(WebApplication.class, args);}
}

  1. spring-boot-starter-actuator
    • 功能介绍
      • spring-boot-starter-actuator 提供了一系列用于监控和管理应用程序的端点。它可以帮助开发者了解应用程序的运行状态、性能指标等信息。
    • 示例应用
      • 启用 Actuator 后,可以通过访问 /actuator/health 端点来获取应用程序的健康状态:
{"status": "UP","components": {"diskSpace": {"status": "UP","details": {"total": 100000000000,"free": 50000000000,"threshold": 1000000000}},"db": {"status": "UP","details": {"database": "MySQL","version": "8.0.22"}}}
}

(二)数据库访问相关的 Starters

  1. spring-boot-starter-data-jpa
    • 功能介绍
      • 这个 Starter 用于简化 Java Persistence API(JPA)的使用。它包含了 JPA 实现库(如 Hibernate)、数据库驱动等依赖项,并自动配置了数据库连接和 JPA 实体管理器等。
    • 示例应用
      • 以下是一个使用 spring-boot-starter-data-jpa 和 Hibernate 实现的简单数据访问应用程序:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.JpaRepository;@SpringBootApplication
public class DataApplication {public static void main(String[] args) {SpringApplication.run(DataApplication.class, args);}interface UserRepository extends JpaRepository<User, Long> {}
}

  1. spring-boot-starter-data-redis
    • 功能介绍
      • spring-boot-starter-data-redis 用于集成 Redis 数据库。它提供了对 Redis 的操作接口,并自动配置了 Redis 连接。
    • 示例应用
      • 以下是一个使用 spring-boot-starter-data-redis 进行 Redis 操作的示例:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.redis.core.RedisTemplate;@SpringBootApplication
public class RedisApplication {public static void main(String[] args) {SpringApplication.run(RedisApplication.class, args);}@Beanpublic RedisTemplate<String, Object> redisTemplate() {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory());return template;}
}

(三)安全相关的 Starters

  1. spring-boot-starter-security
    • 功能介绍
      • 这个 Starter 用于快速集成 Spring Security,为应用程序提供安全认证和授权功能。
    • 示例应用
      • 以下是一个使用 spring-boot-starter-security 实现用户认证和授权的示例:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@SpringBootApplication
@EnableWebSecurity
public class SecurityApplication extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN").antMatchers("/user/**").hasRole("USER").anyRequest().authenticated().and().formLogin();}public static void main(String[] args) {SpringApplication.run(SecurityApplication.class, args);}
}

  1. spring-boot-starter-oauth2-client
    • 功能介绍
      • spring-boot-starter-oauth2-client 用于集成 OAuth 2.0 客户端功能,实现第三方认证和授权。
    • 示例应用
      • 以下是一个使用 spring-boot-starter-oauth2-client 进行 OAuth 2.0 认证的示例:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.authentication.OAuth2LoginAuthenticationFilter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;@SpringBootApplication
public class OAuth2ClientApplication {public static void main(String[] args) {SpringApplication.run(OAuth2ClientApplication.class, args);}@Beanpublic SecurityFilterChain filterChain(HttpSecurity http, ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) throws Exception {http.authorizeRequests(authorizeRequests ->authorizeRequests.antMatchers("/", "/login**", "/oauth2**").permitAll().anyRequest().authenticated()).oauth2Login(oauth2Login ->oauth2Login.clientRegistrationRepository(clientRegistrationRepository).authorizedClientRepository(authorizedClientRepository)).logout(logout ->logout.logoutSuccessUrl("/").addLogoutHandler(new LogoutFilter("/logout", clientRegistrationRepository, authorizedClientRepository)));return http.build();}
}

五、自定义 Starters

(一)创建自定义 Starter 的需求

  1. 封装特定功能
    • 在某些情况下,开发者可能需要封装特定的功能或技术,以便在多个项目中重复使用。例如,如果开发了一个自定义的日志框架,或者一个特定的数据库访问组件,可以将其封装为一个 Starter,方便在其他项目中引入。
  2. 简化项目配置
    • 自定义 Starter 可以简化项目的配置过程。通过将相关的依赖项和配置封装在一起,开发者可以在项目中快速引入特定的功能,而无需手动配置多个依赖项和进行复杂的配置。

(二)创建自定义 Starter 的步骤

  1. 确定功能和依赖项
    • 首先,确定要封装的功能和所需的依赖项。这可能包括特定的库、配置文件、自动配置类等。
  2. 创建项目结构
    • 创建一个新的 Maven 或 Gradle 项目,并按照 Spring Boot 的项目结构进行组织。通常包括 src/main/java 和 src/main/resources 目录。
  3. 编写自动配置类
    • 在 src/main/java 目录下,编写自动配置类。自动配置类应该使用条件注解来决定是否进行特定的配置,并提供默认的配置。
  4. 打包和发布
    • 将自定义 Starter 打包为一个 JAR 文件,并发布到本地 Maven 仓库或远程仓库中。这样,其他项目就可以通过在构建文件中添加依赖项的方式引入自定义 Starter。

(三)示例:创建一个自定义日志 Starter

  1. 确定功能和依赖项
    • 假设要创建一个自定义的日志 Starter,它使用 Log4j2 作为日志框架,并提供一些默认的配置。所需的依赖项包括 Log4j2 的库和相关的配置文件。
  2. 创建项目结构
    • 创建一个新的 Maven 项目,项目结构如下:
my-logging-starter
├── pom.xml
└── src├── main│   ├── java│   │   └── com.example.logging│   │       └── LoggingAutoConfiguration.java│   └── resources│       └── log4j2.xml└── test└── java

  1. 编写自动配置类
    • 在 LoggingAutoConfiguration.java 中,编写自动配置类:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ConditionalOnClass(Logger.class)
public class LoggingAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic Logger logger() {return LogManager.getLogger(getClass());}
}

  1. 打包和发布
    • 在项目的 pom.xml 文件中,添加必要的依赖项和打包配置,然后将项目打包为一个 JAR 文件。可以使用 Maven 的 mvn install 命令将其发布到本地 Maven 仓库中,或者使用 Maven 的 mvn deploy 命令将其发布到远程仓库中。

六、Starters 的使用技巧与注意事项

(一)选择合适的 Starter

  1. 根据项目需求
    • 在选择 Starter 时,要根据项目的具体需求来确定。不同的 Starter 提供了不同的功能,要选择与项目需求最匹配的 Starter,避免引入不必要的依赖项。
  2. 考虑性能和资源占用
    • 一些 Starter 可能会引入较多的依赖项,从而增加项目的体积和启动时间。在选择 Starter 时,要考虑性能和资源占用的问题,选择轻量级的 Starter 或者根据实际需求进行定制。

(二)排除不需要的自动配置

  1. 使用 @EnableAutoConfiguration 的 exclude 属性
    • 如果某个 Starter 中的自动配置与项目需求不匹配,可以使用 @EnableAutoConfiguration 的 exclude 属性来排除特定的自动配置类。例如:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

  1. 在 application.properties 或 application.yml 文件中设置属性
    • 也可以在 application.properties 或 application.yml 文件中设置属性来排除特定的自动配置。例如,设置 spring.autoconfigure.exclude 属性可以排除多个自动配置类:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

(三)注意依赖项版本冲突

  1. 了解依赖项关系
    • 在使用多个 Starter 时,要注意依赖项之间的版本冲突问题。不同的 Starter 可能会引入不同版本的依赖项,这可能会导致兼容性问题。要了解各个 Starter 所依赖的库的版本关系,避免版本冲突。
  2. 手动解决版本冲突
    • 如果出现版本冲突,可以通过手动排除特定的依赖项、调整依赖项的版本等方式来解决。在 Maven 或 Gradle 的构建文件中,可以使用 exclusion 标签来排除特定的依赖项,或者使用 version 属性来指定依赖项的版本。

七、实际案例分析

(一)案例背景

假设有一个电商项目,需要构建一个基于 Spring Boot 的后端服务。该项目需要实现 Web 服务、数据库访问、安全认证等功能。

(二)技术选型

  1. 使用 Spring Boot 和相关的 Starters
    • 选择 Spring Boot 作为开发框架,并根据项目需求选择合适的 Starters。例如,使用 spring-boot-starter-web 构建 Web 服务,使用 spring-boot-starter-data-jpa 访问数据库,使用 spring-boot-starter-security 实现安全认证。
  2. 数据库选择
    • 选择一个关系型数据库(如 MySQL)来存储数据,并使用 spring-boot-starter-data-jpa 中的自动配置功能来简化数据库访问的配置。
  3. 前端框架选择
    • 可以选择一个前端框架(如 Vue.js 或 React)来构建用户界面,与后端的 Spring Boot 服务进行交互。

(三)Starters 的应用

  1. 引入所需的 Starters
    • 在项目的构建文件中,添加所需的 Starters 依赖项:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

 

  1. 配置自动配置
    • 根据项目的具体需求,可能需要对一些自动配置进行调整。例如,可以在 application.properties 或 application.yml 文件中设置数据库连接信息、安全认证的配置等。
spring.datasource.url=jdbc:mysql://localhost:3306/ecommerce_db
spring.datasource.username=root
spring.datasource.password=password
spring.security.user.name=admin
spring.security.user.password=admin123

  1. 开发业务逻辑
    • 在引入了所需的 Starters 并进行了必要的配置后,可以开始开发业务逻辑。例如,可以创建实体类、数据访问层(Repository)、服务层(Service)和控制器层(Controller)来实现电商项目的各种功能,如商品管理、订单管理、用户管理等。

(四)效果评估

  1. 开发效率提升
    • 通过使用 Spring Boot 的 Starters,大大提高了开发效率。无需手动配置多个依赖项和进行复杂的配置,快速启动了项目的开发。
  2. 项目结构清晰
    • Starters 的使用使得项目的结构更加清晰。每个 Starter 负责特定的功能,使得项目的依赖关系更加明确,易于维护和扩展。
  3. 功能实现便捷
    • 借助 Starters 提供的自动配置和默认配置,能够快速实现项目所需的各种功能,如 Web 服务、数据库访问、安全认证等。

八、总结

Spring Boot 中的 Starters 是一种强大的工具,为开发者提供了快速启动项目、简化依赖管理和提供默认配置的功能。通过理解 Starters 的概念、工作原理和常见的 Starters,以及掌握自定义 Starters 的方法和使用技巧,开发者可以更好地利用 Spring Boot 进行高效开发。在实际项目中,要根据项目需求选择合适的 Starters,并注意排除不需要的自动配置和解决依赖项版本冲突问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/886087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

「QT」文件类 之 QTextStream 文本流类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「Win」Windows程序设计「IDE」集成开发环境「UG/NX」BlockUI集合「C/C」C/C程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「UG/NX」NX定制…

mysql 配置文件 my.cnf 增加 lower_case_table_names = 1 服务启动不了的原因

原因&#xff1a;在MySQL8.0之后的版本&#xff0c;只允许在数据库初始化时指定&#xff0c;之后不允许修改了 mysql 配置文件 my.cnf 增加 lower_case_table_names 1 服务启动不了 报错信息&#xff1a;Job for mysqld.service failed because the control process exited …

PVE纵览-安装系统卡“Loading Driver”的快速解决方案

PVE纵览-安装系统卡“Loading Driver”的快速解决方案 文章目录 PVE纵览-安装系统卡“Loading Driver”的快速解决方案摘要通过引导参数解决PVE安装卡在“Loading Driver”问题官方解决方法 关键字&#xff1a; PVE、 显卡、 Loading、 Driver、 nomodeset 摘要 在虚拟机…

[Android]相关属性功能的裁剪

1.将home界面的search bar 移除 /src/com/android/launcher3/graphics/LauncherPreviewRenderer.java // Add first page QSBif (FeatureFlags.QSB_ON_FIRST_SCREEN) {CellLayout firstScreen mWorkspaceScreens.get(FIRST_SCREEN_ID);View qsb mHomeElementInflater.infla…

Git的概念、安装、操作与分支管理和图形化界面TortoiseGit(小乌龟 )的安装与使用

目录 一、Git 概述 简介 安装 使用场景 二、Git 操作详解 使用git管理文件版本 使用 Git 管理代码 三、分支操作 使用小乌龟操作分支 创建新的分支 两个分支合并 四、总结 在当今的软件开发和文档编写等领域&#xff0c;版本控制工具至关重要。Git 作为其中的佼佼者…

边缘计算在智能制造中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 边缘计算在智能制造中的应用 边缘计算在智能制造中的应用 边缘计算在智能制造中的应用 引言 边缘计算概述 定义与原理 发展历程 …

设计模式之装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

前言&#xff1a; 两个本想描述一样的意思的词&#xff0c;只因一字只差就让人觉得一个是好牛&#xff0c;一个好搞笑。往往我们去开发编程写代码时也经常将一些不恰当的用法用于业务需求实现中&#xff0c;但却不能意识到。一方面是由于编码不多缺少较大型项目的实践&#xff…

使用热冻结数据层生命周期优化在 Elastic Cloud 中存储日志的成本

作者&#xff1a;来自 Elastic Jonathan Simon 收集数据对于可观察性和安全性至关重要&#xff0c;而确保数据能够快速搜索且获得低延迟结果对于有效管理和保护应用程序和基础设施至关重要。但是&#xff0c;存储所有这些数据会产生持续的存储成本&#xff0c;这为节省成本创造…

Node.js事件循环:解锁异步编程的奥秘

Node.js的事件循环是实现高性能、异步编程的关键机制。了解Node.js事件循环的工作原理和使用方法对于开发高效的应用程序至关重要。本文将深入介绍Node.js事件循环的原理、阶段和最佳实践&#xff0c;帮助您充分利用这一强大功能。 Node.js事件循环概述 Node.js事件循环是Node…

Windows docker下载minio出现“Using default tag: latestError response from daemon”

Windows docker下载minio出现 Using default tag: latest Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded 此类情况&#xff0c;一般为镜像地址问题。 {"registry-mirrors": ["https://docker.re…

20241114软考架构-------软考案例16答案

每日打卡题案例16答案 16.【2017年真题】 难度&#xff1a;简单 阅读以下关于软件架构评估的叙述&#xff0c;在答题纸上回答问题1和问题2.(共25分) 【说明】 某单位为了建设健全的公路桥梁养护管理档案&#xff0c;拟开发一套公路桥梁在线管理系统。在系统的需求分析与架构设…

使用C语言进行信号处理:从理论到实践的全面指南

1. 引言 在现代操作系统中&#xff0c;信号是一种进程间通信机制&#xff0c;它允许操作系统或其他进程向一个进程发送消息。信号可以用来通知进程发生了一些重要事件&#xff0c;如用户请求终止进程、硬件异常、定时器超时等。掌握信号处理技术对于开发健壮、高效的系统程序至…

7天用Go从零实现分布式缓存GeeCache(学习)(2)

参考:https://geektutu.com/post/geecache-day2.html // Cache 是一个 LRU 缓存&#xff08;最近最少使用缓存&#xff09;&#xff0c;它不是并发安全的。 type Cache struct { maxBytes int64 // 缓存的最大字节数 nbytes int64 …

【微服务】Docker 容器化

一、初识Docker 1. 为什么需要 Docker 大型项目组件较多&#xff0c;运行环境也较为复杂&#xff0c;部署时会遇到一些问题&#xff1a; 依赖关系复杂&#xff0c;容易出现兼容性的问题开发、测试、生产环境有差异 Docker 如何解决依赖的兼容问题 将应用的Libs&#xff08;…

curl命令提交大json

有个客户需要提交一个4M左右的pdf&#xff0c;接口里传的是pdf字节流base64编码后的字符串。 直接curl -XPOST -d json串 api接口会报 参数过长报错Argument list too long 网上搜了下解决方案把json串放到文本里然后通过json.txt引入参数 这一试不要紧&#xff0c;差点儿导致…

websocket身份验证

websocket身份验证 前言 上一集我们就完成了websocket初始化的任务&#xff0c;那么我们完成这个内容之后就应该完成一个任务&#xff0c;当客户端与服务端连接成功之后&#xff0c;客户端应该主动发起一个身份认证的消息。 身份认证proto 我们看一眼proto文件的内容。 我…

Scala学习记录,case class,迭代器

case class case class创建的对象的属性是不可改的 创建对象&#xff0c;可以不用写new 自动重写&#xff1a;toString, equals, hashCode, copy 自动重写方法&#xff1a;toString,equals,hashCode,copy 小习一下 1.case class 的定义语法是什么 基本形式&#xff1a;case …

mysql中的EXISTS和NOT EXISTS使用详解

本文来编写一个实例说下mysql中的EXISTS和NOT EXISTS使用详解 文章目录 exists用法SQL中in, not in, exists, not exists的区别使用实例本文小结 exists用法 exists: 如果括号内子查询语句返回结果不为空&#xff0c;说明where条件成立&#xff0c;就会执行主SQL语句。如果括号…

HTB:Precious[WriteUP]

目录 连接至HTB服务器并启动靶机 使用nmap对靶机TCP端口进行开放扫描 使用curl访问靶机80端口 使用ffuf爆破一下子域 使用浏览器访问该域名 使用curl访问该域名响应头 使用exiftool工具查看该pdf信息 横向移动 USER_FLAG&#xff1a;adf5793a876a190f0c08b3b6247cec32…

【论文分享】三维景观格局如何影响城市居民的情绪

本次带来一篇SCI论文的全文翻译&#xff01;该论文以上海LivingLine项目为例&#xff0c;探索利用时空Wi-Fi数据分析街道层面的城市活力。 【论文题目】Understanding street-level urban vibrancy via spatial-temporal Wi-Fi data analytics: Case LivingLine Shanghai 【题…