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然后实现方法即可!