SpringMVC框架概述和入门案例
-
概述:
- MVC模型概述:
- MVC全名是Model View Controller 模型视图控制器,每个部分各司其职。
- Model:数据模型,JavaBean的类,用来进行数据封装。
- View:指JSP、HTML用来展示数据给用户
- Controller:用来接收用户的请求,整个流程的控制器。用来进行数据校验等。
- MVC全名是Model View Controller 模型视图控制器,每个部分各司其职。
- SpringMVC的概述:
- 是一种基于Java实现的MVC设计模型的请求驱动类型的轻量级WEB框架。
- Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。
- 使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2等。
- SpringMVC 在三层架构的位置 :表现层
- SpringMVC和Struts2的对比:(常见的面试题)
- 共同点:
- 它们都是表现层框架,都是基于 MVC 模型编写的。
- 它们的底层都离不开原始 ServletAPI。
- 它们处理请求的机制都是一个核心控制器。
- 区别:
- Spring MVC 的入口是
Servlet
, 而 Struts2 是Filter
- Spring MVC 是基于方法设计的,而 Struts2 是基于类,Struts2 每次执行都会创建一个动作类。所以 Spring MVC 会稍微比 Struts2 快些。
- Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便
- JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们 JavaBean 的属性上面,就可以在需要校验的时候进行校验
- Struts2 的 OGNL 表达式使页面的开发效率相比Spring MVC 更高些,但执行效率并没有比 JSTL 提升,尤其是 struts2的表单标签,远没有 html 执行效率高。
- Spring MVC 的入口是
- 共同点:
- MVC模型概述:
-
入门案例:
-
创建MAVEN工程,在
pom.xml
中导入坐标如下:<!-- 版本锁定:指定Spring版本 --> <properties> <spring.version>5.0.2.RELEASE</spring.version> </properties> <!-- 依赖坐标 --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> <scope>provided</scope> </dependency> </dependencies>
-
配置核心的控制器也就是
DispatcherServlet
,并使Spring容器在TOMCAT初始化时创建.- 在工程的
webapp/WEB_INF
目录下配置web.xml
<!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> <display-name>Archetype Created Web Application</display-name> <!--配置过滤器使用的是filter标签 注意的是filter标签在Servlet标签的之前用来设置字符集--> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- SpringMVC的核心控制器 --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 配置servlet启动时加载对象 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
- 在工程的
-
进行
springmvc.xml
配置文件的编写<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--spring中的开启注解扫描--> <context:component-scan base-package="com.itheima"></context:component-scan> <!--配置视图的解析器--> <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--表示文件所在的目录 (前缀)--> <property name="prefix" value="/WEB-INF/pages/" ></property> <!--文件的后缀名是什么 (后缀)--> <property name="suffix" value=".jsp"></property> </bean> <!--开启springmvc框架的注解的支持--> <mvc:annotation-driven conversion-service="dateConverter"></mvc:annotation-driven> </beans>
-
进行控制器(Controller)和视图(jsp)的编写:
-
index.jsp: 在
webapp
目录下创建<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>主页</title> </head> <body> <h3>入门案例</h3> <a href="hello">入门案例</a> </body>
-
HelloController :在java目录下创建控制器类
com.itheima.controller
下@Controller public class HelloController { @RequestMapping(path="/hello") // 指定方法对应的URL public String helloHandler() { System.out.println("Hello SpringMVC!!"); return "success"; // 指定跳转的视图的地址,被ViewResolver解析为 /WEB-INF/pages/success.jsp } }
-
在 webapp/WEB-INF目录下创建pages目录,在pages目录下创建
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <h3>入门成功</h3> </body> </html>
-
配置TOMCAT服务器
-
点击右上角配置,添加TOMCAT服务器
-
选择本地TOMCAT服务器
- Tips:在进行配置时将 端口从8080改为80 就不用再进行访问的时候输入端口
-
在
Deployment
选项卡下将当前项目部署到TOMCAT服务器上,并在Application Context
中配置当前项目的URL路径
-
-
进行测试: 启动服务器:访问
http://localhost:8080/springmvc
默认访问的是index.jsp
-
点击链接,跳转到success.jsp页面并在控制台输出"Hello SpringMVC!!"
-
-
-
入门案例的执行流程分析:
- 入门案例的执行流程
- 当启动Tomcat服务器的时候,因为配置了
load-on-startup
标签,所以会创建DispatcherServlet
对象,就会加载springmvc.xml
配置文件 - 开启了注解扫描,那么
HelloController
对象就会被创建 - 从
index.jsp
发送请求,请求会先到达DispatcherServlet
核心控制器,根据配置@RequestMapping
注解找到执行的具体方法 - 根据执行方法的
返回值
,再根据配置的视图解析器
,去指定的目录下查找指定名称的JSP文件
- 最终Tomcat服务器渲染页面,响应到浏览器
- 当启动Tomcat服务器的时候,因为配置了
- SpringMVC 的请求响应流程
- 入门案例的执行流程
-
SpringMVC中涉及到的组件详解 :
- 前端控制器(DispatcherServlet)
- 用户请求到达前端控制器,它就相当于 mvc 模式中的 c,DispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。
- 处理器映射器(HandlerMapping)
- HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等
- 处理器(Handler)
- 是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。
- 处理器适配器(HandlAdapter)
- 通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行
- 视图解析器(View Resolver)
- View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
- 视图(View)
- 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面 如:jsp。
<mvc:annotation-driven>
- SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC 的三大组件
- 使 用
<mvc:annotation-driven>
自动加载RequestMappingHandlerMapping
(处理映射器) 和RequestMappingHandlerAdapte
r ( 处 理 适 配 器 ) , 可 用 在SpringMVC.xml
配 置 文 件 中 使 用<mvc:annotation-driven>
替代注解处理器和适配器的配置-
<mvc:annotation-driven>
标签相当于在 xml 中配置如下标签:<!-- HandlerMapping --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerM apping"></bean> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> <!-- HandlerAdapter --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerA dapter"></bean> <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- HadnlerExceptionResolvers --> <bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExcept ionResolver"></bean> <bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolv er"></bean> <bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver" ></bean>
-
【注意】开发中,需要将配置配置齐全 而不是进行简化的配置,该标签还有具体的使用场景
-
- 前端控制器(DispatcherServlet)
-
请求参数的绑定:
- 参数绑定的机制:表单中的请求参数是基于key,value的SpringMVC 中绑定请求参数的过程是通过将表单提交的请求参数作为控制器中的方法参数进行绑定的
- SpringMVC内置参数绑定类型:
- 基本类型参数:
- 包括基本类型和 String 类型
- POJO 类型参数:
- 包括实体类,以及关联的实体类
- 数组和集合类型参数:
- 包括 List 结构和 Map 结构的集合(包括数组)
- 基本类型参数:
- 参数绑定的使用要求:
- SpringMVC中参数的绑定是自动的 但是使用必须遵循要求:数据绑定要求请求参数名和方法中的参数名相同,或使用
@RequestParam
为方法参数起别名.- 基本类型或者是String类型:要求参数名称必须和控制器中方法的形参名称保持一致 (严格区分大小写)
<a href="account/findAccount?accountId=10&accountName=zhangsan">查询账户</a>
@Controller @RequestMapping(path = "/account") public class HelloController { @RequestMapping("/findAccount") public String findAccount(Integer accountId, String accountName) { // 能够获取url中的参数 // 方法体... } }
- POJO 类型或者它的关联对象:要求表单中参数名称和 POJO 类的属性名称保持一致 并且控制器方法的参数类型是 POJO 类型(JavaBean类型有空参的构造方法 和 get set方法)
- 如果Bean类型的参数类型都是基本类型或者是String类型:以属性名作为请求参数名,则SpringMVC会自动将其封装成JavaBean对象
- 集合类型:两种方式实现
- 集合类型的请求参数必须在bean 中。在表单中请求参数名称要和bean 中集合属性名称相同 List使用的是下标进行赋值 Map中使用键值对进行赋值
- 使用json的格式进行赋值 使用的是
@ResponseBody
注解
- 基本类型或者是String类型:要求参数名称必须和控制器中方法的形参名称保持一致 (严格区分大小写)
- SpringMVC中参数的绑定是自动的 但是使用必须遵循要求:数据绑定要求请求参数名和方法中的参数名相同,或使用
-
常用的注解:
@RequestMapping
注解 详解:- 使用的说明:
- 源码:
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface RequestMapping { }
- 作用:用于建立请求的URL和请求方法之间的对应关系
- 源码:
- 作用的位置:
- 类上:请求 URL 的第一级访问目录。此处不写的话,就相当于应用的根目录。写的话需要以/开头
- 方法上:请求 URL 的第二级访问目录
@Controller @RequestMapping("/account")// 指定的是一级目录account public class AccountController { @RequestMapping("/findAccount")//指定的是二级目录findAccount public String findAccount() { System.out.println("查询账户"); return "success"; } }
- 属性:属性之间的关系是与的关系 常使用的是
前两种
属性- value:用于指定请求的 URL。它和 path 属性的作用是一样的。能使用通配符
* ?**
- 遵循最长匹配原则,若URL请求了/project/dir/file.jsp,现在存在两个匹配模式:
/**/*.jsp
和/project/dir/*.jsp
,那么会根据/project/dir/*.jsp
来匹配.
- 遵循最长匹配原则,若URL请求了/project/dir/file.jsp,现在存在两个匹配模式:
- method:用于指定请求的方式。常用的属性值是
RequestMethod.POST
和RequestMethod.GET
- params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样
params = {"accountName"}
,表示请求参数必须有accountNameparams = {"moeny!100"}
,表示请求参数中 money不能是100
- headers:用于指定限制请求消息头的条件 同样是支持简单的表达式
- value:用于指定请求的 URL。它和 path 属性的作用是一样的。能使用通配符
- 使用的说明:
@PathVaribale
注解 详解:-
作用:绑定URL占位符,支持RESTFULE风格URL
- 例如:url中有
/delete/{id}
,{id}
就是占位符 - RESTFULE风格URL的特点:
- 资源
Resources
: 通过一个URI来指定一个具体的资源 - 表现层
Representation
: 把资源具体呈现出来的形式 - 状态转化
State Transfer
: 通过HTTP请求方法来决定状态转化
- 资源
- 例如:url中有
-
属性:
- value或者是叫name:用于指定url中的占位符名称
-
作用的位置:
@Target(ElementType.PARAMETER)
// 进行访问时会将url中的id传入到id 参数上 @RequestMapping(path="/hello/{id}") public String sayHello(@PathVariable(value="id") String id) { System.out.println(id); return "success"; }
-
@RequestParam
注解- 作用:把请求中的指定名称的参数传递给控制器中的形参赋值
- 属性:
- value或者是叫name:请求参数中的名称
- required:请求参数中是否必须提供此参数,默认值是true,必须提供
- 作用的位置:
@Target(ElementType.PARAMETER)
@RequestMapping(path="/hello") public String sayHello(@RequestParam(value="username",required=false)String name) { System.out.println("aaaa"); System.out.println(name); return "success"; }
@RequestBody
注解-
作用:用于获取请求体的内容(注意:get方法不可以使用次注解 原因就是GET方式没有请求体)
-
属性:
- required:是否必须有请求体,默认值是true
-
作用的位置:
@Target(ElementType.PARAMETER)
@RequestMapping(path="/hello") public String sayHello(@RequestBody String body) { System.out.println(body); return "success"; }
-
@RequestHeader
注解- 作用:获取指定请求头的值
- 属性:
- value或者是叫name:请求头的名称
- 作用的位置:
@Target(ElementType.PARAMETER)
@RequestMapping(path="/hello") public String sayHello(@RequestHeader(value="Accept") String header) { System.out.println(header); return "success"; }
@CookieValue
注解- 作用:用于获取指定cookie的名称的值
- 属性:
- value或者是叫name:cookie的名称
- 作用的位置:
@Target(ElementType.PARAMETER)
@ModelAttribute
注解- 作用 被注解的方法会在其他的方法之前执行就像是@Before注解
- 出现在方法上:表示当前方法会在控制器方法执行前线执行。
- 出现在参数上:获取指定的数据给参数赋值。
- 应用场景
- 当提交表单数据不是完整的实体数据时,保证没有提交的字段使用数据库原来的数据。
- 出现的位置:
@Target({ElementType.PARAMETER, ElementType.METHOD})
- 作用 被注解的方法会在其他的方法之前执行就像是@Before注解
@SessionAttributes
注解- 作用:用于多次执行控制器方法间的参数共享 就是将controller返回的数据保存到session中 要是获取session 使用的是
@SessionAttribute
注解 就像是@CookieValue
注解一样 - 属性:
- String[] value或者是叫names:指定存入属性的名称
- Class<?>[] types:用于指定参数的类型
- 出现的位置:
@Target({ElementType.TYPE})
- 作用:用于多次执行控制器方法间的参数共享 就是将controller返回的数据保存到session中 要是获取session 使用的是