第四章SpringMVC第一讲-讲解SpringMVC的基础-学习笔记
前言
2021.1.7 是正式开始学本课的日子,这一课讲解springMVC基础知识。本课为录播课因此学习起来会相对简单,我将跟着课程内容做笔记,并且尽量自己做出演示来验证知识点。
本文和本文内一切内容,均来自我对于开课吧Java企业级分布式架构师010期课程的学习笔记,并在我自身的理解上整理而成。
学习方式为先根据视频理解讲义,再根据讲义做笔记,最后看视频完善笔记的模型进行。
我近年来就是一直在进行在这个框架下搭建的项目的开发,因此有一定的熟练度,但是虽然能完成工作任务却缺少扎实的基础知识,所以特别来学习一下。
学习目标
- 熟悉springmvc六大组件的作用及使用方式(这部分知识点在介绍部分)
- 掌握搭建ssm开发框架(这部分知识点在ssm框架整合部分.本次略改为环境搭建)
- 掌握springmvc对于返回值的处理(这部分知识点在于返回值处理)
- 掌握springmvc对于参数的处理(这部分知识点在于参数处理部分)
- 理解REST和RESTful,掌握springmvc对于RESTful的支持
- 掌握springmvc拦截器的应用(这部分知识点在于拦截器应用)
springmvc框架介绍
基础概念介绍
BS和CS开发架构
- 一种是C/S架构,也就是客户端/服务器。
- 一种是B/S架构,也就是浏览器/服务器。
当前使用java开发的大多数都是web应用,这些web应用几乎全是用B/S架构开发的。
在B/S架构中,应用系统的标准三层架构为:表现层、业务层、持久层。
javaEE制定了一套规范(Servlet),去进行BS结构的处理。
应用系统标准三层结构
表现层
- 指web层。
- 负责接收客户端请求,向客户端响应结果,客户端常用http协议进行请求。
- 包括展示层和控制层:展示层负责结果的展示;控制层负责接收请求。
- 功能依赖于业务层实现。表现层接收到客户端请求一般会调用业务层进行业务处理,并将处理结果给客户端。
- 设计模型为MVC(MVC仅用于三层结构的表现层)。
业务层
- 指service层。
- 负责业务逻辑。
- 被表现层依赖,但是自身功能不依赖表现层
- 在处理业务时可能会依赖持久层,如果要对数据持久化需要保持事务一致性(业务层控制事务)。
持久层
- 指dao层(数据库相关)。
- 负责数据持久化,包括数据层(数据库)和数据访问层。数据层是对数据进行持久化的载体;数据访问层是业务层和持久层交互的接口(业务层通过数据访问层进行数据持久化)。
MVC设计模式
MVC是模型(model)- 视图(view)-控制器(controller)的缩写,是一种用于设计编写Web应用程序表现层的模式。
特色
Model
- 模型包含业务模型和数据模型,业务模型用于处理业务。数据模型用于封装数据。
View
- 指jsp或者html。
- 用于展示数据。
- 通常根据数据模型创建。
Controller
- 是应用程序中处理用户交互的部分。作用一般就是处理程序逻辑的。
SpringMVC介绍
- SpringMVC是一种基于MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFramework(Spring框架)的后续产品,已经融合在Spring Web Flow中。Spring框架提供了构建Web应用程序的全功能MVC模块。
- 使用Spring可插入的MVC架构,从而在使用Spring进行Web开发时,可以选择使用Spring的SpringMVC框架或者集成其他MVC开发框架,如Struts1(一般不用)、Struts2等。
- SpringMVC已经成为目前最主流的MVC框架之一,在Spring3.0版本后,几乎成为最优秀的MVC框架。
- SpringMVC通过注解方式,使得简单的Java类无需任何借口就可成为处理请求的控制器。此外还支持RESTful编程风格的请求。
- SpringMVC全称为Spring Web MVC,在Spring体系中Web模块的一个重要成员。
- SpringMVC目前有最高的市场占有率,并且可以轻易整合Spring。
六大组件介绍(MVC组件和其他三大组件)
图:
- MVC组件为:前端控制器、处理器、视图
- 三大组件为:处理器映射器、处理器适配器、视图解析器
- 环境搭建完毕后通常只需要开发处理器和视图
DispatcherServlet:前端控制器
- 用户的请求首先到达DispatcherServlet前端控制器(相当于MVC模式的C)。
- DispatcherServlet是整个流程控制的中心,由它调用其他组件处理用户的请求
- DispatcherServlet的存在降低了组件间的耦合性。
Handler:处理器
- Handler是继DispatcherServlet前端控制器的后端控制器,在前端控制器控制下对具体的用户请求进行处理。
- 由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
View:视图
- springmvc框架提供了很多view视图类型的支持,包括jstlView、freemarkerView、pdfView等。最常用的就是jsp。
- 一般情况下需要通过页面标签或者页面模板技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
HandlerMapping:处理器映射器
- HandlerMapping根据用户请求找打Handler(处理器)。
- springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式、实现接口方式、注解方式等。
HandlerAdapter:处理器适配器
- 通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
View Resolver:视图解析器
- View Resolver负责将处理结果生成View视图。
- View Resolver 首先根据逻辑视图名解析成物理视图名(具体的网页地址),再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
springmvc入门程序
项目搭建
创建一个maven工程,添加mvc、jstl、servlet-api依赖
创建maven工程的步骤跟最开始的Mybatis方式相同,主要区别在于相关的依赖文件。
本地调试需要准备一个环境,我采用的是Tomcat6.0
参考链接:Java企业级分布式架构师010期课程第一章-第一讲-学习笔记
添加依赖
pom代码:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bao</groupId>
<artifactId>HelloSpringMVC</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>HelloSpringMVC Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>4.3.0.RELEASE</spring.version>
</properties>
<dependencies>
<dependency> <!-- 谷歌推送依赖 -->
<groupId>com.google.firebase</groupId>
<artifactId>firebase-admin</artifactId>
<version>6.10.0</version>
</dependency>
<dependency><!-- 谷歌推送依赖1 -->
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency><!-- 谷歌推送依赖2 -->
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</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>
<!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>HelloSpringMVC</finalName>
</build>
</project>
配置部分
web.xml
<web-app
version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<!--DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" -->
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
springContext.xml(springmvc.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 搜索spring控件 -->
<context:component-scan base-package="com.bao"/>
<!-- 视图页面配置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
编码部分
Controller
处理器开发方式有多种:
- 实现HttpRequestHandler接口
- 实现Controller接口
- 使用注解方式
企业项目中常用注解方式举例如下:
@Controller
public class HelloSpringController {
String message = "Welcome to Spring MVC!";
@RequestMapping("/hello")
public ModelAndView showMessage(@RequestParam(value = "name", required = false, defaultValue = "Spring") String name) {
ModelAndView mv = new ModelAndView("hellospring");//指定视图
System.out.println("test_1");
//向视图中添加所要展示或使用的内容,将在页面中使用
mv.addObject("message", message);
mv.addObject("name", name);
return mv;
}
@RequestMapping("/bey")
public ModelAndView showMessage2(@RequestParam(value = "name", required = false, defaultValue = "Spring") String name) {
System.out.println("test_2");
ModelAndView mv = new ModelAndView("hellospring");//指定视图
//向视图中添加所要展示或使用的内容,将在页面中使用
mv.addObject("message", message+"2");
mv.addObject("name", name);
return mv;
}
}
springmvc对于返回值的处理
可以采用注解修饰或者不使用注解修饰,本次重点介绍注解方式
使用注解修饰
@ResponseBody注解介绍
@ResponseBody注解的作用:
- ResponseBody注解可以针对Controller返回值类型,使用内置的9种HttpMessageConverter进行匹配,找到合适的HttpMessageConverter进行处理.
- HttpMessageConverter处理逻辑分为三步(??):
- 指定HttpServletResponse的ContentType值。
- 将转换之后的数据放到HttpServletResponse对象的响应体返回到页面
@RequestBody注解和@ResponseBody注解的作用相反,@RequestBody注解是处理请求参数的http消息转换的。
常用的HttpMessageConverter
MappingJacksonHttpMessageConverter
- 作用:处理POJO类型返回值
- 默认使用MappingJackson的JSON处理能力,将后台返回的Java对象(POJO类型),转换JSON格式输出到页面
- 将响应体的Content-Type设置为
application/json;charset=utf-8
- 调用
response.getWriter()
方法将JSON格式的字符串写回给调用者
StringHttpMessageConverter
- 作用:处理String类型返回值
- 将响应体的Content-Type设置为
text/plain;charset=utf-8
- 调用
response.getWriter()
方法将String格式的字符串写回给调用者
@ResponseBody示例
JSP示例代码
<h3>演示JSON格式数据参数绑定和返回值处理</h3>
<!-- 使用@ResponseBody注解 -->
<h3>
<a href="${pageContext.request.contextPath}/responsebody/returnString">测试String类型返回值</a>
</h3>
<h3>
<a href="${pageContext.request.contextPath}/responsebody/returnPOJO">测试POJO类型返回值</a>
</h3>
<!-- 使用@RestController注解 -->
<h3>
<a href="${pageContext.request.contextPath}/restController/returnString">测试String类型返回值</a>
</h3>
<h3>
<a href="${pageContext.request.contextPath}/restController/returnPOJO">测试POJO类型返回值</a>
</h3>
Controller代码
方法1:@ResponseBody
@RequestMapping("responsebody")
@Controller
public class ResponseBodyController {
@RequestMapping(
value = "returnString",
produces = "text/plain;charset=utf-8"
)
@ResponseBody
public String returnString() {
return "return some";
}
@RequestMapping(
value = "returnPOJO"
)
@ResponseBody
public Person returnPOJO() {
Person person = new Person();
person.setId(12);
person.setName("bob");
return person;
}
}
方法2:@RestController
@RequestMapping("restcontroller")
@RestController //等效于Controller和Response的结合
public class MyTestRestController {
@RequestMapping(
value = "returnString",
produces = "text/plain;charset=utf-8"
)
public String returnString() {
return "return some";
}
@RequestMapping(
value = "returnPOJO"
)
public Person returnPOJO() {
Person person = new Person();
person.setId(12);
person.setName("bob");
return person;
}
}
springmvc对于参数的处理
参数绑定的概念
参数绑定就是将请求参数串中的value值获取之后,再进行类型转换,然后将类型转换后的值赋给Controller类中方法的形参。这个过程就是参数绑定。
参数绑定需要两步:
- 类型转换(请求中的String类型转换成Controller类中方法的所需的各种数据类型)
- 赋值操作(将转换之后的赋值给Controller方法的形参)
请求参数格式
默认是key/value格式,比如:http://xxx?id=1&type=301
请求参数值的数据类型
以String类型表现的各种值
请求参数值要绑定的目标类型
Controller类中的方法参数,比如简单类型、POJO类型、集合类型等。
SpringMVC内置的参数解析组件
默认内置了24种参数解析组件(ArgumentResolver)
默认支持的参数类型
Controller方法形参中可以随时添加如下类型的参数(Servlet API支持),处理适配器会自动处理并进行赋值。
- HttpServletRequest
通过request对象获取请求信息 - HttpServletResponse
通过response处理响应信息 - HttpSession
通过session对象得到session中存放的对象 - InputStream、OutputStream
- Reader、Writer
- Model/ModelMap
ModelMap继承自LinkedHashMap,Model是一个接口,它们的底层实现都是一个类(BindingAwareModelMap),作用就是向页面传递数据,相当于Request的作用。
参数绑定使用要求
简单类型
直接绑定
http请求参数的【key】和controller方法的【形参名称】一致
注解绑定
应用场景为当http请求参数的【key】和controller方法的【形参名称】不一致时,需要使用@RequestParam注解,也就是使用了注解就一定可以绑定,一定满足要求。
@RequestParam注解属性
- value:参数名字,入参的请求参数名字
- required:判断是否必须要有参数,默认为true,必须需要。在这种情况下如果没有参数将报错:
TTP Status 400 – Required Integer parameter `xxx` is not present
- defaultValue:默认值,表示如果请求中没有同名参数时的默认值
POJO类型
要求表单中【参数名称】和Controller方法中的【POJO形参的属性名称】保持一致。
集合或者数组类型
简单类型数组
通过HTTP请求批量传递简单类型数据的情况,Controller方法中可以使用String[]
或者pojo的String[]
属性接收(两种方法任选其一),但是不能使用List集合接收。
POJO类型集合或数组
批量传递的参数请求,最终要使用List<POJO>
来接收,那么这个List必须放在另一个POJO类中。
RESTful的支持
为方便理解先介绍一下HTTP
HTTP
HTTP协议概述
超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上,是互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。
什么是HTTP:
- HTTP是一个建立在TCP/IP协议基础之上的一个网络协议。
- HTTP协议是属于网络七层结构中最上层(应用层)的协议。
- HTTP协议是一个无状态协议(不会记录每次访问时信息)
- HTTP是一个客户端和服务端请求和应答的标准(TCP)。客户端是终端用户,服务端是网站
什么是URL/URI:
- URI:Uniform Resource Identifier,统一标识符。
相当于网络资源的名称,但是这个名称的表现形式是/开头的路径形式 - URL:Uniform Resource Location,统一资源定位符。
- 区别:URL是URI的子集。
什么是web资源:
通过浏览器可以访问到的所有资源都是web资源,web资源分为静态资源和动态资源:
- 静态资源是不变的,比如HTML、JPG、AVI。
- 动态资源是通过后台程序展示页面数据的,比如Servlet请求。
HTTP的作用是什么:
约束客户端和服务端之间传输web资源时的格式。
HTTP协议版本
目前有1.0版本和1.1版本。
1.1版本的优势在于可以一个连接传输多个web资源。
因此建议使用1.1版本。
HTTP协议组成
HTTP协议由两部分组成:请求协议信息和响应协议信息。
请求协议信息
HTTP请求协议信息由三部分组成:请求行、请求头、请求体
(行头体)
- 请求行(请求首行):请求方法 web资源URI http/1.1
- 请求头:key value方式,不同的请求头配置会告诉服务器端不同的辅助信息。
- 请求体:承载传输的具体数据,不过请求体中的数据表现形式有三种,这三种都是通过form表单的enctpye属性来决定的
响应协议信息
HTTP响应协议信息也是由三部分组成:状态行、响应头、响应体(响应正文)。
(行头体)
- 状态行: 由(协议/版本、数字形式的状态码、状态描述)三部分组成。
- 响应头:以key value的方式展现。
- 响应体:响应正文,包含服务器发给客户端的web资源信息。
get请求和post请求的区别
GET和POST都属于请求行中的8种请求方法中的一种。
区别在于:
- 提交时数据的方式不同
GET通过请求行提交请求的。
POST是通过请求体提交请求参数的。 - 使用场景不同
GET请求的目的是获取到数据,简单点说,就是客户端向服务端要东西
POST请求的目的是提交数据,对应的就是客户端向服务端给东西 - 传递参数的大小不同
GET请求是通过请求行中的URL传递给客户端的。虽然协议对此没有限制,但是浏览器对此有限制。
POST请求是通过请求体传递请求参数的。大小可以远大于GET。
RESTful概述
REST
- REST(Representational State Transfer,意思为:资源表述性状态转化)描述了一个架构样式的网络系统,比如web应用程序。
- 它是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务端角度类的软件。基于这个风格设计的软件可以更简洁,有层次,易于实现缓存等机制。
- 它本身并没有实用性,意义在于提供了一种优秀的设计风格。
RESTful
满足REST设计风格,即满足REST的约束条件和原则的应用程序或设计就是RESTful。
RESTful特性
资源(Resource):
- 网络上的一个实体,或者说是网络上的一个具体信息。
- 它可以是一段文本、一张图片、一首歌曲、一种服务。总之是一个具体从存在。
- 可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI即为每一个资源的独一无二的识别符。
表现层(Representaion):
- 把资源具体呈现出来的形式,叫做表现层
- 例如,文本可以以txt格式表现,也可以用HTML格式、XML格式、JSON格式等形式表现。
状态转化(State Transfer):
每发出一个HTTP请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生”状态转化”。而这种转化是建立在表现层之上的,因此是表现层状态转化。
具体说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应4种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。
如何设计RESTful应用程序的API
- 路径设计:数据库设计完毕后,基本就可以确定有哪些资源要进行操作,相对于的路径也可以设计出来
- 动词设计:也就是针对资源的具体操作类型,由HTTP动词表示,常用的HTTP动词如下:GET、POST、PUT、DELETE
RESTful的示例:
- /account/1 HTTP GET : 得到id = 1的account
- /account/1 HTTP DELETE : 删除id = 1的account
SpringMVC对RESTful的支持
RESTful的URL路径变量
URL-PATTERN:设置为/,方便拦截RESTful请求
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
@PathVariable:可以解析出来URL中模板变量({id})
比如这样的URL:http://localhost:8080/HelloSpringMVC/index/Person/1/LISI
Controller:
@RequestMapping(
"{id}/{name}"
)
@ResponseBody
public Person selectPersonById(@PathVariable Integer id,@PathVariable String name) {
RESTful的CRUD
- @RequestMapping:通过设计method属性值,可以将同一个URL映射到不同的HandlerMethod方法上
- @GetMapping、@PostMapping、@PutMapping、@DeleteMapping注解同@RequestMapping注解的method属性设置。
RESTful的资源表述
RESTful服务中一个重要的特性就是一种资源可以有多种表现形式,在SpringMVC中可以使用ContentNegotiatingManager这个内容管理器开实现这种方式。
内容协商的方式有三种:
- 扩展名:比如.json表示要用JSON格式数据、.xml表示要用XML格式数据
- 请求参数:默认是”format”
- 请求头设置Accept参数:比如设置Accept为application/json表示要JSON格式数据
不过现在RESTful响应的数据一般都是JSON格式,所以一般也不使用内容协商管理器,直接使用@ResponseBody注解将数据按照JSON格式返回。
静态资源访问
如果在DispatchServlet中设置url-pattern为/则必须对静态资源进行访问处理。
之前是这么设置的:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
所以需要在springmvc.xml(我的是springContext.xml)文件中,使用mvc:resources
标签,如下:
<mvc:resources location = "/js/" mapping = "/js/"/>
<mvc:resources location = "/css/" mapping = "/css/"/>
SpringMVC会吧mapping映射到ResourceHttpRequestHandler,这样静态资源在经过DispatcherServlet转发时就可以找到对应的Handler了。
拦截器应用
SpringMVC的拦截器主要是针对特定处理器进行拦截的。
拦截器介绍
- SpringMVC拦截器(Interceptor)实现对每一个请求处理前后进行相关的业务处理,类似与Servlet中的Filter。
- SpringMVC中的Interceptor拦截请求是通过HandlerInterceptor接口来实现的。
在SpringMVC中定义一个Interceptor非常简单,主要有4种方式:
- 实现SpringMVC的HandlerInterceptor接口;
- 继承实现了HandlerInterceptor接口的类,比如SpringMVC已经提供的实现了HandlerInterceptor接口的抽象类HandlerInterceptorAdapter;
- 实现SpringMVC的WebRequestInterceptor接口;
- 继承实现了WebRequestInterceptor的类;
定义拦截器
实现SpringMVC的HandlerInterceptor接口:
public class MyInterceptor implements HandlerInterceptor{
//Handler执行前调用
//应用场景:登录认证、身份授权
//返回值为true表示放行,为false表示不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO 自动生成的方法存根
return false;
}
//进入Handler开始执行,并且在返回ModelAndView之前调用
//应用场景:对ModelAndView对象进行操作,可以把公共模型数据传到前台,可以统一指定试图
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO 自动生成的方法存根
}
//执行完Handler之后调用
//应用场景:统一异常处理、统一日志处理
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO 自动生成的方法存根
}
}
配置拦截器
SpringMVC拦截器是绑定在HandlerMapping中的,即:如果某个HandlerMapping中配置拦截,则该HandlerMapping映射成功的Handler会使用该拦截器。
SpringMVC的全局拦截器配置,其实是把配置的拦截器注入到每个已初始化的HandlerMapping中了。
配置模板:
<!-- 配置全局mapping的拦截器 -->
<mvc:interceptors>
<!-- 公共拦截器可以拦截所有请求,而且可以有多个 -->
<bean class = "com.bao.interceptor.MyInterceptor"></bean>
<bean class = "com.bao.interceptor.MyInterceptor2"></bean>
<!-- 如果有针对特定URL的拦截器则进行如下配置 -->
<mvc:interceptor>
<!-- /**表示所有URL和子URL路径 -->
<mvc:mapping path="/console/**"/>
<!-- 特定的拦截器只能有一个 -->
<bean class = "com.bao.interceptor.MyInterceptor3"></bean>
</mvc:interceptor>
</mvc:interceptors>
多拦截器优先级
当配置了多个拦截器时,在springmvc.xml配置文件中配置的越靠前,优先级越高(从上至下排列优先级)
拦截器应用(以实现登录认证来举例)
需求
拦截器对访问的请求URL进行登录拦截校验。
分析如下:
- 如果请求的URL是公开地址,则放行
- 如果用户session存在,则放行。
- 不放行的情况下都需要跳转到登录页面
登录页面(略)
略,用于进行登录活动
Controller类(略)
用于进行登录活动,和退出登录活动
HandlerInterceptor类
public class LoginInterceptor implements HandlerInterceptor{
//Handler执行前调用
//应用场景:登录认证、身份授权
//返回值为true表示放行,为false表示不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//获取请求的URI
String URI = request.getRequestURI();
System.out.println("URI");
//1.如果URI是公开的地址,采取放行
if(URI.indexOf("login")>-1)
return true;
//2.如果用户session存在,则放行。
String uname = (String)request.getSession().getAttribute("username");
if(uname!=null && !uname.equals(""))
return true;
//其他情况都一律跳转到登录界面
//response.sendRedirect("/login.jsp");
response.sendRedirect("/hellospring.jsp"); //login没做拿个其他页面临时替换一下
return false;
}
//进入Handler开始执行,并且在返回ModelAndView之前调用
//应用场景:对ModelAndView对象进行操作,可以把公共模型数据传到前台,可以统一指定试图
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO 自动生成的方法存根
}
//执行完Handler之后调用
//应用场景:统一异常处理、统一日志处理
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO 自动生成的方法存根
}
}
HandlerInterceptor配置
<!-- 配置全局mapping的拦截器 -->
<mvc:interceptors>
<!-- 公共拦截器可以拦截所有请求,而且可以有多个 -->
<bean class = "com.bao.interceptor.LoginInterceptor"></bean>
<bean class = "com.bao.interceptor.MyInterceptor"></bean>
<bean class = "com.bao.interceptor.MyInterceptor2"></bean>
<!-- 如果有针对特定URL的拦截器则进行如下配置 -->
<mvc:interceptor>
<!-- /**表示所有URL和子URL路径 -->
<mvc:mapping path="/console/**"/>
<!-- 特定的拦截器只能有一个 -->
<bean class = "com.bao.interceptor.MyInterceptor3"></bean>
</mvc:interceptor>
</mvc:interceptors>
结语
2021.1.21日至此基础的SpringMVC知识已经学习完毕,接下来的时间里,我会花几周来巩固第一期学习计划的知识,也顺便过一下年。
本次学习花费了非常久的时间,为了不影响学习热情,部分知识点我选择了跳过,这些跳过的知识点一般不会在日常工作中出现,因此在剩下的巩固时间里我会对于这部分进行补充,具体的会再发布一篇作为SpringMVC了解篇来供后续学习。