1.概述
- Spring 为展现层提供的基于 MVC 设计理念的优秀的 Web 框架,是目前最主流的 MVC 框架之一
- Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架。
- SpringMVC 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口。
- 支持 REST 风格的 URL 请求。
- 采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性。
- 基于Servlet实现,方便运行于常用Java EE容器。
1.1 MVC模式
MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式:
- Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
- View(视图)是应用程序中处理数据显示的部分。
- Controller(控制器)是应用程序中处理用户交互的部分。
优点:耦合性低、重用性高、可维护性高。
1.2 Spring MVC 模式
前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。
Spring MVC使用Servlet来实现(DispatcherServlet)。DispatcherServlet 作为前置控制器是web服务器的入口,是spring mvc最重要的一个类。
1.3 SpringMVC 是什么
1)一种轻量级的、基于 MVC 的 Web 层应用框架。偏前端而不是基于业务逻辑层。Spring框架的一个后续产品。
2)Spring 框架结构图(新版本):
1.4SpringMVC 能干什么
- 天生与 Spring 框架集成,如:(IOC,AOP)
- 支持 Restful 风格
- 进行更简洁的 Web 层开发
- 支持灵活的 URL 到页面控制器的映射
- 非常容易与其他视图技术集成,如:Velocity、FreeMarker 等等
- 因为模型数据不存放在特定的 API 里,而是放在一个 Model 里(Map 数据结构实现, 因此很容易被其他框架使用)
- 非常灵活的数据验证、格式化和数据绑定机制、能使用任何对象进行数据绑定, 不必实现特定框架的 API
- 更加简单、强大的异常处理
- 对静态资源的支持
- 支持灵活的本地化、主题等解析
1.5 SpringMVC 常用组件
- DispatcherServlet:前端控制器
- Controller:处理器/页面控制器,做的是 MVC 中的 C 的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理
- HandlerMapping :请求映射到处理器,找谁来处理,如果映射成功返回一个 HandlerExecutionChain 对象(包含一个 Handler 处理器(页面控制器)对象、多 个 HandlerInterceptor 拦截器对象)
- ViewResolver: 视图解析器,找谁来处理返回的页面。把逻辑视图解析为具体 的 View,进行这种策略模式,很容易更换其他视图技术; 如 InternalResourceViewResolver 将逻辑视图名映射为 JSP 视图
- LocalResolver:本地化、国际化
- MultipartResolver:文件上传解析器
- HandlerExceptionResolver:异常处理器
1.6 SpringMVC常用注解
@Controller
负责注册一个bean 到spring 上下文中
@RequestMapping
注解为控制器指定可以处理哪些 URL 请求
@RequestBody
该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上
浏览器发ajax请求,设置成contentType:”application/json”,以json字符串的方式发送对象,服务器端通过@RequestBody把接受道德字符串转成java对象
@ResponseBody
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区
@RestController
@ModelAttribute
在方法定义上使用 @ModelAttribute 注解:Spring MVC 在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法
在方法的入参前使用 @ModelAttribute 注解:可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数 –绑定到对象中,再传入入参将方法入参对象添加到模型中
@RequestParam
在处理方法入参处使用 @RequestParam 可以把请求参 数传递给请求方法
@PathVariable
绑定 URL 占位符到入参
@ExceptionHandler
注解到方法上,出现异常时会执行该方法
@ControllerAdvice
使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常
2 SpringMVC-HelloWorld
2.1.新建 maven工程,添加web支持,引入各种 jar 包依赖
2.2 引入jar包依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
2.3. 在 web.xml 中配置 DispatcherServlet
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- 配置 SpringMVC 核心控制器: -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置 DispatcherServlet 的初始化參數:设置文件的路径和文件名称 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<!--拦截所有请求-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
*拦截所有请求应该将url-pattern的/换成/,这样可以拦截一切请求
新建对应的目录并且将其标记:
2.4 加入 SpringMVC 的配置文件:springmvc.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="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.xsd">
<!-- 设置扫描组件的包: -->
<context:component-scan base-package="net.suncaper"/>
</beans>
2.5 需要创建一个入口页面,index.jsp
<a href="${pageContext.request.contextPath}/helloworld">HelloWorld</a>
2.6 编写处理请求的处理器,并标识为处理器
package net.suncaper.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author nedli
*/
//1. 用@Controller告诉Spring MVC这是一个处理器,可以处理页面请求
@Controller
public class HelloController {
//2. 标志此方法处理 /hello 请求
@RequestMapping("/hello")
public String hello() {
//3. 返回.jsp页面的路径,很麻烦
return "/WEB-INF/views/hello.jsp";
}
}
2.7. 配置视图解析器(简化路径配置)
<!-- 配置视图解析器:如何将控制器返回的结果字符串,转换为一个物理的视图文件(拼接页面地址)-->
<bean id="internalResourceViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
这个时候Controller改为
package net.suncaper.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author nedli
*/
//1. 用@Controller告诉Spring MVC这是一个处理器,可以处理页面请求
@Controller
public class HelloController {
//2. 标志此方法处理 /hello 请求,使用hello也是一样的效果哦
@RequestMapping("/hello")
public String hello() {
//3. 返回.jsp页面的路径
return "hello";
}
}
2.8.部署测试
http://localhost:8080/SpringMVC_01_HelloWorld/index.jsp
3. HelloWorld 深度解析
3.1 HelloWorld 请求流程图解:
一般请求的映射路径名称和处理请求的方法名称最好一致(实质上方法名称任意);
经常有同学会出现配置上错误,把“/WEB-INF/views/”配置成了 “/WEB-INF/views”;
3.2 流程分析
基本步骤:
- 客户端请求提交到 DispatcherServlet
- 由 DispatcherServlet 控制器查询一个或多个 HandlerMapping,找到处理请求的 Controller
- DispatcherServlet 将请求提交到 Controller(也称为 Handler)
- Controller 调用业务逻辑处理后,返回 ModelAndView
- DispatcherServlet 查询一个或多个 ViewResoler 视图解析器,找到 ModelAndView 指定的视图
- 视图负责将结果显示到客户端.