什么是Spring MVC ?
SpirngMVC是Spring 的一个模块,其实就是:Spring实现MVC、Spring 实现web模块、简化web开发
SpringMVC采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性,在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1等..
Spring 和 SpringMvc 无缝集成
MVC 模式
mvc是一种程序开发设计模式,及:模型model 、view 视图、controller 控制。
它强制性的使应用程序的输入、处理和输出分开,将一个复杂的应用程序分层管理,
从而使得应用程序结构更加分明、低耦合、易于维护
mvc流程图:
Spring MVC 模式流程图:
- 用户发起请求到前端控制器(DispatcherServlet),该控制器会过滤出哪些请求可以访问Servlet、哪些不能访问。就是url-pattern的作用,并且会加载springmvc.xml配置文件。
- 前端控制器会找到处理器映射器(HandlerMapping),通过HandlerMapping完成url到controller映射的组件,简单来说,就是将在springmvc.xml中配置的或者注解的url与对应的处理类找到并进行存储,用map<url,handler>这样的方式来存储。
- HandlerMapping有了映射关系,并且找到url对应的处理器,HandlerMapping就会将其处理器(Handler)返回,在返回前,会加上很多拦截器。
- DispatcherServlet拿到Handler后,找到HandlerAdapter(处理器适配器),通过它来访问处理器,并执行处理器。
- 执行处理器
- 处理器会返回一个ModelAndView对象给HandlerAdapter
- 通过HandlerAdapter将ModelAndView对象返回给前端控制器(DispatcherServlet)
- 前端控制器请求视图解析器(ViewResolver)去进行视图解析,根据逻辑视图名解析成真正的视图(jsp),其实就是将ModelAndView对象中存放视图的名称进行查找,找到对应的页面形成视图对象
- 返回视图对象到前端控制器。
- 视图渲染,就是将ModelAndView对象中的数据放到request域中,用来让页面加载数据的。
- 通过第8步,通过名称找到了对应的页面,通过第10步,request域中有了所需要的数据,那么就能够进行视图渲染了。最后将其返回即可。
下面使用SpringMvc 写一个 hello world 的小程序
1.使用maven 创建一个war 包
2.编写index.jsp 首页 和 helloWorld.jsp 响应页面
index.jsp
helloWorld.jsp
接下来开始编写我们的 SpringMvc
3.首先在Maven的pom.xml 中 导入Spring以及SpringMvc 模块的依赖 (直接导入 Spring-webmvc 就行啦,maven内部会自动导入相关连的Spring依赖)
<!-- Spring Mvc 是 Spring中的一个模块 -->
<!-- Spring Web Mvc -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
4.在web.xml中配置映射前端控制器 DispatcherServlet
<!--
配置Spring Mvc的前端控制器,拦截客户端请求,并进行智能派发 -->
<servlet>
<servlet-name>springMvc</servlet-name>
<!--指定前端控制器来自于哪个类 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 初始化配置 :初始化时加载SpringMvc配置文件 -->
<init-param>
<!-- 指定 SpringMvc配置文件位置 -->
<param-name>contextConfigLocation</param-name> <!-- 指定配置文件的key -->
<param-value>classpath:springMvc-servlet.xml</param-value> <!-- 指定文件位置 -->
</init-param>
<!-- 配置加载时期 (启动tomcat时,就加载 前端控制器)-->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 配置 前端控制器 servlet 映射 -->
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
注: url-pattern 的 配置
/ :会匹配到路径型的 url,不会匹配到模式为 *.jsp 这样的后缀型url
访问*.jsp不会经过 DispatcherServlet
*/:会匹配到所有url:包括路径型和后缀型的url(login、 *.jsp、 *.js、 *.html等)
所有的请求都会经过DispatcherServlet
重要:当设置为 */ 时,客户端访问 login.jsp请求,会被前端控制器拦截, 故而DispatcherServlet会再次将
login.jsp当成请求寻找对应的Controller去执行,此时肯定找不到对应的Controller,故而报404
重要:在配置视图的时候尽量用 / 这种方式
注意:前端控制器 <init-param> 初始化加载配置文件的问题
如果web.xml中如果 不配置前端控制器 初始化时加载springMvc-servlet.xml配置文件
<!--
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
-->那么前端控制器创建时,会根据配置的<servlet-name>xxx名字,默认加载配置文件:/WEB-INF/xxx名字-servlet.xml
例如:
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
默认加载:/WEB-INF/mvc-servlet.xml项目中每一个文件的存放位置都是有严格要求的,总之还是把文件放在他的默认加载位置好一些
5.编写控制器和处理请求方法
/**
* 该类是一个控制器,用于接收响应index.jsp 页面请求
*
* 普通的java类想要成为一个控制器需要继承Servlet 类或者接口
*
* 在SpringMvc中通过注解@Controller 就能让一个类成为控制器
* 通过注解:@Controller 标识该类是一个控制器
*/
@Controller
public class FirstController {
/**
* 定义一个方法接受请求
* 通过@RequestMapping() 来声明要处理什么样的请求
*/
@RequestMapping("/hello") //处理 hello 请求
public String hello() {
System.out.println("正在处理请求......");
/* SpringMVC会将方法处理的返回值 作为一个具体的响应视图
*
* return "/WEB-INF/inner/helloWorld.jsp"; //转发 页面地址
*
* 因为我们配置了视图解析器,不用填写视图的全路径
*
* 视图解析器,进行字符串拼接 得到最终具体的响应视图页面
* /WEB-INF/inner/ helloWorld .jsp
*/
return "helloWorld"; // 内部通过转发 响应到视图页面
}
}
通过注解@Controller 可以让一个普通的java类成为控制器
6.编写SpringMvc-servlet.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- springmvc 本就是spring的一个模块,他们是无缝集成的
约束直接使用spring的就行啦
-->
<!-- Spring MVC 配置文件 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 扫描注解组件 (将注解的类全部加载到Spring容器中) -->
<context:component-scan base-package="com.tz"></context:component-scan>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"></property> <!-- 前缀 -->
<property name="suffix" value=".jsp"></property> <!-- 后缀 -->
</bean>
</beans>
- 自动扫描组件:将控制器自动加载到 Spring容器中
- 视图解析器:将目标方法返回值,做字符串拼接得到完整的视图页面
项目视图:
客户端访问
http://localhost:8080/springMvc01/index.jsp
点击a标签,向服务器发送请求hello请求
控制台:
hello World小程序在Spring Mvc 中的处理流程:
- 浏览器点击超链接发送hello请求:http://localhost:8080/springMvc01/hello
- 来到tomcat服务器
- 前端控制器接收到hello请求
- 前端控制器根据请求地址去匹配controller中的@RequestMapping()地址
- 前端控制器找到了目标处理类和目标处理方法,利用反射执行目标处理方法
- 执行完目标方法后的返回值,SpringMvc认为该返回值就是要响应的页面地址
- 拿到方法的返回值之后,视图解析器进行字符串拼接得到完整页面地址
- 拿到页面地址,前端控制器转发到页面