第一章 拦截器(重点)
1. 概念
1.1 使用场景
1.1.1 生活中坐地铁的场景
为了提高乘车效率,在乘客进入站台前统一检票:
1.1.2 程序中的校验登录场景
在程序中,使用拦截器在请求到达具体 handler 方法前,统一执行检测。
1.2 拦截器与过滤器的对比
1.2.1 相同点
三要素相同
- 拦截(配置拦截路径):必须先把请求拦住,才能执行后续操作
- 过滤(根据某种规则/业务逻辑进行筛选):拦截器或过滤器存在的意义就是对请求进行统一处理
- 放行(满足规则/筛选条件,就让你访问你想访问的资源):对请求执行了必要操作后,放请求过去,让它访问原本想要访问的资源
1.2.2 不同点
- 工作平台不同
过滤器工作在 Servlet 容器中
拦截器工作在 SpringMVC 的基础上
- 拦截的范围
过滤器:能够拦截到的最大范围是整个 Web 应用
拦截器:能够拦截到的最大范围是整个 SpringMVC 负责的请求(handler方法、view-controller跳转页面、default-servlet-handler处理的静态资源)
- IOC 容器支持
过滤器:想得到 IOC 容器需要调用专门的工具方法,是间接的
拦截器:它自己就在 IOC 容器中,所以可以直接从 IOC 容器中装配组件,也就是可以直接得到 IOC 容器的支持
2. 具体使用
2.1 创建拦截器类
public class Process01Interceptor implements HandlerInterceptor {
Logger logger = LoggerFactory.getLogger(this.getClass());
// 在处理请求的目标 handler 方法前执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.debug("Process01Interceptor preHandle方法");
// 返回true:放行
// 返回false:不放行
return true;
}
// 在目标 handler 方法之后,渲染视图之前
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.debug("Process01Interceptor postHandle方法");
}
// 渲染视图之后执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.debug("Process01Interceptor afterCompletion方法");
}
}
单个拦截器执行顺序:
- preHandle() 方法
- 目标 handler 方法
- postHandle() 方法
- 渲染视图
- afterCompletion() 方法
2.2 注册拦截器
2.2.1 默认拦截全部请求
<!-- 注册拦截器 -->
<mvc:interceptors>
<!-- 直接通过内部 bean 配置的拦截器默认拦截全部请求(SpringMVC 范围内) -->
<bean class="com.akiba.interceptor.Demo01Interceptor"/>
</mvc:interceptors>
2.2.2 配置拦截路径
2.2.2.1 精确匹配
<!-- 具体配置拦截器可以指定拦截的请求地址 -->
<mvc:interceptor>
<!-- 精确匹配 -->
<mvc:mapping path="/hello/sayHello"/>
<bean class="com.akiba.interceptor.Demo01Interceptor"/>
</mvc:interceptor>
2.2.2.2 模糊匹配:匹配单层路径
<mvc:interceptor>
<!-- /*匹配路径中的一层 -->
<mvc:mapping path="/hello/*"/>
<bean class="com.akiba.interceptor.Demo01Interceptor"/>
</mvc:interceptor>
2.2.2.3 模糊匹配:匹配多层路径
<mvc:interceptor>
<!--模糊匹配多级目录-->
<mvc:mapping path="/hello/**"/>
<!--排除-->
<mvc:exclude-mapping path="/hello/sayHello"/>
<bean class="com.akiba.interceptor.Demo01Interceptor"/>
</mvc:interceptor>
2.3 多个拦截器执行顺序
- preHandle()方法:和配置的顺序一样
- 目标handler方法
- postHandle()方法:和配置的顺序相反
- 渲染视图
- afterCompletion()方法:和配置的顺序相反
第二章 类型转换
SpringMVC 将『把请求参数注入到 POJO 对象』这个操作称为『数据绑定』,英文单词是 binding。数据类型的转换和格式化就发生在数据绑定的过程中。 类型转换和格式化是密不可分的两个过程,很多带格式的数据必须明确指定格式之后才可以进行类型转换。最典型的就是日期类型。
1. 自动类型转换
HTTP 协议是一个无类型的协议,我们在服务器端接收到请求参数等形式的数据时,本质上都是字符串类型。请看
javax.servlet.ServletRequest 接口中获取全部请求参数的方法:
public Map<String, String[]> getParameterMap();
而我们在实体类当中需要的类型是非常丰富的。对此,SpringMVC 对基本数据类型提供了自动的类型转换。例如:请求参数传入“100”字符串,我们实体类中需要的是 Integer 类型,那么 SpringMVC 会自动将字符串转换为 Integer 类型注入实体类。
2. 日期和数值类型转换
2.1 通过注解设定数据格式
package com.akiba.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;
import java.util.Date;
/**
* 包名:com.akiba.pojo
*
* @author Akiba
* SpringMVC提供了一些注解,可以让我们进行一些手动类型转换
* 1. DateTimeFormat注解:可以对日期时间类型进行转换
* 2. NumberFormat注解:可以对数值类型进行转换
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date productDate;
@NumberFormat(pattern = "###,###,###.###")
private Double productPrice;
}
2.2 前端表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<form action="/springmvcday0303/hello/saveProduct" method="post">
生产日期:<input type="text" name="productDate" value="1992-10-15 17:15:06" /><br/>
产品价格:<input type="text" name="productPrice" value="111,222,333.444" /><br/>
<button type="submit"&g