Spring-webmvc模块分析

Spring-webmvc模块主要用于在遵守servlet规范的前提下将Spring框架集成到java web 应用

springmvc启动过程:容器加载ContextLoaderListenr,调用contextInitialized()(内部调用initWebApplicationContext方法)

ContextLoaderListener:Spring的ApplicationContext加载类,继承ContextLoader类,实现ServletContextListener接口

核心方法:

1.initApplicationContext

2.createWebApplicationContext

备注:默认使用的是XmlWebApplicationContext

3.configureAndRefreshWebApplicationContext

DispatcherServlet:http请求应答核心处理器,集成了springmvc框架的各个组件

请求应答流程如下:

核心方法:

1.doService

2.doDispatch

UML类图结构如下:

HttpServletBean:  负责将init-param参数值保存到当前类型的同名属性

FrameworkServlet:Spring Web框架的基本servlet,根据web.xml或者注解的context配置参数集成Spring应用程序上下文

核心方法:

1.initServletBean()

2.initWebApplicationContext()

   WebApplicationContext查找顺序:

  1.配置已设置的webapplicationContext:主要配置ServletContext和ServletConfig,添加ContextRefreshListener等

  2.查找webapplicationContext:根据ContextAttribute属性查找对应的webapplicationContext

  3.创建webapplicationContext:  根据ContextClass和ContextConfigLocation属性创建webapplicationContext

HandlerMapping:负责定义HttpServletRequest与handler之间映射的接口

UML类图结构如下:

AbstractHandlerMapping:HandlerMapping接口的抽象实现,包含默认handler和handler interceptors

初始化过程:

核心方法:

1.getHandler

备注:用于根据HttpSerlvetRequest获取对应的HandlerExecutionChain。在涉及IO的编程模型中,大量使用装饰器模式

AbstractHandlerMethodMapping:定义了HttpServletRequest与HandlerMethod之间的映射,每个HandlerMethod只对应唯一一个HandlerMapping

初始化过程:

1.initHandlerMethods

2.registerHandlerMethod

运行过程:

1.getHandlerInternal

2.lookupHandlerMethod

RequestMappingInfoHandlerMapping:使用RequestMappingInfo类型定义HttpServletRequest与handlerMethod之间的映射

核心方法:

1.handleMatch

RequestMappingInfo:RequestCondition类型的聚合类,主要功能是合并其他的RequestMappingInfo对象的各个RequestCondition,根据HttpServletRequest获取满足条件的RequestMappingInfo,在同一个HttpServletRequest的基础上与其他的requestInfo对象进行比较

         

核心方法:

1.combine

2.getMatchingCondition

3.compareTo

类型描述核心逻辑
PatternsRequestCondition判断HttpServletRequest的url是否满足特定的格式

getMatchingCondition

RequestMethodsRequestCondition根据HttpServletRequest的Http请求方法(GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE)筛选出对应的RequestMethodsRequestCondition

getMatchingCondition

ParamsRequestCondition根据HttpServletRequest的Parameter或ParameterMap的内容进行过滤

内部类:ParamExpression

getMatchingCondition

 

RequestMappingHandlerMapping:在Controller注解应用的类上使用RequestMapping注解(应用于类型和方法)创建RequestMappingInfo实例

1.getMappingForMethod

备注:根据RequestMapping注解的内容生成RequestMappingInfo对象,并根据HttpServletRequest和pattern进行匹配

HandlerExceptionResolver:处理handler映射和运行时抛出异常的接口。具体实现可以登记到ApplicationContext对象中

UML类结构图如下:

AbstractHandlerExceptionResolver:HandlerExceptionResolver接口的抽象实现

核心方法

1.resolveException

 

AbstractHandlerMethodExceptionResolver:支持处理HandlerMethod类型抛出异常的抽象类型

核心方法:

1.doResolveException

ExceptionHandlerExceptionResolver:待分析

HandlerAdapter:处理HttpServletRequest请求的handler基本接口,DispatcherServlet直接使用HandlerAdapter接口类型处理请求

UML结构图如下:

具体实现如下:

AbstractHandlerMethodAdapter:支持HandleMethod类型handler的基类

RequestMappingHandlerAdapter:读取RequestMapping定义来帮助HandlerMethod方法实现和处理其方法参数和返回类型

可以通过setCustomArgumentResolvers和setCustomReturnValueHandlers添加对自定义参数和返回值类型的支持

初始化过程如下:

1.initControllerAdviceCache:查找applicationContext中注解为ControllerAdvice的bean,并把bean和包含注解为RequestMapping或者ModelAttribute的方法,包含注解为InitBinder的方法添加到局部列表

2.初始化argumentResolvers

3.初始化initBinderArgumentResolvers

初始化内容同上

4.初始化returnValueHandlers

请求处理过程如下:

invokeHandlerMethod处理过程:

总体分为3个阶段:

1.设置ServletInvocableHandlerMethod对象

2.ServletInvocableHandlerMethod对象invocableMethod调用invokeAndHandle方法

3.返回ModelAndView对象

InvokeForRequest具体实现:

1.获取方法参数值:遍历方法参数列表的过程中,argumentResolvers将HttpServletRequest内容转化为方法参数值

(argumentResolvers.supportsParameter()=>argumentResolvers.resolveArgument())

2.调用bridgeMethod: getBridgedMethod().invoke(getBean(), args)

returnValueHandlers.handleReturnValue具体实现:

1.选择处理器:遍历returnValueHandlers,查找到对应handler(handler.supportsReturnType())

2.处理器实际处理返回值

HandlerExecutionChain:处理程序执行链,由Handler对象和HandlerInteceptor列表组成

核心方法描述代码片段
applyPreHandle

调用拦截器链的preHandle方法:如果preHandle方法返回false,

调用triggerAfterCompletion方法并且请求不再进行处理

 

applyPostHandle

调用拦截器链的postHandle方法 
triggerAfterCompletion调用拦截器链的afterCompletion方法 

HandlerMethodArgumentResolver:将HttpServletRequest请求的内容绑定对应方法参数值

UML类图如下:

接口方法:

1.boolean supportsParameter(MethodParameter parameter):   是否该parameter参数由当前解析类支持。

2.Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,

 NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception: 从MethodParameter对象解析出参数值

AbstractMessageConverterMethodArgumentResolver:通过HttpMessageConverter读取HttpServetRequest body 来绑定HandlerMapping 方法请求参数

属性:

protected final List<HttpMessageConverter<?>> messageConverters; //核心对象

protected final List<MediaType> allSupportedMediaTypes;

private final RequestResponseBodyAdviceChain advice;  //责任链模式

构造函数:

/**
	 * Constructor with converters and {@code Request~} and {@code ResponseBodyAdvice}.
	 * @since 4.2
	 */
	public AbstractMessageConverterMethodArgumentResolver(List<HttpMessageConverter<?>> converters,
			@Nullable List<Object> requestResponseBodyAdvice) {

		Assert.notEmpty(converters, "'messageConverters' must not be empty");
		this.messageConverters = converters;
		this.allSupportedMediaTypes = getAllSupportedMediaTypes(converters);
		this.advice = new RequestResponseBodyAdviceChain(requestResponseBodyAdvice);
	}

备注:allSupportedMediaTypes从messageConverter.getAllSupportedMediaTypes聚合得来

核心方法:

1.readWithMessageConverters

/**
	 * Create the method argument value of the expected parameter type by reading
	 * from the given HttpInputMessage.
	 * @param <T> the expected type of the argument value to be created
	 * @param inputMessage the HTTP input message representing the current request
	 * @param parameter the method parameter descriptor
	 * @param targetType the target type, not necessarily the same as the method
	 * parameter type, e.g. for {@code HttpEntity<String>}.
	 * @return the created method argument value
	 * @throws IOException if the reading from the request fails
	 * @throws HttpMediaTypeNotSupportedException if no suitable message converter is found
	 */
	@SuppressWarnings("unchecked")
	@Nullable
	protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {

		MediaType contentType;
		boolean noContentType = false;
		try {
			contentType = inputMessage.getHeaders().getContentType();
		}
		catch (InvalidMediaTypeException ex) {
			throw new HttpMediaTypeNotSupportedException(ex.getMessage());
		}
		if (contentType == null) {
			noContentType = true;
			contentType = MediaType.APPLICATION_OCTET_STREAM;
		}

		Class<?> contextClass = parameter.getContainingClass();
		Class<T> targetClass = (targetType instanceof Class ? (Class<T>) targetType : null);
		if (targetClass == null) {
			ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
			targetClass = (Class<T>) resolvableType.resolve();
		}

		HttpMethod httpMethod = (inputMessage instanceof HttpRequest ? ((HttpRequest) inputMessage).getMethod() : null);
		Object body = NO_VALUE;

		EmptyBodyCheckingHttpInputMessage message;
		try {
			message = new EmptyBodyCheckingHttpInputMessage(inputMessage);

			for (HttpMessageConverter<?> converter : this.messageConverters) {
				Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
				GenericHttpMessageConverter<?> genericConverter =
						(converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
				if (genericConverter != null ? genericConverter.canRead(targetType, contextClass, contentType) :
						(targetClass != null && converter.canRead(targetClass, contentType))) {
					if (logger.isDebugEnabled()) {
						logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
					}
					if (message.hasBody()) {
						HttpInputMessage msgToUse =
								getAdvice().beforeBodyRead(message, parameter, targetType, converterType);
						body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) :
								((HttpMessageConverter<T>) converter).read(targetClass, msgToUse));
						body = getAdvice().afterBodyRead(body, msgToUse, parameter, targetType, converterType);
					}
					else {
						body = getAdvice().handleEmptyBody(null, message, parameter, targetType, converterType);
					}
					break;
				}
			}
		}
		catch (IOException ex) {
			throw new HttpMessageNotReadableException("I/O error while reading input message", ex);
		}

		if (body == NO_VALUE) {
			if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod) ||
					(noContentType && !message.hasBody())) {
				return null;
			}
			throw new HttpMediaTypeNotSupportedException(contentType, this.allSupportedMediaTypes);
		}

		return body;
	}

  流程如下:

AbstractNamedValueMethodArgumentResolver:用于从命名值解析方法参数的抽象基类。请求参数,请求标头和路径变量是已命名的示例值。 每个可以有一个名称,一个必需的标志和一个默认值

核心方法:

1.resolveArgument

执行过程:

Annotation-based Resolver:继承自AbstractNamedValueMethodArgumentResolver,通过注解的方式将HttpServletRequest里面的内容转化为对应对象

UML结构图如下:

ModelAttributeMethodProcessor:解析注解为ModelAttribute的方法参数和方法返回值

                                     

Type-based Resolver:将HttpServletRequest请求内容绑定到HandleMethod方法的请求参数类型

ViewResolver:Web应用程序的所有MVC框架都提供了一种展示视图的途径。Spring提供了视图解析器(ViewResolver):使您能够在浏览器中灵活地渲染模型,而不用考虑一个特定的视图技术。Spring的视图解析器能够方便,灵活地使用JSP页面,Velocity模板和XSLT技术输出返回结果

View类UML结构图:

View类列表:

AbstractView:提供对静态属性的支持,以供视图使用:可以通过各种方法来指定静态属性。静态属性可以合并到具体的model对象中,在视图中展示出来

核心方法:

1.render

2.createMergedOutputModel

备注:创建一个包含静态属性,路径变量,model和RequestContext的组合model(动态值优先于静态属性)

renderMergedOutputModel: 实际展示抽象方法:所有的具体视图必须重写这个方法

第一步准备请求:在JSP视图中,意味着将模型对象保存为请求属性。

第二步负责视图的实际呈现,例如包括通过RequestDispatcher的include或者forward方法访问JSP页面

FreeMarkerView:使用FreeMarker模板引擎的视图

核心方法:

1.initServletContext

2.doRender

InternalResourceView:用于访问Web应用程序的JSP或其他资源的包装器视图。url属性指定了Web的资源,能够传递到RequestDispatcher的forward或者include方法中

核心方法:

1.renderMergeOutputModel

ViewResolver类UML结构图如下:

ContentNegotiatingViewResolver:优先级最高,根据文件名或者HTTP头部信息的Accept字段委托给具体的视图解析类进行视图解析(contentNegotiationManager负责具体的映射工作)

核心方法:

1.Bean初始化

2.resolveViewName

                   

UrlBasedViewResolver:  ViewResolver接口的简单实现.允许直接通过请求URL映射到View名称

核心方法:

1.initApplicationContext

检验viewClass属性是否为空

2.createView

备注:添加redirect和forward特殊处理逻辑

3.loadView

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值