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