2013-08-14 3 views
0

При изучении структуры Spring я замечаю в книге Весна в действии, автор не использует тип возвращаемого метода в контроллерах ModelandView. Автор объявляет методы контроллера как возвращаемый тип String, а предложение возврата в методе возвращает строку, такую ​​как return "/views/theview";Метод обработчика контроллера поддерживается типами возвращаемых данных

Может кто-то уточнить внутренние различия в том, как это работает?

+0

Это не дубликат. Я хочу, чтобы внутренние детали реализации касались различий в (старой) весне 2.0 и (новой) весне 3.0 способам делать то же самое. –

+0

Я дал ответ на 3.2+. Ларри З отправил ответ на версию до 3.2. То, что вы также можете сделать, это сделать метод Controller, поместить в него точку останова, затем отладить. Посмотрите на трассировку стека, когда вы находитесь внутри, чтобы увидеть связанные классы. Затем вы можете вернуться из своего метода, чтобы посмотреть, куда он идет, чтобы обработать возвращаемый тип. –

ответ

3

Вот углубленный взгляд.

Spring предлагает класс DispatcherServlet, который, как правило, обрабатывает все ваши запросы. Он делает это в своем doDispatch(HttpServletRequest request, HttpServletResponse response) методы

// Actually invoke the handler. 
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 

где mv окончательный ModelAndView объект, ha является оболочкой для вашего метода контроллера с аннотацией @RequestMapping.

Это, как правило, проходят через стек вызовов метода в конечном итоге на ServletInvocableHandlerMethod.invokeAndHandle

at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod 
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal 
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle 
at org.springframework.web.servlet.DispatcherServlet.doDispatch 

Глядя на источник

public final void invokeAndHandle(ServletWebRequest webRequest, 
       ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { 

    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); 

    setResponseStatus(webRequest); 

    if (returnValue == null) { 
     if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) { 
      mavContainer.setRequestHandled(true); 
      return; 
     } 
    } else if (StringUtils.hasText(this.responseReason)) { 
     mavContainer.setRequestHandled(true); 
     return; 
    } 

    mavContainer.setRequestHandled(false); 

    try { 
     this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest); 
    } 
    catch (Exception ex) { 
     if (logger.isTraceEnabled()) { 
      logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex); 
     } 
     throw ex; 
    } 
} 

returnValue является объектом, возвращенный методом @RequestMapping. Он проходит через

this.returnValueHandlers.handleReturnValue 

где весна определяющей HandlerMethodReturnValueHandler для обработки этого объекта.

public void handleReturnValue(
     Object returnValue, MethodParameter returnType, 
     ModelAndViewContainer mavContainer, NativeWebRequest webRequest) 
     throws Exception { 

    HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType); // returns the appropriate handler 
    Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]"); 
    handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); 
} 

getReturnValueHandler(returnType); возвращает соответствующий обработчик. HandlerMethodReturnValueHandler - это интерфейс с методом supportsReturnType, который возвращает true, если обработчик поддерживает этот тип (String, View, ResponseEntity, etc. (look for supported return types)). Таким образом, метод возвращает первый обработчик, который находит, который поддерживает этот тип и запускает его.

Весна, при инициализации, регистрирует целый набор реализаций HandlerMethodReturnValueHandler. В основном все known implementing classes in its javadoc.

Например, если вы вернете строку, Spring будет использовать ViewNameMethodReturnValueHandler для обработки ответа.

Теперь, тип возвращаемого типа зависит от вас. Если вы хотите вернуть Model, чтобы вы могли использовать атрибуты запроса в своем представлении jsp, вы можете либо передать Spring пример Model, либо самостоятельно создать объект Model и передать его в ModelAndView, который будет вам возвращен. В большинстве случаев это вопрос стиля.

0

Функциональности мудра нет никакой разницы, как они эквивалентны:

@RequestMapping(..) 
public String requestMapping1(Model model){ 
    model.addAttribute("attr1", attr1); 
    return "viewName"; 
} 

@RequestMapping(..) 
public ModelAndView requestMapping2(){ 
    ModelAndView modelAndView = new ModelAndView("viewName"); 
    modelAndView.addObject("attr1", attr1); 
    return modelAndView; 
} 

Однако предпочтительный подход является бывшим, и что является причиной, почему автор не использовал последний в книге образцах.

0

В весеннем исходном коде вы можете увидеть этот класс org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter. В методе public ModelAndView getModelAndView(...) вы можете получить, как sping-mvc генерирует объект ModelAandView.

if (returnValue instanceof HttpEntity) { // returnValue is returned Value of Handler method 
      handleHttpEntityResponse((HttpEntity<?>) returnValue, webRequest); 
      return null; 
     } 
     else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) { 
      handleResponseBody(returnValue, webRequest); 
      return null; 
     } 
     else if (returnValue instanceof ModelAndView) { 
      ModelAndView mav = (ModelAndView) returnValue; 
      mav.getModelMap().mergeAttributes(implicitModel); 
      return mav; 
     } 
     else if (returnValue instanceof Model) { 
      return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap()); 
     } 
     else if (returnValue instanceof View) { 
      return new ModelAndView((View) returnValue).addAllObjects(implicitModel); 
     } 
     else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) { 
      addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel); 
      return new ModelAndView().addAllObjects(implicitModel); 
     } 
     else if (returnValue instanceof Map) { 
      return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map) returnValue); 
     } 
     else if (returnValue instanceof String) { // String is here, return new ModelAndView 
      return new ModelAndView((String) returnValue).addAllObjects(implicitModel); 
     } 

Таким образом, в этом методе вы можете узнать, что весна-MVC может обрабатывать множество возвращаемых типов метода обработчика для создания объекта ModleAndView.

+0

Обратите внимание, что этот класс устарел с 3.2 –

+0

Благодарим за внимание. Я думаю, что обновить весеннюю версию до 3.2.x –

+0

OP, похоже, хочет знать реализации с 2.0, поэтому это по-прежнему действительный ответ. –

Смежные вопросы