一、拦截器
1.介绍拦截器
1.拦截器(springmvc提供)
2.只拦截控制单元(生效必须配置拦截器)
3.会拦截静态资源,使用拦截器时,尽量使用局部配置,配置拦截的控制单元即可。
注意:只有URL匹配到了控制单元,拦截器才能生效。
4.拦截器中实现的三方法执行的顺序:
- 执行控制单元之前 执行拦截器preHandle方法。对请求进行相关的处理。
- 执行控制单元之后 ,视图解析器解析渲染视图之前,执行拦截器postHandle方法。对应modelandview进行相关操作。
- 向客户端完成响应 执行拦截器afterCompletion方法。进行相关结尾的操作,无论是否出现异常都会执行。
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("preHandle执行");
//false拦截器不放行
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion执行");
}
}
2.2 配置拦截器
<mvc:interceptors>
<!--会拦截静态资源,使用拦截器时,尽量使用局部配置,配置拦截的控制单元即可。 -->
<!-- 1.全局的配置,全部的控制单元执行该拦截器 -->
<!-- <bean class="com.zqwl.interceptor.MyInterceptor"/>-->
<!-- 局部的配置,符合配置拦截路径的控制单元,执行该拦截器 -->
<!-- 2. 局部拦截器配置-->
<mvc:interceptor>
<!-- 拦截的控制单元-->
<mvc:mapping path="/demo/*"/>
<!-- 排除拦截的控制单元-->
<mvc:exclude-mapping path="/demo/bb"/>
<!-- 使用的拦截器-->
<bean class="com.zqwl.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
2.3. 拦截器栈
拦截器栈指多个拦截器。当一个控制单元被多个拦截器拦截时,就形成了拦截器栈。拦截器栈中拦截器有着严格的执行顺序。执行顺序按照配置顺序执行。先配置的优先级更高。
例如:拦截器A和拦截器B,优先级更高指以控制单元(demo)为核心,前面的方法优先级高的先执行,后面的方法优先级高的后执行。
preHandle1 -> preHandle2 -> demo -> postHandle2 -> postHandle1 -> afterCompletion2 -> afterCompletion1。
配置拦截器栈分为局部配置和全局配置(与单个一样)。
执行顺序:
2.4. 拦截器和过滤器的区别(面试题)
来源不同
拦截器是SpringMVC中的技术,过滤器是Java EE中的技术。
生效位置不同
拦截器是进入DispatcherServlet后才能执行,过滤器是进入到Servlet容器后就可以触发。
目标不同
拦截器拦截的目标是HandlerMethod(控制单元,控制器方法),过滤器可以过滤所有的URL。
运行机制不同
拦截器是在HandlerMethod执行前后和视图处理完成后执行,分为三部分。过滤器只能在目标资源前后执行。
接口中方法类型不同
拦截器中的方法都是default方法,可以重写也可以不重写。过滤器中的方法都是abstract方法,如果当前类不是抽象类,必须重写。
上下文不同
拦截器被Spring MVC管理,可以获取到Spring容器中内容。Filter被Tomcat管理,所以无法获取Spring容器内容。
二、跨域
1. 跨域介绍
项目和项目之前访问的网址或ip:port称为域(domain)。
跨域:当前项目的协议、ip、端口和访问的URL的协议、IP、端口中有一个不同,这种访问就叫跨域。
例如:当前项目http://localhost:8080 访问了 http://127.0.0.1:8080 就是跨域访问。
2. 什么时候有跨域
跨域只发生在Ajax请求中。
Ajax研发之初为了保证安全性,设置默认情况下不允许跨域访问。
3.解决Ajax不能跨域问题
在需要访问的控制单元方法上面添加@CrossOrigin注解即可。
三、Spring MVC异常处理
1. 介绍
在Spring MVC支持异常处理。不会呈现给用户500界面。而是当出现异常时交给某个特定的控制器。
如果是一个上线的项目,呈现了500界面,会非常影响用户体验度。同时也显示公司实力有问题、不专业。
2. 局部配置
配置在@Controller的控制器类中,只有当前这个控制器类的控制单元出现异常时才能执行,其他类的控制单元出现异常不能执行。
每个控制器类中可以有多个处理异常的方法。每个方法上面只需要有@ExceptionHandler,千万别添加了@RequestMapping注解。、
@ExceptionHandler(Exception.class) //里面写具体的异常,写在这儿只能处理该控制器类中控制单元出现的异常
public String MyException(){
System.out.println("发生了异常");
return "/exception.jsp";
}
3. 全局配置
因为@ControllerAdvice已经继承了@Component注解,所以类上只添加这个注解就可以了。
不需要在添加@Controller注解了。
小提示:
如果配置了局部异常处理器和全局异常处理器,优先匹配局部异常处理器。
//全局配置异常处理(单独写一个类,也交给SpringMvc管理),可以当其他控制器类出现异常也可以处理
@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:/exception.jsp";
}
}
4. 使用配置文件配置
在Spring MVC中包含HandlerExceptionResolver组件,专门负责处理异常的。接口中只包含一个resolveException方法。
在spring mvc.xml中配置:
//xml配置解决异常:异常解析器 优先级比状态码异常高:因为出现异常先遇到他,而状态码是返回给客户端时才遇到
<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">/exception.jsp</prop>
</props>
</property>
</bean>
5. 根据状态码跳转到指定页面
在Spring MVC框架中没有提供根据状态码跳转到特定的视图。想要实现根据状态码跳转到指定页面可以使用Java EE中提供的实现方案。
在web.xml中配置。
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error1.jsp</location>
</error-page>
四、Spring MVC数据校验
1. 数据校验介绍
2. 基于注解方式
所需依赖:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.7.Final</version>
</dependency>
在实体类属性上添加注解
注解放在实体类的属性上面,每个实体类属性都支持配置多个注解,这些注解同时生效。
实体类:
public class People {
@NotNull(message = "姓名不能是null")
@Length(min = 2,max = 6,message = "长度应该是2-6位")
private String name;
private String age;
// 省略Getter和Setter
}
控制单元:
控制单元中必须添加@Valid注解,否则校验不生效。
如果配置了日志文件,需要将日志级别设置为WARN。
@RequestMapping("/valid")
public String testValid(@Valid People peo){
System.out.println(peo);
return "/abc.jsp";
}
五、Spring MVC中包含哪些组件
1.介绍
SpringMVC将Servlet访问的流程整体封装了起来,浏览器发起请求后调用单元方法来处理请求,这个整个过程从接收到请求,到找到单元方法并调用执行,再到响应结果给浏览器都是由不同的组件协同来实现的,有如下组件:
不同的组建在整个运行过程中的具体表现其实就是不同的对象,也就是不同对象之间的相互调用完成了请求的处理,组件的初始化应该在请求来之前就完成的,当服务器启动的时候会先完成对DispactherServlet的初始化创建,在DispatcherServlet被初始化的时候其底层内部也会完成第2到第10个组件的初始化,调用其initStrategies方法来完成
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运行原理(常见面试题)
客户端向服务端发起请求,Spring MVC总体入口中央调度器DispatcherServlet进行请求分发。
中央调度器DispatcherServlet把URL交给映射处理器HandlerMapping进行解析URL。
映射处理器HandlerMapping将请求映射为HandlerExecutionChain处理器执行链
可以为多个处理器拦截器HandlerInterceptor
处理器Handler对象(处理Controller)。
将处理器执行链HandlerExecutionChain返回到中央调度器DispatcherServlet。
DispatcherServlet根据返回的处理器执行链HandlerExecutionChain获得的处理器Handler,根据处理器Handler选择处理器适配器HandlerAdapter。
执行拦截器的preHandle()方法。
调用具体的Handler处理器(处理Controller),在填充Handler的入参过程中会执行数据转换、数据格式化、数据验证,调用具体的Controller完成处理功能,并创建ModelAndView对象。
执行拦截器的postHandle()方法。
将ModelAndView对象返回到处理器适配器HandlerAdapter。
处理器适配器HandlerAdapter将ModelAndView对象返回到中央调度器DispatcherServlet。
中央调度器DispatcherServlet调用视图解析器ViewResolver解析视图。
将解析的视图View对象返回到中央调度器DispatcherServlet。
渲染视图,将视图返回到中央调度器DispatcherServlet,执行拦截器afterCompletion()方法。
中央调度器DispatcherServlet相应回到浏览器。