标签: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编程的更多相关文章

  1. PHP求职宝典系列——PHP Web 编程篇

    PHP Web 编程篇 form表单 1.简述 POST 和 GET 传输的最大容量分别是多少? GET 方法提交的表单数据被附加到 URL 上,并作为URL 的一部分发送到服务器端. URL 的长度 ...

  2. Web编程基础--HTML、CSS、JavaScript 学习之课程作业“仿360极速浏览器新标签页”

    Web编程基础--HTML.CSS.JavaScript 学习之课程作业"仿360极速浏览器新标签页" 背景: 作为一个中专网站建设出身,之前总是做静态的HTML+CSS+DIV没 ...

  3. Java Web 编程

    Java Web 编程 21天学通JAVA-WEB开发:http://files.cnblogs.com/files/maven-chao/Java_Web.zip

  4. python web编程-概念预热篇

    互联网正在引发一场革命??不喜欢看概念的跳过,注意这里仅仅是一些从python核心编程一书的摘抄 这正是最激动人心的一部分了,web编程 Web 客户端和服务器端交互使用的“语言”,Web 交互的标准 ...

  5. 物联网网络编程、Web编程综述

    本文是基于嵌入式物联网研发工程师的视觉对网络编程和web编程进行阐述.对于专注J2EE后端服务开发的童鞋们来说,这篇文章可能稍显简单.但是网络编程和web编程对于绝大部分嵌入式物联网工程师来说是一块真 ...

  6. 《Web编程入门经典》

    在我还不知道网页的基础结构的时候,我找过很多本介绍Web基础的书籍,其中这本<Web编程入门经典>,我认为是最好的. 这本书内容很全面.逻辑很严谨.结构很清晰.语言文字浅显易懂. 看这本书 ...

  7. 全部编程皆为Web编程

    原文作者:Jeff Atwood   原文链接:http://blog.codinghorror.com/all-programming-is-web-programming Michael Brau ...

  8. MVC 5 Web编程2 -- URL映射

    ASP.NET MVC 5 Web编程2 -- URL映射(路由原理) 2015-02-12 08:50 by hangwei, 704 阅读, 5 评论, 收藏, 编辑 本章将讲述ASP.NET M ...

  9. Go web编程实例

    1. go web编程入门 记录个web编程例子方便以后使用. 主要有: chan的使用(带缓存,不带缓存) client发起get/post请求 server解析get/post请求参数 http. ...

  10. windows下《Go Web编程》之Go环境配置和安装

    <Go Web编程>笔者是基于unix下讲述的,作为入门练手,我选择在windows下开发,全程按照目录进行... 一.安装 windows下需要安装MinGW,通过MinGW安装gcc支 ...

随机推荐

  1. 2023-02-17:sdl是跨平台的多媒体开发库,请问用go语言如何调用?

    2023-02-17:sdl是跨平台的多媒体开发库,请问用go语言如何调用? 答案2023-02-17: 用 github.com/moonfdd/sdl2-go 这个库. 这是我自己写的golang ...

  2. 2022-09-29:在第 1 天,有一个人发现了一个秘密。 给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后, 每天 给一个新的人 分享 秘密。 同时给你一个整数 forg

    2022-09-29:在第 1 天,有一个人发现了一个秘密. 给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后, 每天 给一个新的人 分享 秘密. 同时给你一个整数 forg ...

  3. 2022-08-25:以下go语言代码输出什么?A:1 0;B:1 2;C:不能编译;D:0 0。 package main import “fmt“ func named() (n, _ int

    2022-08-25:以下go语言代码输出什么?A:1 0:B:1 2:C:不能编译:D:0 0. package main import "fmt" func named() ( ...

  4. 2021-02-16:n皇后问题。给定一个整数n,返回n皇后的摆法有多少种?

    福哥答案2021-02-16: 自然智慧即可.1.普通递归.有代码.需要判断同列和斜线.2.位运算递归.有代码.3.我的递归.有代码.只需要判断斜线. 代码用golang编写,代码如下: packag ...

  5. 数学建模 Excel的批量写入与批量导出

    数学建模中编程手们常常会被要求将大量的数据进行批量的预测操作,并写入某个文件中 Excel的批量导出数据,用循环就可以简单实现,例如 import pandas as pd for i in list ...

  6. Linux,会这些就够了

    在测试当中,其实对Linux的要求不高,我们在工作中需要记住常用的一些命令,不常用的实际用到的时候再查在记即可,最重要我们要使用命令可以查看日志,定位bug   目录篇: 可用  pwd  命令查看用 ...

  7. 为teamcity的代码语法检查工具pyflakes增加支持python2和python3

    TeamCity和pyflakes TeamCity是一款由JetBrains公司开发的持续集成和部署工具,它提供了丰富的功能来帮助团队协作进行软件开发.其中包括代码检查.自动化构建.测试运行.版本控 ...

  8. 苹果WWDC发布会总结

    今年的全球开发者大会没有让人失望.在今天的主题演讲中,苹果首次展示了备受期待的混合现实耳机,证实了过去几个月出现的许多谣言. 虽然这次苹果的 Vision Pro耳机成为了焦点,但该公司还发布了一些其 ...

  9. 曲线艺术编程 coding curves 第六章 平托图 (Pintographs)

    第六章 平托图 (Pintographs) 原作:Keith Peters https://www.bit-101.com/blog/2022/11/coding-curves/ 译者:池中物王二狗( ...

  10. 华为云新一代分布式数据库GaussDB,给世界一个更优选择

    摘要:与伙伴一起,共建繁荣开放的GaussDB数据库新生态. 本文分享自华为云社区<华为云新一代分布式数据库GaussDB,给世界一个更优选择>,作者:华为云头条. 6月7日,在华为全球智 ...