Spring MVC拦截器1:拦截器入门一:拦截器(interceptor)简介;拦截器开发流程简介;演示了拦截器最基本的配置流程;

说明:

(1)本篇博客合理性解释:

          ● 本篇博客介绍Spring MVC中一个高级组件:拦截器;

          ● 但是,本篇博客的主要目的只是【引入Interceptor拦截器】、【简单的走一遍拦截器的配置过程】;

          ● 有关拦截器的【实用技巧】和【具体细节】等深入的内容在后面会介绍;即,本篇博客仅仅是拦截器的一个入门;

(2)本篇博客主要内容:

          ● 拦截器(Interceptor)简介;

          ● 拦截器(Interceptor)开发流程概述;

          ● 拦截器(Interceptor)开发流程走了一遍,演示了最初级的使用;

          ● 介绍了HandlerInterceptor接口的三个方法:preHandle()、postHandle()、afterCompletion();

(3)如有需要:过滤器(filter)可以参考【(5)常用功能与过滤器、监听器、FreeMarker;】专栏中的内容;Spring AOP可以参考【(15)Spring基础:IoC;AOP;JDBC;】专栏中的内容;

目录

一:拦截器简介;

二:拦截器(Interceptor)开发流程;

1. 拦截器(Interceptor)开发流程:简介;

2.开发前准备:准备一个【interceptor工程】;(这部分不是本篇博客的重点,快速扫过去就行)

(1)创建【interceptor】工程;

(2)【interceptor】工程,初始内容展示;

3.开发拦截器(Interceptor);(重点)

(1)第一步:在pom.xml中引入servlet-api依赖;

(2)第二步:新建一个实现了HandlerInterceptor接口的类;

(3)第三步:在applicationContext.xml中配置过滤地址;

(4)启动Tomcat,观察效果;


一:拦截器简介;

说明:

(1)拦截器的作用:拦截url,对其进行前置/后置过滤;

(2)【Spring中的拦截器】和【J2EE中的过滤器】,其作用有点类似,都是拦截请求;但是二者底层的实现逻辑是不同的;

          ● 拦截器(Interceptor)是Spring MVC的标准组件;(Interceptor对象被创建后,是天然的运行在IoC容器中的;)

          ● 过滤器(Filter)是J2EE的标准组件,是J2EE的标准;过滤器(Filter)的具体实现,是由不同的第三方容器厂商实现的;( 比如,我们在【过滤器一:过滤器简介;创建第一个Filter;】中直接使用的过滤器,就是Tomcat这个第三方厂商,根据J2EE标准实现的;)

(3)我们已经知道,拦截器(Interceptor)的作用是拦截url,对其进行前置/后置处理;

          ● 我们很容易就能联想到Spring中的【AOP面向切面编程】;

          ● 其实,拦截器(Interceptor)的底层最基本的实现,就是依赖于Spring AOP理念;(【拦截器(Interceptor)的具体实现】和【AOP中的环绕通知】很相似;)

……………………………………………………

(注)如有需要,过滤器(Filter)的有关内容可以参考【(5)常用功能与过滤器、监听器、FreeMarker;】的内容;Spring AOP的有关内容可以参考【(15)Spring基础:IoC;AOP;JDBC;】;


二:拦截器(Interceptor)开发流程;

1. 拦截器(Interceptor)开发流程:简介;

说明:

(1)拦截器(Interceptor)底层依赖于【最原始的servlet-api,也就是J2EE的javx.servlet】;所以,首先需要引入javax.servlet依赖;(至于为什么要引入Servlet依赖,在【附加:Java简介(Java SE,Java EE,JDK等);【java.servlet.**】和【javax.**】简介;Eclipse和IDEA在使用servlet-api.jar时的区别;】和本篇博客的后续内容中会得到答案;)

(2)新建一个类,然后这个类要实现HandlerInterceptor接口;(这个接口的完整地址是org.springframework.web.servlet.HandlerInterceptor,可以看到,这个接口是Spring定义的)

(3)然后,在编好了拦截器类后,需要在applicationContext.xml中配置过滤地址;

2.开发前准备:准备一个【interceptor工程】;(这部分不是本篇博客的重点,快速扫过去就行)

(1)创建【interceptor】工程;

首先,创建一Maven WebApp项目;

这个过程可以参考【SpringMVC入门与数据绑定2:Spring MVC初体验二:使用IDEA创建【maven + WebApp】项目;】;啰嗦一下吧,其基本过程就是:

     第一步:创建一Maven项目;

     第二步:将工程设置为Web工程;

          ● 添加web功能;

          ● 三个设置项:【设置web.xml文件目录】、【设置web资源保存目录】、【设置artifact发布】;

     第三步:给项目配置Tomcat;

          ● 配置一个本地的Tomcat服务器;

          ● 在Deployment中配置artifact发布;

          ● 设置一下Server中的端口号等内容;

……………………………………………………

然后,配置Spring MVC;

这个过程可以参考【SpringMVC入门与数据绑定3:Spring MVC初体验三:Spring MVC环境配置;(通过一个简单案例,走了一遍Spring MVC流程;)】,其基本过程就是:

     第一步:在pom.xml中引入依赖;

     第二步:在web.xml中配置DispatcherServlet;

     第三步:创建并编写applicationContext.xml;

     第四步:将新引入依赖添加到Tomcat发布中去;

……………………………………………………

至此,一个Spring MVC项目就创建好了;


(2)【interceptor】工程,初始内容展示;

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.imooc</groupId>
    <artifactId>interceptor</artifactId>
    <version>1.0-SNAPSHOT</version>

    <repositories>
        <repository>
            <id>aliyun</id>
            <name>aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.9</version>
        </dependency>
    </dependencies>

</project>

……………………………………………………

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>characterFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>formContentFilter</filter-name>
        <filter-class>org.springframework.web.filter.FormContentFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>formContentFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

……………………………………………………

Persons:

package com.imooc.restful.entity;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.util.Date;

public class Person {
    private String name;
    private Integer age;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date birthday;

    public Person() {
    }

    public Person(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

……………………………………………………

RestfulController:

package com.imooc.restful.controller;

import com.imooc.restful.entity.Person;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/restful")
public class RestfulController {

    @GetMapping("/persons")
    public List<Person> findPersons() {
        List list = new ArrayList();
        Person person1 = new Person();
        person1.setName("zhang");
        person1.setAge(20);
        person1.setBirthday(new Date());
        Person person2 = new Person();
        person2.setName("wang");
        person2.setAge(21);
        person2.setBirthday(new Date());
        list.add(person1);
        list.add(person2);
        return list;
    }
}

……………………………………………………

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mv="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.imooc.restful"></context:component-scan>

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=utf-8</value>
                        <value>application/json;charset=utf-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    <mvc:default-servlet-handler/>

    <mvc:cors>
        <mvc:mapping path="/restful/**"
                     allowed-origins="http://localhost:8080,http://www.imooc.com"
                     max-age="3600"/>
    </mvc:cors>

</beans>

……………………………………………………

client.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="jquery-3.5.1.js"></script>
    <script>
        $(function () {
            $("#btnGet").click(function () {
                $.ajax({
                    "url" : "/restful/request",
                    "type" : "get",
                    "dataType" : "json",
                    "success" : function (json) {
                        $("#message").text(json.message);
                    },
                    "error":function () {
                        alert("mmmmmmm");
                    }
                })
            })
        });

        $(function () {
            $("#btnPost").click(function () {
                $.ajax({
                    "url" : "/restful/request/103",
                    "type" : "post",
                    "data": "name=lily&age=23",
                    "dataType" : "json",
                    "success" : function (json) {
                        $("#message").text(json.message + ":" +json.id);
                    },
                    "error":function () {
                        alert("mmmmmmm");
                    }
                })
            })
        });

        $(function () {
            $("#btnPut").click(function () {
                $.ajax({
                    "url" : "/restful/request",
                    "type" : "put",
                    "data": "name=lily&age=23",
                    "dataType" : "json",
                    "success" : function (json) {
                        $("#message").text(json.message);
                    },
                    "error":function () {
                        alert("mmmmmmm");
                    }
                })
            })
        });

        $(function () {
            $("#btnDelete").click(function () {
                $.ajax({
                    "url" : "/restful/request",
                    "type" : "Delete",
                    "dataType" : "json",
                    "success" : function (json) {
                        $("#message").text(json.message);
                    },
                    "error":function () {
                        alert("mmmmmmm");
                    }
                })
            })
        });

        $(function () {
            $("#btnPersons").click(function () {
                $.ajax({
                    "url" : "/restful/persons",
                    "type" : "get",
                    "dataType" : "json",
                    "success" : function (json) {
                        for (var i = 0; i < json.length; i++) {
                            var p = json[i];
                            $("#divPersons").append("<h2>" +p.name + ":" + p.age + ":"
                                + p.birthday+ "</h2>")
                        }
                    }
                })
            })
        });
    </script>
</head>
<body>
    <input type="button" id="btnGet" value="向服务器发送Get请求">
    <input type="button" id="btnPost" value="向服务器发送Post请求">
    <input type="button" id="btnPut" value="向服务器发送Put请求">
    <input type="button" id="btnDelete" value="向服务器发送Delete请求">
    <h1 id="message"></h1>
    <hr/>
    <input type="button" id="btnPersons" value="查询所有人员">
    <div id="divPersons"></div>

</body>
</html>

其实,【interceptor工程】就是照搬前面的【restful工程】; 

3.开发拦截器(Interceptor);(重点)

(1)第一步:在pom.xml中引入servlet-api依赖;

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

说明:

(1)servlet依赖说明:

(2)第一次遇到,基于IDEA,在工程中引入servlet api是在【OA系统六:前期准备四:整合FreeMarker;引入Servlet3.1依赖;顺带设置下logback.xml日志;】;并且,当时也是把servlet的scope设置为了provided;

(3)一个疑问:Eclipse和IDEA在开发的时候,如果需要用到HttpServletRequest或者HttpServletResponse时,一个不需要引入javax.servlet依赖,一个需要引入javax.servlet依赖,这个问题还未解决,等会解决后,再补充;在【附加:Java简介(Java SE,Java EE,JDK等);【java.servlet.**】和【javax.**】简介;Eclipse和IDEA在使用servlet-api.jar时的区别;】中有详细介绍;


(2)第二步:新建一个实现了HandlerInterceptor接口的类;

MyInterceptor类:

package com.imooc.restful.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取当前的url地址,打印一下示意性的信息;
        System.out.println(request.getRequestURL() + "请求还未进入Controller之前,执行preHandle()方法。");
        //如果返回return true;那么请求就会被送达给【后面的拦截器(如果还有的话)】,或者送给Controller;
        //如果返回return false;那么当前的请求就会被阻止,直接产生响应,返回给客户端;
        //即,这个return的结果,决定了当前请求是继续向后传递执行,还是立即结束、返回响应;
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println(request.getRequestURL() + "Controller方法return以后,但还未产生响应文本之前,执行postHandle()方法。");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println(request.getRequestURL() + "响应文本产生后,执行afterCompletion()方法。");
    }
}

说明:

(1)HandlerInterceptor接口的完整地址是org.springframework.web.servlet.HandlerInterceptor,可以看到这个接口是Spring中定义的;

(2)HandlerInterceptor接口中的三个方法说明:这三个方法对应了三个不同的执行时机;

          ● preHandle():前置执行处理:意思是:一个请求产生后,在请求还未进Controller之前,先要执行preHandle()方法,对这个请求进行预置处理;

          ● postHandle():目标资源已被Spring MVC框架处理:意思是:【Controller的方法已经处理了请求,Controller方法return以后,但还未产生响应文本之前】,在这个时机执行postHandle()方法;

          ● afterCompletion():响应文本已经产生:意思是:产生了响应文本以后,afterCompletion()方法就会被自动执行;(如果Controller方法返回的是ModelAndView,那么数据和模板引擎混合后,会产生一个HTML片段,然后afterCompletion()方法就会被执行;;;;如果Controller方法返回的是一个需要被JSON序列化的对象,那么当jackson组件把这个对象序列化为JSON字符串后,afterCompletion()方法就会被执行)

          ● 这个三个方法在执行时,是按照时间顺序,有序执行的;

(3)preHandle()、postHandle()、afterCompletion()方法的参数,印证了为什么我们在第一步,要先引入servlet依赖;

(4)代码内容说明:

强调一些preHandle()方法的返回值问题:

          ● 首先,一个前提,一个项目可能有多个拦截器,即同一个请求可能会被多个拦截器处理,然后再传给Controller;

          ● 如果preHandle()方法,返回true的话:那么请求就会被送给后面的拦截器(如果还有的话),或者送给Controller;

          ● 如果preHandle()方法,返回false的话:那么当前的请求就会被阻止,直接产生响应,返回给客户端;

          ● 即,这个return的结果,决定了当前请求是继续向后传递执行,还是立即结束、返回响应;


虽然,上面写了实现了HandlerInterceptor接口的MyInterceptor类;但是,Spring MVC还不认识这个类的;我们需要在applicationContext.xml中对其进行配置,就是第三步的内容;

(3)第三步:在applicationContext.xml中配置过滤地址;

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.imooc.restful.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

说明:

(1)内容说明:主要配置两项:【拦截哪些url】,【使用哪个类来处理,拦截到的url】;

其中, 【path="/**"】表示,拦截所有请求; 

(2)一个<mvc:interceptor>中,只能配置一个bean节点;


(4)启动Tomcat,观察效果;

可以看到, preHandle()、postHandle()、afterCompletion()这三个方法的执行顺序,符合预期;

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值