Tomcat一次http请求处理,filter、servlet调用流程

tomcat组件结构图


一次http请求处理的debug调用栈


相关源码

/** StandardWrapperValve.java */
public final void invoke(Request request, Response response)
	throws IOException, ServletException {

	// Initialize local variables we may need
	boolean unavailable = false;
	Throwable throwable = null;
	// This should be a Request attribute...
	long t1=System.currentTimeMillis();
	requestCount++;
	StandardWrapper wrapper = (StandardWrapper) getContainer();
	Servlet servlet = null;
	Context context = (Context) wrapper.getParent();
	
	// Check for the application being marked unavailable
	if (!context.getState().isAvailable()) {
		response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
					   sm.getString("standardContext.isUnavailable"));
		unavailable = true;
	}

	// Check for the servlet being marked unavailable
	if (!unavailable && wrapper.isUnavailable()) {
		container.getLogger().info(sm.getString("standardWrapper.isUnavailable",
				wrapper.getName()));
		long available = wrapper.getAvailable();
		if ((available > 0L) && (available < Long.MAX_VALUE)) {
			response.setDateHeader("Retry-After", available);
			response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
					sm.getString("standardWrapper.isUnavailable",
							wrapper.getName()));
		} else if (available == Long.MAX_VALUE) {
			response.sendError(HttpServletResponse.SC_NOT_FOUND,
					sm.getString("standardWrapper.notFound",
							wrapper.getName()));
		}
		unavailable = true;
	}

	// Allocate a servlet instance to process this request
	try {
		if (!unavailable) {
			// 实例化且初始化处理请求的servlet
			servlet = wrapper.allocate();
		}
	} catch (UnavailableException e) {
		container.getLogger().error(
				sm.getString("standardWrapper.allocateException",
						wrapper.getName()), e);
		long available = wrapper.getAvailable();
		if ((available > 0L) && (available < Long.MAX_VALUE)) {
			response.setDateHeader("Retry-After", available);
			response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
					   sm.getString("standardWrapper.isUnavailable",
									wrapper.getName()));
		} else if (available == Long.MAX_VALUE) {
			response.sendError(HttpServletResponse.SC_NOT_FOUND,
					   sm.getString("standardWrapper.notFound",
									wrapper.getName()));
		}
	} catch (ServletException e) {
		container.getLogger().error(sm.getString("standardWrapper.allocateException",
						 wrapper.getName()), StandardWrapper.getRootCause(e));
		throwable = e;
		exception(request, response, e);
	} catch (Throwable e) {
		ExceptionUtils.handleThrowable(e);
		container.getLogger().error(sm.getString("standardWrapper.allocateException",
						 wrapper.getName()), e);
		throwable = e;
		exception(request, response, e);
		servlet = null;
	}

	// Identify if the request is Comet related now that the servlet has been allocated
	boolean comet = false;
	if (servlet instanceof CometProcessor && Boolean.TRUE.equals(request.getAttribute(
			Globals.COMET_SUPPORTED_ATTR))) {
		comet = true;
		request.setComet(true);
	}
	
	MessageBytes requestPathMB = request.getRequestPathMB();
	DispatcherType dispatcherType = DispatcherType.REQUEST;
	if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC; 
	request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
	request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
			requestPathMB);
	// Create the filter chain for this request
	ApplicationFilterFactory factory =
		ApplicationFilterFactory.getInstance();
	// 创建filter调用链
	ApplicationFilterChain filterChain =
		factory.createFilterChain(request, wrapper, servlet);
	
	// Reset comet flag value after creating the filter chain
	request.setComet(false);

	// Call the filter chain for this request
	// NOTE: This also calls the servlet's service() method
	try {
		if ((servlet != null) && (filterChain != null)) {
			// Swallow output if needed
			if (context.getSwallowOutput()) {
				try {
					SystemLogHandler.startCapture();
					if (request.isAsyncDispatching()) {
						request.getAsyncContextInternal().doInternalDispatch();
					} else if (comet) {
						filterChain.doFilterEvent(request.getEvent());
						request.setComet(true);
					} else {
						filterChain.doFilter(request.getRequest(), 
								response.getResponse());
					}
				} finally {
					String log = SystemLogHandler.stopCapture();
					if (log != null && log.length() > 0) {
						context.getLogger().info(log);
					}
				}
			} else {
				if (request.isAsyncDispatching()) {
					request.getAsyncContextInternal().doInternalDispatch();
				} else if (comet) {
					request.setComet(true);
					filterChain.doFilterEvent(request.getEvent());
				} else {
					// 处理http请求,调用filter链,且完成servlet调用
					filterChain.doFilter
						(request.getRequest(), response.getResponse());
				}
			}

		}
	} catch (ClientAbortException e) {
		throwable = e;
		exception(request, response, e);
	} catch (IOException e) {
		container.getLogger().error(sm.getString(
				"standardWrapper.serviceException", wrapper.getName(),
				context.getName()), e);
		throwable = e;
		exception(request, response, e);
	} catch (UnavailableException e) {
		container.getLogger().error(sm.getString(
				"standardWrapper.serviceException", wrapper.getName(),
				context.getName()), e);
		//            throwable = e;
		//            exception(request, response, e);
		wrapper.unavailable(e);
		long available = wrapper.getAvailable();
		if ((available > 0L) && (available < Long.MAX_VALUE)) {
			response.setDateHeader("Retry-After", available);
			response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
					   sm.getString("standardWrapper.isUnavailable",
									wrapper.getName()));
		} else if (available == Long.MAX_VALUE) {
			response.sendError(HttpServletResponse.SC_NOT_FOUND,
						sm.getString("standardWrapper.notFound",
									wrapper.getName()));
		}
		// Do not save exception in 'throwable', because we
		// do not want to do exception(request, response, e) processing
	} catch (ServletException e) {
		Throwable rootCause = StandardWrapper.getRootCause(e);
		if (!(rootCause instanceof ClientAbortException)) {
			container.getLogger().error(sm.getString(
					"standardWrapper.serviceExceptionRoot",
					wrapper.getName(), context.getName(), e.getMessage()),
					rootCause);
		}
		throwable = e;
		exception(request, response, e);
	} catch (Throwable e) {
		ExceptionUtils.handleThrowable(e);
		container.getLogger().error(sm.getString(
				"standardWrapper.serviceException", wrapper.getName(),
				context.getName()), e);
		throwable = e;
		exception(request, response, e);
	}

	// Release the filter chain (if any) for this request
	if (filterChain != null) {
		if (request.isComet()) {
			// If this is a Comet request, then the same chain will be used for the
			// processing of all subsequent events.
			filterChain.reuse();
		} else {
			filterChain.release();
		}
	}

	// Deallocate the allocated servlet instance
	try {
		if (servlet != null) {
			wrapper.deallocate(servlet);
		}
	} catch (Throwable e) {
		ExceptionUtils.handleThrowable(e);
		container.getLogger().error(sm.getString("standardWrapper.deallocateException",
						 wrapper.getName()), e);
		if (throwable == null) {
			throwable = e;
			exception(request, response, e);
		}
	}

	// If this servlet has been marked permanently unavailable,
	// unload it and release this instance
	try {
		if ((servlet != null) &&
			(wrapper.getAvailable() == Long.MAX_VALUE)) {
			wrapper.unload();
		}
	} catch (Throwable e) {
		ExceptionUtils.handleThrowable(e);
		container.getLogger().error(sm.getString("standardWrapper.unloadException",
						 wrapper.getName()), e);
		if (throwable == null) {
			throwable = e;
			exception(request, response, e);
		}
	}
	long t2=System.currentTimeMillis();

	long time=t2-t1;
	processingTime += time;
	if( time > maxTime) maxTime=time;
	if( time < minTime) minTime=time;

}

/** StandardWrapper.java */
public Servlet allocate() throws ServletException {

	// If we are currently unloading this servlet, throw an exception
	if (unloading) {
		throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
	}

	boolean newInstance = false;
	
	// If not SingleThreadedModel, return the same instance every time
	if (!singleThreadModel) {
		// Load and initialize our instance if necessary
		if (instance == null || !instanceInitialized) {
			synchronized (this) {
				if (instance == null) {
					try {
						if (log.isDebugEnabled()) {
							log.debug("Allocating non-STM instance");
						}

						// Note: We don't know if the Servlet implements
						// SingleThreadModel until we have loaded it.
						instance = loadServlet();
						newInstance = true;
						if (!singleThreadModel) {
							// For non-STM, increment here to prevent a race
							// condition with unload. Bug 43683, test case
							// #3
							countAllocated.incrementAndGet();
						}
					} catch (ServletException e) {
						throw e;
					} catch (Throwable e) {
						ExceptionUtils.handleThrowable(e);
						throw new ServletException(sm.getString("standardWrapper.allocate"), e);
					}
				}
				if (!instanceInitialized) {
					initServlet(instance);
				}
			}
		}

		if (singleThreadModel) {
			if (newInstance) {
				// Have to do this outside of the sync above to prevent a
				// possible deadlock
				synchronized (instancePool) {
					instancePool.push(instance);
					nInstances++;
				}
			}
		} else {
			if (log.isTraceEnabled()) {
				log.trace("  Returning non-STM instance");
			}
			// For new instances, count will have been incremented at the
			// time of creation
			if (!newInstance) {
				countAllocated.incrementAndGet();
			}
			return instance;
		}
	}

	synchronized (instancePool) {
		while (countAllocated.get() >= nInstances) {
			// Allocate a new instance if possible, or else wait
			if (nInstances < maxInstances) {
				try {
					instancePool.push(loadServlet());
					nInstances++;
				} catch (ServletException e) {
					throw e;
				} catch (Throwable e) {
					ExceptionUtils.handleThrowable(e);
					throw new ServletException(sm.getString("standardWrapper.allocate"), e);
				}
			} else {
				try {
					instancePool.wait();
				} catch (InterruptedException e) {
					// Ignore
				}
			}
		}
		if (log.isTraceEnabled()) {
			log.trace("  Returning allocated STM instance");
		}
		countAllocated.incrementAndGet();
		return instancePool.pop();
	}
}

// 实例化且初始化servlet
public synchronized Servlet loadServlet() throws ServletException {

	if (unloading) {
		throw new ServletException(
				sm.getString("standardWrapper.unloading", getName()));
	}

	// Nothing to do if we already have an instance or an instance pool
	if (!singleThreadModel && (instance != null))
		return instance;

	PrintStream out = System.out;
	if (swallowOutput) {
		SystemLogHandler.startCapture();
	}

	Servlet servlet;
	try {
		long t1=System.currentTimeMillis();
		// Complain if no servlet class has been specified
		if (servletClass == null) {
			unavailable(null);
			throw new ServletException
				(sm.getString("standardWrapper.notClass", getName()));
		}

		InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();
		try {
			// 实例化servlet
			servlet = (Servlet) instanceManager.newInstance(servletClass);
		} catch (ClassCastException e) {
			unavailable(null);
			// Restore the context ClassLoader
			throw new ServletException
				(sm.getString("standardWrapper.notServlet", servletClass), e);
		} catch (Throwable e) {
			e = ExceptionUtils.unwrapInvocationTargetException(e);
			ExceptionUtils.handleThrowable(e);
			unavailable(null);

			// Added extra log statement for Bugzilla 36630:
			// http://bz.apache.org/bugzilla/show_bug.cgi?id=36630
			if(log.isDebugEnabled()) {
				log.debug(sm.getString("standardWrapper.instantiate", servletClass), e);
			}

			// Restore the context ClassLoader
			throw new ServletException
				(sm.getString("standardWrapper.instantiate", servletClass), e);
		}

		if (multipartConfigElement == null) {
			MultipartConfig annotation =
					servlet.getClass().getAnnotation(MultipartConfig.class);
			if (annotation != null) {
				multipartConfigElement =
						new MultipartConfigElement(annotation);
			}
		}

		processServletSecurityAnnotation(servlet.getClass());

		// Special handling for ContainerServlet instances
		if ((servlet instanceof ContainerServlet) &&
				(isContainerProvidedServlet(servletClass) ||
						((Context) getParent()).getPrivileged() )) {
			((ContainerServlet) servlet).setWrapper(this);
		}

		classLoadTime=(int) (System.currentTimeMillis() -t1);

		if (servlet instanceof SingleThreadModel) {
			if (instancePool == null) {
				instancePool = new Stack<Servlet>();
			}
			singleThreadModel = true;
		}

		// 初始化servlet
		initServlet(servlet);

		fireContainerEvent("load", this);

		loadTime=System.currentTimeMillis() -t1;
	} finally {
		if (swallowOutput) {
			String log = SystemLogHandler.stopCapture();
			if (log != null && log.length() > 0) {
				if (getServletContext() != null) {
					getServletContext().log(log);
				} else {
					out.println(log);
				}
			}
		}
	}
	return servlet;

}


/** ApplicationFilterFactory.java */
// 创建filter调用链
public ApplicationFilterChain createFilterChain
	(ServletRequest request, Wrapper wrapper, Servlet servlet) {

	// get the dispatcher type
	DispatcherType dispatcher = null; 
	if (request.getAttribute(Globals.DISPATCHER_TYPE_ATTR) != null) {
		dispatcher = (DispatcherType) request.getAttribute(
				Globals.DISPATCHER_TYPE_ATTR);
	}
	String requestPath = null;
	Object attribute = request.getAttribute(
			Globals.DISPATCHER_REQUEST_PATH_ATTR);
	
	if (attribute != null){
		requestPath = attribute.toString();
	}
	
	// If there is no servlet to execute, return null
	if (servlet == null)
		return (null);

	boolean comet = false;
	
	// Create and initialize a filter chain object
	ApplicationFilterChain filterChain = null;
	if (request instanceof Request) {
		Request req = (Request) request;
		comet = req.isComet();
		if (Globals.IS_SECURITY_ENABLED) {
			// Security: Do not recycle
			filterChain = new ApplicationFilterChain();
			if (comet) {
				req.setFilterChain(filterChain);
			}
		} else {
			filterChain = (ApplicationFilterChain) req.getFilterChain();
			if (filterChain == null) {
				filterChain = new ApplicationFilterChain();
				req.setFilterChain(filterChain);
			}
		}
	} else {
		// Request dispatcher in use
		filterChain = new ApplicationFilterChain();
	}
	// filterChain关联servlet
	filterChain.setServlet(servlet);

	filterChain.setSupport
		(((StandardWrapper)wrapper).getInstanceSupport());

	// Acquire the filter mappings for this Context
	StandardContext context = (StandardContext) wrapper.getParent();
	// 获取context配置所有的filter
	FilterMap filterMaps[] = context.findFilterMaps();

	// If there are no filter mappings, we are done
	if ((filterMaps == null) || (filterMaps.length == 0))
		return (filterChain);

	// Acquire the information we will need to match filter mappings
	String servletName = wrapper.getName();

	// Add the relevant path-mapped filters to this filter chain
	for (int i = 0; i < filterMaps.length; i++) {
		// 转发类型匹配
		if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
			continue;
		}
		// URL匹配
		if (!matchFiltersURL(filterMaps[i], requestPath))
			continue;
		ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
			context.findFilterConfig(filterMaps[i].getFilterName());
		if (filterConfig == null) {
			// FIXME - log configuration problem
			continue;
		}
		boolean isCometFilter = false;
		if (comet) {
			try {
				isCometFilter = filterConfig.getFilter() instanceof CometFilter;
			} catch (Exception e) {
				// Note: The try catch is there because getFilter has a lot of 
				// declared exceptions. However, the filter is allocated much
				// earlier
				Throwable t = ExceptionUtils.unwrapInvocationTargetException(e);
				ExceptionUtils.handleThrowable(t);
			}
			if (isCometFilter) {
				filterChain.addFilter(filterConfig);
			}
		} else {
			filterChain.addFilter(filterConfig);
		}
	}

	// Add filters that match on servlet name second
	for (int i = 0; i < filterMaps.length; i++) {
		if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
			continue;
		}
		// Servlet名称匹配
		if (!matchFiltersServlet(filterMaps[i], servletName))
			continue;
		ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
			context.findFilterConfig(filterMaps[i].getFilterName());
		if (filterConfig == null) {
			// FIXME - log configuration problem
			continue;
		}
		boolean isCometFilter = false;
		if (comet) {
			try {
				isCometFilter = filterConfig.getFilter() instanceof CometFilter;
			} catch (Exception e) {
				// Note: The try catch is there because getFilter has a lot of 
				// declared exceptions. However, the filter is allocated much
				// earlier
			}
			if (isCometFilter) {
				filterChain.addFilter(filterConfig);
			}
		} else {
			filterChain.addFilter(filterConfig);
		}
	}

	// Return the completed filter chain
	return (filterChain);

}

/** ApplicationFilterChain.java */
public void doFilter(ServletRequest request, ServletResponse response)
	throws IOException, ServletException {

	if( Globals.IS_SECURITY_ENABLED ) {
		final ServletRequest req = request;
		final ServletResponse res = response;
		try {
			java.security.AccessController.doPrivileged(
				new java.security.PrivilegedExceptionAction<Void>() {
					@Override
					public Void run() 
						throws ServletException, IOException {
						internalDoFilter(req,res);
						return null;
					}
				}
			);
		} catch( PrivilegedActionException pe) {
			Exception e = pe.getException();
			if (e instanceof ServletException)
				throw (ServletException) e;
			else if (e instanceof IOException)
				throw (IOException) e;
			else if (e instanceof RuntimeException)
				throw (RuntimeException) e;
			else
				throw new ServletException(e.getMessage(), e);
		}
	} else {
		//实际调用filter链
		internalDoFilter(request,response);
	}
}

private void internalDoFilter(ServletRequest request, 
							  ServletResponse response)
	throws IOException, ServletException {

	// Call the next filter if there is one
	if (pos < n) {
		ApplicationFilterConfig filterConfig = filters[pos++];
		Filter filter = null;
		try {
			filter = filterConfig.getFilter();
			support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT,
									  filter, request, response);
			
			if (request.isAsyncSupported() && "false".equalsIgnoreCase(
					filterConfig.getFilterDef().getAsyncSupported())) {
				request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
						Boolean.FALSE);
			}
			if( Globals.IS_SECURITY_ENABLED ) {
				final ServletRequest req = request;
				final ServletResponse res = response;
				Principal principal = 
					((HttpServletRequest) req).getUserPrincipal();

				Object[] args = new Object[]{req, res, this};
				SecurityUtil.doAsPrivilege
					("doFilter", filter, classType, args, principal);
				
			} else {
				// 顺序调用filter链
				filter.doFilter(request, response, this);
			}

			support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
									  filter, request, response);
		} catch (IOException e) {
			if (filter != null)
				support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
										  filter, request, response, e);
			throw e;
		} catch (ServletException e) {
			if (filter != null)
				support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
										  filter, request, response, e);
			throw e;
		} catch (RuntimeException e) {
			if (filter != null)
				support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
										  filter, request, response, e);
			throw e;
		} catch (Throwable e) {
			e = ExceptionUtils.unwrapInvocationTargetException(e);
			ExceptionUtils.handleThrowable(e);
			if (filter != null)
				support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
										  filter, request, response, e);
			throw new ServletException
			  (sm.getString("filterChain.filter"), e);
		}
		return;
	}

	// We fell off the end of the chain -- call the servlet instance
	try {
		if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
			lastServicedRequest.set(request);
			lastServicedResponse.set(response);
		}

		support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT,
								  servlet, request, response);
		if (request.isAsyncSupported()
				&& !support.getWrapper().isAsyncSupported()) {
			request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
					Boolean.FALSE);
		}
		// Use potentially wrapped request from this point
		if ((request instanceof HttpServletRequest) &&
			(response instanceof HttpServletResponse)) {
				
			if( Globals.IS_SECURITY_ENABLED ) {
				final ServletRequest req = request;
				final ServletResponse res = response;
				Principal principal = 
					((HttpServletRequest) req).getUserPrincipal();
				Object[] args = new Object[]{req, res};
				SecurityUtil.doAsPrivilege("service",
										   servlet,
										   classTypeUsedInService, 
										   args,
										   principal);   
			} else {  
				// filter链调用完成后,完成servlet调用
				servlet.service(request, response);
			}
		} else {
			servlet.service(request, response);
		}
		support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
								  servlet, request, response);
	} catch (IOException e) {
		support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
								  servlet, request, response, e);
		throw e;
	} catch (ServletException e) {
		support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
								  servlet, request, response, e);
		throw e;
	} catch (RuntimeException e) {
		support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
								  servlet, request, response, e);
		throw e;
	} catch (Throwable e) {
		ExceptionUtils.handleThrowable(e);
		support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
								  servlet, request, response, e);
		throw new ServletException
		  (sm.getString("filterChain.servlet"), e);
	} finally {
		if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
			lastServicedRequest.set(null);
			lastServicedResponse.set(null);
		}
	}

}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我解释一下您的问题。您想在filter实现异步servlet代理功能,并且请求使用异步HttpClient。我假设您想要在servlet容器实现这个功能,比如Tomcat或Jetty。 首先,您需要编写一个Filter来拦截请求并将请求转发给HttpClient。在这个Filter,您需要使用Servlet 3.0规范的异步特性来实现异步处理请求和响应。这可以通过以下步骤完成: 1. 在Filter调用ServletRequest的startAsync方法,以启动异步处理。 2. 在新的异步上下文,创建一个异步HttpClient,并使用它来发出异步请求。 3. 一旦HttpClient完成请求并收到响应,您可以将响应写回给原始的ServletResponse,并调用AsyncContext的complete方法以结束异步处理。 下面是一个简单的示例代码,展示了如何在Filter实现异步servlet代理功能: ``` public class AsyncProxyFilter implements Filter { private final CloseableHttpAsyncClient httpClient = HttpAsyncClients.createDefault(); @Override public void init(FilterConfig filterConfig) throws ServletException { httpClient.start(); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { final HttpServletRequest httpRequest = (HttpServletRequest) request; final HttpServletResponse httpResponse = (HttpServletResponse) response; // Start asynchronous processing final AsyncContext asyncContext = httpRequest.startAsync(); asyncContext.setTimeout(0); // Disable the timeout // Create an asynchronous HttpClient request final HttpHost target = new HttpHost(httpRequest.getServerName(), httpRequest.getServerPort()); final HttpRequest proxyRequest = new BasicHttpRequest(httpRequest.getMethod(), httpRequest.getRequestURI()); final Header[] headers = ServletUtils.getHeaders(httpRequest); for (Header header : headers) { proxyRequest.addHeader(header); } final HttpAsyncRequestProducer requestProducer = HttpAsyncMethods.create(target, proxyRequest); final AsyncHttpClientHandler responseHandler = new AsyncHttpClientHandler(asyncContext, httpResponse); // Execute the asynchronous request httpClient.execute(requestProducer, responseHandler); } @Override public void destroy() { try { httpClient.close(); } catch (IOException e) { // Ignore } } private static class AsyncHttpClientHandler implements AsyncHandler<Void> { private final AsyncContext asyncContext; private final HttpServletResponse httpResponse; private HttpResponse proxyResponse; public AsyncHttpClientHandler(AsyncContext asyncContext, HttpServletResponse httpResponse) { this.asyncContext = asyncContext; this.httpResponse = httpResponse; } @Override public void completed(Void result) { // Write the proxy response back to the original response ServletUtils.copyHeaders(proxyResponse, httpResponse); ServletUtils.copyBody(proxyResponse, httpResponse); // Complete the asynchronous processing asyncContext.complete(); } @Override public void failed(Exception ex) { // Handle the error asyncContext.complete(); } @Override public void cancelled() { // Handle the cancellation asyncContext.complete(); } @Override public void onStatusReceived(HttpResponse response) throws IOException { this.proxyResponse = response; httpResponse.setStatus(response.getStatusLine().getStatusCode()); } @Override public void onHeadersReceived(HttpResponse response) throws IOException { this.proxyResponse = response; ServletUtils.copyHeaders(response, httpResponse); } @Override public void onBodyReceived(InputStream content) throws IOException { ServletUtils.copyBody(content, httpResponse.getOutputStream()); } } } ``` 在上面的示例代码,我们创建了一个AsyncProxyFilter类,它实现了Filter接口。在init方法,我们创建了一个CloseableHttpAsyncClient并启动它。在doFilter方法,我们首先启动异步处理,然后使用异步HttpClient发送异步请求。我们在AsyncHttpClientHandler处理异步HttpClient的响应,并将响应写回原始的ServletResponse。最后,我们在completed、failed和cancelled方法处理异步处理的结束。 这就是在Filter实现异步servlet代理功能的基本步骤。当然,这只是一个简单的示例代码,您可能需要根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值