SpringBoot3之Web编程
标签:Rest.拦截器.swagger.测试;
一、简介
基于web
包的依赖,SpringBoot可以快速启动一个web
容器,简化项目的开发;
在web
开发中又涉及如下几个功能点:
拦截器:可以让接口被访问之前,将请求拦截到,通过对请求的识别和校验,判断请求是否允许通过;
页面交互:对于服务端的开发来说,需要具备简单的页面开发能力,解决部分场景的需求;
Swagger接口:通过简单的配置,快速生成接口的描述,并且提供对接口的测试能力;
Junit测试:通过编写代码的方式对接口进行测试,从而完成对接口的检查和验证,并且可以不入侵原代码结构;
二、工程搭建
1、工程结构
2、依赖管理
<!-- 基础框架组件 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${spring-boot.version}</version>
</dependency>
<!-- 接口文档组件 -->
<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>${springdoc.version}</version>
</dependency>
<!-- 前端页面组件 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>${spring-boot.version}</version>
</dependency>
<!-- 单元测试组件 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${spring-boot.version}</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version>
</dependency>
三、Web开发
1、接口开发
编写四个简单常规的接口,从对资源操作的角度,也就是常说的:增Post
、删Delete
、改Put
、查Get
,并且使用了swagger
注解,可以快速生成接口文档;
@RestController
@Tag(name = "Rest接口")
public class RestWeb {@Operation(summary = "Get接口")@GetMapping("rest/get/{id}")public String restGet(@PathVariable Integer id) {return "OK:"+id;}@Operation(summary = "Post接口")@PostMapping("/rest/post")public String restPost(@RequestBody ParamBO param){return "OK:"+param.getName();}@Operation(summary = "Put接口")@PutMapping("/rest/put")public String restPut(@RequestBody ParamBO param){return "OK:"+param.getId();}@Operation(summary = "Delete接口")@DeleteMapping("/rest/delete/{id}")public String restDelete(@PathVariable Integer id){return "OK:"+id;}
}
2、页面交互
对于服务端开发来说,在部分场景下是需要进行简单的页面开发的,比如通过页面渲染再去生成文件,或者直接通过页面填充邮件内容等;
数据接口
@Controller
public class PageWeb {@RequestMapping("/page/view")public ModelAndView pageView (HttpServletRequest request){ModelAndView modelAndView = new ModelAndView() ;// 普通参数modelAndView.addObject("name", "cicada");modelAndView.addObject("time", "2023-07-12");// 对象模型modelAndView.addObject("page", new PageBO(7,"页面数据模型"));// List集合List<PageBO> pageList = new ArrayList<>() ;pageList.add(new PageBO(1,"第一页"));pageList.add(new PageBO(2,"第二页"));modelAndView.addObject("pageList", pageList);// Array数组PageBO[] pageArr = new PageBO[]{new PageBO(6,"第六页"),new PageBO(7,"第七页")} ;modelAndView.addObject("pageArr", pageArr);modelAndView.setViewName("/page-view");return modelAndView ;}
}
页面解析:分别解析了普通参数,实体对象,集合容器,数组容器等几种数据模型;
<div style="text-align: center"><hr/><h5>普通参数解析</h5>姓名:<span th:text="${name}"></span>时间:<span th:text="${time}"></span><hr/><h5>对象模型解析</h5>整形:<span th:text="${page.getKey()}"></span>字符:<span th:text="${page.getValue()}"></span><hr/><h5>集合容器解析</h5><table style="margin:0 auto;width: 200px"><tr><th>Key</th><th>Value</th></tr><tr th:each="page:${pageList}"><td th:text="${page.getKey()}"></td><td th:text="${page.getValue()}"></td></tr></table><hr/><h5>数组容器解析</h5><table style="margin:0 auto;width: 200px"><tr><th>Key</th><th>Value</th></tr><tr th:each="page:${pageArr}"><td th:text="${page.getKey()}"></td><td th:text="${page.getValue()}"></td></tr></table><hr/>
</div>
效果图展示
四、拦截器
1、拦截器定义
通过实现HandlerInterceptor
接口,完成对两个拦截器的自定义,请求在访问服务时,必须通过两个拦截器的校验;
/*** 拦截器一*/
public class HeadInterceptor implements HandlerInterceptor {private static final Logger log = LoggerFactory.getLogger(HeadInterceptor.class);@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {log.info("HeadInterceptor:preHandle");Iterator<String> headNames = request.getHeaderNames().asIterator();log.info("request-header");while (headNames.hasNext()){String headName = headNames.next();String headValue = request.getHeader(headName);System.out.println(headName+":"+headValue);}// 放开拦截return true;}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {log.info("HeadInterceptor:postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler, Exception e) throws Exception {log.info("HeadInterceptor:afterCompletion");}
}/*** 拦截器二*/
public class BodyInterceptor implements HandlerInterceptor {private static final Logger log = LoggerFactory.getLogger(BodyInterceptor.class);@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {log.info("BodyInterceptor:preHandle");Iterator<String> paramNames = request.getParameterNames().asIterator();log.info("request-param");while (paramNames.hasNext()){String paramName = paramNames.next();String paramValue = request.getParameter(paramName);System.out.println(paramName+":"+paramValue);}// 放开拦截return true;}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {log.info("BodyInterceptor:postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler, Exception e) throws Exception {log.info("BodyInterceptor:afterCompletion");}
}
2、拦截器配置
自定义拦截器之后,还需要添加到web工程的配置文件中,可以通过实现WebMvcConfigurer
接口,完成自定义的配置添加;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {/*** 添加自定义拦截器*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new HeadInterceptor()).addPathPatterns("/**");registry.addInterceptor(new BodyInterceptor()).addPathPatterns("/**");}
}
五、测试工具
1、Swagger接口
添加上述的springdoc
依赖之后,还可以在配置文件中简单定义一些信息,访问IP:端口/swagger-ui/index.html
即可;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {/*** 接口文档配置*/@Beanpublic OpenAPI openAPI() {return new OpenAPI().info(new Info().title("【boot-web】").description("Rest接口文档-2023-07-11").version("1.0.0"));}
}
2、Junit测试
在个人的习惯上,Swagger
接口文档更偏向在前后端对接的时候使用,而Junit
单元测试更符合开发的时候使用,这里是对RestWeb
中的接口进行测试;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class RestWebTest {@Autowiredprivate MockMvc mockMvc;@Testpublic void testGet () throws Exception {// GET接口测试MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/rest/get/1")).andReturn();printMvcResult(mvcResult);}@Testpublic void testPost () throws Exception {// 参数模型JsonMapper jsonMapper = new JsonMapper();ParamBO param = new ParamBO(null,"单元测试",new Date()) ;String paramJson = jsonMapper.writeValueAsString(param) ;// Post接口测试MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/rest/post").contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).content(paramJson)).andReturn();printMvcResult(mvcResult);}@Testpublic void testPut () throws Exception {// 参数模型JsonMapper jsonMapper = new JsonMapper();ParamBO param = new ParamBO(7,"Junit组件",new Date()) ;String paramJson = jsonMapper.writeValueAsString(param) ;// Put接口测试MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.put("/rest/put").contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).content(paramJson)).andReturn();printMvcResult(mvcResult);}@Testpublic void testDelete () throws Exception {// Delete接口测试MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.delete("/rest/delete/2")).andReturn();printMvcResult(mvcResult);}/*** 打印【MvcResult】信息*/private void printMvcResult (MvcResult mvcResult) throws Exception {System.out.println("请求-URI【"+mvcResult.getRequest().getRequestURI()+"】");System.out.println("响应-status【"+mvcResult.getResponse().getStatus()+"】");System.out.println("响应-content【"+mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8)+"】");}
}
六、参考源码
文档仓库:
https://gitee.com/cicadasmile/butte-java-note源码仓库:
https://gitee.com/cicadasmile/butte-spring-parent
相关文章:

SpringBoot3之Web编程
标签:Rest.拦截器.swagger.测试; 一、简介 基于web包的依赖,SpringBoot可以快速启动一个web容器,简化项目的开发; 在web开发中又涉及如下几个功能点: 拦截器:可以让接口被访问之前,将请求拦截…...

策略模式(C++)
定义 定义一系列算法,把它们一个个封装起来,并且使它们可互相替换((变化)。该模式使得算法可独立手使用它的客户程序稳定)而变化(扩展,子类化)。 ——《设计模式》GoF 使用场景 在软件构建过程中,某些对象使用的算法可能多种多…...
【每日一题Day290】LC1281整数的各位积和之差 | 模拟
整数的各位积和之差【LC1281】 给你一个整数 n,请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。 思路:简单模拟 循环取余,计算「各位数字之积」与「各位数字之和」,最后求差返回 实现 class Solution {public…...

揭示CTGAN的潜力:利用生成AI进行合成数据
推荐:使用 NSDT场景编辑器 助你快速搭建可编辑的3D应用场景 我们都知道,GAN在生成非结构化合成数据(如图像和文本)方面越来越受欢迎。然而,在使用GAN生成合成表格数据方面所做的工作很少。合成数据具有许多好处&#x…...
GitHub中readme.md文件的编辑和使用
GitHub中readme.md文件的编辑和使用 | YuuiChungs BlogGitHub - guodongxiaren/README: README文件语法解读,即Github Flavored Markdown语法介绍...
Python 四舍五入到最接近的十位
本篇文章将讨论使用 Python 的 ceil() 函数将数字四舍五入到最接近的十。 Python 整数到最接近的十 Python 具有三个内置函数 round()、floor() 和 ceil(),可用于对数字进行舍入。 ceil() 函数属于数学模块,用于将浮点数舍入为大于或等于给定数字的最接…...

Unity限制在一个范围内移动
Unity限制在一个范围内移动 这个例子中,我们学习Vector3.ClampMagnitude的用法,限制小球在范围内移动。 在地图上放了一个小球,让他移动,但是不想让他掉下去,限制在一个球星范围内,就好像绳子拴住了一样&…...
dji uav建图导航系列(一)建图
文章目录 1、uav + rplidir雷达1.2、思岚激光雷达1.3、dji uav的launch文件2、cartographer激光建图2.1、启动文件2.2、config修改2.3、建图过程3、融合odom+laser建图1、uav + rplidir雷达 思岚激光雷达frame为base_laser_link, 无人机frame为base_footprint。 文件uav_lid…...

AAAI论文阅读
文章目录 Open-Vocabulary Multi-Label Classifcation via Multi-Modal Knowledge Transfer——知识蒸馏的范畴Med-EASi: Finely Annotated Dataset and Models for Controllable Simplifcation of Medical Texts——医学领域数据集构建“Nothing Abnormal”: Disambiguating M…...

填补5G物联一张网,美格智能快速推进RedCap商用落地
自5G R17版本标准冻结以来,RedCap一直引人注目。2023年更是5G RedCap突破性发展的一年,从首款5G RedCap调制解调器及射频系统——骁龙X35发布,到国内四大运营商发布RedCap技术白皮书,芯片厂商、模组厂商、运营商及终端企业都在积极…...
服务器杂七杂八的知识/常识归纳(不断更新)
一.pID与端口号不一样吗? pID(Process ID,进程标识符)和端口号是不同的概念。 pID是操作系统中用来唯一标识一个正在运行的进程的数字。每个正在运行的进程都会被分配一个唯一的pID,它可以用来追踪和管理进程。 而端口号是在网…...
掌握Java排序算法:实现主流排序方法与性能对比
一,C语言,主流的排序方法介绍 当谈论主流的排序方法时,通常指的是在实际应用中表现优秀且被广泛采用的排序算法。以下是常见的主流排序方法及其介绍、时间复杂度、空间复杂度和简单的C语言代码实现: 冒泡排序(Bubble S…...
jdk17 SpringBoot JPA集成多数据库
switchRegion(切换地区)功能, 客户端可手动切换地区 , 查询不同的数据库, 后台根据地区切换数据库, 请求头添加region的key 配置类 import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; im…...

vue 新学习 06 js的prototype ,export暴露,vue组件,一个重要的内置关系
01 在js中: 原型链 注意:构造函数.prototype实例化对象.__proto__,都是指向函数的原型。 export: -export用于对外输出本模块(一个文件可以理解为一个模块)变量的接口 -import用于在一个模块中加载另一个…...

冠达管理:“高温超导”不是“室温超导”,5天4板百利电气再次澄清
短短半个月,“室温超导”在惊喜、质疑间回转,但资本市场对“超导概念股”的炒作还在进行,8月7日室温超导概念持续疯涨。同花顺显现,到8月7日收盘,18只超导概念股中,有16只股票飘红。 广东研山私募证券投资&…...

CS 144 Lab Four 收尾 -- 网络交互全流程解析
CS 144 Lab Four 收尾 -- 网络交互全流程解析 引言Tun/Tap简介tcp_ipv4.cc文件配置信息初始化cs144实现的fd家族体系基于自定义fd体系进行数据读写的adapter适配器体系自定义socket体系自定义事件循环EventLoop模板类TCPSpongeSocket详解listen_and_accept方法_tcp_main方法_in…...
Linux面试专题
Linux面试专题 1 Linux中主要有哪几种内核锁?2 Linux 中的用户模式和内核模式是什么含意?3 怎样申请大块内核内存?4用户进程间通信主要哪几种方式?5通过伙伴系统申请内核内存的函数有哪些?6) Linux 虚拟文件系统的关键数据结构有哪些?(至少写出四个)7) 对文件或设备的操作…...
MySQL错误日志(Error Log)详解
错误日志(Error Log)是 MySQL 中最常用的一种日志,主要记录 MySQL 服务器启动和停止过程中的信息、服务器在运行过程中发生的故障和异常情况等。 作为初学者,要学会利用错误日志来定位问题。下面介绍如何操作查看错误日志。 启动…...

Qt应用开发(基础篇)——LCD数值类 QLCDNumber
一、前言 QLCDNumber类继承于QFrame,QFrame继承于QWidget,是Qt的一个基础小部件。 QLCDNumber用来显示一个带有类似lcd数字的数字,适用于信号灯、跑步机、体温计、时钟、电表、水表、血压计等仪器类产品的数值显示。 QLCDNumber可以显示十进制…...

新版百度、百家号旋转验证码识别
昨天突然发现,百度旋转验证码发生了变化,导致使用老版本验证码训练出来的识别模型效果不佳。所有昨天花了一天时间完成了新版模型的训练。 老版本验证码 新版本验证码 新版的验证码感觉像是AI绘画随机生成的,还有随机阴影出现。 验证码识别…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...
机器学习的数学基础:线性模型
线性模型 线性模型的基本形式为: f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法,得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...