一、SpringMVC 概述

1、SpringMVC 在知识体系中的坐标

在我们学习框架知识以前,JavaSE+JDBC+JavaWeb+SQL 这样的技术组合已经可以实现任何业务逻辑了。为什么还要学习 SSM 这样的框架呢?

很简单,MyBatis 是对 JDBC 的封装,而 SpringMVC 是对 JavaWeb 的封装。

其中 JavaWeb 和 SpringMVC 提供了表述层(或称表示层)的解决方案,而 JDBC 和 MyBatis 是持久化层的解决方案。

那 Spring 到哪去了?Spring 中的 IOC 容器为我们的整个项目管理组件,而我们配置的各种 bean、切面类、事务通知等等其实都是在容器中工作的组件。

因此我们开发人员的任务其实就两件事:开发组件组装组件

2、 使用 SpringMVC 前后代码的对比

使用原生 ServletAPI 获取请求参数:

1
2
3
4
5
6
7
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

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

System.out.println("userName="+userName);

}

使用 SpringMVC 获取请求参数:

1
2
3
4
5
6
7
@RequestMapping("/user/login")
public String login(@RequestParam("userName") String userName){

System.out.println("userName="+userName);

return "result";
}

这仅仅是其中一个例子,使用 SpringMVC 后确实大大简化了表述层开发。

二、SpringMVC 搭建开发环境及测试

通过这个 HelloWorld,来初步体会 SpringMVC 使用过程中的总体流程。

1、创建 Dynamic Web Project

2、导入 jar 包

3、 在 web.xml 中配置 SpringMVC 的前端控制器:DispatcherServlet

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
<!-- 配置SpringMVC的前端控制器:DispatcherServlet -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<!-- 正常配置Servlet的全类名 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<!-- 使用DispatcherServlet的初始化参数指定Spring配置文件的位置 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>

<!-- 在Servlet生命周期中,在默认情况下,是在第一次请求时创建对象 -->
<!-- 但是DispatcherServlet作为SpringMVC框架的核心组件,在初始化要做的操作非常多 -->
<!-- 这么多初始化操作如果等到第一次请求时才做,就来不及了 -->
<!-- 所以需要借助load-on-startup标签将它设置为随Web应用一起启动 -->
<load-on-startup>1</load-on-startup>
</servlet>



<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>

<!-- 对于DispatcherServlet来说,url-pattern有两种方式配置 -->

<!-- 方式一:匹配所有请求,使用『/』 -->
<url-pattern>/</url-pattern>

<!-- 方式二:匹配请求扩展名,使用*.扩展名格式 -->
<!-- 配置*.mvc表示请求扩展名为mvc时才交给SpringMVC处理,否则与SpringMVC无关 -->
<!--<url-pattern>*.mvc</url-pattern>-->

</servlet-mapping>

4、在 src 目录下创建 Spring 配置文件(spring-mvc.xml)并指定自动扫描的包

1
<context:component-scan base-package="com.atguigu.mvc.controller"/>

注意:Spring 配置文件的文件名必须和 web.xml 中 classpath:后一致,否则将无法找到。

5、在自动扫描的包下创建 HelloHandler 类用来处理请求

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
package com.atguigu.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
* 这个类是在SpringMVC中专门负责处理请求的类
* 这样的类通常有两种习惯的命名方式:
* XxxHandler Xxx处理器
* XxxController Xxx控制器
* 这只是大家的习惯,并不是SpringMVC的语法要求。
*/
@Controller
public class HelloHandler {

// @RequestMapping注解表示浏览器访问/hello地址时,SpringMVC调用当前方法处理这个请求
// 这个注解字面的意思是:请求映射
@RequestMapping("/hello")
public String sayHelloOld() {
System.out.println("嘿!我来了!");

// 目标页面的转发地址:/WEB-INF/pages/target.jsp
// 在SpringMVC的环境下,直接把转发的目标地址作为handler方法的返回值即可
// SpringMVC会替我们转发到这个地址
return "/WEB-INF/pages/target.jsp";
}
}

6、按照方法返回值里的路径创建对应的 JSP 页面

方法返回值里的路径:

之所以放到/WEB-INF/下面是一个习惯,这样浏览器没法直接访问,访问的话必须通过 java 程序,这样方便我们来检查权限,检查权限不需要考虑页面,只需要通过 java 程序来控制就可以了。

1
return "/WEB-INF/pages/target.jsp";

对应的 target.jsp 页面:

1
2
<h1>这是HelloWorld的结果页面!</h1>
<a href="${pageContext.request.contextPath}/index.jsp">回首页</a>

7、在 index.jsp 页面创建访问 HelloWorld 的超链接

1
<a href="${pageContext.request.contextPath }/hello">HelloWorld</a>

8、访问测试

三、分析

1、项目启动过程分析

2、请求处理过程分析

3、url-pattern 中为什么是“/”而不是“/*”?

SpringMVC 在 url-pattern 的配置中支持两种风格——

REST 风格:

1
<url-pattern>/</url-pattern>

扩展名风格:

1
2
<!-- 配置*.mvc表示请求扩展名为mvc时才交给SpringMVC处理,否则与SpringMVC无关 -->
<url-pattern>*.mvc</url-pattern>

以“/”开头的路径会被认为是 REST 风格,而“/*”的写法是不符合 REST 风格规范的。只有在 SpringMVC 这里有映射“/”的情况,其他地方一切照旧。