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