博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA框架——SpringMVC总结(二)拦截器与过滤器的区别,静态资源的访问问题,请求重定向和转发,异常处理以及拦截器,拦截器与过滤器的区别
阅读量:3504 次
发布时间:2019-05-20

本文共 10341 字,大约阅读时间需要 34 分钟。

一、访问静态资源问题

1、*.do

在没有特殊要求的情况下,SpringMVC 的中央调度器 DispatcherServlet 的

常使用后辍匹配方式,如写为*.do 或者 *.action, *.mvc 等。

2、 /

可以写为/,因为 DispatcherServlet 会将向静态资源的获取请求,例如.css、.js、.jpg、.png等资源的获取请求,当作是一个普通的 Controller 请求。中央调度器会调用处理器映射器为其查找相应的处理器。当然也是找不到的,所以在这种情况下,所有的静态资源获取请求也均会报 404 错误。

tomcat本身能处理静态资源的访问, 像html, 图片, js文件都是静态资源

tomcat的web.xml文件有一个servlet 名称是 default , 在服务器启动时创建的。

default
org.apache.catalina.servlets.DefaultServlet
debug
0
listings
false
1
default
/
表示静态资源和未映射的请求都这个default处理

default这个servlet作用:

1.处理静态资源
2.处理未映射到其它servlet的请求。

所以我们在webxml文件中配置url-pattern的值为“/”会拦截所有的静态资源。包括jsp,html,js等但是我们的动态资源就是控制器类是可以访问的

springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
springmvc
/

3、方式一:使用<mvc:default-servlet-handler/>

因为我们在web.xml中设置了"/"。所以我们静态图片,资源都是无法访问的。

所以我们在application.xml中去设置该注解

  • 声明 了 <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。

处理方式:只需要在 springmvc.xml 中添加<mvc:default-servlet-handler/>标签即可

<mvc:default-servlet-handler/>表示使用 DefaultServletHttpRequestHandler 处理器对象。
而该处理器调用了 Tomcat 的 DefaultServlet 来处理静态资源的访问请求。

4、方式二:使用<mvc:resources/>

在 Spring3.0 版本后,Spring 定义了专门用于处理静态资源访问请求的处理器

ResourceHttpRequestHandler。并且添加了<mvc:resources/>标签,专门用于解决静态资源无法访问问题。需要在 springmvc 配置文件中添加如下形式的配置:

  • location 表示静态资源所在目录。当然,目录不要使用/WEB-INF/及其子目录。

  • mapping 表 示 对 该 资 源 的 请 求 ( 以 /images/ 开 始 的 请 求 , 如 /image/beauty.jpg ,/images/car.png 等)。注意,后面是两个星号**。

常见开发中,会进行如下配置:

5. 方式三:声明注解驱动

解决动态资源和静态资源冲突的问题,在 springmvc 配置文件加入:

二、请求重定向与转发

1.请求转发

处理器方法返回 ModelAndView 时,需在 setViewName()指定的视图前添加 forward:且此时的视图不再与视图解析器一同工作,这样可以在配置了解析器时指定不同位置的视图

视图页面必须写出相对于项目根的路径。forward 操作不需要视图解析器。

处理器方法返回 String,在视图路径前面加入 forward: 视图完整路径

@RequestMapping( value = "/doForward.do" )    public ModelAndView doForward(){
ModelAndView modelAndView = new ModelAndView(); //显示转发,明显的说明 这是一个转发 //modelAndView.setViewName("forward:/WEB-INF/show.jsp"); modelAndView.setViewName("forward:/hello.jsp"); return modelAndView; }

注意此处,我们如果想要脱离视图解析器,可以使用该方法,跳出规则限制。想转发到哪个页面就哪个页面, 也称为显示转发,明显的说明这是一个转发

2.请求重定向

在处理器方法返回的视图字符串的前面添加 redirect:,则可实现重定向跳转。

/*     * 处理器方法返回ModelAndView,实现转发forword     * 语法:setViewName("redirect:视图文件完整路径")     * redirect特点:不和视图解析器一同使用,就当项目中没有视图解析器     *     * */    @RequestMapping( value = "/doRedirect.do" )    public ModelAndView doRedirect(){
ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("redirect:/hello.jsp"); return modelAndView; }

此时我们通过表单请求去重定向页面

返回ModelAndView实现redirect

姓名:
年龄:

此时我们并不能用EL从中获取到数据,而是变成了GET请求方式

在这里插入图片描述 注意

  • 框架对重定向的操作是框架会把Model的简单类型的数据,转为String使用,作为show.jsp的get请求参数使用。目的是在doRedirect.do和show.jsp两次请求之间传递数据
  • 该处不能进行直接访问,因为我们重定向不能访问WEB-INF下面的路径文件

如果我们想要获取该数据,我们可以使用param可以获取到域中的参数

body>    

WEB-INF/view/show.jsp

myname数据:${param.myname}

myage数据:${param.myage}

三、异常处理

  • SpringMVC框架采用的是统一,全局的异常处理。把Controller中的所有异常处理都几种到一个地方。采用aop的思想。把业务逻辑和异常处理代码分开,解耦合。

  • 使用两个注解@ExceptionHandler@ControllerAdvice

1.异常处理步骤:

  • 1.新建maven web项目

  • 2.加入依赖

  • 3.新建一个自定义异常类 MyUserException , 再定义它的子类NameException ,AgeException

  • 4.在controller抛出NameException , AgeException

  • 5.创建一个普通类,作用全局异常处理类

    • 在类的上面加入@ControllerAdvice
    • 在类中定义方法,方法的上面加入@ExceptionHandler
  • 6.创建处理异常的视图页面

  • 7.创建springmvc的配置文件

    • 1)组件扫描器 ,扫描@Controller注解
    • 2)组件扫描器,扫描@ControllerAdvice所在的包名
    • 3)声明注解驱动

2.代码实现

书写一个index页面

全局异常处理

姓名:
年龄:

书写三个异常类,用于处理姓名和年龄异常

//用户异常public class MyUserExpection extends Exception{
public MyUserExpection() {
super(); } public MyUserExpection(String message) {
super(message); }}//姓名异常public class NameExpection extends MyUserExpection {
public NameExpection() {
super(); } public NameExpection(String message) {
super(message); }}//年龄异常public class AgeExpection extends MyUserExpection {
public AgeExpection() {
super(); } public AgeExpection(String message) {
super(message); }}

控制器类

@RequestMapping( value = "/some.do" )    public ModelAndView doSome(String name,Integer age) throws MyUserExpection {
ModelAndView modelAndView = new ModelAndView(); if (!"zs".equals(name)) {
throw new NameExpection("姓名不正确"); } if (age == null || age >80) {
throw new AgeExpection("年龄较大"); } modelAndView.addObject("myname",name); modelAndView.addObject("myage",age); modelAndView.setViewName("show"); return modelAndView; }

xml中配置注解扫描器

总异常处理类

异常发生处理逻辑  1.需要把异常记录下来,记录到数据库,日志文件      记录日志发生的时间,哪个方法发生的,异常错误内容   2.发送通知,把异常的信息通过邮箱,短信,微信发送给相关人员   3.给用户有友好的提示

注意使用两个注解即可@ControllerAdvice@ExceptionHandler

/** @ControllerAdvice 控制器增强(给控制器去增加功能——异常处理功能)*       位置:在类的上面*   特点:必须让框架知道这个注解所在的包名,需要在springmvc配置文件声明组件扫描器*   指定@ControllerAdvice所在的包名* */@ControllerAdvicepublic class GlobalExceptionHandler {
//定义方法,处理发生的异常 /* * 处理异常的方法和控制器方法的定义一样,可以有多个参数,可以有ModelAndView, * String ,void ,对象类型的返回值 * * 形参:Expection。表示Controller中抛出的异常对象 * 通过形参可以获取发生的异常信息 * * @ExceptionHandler(异常Class):表示异常的类型,当发生此类型异常时, * 由当前方法处理 * */ @ExceptionHandler( value = NameExpection.class) public ModelAndView doNameException(Exception exe){
//处理NameException的异常 /* * 异常发生处理逻辑 * 1.需要把异常记录下来,记录到数据库,日志文件 * 记录日志发生的时间,哪个方法发生的,异常错误内容 * 2.发送通知,把异常的信息通过邮箱,短信,微信发送给相关人员 * 3.给用户有友好的提示 * */ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("msg","姓名必须是zs,其他用户不能访问"); modelAndView.addObject("exe",exe); modelAndView.setViewName("nameError"); return modelAndView; } @ExceptionHandler( value = AgeExpection.class) public ModelAndView doAgeException(Exception exe){
ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("msg","年龄不能过大"); modelAndView.addObject("exe",exe); modelAndView.setViewName("ageError"); return modelAndView; } //处理其他异常,NameException,AgeException以外,不知的类型异常 @ExceptionHandler public ModelAndView doOtherException(Exception exe){
//处理其他异常 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("msg","年龄不能过大"); modelAndView.addObject("exe",exe); modelAndView.setViewName("defaultError"); return modelAndView; }}

四、拦截器

1.拦截器概述

  • 它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。

  • 拦截器是springmvc中的一种,需要实现HandlerInterceptor接口。

  • 过滤器是用来过滤器请求参数,设置编码字符集等工作

  • 拦截器是拦截用户的请求,做请求做判断处理的。

  • 拦截器是全局的,可以对多个Controller做拦截。

    一个项目中可以有0个或多个拦截器, 他们在一起拦截用户的请求。
    拦截器常用在:用户登录处理,权限检查, 记录日志。

2.拦截器使用步骤

  • 定义类实现HandlerInterceptor接口

  • 在springmvc配置文件中,声明拦截器, 让框架知道拦截器的存在

3.创建一个拦截器

//拦截器类:拦截用户的请求。public class MyInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器的MyInterceptor的preHandle()"); //计算的业务逻辑,根据计算结果,返回true或者false //给浏览器一个返回结果 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mv) 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()"); }}

方法简介

1、preHandle:预处理方法

  • 是整个项目的入口,门户。 当preHandle返回true 请求可以被处理。

  • 参数

    • Object handler : 被拦截的控制器对象
    • 返回值boolean
    1.  true:请求是通过了拦截器的验证,可以执行处理器方法。      拦截器的MyInterceptor的preHandle()       =====执行MyController中的doSome方法=====       拦截器的MyInterceptor的postHandle()       拦截器的MyInterceptor的afterCompletion()    2. false:请求没有通过拦截器的验证,请求到达拦截器就截止了。 请求没有被处理     拦截器的MyInterceptor的preHandle()
  • 特点

    1.方法在控制器方法(MyController的doSome)之前先执行的。   用户的请求首先到达此方法 2.在这个 方法中可以获取请求的信息, 验证请求是否符合要求。   可以验证用户是否登录, 验证用户是否有权限访问某个连接地址(url)。    如果验证失败,可以截断请求,请求不能被处理。    如果验证成功,可以放行请求,此时控制器方法才能执行。

2、postHandle:后处理方法。

  • 参数

    Object handler:被拦截的处理器对象MyController
    ModelAndView mv:处理器方法的返回值

  • 特点

    1.在处理器方法之后执行的(MyController.doSome())    2.能够获取到处理器方法的返回值ModelAndView,可以修改ModelAndView中的  数据和视图,可以影响到最后的执行结果。    3.主要是对原来的执行结果做二次修正,  ModelAndView mv = MyController.doSome();  postHandle(request,response,handler,mv);

3、afterCompletion:最后执行的方法

  • 参数

    Object handler:被拦截器的处理器对象
    Exception ex:程序中发生的异常

  • 特点:

    1.在请求处理完成后执行的。框架中规定是当你的视图处理完成后,对视图执行了forward。就认为请求处理完成。  2.一般做资源回收工作的, 程序请求过程中创建了一些对象,在这里可以删除,把占用的内存回收。

4.拦截器执行顺序

在这里插入图片描述

5.执行多个拦截器

我们只需要多写一个拦截器类即可。并且在Spring.xml中声明多个拦截器即可

注意:

  • 声明拦截器,拦截器可以有0或多个
  • 在框架中保存多个拦截器是ArrayList。
  • 按照声明的先后顺序放入到ArrayList中

输出结果:

在这里插入图片描述
类似于栈的执行顺序,先进后出的概念

6.拦截器的执行链

两个拦截器中

第一个preHandle返回值为true,第二个preHandle返回值为false

在这里插入图片描述第一个preHandle返回值为false,第二个preHandle返回值为true
在这里插入图片描述

结论:不论是哪个拦截器,只要有一个拦截器的preHandle的一个返回值为false那么均不会执行控制器中的方法,我们只要在不同的拦截器中进行不同的功能即可,均正确才能返回我们的控制器类

五、过滤器和拦截器的区别

  • 过滤器是servlet中的对象, 拦截器是框架中的对象

  • 过滤器实现Filter接口的对象, 拦截器是实现HandlerInterceptor

  • 过滤器是用来设置request,response的参数,属性的,侧重对数据过滤的。

  • 拦截器是用来验证请求的,能截断请求。

  • 过滤器是在拦截器之前先执行的

  • 过滤器是tomcat服务器创建的对象

  • 拦截器是springmvc容器中创建的对象

  • 过滤器是一个执行时间点

  • 拦截器有三个执行时间点

  • 过滤器可以处理jsp,js,html等等

  • 拦截器是侧重拦截对Controller的对象。 如果你的请求不能被DispatcherServlet接收, 这个请求不会执行拦截器内容

  • 拦截器拦截普通类方法执行,过滤器过滤servlet请求响应

转载地址:http://btxmj.baihongyu.com/

你可能感兴趣的文章
【零】Linux中MySQL安装
查看>>
Sqoop的安装及测试
查看>>
Kylin的简单使用
查看>>
Presto的概念和安装使用
查看>>
Druid的Web页面使用
查看>>
Scala-HelloWorld
查看>>
Scala-IDEA中环境部署
查看>>
Scala-HelloWorld解析
查看>>
Scala-变量和数据类型
查看>>
Scala-流程控制
查看>>
Scala-面向对象后章
查看>>
iOS蓝牙原生封装,助力智能硬件开发
查看>>
iOS 代码的Taste(品位)
查看>>
iOS开发代码规范
查看>>
iOS组件化实践(基于CocoaPods)
查看>>
【iOS学习】RxSwift从零入手 - 介绍
查看>>
数据结构之栈
查看>>
Elastic Stack简介
查看>>
关于deepin系统安装design compiler的问题解答
查看>>
Java Agent简介及使用Byte Buddy和AspectJ LTW监控方法执行耗时
查看>>