Apache整合Tomcat实现静态资源与动态资源分离(二)

时间:2021-09-22 13:25:40

这几天又研究了一下,有新的发现,赶紧记录下来。


其实可以通过Apache的代理功能来实现静态资源和动态资源的分离。


假设我的web项目中有3个文件夹,分别用来存放不同的静态资源,如:
1) dojo_lib: 存放所有dojo文件(这个比较大)
2) css: 存放项目应用的css样式
3) pages: 存放项目的页面文件


现在我想把dojo_lib放在Apache服务器里,不跟web项目一起部署到tomcat。而css和pages则跟项目一起部署到tomcat。当要请求dojo_lib里的文件时,Apache服务器直接处理请求;而当请求css或pages里的文件时,Apache服务器把请求转给tomcat处理。


好了,怎样实现呢?方法如下:


第一步:

准备两个FQDN。一个用来访问静态资源,一个用来访问web项目。(还没想到怎样才可以只用一个FQDN来实现。。)

FQDN1:static.webapp.com // 用来访问静态资源

FQDN2:webapp.com // 用来访问web项目

(注:这两个FQDN都指向同一个IP,即本地服务器IP)


第二步:

写一个 "static-resource-proxy.conf" 文件,内容如下,然后include到httpd.conf里。

# 要载入这两个modules
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

<VirtualHost *:80>
# DocumentRoot, 存放静态资源的地方
 DocumentRoot C:/Project-Tools/httpd-2.4.18-x64/Apache24/htdocs/webapp/
ServerName static.webapp.com # 访问静态资源的FQDN
ServerAlias static.webapp.com
</VirtualHost>

<VirtualHost *:80>
ServerName webapp.com # 访问项目的FQDN
ServerAlias webapp.com
ErrorLog logs/webapp-error.log
CustomLog logs/webapp-access.log common

# 下面是重点
ProxyRequests off
 ProxyPass /dojo_lib/ http://static.webapp.com/dojo_lib/
ProxyPass /css/ http://webapp.com:8001/project_name/css/
ProxyPass /pages/ http://webapp.com:8001/project_name/pages/
ProxyPass / http://webapp.com:8001/project_name/
ProxyPassReverse / http://webapp.com:8001/project_name/

# 非常重要,用于保持每个request都在同一个session里
    ProxyPassReverseCookiePath /project_name/ /
</VirtualHost>


第一个ProxyPass,意思是,若请求的开头是/dojo_lib/的话,则这个请求不会交给应用服务器(即tomcat)处理,而是由Apache自己处理。Apache会把这个请求转换为一个代理请求。例如,如果原请求是http://webapp.com/dojo_lib/dojo/dojo.js,Apache会把它转换为代理请求http://static.webapp.com/dojo_lib/dojo/dojo.js。


第二个ProxyPass,同理,若请求的开头是/css/(如http://webapp.com/css/app.css),Apache会把它转换为一个代理请求(http://webapp.com:8001/project_name/css/app.css)。注意看这个代理的URL,它是把请求交给tomcat处理,直接访问web项目内部的资源。(我的tomcat端口是8001)


第三个ProxyPass,同上。


第四个ProxyPass,这个是什么意思呢?它的意思是,把http://webapp.com/ 下的所有请求都交给tomcat处理,转换为http://webapp.com:8001/project_name/ 下的对应请求。例如,如果原请求是http://webapp.com/index.do,Apache会把它转换为http://webapp.com:8001/project_name/index.do。


关于这四个ProxyPass的顺序,前三个顺序无所谓,但第四个一定要放在最后。我的猜测是,Apache在匹配请求的时候,是从上到下逐个匹配的。一旦找到对应请求,就马上触发代理规则,并停止向下匹配。而第四个可匹配的范围最大,所以要放最后。


第四个ProxyPass会导致一个非常好的结果,那就是可以隐藏tomcat的端口和项目名。想想,当只有tomcat时,我们访问项目时要指定端口和项目名,如http://webapp.com:8001/project_name/index.do。现在有了Apache代理,我们只需要访问http://webapp.com/index.do就可以了。


补充:

其实之前也尝试过利用Apache的代理来转发,但一直不成功。原因是当时我的代理配置是这样的:

# 要载入这两个modules  
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

<VirtualHost *:80>
# DocumentRoot, 存放静态资源的地方
DocumentRoot C:/Project-Tools/httpd-2.4.18-x64/Apache24/htdocs/webapp/
ServerName static.webapp.com # 访问静态资源的FQDN
ServerAlias static.webapp.com
</VirtualHost>

<VirtualHost *:80>
ServerName webapp.com # 访问项目的FQDN
ServerAlias webapp.com
ErrorLog logs/webapp-error.log
CustomLog logs/webapp-access.log common

# 下面是重点
ProxyPass /dojo_lib/ http://static.webapp.com/dojo_lib/
ProxyPass /css/ http://static.webapp.com/css/
ProxyPass /pages/ http://static.webapp.com/pages/
</VirtualHost>

 
我把css和pages的请求都代理出去了,不交给tomcat。其实这没有问题。最大的问题是我没有配置第四个代理。所以我访问项目时发送的请求是http://webapp.com:8001/project_name/index.do。(静态资源的访问地址是http://webapp.com:8001/project_name/dojo_lib/dojo/dojo.js),代理不成功。为什么?因为我访问的端口(注意是在浏览器输入的端口,不是代理转发后的端口)是8001,不是80。而Apache只监听80端口,所以根本没有触发到Apache的代理规则...