SpringMVC入门(基本配置)

Spring MVC 框架入门

1.1 Spring MVC介绍

SpringMVC和Struts2都属于表现层的框架,它是Spring框架的一个模块,提供web层解决方案,我们可以从Spring的整体结构中看得出来:

1.2 MVC在b/s系统的应用

mvc是一个设计模式,在b/s系统的应用如图:

解释如下:

  • 1.用户发起request请求至控制器(Controller),控制接收用户请求的数据,委托给模型(Model)进行处理。
  • 2.控制器通过模型(Model)处理数据并得到处理结果,模型通常是指业务逻辑(jsp、dao、service)。
  • 3.模型处理结果返回给控制器。
  • 4.控制器将模型数据在视图(View)中展示,web中模型无法将数据直接在视图上显示,需要通过控制器完成。如果在C/S应用中模型是可以将数据在视图中展示的。
  • 5.控制器将视图response响应给用户,通过视图展示给用户要的数据或处理结果。

1.3 Spring MVC 架构

1.3.1 架构图

1.3.2 架构流程

    1. 用户发送请求至前端控制器DispatcherServlet
    1. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
    1. 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
    1. DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
    1. 执行处理器(Controller,也叫后端控制器)。
    1. Controller执行完成返回ModelAndView
    1. HandlerAdaptercontroller执行结果ModelAndView返回
    1. DispatcherServletModelAndView传给ViewReslover视图解析器
    1. ViewReslover解析后返回具体View
    1. DispatcherServletView进行渲染视图(即将模型数据填充至视图中)。
    1. DispatcherServlet响应用户

1.3.3架构中涉及的组件说明

    1. DispatcherServlet:前端控制器。用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。由框架实现
    1. HandlerMapping:处理器映射器。HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。由框架实现
    1. Handler:处理器。Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
    1. HandlAdapter:处理器适配器。通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。由框架实现。
    1. ViewResolver:视图解析器。ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。

1.4 入门程序(使用maven构建)

需求 : 请求一个简单的静态页面

导入相关的jar包,Spring版本4.3.16.RELEASE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<dependencies>
<!-- Junit依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- 导入java ee jar 包 -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<!--=================================================================-->
<!--Spring核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--测试模块,能使用SpringJUnit4ClassRunner快速的实现单元测试-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!--如果要整合mybatis,要加入orm和tx模块,并且mybatis的版本和mybatis-spring版本也要匹配-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!--事务控制-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!--web模块必须的包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!--SpringMVC模块-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>

1.4.1 前端控制器配置(web.xml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!--====================================前端控制器配置=====================================-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载springmvc配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<!--配置文件的地址
如果不配置contextConfigLocation,默认查找的配置文件名称是classpath下的:servlet名称+"-servlet.xml"
即springmvc-servlet.xml-->
<param-value>classpath:spring/applicationContext.xml</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>springmvc</servlet-name>

<!--可以配置"/"此工程所有的请求全部由springmvc解析,此种方式可以实现RESTful方式,
需要特殊处理对静态文件的解析不能由springmvc解析;
可以配置*.do或者*.action,所有请求的url扩展名为.do或.action由springmvc解析,此中方法常用;
不可以配置"/*",如果配置/*,返回jsp也由springmvc解析,这是不对的-->
<url-pattern>*.action</url-pattern>
</servlet-mapping>

1.4.2 配置SpringMVC三大组件 –处理器映射器、处理器适配器、视图解析器

简介:

  • 处理器映射器:根据前端传来的url匹配正确的处理器,并返回给前端控制器
  • 处理器适配器:能够调用不同类别的处理器来执行任务
  • 视图解析器:视图解析

1.4.2.1 处理器映射器

对于用户发起的request请求,前端控制器首先会请求HandlerMapping处理器映射器来查找Handler

applicationContext.xml配置文件中:

1
2
3
<!--配置处理器映射器-->
<!--根据url查找对应id值的Handler-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

1.4.2.2 处理器适配器

处理器适配器有不同类型的,他们可以去调用不同类别的Handler来完成任务,如下方的,让Handler去实现Controller接口,这样,SimpleControllerHandlerAdapter会调用这个类别的处理器去执行任务

1
2
3
<!--配置处理器适配器-->
<!--他只能适配Controller的实现类型的Controller-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

1.4.2.3 视图解析器

1
2
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>

1.4.2.4 处理器编写与配置

处理器是根据你的业务需求需要我们自己来编写的,你可以选择实现不同类型的处理器,他们做了不同程度的封装.

这里我们实现Controller接口,这样他就能被SimpleControllerHandlerAdapter适配器适配,同时又能根据它的name值被BeanNameUrlHandlerMapping映射器找到,从而将相应的请求传入对应的Handler中

1
2
3
4
5
6
7
8
9
10
11
12
public class UserController implements Controller {

@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
// 设置模型数据,通过键值对的形式设置,在页面中就像从response中取数据一样取出来
modelAndView.addObject("msg", "Hello World!");
// 设置视图,这里设置了一个链接,相当于转发
modelAndView.setViewName("jsp/helloworld.jsp");
return modelAndView;
}
}

处理器也作为一个组件,需要在applicationContext.xml进行配置

1
2
3
<!--配置我们自定义的Handler(处理器)-->
<!--它会被BeanNameUrlHandlerMapping类型的处理器映射器映射匹配,根据它的name值-->
<bean name="/helloworld.action" class="com.lee.ssm.controller.UserController"/>

至此配置完毕,当在浏览器的地址栏中输入:http://localhost:8080/ssm/helloworld.action的时候,最终会显示jsp/helloworld.jsp页面中的内容(在我们的处理器UserController中设置了modelAndView.setViewName("jsp/helloworld.jsp");)

流程是这样的:

  1. http://localhost:8080/ssm/helloworld.action
  2. 处理器映射器查找name名称为helloworld.action的处理器,并且返回给前端控制器,也就是返回了UserController
  3. 前端控制器将UserController交给处理器适配器
  4. 处理器适配器判断UserController的类型,看自己能不能调用执行(我们配置的处理器适配器有SimpleControllerHandlerAdapter,所以他能执行,SimpleControllerHandlerAdapter是专门执行调用Controller接口实现类型的Controller)
  5. 处理器适配器执行Handler
  6. Handler返回ModelAndView给前端控制器
  7. 前端控制器调用InternalResourceViewResolver视图解析器进行解析,并将解析后的view返回给前端控制器
  8. 前端控制器渲染视图,响应给客户端(浏览器)

在上面的配置过程中我们分别配置了处理器映射器,处理器适配器,视图解析器,当我们把这三个注释掉,他依然能够完成请求的响应,也就是说,依然能能够完成请求的映射执行,这是为什么呢?

对于前端控制器DispatcherServlet,我有必要多说几句,在spring-webmvc.jar包中有一个DispatcherServlet.properties文件,内容如下:

里面包含一些默认的组件例如处理器映射器、处理器适配器等,当程序启动时,DispatcherServlet会自动加载DispatcherServlet.properties配置文件,从而默认加载各个组件,所以如果我们在springmvc.xml中配置了处理器映射器和处理器适配器,那程序就以springmvc.xml中的配置信息为主。