Springboot项目
# 1. 概述
# 1.1 前后端项目构造
# 1.2 Springboot工程目录结构
# 1.3 开发规范——REST
① 基于REST风格URL如下:
http://localhost:8080/users/1 GET:查询id为1的用户
http://localhost:8080/users POST:新增用户
http://localhost:8080/users PUT:修改用户
http://localhost:8080/users/1 DELETE:删除id为1的用户
2
3
4
其中总结起来,就一句话:通过URL定位要操作的资源,通过HTTP动词(请求方式)来描述具体的操作。
② 开发规范-统一响应结果
前后端工程在进行交互时,使用统一响应结果 Result。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应信息 描述字符串
private Object data; //返回的数据
//增删改 成功响应
public static Result success(){
return new Result(1,"success",null);
}
//查询 成功响应
public static Result success(Object data){
return new Result(1,"success",data);
}
//失败响应
public static Result error(String msg){
return new Result(0,msg,null);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2. 功能开发
# 2.1 基础功能——增删改查
💡注解@Slf4j
: 在类上添加该注解会自动生成Logger对象,对象名 log
问题1:如何限定请求方式?(控制层)
@PostMapping —— 增加请求
@DeleteMapping —— 删除请求
@GetMapping —— 查询请求
@PutMapping —— 修改请求
问题2:怎么在controller中接收json格式的请求参数?
@RequestBody //把前端传递的json数据填充到实体类中
问题3:怎么在controller中接收路径中的请求参数(单个)?
@PathVariable //把请求路径:/depts/**{id}**中的路径参数 {id}作为请求参数
@Slf4j
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("/depts")
public Result add(@RequestBody Dept dept){
//记录日志
log.info("新增部门:{}",dept);
//调用service层添加功能
deptService.add(dept);
//响应
return Result.success();
}
//省略...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
💡在Spring当中为了简化请求路径的定义,可以把公共的请求路径,直接抽取到类上,在类上加一个注解@RequestMapping
,并指定请求路径"/depts"
# 2.2 分页查询——PageHelper
后端给前端返回的数据,我们通常封装到PageBean对象(自定义pojo类)中,并将该对象转换为json格式的数据响应回给浏览器。
1、在pom.xml引入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.2</version>
</dependency>
2
3
4
5
2、EmpMapper
@Mapper
public interface EmpMapper {
//获取当前页的结果列表
@Select("select * from emp")
public List<Emp> page(Integer start, Integer pageSize);
}
2
3
4
5
6
3、EmpServiceImpl
@Override
public PageBean page(Integer page, Integer pageSize) {
// 设置分页参数
PageHelper.startPage(page, pageSize);
// 执行分页查询
List<Emp> empList = empMapper.list(name,gender,begin,end);
// 获取分页结果
Page<Emp> p = (Page<Emp>) empList;
//封装PageBean
PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
return pageBean;
}
2
3
4
5
6
7
8
9
10
11
12
在执行empMapper.list()方法时,就是执行:select * from emp 语句,怎么能够实现分页操作呢?
分页插件帮我们完成了以下操作:
- 先获取到要执行的SQL语句:select * from emp
- 把SQL语句中的字段列表,变为:count(*)
- 执行SQL语句:select count(*) from emp //获取到总记录数
- 再对要执行的SQL语句:select * from emp 进行改造,在末尾添加 limit ? , ?
- 执行改造后的SQL语句:select * from emp limit ? , ?
# 2.3 文件上传 —— 本地存储
文件上传,是指将本地图片、视频、音频等文件上传到服务器,供其他用户浏览或下载的过程。
# 2.3.1 前端实现:
- 表单提交方式必须为
POST
通常上传的文件会比较大,所以需要使用 POST 提交方式
- 表单的编码类型enctype必须要设置为:multipart/form-data
普通默认的编码格式是不适合传输大型的二进制数据的,所以在文件上传时,表单的编码格式必须设置为multipart/form-data
# 2.3.2 后端实现:
- 首先在服务端定义这么一个controller,用来进行文件上传,然后在controller当中定义一个方法来处理
/upload
上传文件请求 - 在定义的方法中接收提交过来的数据 (方法中的形参名和请求参数的名字保持一致)
# 2.3.3 本地存储
使用MultipartFile类提供的API方法,把临时文件转存到本地磁盘目录下
MultipartFile 常见方法:
- String getOriginalFilename(); //获取原始文件名
- void transferTo(File dest); //将接收的文件转存到磁盘文件中
- long getSize(); //获取文件的大小,单位:字节
- byte[] getBytes(); //获取文件内容的字节数组
- InputStream getInputStream(); //获取接收到的文件内容的输入流
@Slf4j
@RestController
public class UploadController {
@PostMapping("/upload")
public Result upload(String username, Integer age, MultipartFile image) throws IOException {
log.info("文件上传:{},{},{}",username,age,image);
//获取原始文件名
String originalFilename = image.getOriginalFilename();
//构建新的文件名
String extname = originalFilename.substring(originalFilename.lastIndexOf("."));//文件扩展名
String newFileName = UUID.randomUUID().toString()+extname;//随机名+文件扩展名
//将文件存储在服务器的磁盘目录
image.transferTo(new File("E:/images/"+newFileName));
return Result.success();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
💡使用UUID保证文件名唯一,不会覆盖
💡在SpringBoot中,文件上传时默认单个文件最大大小为1M,如果需要上传大文件,可以在application.properties进行如下配置:
#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB
#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB
2
3
4
# 3. 配置文件
将各个文件中的配置信息统一写在一个配置文件中,便于管理维护
# 3.1 properties配置文件
application.properties是springboot项目默认的配置文件,所以springboot程序在启动时会默认读取application.properties配置文件
aliyun.oss.endpoint=https://oss-cn-hangzhou.aliyuncs.com
aliyun.oss.accessKeyId=LTAI4GCH1vX6DKqJWxd6nEuW
aliyun.oss.accessKeySecret=yBshYweHOpqDuhCArrVHwIiBKpyqSL
aliyun.oss.bucketName=web-tlias
2
3
4
# 3.2 yml配置文件(惯用)
# 3.2.1 书写形式
aliyun:
oss:
endpoint: https://oss-cn-hangzhou.aliyuncs.com
accessKeyId: LTAI4GCH1vX6DKqJWxd6nEuW
accessKeySecret: yBshYweHOpqDuhCArrVHwIiBKpyqSL
bucketName: web-397
2
3
4
5
6
# 3.2.2 基本语法
- 大小写敏感
- 数值前边必须有空格,作为分隔符
- 使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(idea中会自动将Tab转换为空格)
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
#
表示注释,从这个字符一直到行尾,都会被解析器忽略
# 3.2.3 常见数据格式
① 定义对象或Map集合
user:
name: zhangsan
age: 18
password: 123456
2
3
4
② 定义数组、list或set集合
hobby:
- java
- game
- sport
2
3
4
# 3.3 配置属性注入
# 3.3.1 value注解
通过使用一个现成的注解:@Value
,获取配置文件中的数据。
@Value 注解通常用于外部配置的属性注入
具体用法为: @Value("${配置文件中的key}")
@Component
public class AliOSSUtils {
@Value("${aliyun.oss.endpoint}")
private String endpoint;
}
2
3
4
5
当需要注入的属性过多时,就会非常繁琐
# 3.3.2 ConfigurationProperties注解
① 需要创建一个实现类,且实体类中的属性名和配置文件当中key的名字必须要一致
比如:配置文件当中叫endpoints,实体类当中的属性也得叫endpoints,另外实体类当中的属性还需要提供 getter / setter方法
② 需要将实体类交给Spring的IOC容器管理,成为IOC容器当中的bean对象
③ 在实体类上添加@ConfigurationProperties
注解,并通过perfect
属性来指定配置参数项的前缀