spring mvc 源码(二) MultiActionController 处理流程

spring mvc 提供了控制器的入口:接口Controller

public interface Controller {

	ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;

}

根据不同需要提供了不同实现的Controller,今天我们来说说最常用的MultiActionController,在一个controller里多个方法对应多个请求

1 首先来看一下MultiActionController的继承关系:

public class MultiActionController extends AbstractController implements LastModified {}

 MultiActionController继承了AbstractController

public abstract class AbstractController extends WebContentGenerator implements Controller {}

 AbstractController实现了Controller了接口

2 处理请求

   Controller处理请求应该调用handleRequest()方法,在MultiActionController类里没有handleRequest()方法的具体实现,所以会使用父类AbstractController里的handleRequest()方法,具体实现如下:

	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws Exception {

		// Delegate to WebContentGenerator for checking and preparing.
                //参数各方面的检查
		checkAndPrepare(request, response, this instanceof LastModified);

		// Execute handleRequestInternal in synchronized block if required.
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					return handleRequestInternal(request, response);
				}
			}
		}

		return handleRequestInternal(request, response);
	}

        //子类去实现如何处理请求
	protected abstract ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
	    throws Exception;

 由上面代码可知,父类AbstractController里的handleRequest()方法不是一个完整的方法,具体处理请求的方法handleRequestInternal()由子类去实现,所以我们在MultiActionController去找handleRequestInternal()方法实现:

	protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		try {
                        //使用方法名解析器从请求中获取请求访问的方法名
			String methodName = this.methodNameResolver.getHandlerMethodName(request);
                        //调用具体的方法
			return invokeNamedMethod(methodName, request, response);
		}
		catch (NoSuchRequestHandlingMethodException ex) {
			return handleNoSuchRequestHandlingMethod(ex, request, response);
		}
	}

 上面方法的逻辑:使用methodNameResolver找到请求对应的方法名,然后调用方法,调用方法的具体实现为:

	protected final ModelAndView invokeNamedMethod(
			String methodName, HttpServletRequest request, HttpServletResponse response) throws Exception {
 
                //根据具体的方法名获取到具体的方法
		Method method = this.handlerMethodMap.get(methodName);
		if (method == null) {
			throw new NoSuchRequestHandlingMethodException(methodName, getClass());
		}

                //根据方法参数个数和类型,获取方法具体需要的参数request, response, 或者session 调用处理请求的方法
		try {
			Class[] paramTypes = method.getParameterTypes();
			List<Object> params = new ArrayList<Object>(4);
			params.add(request);
			params.add(response);

			if (paramTypes.length >= 3 && paramTypes[2].equals(HttpSession.class)) {
				HttpSession session = request.getSession(false);
				if (session == null) {
					throw new HttpSessionRequiredException(
							"Pre-existing session required for handler method '" + methodName + "'");
				}
				params.add(session);
			}

			// If last parameter isn't of HttpSession type, it's a command.
			if (paramTypes.length >= 3 &&
					!paramTypes[paramTypes.length - 1].equals(HttpSession.class)) {
				Object command = newCommandObject(paramTypes[paramTypes.length - 1]);
				params.add(command);
				bind(request, command);
			}

                        //调用具体的方法
			Object returnValue = method.invoke(this.delegate, params.toArray(new Object[params.size()]));
			return massageReturnValueIfNecessary(returnValue);
		}
		catch (InvocationTargetException ex) {
			// The handler method threw an exception.
			return handleException(request, response, ex.getTargetException());
		}
		catch (Exception ex) {
			// The binding process threw an exception.
			return handleException(request, response, ex);
		}
	}

 就是通过如上这个过程spring mvc 解析请求,找到对应的处理请求的方法,然后传入参数调用对应方法,完成整个请求的处理;有的controller只能处理一个请求,MultiActionController可以实现多个,就是因为handleRequestInternal()具体实现不同导致的。我们要实现自己的controller的时候,只要继承MultiActionController然后实现方法即可!

猜你喜欢

转载自abc08010051.iteye.com/blog/1978445