如何不使用应用名,直接通过虚拟主机的名称或绑定的域名来访问应用呢?
进行Web开发部署的人常会有以上的疑问。在进行Web应用发布时,经常需要通过以下这种形式进行应用的请求。
虚拟主机 +端口 + 应用名
而如果我们配置了针对应用的特定虚拟主机,一个虚拟主机上只有这一个应用,再通过应用名访问就没什么必要,同时显的繁琐。
那在Tomcat中,怎么样配置,以支持通过虚拟主机(端口如果是80,也可以跳过)直接访问应用呢?
官方文档中,对于Context中应用名称这个属性有这样的描述:
我们看到,如果要为虚拟主机配置默认的应用,我们可以给context的path配置为空。这里注意一下,为空的意思,是指空串,而不是不指定。当然,对于应用名称,我们在指定时一般是 /abc这种形式,所以为空时,也可以指定成 / 这样
所以,配置成以下两种形式,都是OK的。
<Context path="" docBase="/home/abc/xxx"/>
<Context path="/" docBase="/home/abc/xxx"/>
当然,除了以上这种配置外,将应用的WAR包或者目录命名为ROOT,也可以起到上面的作用。Tomcat在webapps目录下自带的ROOT应用就是个例子。
我们来看Tomcat内部,是如何处理的这些逻辑。
首先在Server启动时,会涉及到应用的部署,部署过程,可以参考前面的文章:
部署过程中,会根据具体的Context的配置,获取对应的应用名称,从而进行应用名称的配置和注册。
以下是部署前,解析配置的应用名称:
部署时,根据是在server.xml中配置部署还是在自动部署目录中部署,处理情况不同:
在配置文件中配置的情况:
webapps自动部署时的配置是这样:
我们再看,在代表应用名称的类ContextName内,包含以下声明:
public static final String ROOT_NAME = "ROOT";
同时,应用部署,获取具体Context名称的时候,对应的ContextName构造函数里有下面的逻辑,
public ContextName(String path, String version) {
// Path should never be null, '/' or '/ROOT'
if (path == null || "/".equals(path) || "/ROOT".equals(path)) {
this.path = "";
} else {
this.path = path;
}
同时,对于
我们发现对于ROOT应用,在另一个构造函数里,直接对应到的请求路径为空。
if (ROOT_NAME.equals(tmp2)) {
path = "";
}
后续的Context注册,就会用到这里的path。这里的注册过程,可以参考前面的文章:
我们看到,注册的过程中,如果有path为/的情况,也会自动转化为空串。
而在应用请求的时候,如果我们只输入了主机名(这里假设端口为80,忽略端口号),此时,到达Tomcat的请求应用名直接是一个 / , 此时,会经历从mapper中寻找应用的过程,会根据mapper中对应的应用名称列表,以及当前的请求应用名称进行比对,判断具体对应关系。
整个匹配对应的过程,从一个二分查找中进行
没有匹配到,就会匹配a的默认值0,即第一个应用。第一个应用是什么呢?
就是我们配置的默认应用,path为空的那个。
例如下面是Tomcat自带的几个应用的path,这是在mapper中注册的情况。
所以,在配置到默认的path为空的应用后,就会用它进行请求的后续响应了。
标签:虚拟主机,部署,配置,访问,应用,path,ROOT 来源: https://blog.51cto.com/u_15127648/2776634
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。