springMVC详解

2018年02月28日 15:25 | 3080次浏览

一、前言

前一章节对springMVC初步讲解了,我们得知它由C-Dispatcher;M-HanlderMapping、HandlerAdapter、Handler;V-ViewResolver三部分组成;其中我们加入了一个spring的字符集拦截器CharacterEncodingFilter在我们的Web.xml里面,构成为SpringMVC。我们只有记住spring的这几个大结构,即使其中的某个部分换了组件,依然能够知道怎么去配置,例如struts2的整合。接下来首先讲一下映射器HandlerMapping与HandlerAdapter。

二、非注解处理器映射器与适配器

2.1 BeanNameUrlHandlerMapping与SimpleUrlHanlderMapping映射器

  2.1.1  BeanNameUrlHandlerMapping

  匹配Spring容器Bean的Name找到的Bean(程序员编写Hanlder),springmvc.xml中配置如下代码

	<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
	<!-- 2.1 BeanNameUrlHandlerMapping controller配置 -->
	<bean name="/items1" id="itemList1" class="com.spring.Controller.ItemController"/>

 2.1.2  SimpleUrlHandlerMapping

BeanNameHandlerMapping的升级版,因为它可以统一配置Controller里面对应Url

     <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
            <property name="mappings">
                <props>
                    <prop key="/simpleItems1" >simpleController1</prop>
                    <prop key="/simpleItems2" >simpleController1</prop>
                </props>
            </property>
        </bean>
<bean  id="simpleController1" class="com.ycy.controller.ItemController"/>

注意:benaname与simple两者同时配置,那么两者同时有效。

2.2 SimpleControllerHandlerAdapter与HttpRequestHandlerAdapter适配器

2.2.1 SimpleControllerHandlerAdapter

      <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">
        </bean>

要求程序编写的Handler(Controller)需要实现 Controller接口。

package
import com.ycy.model.Items;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 
 */
public class ItemController implements Controller {

    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest,
                                      javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
        //商品列表
        List<Items> itemsList = new ArrayList<Items>();

        Items items_1 = new Items();
        items_1.setName("联想笔记本");
        items_1.setPrice(6000f);
        items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
        items_1.setCreatetime(new Date());

        Items items_2 = new Items();
        items_2.setName("苹果手机");
        items_2.setPrice(5000f);
        items_2.setDetail("iphone6苹果手机!");
        items_2.setCreatetime(new Date());
        itemsList.add(items_1);
        itemsList.add(items_2);

        //创建modelAndView准备填充数据、设置视图
        ModelAndView modelAndView = new ModelAndView();
        httpServletRequest.setCharacterEncoding("utf-8");
        //填充数据
        modelAndView.addObject("itemsList", itemsList);
        //视图
        modelAndView.setViewName("order/itemsList");

        return modelAndView;
    }
}

2.2.2 

HttpRequestHandlerAdapter

要求Handler 实现 HttpRequestHandler接口

      <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
        </bean>

提醒:我用的时候需要加全路径

-

-

package 
import com.ycy.model.Items;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2015/9/17 0017.
 */
public class ItemController2 implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
        //商品列表
        List<Items> itemsList = new ArrayList<Items>();

        Items items_1 = new Items();
        items_1.setName("联想笔记本");
        items_1.setPrice(6000f);
        items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
        items_1.setCreatetime(new Date());

        Items items_2 = new Items();
        items_2.setName("苹果手机");
        items_2.setPrice(5000f);
        items_2.setDetail("iphone6苹果手机!");
        items_2.setCreatetime(new Date());
        itemsList.add(items_1);
        itemsList.add(items_2);

        //创建modelAndView准备填充数据、设置视图
        ModelAndView modelAndView = new ModelAndView();
        httpServletRequest.setCharacterEncoding("utf-8");
        httpServletRequest.setAttribute("itemsList", itemsList);
            httpServletRequest.getRequestDispatcher("pages/jsp/order/itemsList.jsp").forward(httpServletRequest,httpServletResponse);
    }

}

三、注解处理器映射器与适配器

3.1注解映射器

spring3.1版本之前加载映射器org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

spring3.1之后用org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping

也是源码解读:/org/springframework/spring-webmvc/4.2.0.RELEASE/spring-webmvc-4.2.0.RELEASE.jar!/org/springframework/web/servlet/DispatcherServlet.properties里面清楚记载了先加载谁

在springmvc.xml中配置RequestMappingHandlerMapping:

使用RequestMappingHandlerMapping需要在Handler 中使用@controller标识此类是一个控制器,使用@requestMapping指定Handler方法所对应的url。

        <!--
         2.3使用注解RequestMappingInfoHandlerMapping映射器
         注解映射器配对使用,主要解析Handler方法中的形参
         单个:
         <bean class="com.ycy.controller.ItemController3"/>
        -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
        </bean>

        <context:component-scan base-package="com.ycy.controller"/>

3.2注解适配器

spring3.1版本之前org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

spring3.1版本之后org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter

        <!--
        3.3 RequestMappingHandlerAdapter:注解适配器,与RequestMappingInfoHandlerMapping配对使用
        -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

3.3Controler

package com.ycy.controller;


import com.ycy.model.Items;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2015/9/17 0017.
 */
@Controller
public class ItemController3 {
    @RequestMapping("/queryItems")//建议与方法名称一致
    public ModelAndView queryItems(javax.servlet.http.HttpServletRequest httpServletRequest,
                                      javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
        //商品列表
        List<Items> itemsList = new ArrayList<Items>();

        Items items_1 = new Items();
        items_1.setName("联想笔记本");
        items_1.setPrice(6000f);
        items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
        items_1.setCreatetime(new Date());

        Items items_2 = new Items();
        items_2.setName("苹果手机");
        items_2.setPrice(5000f);
        items_2.setDetail("iphone6苹果手机!");
        items_2.setCreatetime(new Date());
        itemsList.add(items_1);
        itemsList.add(items_2);

        //创建modelAndView准备填充数据、设置视图
        ModelAndView modelAndView = new ModelAndView();
        httpServletRequest.setCharacterEncoding("utf-8");
        //填充数据
        modelAndView.addObject("itemsList", itemsList);
        //视图
        modelAndView.setViewName("order/itemsList");

        return modelAndView;
    }
}

访问结果url:http://localhost:8080/spring01/queryItems

--

四、SpringMVC总结分析

前面我们清楚了一下流程,现在我们看看spring源码分析,到底这些流程是怎么来的。

DispatcherServlet:前端控制器,中央指挥机器,降低组件之间的耦合度。

HandlerMappring: 负责处理器映射,根据url找到Handle

HandlerAdapter:处理器适配器,根据处理器需求执行适配器。可以通过扩展适配器支持不同类型的Handler 例如:Struts2

ViewResolver:视图解析器,根据逻辑视图解析为真正的视图。视图地址=前缀+逻辑视图名+后缀

视图解析器配置:

        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
            <property name="prefix" value="/pages/jsp/"/>
            <property name="suffix" value=".jsp"/>
        </bean>

执行流程:

1、DispatcherServlet

我们进入该类看到doDispatch这个方法有个注释:

Process the actual dispatching to the handler 翻译:进程调度的实际处理程序。

这个就是我们的中心处理程序方法:

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);
				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()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, 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
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

1】 Dispatcher通过Hander查询handle

springMVC详解

2】Dispatcher 通过适配器执行Handler,得到ModelAndView

3】得到ModelAndView,解析视图

springMVC

解析视图最里层我们看看。再往里,其实就是网request里面放置属性了。

jiangmodle数据填充到request中

springMVC教程

摘录自ycy博文



小说《我是全球混乱的源头》

感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程