zoukankan      html  css  js  c++  java
  • spring mvc 原理

    1.RequestMappingHandlerMapping

     1.继承了InitializingBean 加载所有的 Controller.class 和  RequestMapping.class

    2. WebMvcAutoConfiguration   初始化时加载interception

     3.根据url 获取在RequestMappingHandlerMapping获取handlerMethod,并包装成HandlerExecutionChain,并将RequestMappingHandlerMapping中的intercepters加入到 HandlerExecutionChain

    加入规则如下

    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
            HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                    (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
    
            String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
            for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
                if (interceptor instanceof MappedInterceptor) {
                    MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                    if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                        chain.addInterceptor(mappedInterceptor.getInterceptor());
                    }
                }
                else {
                    chain.addInterceptor(interceptor);
                }
            }
            return chain;
        }

    4.使用 handlerMethod 获取handlerAdapter 

    4.1  RequestMappingHandlerAdapter (初始化时,初始化adviceCache,和参数解析器)

    @Override
        public void afterPropertiesSet() {
            // Do this first, it may add ResponseBody advice beans
            initControllerAdviceCache();
    
            if (this.argumentResolvers == null) {
                List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
                this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
            }
            if (this.initBinderArgumentResolvers == null) {
                List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
                this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
            }
            if (this.returnValueHandlers == null) {
                List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
                this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
            }
        }
    
        private void initControllerAdviceCache() {
            if (getApplicationContext() == null) {
                return;
            }
    
            List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
            AnnotationAwareOrderComparator.sort(adviceBeans);
    
            List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();
    
            for (ControllerAdviceBean adviceBean : adviceBeans) {
                Class<?> beanType = adviceBean.getBeanType();
                if (beanType == null) {
                    throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
                }
                Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
                if (!attrMethods.isEmpty()) {
                    this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
                }
                Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
                if (!binderMethods.isEmpty()) {
                    this.initBinderAdviceCache.put(adviceBean, binderMethods);
                }
                if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
                    requestResponseBodyAdviceBeans.add(adviceBean);
                }
            }
    
            if (!requestResponseBodyAdviceBeans.isEmpty()) {
                this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);
            }
    
            if (logger.isDebugEnabled()) {
                int modelSize = this.modelAttributeAdviceCache.size();
                int binderSize = this.initBinderAdviceCache.size();
                int reqCount = getBodyAdviceCount(RequestBodyAdvice.class);
                int resCount = getBodyAdviceCount(ResponseBodyAdvice.class);
                if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) {
                    logger.debug("ControllerAdvice beans: none");
                }
                else {
                    logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize +
                            " @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice");
                }
            }
        }

    5.使用handlerAdapter handler方法获取ModerAndView

    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

    6.

    在当前类和ControllerAdvice 中  获取 有InitBinder.class注解的方法全部封装在一起。(InitBinder用法https://blog.csdn.net/qq_38016931/article/details/82080940

    在当前类和ControllerAdvice 中  获取 有ModelAttribute且没有RequestMapping 的注解的方法,全部封装在一起。(ModelAttribute用法https://blog.csdn.net/abc997995674/article/details/80464023

     7.将注解有ModelAttribute的方法,初始化后绑定到sessionAttributes;

    8. resolvers解析参数  

    例:RequestResponseBodyMethodProcessor 

    8.1 1.使用 binder和 messageConverters 转化 json或xml,或其他的为对象。

    8.2 valid 校验参数

    9.参数解析正常 则调用代理对象

    9.1使用代理对象的拦截器拦截方法,或初始化一些对象

    9.2具体的方法调用

    10.参数解析异常抛出异常

    10.1

    0 = {DefaultErrorAttributes@15395}
    1 = {HandlerExceptionResolverComposite@12775}

    10.2  HandlerExceptionResolverComposite里又含有三个异常

    0 = {ExceptionHandlerExceptionResolver@15442}  --使用 @ExceptionHandler 解决异常   有些这里抛出的异常会导致 发起/error

    1 = {ResponseStatusExceptionResolver@15443}  --解决@ResponseStatus或instanceof ResponseStatusException

    2 = {DefaultHandlerExceptionResolver@12774} 针对于一些异常,重新发起(/error)请求

    @Override
        @Nullable
        protected ModelAndView doResolveException(
                HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
    
            try {
                if (ex instanceof HttpRequestMethodNotSupportedException) {
                    return handleHttpRequestMethodNotSupported(
                            (HttpRequestMethodNotSupportedException) ex, request, response, handler);
                }
                else if (ex instanceof HttpMediaTypeNotSupportedException) {
                    return handleHttpMediaTypeNotSupported(
                            (HttpMediaTypeNotSupportedException) ex, request, response, handler);
                }
                else if (ex instanceof HttpMediaTypeNotAcceptableException) {
                    return handleHttpMediaTypeNotAcceptable(
                            (HttpMediaTypeNotAcceptableException) ex, request, response, handler);
                }
                else if (ex instanceof MissingPathVariableException) {
                    return handleMissingPathVariable(
                            (MissingPathVariableException) ex, request, response, handler);
                }
                else if (ex instanceof MissingServletRequestParameterException) {
                    return handleMissingServletRequestParameter(
                            (MissingServletRequestParameterException) ex, request, response, handler);
                }
                else if (ex instanceof ServletRequestBindingException) {
                    return handleServletRequestBindingException(
                            (ServletRequestBindingException) ex, request, response, handler);
                }
                else if (ex instanceof ConversionNotSupportedException) {
                    return handleConversionNotSupported(
                            (ConversionNotSupportedException) ex, request, response, handler);
                }
                else if (ex instanceof TypeMismatchException) {
                    return handleTypeMismatch(
                            (TypeMismatchException) ex, request, response, handler);
                }
                else if (ex instanceof HttpMessageNotReadableException) {
                    return handleHttpMessageNotReadable(
                            (HttpMessageNotReadableException) ex, request, response, handler);
                }
                else if (ex instanceof HttpMessageNotWritableException) {
                    return handleHttpMessageNotWritable(
                            (HttpMessageNotWritableException) ex, request, response, handler);
                }
                else if (ex instanceof MethodArgumentNotValidException) {
                    return handleMethodArgumentNotValidException(
                            (MethodArgumentNotValidException) ex, request, response, handler);
                }
                else if (ex instanceof MissingServletRequestPartException) {
                    return handleMissingServletRequestPartException(
                            (MissingServletRequestPartException) ex, request, response, handler);
                }
                else if (ex instanceof BindException) {
                    return handleBindException((BindException) ex, request, response, handler);
                }
                else if (ex instanceof NoHandlerFoundException) {
                    return handleNoHandlerFoundException(
                            (NoHandlerFoundException) ex, request, response, handler);
                }
                else if (ex instanceof AsyncRequestTimeoutException) {
                    return handleAsyncRequestTimeoutException(
                            (AsyncRequestTimeoutException) ex, request, response, handler);
                }
            }
            catch (Exception handlerEx) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Failure while trying to resolve exception [" + ex.getClass().getName() + "]", handlerEx);
                }
            }
            return null;
        }
  • 相关阅读:
    C/C++ 获取线程入口地址模块等
    C/C++ IAT HOOK MessageBoxW
    C/C++ HOOK 全局 API
    c/c++创建静态库
    如何画Windows窗体
    WindowsPE TLS表
    WindowsPE 延迟加载导入表
    WindowsPE 资源表
    WindowsPE 重定位表
    WindowsPE 导出表
  • 原文地址:https://www.cnblogs.com/z-test/p/11550743.html
Copyright © 2011-2022 走看看