spring mvcソース(二)MultiAction Controller処理プロセス


spring mvcはコントローラの入り口を提供します.
 
public interface Controller {

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

}
 
 
 
必要に応じて異なる実装のControllerを提供します.今日は最も一般的なMultiAction Controllerと言います.一つのcontrollerの中で複数の方法が複数の要求に対応します.
 
1まずMultiAction Controllerの後継関係を見てみます.
 
public class MultiActionController extends AbstractController implements LastModified {}
 MultiAction ControllerはAbstractControllerを引き継いだ.
 
 
public abstract class AbstractController extends WebContentGenerator implements Controller {}
 AbstractControllerがControllerを実現しました.
 
 
2処理要求
   Controller処理要求はhandleRequest()方法を呼び出すべきで、Multi Action Controller類には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()の方法は完全な方法ではなく、要求を具体的に処理する方法はhandlerequest Internal()はサブクラスで実現します.だから、MultiAction Controllerでhandlequest Internalを探します.
	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);
		}
	}
 上記の方法の論理:methodNameResoloverを使用して、対応する方法名を要求し、方法を呼び出し、方法の具体的な実現は以下の通りである.
	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は一つの要求しか処理できません.MultiAction Controllerは複数を実現できます.つまり、handleRequest Internal()が具体的に異なる実現をするからです.私たちが自分のcontrollerを実現するには、Multi Action Controllerを引き継いで方法を実現すればいいです.