Spring提供了DispatcherServlet,这个类不仅负责实现请求转发,还负责启动一个WebApplicationContext容器。 按照Spring一贯的IoC哲学,所有的Controller都是JavaBean,并由IoC容器统一管理。对于View,则采取了更灵活的处理方 式,Spring MVC允许使用不同的View实现,除了JSP外,还可以使用Velocity、Freemaker、XSLT等多种View技术。

总的来讲,要使用spring MVC框架,需要以下步骤。

① 在web.xml中配置DispatcherServlet及URL映射。

② 编写IoC容器需要的XML配置文件,命名为<servlet-name>-servlet.xml,放到/WEB-INF目录下。例如,如果DispatcherServlet在web.xml中的配置名称为dispatcher,则Spring将寻找dispatcher- servlet.xml配置文件。

③ 在XML配置文件中定义URL映射方式和使用哪种View技术。

我们仍以SimpleMVC为基础,用Spring MVC框架来实现这个Web应用程序。在Eclipse中创建一个SpringMVC项目,结构如图7-21所示。

/web/WEB-INF/lib目录下的jstl.jar和standard.jar是JSP标准标签库,将在JSP视图中用到,/web/WEB-INF/c.tld是标签库的声明文件,稍后我们会在JSP视图文件中用到它们。

一、  配置DispatcherServlet

首先,在web.xml中配置DispatcherServlet,并将所有以“.html”结尾的URL全部映射到DispatcherServlet上,这样,用户仅从URL地址上无法得知服务器端后台使用了何种技术。

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://Java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<!-- spring dispatch servlet -->

<servlet>

<servlet-name>dispatcher</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</ servlet-class>

<load-on-startup>0</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>dispatcher</servlet-name>

<url-pattern>*.html</url-pattern>

</servlet-mapping>

<!-- 申明taglib,将在JSP中使用 -->

<taglib>

<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>

<taglib-location>/WEB-INF/c.tld</taglib-location>

</taglib>

</web-app>

和普 通的Spring应用程序稍有不同,对于Web应用程序,Spring的ApplicationContext是由DispatcherServlet加 载的,它会在/WEB-INF/下查找一个名称为<servletName> -servlet.xml的XML配置文件来初始化Spring Web应用程序的ApplicationContext。对于上例,我们在web.xml中定义DispatcherServlet的名称为 dispatcher,因此,相应的XML配置文件就必须是/WEB-INF/dispatcher-servlet.xml。

下一步便是编写dispatcher-servlet.xml配置文件,首先定义URL的映射方式(HandlerMapping)。Spring提供了几种常用的HandlerMapping。

1.使用SimpleUrlHandlerMapping

SimpleUrlHandlerMapping提供了最简单的URL映射,通过Properties将URL和Controller对应起来,配置示例如下。

<bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet. handler.SimpleUrlHandlerMapping">

<property name="mappings">

<props>

<prop key="/a.html">controllerA</prop>

<prop key="/b.html">controllerB</prop>

</props>

</property>

</bean>

这种方式和Struts的配置类似。当用户请求一个URL时,Spring就在SimpleUrl HandlerMapping注入的Properties中查找对应的Controller。

2.使用BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping的实现更为简单,每个Controller的URL与其name属性对应,因此,只需要对每个Controller以URL作为name,就可以实现URL映射。配置示例如下。

<bean id="beanNameUrlHandlerMapping" class="org.springframework.web.servlet. handler.BeanNameHandlerMapping" />

<bean name="/a.html" class="example.chapter7.ControllerA" />

<bean name="/a.html" class="example.chapter7.ControllerB" />

之所以用Bean的name作为URL而不是id,是因为XML规范不允许在id标识中使用特殊字符“/”。当用户请求一个URL时,Spring将直接查找name为URL的Controller。

使用 SimpleUrlHandlerMapping的麻烦之处在于,添加或删除Controller时必须要对 SimpleUrlHandlerMapping做相应的修改,而BeanNameUrlHandlerMapping则无需手工编写映射,只需要在每个 Controller中仔细定义name属性。如果使用XDoclet自动生成配置文件,则可以将name在Controller的注释中定义,维护起来 更加方便。因此,我们推荐首先考虑使用BeanNameUrlHandlerMapping。事实上,如果没有在XML配置文件中定义任何 UrlHandlerMapping,则Spring MVC默认使用BeanNameUrlHandlerMapping。

Spring还提供了一个 ControllerClassNameHandlerMapping,它和BeanName UrlHandlerMapping类似,不过是将Controller的ClassName和对应的URL关联起来,由于这种方式灵活性欠佳,实际使用 较少。

也可以混合使用多种 UrlHandlerMapping,但是必须为每个UrlHandlerMapping指定order属性来表示优先级,order值越小优先级越高, Spring会先查询优先级高的UrlHandlerMapping。若找到了对应的Controller,就不再继续查询,否则,按照优先级依次查询, 直到找到为止。若所有的UrlHandlerMapping都无法返回一个合适的Controller,并且没有设置默认的Controller时,就会 返回给客户端一个“404 Not Found”错误,表示不存在这个URL。

下一步需要为Spring MVC指定一个ViewResolver(视图解析器),指示使用何种视图技术,以及如何解析ModelAndView返回的逻辑视图名称。

这里我们直接给出使用JSP视图的配置,对于其他的视图技术将会在后面讲到。

<bean id="viewResolver" class="org.springframework.web.servlet.view. InternalResourceViewResolver">

<property name="viewClass" value="org.springframework.web.servlet. view.JstlView" />

<property name="prefix" value="/" />

<property name="suffix" value=".jsp" />

</bean>

prefix和suffix将和逻辑视图名称一起组合成为实际视图的路径。例如,对于上例,若返回一个new ModelAndView("test", model),则实际的视图路径由prefix+逻辑视图名+suffix这3部分构成。

/test.jsp

定义 前缀(prefix)使得视图文件无论放在何处都可以通过修改前缀来实现位置无关性(当然,必须在web目录内),许多应用程序将其放在/WEB-INF 目录下,使得用户无法通过URL直接访问视图文件以保证视图文件的安全;定义后缀(suffix)可以在将来用另一种视图技术(例如,Velocity) 取代现在的JSP视图,只需将后缀从“.jsp”更改为“.vm”即可,而不必更改源代码中的逻辑视图名。总之,一切目标都是为了实现最大限度的解耦。

二、实现Controller

实现了org.springframework.web.servlet.mvc.Controller接口的Bean都可以作为有效的Controller来处理用户请求。例如,一个最简单的TestController。

public class TestController implements Controller {

public ModelAndView handleRequest(HttpServletRequest request, HttpServlet Response response) throws Exception {

String name = request.getParameter("name");

if(name==null)

name = "spring";

Map model = new HashMap();

model.put("name", name);

model.put("time", new Date());

return new ModelAndView("test", model);

}

}

注 意,上例的Controller接口和返回值ModelAndView都是在Spring框架中定义的,这和SimpleMVC项目中我们自己定义的 Controller接口和ModelAndView类所在的包是不同的。在SimpleMVC项目中,我们并没有使用Spring MVC,而是借用Spring MVC的概念自定义接口。在现在的SpringMVC项目中,我们没有自定义任何接口,而是直接使用Spring MVC框架来实现Web应用程序,这一点请读者务必区分清楚。

另外需要注意的是,ModelAndView返回的逻辑视图是“test”,还记得在viewResolver中定义的prefix和suffix吗?实际的视图名称由这3部分构成便是“/test.jsp”。

最后将这个TestController作为Bean定义在dispatcher-servlet.xml中,由于我们准备使用默认的BeanNameUrlHandlerMapping,因此,需要在Bean的name中指定URL。

<bean name="/test.html" class="example.chapter7.TestController" />

完整的dispatcher-servlet.xml配置文件的内容如下。

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean name="/test.html" class="example.chapter7.TestController" />

<bean id="viewResolver" class="org.springframework.web.servlet.view. InternalResourceViewResolver">

<property name="viewClass" value="org.springframework.web.servlet. view.JstlView" />

<property name="prefix" value="/" />

<property name="suffix" value=".jsp" />

</bean>

</beans>

注意,我们没有指定UrlHandlerMapping,Spring会自动使用默认的BeanNameUrl HandlerMapping。

三、  实现View

到目前为止,我们已经编写了 Controller的实现和配置文件,最后一步是编写一个JSP文件作为视图。由于采用了MVC架构,视图的任务只有一个,就是将Controller 返回的Model渲染出来。Spring MVC会将Model中的所有数据全部绑定到HttpServlet Request中,然后将其转发给JSP,JSP只需将数据显示出来即可。

通过JSTL标签库能进一步简化显示逻辑,我们看看如何显示TestController返回的Model。test.jsp文件的内容如下。

<%@ page contentType="text/html; charset=utf-8" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<html>

<head>

<title>SpringMVC</title>

</head>

<body>

<h3>Hello, <c:out value="${name}" />,

it is <c:out value="${time}" /></h3>

</body>

</html>

现在,Spring MVC所需的所有组件都已编写并配置完毕,我们先来回顾一下Spring MVC的处理流程,如图7-22所示。

将SpringMVC工程的编译输出目录设置为/web/WEB-INF/classes,然后编译工程,打开浏览器,测试我们编写的SpringMVC,结果如图7-23所示。

图7-23

现在,读者对Spring的MVC框架应该有了一个初步的认识。实际上,除了基本的MVC标准流程外,Spring MVC还提供了相当多的功能,下面我们将逐一介绍Spring MVC提供的各种丰富的Controller、拦截器和异常处理机制

Spring MVC的实现原理的更多相关文章

  1. Spring MVC的工作原理和机制

    Spring  MVC的工作原理和机制 参考: springMVC 的工作原理和机制 - 孤鸿子 - 博客园https://www.cnblogs.com/zbf1214/p/5265117.html ...

  2. Spring MVC的工作原理,我们来看看其源码实现

    前言 开心一刻 晚上陪老丈人吃饭,突然手机响了,我手贱按了免提……哥们:快出来喝酒!哥几个都在呢!我:今天不行,我现在陪老丈人吃饭呢.哥们:那你抓紧喝,我三杯白酒,把我岳父放倒了才出来的,你也快点.看 ...

  3. Spring MVC内容协商实现原理及自定义配置【享学Spring MVC】

    每篇一句 在绝对力量面前,一切技巧都是浮云 前言 上文 介绍了Http内容协商的一些概念,以及Spring MVC内置的4种协商方式使用介绍.本文主要针对Spring MVC内容协商方式:从步骤.原理 ...

  4. spring mvc的工作原理

    该文转载自:http://blog.csdn.net/u012191627/article/details/41943393 SpringMVC框架介绍 1) spring MVC属于SpringFr ...

  5. spring MVC 及 AOP 原理

    SpringMVC工作原理https://www.cnblogs.com/xiaoxi/p/6164383.htmlspring MVC 原理https://blog.csdn.net/y199108 ...

  6. 阿里P7工作总结:Spring MVC的工作原理,看完受益匪浅

    这篇文章将深入探讨Spring框架的一部分——Spring Web MVC的强大功能及其内部工作原理. 项目安装 在本文中,我们将使用最新.最好的Spring Framework 5.我们将重点介绍S ...

  7. Spring MVC 的工作原理

    引自:https://www.cnblogs.com/xiaoxi/p/6164383.html SpringMVC的工作原理图: SpringMVC流程 1.  用户发送请求至前端控制器Dispat ...

  8. spring mvc拦截器原理分析

    我的springMVC+mybatis中的interceptor使用@autowired注入DAO失败,导致报空指针错误,这个是为什么呢? :空指针说明没有注入进来,你可以检查一下你的这个拦截器int ...

  9. Spring MVC 原理探秘 - 一个请求的旅行过程

    1.简介 在前面的文章中,我较为详细的分析了 Spring IOC 和 AOP 部分的源码,并写成了文章.为了让我的 Spring 源码分析系列文章更为丰富一些,所以从本篇文章开始,我将来向大家介绍一 ...

随机推荐

  1. java面试笔试大汇总

    java面试笔试题大汇总5 JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象:2.继承:3.封装:4. 多态性: 2.String是最基本的数据类型吗? 基本数据类型包括byte.int. ...

  2. [0] MVC&MVP&MVVM差异点

    MVC: 用户的请求首先会到达Controller,由Controller从Model获取数据,选择合适的View,把处理结果呈现到View上: MVP: 用户的请求首先会到达View,View传递请 ...

  3. POJ 1207 3N+1 Problem

    更简单的水题,穷举法即可. 需要注意的点: 1.i 和 j的大小关系不确定,即有可能 i>j 2.即使i>j,最后输出的结果也要严格按照输出,亦即如果输入10,1,则对应输出也应为 10 ...

  4. python 文件操作(pickle)

    >>> with open('text.txt','wb') as data:pickle.dump(['a','b',2],data) 保存到文件 >>> wit ...

  5. 9天C#转Java学习过程,自己记录一下

    其实没有完整的9天,就是连续每天花点时间,过程so frustrated,踩坑无数...下面是学习过程的记录 第1天 开始正式学习JavaEE,已完成: 1. Tomcat安装: 2. Tomcat配 ...

  6. php对数组中的键与值进行合并处理

    $res=array(); $re=array_count_values($month); foreach( $re as $k=>$v){ $arr['month_name'] = strva ...

  7. mysql 列类型以及属性特点

    整形列: 一个字节有8个位,例如:int 类型的列存入数字1,00000000 00000000 00000000 00000001它就在最低位置上存入一个1,由此可见是极大的浪费资源,所以在建立列类 ...

  8. 剑指offer 练习题目

    #include <iostream> #include<vector> #include <stack> #include<map> #include ...

  9. 【LeetCode】327. Count of Range Sum

    题目: Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusiv ...

  10. 禁用自动映射的 Exchange 邮箱

    客户最近询问他们无法从用户的Outlook配置文件中删除邮箱.在这种情况下,它们是共享邮箱,并出现在Outlook的左窗格中.但原因和解决方法同样适用于用户邮箱.并且 无论用户邮箱在本地 Exchan ...