Tomcat实现动态context切换

来源:互联网 发布:android ble 大数据 编辑:程序博客网 时间:2024/05/16 05:40


需求:

希望通过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 ="?";@Overridepublic 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 contextif (decodedRequestURI.contains(currentContext)) {// Replace current context to new contextorg.apache.coyote.Request coyoteRequest = request.getCoyoteRequest();String newPathStr = coyoteRequest.decodedURI().getString().replace(currentContextName, nextContextName); // Don't have query stringMessageBytes contextPath = MessageBytes.newInstance();contextPath.setString(nextContext);request.getMappingData().contextPath = contextPath;// Rewrite request URIMessageBytes 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 URIMessageBytes path = MessageBytes.newInstance();path.setString(newPathStr.substring(nextContext.length()));request.getMappingData().requestPath = path;request.getMappingData().wrapperPath = path;// Get ContextHost 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 valvegetNext().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>


 


原创粉丝点击