一、SpringBoot解析
1、起步依赖
在搭建SpringBoot项目时,引入了web依赖和test依赖,这两个依赖是SpringBoot的起步(starter)依赖。
- 在SpringBoot中,以spring-boot-starter 为前缀的都是起步依赖(下图为web依赖和test依赖)
- SpringBoot自己起步依赖的版本是在创建时指定的springboot的版本
- 第三方起步依赖:以spring-boot-starter为后缀的都是第三方起步依赖
2、统一版本管理
SpringBoot通过Maven引入的版本号是没有指定依赖的,但是SpringBoot继承了一个父工程,依赖的版本在父工程内做统一的管理。
2.1 spring-boot-starter-parent
- 在项目文件下的pom.xml文件内可以[Ctrl+鼠标左键]进入他的父项目pom文件
- 在spring-boot-starter-parent.pom文件内可以看到此父项目管理的java版本号和springboot版本号
2.2 spring-boot-dependencies
spring-boot-starter-parent项目它还继承了一个父项目,这个项目的pom.xml文件中管理了依赖、插件和所有依赖的版本号。这就是创建的springboot项目可以省略version的原因
- 管理版本
- 管理依赖dependencyManagement
2.3 标签管理
1)properties
在标签内可以把版本号作为变量进行声明,后面dependency中用到版本号时可以用${变量名}的形式代替
2)dependencyManagement
依赖管理
3)build
描述了如何编译及打包项目,具体的编译和打包工作是通过其中的plugin配置来实现的
4)pluginManagement
插件管理
3、内嵌Tomcat服务器
项目要部署在Tomcat下的ROOT目录下才能运行,SpringBoot没有部署也能运行是因为SpringBoot内嵌了Tomcat服务器
4、主启动类
4.1 定义
在SpringBoot项目中有@SpringBootApplication注解就是主启动类
4.2 规范
①项目名称+Application
②项目名称+App
4.3 启动类的位置
1.如果域名下面有项目包,那么必须放在项目包下
2.如果没有项目包,那么就放在域名下
5、配置SpringBoot项目的文件
Tomcat默认的端口号是8080,如果不想用其默认的端口号,就可以在SpringBoot的配置文件内更改。
5.1 配置文件分类
后缀为.properties的文件内的配置优先级最高
- application.properties
- application.yaml
- application.yml
5.2 properties配置文件写法
properties以键值对(key=value)的方式编写配置
5.3 Yaml/Yml配置文件写法
- 键值对之间用的是冒号":"隔开,并且冒号后必须加一个空格
- 层级关系需要在前面加一个tab空格,也只能加一个tab
- key和value区分大小写(之前的驼峰用"-"隔开)
- value是字符串也不需要加双引号
5.4 多环境配置
# 最上面的就是默认配置,默认配置不需要指定profile
server:
# 设置端口号
port: 8081
spring:
profiles:
# 要启动的环境标识,如果环境标识在下面找不到那么就启动默认配置
active: dev
# 每套环境中间需要有此分隔符,分隔每套环境
---
server:
# 设置端口号
port: 8082
spring:
config:
activate:
on-profile: pro
---
server:
# 设置端口号
port: 8083
spring:
config:
activate:
on-profile: test
6、SpringBoot单元测试
6.1 定义
在JavaSE中有Junit的单元测试,在SpringBoot中有SpringBoot专门的单元测试,只有SpringBoot单元测试内才能使用SpringBoot的一些功能。
6.2 使用
- 想使用SpringBoot的单元测试,必须有spring-boot-starter-test依赖(此依赖是创建SpringBoot项目是引入的起步依赖)
- 建立一个springboot测试就是在测试类上加上一个@SpringBootTest,比如要导入spring-boot-starter-test依赖,方法上还是加@Test
6.3 @SpringBootTest注解
此注解告诉SpringBoot查找带 @SpringBootApplication 注解的主配置类,并使用该类启动 Spring 应用程序上下文,这样我们就可以使用SpringBoot的一些核心功能
7、开发模式
7.1 前后端不分离
把前端项目写在后端代码中,访问页面靠资源去访问
7.2 前后端分离
- 前端是一个项目,后端是一个项目,各不干扰,交互靠后端资源
- 前端项目使用NodeJs进行部署,后端使用Tomcat进行部署
8、控制器类
8.1 定义
写在controller下的并且以Controller结尾的类,我们称为控制器类,控制器类是用于接收前端请求的
8.2 控制器类要求
效果如上图所示
- 必须写在controller包下
- 必须以Controller结尾
- 类上必须加上@RestController/@Controller(建议加@RestController注解,因为其中包含了@Controller注解和@RequestBody注解)
- 方法上必须加上@RequestMapping("资源路径")
8.3 SpringMVC
8.3.1 概要
SpringMVC属于SpringFrameWork的后续产品,SpringMVC是Spring框架中Servlet的一部分。
是一个WEB框架,是spring中专用用来处理控制器类的一个框架。
在springboot中已经集成好了springmvc,我们只需要导入spring-boot-starter-web依赖就可以使用。
8.3.2 DispatcherServlet
SpringMVC其底层是一个Servlet(指的就是DispatcherServlet),所有的前端请求都是发到DispatcherServlet,并由它转发给对应的接口,所有的一切都是springmvc帮我们处理好的
8.4 请求&响应对象
8.4.1 HttpServletRequest
是springmvc帮我们准备好的请求对象,前端的所有请求过来的数据参数都可以获取到,比如ip+port
8.4.2HttpServletResponse
是springmvc帮我们准备好的响应对象,我们可以设置响应编码字符集,响应的数据格式,响应的数据等...
8.5 接口
控制器类的方法叫做接口,也叫做资源:请求后端接口也可以是请求后端资源/访问资源。
二、API协同研发工具
1、作用
前后端分离项目中,前端开发使用mock进行测试,后端开发使用postman进行测试。
2、下载工具-Apifox
Apifox官网:Apifox - API 文档、调试、Mock、测试一体化协作平台 - 接口文档工具,接口自动化测试工具,接口Mock工具,API文档工具,API Mock工具,API自动化测试工具,直接下载安装即可。
三、JSON
1、定义
英文名称JavaScript Object Notation,是一种轻量级的数据交换格式。
易于人阅读和编写,可以在多种语言之间进行数据交换,同时也易于机器解析和生成。是现在最主流的数据交换格式
2、格式要求
key必须用双引号,value如果是字符串/字符也必须用双引号
2.1 JSON一个对象格式
{
"key1":"value1",
"key2":"value2",
...
}
2.2 JSON多个对象格式
[
{
"key1":"value1",
"key2":"value2",
...
},
{
"key1":"value1",
"key2":"value2"
...
},
{
"key1":"value1",
"key2":"value2",
...
}
]
四、后端接收参数
1、参数接收,请求参数接收
使用HttpServletRequest对象的getParameter()方法获取参数
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
2、形参接收(普通参数-参数名一致)
直接在接口的方法中以形参的形式进行接收,形参名称必须跟前端对应
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
3、形参接收(普通参数-参数名不一致)
也是使用形参,但是后端形参名称与前端传递的不一致,使用@RequestParam(value="前端名称")写在字段名称不一致的形参前面,required属性是决定字段是否必填,默认为true
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
4、简单实体参数接收(对象)
创建一个实体类对象,对象中写字段+get+set+toString方法,接口方法上使用形参进行接收
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
5、复杂实体参数接收(对象内含对象字段)
创建一个复杂实体类对象,把对象当成字段,前端在传递参数的时候需要使用对象字段名称.字段名称进行传递
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
6、数组作为形参接收
数组就直接使用形参接收数组集合
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
7、集合作为参数接收
集合需要在形参前面加上一个@RequstParam注解
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
8、日期作为参数接收
形参正常写日期字段2.在日期字段前面加上@DateTimeFormat(pattrn="日期格式"),前端传递的时候必须按照此日期格式传递
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
9、JSON作为参数接收
后端接口必须在形参前面加上@RequestBody2.前端传递的时候必须放在请求体中进行传递
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
10、路径作为参数接收
在路径中使用/{参数名称}作为路径2.在形参中使用普通字段去接收路径中的值,必须在形参前面加上@PathVariable("路径{}中的字段名")
- 定义接口
- 用Postman(Apifox)发送请求
- 后端传输结果
五、公共路径抽取
在类上写上@ReuqestMapping("/模块名称"),代表当前controller类的一级路径,只要加上了一级路径访问此controller类下的所有接口都必须加上一级路径
六、响应
1、概要
- 企业开发中,前端发起了请求那么后端接口就会提供响应,并且通常我们会响应JSON格式数据给到前端
2、响应的体现
- 后端想要响应JSON数据那么就必须在接口上加上一个注解@ResponseBody,表示要将响应数据转换为JSON格式数据响应给前端。这也是前面说的前后端交互使用JSON格式
- @RestController:此注解是一个复合注解,里面包含了两个注解 ——@Controller+@ResponseBody,为了避免在每个方法上写@ResponseBody推荐以后直接使用@RestController
3、统一响应规范
3.1 定义
前后端交互会固定返回几个字段,帮助前端判断此次调用是否成功
3.2 固定返回字段
- code:本次调用的状态码,比如200、500、10001...状态码是自定义的
- success:是否成功,值是true或者false
- message:提示语,比如操作成功、删除成功、修改成功....
- data:用于存储当前接口的响应数据
3.3 统一响应结果
1)作用
如果不统一响应结果那么前端解析响应结果时:
- 前端每次都要根据不同的结果做不同的处理,非常麻烦
- 不知道后端接口请求是否成功,无法做进一步的处理
2)定义统一响应结果类工具类
package cn.sunyongjie.utils;
/**
* @Author: XIAOYU
*/
public class R<T> {
// 响应状态码
private Integer code;
// 操作结果
private Boolean success;
// 提示语
private String msg;
// 响应数据
private T data;
public static <T> R<T> ok() {
return new R<T>(200, true, "操作成功", null);
}
public static <T> R<T> ok(T data) {
return new R<T>(200, true, "操作成功", data);
}
public static <T> R<T> ok(String message) {
return new R<T>(200, true, message, null);
}
public static <T> R<T> ok(String message, T data) {
return new R<T>(200, true, message, data);
}
public static <T> R<T> fail() {
return new R<T>(500, false, "操作失败!", null);
}
public static <T> R<T> fail(T data) {
return new R<T>(500, false, "操作失败!", data);
}
public static <T> R<T> fail(String message) {
return new R<T>(500, false, message, null);
}
public static <T> R<T> fail(Integer code) {
return new R<T>(code, false, "操作失败!", null);
}
public static <T> R<T> fail(String message, T data) {
return new R<T>(500, false, message, data);
}
public static <T> R<T> fail(Integer code, T data) {
return new R<T>(code, false, "操作失败!", data);
}
public static <T> R<T> fail(Integer code, String message) {
return new R<T>(code, false, message, null);
}
public static <T> R<T> fail(Integer code, String message, T data) {
return new R<T>(code, false, message, data);
}
public R(Integer code, Boolean success, String msg, T data) {
this.code = code;
this.msg = msg;
this.success = success;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}