URI vs URL:彻底搞懂这两个常被混淆的概念

URI vs URL:彻底搞懂这两个常被混淆的概念(超详细图文教程)

作者:IT之一小佬
发布日期:2025年10月19日
阅读时间:12分钟
适合人群:前端开发、后端开发、网络工程师、计算机专业学生


🌟 引言:一个常见的面试题

你是否曾在面试中被问到:

“URI 和 URL 有什么区别?”

或者在开发中看到这样的代码感到困惑:

// 这是 URI 还是 URL?
const resource = "/api/users/123";

又或者在配置 Nginx 时纠结:

location /static/ {
    # 这里匹配的是 URI 还是 URL?
}

今天,我们将用最通俗易懂的方式,结合大量实例和图解,彻底搞懂 URIURL 的区别与联系。


一、快速结论(先看答案)

概念全称中文关系
URIUniform Resource Identifier统一资源标识符父类,表示“我是谁”
URLUniform Resource Locator统一资源定位符子类,表示“我在哪”

一句话总结

  • 所有 URL 都是 URI
  • 但并非所有 URI 都是 URL

就像:

  • “动物” 是一个广义的类别(类似 URI)
  • “狗” 是一种具体的动物,可以定位(类似 URL)
  • 但“独角兽”是一种虚构的动物(类似 URN),它存在但无法定位

二、核心概念详解

1. 什么是 URI?(统一资源标识符)

URI 是一个 字符串,用于唯一标识互联网上的一个资源。

  • 🔹 它回答的问题是:“这个资源叫什么?”
  • 🔹 它不关心资源在哪里,只关心如何标识它
URI 的通用格式:
<scheme>:[//<authority>]<path>[?<query>][#<fragment>]
部分说明示例
scheme协议类型http, https, ftp, mailto
authority权威部分(用户@主机:端口)user@host.com:8080
path资源路径/docs/readme.html
query查询参数?q=python&sort=desc
fragment片段标识#section-2

URI 的目标是“唯一性”,确保每个资源都有一个独一无二的名字。


2. 什么是 URL?(统一资源定位符)

URL 是 URI 的一个子集,它不仅标识资源,还提供如何访问该资源的位置信息

  • 🔹 它回答的问题是:“这个资源在哪?怎么找到它?”
  • 🔹 必须包含协议和主机名(如 http://example.com
URL 的典型结构:
协议://主机名[:端口]/路径?查询参数#片段

👉 示例

https://www.example.com:443/blog/post?id=123#comments
部分
协议https
主机名www.example.com
端口443
路径/blog/post
查询id=123
片段comments

URL 的目标是“可访问性”,你可以直接在浏览器中输入它来获取资源。


3. 什么是 URN?(统一资源名称)

URN 是另一种 URI 子集,它为资源提供持久的、位置无关的名称

  • 🔹 它回答的问题是:“这个资源的永久名字是什么?”
  • 🔹 即使资源移动或删除,URN 依然有效
格式:
urn:<namespace>:<identifier>
示例:
urn:isbn:978-3-16-148410-0        # 一本书的 ISBN
urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66  # 一个 UUID

⚠️ 注意:URN 不能直接访问资源,它只是一个名字。你需要额外的系统(如 DNS、数据库)来解析它。


三、关系图解(一张图看懂)

                    ┌─────────────────┐
                    │     URI         │
                    │ (标识资源)       │
                    └────────┬────────┘
                             │
           ┌────────────────┼────────────────┐
           │                                │
┌───────────────────┐          ┌────────────────────┐
│        URL        │          │        URN         │
│  (定位资源)        │          │  (命名资源)         │
└───────────────────┘          └────────────────────┘
  https://...                     urn:isbn:...
  ftp://...                       urn:uuid:...
  mailto:user@com

URL + URN ⊆ URI


四、真实世界中的例子对比

字符串是 URI?是 URL?说明
https://www.google.com/search?q=uri完整 URL,也是 URI
/images/logo.png相对路径,标识资源但无位置
#top页面内锚点,仅标识片段
mailto:support@example.com特殊 URL,通过邮件协议定位
urn:isbn:1234567890只是名字,无法直接访问
javascript:alert('hello')JS URL,执行脚本
file:///home/user/doc.txt本地文件 URL

💡 注意:mailto:javascript: 虽然看起来不像传统网址,但它们是合法的 URL,因为它们指明了“如何处理”该资源。


五、在 Web 开发中的实际应用

1. HTML 中的使用

<!-- URL:外部资源 -->
<link rel="stylesheet" href="https://cdn.example.com/style.css">

<!-- URI:相对路径(也是 URI) -->
<img src="/assets/logo.svg" alt="Logo">

<!-- URI:页面内跳转 -->
<a href="#footer">跳转到底部</a>

<!-- URL:发送邮件 -->
<a href="mailto:contact@example.com">联系我们</a>

2. HTTP 请求中的角色

GET /api/users/123?include=posts HTTP/1.1
Host: api.example.com
  • Request-URI/api/users/123?include=posts
    • 这是一个 URI,服务器用它来识别要操作的资源
  • 完整的 URL 是:http://api.example.com/api/users/123?include=posts
    • 由客户端根据 Host 头和协议拼接而成

3. Nginx/Apache 配置

location /static/ {
    alias /var/www/static/;
}
  • 这里的 /static/ 是一个 URI 路径前缀
  • 它匹配所有以该 URI 开头的请求,无论来自哪个域名

4. RESTful API 设计

POST /api/v1/users      → 创建用户(URI)
→ 响应:201 Created, Location: https://api.example.com/users/123
                         ↑ 这是一个 URL,指向新创建的资源
  • 请求中的 /api/v1/usersURI
  • 响应头中的 LocationURL,告诉客户端新资源的位置

六、常见误区与答疑

❌ 误区 1:“URI 就是网址”

纠正:网址(Website Address)通常指的是 URL。URI 更广泛,包括不能直接访问的标识符。


❌ 误区 2:“相对路径不是 URI”

纠正:相对路径如 /css/main.css 是合法的 URI。URI 不要求必须有协议和主机。


❌ 误区 3:“URN 已经过时了”

纠正:URN 在特定领域(如数字出版、学术引用)仍在使用。UUID 常被用作 URN 实现持久标识。


❓ 为什么需要区分 URI 和 URL?

场景为什么重要
API 设计正确使用 URI 可以设计出更语义化的接口
搜索引擎优化规范的 URI 结构有助于 SEO
安全策略CSP(内容安全策略)基于 URI 匹配资源
缓存机制缓存键通常是请求的 URI

七、编程语言中的处理

Python 示例

from urllib.parse import urlparse, urljoin

# 解析 URL
url = "https://www.example.com:8080/path?query=1#frag"
parsed = urlparse(url)

print(parsed.scheme)   # https
print(parsed.netloc)   # www.example.com:8080
print(parsed.path)     # /path
print(parsed.query)    # query=1
print(parsed.fragment) # frag

# 构建绝对 URI
base = "https://example.com/docs/"
relative = "tutorial.html"
absolute = urljoin(base, relative)
print(absolute)  # https://example.com/docs/tutorial.html

JavaScript 示例

// 浏览器环境
const url = new URL('https://api.example.com/users?limit=10');

console.log(url.origin);     // https://api.example.com
console.log(url.pathname);   // /users
console.log(url.search);     // ?limit=10
console.log(url.hash);       // (empty)

// 获取完整 URI(不含 origin)
const uri = url.pathname + url.search + url.hash;
console.log(uri);            // /users?limit=10

八、总结:一张表快速掌握

特性URIURLURN
全称统一资源标识符统一资源定位符统一资源名称
是否唯一标识资源
是否包含位置信息
是否可直接访问
示例/api/users, #sectionhttps://..., ftp://...urn:isbn:...
关系父类子类子类

九、延伸阅读

  • RFC 3986 - URI 通用语法(权威文档)
  • MDN: Standard request headers - 了解 Host、Location 等头字段
  • 《RESTful Web APIs》- Leonard Richardson 著,深入讲解 URI 设计原则

🔚 结语

现在,当你再被问到:

“URI 和 URL 有什么区别?”

你可以自信地回答:

“URI 是资源的唯一标识,URL 是 URI 的一种,它不仅标识资源,还告诉我们在哪里可以找到它。就像‘身份证号’和‘家庭住址’的关系。”

希望这篇教程帮你彻底理清了这两个概念。如果觉得有用,欢迎分享给你的朋友和同事!

💬 评论区互动:你在项目中遇到过哪些 URI/URL 的坑?欢迎留言讨论!

spring: cloud: gateway: globalcors: add-to-simple-url-handler-mapping: true corsConfigurations: '[/**]': allowedHeaders: "*" allowedOrigins: "*" allowedMethods: - GET - POST - DELETE - PUT - OPTION routes: # 用户微服务 - id: user uri: lb://leadnews-user predicates: - Path=/user/** filters: - StripPrefix= 1 # 文章微服务 - id: article uri: lb://leadnews-article predicates: - Path=/article/** filters: - StripPrefix= 1 #搜索微服务 - id: leadnews-search uri: lb://leadnews-search predicates: - Path=/search/** filters: - StripPrefix= 1 #行为微服务 - id: leadnews-behavior uri: lb://leadnews-behavior predicates: - Path=/behavior/** filters: - StripPrefix= 1 #评论微服务 - id: leadnews-comment uri: lb://leadnews-comment predicates: - Path=/comment/** filters: - StripPrefix= 1这是user-gateway的网关配置,spring: cloud: gateway: globalcors: add-to-simple-url-handler-mapping: true corsConfigurations: '[/**]': allowedHeaders: "*" allowedOrigins: "*" allowedMethods: - GET - POST - DELETE - PUT - OPTION routes: # 平台管理微服务 - id: admin uri: lb://leadnews-admin predicates: - Path=/admin/** filters: - StripPrefix= 1 # 用户微服务 - id: user uri: lb://leadnews-user predicates: - Path=/user/** filters: - StripPrefix= 1 # 文章微服务 - id: article uri: lb://leadnews-article predicates: - Path=/article/** filters: - StripPrefix= 1 # 频道微服务 - id: wemedia uri: lb://leadnews-wemedia predicates: - Path=/wemedia/** filters: - StripPrefix= 1 # 敏感词微服务 - id: sensitive uri: lb://leadnews-sensitive predicates: - Path=/sensitive/** filters: - StripPrefix= 1 #搜索微服务 - id: leadnews-search uri: lb://leadnews-search predicates: - Path=/search/** filters: - StripPrefix= 1这是admin-gateway的配置,这两个都有 # 文章微服务 - id: article uri: lb://leadnews-article predicates: - Path=/article/** filters: - StripPrefix= 1这样的断言,现在我是admin用户登录,我想要查询文章信息,用到leadnews-article微服务,再断言一样的情况下怎么知道走那个网关
06-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值