测试开发【Mock平台】10基础:拦截器实现Mock功能(一)探索HandlerInterceptor

【Mock平台】为系列测试开发教程,从0到1编码带你一步步使用Spring Boot 和 Antd React框架完成搭建一个测试工具平台,希望作为一个实战项目对各位的测试开发学习之路有帮助,大奇一个专注测试技术干货原创与分享的家伙。

在本系列 Mock 平台开发过程中,接口拦截服务核心是用到了 spring boot 中的 HandlerInterceptor 类,它主要进行所有请求的拦截服务。另外还需要一个 WebMvcConfigurer 对其拦截内容进行 JavaBean 形式的配置。这一篇我们先来认识和简单的应用HandlerInterceptor,看看如何实现不同需求的拦截。

HandlerInterceptor

通过查看类源代码,HandlerInterceptor 接口类只有三个方法,在我们 controller 应用层面分别表示:

  • preHandle:在 Controller 执行之前调用,如果返回 false,controller 不执行;
  • postHandle:controller 执行之后,且页面渲染之前调用;
  • afterCompletion:页面渲染之后调用,一般用于资源清理操作。
public interface HandlerInterceptor {default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;}default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {}
}

因此要实现接口拦截,我们只需要创建一个类,并通过 implements 实现这个接类,相应地在 preHandle 实现业务逻辑即可。注意我们的项目前后端是完全分离的,所以对于 postHandle 页面渲染和 afterCompletion 资源相关的逻辑用不到。

在之前创建项目的时候,我们就已经创建过一个空的 qmock-service-gateway 服务项目,现在通过 IDE 工具打开此 Spring boot 项目,在 src 跟目录下创建一个自定义拦截器类 QMockInterceptor,并实现接口方法 preHandle 做一个默认的结果返回。这里先举例一个简单可运行的 demo 代码:

package cn.daqi.mock.gateway;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;@Slf4j
public class QMockInterceptor implements HandlerInterceptor{// 在Controller执行之前调用,如果返回false,controller不执行public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("====== 执行Mock服务: START ======");// 获取基本请求信息String requestURI = request.getRequestURI();String requestMethod = request.getMethod();log.info("拦截URI为".concat(requestURI).concat(",方法为").concat(requestMethod));JSONObject resBody = new JSONObject();resBody.put("uri", requestURI);resBody.put("method", requestMethod);JSONObject resResult = new JSONObject();resResult.put("code", 200);resResult.put("data", resBody);// 封装返回数据response.setContentType("application/json");response.setCharacterEncoding("UTF-8");PrintWriter printWriter = response.getWriter();printWriter.write(JSONObject.toJSONString(resResult));printWriter.flush();printWriter.close();log.info("====== 执行Mock服务: END ======");// 只做匹配数据返回,所以不需要执行任何controllerreturn false;}
}

再添加一个配置器,具体它的方法使用将在后边讲解。

package cn.daqi.mock.gateway;import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.*;@SpringBootConfiguration
public class QMockAdapter implements WebMvcConfigurer {@Beanpublic QMockInterceptor mockInterceptor(){return new QMockInterceptor();}// 正则匹配所有路径请求public void addInterceptors(InterceptorRegistry registry){registry.addInterceptor(new QMockInterceptor()).addPathPatterns("/**");}
}

最后运行这个 demo,我们只需要 run QMockServiceGatewayApplication.java 类即可。请注意,这是个新项目如有在拷贝复制代码的过程中遇到依赖报错,记得在 pom.xml 新增加以下依赖包:

<!--web服务包,拦截和配置服务依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><!--JSON对象-->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.56</version>
</dependency><!--注解类依赖-->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>

另外为了避免默认端口冲突,我们还需要给这个项目application.properties配置另外一个服务端口,比如:

server.port=8089

结果验证,我们通过 curl 或者 postman 工具,看是否得到返回

  • GET 请求
> curl http://localhost:8089/api/demo/get
{"code":200,"data":{"method":"GET","uri":"/api/demo/get"}}
  • POST 请求
    在这里插入图片描述

从上边的 demo 中我们注意到 preHandle 方法中的有两个参数类 HttpServletRequest 提供请求信息,和 HttpServletResponse 提供返回信息。

因此我们实现 mock 拦截网关服务的逻辑处理就在于此,通过 request 获取请求方法、路径、参数等去数据库匹配,如果有匹配的配置 mock 数据,则按照设定的返回值塞到 response 中返回来完成接口 Mock 服务。

通过查看源码 HttpServletRequestServletRequest类,里边方法很多可自行查看,这里重点认识下几个获取参数的方法:

  • getQueryString 方法返回请求 URL 中的查询字符串部分,即 URL 中位于问号后面的内容。

    例如,对于 URL ‘http://example.com/page?param1=value1&param2=value2’,getQueryString()方法将返回param1=value1&param2=value2。返回的是一个字符串,包含了原始的查询字符串内容

  • getParameterMap 方法用于获取请求参数的映射,返回一个 Map<String, String[]>对象,其中键是参数名,值是参数值的字符串数组。

    例如,对于URL ‘http://example.com/page?param1=value1&param2=value2’,并且请求体中有参数param3=value3,getParameterMap()方法将返回一个Map,其中包含三个键值对:param1 -> [“value1”],param2 -> [“value2”],param3 -> [“value3”]。它会解析请求中的参数,包括查询字符串和请求体中的参数。如果有多个同名参数,它们将作为数组值存储在Map中。

  • getInputStream 方法用于获取请求的输入流。它返回一个InputStream对象,可以用于读取请求的主体数据。

    当HTTP请求是POST或PUT请求,并且请求中包含主体数据时,可以使用getInputStream()方法来获取请求主体的内容。通过读取输入流,您可以获取请求的原始数据并进行处理,例如解析JSON或其他自定义格式的数据。
    另外需要注意的一点是:一旦使用getInputStream()方法读取了输入流中的数据,就无法再使用getParameter()或getParameterMap()等方法来获取请求参数。这是因为这些方法在读取输入流后会失效。

最后基于上边演示代码,增加两行getQueryString和getParameterMap获取参数的代码,通过打断点来看下都是获取params参数的本质区别:

  1. 增加获取参数代码,debug模式下启动会晤,并在打上断点。
String query = URLDecoder.decode(request.getQueryString());  // 断点处
Map<String, String[]> param = request.getParameterMap();
  1. 通过postman请求接口并在params和form-data里给定键值对值
    在这里插入图片描述

  2. 执行调试模式查看获取的参数值
    在这里插入图片描述

至此,我们实现了请求接口相关信息的拦截,后续我们将在此基础上进行规则​判断返回,来真正实现Mock服务。

下一篇我们稍微扩展的讲一下它的搭档 WebMvcConfigurer ,看看它的一些作用,这样能更结合自身项目需求来更友好的配置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/103662.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

揭秘#AI Grant 第二期项目,我是如何用AI获取灵感的?

hi&#xff0c;大家好&#xff0c;最近看到一篇文章&#xff0c;介绍了 AI版YC的二期项目&#xff0c;里面的项目非常值得我们去研究&#xff0c;推荐给大家&#xff1a; aigrant.com AI版YC 指的是 AI Grant&#xff0c;这是一家&#xff1a; 提供资金和支持的加速器项目由Nat…

JAVA怎么进行内存管理? - 易智编译EaseEditing

Java使用自动内存管理系统&#xff0c;主要通过垃圾回收器&#xff08;Garbage Collector&#xff09;来进行内存管理。这意味着开发人员不需要手动分配或释放内存&#xff0c;而是让垃圾回收器来处理不再使用的对象的内存释放。以下是关于Java内存管理的一些重要概念和建议&am…

C语言——程序环境和预处理(再也不用担心会忘记预处理的知识)

了解程序环境和预处理 前言&#xff1a;一、程序环境二、编译链接2.1 翻译环境2.2 编译的几个阶段2.3 运行环境 三、预处理3.1 预定义符号3.2. #define的使用3.2.1 #define 定义标识符3.2.2 #define 定义宏3.2.3 #define 替换规则3.2.4 #和##的用途3.2.5 带副作用的宏参数3.2.6…

postgresql|数据库|数据迁移神器ora2pg的安装部署和初步使用

前言&#xff1a; 有的时候有需求需要迁移Oracle数据库的数据到postgresql&#xff0c;那么&#xff0c;其实可供选择的工具是比较多的&#xff0c;但从迁移效率&#xff0c;准确度这些角度来选择的话&#xff0c;无疑还是GitHub上的开源免费工具ora2pg比较合适的。 ora2pg的…

MyBatis快速入门

JDBC介绍&#xff1a; JDBC&#xff1a;就是使用Java语言操作关系型数据库的一套API 本质&#xff1a; sun公司官方定义的一套操作所有关系型数据库的规范&#xff0c;即接口 各个数据库厂商去实现这套接口&#xff0c;提供数据库驱动jar包 我们可以使用这套接口&#xff08;J…

快速掌握STM32工程创建

STM32 工程创建-- 使用Keil uVision5 软件 晓理紫 1 准备库函数库 STM32F10x_StdPeriph_Lib_V3.5.0 VX 搜索“晓丽紫”关注回复STM32F10x即可下载 2、创建一个目录用来存放工程 STM32Study STM32Study/study1 存放本次工程目录 3、打开Keil uVision5 创建工程 4、选择型号(根据…

docker从零部署jenkins保姆级教程(上)

jenkins&#xff0c;基本是最常用的持续集成工具。在实际的工作中&#xff0c;后端研发一般没有jenkins的操作权限&#xff0c;只有一些查看权限&#xff0c;但是我们的代码是经过这个工具构建出来部署到服务器的&#xff0c;所以我觉着有必要了解一下这个工具的搭建过程以及简…

SpringAOP面向切面编程

文章目录 一. AOP是什么&#xff1f;二. AOP相关概念三. SpringAOP的简单演示四. SpringAOP实现原理 一. AOP是什么&#xff1f; AOP&#xff08;Aspect Oriented Programming&#xff09;&#xff1a;面向切面编程&#xff0c;它是一种编程思想&#xff0c;是对某一类事情的集…

PaddleOCR学习笔记3-通用识别服务

今天优化了下之前的初步识别服务的python代码和html代码。 采用flask paddleocr bootstrap快速搭建OCR识别服务。 代码结构如下&#xff1a; 模板页面代码文件如下&#xff1a; upload.html : <!DOCTYPE html> <html> <meta charset"utf-8"> …

【数据结构-栈】栈基础

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

【进阶篇】Redis内存淘汰详解

文章目录 Redis内存淘汰详解0. 前言大纲Redis内存淘汰策略 1. 什么是Redis内存淘汰策略&#xff1f;1.1.Redis 内存不足的迹象 2. Redis内存淘汰策略3. 原理4. 主动和被动1. 主动淘汰1.1 键的生存周期1.2 过期键删除策略 2. 被动淘汰2.2 被动淘汰策略的实现 5. 项目实践优化策略…

Android 播放mp3文件

1&#xff0c;在res/raw中加入mp3文件 2&#xff0c;实现播放类 import android.content.Context; import android.media.AudioManager; import android.media.SoundPool; import android.util.Log;import java.util.HashMap; import java.util.Map;public class UtilSound {pu…