springソース—四、MVC
7786 ワード
スプリングmvcはどうやって実現しますか?なぜ私たちは方法に注釈を書くだけで、httpを通じてこのインターフェースにアクセスできますか?この二つの問題を3つの部分に分けて解いてみます. spring mvc全体の流れ HandlerMapping HandlerAdapter spring mvc全体の流れ
私達はspringを見てhttp要求を処理する過程で大体分かります.
Spring mvcの入り口がDispactch Servletです.このservletに渡してくださいと要請した後、doDisplatchを呼び出してこの要求を配布しました.主にいくつかのことをしました. multiiplet要求を処理して、ファイルのアップロードなどの要求があれば、先にDefault MultiiprtHttpServletRequest にカプセル化します.は、要求を処理するhandlerMappingからhandlerを取得し、HandlerExecution Chinを構築し、すべてのinterceptr に入る. handlerによって、すべてのHandlerAdapterからこのhanderを処理できるadapper が見つかりました.すべてのinterceptor.prehandle方法を実行する Request Mappingの注釈が書かれている方法を呼び出し、ModelAndView に戻る.すべてのinterceptor.postHandle方法を実行する 解析view レンダーは、モデルをレスポンスに変換して に戻る.すべてのinterceptor.afterCompration を実行します. cleanupumltipad 上の流れから分かるように、処理の過程では主にいくつかのキーコンポーネントが対応するロジックを完成しました.
HandlerMapping
Displatch Servletコンポーネントの一つとして、その中の一つがfieldです.
どのようなHandlerMappingがありますか?
springはどのようにすべてのHandlerMappingを調べますか?Displatch Servlet初期化時にこのフィールドを検索して初期化するものです.
もし私たちが配置を行ったら
では BenNamehandlerMapping Default AnnotationHandlerMapping このような場合にはこの3つのHandlerMappingタイプのbeanがあり、springはhanderMappingsを巡回して、request pathによって対応するhandlerを検索します.
HandlerMappingはurlからhandlerまでのマッピング関係をどう管理しますか?
HandlerMapping抽象類Abstracthandler MethodMappingの中にfieldがあります.容器の中の全てのbean を見つけました.各beanに対して中にmappingがありますか?
inithandler Methodsメソッドを呼び出した時に容器の中の全てのbeanを取り出し、ishandlerでhandlerかどうかを判断します.実は、ControllerまたはRequest Mappingの注釈があるかどうかを判断します.
HandlerAdapter
HandlerAdapterは、パラメータ解析などのDispactch Servletに対してinvokeプロセスの詳細を遮断するためである.
Displatch Servlet初期化の時にinithanderAdaptersを呼び出して、中で容器の中のすべてのhandler Adapter実現類を探して、容器の中のhanderAdapterはmvcラベルを解析する時に容器に入れます.
締め括りをつける
この文章はspringを通じて一回の要求の過程を処理して、springmvcがどのように働いているかということと、その中の二つの重要なコンポーネント、HandlerMappingとHandlerAdapterを理解しました.
: spring4.3.2
私達はspringを見てhttp要求を処理する過程で大体分かります.
Spring mvcの入り口がDispactch Servletです.このservletに渡してくださいと要請した後、doDisplatchを呼び出してこの要求を配布しました.主にいくつかのことをしました.
HandlerMapping
Displatch Servletコンポーネントの一つとして、その中の一つがfieldです.
org.springframework.web.servlet.DispatcherServlet#handlerMappings
主な役割はurlからControllerへのマッピングを維持し、urlによって対応するControllerを見つけることです.どのようなHandlerMappingがありますか?
springはどのようにすべてのHandlerMappingを調べますか?Displatch Servlet初期化時にこのフィールドを検索して初期化するものです.
// org.springframework.web.servlet.DispatcherServlet#initHandlerMappings
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
// HandlerMapping bean
Map matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}
どのようなHandlerMappingタイプのbeanが容器にありますか?私たちがRequest Mappingを使用するなら、xmlに以下の配置が必要です.
spring解析というラベルはorg.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser
このクラスの解析xmlタグは容器にRequest MappingHandlerMappingを登録します.この類はHandlerMappingから継承されます.もし私たちが配置を行ったら
このタブの使用はspring解析です.org.springframework.web.servlet.config.DefaultServletHandlerBeanDefinitionParser
解析時のspringはDefault ServletHttpRequest HandlerとSimpleUrlhandler Mappingを容器に注入します.では
HandlerMappingはurlからhandlerまでのマッピング関係をどう管理しますか?
HandlerMapping抽象類Abstracthandler MethodMappingの中にfieldがあります.
// org.springframework.web.servlet.handler.AbstractHandlerMethodMapping
private final MappingRegistry mappingRegistry = new MappingRegistry();
このクラスはurlからhandlerまでのマッピングを維持するために使われています.このクラスにはどのようなデータ構造がありますか?// org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry
// mapping map
private final Map mappingLookup = new LinkedHashMap();
// ( org.springframework.util.AntPathMatcher#isPattern) map
private final MultiValueMap urlLookup = new LinkedMultiValueMap();
// name handler
private final Map> nameLookup =
new ConcurrentHashMap>();
// cors mapping
private final Map corsLookup =
mappingを登録する過程は、上記の対応するデータ構造に、Request MappingHandlerMappingを例にとって、具体的に登録するタイミングはRequest MappingHandlerMapping beanを初期化する時で、spring容器は初期化が完了したら、容器の中のeagere initのbeanを初期化します.最後にAbstracthandler MethodMappingを呼び出します.容器の中のbeanを全部探しに来ます.inithandler Methodsメソッドを呼び出した時に容器の中の全てのbeanを取り出し、ishandlerでhandlerかどうかを判断します.実は、ControllerまたはRequest Mappingの注釈があるかどうかを判断します.
protected boolean isHandler(Class> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
種類を見つけたら、中の方法を探します.方法の検索ロジックは方法にRequest Mappingがありますか?private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
// RequestMapping
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition> condition = (element instanceof Class> ?
getCustomTypeCondition((Class>) element) : getCustomMethodCondition((Method) element));
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
対応方法を見つけたら、MappingRegistryにmappingとして登録します.public void register(T mapping, Object handler, Method method) {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
assertUniqueMethodMapping(handlerMethod, mapping);
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
}
// mapping mappingLookup
this.mappingLookup.put(mapping, handlerMethod);
List directUrls = getDirectUrls(mapping);
// ( , ) url urlLookup
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
this.registry.put(mapping, new MappingRegistration(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
urlによってhandlerを検索する時、url Look upを優先的に探して、ワイルドカードがないのがマッチングできるかどうかを見てください.直接マッチングしていないなら、mappingLook upの中から探します.HandlerAdapter
HandlerAdapterは、パラメータ解析などのDispactch Servletに対してinvokeプロセスの詳細を遮断するためである.
Displatch Servlet初期化の時にinithanderAdaptersを呼び出して、中で容器の中のすべてのhandler Adapter実現類を探して、容器の中のhanderAdapterはmvcラベルを解析する時に容器に入れます.
締め括りをつける
この文章はspringを通じて一回の要求の過程を処理して、springmvcがどのように働いているかということと、その中の二つの重要なコンポーネント、HandlerMappingとHandlerAdapterを理解しました.