16.springmvc工作原理分析

springmvc 如何做URL映射关系

1.SpringIOC容器加载时开始遍历所有的bean对象 判断 bean对象 类上是否有加上

@Controller注解,如果类上有加该注解的话 则该类就是为我们控制类;

2.在容器初始化时会建立所有url和controller的对应关系,利用java反射机制,查找该控制类中所有方法,判断方法上是否有加上@RequestMapping注解,如果有加上该注解的话 保存到Map<url,controller>中(key=/mayiktDemo01,MayiktController#mayiktDemo01())

3.定义DispatcherServlet 接受客户端所有请求 从该map集合中查找到具体的控制类 方法 调用(java反射机制调用)

springmvc 请求映射原理

SpringMVC 前端控制器 DispatcherServlet

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    // Handler 责任链
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;
    
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
    try {
        ModelAndView mv = null;
        Exception dispatchException = null;
        
        try {
            // 判断客户端发送的请求是否是上传文件
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);
            
            //根据请求路径  获取对应的Handler责任链(处理器)
            mappedHandler = getHandler(processedRequest);// 如果没有查找到的情况下 则返回404
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }
            //根据对应的Handler 获取对应的适配器

          HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
           //根据适配器执行请求方法
           //mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

责任链设计模式 具体流程

springmvc 拦截器

拦截器A

拦截器B

拦截器C

public String demo01() {

}

1、用户向服务器发送请求,请求会先达到 SpringMVC 前端控制器 DispatcherServlet ;

2、DispatcherServlet 根据该 URI,调用 HandlerMapping 获得该 Handler 配置的所有相关的对象(包括 Handler 对象以及 Handler 对象对应的拦截器),最后以 HandlerExecutionChain 执行链对象的形式返回

3、DispatcherServlet 根据获得的 Handler,获取对应的 HandlerAdapter;

5、获取到 HandlerAdapter,将开始执行拦截器的 preHandler(…)方法;

6、提取 Request 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller)方法,处理请求,在填充 Handler 的入参过程中,根据你的配置,Spring 将帮你做一些额外的工作:

HttpMessageConveter:将请求消息(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的类型信息

数据转换:对请求消息进行数据转换。如 String 转换成 Integer、Double 等

数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等

数据验证:验证数据的有效性(长度、格式等),验证结果存储到 BindingResult 或 Error 中

7、Handler 方法执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象。

8、开始执行拦截器的 postHandle(…)方

9、根据返回的 ModelAndView(此时会判断是否存在异常:如果存在异常,则执行 HandlerExceptionResolver 进行异常处理)选择一个适合的 ViewResolver 进行视图解析,根据 Model 和 View,来渲染视图

10、渲染视图完毕执行拦截器的 afterCompletion(…)方法

11、将渲染结果返回给客户端

HandlerMappings

1.实现Controller方式所使用的适配器

2.实现HTTP请求处理器的适配器:HttpRequestHandlerAdapter

3.注解方式(@Controller)的处理器适配器:

4.实现servlet方式的适配器:

HandlerMapping 负责解析请求URL

HandlerMapping的分类

SpingMVC中的HandlerMapping负责解析请求URL,对应到Handler进行处理(这里的Handler一般为Controller里的一个方法method,也可以为servlet或者Controller等)

1.RequestMappingHandlerMapping 会将Controller中配置@RequestMapping注解的方法做映射存储 url 具体 控制类和方法(map=key=url ,控制类和方法)

2.BeanNameUrlHandlerMapping 根据bean标签的名称找到对应的Controller类

 <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
 <bean id="/baanNameMayikt" class="com.mayikt.controller.BeanNameController" />    

3.RouterFunctionMapping 函数式接口

img

1.RequestMappingHandlerMapping 会将Controller中配置@RequestMapping注解的方法做映射存储 走AbstractHandlerMethodMapping#

protected void initHandlerMethods() {
		for (String beanName : getCandidateBeanNames()) {
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
				processCandidateBean(beanName);
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}

2.org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping

获取注解映射url 存放在this.handlerMap.put(urlPath, resolvedHandler);

protected void detectHandlers() throws BeansException {
		ApplicationContext applicationContext = obtainApplicationContext();
		String[] beanNames = (this.detectHandlersInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
				applicationContext.getBeanNamesForType(Object.class));

		// Take any bean name that we can determine URLs for.
		for (String beanName : beanNames) {
			String[] urls = determineUrlsForHandler(beanName);
			if (!ObjectUtils.isEmpty(urls)) {
				// URL paths found: Let's consider it a handler.
				registerHandler(urls, beanName);
			}
		}

		if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) {
			logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName());
		}
	}

如果我们是使用@Component(“/implController”) 自定义url映射 走的

BeanNameUrlHandlerMapping

org.springframework.web.servlet.handler.AbstractUrlHandlerMapping#lookupHandler this.handlerMap.get(urlPath); 查找对应的 控制类

img

如果使用@RequestMapping()

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal 查找具体url

img

因为springmvc支持多种url映射方式 ,每一种url映射的方式 都有自己独立的

handlerMapping 处理的方式。

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

查找具体HandlerMapping

根据url请求地址查找具体的HandlerMapping

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
            // 循环查找对应的handlerMapping
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

注册HandlerMappings

	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
        // 初始化HandlerMappings
		initHandlerMappings(context);
        // 初始化HandlerAdapters
		initHandlerAdapters(context);
        
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}

从DispatcherServlet.properties中获取HandlerMapping

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
	org.springframework.web.servlet.function.support.RouterFunctionMapping

使用反射初始化HandlerMapping 同时注册到handlerMappings 集合中。

springmvc适配器简单介绍

1.实现Controller接口方式所使用的适配器:SimpleControllerHandlerAdapter

2.实现HTTP请求处理器的适配器:HttpRequestHandlerAdapter

3.注解方式(@Controller)的处理器适配器:RequestMappingHandlerAdapter

4.实现servlet方式的适配器:SimpleServletHandlerAdapter

5.自己开发者新增适配器

方式一:@Controller/@RequestMapping

方式二:实现HttpRequestHandler接口

方式三:实现Controller接口

适配器模式就是把一个类的接口替换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

public static void invok(Controller controller) {
      // 判断请求url 如果是 使用Controller 该方式查找具体方法执行
        if (controller instanceof AnnotationController) {
            AnnotationController annotationController = (AnnotationController) controller;
            annotationController.requestMapping();
            return;
        }
        if (controller instanceof ImplController) {
            ImplController implController = (ImplController) controller;
            implController.handleRequest();
        }
        if (controller instanceof RequestHandlerController) {
            RequestHandlerController requestHandlerController = (RequestHandlerController) controller;
            requestHandlerController.requestHandler();
        }

        
    }

    public static void main(String[] args) {
        AdapterInvok.invok(new ImplController());
    }
}

springmvc适配器模式源码解读

获取HandlerAdapter源码解读

// 根据handler获取具体的HandlerAdapter

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

//根据 handler 获取对应的HandlerAdapter

	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
                //判断该handler是否是为该HandlerAdapter 是则返回
                //该HandlerAdapter
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

使用实现controller接口的方式 SimpleControllerHandlerAdapter

执行我们的 handleRequest

@Component("/implController")
public class MayiktImplController implements Controller {
     public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        PrintWriter writer = response.getWriter();
        writer.print("mayikt--MayiktImplController");
        writer.close();
        return null;
    }
public class SimpleControllerHandlerAdapter implements HandlerAdapter {

	@Override
	public boolean supports(Object handler) {
		return (handler instanceof Controller);
	}
执行// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
请求的方法
直接利用 多态机制 访问handleRequest(HttpServletRequest reques  也就是没有使用反射调用我们的方法。

使用到我们的RequestMapping(“/mayiktDemo02”)

使用org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports

	public final boolean supports(Object handler) {
		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
	}

得到bean和方法使用反射机制 调用 请求方法

	protected Object doInvoke(Object... args) throws Exception {
		ReflectionUtils.makeAccessible(getBridgedMethod());
		try {
			return getBridgedMethod().invoke(getBean(), args);

初始化HandlerAdapter源码解读

// 初始化HandlerAdapters

	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
        // 初始化HandlerAdapters
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}

private void initHandlerAdapters(ApplicationContext context) {
		this.handlerAdapters = null;

		if (this.detectAllHandlerAdapters) {
			// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
			Map<String, HandlerAdapter> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerAdapters = new ArrayList<>(matchingBeans.values());
				// We keep HandlerAdapters in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerAdapters);
			}
		}
		else {
			try {
				HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
				this.handlerAdapters = Collections.singletonList(ha);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerAdapter later.
			}
		}

		// Ensure we have at least some HandlerAdapters, by registering
		// default HandlerAdapters if no other adapters are found.
		if (this.handlerAdapters == null) {
			this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
			if (logger.isTraceEnabled()) {
				logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
						"': using default strategies from DispatcherServlet.properties");
			}
		}
	}

使用反射机制初始化适配器模式

	// Ensure we have at least some HandlerAdapters, by registering
		// default HandlerAdapters if no other adapters are found.
		if (this.handlerAdapters == null) {
			this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
			if (logger.isTraceEnabled()) {
				logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
						"': using default strategies from DispatcherServlet.properties");
			}
		}

读取配置DispatcherServlet.properties 文件img

使用java反射机制初始化适配器类

protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
		String key = strategyInterface.getName();
        //读取配置DispatcherServlet.properties 文件
		String value = defaultStrategies.getProperty(key);
		if (value != null) {
			String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
			List<T> strategies = new ArrayList<>(classNames.length);
			for (String className : classNames) {
				try {
                    //使用java反射机制初始化适配器类
					Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
					Object strategy = createDefaultStrategy(context, clazz);
					strategies.add((T) strategy);
				}
				catch (ClassNotFoundException ex) {
					throw new BeanInitializationException(
							"Could not find DispatcherServlet's default strategy class [" + className +
							"] for interface [" + key + "]", ex);
				}
				catch (LinkageError err) {
					throw new BeanInitializationException(
							"Unresolvable class definition for DispatcherServlet's default strategy class [" +
							className + "] for interface [" + key + "]", err);
				}
			}
			return strategies;
		}
		else {
			return new LinkedList<>();
		}
	}

根据Handler查找对应的适配器源码解读

根据Handler查找对应的适配器源码解读

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
                //根据Handler查找对应的适配器源码解读
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

img

循环遍历每个适配器 判断该 handler 查找匹配对应的HandlerAdapter

1.如果是RequestMappingHandlerAdapter 则执行AbstractHandlerMethodAdapter#supports方法

注解方式(@Controller)的处理器适配器:RequestMappingHandlerAdapter

判断 return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));

2.HttpRequestHandlerAdapter#supports方法

	public boolean supports(Object handler) {
		return (handler instanceof HttpRequestHandler);
	}

3.SimpleControllerHandlerAdapter#supports方法

	@Override
	public boolean supports(Object handler) {
		return (handler instanceof Controller);
	}

4.SimpleServletHandlerAdapter#supports方法

	public boolean supports(Object handler) {
		return (handler instanceof Servlet);
	}

执行对应的ha.handle方法

执行调用对应的ha.handle方法

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

执行对应适配器的handle方法

img

RequestMappingHandlerAdapter

如果是RequestMappingHandlerAdapter 则执行AbstractHandlerMethodAdapter#handle方法 使用java反射机制调用控制层方法

protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// //使用java反射机制调用 方法
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav;
	}
	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
        // 拼接url上参数
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Arguments: " + Arrays.toString(args));
		}
        //使用反射调用方法
		return doInvoke(args);
	}
      protected Object doInvoke(Object... args) throws Exception {
		ReflectionUtils.makeAccessible(getBridgedMethod());
		try {
            //使用反射调用方法
			return getBridgedMethod().invoke(getBean(), args);
		}

如果是RequestMappingHandlerAdapter 则执行

img

RequestMappingHandlerAdapter

如果是实现了controller接口,会执行SimpleControllerHandlerAdapter

#handle方法 ,执行到 controller接口对应的实现类

	@Override
	@Nullable
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		return ((Controller) handler).handleRequest(request, response);
	}

img

MayiktImplController#handleRequest

package com.mayikt.controller;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;

/**
* @author songchuanfu
* @qq 1802284273
*/
@Component("/implController")
public class MayiktImplController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        PrintWriter writer = response.getWriter();
        writer.print("mayikt--MayiktImplController");
        writer.close();
        return null;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌陌龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值