ramostear.comramostear.com 谭朝红的技术分享博客

格言 编程是一门技术,也是一门艺术 !

spring boot中使用拦截器

spring boot中使用拦截器

Spring Boot (八)— 拦截器

在Spring Boot应用程序中,可以使用拦截器对Request请求到达控制器前和Response响应发送到客户端前进行拦截,并做相应的操作,如添加请求头信息或者进行鉴权等操作。在本章节中,我将演示如何在Spring Boot应用程序中使用拦截器。

在开始正文之前,我们先通过一张图来了解Spring Boot应用程序中拦截器的使用步骤:

首先,我们需要定义一个拦截器类,并使用@Component注解进行标注,此外,该拦截器类还需要实现HandlerInterceptor接口的三个方法:

  • preHandle() : 用于在请求发送到控制器前执行操作
  • postHandle : 用于在将响应发送到客户端之前进行操作
  • afterHandle : 用于在完成请求和响应后执行操作

1. 创建拦截器 — UserServiceInterceptor.java

package com.ramostear.application.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * @author ramostear
 * @create-time 2019/3/6 0006-23:55
 * @modify by :
 * @since:
 */
@Component
public class UserServiceInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("Pre handle method is calling.");
        logger.info("Request URL is : "+ request.getRequestURL());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        logger.info("Post handle method is calling.");
        logger.info("Response Status is : "+response.getStatus());
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        logger.info("Request and Response is completed.");
    }
}

在上述的拦截器中,我们在请求发送到控制器之前,记录了当前请求的URL地址,在控制器执行完操作响应客户端之前,记录了当前响应的状态码;最后,在完成请求和响应后,记录请求和响应已经完成的消息。

2. 注册拦截器

接下来,我们需要将定义好的拦截器注册到拦截器注册表中。在Spring Boot 2.0中,我们可以通过扩展WebMvcConfigurationSupport类来注册我们的拦截器:

package com.ramostear.application.config;

import com.ramostear.application.interceptor.UserServiceInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

/**
 * @author ramostear
 * @create-time 2019/3/7 0007-2:42
 * @modify by :
 * @since:
 */
@Component
public class UserServiceInterceptorConfig extends WebMvcConfigurationSupport{

    @Autowired
    UserServiceInterceptor userServiceInterceptor;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(userServiceInterceptor);
    }
}

说明:在Spring Boot 2.0及以后的版本中,WebMvcConfigurerAdapter类已经被废弃掉了,所以我们可以选择直接实现WebMvcConfigurer 接口中的方法来注册自定义拦截器,也可以选择扩展WebMvcConfigurationSupport类来注册自定义的拦截器。这里采用扩展WebMvcConfigurationSupport类的方式注册自定义的拦截器。

以下是Spring 官方的文档信息:

/**
* @author Rossen Stoyanchev
* @since 3.1
* @deprecated as of 5.0 {@link WebMvcConfigurer} has default methods (made
* possible by a Java 8 baseline) and can be implemented directly without the
* need for this adapter
*/
@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
    ...
}

3. 控制器 — UserServiceController.java

我们将定义一个控制器来处理客户端的请求,客户端通过HTTP GET方法请求用户资源信息:

package com.ramostear.application.controller;

import com.ramostear.application.model.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ramostear
 * @create-time 2019/3/7 0007-2:51
 * @modify by :
 * @since:
 */
@RestController
public class UserServiceController {

    private static Map<Long,User> userRepo = new HashMap<>();

    @PostConstruct
    public void initUserRepo(){
        User admin = new User().setId(1).setName("admin");
        User editor = new User().setId(2).setName("editor");
        userRepo.put(admin.getId(),admin);
        userRepo.put(editor.getId(),editor);
    }

    @GetMapping("/users")
    public ResponseEntity<Object> getUsers(){
        return new ResponseEntity<>(userRepo.values(), HttpStatus.OK);
    }

}

4. POJO类 — User.java

用户信息模型的POJO类代码如下所示:

package com.ramostear.application.model;

import lombok.Data;

/**
 * @author ramostear
 * @create-time 2019/3/6 0006-23:52
 * @modify by :
 * @since:
 */
@Data
public class User {

    private long id;

    private String name;

    public User setId(long id){
        this.id = id;
        return this;
    }

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

5.应用主类 — InterceptorApplication.java

应用程序的主类代码如下所示:

package com.ramostear.application;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class InterceptorApplication {

    public static void main(String[] args) {
        SpringApplication.run(InterceptorApplication.class, args);
    }

}

6. Maven构建文件 — pom.xml

maven 构建文件代码清单如下所示:

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ramostear</groupId>
    <artifactId>interceptor</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>interceptor</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

7. 运行程序并测试

你可以使用maven的“mvn clean install”命令来进行打包,然后使用java -jar 命令来运行项目,也可以使用集成开发环境IDEA或者Eclipse来打包运行项目。

现在,我们的应用程序在Tomcat服务器上使用8080端口启动成功,控制台输出信息如下所示:

接下来,启动Postman应用程序,在地址栏输入:http://localhost:8080/users ,并以GET的方式发送请求,如下图所示:

测试显示,控制器成功返回了用户信息,最后,让我们观察控制台窗口输出的信息:

通过控制台显示的信息可知,我们的拦截器已经成功的对客户端的请求以及服务端的响应进行了拦截。