一、拦截器
1. 介绍
过滤器的作用是保护请求的服务器资源,在请求资源被执行之前,如果请求地址符合过滤范围,则会先执行过滤器。过滤器的执行时机,是在Servlet之前执行的。 使用了SpringMVC , SpringMVC给出了拦截器来实现单元方法的拦截,拦截器的执行是在DispatcherServlet之后和单元方法之前的,这样我们就可以在单元方法被之前之前对请求进行自定义的拦截处理了。
注意:只有URL匹配到了控制单元,拦截器才能生效。
2. 使用拦截器
2.1 创建拦截器类
在src下创建包,包名随意,并创建java类实现HandlerInterceptor接口。并实现preHandle、postHandle、afterCompletion三个方法。
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor.preHandle");
return fasle;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor.postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor.afterCompletion");
}
}
2.2 配置拦截器
拦截器是由DispatcherServlet接收到请求后来调用的,所有需要将拦截器配置为bean,并且配置其拦截范围。
<!--配置注解扫描路径-->
<context:component-scan base-package="com.controller"></context:component-scan>
<!--配置拦截器-->
<mvc:interceptors>
<!--配置具体的拦截器的bean及其拦截范围-->
<mvc:interceptor>
<mvc:mapping path="/myController/demo"/><!--配置拦截的单元方法的访问路径,第一个/表示项目根目录-->
<bean class="com.interceptor.MyInterceptor"></bean><!--配置拦截器的bean对象,只在当前mvc:interceptor内有效-->
</mvc:interceptor>
</mvc:interceptors>
3. 拦截方法介绍
3.1 preHandle方法
作用:
执行拦截的方法preHandle(),返回false表示拦截此次请求,返回true表示放行。
执行时机:
单元方法执行之前。
参数:
HttpServletRequest request:此次拦截的请求的request对象。
HttpServletResponse response:此次拦截的请求的response对象。
Object handler:HandlerMethod类型,存储了拦截的单元方法的method对象。
返回值:
boolean类型,false表示拦截,true表示放行。
3.2 postHandle方法
作用:
执行拦截的方法postHandle(),可以对ModelAndView进行操作,Model数据进行校验,View操作等。
执行时机:
单元方法执行之后,视图解析器解析渲染视图之前。
参数:
HttpServletRequest request:此次拦截的请求的request对象。
HttpServletResponse response:此次拦截的请求的response对象。
Object handler:HandlerMethod类型,存储了拦截的单元方法的method对象。
ModelAndView:存储了model和view信息的对象。
3.3 afterCompletion方法
作用:
执行拦截的方法afterCompletion(),无论是否出现异常都会执行,可以处理异常,清理资源等。
执行时机:
视图解析器解析渲染视图完成之后。
参数:
HttpServletRequest request:此次拦截的请求的request对象。
HttpServletResponse response:此次拦截的请求的response对象。
Object handler:HandlerMethod类型,存储了拦截的单元方法的method对象。
Exception:存储异常信息的对象,如果没有异常信息则默认为null。
3.4 拦截器执行顺序总结
4. 拦截配置说明
拦截器类创建好后需要在springmvc.xml文件中配置拦截器的bean以及其拦截范围。
<!--配置拦截器-->
<mvc:interceptors>
<!--配置拦截器的bean对象,拦截所有的单元方法-->
<bean class="com.interceptor.MyInterceptor2"></bean>
<!--配置具体的拦截器的bean极其拦截范围,可以配置多个-->
<mvc:interceptor>
<mvc:mapping path="/myController/demo"/><!--配置拦截的单元方法的访问路径,第一个/表示项目根目录,可以多个-->
<mvc:mapping path="/myController/kk/*"/><!--支持*通配符表示任意个数的任意字符,**表示路径及子路径-->
<bean class="com.interceptor.MyInterceptor"></bean><!--配置拦截器的bean对象,只在当前mvc:interceptor内有效-->
</mvc:interceptor>
</mvc:interceptors>
5. 拦截器和过滤器的区别
来源不同
拦截器是SpringMVC中的技术,过滤器是Java EE中的技术。
生效位置不同
拦截器是进入DispatcherServlet后才能执行,过滤器是进入到Servlet容器后就可以触发。
目标不同
拦截器拦截的目标是HandlerMethod(控制单元,控制器方法),过滤器可以过滤所有的URL。
运行机制不同
拦截器是在HandlerMethod执行前后和视图处理完成后执行,分为三部分。过滤器只能在目标资源前后执行。
接口中方法类型不同
拦截器中的方法都是default方法,可以重写也可以不重写。过滤器中的方法都是abstract方法,如果当前类不是抽象类,必须重写。
上下文不同
拦截器被Spring MVC管理,可以获取到Spring容器中内容。Filter被Tomcat管理,所以无法获取Spring容器内容。
二、跨域
1. 跨域介绍
跨域:当前项目的协议、ip、端口和访问的URL的协议、IP、端口中有一个不同,这种访问就叫跨域。
跨域只发生在Ajax请求中。
2. 跨域的支持
浏览器为了保证Ajax默认不允许跨域实现,浏览器中都有一个同源策略。同源策略:当使用ajax请求时,不允许跨域访问。只能访问当前域的资源。
三、Spring MVC异常处理
1. 介绍
在Spring MVC支持异常处理。不会呈现给用户500界面。而是当出现异常时交给某个特定的控制器。
2. 局部配置
配置在@Controller的控制器类中,只有当前这个控制器类的控制单元出现异常时才能执行,其他类的控制单元出现异常不能执行。
每个控制器类中可以有多个处理异常的方法。每个方法上面只需要有@ExceptionHandler,千万别添加了@RequestMapping注解。
@Controller
public class DemoController {
@RequestMapping("/demo")
@ResponseBody
public String demo2(){
Object obj = null;
obj.toString();
return "demo2";
}
@ExceptionHandler(value = ArithmeticException.class)
public String myexception(){
System.out.println("Demo-1");
return "forward:/exception.jsp";
}
@ExceptionHandler(value = Exception.class)
public String myexception2(){
System.out.println("Demo-2");
return "forward:/exception2.jsp";
}
}
3. 全局配置
因为@ControllerAdvice已经继承了@Component注解,所以类上只添加这个注解就可以了。
如果配置了局部异常处理器和全局异常处理器,优先匹配局部异常处理器。
@ControllerAdvice
public class MyExceptionController {
@ExceptionHandler(value = ArithmeticException.class)
public String myexception(){
System.out.println("MyException-1");
return "forward:/exception.jsp";
}
@ExceptionHandler(value = Exception.class)
public String myexception2(){
System.out.println("MyException-2");
return "forward:/exception2.jsp";
}
}
4. 使用配置文件配置
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.NullPointerException">/error1.jsp</prop>
<prop key="java.lang.Exception">/error2.jsp</prop>
</props>
</property>
</bean>
上面的方式只有在Spring MVC中出现异常时才会触发,也可以使用Java EE中的配置方式。在web.xml中配置error-page即可。
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error3.jsp</location>
</error-page>
5. 根据状态码跳转到指定页面
在Spring MVC框架中没有提供根据状态码跳转到特定的视图。想要实现根据状态码跳转到指定页面可以使用Java EE中提供的实现方案。在web.xml中配置。
<error-page>
<error-code>404</error-code>
<location>/error4.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error5.jsp</location>
</error-page>
如果在Spring MVC中配置了异常解析器,对特定的异常类型跳转到指定的视图,代表着异常已经被解决了。对于Tomcat来说就不是500了。
四、Spring MVC数据校验
1. 数据校验介绍
数据校验分为客户端数据校验和服务端数据校验。常用在登录、注册功能中。
客户端和服务端都有数据校验时,称为双重校验。
服务端数据校验根据使用的技术完成校验。如果是Servlet技术可以自己编写校验逻辑,所有的校验过程都是通过正则表达式、等值判断等进行校验。而在Spring MVC中数据校验包含两种:
(1)基于注解方式
(2)自定义校验类的方式
2. 基于注解方式
注解 | 含义 |
---|---|
@AssertFalse | 类型必须是布尔,取值必须为false |
@AssertTrue | 类型必须是布尔,取值必须为true |
@DecimalMax("3") | 最大值为3,value属性是String类型 |
@DecimalMin("1") | 最小值为1,value属性是String类型 |
@Digits(integer = 10,fraction = 3) | integer:整数位最大长度,fraction小数位最大长度 |
必须是邮箱地址。只要中间包含@,且@前后都具有超过1位的字符就能通过校验。字符可以是数字字母下划线 | |
@Future | 类型必须是时间类型,允许为null,如果设置值必须是一个将来的时间 |
@FutureOrPresent | 类型必须是时间类型,允许为null,如果设置值必须是一个将来或现在的时间(精确到秒) |
@Max(5) | 最大值为5,value属性是long类型 |
@Min(1) | 最小值为1,value属性是long类型 |
@Negative | 必须是负数,对数据类型没有要求 |
@NegativeOrZero | 必须是负数或零,对数据类型没有要求 |
@NotBlank | 用在String类型。不能是空白(null和"") |
@NotEmpty | 用在String类型。不能是空白(null和"")。用在数组,集合类型中判断不能没有元素。 |
@NotNull | 不能为null,可以是""。可以用在所有类型中。对于八大基本数据类型来说,永远不为null |
@Null | 必须为Null。可以用在所有类型中。对于八大基本数据类型来说,永远不可能为null |
@Past | 类型必须是时间类型,必须是一个过去的时间。精确到秒 |
@PastOrPresent | 类型必须是时间类型,必须是一个过去的时间或现在的时间。精确到秒 |
@Pattern(regexp = "\w{1,6}") | 必须满足正则表达式。regexp是必有属性 |
@Positive | 必须是正数,对数据类型没有要求 |
@PositiveOrZero | 必须是正数或零,对数据类型没有要求 |
@Size(min = 1,max = 10) | 用在String类型。个数必须在1和10之间 |
注解 | 含义 |
---|---|
@Length(min = 1,max = 10) | 用在String类型。长度需要在1和10之间 |
@Range(min = 1,max = 10) | 数据类型没有要求。取值范围需要在1和10之间 |
@URL(port = 8080,host = "127.0.0.1",protocol = "https") | 需要是一个合法的URL。默认情况下只要是以http:开头即可。可以通过port限制端口、host限制主机名、protocol限制协议 |
注解方式的具体实现
添加依赖
除了项目正常的依赖以外,额外需要导入Hibernate-validator依赖。
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.7.Final</version>
</dependency>
在实体类属性上添加注解
(1)@NotNull中message是可选属性,如果设置了message,在违反规则后日志会打印message中内容。
(2)@Length是设置字符串长度。
所以name必须不能是null的,且长度是2-6位。
注解放在实体类的属性上面,每个实体类属性都支持配置多个注解,这些注解同时生效。
public class People {
@NotNull(message = "姓名不能是null")
@Length(min = 2,max = 6,message = "长度应该是2-6位")
private String name;
private String age;
// 省略Getter和Setter
}
五、Spring MVC中包含哪些组件
1. 组件介绍
组件是将处理某类问题的代码进行封装的整体模块。一个大的问题可以拆分为不同的小问题,解决每个小问题的代码封装可以称之为组件,但是组件又是无法独立运行的,必须结合其他组件一起才能最终解决问题。
2.常用组件说明
DispatcherServlet:前端控制器。Spring MVC的入口,也是整个流程控制中心。其他组件由DispatcherServlet统一调度,降低了组件和组件之间的耦合度。
MultipartResovler:多部分处理器。文件上传时需要使用。
LocaleResolver:解决客户端的区域和时区问题。
ThemeResolver:主题解析器。提供自定义布局。
HandlerMapping: 映射处理器。主要负责处理URL,并找到对应的HandlerMethod。简单说就是找@RequestMapping注解中映射路径是否有和URL匹配的。
HandlerAdapter:适配器。负责调用具体的HandlerMethod。
HandlerExceptionResovler:异常处理器。异常处理,根据不同异常返回视图。
RequestToViewNameTranslator:从请求中获取到视图名称。
ViewResovler:视图解析器,负责解析字符串视图名和物理视图文件的。
FlashMapManager:主要用于存储属性的,本质是一个Map。多用在重定向时。FlashMap在重定向之前存储,重定向之后删除。
ModelAndView:模型和视图。Spring MVC中提供的模型和视图接口。
HandlerInterceptor:拦截器。拦截控制器资源的。
六、SpringMVC运行原理
SpringMVC执行流程:
0.Tomcat启动
1.监听到了ServletContext对象创建,加载Spring配置文件,创建Spring容器。
2.创建Dispatcher,Dispatcher初始化时
1.加载Springmvc配置文件,创建Springmvc容器。
2.初始化SpringMVC相关组件
1.MultipartResovler:文件解析器(上传文件时需要使用)
2.HandlerMapping:处理器映射器(根据请求的url获取对应的控制单元和控制单元的拦截器)
3.HandlerAdapter:处理器适配器(由处理器适配器指定控制单元)
4.HandlerExceptionResovler:处理器异常解析器(处理异常)
5.ModelAndView:模型和视图(存储模型数据和视图名),控制单元执行后,最终返回ModelAndView
6.ViewResovler:视图解析器(解析ModelAndView中的视图名,找到对应视图解析器,视图解析器解析出对应的视图对象,视图对象完成页面渲染)
7.HandlerInterceptor:处理器拦截器
1.拦截器:拦截Dispatcher分发的资源,使用拦截器主要拦截控制单元。
preHandle:控制单元执行之前 执行
psotHandle:控制单元执行之后 执行
afterCompletion:页面渲染完成后 执行
1.客户端发起请求访问服务端Tomcat服务器中部署项目中的资源(控制单元)
2.tomcat将请求交由DispatcherServlet执行,DispatcherServlet将请求进行分发
3.执行HandlerMapping(处理器映射器),根据请求的url获取对应的控制单元和控制单元的拦截器,返回执行链到DispatcherServlet
4.执行根据访问的控制单元获取对应的HandlerAdapter(处理器适配器),返回处理器适配器到DispatcherServlet
5.存在拦截器,执行拦截器的preHandle方法
6.处理器适配器执行控制单元,控制单元执行后,最终返回ModelAndView
7.存在拦截器,执行拦截器的postHandle方法
8.没有使用@Response | @RestController | response.getWriter().print()
1.执行视图解析器,解析出对应的视图对象,视图对象完成渲染(将模型数据通过视图响应回到客户端)
8.使用@Response | @RestController | response.getWriter().print()
1.将数据响应回到客户端,不经过视图解析器