apache的servername仅标识虚拟主机,真正控制请求流向的是rewriterule配合rewritecond;需用%{http_host}(非servername字面值)做条件匹配,且每条rewritecond仅对紧随其后的rewriterule生效。

Apache 的 ServerName 本身只是用于标识虚拟主机的域名,它不直接参与请求处理流程的改变,真正控制请求流向和行为的是 RewriteRule 配合 RewriteCond。但你可以利用 ServerName(或更准确地说,是 %{HTTP_HOST} 这个服务器变量)作为判断依据,在 Rewrite 规则中做条件分支,从而让不同域名走不同的处理逻辑。
关键点在于:ServerName 是配置项,而 %{HTTP_HOST} 是运行时实际收到的 Host 请求头值——后者才是 Rewrite 中可匹配、可判断的真实依据。
✅ 基于域名(ServerName 对应的 Host)做 Rewrite 分流
这是最常见也最实用的方式。例如:
<virtualhost>
ServerName example.com
ServerAlias www.example.com blog.example.com api.example.com
DocumentRoot /var/www/example
<directory>
Options +FollowSymLinks
AllowOverride None
Require all granted
RewriteEngine On
# 条件1:如果是 blog.example.com,全部代理到内部博客服务
RewriteCond %{HTTP_HOST} ^blog\.example\.com$ [NC]
RewriteRule ^(.*)$ http://127.0.0.1:8080$1 [P,L]
# 条件2:如果是 api.example.com,强制走 HTTPS 并转发
RewriteCond %{HTTP_HOST} ^api\.example\.com$ [NC]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
# 条件3:其他子域(如 www 或主站)走静态文件+PHP 入口
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [L]
</directory></virtualhost>
说明:
-
%{HTTP_HOST}获取浏览器发来的 Host 头,不是ServerName字面值,但通常与之一致; - 每个
RewriteCond只对紧随其后的 一条RewriteRule生效; -
[P]表示反向代理(需加载mod_proxy),[R=301]是外部跳转,[L]表示终止当前规则链; - 所有规则都写在
<directory></directory>内,且必须有RewriteEngine On。
✅ 利用 ServerName 区分多站点并独立启用 Rewrite
多个 VirtualHost 之间 不共享 Rewrite 规则,也不能继承。即使共用同一 IP 和端口,每个 VirtualHost 必须显式开启引擎并定义自己的规则:
Apache 2.4.62 官方 tar.gz 源码包是 Linux 及类 Unix 系统构建 Web 服务器的核心基础。通过源码编译安装,开发者能够灵活定制模块、优化性能并精准控制安装路径,满足多样化的业务需求。
<virtualhost>
ServerName shop.example.com
DocumentRoot /var/www/shop
<directory>
Options +FollowSymLinks
AllowOverride None
Require all granted
RewriteEngine On
RewriteRule ^product/(\d+)$ /product.php?id=$1 [L]
</directory></virtualhost><virtualhost>
ServerName admin.example.com
DocumentRoot /var/www/admin
<directory>
Options +FollowSymLinks
AllowOverride None
Require all granted
RewriteEngine On
RewriteRule ^(.*)$ /auth.php?path=$1 [QSA,L]
</directory></virtualhost>
注意:
- 即使两个站点目录相同,规则也互不影响;
-
ServerName在这里起“路由分发”作用——Apache 先根据 Host 头选中对应VirtualHost,再执行其中的 Rewrite; - 不写
RewriteEngine On,该虚拟主机内的所有RewriteRule都会被忽略。
✅ 常见误用提醒
- ❌ 不要在
<virtualhost></virtualhost>根层级直接写RewriteRule,必须包裹在<directory></directory>或<location></location>中; - ❌ 不要混用
.htaccess和<directory></directory>里的规则,易冲突或重复执行; - ❌
^/article/是错的写法,路径匹配用^article/(开头无斜杠); - ❌ 忘记
Options +FollowSymLinks会导致 500 错误(尤其在启用.htaccess时); - ❌ 忘加
!-f和!-d判断,会导致真实文件/目录被错误重写到 PHP 脚本。
✅ 实用技巧:统一入口 + 多域名识别
如果你用单入口(如 index.php)统一路由,又想区分来源域名做不同逻辑,可在 PHP 中读取:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [QSA,L]
然后在 index.php 里:
$host = $_SERVER['HTTP_HOST'] ?? '';
if (strpos($host, 'admin.') === 0) {
// 后台逻辑
} elseif (strpos($host, 'api.') === 0) {
// API 逻辑
} else {
// 前端逻辑
}
这样把路由判断后移到应用层,更灵活,也避免 Apache 规则过于复杂。
不复杂但容易忽略。










