从虚拟主机的URL中删除Tomcat上下文(mod_jk,mod_rewrite)
我有一个包含多个webapps的Tomcat实例,每个实例都可以通过/ Context访问。 Tomcat的背后是httpd(实际上是Debian Apache2),配置了虚拟主机来为每个应用/上下文服务。 Tomcat连接与mod_jk。从虚拟主机的URL中删除Tomcat上下文(mod_jk,mod_rewrite)
当我不关心从网址中删除上下文时,此功能正常工作:当请求虚拟域的根时,请求被重定向到domain.com/Context。
但是对于一个应用程序,我做想要删除上下文。我相信这可以通过使用mod_rewrite来完成,并将重写的url传递给mod_jk以传递给正确的Tomcat上下文。所以,我的Debian Apache2的网站,提供文件看起来像这样:
NameVirtualHost *
<VirtualHost *>
ServerName domain.be
DocumentRoot /home/webapp/app/static/domain/
RewriteEngine on
RewriteRule ^/(.*)$ /Context/$1 [L,PT]
RewriteLog "/var/log/apache2/domain-rewrite.log"
RewriteLogLevel 4
JkLogFile /var/log/apache2/domain-mod_jk.log
JkLogLevel debug
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkMount /Context w1
JKMount /Context* w1
JkOptions +ForwardURICompat
ErrorLog /var/log/apache2/domain_error.log
CustomLog /var/log/apache2/domain_access.log combined
LogLevel warn
</VirtualHost>
根据该文档时,[PT]标志和+ ForwardURICompat选项应该导致重写URL传递给jk_mod。但是,这似乎并没有发生。
URL正在重写,但看起来好像mod_jk忽略它:例如,将domain.be/Context的请求重写为/ Context/Context - 但仍然作为/ Context传递给mod_jk。
任何想法?顺便说一下,我目前不能使用mod_proxy。
感谢
我一直在使用这种大获成功:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/(Context/.*)$
RewriteRule ^/(.*)$ /Context/$1 [P,L]
说明您的情况:
- 您将需要获得mod_proxy的工作或
[P]
将被忽略并且该请求将被转发而不是代理。这是没有办法的。 -
+ForwardURICompat
是mod_jk的一部分,将在重写后生效。 - mod_jk忽略请求,因为它永远不会到达那里。您需要一个
RewriteCond
(上面)来防止/ Context的请求被重写。
我目前正在寻找一种方法来做到这一点没有mod_rewrite和使用,而是,just mod_jk and Tomcat <Host>'s。但是我在apache,mod_jk和Tomcat主机很好地一起玩时遇到了麻烦。以上应该适合你。
@Josh,我认为这个解决方案不会工作,如果tomcat执行任何重定向。例如,在需要登录的应用程序中,这是典型的情况。当用户未通过认证时,应用程序将重定向到/ login这样的内容,但是tomcat会像在/ context/login中一样追加当前上下文,因此最终上下文在URL中显示。
正如你在其他问题/回应中提到的,只使用mod-jk加上tomcat虚拟主机是一个选项,但是你需要将你的应用程序部署为ROOT.war,这可能不那么简单。有一个解决方法,所以你的应用程序可以放在tomcat webapps文件夹中,但正如我所描述的here服务器将部署应用程序至少两次。
如果RewriteRule [P]加上JkOptions + ForwardURICompat可以工作,但它不会。顺便说一句,我已经测试了这一点,我知道mod_proxy的工作,因为我代理我的网站cnn.com,我得到他们的网页下我的网站URL。以下是日志BTW的请求,你可以看到一个代理正在使用:
127.0.0.1 - - [15/Dec/2011:12:56:34 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/
127.0.0.1 - - [15/Dec/2011:12:56:34 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/ [OK]
127.0.0.1 - - [15/Dec/2011:12:56:49 --0500] [localhost/sid#1008ef278][rid#1009aaca8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/login
127.0.0.1 - - [15/Dec/2011:12:56:49 --0500] [localhost/sid#1008ef278][rid#1009aaca8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/login [OK]
127.0.0.1 - - [15/Dec/2011:12:57:15 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/j_spring_security_check
127.0.0.1 - - [15/Dec/2011:12:57:15 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/j_spring_security_check [OK]
127.0.0.1 - - [15/Dec/2011:13:08:41 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/
127.0.0.1 - - [15/Dec/2011:13:08:41 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/ [OK]
我会离开我的原始答案,但它是错误的。这样做的正确方法是用Tomcat的虚拟主机:
http://tomcat.apache.org/tomcat-6.0-doc/virtual-hosting-howto.html
官方步行通过上面的链接正是我用过好几次了。我不会试图在这里把它煮沸。
该概念与Apache Vhost相同。创建一个虚拟主机(例如something.yourtdomain.com
),然后将您的Web应用程序部署到该虚拟主机的ROOT
应用程序(/
),然后完成设置。这样,如果您已有一个ROOT
Web应用程序,则可以在另一个域中拥有另一个域,并且以前不会受到影响。
正如Nestor提到的,Apache重写规则不会处理标记库和框架等内容,它们会根据上下文根自动为您创建链接/表单动作/ etc。在这种情况下,他们将创建正确的上下文根(/
)。
如果您不知道,可以将应用程序保留在webapps目录中,并将appBase设置为应用程序的完整路径。 ---示例:
使用的mod_proxy_ajp代替mod_jk的象下面这样:
<VirtualHost *:80>
ServerName domain.be
DocumentRoot /home/webapp/app/static/domain/
...
ProxyPass /Context ajp://localhost:8009/Context
ProxyPass/ajp://localhost:8009/Context/
...
</VirtualHost>
如果Tomcat执行任何重定向,那仍然不起作用。它根本没有改变根本问题。没有答案。 – EJP 2012-11-04 09:05:58
继内斯特乌尔基萨的答案给出提示,我设法在tomcat的server.xml中定义额外的主机来解决问题,因为正如所说,j_security_check请求回答通过tomcat向浏览器发送一个前向指令,这个指令不可避免地包含上下文名称,以便试图登录的用户获得408个错误。因此,Apache VirtualHost JkMount /* worker1
指令中的实际传递可通过制定预期的上下文来实现,即ROOT
。
Apache的httpd.conf [和/或所包括的*的.conf]的文件:
<!-- the subdomain -->
<VirtualHost *:80>
ServerName appWelcome.example.org
ServerAlias www.appWelcome.example.org
JKMount /* worker1
</VirtualHost>
<!-- with mod_jk set up -->
LoadModule jk_module modules/mod_jk.so
JWorkersFile /etc/apache2/workers.properties
JkShmFile /var/log/apache2/mod_jk.shm
所以映射作出直接子域http://appWelcome.example.org/
到主管/ appWelcome Tomcat的上下文中,所有appWelcome请求上下文必须是可寻址的http://appWelcome.example.org:8080/
因此,tomcat server.xml文件将为您正在使用的应用程序公开一个单独的Host
文件:。
<Server ...>
<Service>
<Engine defaultHost="localhost" ...>
<Host name="appWelcome.example.org" appBase="appWelcomeBase" ... >
<Valve ... />
</Host>
<Host name="localhost" appBase="webapps" ...>
<!-- this Host is typically shipped with manager, host-manager, docs,
sample, examples and a default ROOT context that shows tomcat default home. -->
<Valve ... />
</Host>
</Engine>
</Service>
</Server>
注意的权限(如果启用SELinux的上下文中)必须调整以模仿默认Host
者如下:
$CATALINA_HOME/conf/Catalina/app.example.org
为$CATALINA_HOME/conf/Catalina/localhost
$CATALINA_HOME/appWelcomeBase
为$CATALINA_HOME/webapps
何处这是做的所有剩下要做的是问题重命名和移动appWelcome.war
网络归档为它自动部署在创建的appBase
(用它的值替换$ CATALINA_HOME,例如/ var/www/tomcat7):
# mv $CATALINA_HOME/webapps/appWelcome.war $CATALINA_HOME/appWelcomeBase/ROOT.war
瞧!
你是对的,我的原始解决方案不是最好的方式,充满危险。但自发布以来,我用Tomcat VirtualHosts取得了很大的成功。尽管没有听说过人们使用它,但在这种情况下肯定会想要使用它,而在创建之后却一点也不难。 – 2012-06-16 17:38:42