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);
@Override
public 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;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
log.info("HeadInterceptor:postHandle");
}
@Override
public 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);
@Override
public 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;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
log.info("BodyInterceptor:postHandle");
}
@Override
public 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 {
/**
* 添加自定义拦截器
*/
@Override
public 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 {
/**
* 接口文档配置
*/
@Bean
public 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 {
@Autowired
private MockMvc mockMvc;
@Test
public void testGet () throws Exception {
// GET接口测试
MvcResult mvcResult = mockMvc
.perform(MockMvcRequestBuilders.get("/rest/get/1"))
.andReturn();
printMvcResult(mvcResult);
}
@Test
public 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);
}
@Test
public 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);
}
@Test
public 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编程的更多相关文章
- PHP求职宝典系列——PHP Web 编程篇
PHP Web 编程篇 form表单 1.简述 POST 和 GET 传输的最大容量分别是多少? GET 方法提交的表单数据被附加到 URL 上,并作为URL 的一部分发送到服务器端. URL 的长度 ...
- Web编程基础--HTML、CSS、JavaScript 学习之课程作业“仿360极速浏览器新标签页”
Web编程基础--HTML.CSS.JavaScript 学习之课程作业"仿360极速浏览器新标签页" 背景: 作为一个中专网站建设出身,之前总是做静态的HTML+CSS+DIV没 ...
- Java Web 编程
Java Web 编程 21天学通JAVA-WEB开发:http://files.cnblogs.com/files/maven-chao/Java_Web.zip
- python web编程-概念预热篇
互联网正在引发一场革命??不喜欢看概念的跳过,注意这里仅仅是一些从python核心编程一书的摘抄 这正是最激动人心的一部分了,web编程 Web 客户端和服务器端交互使用的“语言”,Web 交互的标准 ...
- 物联网网络编程、Web编程综述
本文是基于嵌入式物联网研发工程师的视觉对网络编程和web编程进行阐述.对于专注J2EE后端服务开发的童鞋们来说,这篇文章可能稍显简单.但是网络编程和web编程对于绝大部分嵌入式物联网工程师来说是一块真 ...
- 《Web编程入门经典》
在我还不知道网页的基础结构的时候,我找过很多本介绍Web基础的书籍,其中这本<Web编程入门经典>,我认为是最好的. 这本书内容很全面.逻辑很严谨.结构很清晰.语言文字浅显易懂. 看这本书 ...
- 全部编程皆为Web编程
原文作者:Jeff Atwood 原文链接:http://blog.codinghorror.com/all-programming-is-web-programming Michael Brau ...
- MVC 5 Web编程2 -- URL映射
ASP.NET MVC 5 Web编程2 -- URL映射(路由原理) 2015-02-12 08:50 by hangwei, 704 阅读, 5 评论, 收藏, 编辑 本章将讲述ASP.NET M ...
- Go web编程实例
1. go web编程入门 记录个web编程例子方便以后使用. 主要有: chan的使用(带缓存,不带缓存) client发起get/post请求 server解析get/post请求参数 http. ...
- windows下《Go Web编程》之Go环境配置和安装
<Go Web编程>笔者是基于unix下讲述的,作为入门练手,我选择在windows下开发,全程按照目录进行... 一.安装 windows下需要安装MinGW,通过MinGW安装gcc支 ...
随机推荐
- Xposed框架关于无法在模拟器中下载和激活的问题
开头 最近xposed不知道出了什么问题,导致安装的时候一直在失败,所以记录下网上参考到的并用于实践中 安装软件 1.模拟器 逍遥游模拟器 安卓7.1 版本.下载地址为: https://www.52 ...
- python中的一些解码和编码
开头 最近爬取百度贴吧搜索页的时候遇到一个url的编码问题,颇为头疼,记录下来防止下次忘记 工具网站 解码编码的工具网站推荐 http://tool.chinaz.com/tools/urlencod ...
- vue下载附件按钮功能
一.tools文件夹下tools文件中封装下载方法: const iframeId = 'download_file_iframe' function iframeEle (src) { let el ...
- 2021-03-31:给定一个数组arr,给定一个值v。求子数组平均值小于等于v的最长子数组长度。
2021-03-31:给定一个数组arr,给定一个值v.求子数组平均值小于等于v的最长子数组长度. 福大大 答案2021-03-31: 这道题是昨天每日一题的变种.数组每个元素减v,然后求<=0 ...
- ArcMap手动新建矢量要素的方式
本文介绍在ArcGIS下属ArcMap软件中,新建点.线.面等矢量要素图层,并对新建图层的空间范围加以划定的方法. 首先,在右侧"Catalog"栏中选择需要存放新建立矢量 ...
- Vue——前端发展史、Vue介绍和使用、插值语法、文本指令、事件指令
前端的发展史 # 1 HTML(5).CSS(3).JavaScript(ES5.ES6):编写一个个的页面 -> 给后端(PHP.Python.Go.Java) -> 后端嵌入模板语法 ...
- Kubernetes 集群管理:Kurator or Kubespray
摘要:Kubespray 和 Kurator 就是这类开源工具的典型代表.本文将对这两款工具进行比较. 本文分享自华为云社区<Kubernetes 集群管理:Kurator or Kubespr ...
- 前端学习C语言 - 开篇
前端学习C语言 - 开篇 前端学习C语言有很多理由:工作.兴趣或其他. C 语言几个常见的使用场景: 操作系统开发:Linux 操作系统的内核就是主要由 C 语言编写的.其他操作系统也广泛使用 C 语 ...
- 【技术积累】JavaSciprt中的函数【一】
什么是函数?如何声明函数? JavaScript中的函数是一段可重复使用的代码块,它可以接受输入并返回输出. 在JavaScript中,函数是一种特殊的对象,因此可以将其存储在变量中,将其作为参数传递 ...
- uniapp微信小程序转支付宝小程序踩坑(持续更新)
首先第一个,真有被折磨到! // 微信正常使用,支付宝不行 <image src="https://static.dabapiao.com/images/coupon-index.pn ...