🐈

Spring Framework MVC

2023/11/20に公開

Request Process Workflow

  • OriginalFilterChain
  • AdditinalFiltterChain
  • FrameworkServlet
  • DispatcherServlet

Application Context

Root Application Context

  • このコンテキストは、アプリケーション全体に共通のBean(@Service, @Repositoryなど)を含む
  • 通常ContextLoaderListenerによって作成される
    • web.xmlファイルまたはJavaベースの設定(@Configurationクラス)で定義されるContextLoaderListenerは、アプリケーション起動時にルートコンテキストを初期化

Servlet Application Context

  • このコンテキストは、特定のServletに関連付けられたBean(Controller, Resolver, HandlerMappingなど)を含む
  • 通常DispatcherServletによって作成される
    • DispatcherServletは、その独自のアプリケーションコンテキストを持ち、ルートコンテキストを親として使用

spring di bean get
spring application context loader

Component一覧

ContextLoaderListener

  • Web Application用のApplicationContextを生成するために、ContextLoaderListenerをServletに登録
  • ContextLoaderListener classを登録する場合、Bean定義が必要

DispatcherServlet

  • Spring MVCのフロントコントローラを利用するためにDispatcherServlet classをServletContextに登録
Interface Description
HandlerExceptionResolver 例外ハンドリングを行うためのinterface
LocalResolver, LocaleContextResolver clientのLocale や Timezone を解決するためのinterface
ThemeResolver clientのtheme(UI)を解決するためのinterface
FlashMapManager FlashMapと呼ばれるobjectを管理するためのinterface
RequestToViewNameTranslator HandlerがView名やViewを返却しなかったときに適用するview名を決定するためのinterface
HandlerInterceptor Handlerの実行前後に行う共通処理を実装するためのinterface
MultipartResolver multipart requestを扱うためのinterface

HandlerMapping

  • HanlderMapping interfaceは、requestに対応するHandlerを選択する役割を担う
    • 実装クラス: RequestMappingHandlerMapping
      • @RequestMappingに定義されている設定情報をもとに実行するhandlerを選択

HandlerAdapter

HandlerAdaptor interfaceは、controllerのmethodを呼び出す

Interface Description
HandlerMethodArgumentResolver controllerのmethod引数に渡す値を解決するためのinterface
HandlerMethodReturnValueHandler controllerのmethodから返却された値をhandlingされるためのinterface

ViewResolver

ViewResolver interfaceは、controllerから返却されたView名を名を元に使用するView Interfaceの実装classを解決する役割を担う

Interface Description
InternalResourceViewResolver template engineとしてJSPを利用する際に使用するclass
BeanNameViewResolver Spring DIコンテナからView Objectを取得する際にに使用するclass

Spring MVC Flow

  1. DispatcherServletクラスはクライアントからのRequestを受け付ける
  2. DispatcherServletクラスはHandlerMapping InterfaceのgetHandler() を呼び出し、処理を実行するControllerを取得
  3. DispatcherServletクラスはHandlerAdaptor interfaceのhandle()を呼び出し、Controller classのメソッドを呼び出し依頼
  4. HandlerAdaptor Interfaceの実装クラスはController classに実装されているmethodを呼び出し、処理実行
  5. DispatcherServletクラスはViewResolver interfaceのresolveViewName()を呼び出し、Viewを取得
  6. DispatcherServletクラスはView Interfaceの実装クラスは、template engineを利用してレンダリングするデータを生成
  7. DispatcherServletクラスはresponseを返却

spring mvc process flow

REST API with Spring MVC

  1. DispatcherServlet classは、clientからのrequestを受け付ける
  2. DispatcherServlet classは、HandlerMapping interfaceのgetHandler()を呼び出し、request処理を行うcontroller objectを取得する
  3. DispatcherServlet classはHandlerAdapter interfaceのhandle()を呼び出し、controller object呼び出しを依頼
  4. HandlerAdaptor Interfaceの実装クラスはHttpMessageConverterのmethodを呼び出し、request bodyのデータをリソースクラスのobjectへ変換する
  5. HandlerAdaptor Interfaceの実装クラスはcontroller objectに実装されているmethodを呼び出し、リクエストを処理する
  6. HandlerAdaptor Interfaceの実装クラスはHttpMessageConverterのmethodを呼び出し、controller objectをresponse bodyへ書き込む
  7. DispatcherServletクラスはclientへresponseを返却する

rest api with spring mvc

Servletコンテナ設定

  • HiddenHttpMethodFileterの適用
    • REST APIを利用する場合、PUT, PATCH, DELETEなども利用する
    • clientとの物理的な通信はPOSTメソッドを利用するが、_method=putというrequest paramを送ることで、servletコンテナ内でPUT methodでアクセスしたものとして扱われる

HttpMessageConverterの設定例

Class name Description Library要否
ByteArrayHttpMessageConverter body(任意のmediatype) <-> bytearray変換用class NO
StringHttpMessageConverter body(txt形式のmediatype) <-> string 変換用class NO
ResourceHttpMessageConverter body(任意のmediatype) <-> org.springframework.core.io.Resource 変換用class NO
AllEncompassingFormatHttpMessageConverter body(form or multipart形式 のmediatype) <-> org.springframework.util.MultiValueMap 変換用class NO
MappingJackson2HttpMessageConverter FasterXML Jackson Databind を利用した変換用class YES
GsonHttpMessageConverter Google Gson を利用した変換用class YES
MappingJackson2XmlHttpMessageConverter FasterXML Jackson XML Databind を利用した変換用class YES

どのHttpMessageConverterが利用されるかは、body部分のMediaTypeと変換対象のJava classの種類に依存する.

@Configuration
public class WebMvcConfig extends WebMvcConfigurationAdaptor {
    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        return new Jackson2ObjectMapperBuilder.json().indentOutput(true).build();
    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(0, mappingJackson2HttpMessageConverter());
    }
}

Discussion