目录
1、SpringMVC概述
1.1 SpringMVC概念
1.2 SpringMVC原理
1.3 SpringMVC优势
2、MVC模式回顾
3、入门程序
3.1 创建web的maven工程
3.2 pom.xml文件添加依赖和插件
3.3 创建Spring和SpringMVC的配置文件
3.3.1 创建Spring配置文件applicationContext.xml文件
3.3.2 创建SpringMVC的配置文件springmvc.xml
3.4 在web.xml中进行Spring和SpringMVC配置
3.5 创建控制器
3.6 配置视图解析器
3.7 编写index.jsp页面
3.8 测试
3.9 启动web容器后web.xml中发生了什么
4、SpringMVC工作流程
4.1 工作流程分析
4.2 SpringMVC组件
5 @RequestMapping 注解
5.1@RequestMapping出现的位置
5.2 指定请求的提交方式
5.3 补充url-pattern解析(*.do和/区别)
5.3.1 url-pattern解析
5.3.2 静态资源访问
6、处理器方法接收请求参数
6.1 直接使用方法的参数逐个接收
6.2 使用对象接收多个参数
6.3 请求参数和方法名称的参数不一致
6.4 使用HttpServletRequest 对象获取参数
6.5 直接使用URL地址传参
6.6 获取日期类型的参数
6.7 获取数组类型的参数
6.8 获取集合类型的参数
7、请求参数中文乱码
7.1 乱码解决方案
7.2 解决方案原理
7、处理器方法的返回值
7.1 返回ModelAndView
7.2 返回String
7.3 返回对象类型(Integer、String、Map、List或自定义)
7.3.1 返回基础类型
7.3.2 返回自定义对象类型
7.3.3 返回集合List
7.3.4 返回集合Map
7.4 无返回值 void-了解
8、页面导航的方式
8.1 转发到一个jsp页面
8.1.1 字符串方式转发
8.1.2 ModelAndView转发
8.2 重定向到一个jsp页面
8.2.1 字符串方式重定向
8.2.2 ModelAndView重定向方式
8.3 重定向或者转发到控制器
9、异常处理
9.1@ExceptionHandler 注解
9.2 实现步骤
9.3优化
10、拦截器
10.1 自定义拦截器
10.2 配置拦截器
11、文件上传和下载
11.1 文件上传
11.2 文件下载
12、RESTful风格
12.1 REST概念
12.2 RESTful概念
12.3 RESTful风格的API设计/URL设计
12.3.1 动词+宾语
12.4 HTTP状态码
12.4.1 状态码2xx
12.4.2 状态码3xx
12.4.4 状态码5xx
12.5 服务器响应
12.6 案例
12.6.1RESTful风格的查询
12.6.2RESTful风格的添加
12.6.3 RESTful风格的更新
12.6.4RESTful风格的删除
12.6.5 RESTful风格的更新和删除遇到的问题
12.7 自己封装响应结果
1、SpringMVC概述
1.1 SpringMVC概念
SpringMVC
也叫
Spring web mvc
。是
Spring
内置的一个
MVC
框架,在
Spring3.0
后发布。
SpringMVC 框架解决了WEB
开发中常见的问题
(
参数接收、文件上传、表单验证等等
)
,而且使用简单,与
Spring
无缝集成。支持 RESTful
风格的
URL
请求。采用了松散耦合可插拔组件结构,比其他
MVC
框架更具扩展性和灵活性。
1.2 SpringMVC原理
在没有使用SpringMVC之前我们都是使用
Servlet
在做
Web
开发。但是使用
Servlet
开发在接收请求参数, 数据共享,页面跳转等操作相对比较复杂。servlet
是
java
进行
web
开发的标准,既然
springMVC
是对 servlet的封装,那么很显然
SpringMVC
底层就是
Servlet
,
SpringMVC
就是对
Servlet
进行深层次的封
装。
1.3 SpringMVC优势
1
、基于
MVC
架构,功能分工明确。解决页面代码和后台代码的分离。
2
、简单易用。
SpringMVC
也是轻量级,
jar
很小。不依赖特定接口和类就可开发一个注解的
SpringMVC
项目。
3
、是
Spring框架一
部 分 ,能够使用
Spring
的
IoC
和
AOP ,
方 便 整 合
MyBatis,Hiberate,JPA
等
其他框架。
4
、
springMVC
的注解强大易用。
2、MVC模式回顾
模型
1
:
jsp+javabean
模型
---
在
jsp
页面中嵌入大量的
java
代码
模型
2
:
jsp+servlet+javabean
模型
---jsp
页面将请求发送给
servlet
,由
servlet
调用
javabean
,再
由
servlet
将制定
jsp
页面响应给用户。
模型
2
一般就是现在的
MVC
模式,也是我们一直使用的。
Model-View-Controller:模型--视图--控制器
Model
: 模型层
javaBean
负责数据访问和业务处理
dao service pojo
View
:
视图
JSP
技术
负责收集和展示数据
Controller
: 控制器
servlet
技术
中间调度
控制器的工作:
1
、接受客户端的请求(包括请求中携带的数据)
2
、处理请求:调用后台的模型层中的业务逻辑
3
、页面导航:处理完毕给出响应:
JSP
页面
3、入门程序
3.1 创建web的maven工程
创建项目并补齐目录结构
3.2 pom.xml文件添加依赖和插件
3.3 创建Spring和SpringMVC的配置文件
我们一般将除了
Controller
之外的所有
Bean
注册到
Spring
容器中,而将
Controller
注册到
SpringMVC
容器中。所以我们在
resources
目录下添加
applicationContext.xml
作为
spring
的配置, 添加springmvc.xml
作为
springmvc
的配置文件。
3.3.1 创建Spring配置文件applicationContext.xml文件
spring作为IOC容器创建管理对象,在xml中需要配置组件扫描器进行包扫描,找到@Component、@Repository、@Service、@Controller注解的类进行对象的创建,因此需要添加context约束。一般将除了 Controller 之外的所有 Bean 注册到 Spring 容器中
3.3.2 创建SpringMVC的配置文件springmvc.xml
一般将
Controller
注册到SpringMVC 容器中,所以也需要context约束(命名空间),需要组件扫描器进行包扫描,另外还需要添加mvc约束。
3.4 在web.xml中进行Spring和SpringMVC配置
web服务器启动后,读了web.xml后就会去启动Spring容器和SpringMVC容器,创建各自对象。
<!--spring的配置-->
<!--contextConfigLocation:表示用于加载 Bean的配置文件-->
<!--指定spring配置文件的位置 ,这个配置文件也有一些默认规则,它的配置文件名默认就叫 applicationContext.xml , 如果将这个配置文件放在 WEB-INF 目录下,那么这里就可以不用 指定配置文件位置, 只需要指定监听器就可以。
这段配置是 Spring 集成 Web 环境的通用配置;一般用于加载除控制器层的 Bean(如 dao、service 等),以便于与其他任何Web框架集成。
<!--SpringMVC的配置-->
<!--
前端控制器:所有的请求都会经过此控制器,然后通过此控制器分发到各个分控制器.
前端控制器本质上还是一个Servlet,因为SpringMVC底层就是使用Servlet编写的
-->
<!-- 创建前端控制器的时候读取springmvc配置文件启动ioc容器 -->
load-on-startup <!-- Tomcat启动就创建此对象(值>0) -->
<!-- 配置拦截路径url,所有以.do结尾的请求都会被前端控制器拦截处理 -->
SpringMVC的配置解析:
1、servlet-class:前端控制器的完全限定名,在spring-webmvc-5.2.5.RELEASE.jar包中的
org.springframework.web.servlet下
2、load-on-startup:标记是否在Web服务器(这里是Tomcat)启动时会创建这个 Servlet 实
例,即是否在 Web 服务器启动时调用执行该 Servlet 的 init()方法,而不是在真正访问时才创建。
要求取值是整数。 值大于0:表示容器在启动时就加载并初始化这个 servlet,数值越小,Servlet的优先级就越高,其被创建的也就越早值小于0或者省略:表示该 Servlet 在真正被使用时才会去创建。 值相同:容器会自己选择创建顺序
3、url-pattern:可以写为 / ,可以写为*.do 、*.action、*.mvc等形式,此处先写*.do,以后
介绍不同写法的区别。
4、init-param:表示了springmvc配置文件的名称和位置。如果没有配置,默认在项目的WEB-INF 目录下找名称为 Servlet 名称-servlet.xml 的配置文件。
如果没有配置,启用默认的规则:即如果配置文件放在 webapp/WEB-INF/ 目录下,并且配置文
件的名字等于 DispatcherServlet 的名字+ -servlet(即这里的配置文件路径是 webapp/WEB-
INF/dispatcherServlet-servlet.xml),如果是这样的话,可以不用添加 init-param 参数,即不
用手动配置 springmvc 的配置文件,框架会自动加载。
而一般情况下,配置文件是放在类路径下,即 resources 目录下。所以,在注册前端控制器时,
还需要设置查找 SpringMVC 配置文件路径。
其中contextConfigLocation属性:来自DispatcherServlet的父类FrameworkServlet,
该类中的contextConfigLocation属性用来配置springmvc的路径和名称。
3.5 创建控制器
3.6 配置视图解析器
在
springmvc.xml
配置文件中添加视图解析器的配置
<!--annotation-driven是一种简写形式,也可以手动配置替代这种简写形式,简写形式可以让初学者快速应用默认配置方案。
该注解会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter
两个bean,是springMVC为@Controller分发用户请求所必须的,解决了@Controller注解使用的前提配置。同时它还提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB,读写JSON的支持(Jackson)。我们处理响应ajax请求时,就使用到了对json 的支持(配置之后,在加入了jackson的core和mapper包之后,不写配置文件也能自动转换成json)。
-->
3.7 编写index.jsp页面
webapp
文件夹下面创建文件夹
jsp,
然后
jsp
文件夹中添加
index.jsp
页面
3.8 测试
在maven中使用tomcat插件无法访问的话,就直接使用本地的tomcat
1 ,点击 Run---EDit Confifigurations...
2. 点击左侧 “+” 号,找到 Tomcat Server---Local (若是没有找到 Tomcat Server 可以点击最后一行 34 items more )
3. 在 Tomcat Server -> local-> Server -> Application server 项目下,点击 Confifiguration ,找到本地 Tomcat 服务 器,再点击 OK 按钮。
3.9 启动web容器后web.xml中发生了什么
ContextLoaderListener
初始化的上下文加载的
Bean
是对于整个应用程序共享的,不管是使用什
么表现层技术,一般如
dao
层、
service
层 的
bean
;
DispatcherServlet
初始化的上下文加载的
bean
是只对
Spring Web MVC
有效的
bean
,如
Controller
、
HandlerMapping
、
HandlerAdapter
等等,该初始化上下文应该只加载
Web
相关组
件
1.Spring
容器中不能扫描所有
Bean
嘛?
不可以。当用户发送的请求达到服务端后,会寻找前端控制器
DispatcherServlet
去处理,只在
SpringMVC
容器中找,所以
Controller
必须在
SpringMVC
容器中扫描。
2.SpringMVC
容器中可以扫描所有
Bean
嘛?
可以。可以在
SpringMVC
容器中扫描所有
Bean
。但是实际开发中一般不会这么做,原因如下:
(
1
)为了方便配置文件的管理(两个xml分别管理spring和springmvc的配置)
(
2
)未来在SSM
组合中,要写的配置内容很多,一般都会根据功能分开编写
4、SpringMVC工作流程
4.1 工作流程分析
(
1
)用户通过浏览器发送请求到前端控制器
DispatcherServlet
。
(
2
)前端控制器直接将请求转给处理器映射器
HandleMapping
。
(
3
)处理器映射器
HandleMapping
会根据请求,找到负责处理该请求的处理器,并将其封装为处理器执行链HandlerExecutionChina后返回给前端控制器
DispatcherServlet
。
(
4
)前端控制器
DispatcherServlet
根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器HandlerAdaptor
。
(
5
)处理器适配器
HandlerAdaptor
调用执行处理器
Controller
。
(
6
)处理器
Controller
将处理结果及要跳转的视图封装到一个对象
ModelAndView
中,并将其返回给处理器适配器HandlerAdaptor
。
(
7
)处理器适配器直接将结果返回给前端控制器
DispatcherServlet
。
(
8
)前端控制器调用视图解析器,将
ModelAndView
中的视图名称封装为视图对象。
(
9
)视图解析器ViewResolver[rɪˈzɒlvə]
将封装的视图View
对象返回前端控制器
DispatcherServlet.
(
10
)前端控制器
DispatcherServlet
调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象。
(
11
)前端控制器响应浏览器。
4.2 SpringMVC组件
1.DispatcherServlet
:前端控制器
,
也称为中央控制器或者核心控制器。
用户请求的入口控制器,它就相当于 mvc 模式中的c,DispatcherServlet 是整个流程控制的中心,相当于是 SpringMVC 的大脑,由它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。SpringMVC框架提供的该核心控制器需要我们在web.xml文件中配置。
2.HandlerMapping
:处理器映射器
HandlerMapping
也是控制器,派发请求的控制器。我们不需要自己控制该类,但是他是
springmvc
运转历程中的重要的一个控制器。 HandlerMapping
负责根据用户请求找到 Handler 即处理器
(也就是我们所说的 Controller
),
SpringMVC
提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等,在实际开发中,我们常用的方式是注解方式。
3.Handler
:处理器
Handler
是继
DispatcherServlet
前端控制器的后端控制器,
在DispatcherServlet 的控制下Handler 对具体的用户请求进行处理
。由于 Handler
涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发 Handler
。(这里所说的
Handler
就是指我们的
Controller
)
4.HandlerAdapter
:处理器适配器
通过 HandlerAdapter 对处理器进行执行
,这是适配器模式的应用,通过扩展处理器适配器,支持更多类型的处理器,
调用处理器传递参数等工作。
5.ViewResolver
:视图解析器
ViewResolver
负责将处理结果生成
View
视图,
ViewResolver
首先根据逻辑视图名解析成物理视图名称,即具体的页面地址,再生成 View
视图对象,最后对
View
进行渲染将处理结果通过页面展示给用户。 SpringMVC
框架提供了很多的
View
视图类型,包括:
jstlView
、
freemarkerView
、
pdfView
等。 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面
5 @RequestMapping 注解
5.1@RequestMapping出现的位置
@RequestMapping
注解定义了处理器对于请求的映射规则。该注解可以定义在类上,也可以定义在方法上,但是含义不同。
一个
@Controller
所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法所匹配的
URI 是不同的。这些不同的 URI 被指定在方法之上的注解@RequestMapping 的
value
属性中。但若
这些请求具有相同的 URI 部分,则这些相同的 URI,可以被抽取到注解在类之上的RequestMapping 的 value 属性中
。此时的这个 URI
表示模块的名称。
URI
的请求是相对于
Web
的根目录。在类的级别上的注解会将一个特定请求或者请求模式映射到一个控制器之上。之后你还可以另外添加方法级别的注解来进一步指定到处理方法的映射关系
将处理器方法中相同部分的映射路径抽取到注解在类上的RequestMapping中
5.2 指定请求的提交方式
@RequestMapping
的
method
属性,用来对被注解方法所处理请求的提交方式进行限制,即只有满足method 属性指定的提交方式的请求,才会执行该被注解方法。
Method
属性的取值为
RequestMethod
枚举常量。常用的为
RequestMethod.GET
与
RequestMethod.POST
,分别表示提交方式的匹配规则为
GET
与
POST
提交。
常用的提交方式
5.3 补充url-pattern解析(*.do和/区别)
对于.do,当用户发送请求后,前端控制器只负责后缀中含有.do的请求的处理,对于/,所有请求都会由前端控制器处理,那么访问静态资源的时候(css,js,图片)请求也会当做一个普通的controller请求,前端控制器会调用处理器映射器,查找相应的处理器,就找不到,所有的静态资源在这种情况下都会报04错误。
5.3.1 url-pattern解析
在web.xml配置SpringMVC的前端控制器时有这个节点。这个节点中的值一般有两种写法:
在
index.jsp
页面添加图片,如果节点中的值为
*.do,
图片可以正常访问,但是如果为
/
就不能访问。
1
、项目中添加图片,同时修改
index.jsp
页面
2
、修改
web.xml
5.3.2 静态资源访问
如果url-pattern的值配置为/
后,静态资源可以通过以下两种方法解决。
5.3.2.1
使用
< mvc:default-servlet-handler/ >标签
<!--声 明 了 <mvc:default-servlet-handler /> 后 ,springmvc框架会在容器中创建
DefaultServletHttpRequestHandler默认处理器对象。该对象会对所有进入 DispatcherServlet的URL 进行检查。如果发现是静态资源请求,就
将该请求转由Web应用服务器默认的Servlet 处理
。
一般的服务器都有默认的 Servlet。例如咱们使用的Tomcat服务器中,有一个专门用于处理静态资源访问的 Servlet 名叫 DefaultServlet。其<servlet-name/>为default。可以处理各种静态资源访问
请求。该Servlet注册在 Tomcat 服务器的 web.xml 中。在 Tomcat安装目录/conf/web.xml。-->
静态资源的访问就不会被前端控制器拦截处理,而是交由web容器默认的servlet处理
5.3.2.2
使用
< mvc:resources/ > 标签 记住
在
springmvc
的配置文件中添加如下内容:
location: 表示静态资源所在目录。当然,目录不要使用/WEB-INF/及其子目录。
mapping: 表示对该资源的请求。注意,后面是两个星号**。
在
Spring3.0
版本后,
Spring
定义了专门用于处理静态资源访问请求的处理器
ResourceHttpRequestHandler
。并且添加了
< mvc:resources/ >
标签,专门用于解决静态资源无法访问问题。
6、处理器方法接收请求参数
处理器方法就是Controller中的定义的方法
处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值
.
所以我们可以在方法内直接使用。以下是这四类参
HttpServletRequest
HttpServletResponse
HttpSession
请求中所携带的请求参数
注意:如果请求后,服务器这边使用对象接收时,有个别的参数没有值,可能是参数类型和实体类属性不一致,另外需要set、get方法。
准备工作:创建新的控制器
ParamController.java
和前端页面
param.jsp
页面,url-partern设置/
6.1 直接使用方法的参数逐个接收
form表单提交请求
处理器方法
先访问http://localhost:8080/param/test,该处理器方法向浏览器返回param.jsp页面,如下
控制台
6.2 使用对象接收多个参数
注意,实体类中要有set、get方法,还是需要set的给对象赋值的。
form表单
处理器方法
实体类Team
测试
控制台
6.3 请求参数和方法名称的参数不一致
表单
处理器方法
测试
6.4 使用HttpServletRequest 对象获取参数
表单
处理器方法
测试
6.5 直接使用URL地址传参
地址栏
处理器方法
测试
6.6 获取日期类型的参数
将Team实体类中添加createTime属性,并添加@DateTimeFormat注解,还要添加该属性的set、get方法
表单
控制器方法
测试
6.7 获取数组类型的参数
表单
处理器方法
测试
6.8 获取集合类型的参数
1.简单类型集合(String/double..)
表单
处理器方法
测试
2.获取集合类型的参数: 对象集合不支持直接获取,必须封装在类中,作为一个属性操作
创建QueryVO类,定义一个List<Team>teamList集合属性,在处理器方法参数中使用QueryVO对象vo接收请求参数,input组件的name是teamList[0].teamId,表示向vo对象的属性teamList中的第1个Team对象的teamId赋值为输入框内容,以此类推。
表单
处理器方法
测试
7、请求参数中文乱码
在没有使用Springmvc前,处理请求参数中文乱码都是通过过滤拦截后统一设置编码,request.setCharacterEncoding("字符集")。
对于上面所接收的请求参数,若含有中文,则会出现中文乱码问题。
Spring
对于请求参数中的中文乱码问题,给出了专门的
字符集过滤器CharacterEncodingFilter 类
。如图所示。
7.1 乱码解决方案
在
web.xml
中注册字符集过滤器,推荐将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的。
在
web.xml
配置文件直接注册字符集
强制request/response使用字符集encoding,是指当你在处理器方法中通过setCharacterEncoding()
设置字符集,但xml配置这边强制使用指定的encoding。
测试:
7.2 解决方案原理
7、处理器方法的返回值
使用
@Controller
注解的处理器的处理器方法,其返回值常用的有四种类型
1. ModelAndView
2. String
3.
返回自定义类型对象
4.
无返回值
void
根据实际的业务选择不同的返回值
创建控制器
ResultController.java
在
jsp
文件夹中添加页面
result.jsp
7.1 返回ModelAndView
如果是前后端不分的开发,大部分情况下,我们返回 ModelAndView,即数据模型+视图.
Model 中,放我们的数据,然后在 ModelAndView 中指定视图名称。
当处理器方法处理完后,需要跳转到其它资源的同时传递数据,选择返回
ModelAndView
比较好,但是如果只是需要传递数据或者跳转之一,这个时候ModelAndView
就不是最优选择。
控制器
ResultController.java
中添加方法:
result.jsp
页面中添加如下内容:
测试
7.2 返回String
上一种方式中的
ModelAndView
可以拆分为两部分,
Model
和
View
,在
SpringMVC
中,
Model
我们可以直接在参数中指定,然后返回值是逻辑视图名
,视图解析器解析可以将逻辑视图名称转换为物理视图地址。
视图解析器通过内部资源视图解析器InternalResourceViewResolver将字符串与解析器中的prefix和suffix结合形成要跳转的额URI。
控制器ResultController.java中添加方法:
result.jsp页面中添加如下内容:
测试
7.3 返回对象类型(Integer、String、Map、List或自定义)
处理器方法返回
Object
对象类型时,可是
Integer
、
String
、
Map
、
List
,也可是自定义的对象类型。
但是无论是什么类型,都不是作为逻辑视图出现,而是直接作为数据返回然后展示的
一般前端发起Ajax
请求的时候都会使用直接返回对象的形式。
返回对象的时候,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。
pom.xml文件中添加两个依赖
7.3.1 返回基础类型
7.3.2 返回自定义对象类型
处理器方法
测试
使用ajax向test033()方法获取返回值自定义对象
当点击"ajax请求"按钮,
7.3.3 返回集合List
ajax请求
处理器方法
测试
7.3.4 返回集合Map
ajax请求
处理器方法
给实体类createTime属性添加注解
测试
7.4 无返回值 void-了解
方法的返回值为
void
,并不一定真的没有返回值,我们可以通过其他方式给前端返回。实际上,这种方式也可以理解为 Servlet
中的的处理方案
通过 HttpServletRequest 做服务端跳转
通过 HttpServletResponse 做服务端重定向
通过response.getWriter向浏览器写入字符串(注意乱码处理)
通过response.setHeader另一种重定向
8、页面导航的方式
页面导航分为两种:1、转发 2、重定向
springMVC有以下两种方式实现页面的转发或重定向:
1
、返回字符串
2
、使用
ModelAndView
在
SpringMVC
中两种导航进行页面导航的时候使用不同的前缀指定转发还是重定向,使用前缀后,视图解析器中前后缀就实现了,此时必须自己编写绝对路径。
前缀:
转发: forward:url 不写前缀,
默认是转发
重定向: redirect:url
使用ModelAndView方式的重定向,解决了request中数据丢失问题,会把存储在request作用域中的值以参数形式追加到地址栏URL后面。
准备工作:创建一个新的控制器
NavigationController.java
:
8.1 转发到一个jsp页面
8.1.1 字符串方式转发
8.1.2 ModelAndView转发
8.2 重定向到一个jsp页面
8.2.1 字符串方式重定向
8.2.2 ModelAndView重定向方式
8.3 重定向或者转发到控制器
9、异常处理
SpringMVC框架常用@ExceptionHandler 注解处理异常。
9.1@ExceptionHandler 注解
@ExceptionHandler
可以将一个方法指定为异常处理方法。
被注解的方法,其返回值可以是
ModelAndView
、
String
,或
void
,方法名随意,方法参数可以是
Exception
及其子类对象、
HttpServletRequest
、
HttpServletResponse
等。系统会自动为这些方法参数赋值。
对于异常处理注解的用法,也可以直接将异常处理方法注解于
Controller
之中
9.2 实现步骤
TeamException异常类
TeamIdException异常类
TeamNameException异常类 出现异常需要跳转到异常页面jsp
error.jsp
idError.jsp
nameError.jsp
异常处理的控制器
测试
9.3优化
一般将异常处理方法专门定义在一个类中,作为全局的异常处理类。
使用注解
@ControllerAdvice
,就是
“
控制器增强
”
,是给控制器对象增强功能的。使用
@ControllerAdvice
修饰的类中可以使用
@ExceptionHandler
。
当使用
@RequestMapping
注解修饰的方法抛出异常时,会执行
@ControllerAdvice
修饰的类中的异常处理方法。
@ControllerAdvice
注解所在的类需要进行包扫描,否则无法创建对象。
全局异常处理类(控制器)
实际开发中,对比较重要的字段,都是要求自定义异常去处理的
10、拦截器
10.0.什么是拦截器,拦截时间点在什么位置
SpringMVC
中的 拦截器(
Interceptor
)是非常重要的,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。
拦截的时间点在
“
处理器映射器
HandlerMapping
根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器HandlerAdaptor
执行处理器之前
”
。
在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链
HandlerExecutionChain
,并返回给了前端控制器。
10.1 自定义拦截器
自定义拦截器,需要实现 HandlerInterceptor 接口。而该接口中含有三个方法:
preHandle(request,response, Object handler)
该方法
在处理器方法执行之前执行
。其返回值为
boolean
,若为
true
,则紧接着会执行处理器方法,且会将afterCompletion()
方法放入到一个专门的方法栈中等待执行。
postHandle
(request,response, Object handler,modelAndView)
该方法
在处理器方法执行之后执行
。处理器方法若最终未被执行,则该方法不会执行。由于该方法是在处理器方法执行完后执行,且该方法参数中包含 ModelAndView
,所以该方法
可以修改处理器方法的处理结果数据,且可以修改跳转方向
afterCompletion
(request,response, Object handler, Exception ex)
:
当
preHandle()
方法返回
true
时,会将该方法放到专门的方法栈中,等到对请求进行响应的所工作完成之后才执行该方法。即该方法是在前端控制器渲染(数据填充)了响应页面之后执行的,此时对ModelAndView再操作也对响应无济于事。
第一个拦截器
第二个拦截器
10.2 配置拦截器
在SpringMVC中配置拦截器
测试:随便访问一个处理器方法
11、文件上传和下载
Spring MVC
为文件上传提供了直接支持
,
这种支持是通过即插即用的
MultipartResolver
实现。
Spring
中有一个
MultipartResolver
的实现类
:CommonsMultipartResolver
。
在
SpringMVC
上下文中默认没有装配
MultipartResolver,
因此默认情况下不能处理文件上传工作。
如果想使用
Spring
的文件上传功能
,
则需要先在上下文中配置
MultipartResolver
。
[mao] [rɪˈzɒlvə]多组件处理器
11.1 文件上传
(1)添加依赖
(2)springmvc.xml
文件中配置
MultipartResolver:
(3)fileHandle.jsp页面表单
(4)文件上传控制器(注意要创建文件夹保存上传之后的文件)
优化:如果需要限定文件的大小和类型:
在springmvc.xml中限定文件大小
定义文件拦截器,只有.png和.jpg文件类型放行
在springmvc.xml中添加拦截器
若出现非指定后缀文件,跳转到异常页面fileTypeError.jsp
11.2 文件下载
(1
)前端页面
(2)配置处理类方法
测试
12、RESTful风格
12.1 REST概念
12.2 RESTful概念
REST(英文:Representational State Transfer,简称REST,意思:表述性状态转换,描述了一个架构样式的网络系统,比如web应用)。
它是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件,它主要用于
客
户端和服务端
交互类的软件。基于这个风格设计的软件可以更简介,更有层次,更易于实现缓存等机制.
它本身并没有什么使用性,其
核心价值在于如何设计出符合REST风格的网络接口
REST
指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就
RESTful
。
RESTful
的特性:
资源
(Resources)
:互联网所有的事物都可以被抽象为资源 。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI
(统一资源定位符)指向它,每种资源对应一个特性的URI
。要获取这个资源,访问它的
URI
就可以,因此
URI
即为每一个资源的独一无二的识别符。
表现层
(Representation)
:把资源具体呈现出来的形式,叫做它的表现层
(Representation)
。比如,文本可以用txt
格式表现,也可以用
HTML
格式、
XML
格式、
JSON
格式表现,甚至可以采用二进制格式。
状态转换
(State Transfer)
:每发出一个请求,就代表了客户端和服务器的一次交互过程。
HTTP
协议, 是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某 种手段,让服务器端发生“
状态转换
”(State Transfer)
。而这种转换是建立在表现层之上的,所以就是
“
表 现层状态转换”
。
具体来说就是
HTTP
协议里面,四个表示操作方式的动词:
GET
、
POST
、
PUT
、
DELETE
。他们分别对应四种基本操作:GET
用来
获取
资源,
POST
用来
新建
资源,
PUT
用来
更新
资源,
DELETE
用来
删除
资源。
http://localhost:8080/getExpress.do?id=1
http://localhost:8080/saveExpress.do
http://localhost:8080/updateExpress.do
http://localhost:8080/deleteExpress.do?id=1
原来用的方式当然没有问题,但是如果有更简洁的方式就更好了,此时就是
RESTful
风格。
GET /expresses #
查询所有的快递信息列表
GET /express/1006 #
查询一个快递信息
POST /express #
新建一个快递信息
PUT /express/1006 #更新一个快递信息(
全部更新
)
PATCH /express/1006 #更新一个快递信息(部分更新)
DELETE /express/1006 #删除一个快递信息
12.3 RESTful风格的API设计/URL设计
12.3.1 动词+宾语
RESTful 的核心思想就是客户端的用户发出的数据操作指令都是"动词 + 宾语"的结构
。例如
GET
/expresses
这个命令,
GET
是动词,
/expresses
是宾语。
动词通常就是五种
HTTP
方法,对应
CRUD
操作。
GET
:读取(
Read
)
POST
:新建(
Create
)
PUT
:更新(
Update
)
PATCH
:更新(
Update
),通常是部分更新
DELETE
:删除(
Delete
)
PS: 1
、根据
HTTP
规范,动词一律大写。
2
、一些代理只支持
POST
和
GET
方法, 为了使用这些有限方法支持
RESTful API
,需要一种办法覆盖http原来的方法。使用订制的
HTTP
头
X-HTTP-Method-Override
来覆盖
POST
方法
.
宾语就是
API
的
URL
,是
HTTP
动词作用的对象。它应该是名词,不能是动词
比如,
/expresses
这个
URL
就是正确的。
以下这些
URL
都是不推荐的,因为带上了动词,不是推荐写法。
/getAllExpresses
/getExpress
/createExpress
/deleteAllExpress
ps:
不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。
12.3.3
避免多级
URL
如果资源有多级分类,不建议写出多级
URL
。例如要获取编号1001球队中1005号队员,有人写:
GET /team/1001/player/1005
这种写法的语义不够明确,所以推荐使用查询字符串做后缀,改写为
GET /team/1001?player=1005
GET /expresses/statu
不推荐
GET /expresses?statu=false
推荐
12.4 HTTP状态码
客户端用户发起每一次请求,服务器都必须给出响应。响应包括 HTTP 状态码和数据两部分。
HTTP 状态码就是一个三位数,分成五个类别。
每一种状态码都有标准的(或者约定的)解释,客户端只需查看状态码,就可以判断出发生了什么情况,所以服务器应该返回尽可能精确的状态码。
五类状态码分别如下:
1xx
:相关信息
2xx
:操作成功
3xx
:重定向
4xx
:客户端错误
5xx
:服务器错误
PS
:
API
不需要
1xx
状态码,所以这个类别直接忽略
12.4.1 状态码2xx
200 状态码表示操作成功,但是不同的方法可以返回更精确的状态码
GET: 200 OK
表示一切正常
POST: 201 Created
表示新的资源已经成功创建
PUT: 200 OK 更新成功
PATCH: 200 OK 更新成功
DELETE: 204 No Content
表示资源已经成功删除
12.4.2 状态码3xx
API
用不到
301
状态码(永久重定向)和
302
状态码(暂时重定向,
307
也是这个含义),因为它们可以由应用级别返回,浏览器会直接跳转,API
级别可以不考虑这两种情况
API
用到的
3xx
状态码,主要是
303 See Other
,表示参考另一个
URL
。它与
302
和
307
的含义一 样,也是"
暂时重定向
"
,区别在于
302
和
307
用于
GET
请求,而
303
用于
POST
、
PUT
和
DELETE
请求。 收到 303
以后,浏览器不会自动跳转,而会让用户自己决定下一步怎么办。
我们只需要关注一下
304
状态码就可以了
304
: Not Modified 客户端使用缓存数据
12.4.3
状态码
4xx
4xx
状态码表示客户端错误。
400
Bad Request
:服务器不理解客户端的请求,未做任何处理。
401
Unauthorized
:用户未提供身份验证凭据,或者没有通过身份验证。
403
Forbidden
:用户通过了身份验证,但是不具有访问资源所需的权限。
404
Not Found
:所请求的资源不存在,或不可用。
405
Method Not Allowed
:用户已经通过身份验证,请求方式不匹配(get/post..)
。
410 Gone
:所请求的资源已从这个地址转移,不再可用。
415 Unsupported Media Type
:客户端要求的返回格式不支持。比如,
API
只能返回
JSON
格式,但是客户端要求返回 XML
格式。
422 Unprocessable Entity
:客户端上传的附件无法处理,导致请求失败。
429 Too Many Requests
:客户端的请求次数超过限额
12.4.4 状态码5xx
5xx
状态码表示服务端错误。一般来说,
API
不会向用户透露服务器的详细信息,所以只要两个状态码就够了。
500
Internal Server Error
:客户端请求有效,服务器处理时发生了意外。
503
Service Unavailable
:服务器无法处理请求,一般用于网站维护状态。
12.5 服务器响应
服务器返回的信息一般不推荐纯文本,而是建议大家选择
JSON
对象,因为这样才能返回标准的结构化数据。
所以,
服务器回应的 HTTP 头的
Content-Type
属性要设为 application/json 。
客户端请求时,也要明确告诉服务器,可以接受 JSON
格式,即
请求的 HTTP 头的
ACCEPT
属性也要设成 application/json 。
当发生错误时候,除了返回状态码外,也要返回错误信息。所以我们可以
自己封装要返回的信息
。
12.6 案例
12.6.1RESTful风格的查询
前端页面restful.jsp
控制器RestfulController.java
12.6.2RESTful风格的添加
ajax
处理器方法
测试
12.6.3 RESTful风格的更新
ajax异步请求
处理器方法
测试
12.6.4RESTful风格的删除
12.6.5 RESTful风格的更新和删除遇到的问题
12.6.5.1
遇到的问题:
在Ajax中,采用Restful风格PUT和DELETE请求传递参数无效,传递到后台的参数值为null
12.6.5.2
产生的原因:
1.
将请求体中的数据,封装成一个
map
2.request.getParameter(key)
会从这个
map
中取值
3.SpringMvc
封装
POJO
对象的时候,会把
POJO
中每个属性的值进行
request.getParamter();
AJAX送PUT或者DELETE请求时,请求体中的数据data通过request.getParamter()拿不到。
Tomcat
检测是
PUT
或
DELETE
就不会封装请求体中数据data为
map
,
POST
形式data才封装为map
总之就是,当是更新或者删除的请求时,tomcat是不会把请求体data数据转为map,后台处理器方法也就无法通过key获取值,若请求体data数据为空,比如删除的时候只需要在url属性中提供id,请求头data中不需数据,不影响程序运行。
12.6.5.3
解决方案:
1
、前端页面中的
ajax
发送请求的时候在data
中加
&_method=”PUT”
或者
&_method=”DELETE”
2. web.xml中配置HiddenHttpMethodFilter
配置的时候多个过滤器需要注意顺序
12.7 自己封装响应结果
AjaxResultVO<T>
处理器返回类型统一改成AjaxResultVO<Team>