springmvc_第一天基础知识

本文深入剖析了SpringMVC框架的工作原理,从组件介绍到执行流程,详细解释了前端控制器、处理器映射器、适配器及视图解析器的作用。并通过入门案例,展示了如何配置与使用这些组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.springmvc框架

   1.1什么是springmvc

springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。

springmvc是一个基于mvc的web框架。

   1.2mvc在b/s系统下的应用

mvc是一个设计模式,

  1.3springmvc框架

第一步:发起请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求HandlerMapping查找Handler

             可以根据xml配置、注解进行查找。

第三步:处理器映射器HandlderMapping向前端控制器返回Handler

第四步:前端控制器调用处理器适配器去执行Handler

第五步:处理器适配器去执行Handler

第六步:Handler执行完给适配器返回ModelAndView

第步七:处理器适配器向前端控制器返回ModelAndView

             ModelAndView是springmvc框架的一个底层对象,包含了Model和View.

第八步:前端控制器请求视图解析器区进行视图解析。

            根据逻辑视图名解析成真正的视图(jsp)

第九步:视图解析器向前端控制器返回View

第十步:前端控制器进行视图渲染 

             视图渲染将模型数据(在ModelAndView对象中)填充到request域

第十一步:前端控制器向对象响应结果

 

组件:

1、前端控制器:DispatcherServlet

作用接收请求,响应结果,相当于转发器,中央处理器。

有了DispatcherServlet就减少勒其他组件之间的耦合性

2.处理器映射器HandlerMapping

作用:根据请求的url查找Handler,Handler需要程序员开发。

3.处理器适配器HandlerAdapter

作用:按照特定规则(HandlerAdapter)去执行Handler

注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以区正确执行Handler.

4.视图解析器View resolver

作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)

5.视图View(需要程序员开发jsp)

View是一个接口,实现支持步同的view类型(jsp、freemarker、pdf.....)

2.入门程序

  2.1环境准备

  2.2需求

以案例作为驱动。

springmvc和mybatis使用一个案列(商品订单管理)

 功能需求:商品的列表查询

2.3配置前端控制器

2.4配置处理器适配器

在classpath下的springmvc.xml中配置处理器映射器

通过查看源代码:

此适配器能执行实现Controller接口的Handler.  

2.5开发Handler

需要实现controller接口,才能由"org.springframework.web.servllet.mvc.SimpleController"适配器执行。

2.6视图编写

2.7配置Handler

将编写Handler在spring容器加载。

2.8配置处理器映射器

在classpath下的springmvc.xml中配置处理器映射器。

2.9配置视图解析器

需要配置解析jsp的视图解析器。


3.非注解的处理器映射器和适配器

3.1非注解处理器映射器:

org.springframework.web.servlet.handler.BeanNameUrlHandllerMapping

另一个映射器:

org.spring framework.web.servlet.handler.SimpleUrlHandlerMapping

多个映射器可以并存,前端控制器判断url能让那个映射器处理就让那个映射器处理.

3.2非注解的适配器

org.springframework.web.servllet.mvc.SimpleControllerAdapter

要求编写的Handler实现Controller接口。

org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter

要求编写的Handler实现HttpRequestHandler接口。

4.DispatcherSerlvet.properties

前端控制器从上边的文件中加载处理映射器、适配器、试图解析器等组件,如果不在spring.xml中配置,使用默认加载的。

5.注解的处理器映射器和适配器

在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping注解映射器。
在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器。
在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter注解适配器。
在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter注解适配器
5.1配置注解映射器和适配器

	<!-- 配置注解Handler -->
<!--	<bean class="cn.itcast.ssm.controller.ItemController1"></bean>-->
	<!-- 当应用中有多个handler时,可以使用组件扫描所有Handler -->
	<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
	
	<!-- 注解映射器 -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
	<!-- 注解适配器 -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
	
	<!--使用mvc:annotation-driven代替上面的注解映射器和注解适配器 
		mvc:annotation-driven默认加载了很多参数绑定方法,
	 -->
<!--	<mvc:annotation-driven/>-->
	
	<!-- 配置视图解析器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 配置视图解析器的前缀和后缀 -->
		<property name="prefix" value="/WEB-INF/jsp/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>

5.2开发注解Handler

使用注解的映射器和注解的适配器.(注解的适配器和映射器必须配对使用),

6.源码分析

通过前端控制器源码分析springMVC的执行过程

第一步:前端接收器接收请求

调用doDispatch

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		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;
 
 
				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest, false);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}
 
 
				// Determine handler adapter for the current request.
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
 
 
				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						String requestUri = urlPathHelper.getRequestUri(request);
						logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
 
 
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
 
 
				try {
					// Actually invoke the handler.
					mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				}
				finally {
					if (asyncManager.isConcurrentHandlingStarted()) {
						return;
					}
				}
 
 
				applyDefaultViewName(request, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Error err) {
			triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				return;
			}
			// Clean up any resources used by a multipart request.
			if (multipartRequestParsed) {
				cleanupMultipart(processedRequest);
			}
		}
	}

第二步:前端控制器调用处理器映射器查找Handler

在doDiapatch()方法中调用了DispatcherServlet类的getHandler方法

HandlerExecutionChain mappedHandler = null;
......
mappedHandler = getHandler(processedRequest, false);

其中getHandler方法:

@Deprecated
	protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
		return getHandler(request);
	}
 
 
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		for (HandlerMapping hm : this.handlerMappings) {
			if (logger.isTraceEnabled()) {
				logger.trace(
						"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
			}
			HandlerExecutionChain handler = hm.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
		return null;
	}

说明映射器根据request当中的URL,找到了Handler,最终返回一个执行器的链(HandlerExecutionChain)。这个链里面有Handler。

第三步:调用处理器适配器执行Handler,得到执行结果ModelAndView

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

第四步:视图渲染,将model数据填充到request域

视图解析,得到view

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

调用view的渲染方法,将模型数据填充到request域

渲染方法

view.render(mv.getModelInternal(), request, response);

调用view的渲染方法,将model数据填充到request域

protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
		//遍历model里面的数据,填充到request域
		for (Map.Entry<String, Object> entry : model.entrySet()) {
			String modelName = entry.getKey();
			Object modelValue = entry.getValue();
			if (modelValue != null) {
				request.setAttribute(modelName, modelValue);
				if (logger.isDebugEnabled()) {
					logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +
							"] to request in view with name '" + getBeanName() + "'");
				}
			}
			else {
				request.removeAttribute(modelName);
				if (logger.isDebugEnabled()) {
					logger.debug("Removed model object '" + modelName +
							"' from request in view with name '" + getBeanName() + "'");
				}
			}
		}
	}

7入门程序小结

通过入门程序理解springmvc前端控制器、处理器映射器、处理器适配器、视图解析器用法。

前端控制器配置器:

  第一种:*.action,访问.action结尾,由DispatcherServlet进行解析

 第二种:/,所有访问地址都由DispatcherServlet进行解析,对静态文件的解析需要配置不让DispatcherServlet进行解析

处理器映射器:

非注解处理器映射器(了解)

注解的处理器映射器(掌握)

     对标记又@Controller类忠标记又@RequestMapping的方法进行映射。在@RequestMapping里面定义映射的url。实用注解的映射器不用再xml中配置url和Handler的映射关系。

处理器适配器:

非注解处理器适配器(了解)

注解的处理器映射器(掌握)

   注解处理器适配器和注解的处理器映射器是配对使用的。

<!-- 注解的映射器 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

<!-- 注解的适配器 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

以上代码可以用以下代码代替,实际开发使用下者。 

<mvc:annotation-driven></mvc:annotation-driven>

参考博客:

https://blog.youkuaiyun.com/nuoWei_SenLin/article/details/53698834

https://blog.youkuaiyun.com/h3243212/article/details/50834272

https://blog.youkuaiyun.com/acmman/article/details/46980497

https://blog.youkuaiyun.com/nuoWei_SenLin/article/details/53698834

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值