概述
需求:
希望通过request header来动态请求不同的war包(即Context)
问题:
由于servlet只提供了filter进行过滤,而filter实现在context中,所以该需求以servlet标准无法实现.
解决方法:
Tomcat在context以上存在engine和host层.因此在host层加入一层valve过滤,通过判断request header,重写request URI, context和wrapper(servlet)来动态实现context的切换.
代码实现:
Valve类:
package com.mobiscloud;
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.catalina.Context;
import org.apache.catalina.Host;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.tomcat.util.buf.MessageBytes;
public class ProxyValve extends ValveBase {
// private static String QUESTION_MARK ="?";
@Override
public void invoke(Request request, Response response) throws IOException,
ServletException {
String currentContext = "/miaomiao";
String currentContextName = "miaomiao";
String nextContext = "/cloudcrawlweb";
String nextContextName = "cloudcrawlweb";
String decodedRequestURI = request.getDecodedRequestURI();
// Judge context
if (decodedRequestURI.contains(currentContext)) {
// Replace current context to new context
org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest();
String newPathStr = coyoteRequest.decodedURI().getString().replace(currentContextName, nextContextName); // Don't have query string
MessageBytes contextPath = MessageBytes.newInstance();
contextPath.setString(nextContext);
request.getMappingData().contextPath = contextPath;
// Rewrite request URI
MessageBytes newPath = MessageBytes.newInstance();
newPath.setString(newPathStr);
coyoteRequest.requestURI().duplicate(newPath);
coyoteRequest.decodedURI().duplicate(newPath);
coyoteRequest.getURLDecoder().convert(newPath, false);
coyoteRequest.unparsedURI().duplicate(newPath);
// Get request suffix URI
MessageBytes path = MessageBytes.newInstance();
path.setString(newPathStr.substring(nextContext.length()));
request.getMappingData().requestPath = path;
request.getMappingData().wrapperPath = path;
// Get Context
Host host = request.getHost();
Context context = (Context)host.findChild(nextContext);
request.getMappingData().context = context;
request.setContext(context);
// Get wrapper
String wrapperName = context.findServletMapping(path.getString());
request.setWrapper((Wrapper) context.findChild(wrapperName));
// Get next valve
getNext().invoke(request, response);
} else {
getNext().invoke(request, response);
}
}
}
Server.xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
...
<Service name="Catalina">
...
<Engine defaultHost="localhost" name="Catalina">
...
<Host appBase="webapps" autoDeploy="true" name="localhost"
unpackWARs="true">
...
<Valve className="com.mobiscloud.ProxyValve" />
</Host>
</Engine>
</Service>
</Server>

最后
以上就是小巧墨镜为你收集整理的Tomcat实现动态context切换的全部内容,希望文章能够帮你解决Tomcat实现动态context切换所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复