导航
[封装01-设计模式] 设计原则 和 工厂模式(简单抽象方法) 适配器模式 装饰器模式
[封装02-设计模式] 命令模式 享元模式 组合模式 代理模式
[React 从零实践01-后台] 代码分割
[React 从零实践02-后台] 权限控制
[React 从零实践03-后台] 自定义hooks
[React 从零实践04-后台] docker-compose 部署react+egg+nginx+mysql
[React 从零实践05-后台] Gitlab-CI使用Docker自动化部署
[源码-webpack01-前置知识] AST抽象语法树
[源码-webpack02-前置知识] Tapable
[源码-webpack03] 手写webpack - compiler简单编译流程
[源码] Redux React-Redux01
[源码] axios
[源码] vuex
[源码-vue01] data响应式 和 初始化渲染
[源码-vue02] computed 响应式 - 初始化,访问,更新过程
[源码-vue03] watch 侦听属性 - 初始化和更新
[源码-vue04] Vue.set 和 vm.$set
[源码-vue05] Vue.extend
[源码-vue06] Vue.nextTick 和 vm.$nextTick
[部署01] Nginx
[部署02] Docker 部署vue项目
[部署03] gitlab-CI
[深入01] 执行上下文
[深入02] 原型链
[深入03] 继承
[深入04] 事件循环
[深入05] 柯里化 偏函数 函数记忆
[深入06] 隐式转换 和 运算符
[深入07] 浏览器缓存机制(http缓存机制)
[深入08] 前端安全
[深入09] 深浅拷贝
[深入10] Debounce Throttle
[深入11] 前端路由
[深入12] 前端模块化
[深入13] 观察者模式 发布订阅模式 双向数据绑定
[深入14] canvas
[深入15] webSocket
[深入16] webpack
[深入17] http 和 https
[深入18] CSS-interview
[深入19] 手写Promise
[深入20] 手写函数
[深入21] 数据结构和算法 - 二分查找和排序
[深入22] js和v8垃圾回收机制
[深入23] JS设计模式 - 代理,策略,单例
[前端学java01-SpringBoot实战] 环境配置和HelloWorld服务
[前端学java02-SpringBoot实战] mybatis + mysql 实现歌曲增删改查
[前端学java03-SpringBoot实战] lombok,日志,部署
[前端学java04-SpringBoot实战] 静态资源 + 拦截器 + 前后端文件上传
[前端学java05-SpringBoot实战] 常用注解 + redis实现统计功能
[前端学java06-SpringBoot实战] 注入 + Swagger2 3.0 + 单元测试JUnit5
[前端学java07-SpringBoot实战] IOC扫描器 + 事务 + Jackson
[前端学java08-SpringBoot实战总结1-7] 阶段性总结
(一) 前置知识
(1) 一些单词
fragment 片段
drawer 抽屉
library 资源库
premium 昂贵的 溢价 // navicat permium 支持多种数据库
rainbow 彩虹
bracket 括号
rainbow bracket 彩虹括号
wired 连线
auto wired 自动连接 // @Autowired
conditional 条件的 // @Conditional
override 复写
preference 偏好
distinct 清晰的 不同的
exception 异常
(2) mac版idea快捷键
1. 全局查找
command + shift + r
2. 调出actions
command + 3
3. 设置
command + ,
4. 文件间的跳转
command + e
5. 信息提示
command + 1
6. 跳转到别的类
control + 鼠标左键
7. 复制文件的引用路径
鼠标右键 - copy path - copy reference
8. 左右移动代码块
- 左移动 shift + tab
- 右移动 tab
9. 查找文件
- ctrl + h
(3) 一些常用的服务器应用端口号
mysql ----------------------- 3306
nginx ----------------------- 80
(4) idea中出现端口被占用
lsof -i tcp:7890
kill PID
// 7890表示被占用的端口号
(二) 常用注解
(1) lombok中常用注解
(1.1) lombok 的添加和使用
- 在
bean dto model
等对象中使用
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
(1.2) @Data
- @Data包含了以下注解
- @Getter/@Setter
- @ToString
- @EqualsAndHashCode
- @RequiredArgsConstructor 特定参数的构造器,特定参数是指加上了 final 修饰符的变量
(1.3) @Value
只有getter,其他的和@Data一样,会把所有的变量都设成 final 的
- @Getter
- @ToString
- @EqualsAndHashCode
- @RequiredArgsConstructor 特定参数的构造器,特定参数是指加上了 final 修饰符的变量
(1.4) @Builder
- @Builder 自动生成 ( 流式set值 ) 写法,不需要写一堆setter
- @Builder 十分有用的一个注解
注意:通常情况下 @Data 和 @Builder 会一起使用,因为还是必须写getter/setter
@Data
@Builder
public class FirstBean {
private String name;
private Integer age;
private String sex;
}
-----------------------
FirstBean firstBean = FirstBean.builder()
.name(name)
.age(age)
.sex(sex)
.build();
(1.5) @Slf4j
- @Slf4j 自动生成该类的 log 静态常量,所以不需要sout了
log.info("传入的参数变量{}", name);
// {} 就是占位符,表示后面的变量name
(1.6) @NoArgsConstructor @AllArgsConstructor @RequiredArgsConstructor
- @NoArgsConstructor 无参构造器
- @AllArgsConstructor 全参构造器
- @RequiredArgsConstructor 特定参数构造器
(2) mybatis中常用注解
(3) controller 中常用注解
(3.1) @RestController 和 @Controller + @ResponseBody
- @RestController
@RestController = @Controller + @ResponseBody
- @RestController 不能返回html页面,返回的内容就是return的内容
- 如果一个controller,一些页面要返回html,一些又要返回return的内容,就需要用 @Controller注解controller返回html,然后在要返回的return的方法上加上@ResponseBody来返回return后面的内容
- @ResponseBody作用于类的方法上,@RestController和@Controller作用于类上
// @RestController = @Controller + @ResponseBody
@Controller --------------------------------- 1
@Slf4j
public class FirstController {
@RequestMapping(value = "/music/{name}", method = {RequestMethod.GET})
@ResponseBody --------------------------- 2
public String getMusic(
@PathVariable("name") String name,
@RequestParam("age") Integer age,
@RequestParam("sex") String sex
) {
System.out.println(name);
log.info("传入的参数变量2{}", name);
FirstBean firstBean = FirstBean.builder()
.name(name)
.age(age)
.sex(sex)
.build();
System.out.println(firstBean);
return "good246";
}
}
(3.2) @GetMapping @PostMapping @PutMapping @DeleteMapping
- @GetMapping
@GetMapping("/music/{name}")
相当于
@RequestMapping(value="/music/{name}", method = {RequestMethod.GET})
- CRUD 分别是 create read update delete 的缩写
(3.3) @RequestParam 和 @PathVariable ------ get delete 请求
- 有这样一段url地址:
www.baidu.com/music/周杰伦?age=20&sex=man
-
@PathVariable
- 可以获取到path的动态参数部分
"/music/{name}" 中的name即"周杰伦"
@PathVariable("name") String name
-
@RequestParam
- 可以获取到age和sex
@RequestParam("age") Integer age
(3.4) @RequestBody 和 @RequestHeader ------ post put 请求
@PostMapping("/music")
public MusicBean addMusic(
@RequestBody MusicBean musicBean,
@RequestHeader("Content-Type") String contentType
) {
log.info("musicBean:{}", musicBean);
log.info("Content-Type:{}", contentType);
return musicBean;
}
(3-5) @RequestPart
-
@RequestPart
主要用在multipart/form-data
表单提交请求的方法上 - 支持的请求方式是:
MultipartFile
,属于Spring的MultipartResolver类,通过http协议传输 注意:前端上传组件的name="aaa",是和java中的 @RequestPart("aaa") 对应的
- 结合下面上传的例子
(4) 容器相关的注解
(4.1) @Configuration + @Bean 向容器中添加组件
- @Configuration 配置类
- 告诉springboot这是一个 (
配置类
) - @Configuration 标注的 (
配置类本身也是一个组件
) - @Configuration(proxyBeanMethods = true)
- proxyBeanMethods代理bean的方法,默认true
- 当 ( proxyBeanMethods=true ) 时,外部无论对配置类中的组建注册方法调用多少次,获取的都是之前注册到容器中的 ( 单实例对象 )
- proxyBeanMethods=true 解决组件依赖问题
- proxyBeanMethods=false 会跳过检查,提升速度
- 可以理解为 xml 中的 ( beans 标签 )
- 告诉springboot这是一个 (
- @Bean 向容器中添加组件
- (
@Bean
) 用来 (向容器中添加组件
),并且添加的组件是 (单实例
) 的 - @Bean 是标注在类的方法上的
- 可以理解为 xml 中的 ( bean 标签 )
- (
-
流程
- @Configuration + @Bean + @Autowired
1.注册:@Configuration + @Bean 向容器中注入组件
2.使用:@Autowired 将组件注入类中使用
/**
* 1. @Configuration 标注的类就是 配置类
* 2。配置类里,使用 @Bean 标注在方法上给容器注册组件,注册的组件默认也是单实例的
* 3. 注意:@Configuration标注的类,该类本身也是一个组件,即 UserConfig 也是一个组件,即 ( 配置类本身也是一个组件 )
*
* 4. proxyBeanMethods 代理bean的方法,默认值是true
* Full(proxyBeanMethods = true) 单例,可以用于 ( 组件依赖 )
* Lite(proxyBeanMethods = false)
*/
// 告诉 SpringBoot 这是一个 ( 配置类 ),等用于以前的配置文件
// @Configuration 配置类
@Configuration(proxyBeanMethods = true)
public class UserConfig {
// @Bean
// @Bean 给容器中添加组件
// 1. 以方法名作为组件的id => user1
// 2. 返回类型就是组件类型 => UserBean
// 3. 返回的值就是组件在容器中的实例 => new UserBean()
// @Bean("userX") 的参数可以自定义id
@Bean("userX")
public UserBean user01() {
return new UserBean("woow_wu7", 20);
}
}
(4.2) @Autowired 和 @Resource 和 new
- @Autowired
- @Autowired是自动装配的意思,wired连接,auto wired自动连接
- @Autowired ( 按类型装配 ) ( 单例 ) ( 在程序启动时创建 )
- @Resource
- @Autowired 和 new 的区别
-
@Autowired
:是由spring创建的对象,( 单例 ),( 作用域是整个项目 ),项目已启动就创建了 -
new
: 是手动生成实例对象,( 多例 ),每次调用生成都都是新的对象
-
-
流程
- @Configuration + @Bean + @Autowired
- 1.注册:@Configuration + @Bean 向容器中注入组件
-
2.使用:@Autowired 将组件注入类中使用
(4.3) @Import 和 @Bean
- @Import作用在类上,可以是配置类,容器中的类比如Controller Service 等
- @Import向容器中添加组件,作用和@Bea类似
- @Configuration + @Bean 一般一起使用
(三) 热更新
- 1.引入 spring-boot-devtools 包
- 2.
setting => Build,Execution,Deployment => Compiler => 勾上Build project automaticallly
- 3.command + 3 调出
actions
,然后搜索Registry
- 4.勾选
compiler.autoMake.allow.when.app.running
<!-- spring-boot-devtools 热更新 -->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
(四) 连接数据库实现crud
- 重点掌握mybatis的xml配置方式
- 当添加,删除,更新时,返回值是一个Integer类型,1表示成功,0表示失败
- 可以在入口类中配置 @MapperScan 这样就不用在每一个Interface加@Mapper了
(4-1) 安装mysql数据库到服务器,并通过 navicat premium 连接数据库
- mac安装-免费的社区版本-最底部-MySQL Community Server
- windows版本mysql安装教程
- mysql常用命令教程
- mysql常用命令 ( 可以直接通过navicat进行操作 )
- 连接数据库
mysql -h主机地址 -u用户名 -p用户密码
- 连接数据库
mysql -h 120.53.220.141 -u root -p
- 退出
exit
- 查看数据库
show databases;
- 创建数据库
create database 数据库名;
- 删除数据库
drop database 数据库名;
-
使用数据库
use 数据库名;
-
查看当前使用的数据库
select database();
- 查看表
show tables;
- 创建表
create table 表名 (dde列名 类型);
- 删除表
droop table 表名;
-
显示表结构
desc 表名;
- 修改密码
mysqladmin -uroot -p123456 password 12345678;
- 修改密码
-p12345是当前的数据库密码,password是将要设置的数据库密码
-
查看数据库的安装路径
show variables like "%char%";
- 查看mysql的版本:
- 1.如果已经连接了数据库,使用命令 select version();
- 2.如果未连接数据库:cmd,切换至mysql的bin目录,运行 mysql -V
- 连接数据库
-
下载到本地环境
-
连接,这里是远程服务器
(4-2) 添加必须的maven依赖
- 需要
mysql-connector-java
- 需要
spring-boot-starter-jdbc
- 需要
mybatis-spring-boot-starter
<!-- mysql依赖 -->
<!-- mysql, 版本需要和你安装的mysql版本保持一致 -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.24</version>
</dependency>
<!-- jdbc依赖 -->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>2.4.5</version>
</dependency>
<!-- mybatis依赖 -->
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
(4-3) 在 application.properties 中配置数据源组件配置项
application.properties
-------
# 定义数据源组件
# 已弃用 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 注意 spring.datasource.url="jdbc:mysql://localhost:3306/数据库名称?时区信息"
# 注意 上面的时区信息不能少,不然会报错
# 分别是 ( 数据库url ) ( 数据库驱动 ) ( 用户名 ) ( 密码 )
spring.datasource.url=jdbc:mysql://localhost:3306/7-community-java?serverTimezone=GMT%2B8&useSSL=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
(4-4) 注解方式 - 利用mybatis注解的方式操作数据库
- 遇到的坑
- 入口主类的名称一定要正确,不然回报 server中找不到mapper依赖的错误
-
mapper文件中的类型,记得选 interface 类型
(4-5) xml方式 - 利用mybatis的xml方式操作数据库 ( 重点 )
- 在大型项目中更推荐使用xml的方式,更强大和灵活
- 第一步
- 在
resources
文件夹中新建mybatis
文件夹 - 在mybatis文件夹中新建
mybatis-config.xml
全局配置文件- mybatis/mybatis-config.xml
- mubatis官网教程
- 建议
<configuration>
所代表的配置在application.yml
中去配置
- 在mybatis文件夹中新建
mapper
文件夹,接着在里面创建musicMapper.xml
mapper的sql映射文件- mybatis/mapper/musicMapper.xml
- 里面写 增删改查的代码
- 我之前的文章
- 在
- 第二步
- 在
resources.yml
中配置mybatis的全局配置文件
和mapper的sql映射文件
,即制定mybatis的全局配置文件位置和sql映射文件位置- config-location: classpath:mybatis/mybatis-config.xml # mybatis全局配置文件
- mapper-locations: classpath:mybatis/mapper/*.xml # mybatis的sql映射文件
- 在
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.MusicMapper">
<!-- namespace 就是 mapper 文件夹中对应的 Mapper 文件 -->
<!-- public abstract List<MusicBean> getMusic(); -->
<!-- id 是方法名 -->
<!-- resultType 是方法的返回值类型,通过 copy path => copy reference 可以快速生成 -->
<select id="getAllMusic" resultType="com.example.demo.bean.MusicBean">
select * from music
</select>
<select id="getMusic" resultType="com.example.demo.bean.MusicBean">
SELECT * FROM music
WHERE
name=#{name}
</select>
<insert id="addMusic" parameterType="com.example.demo.bean.MusicBean">
insert into music
(name, singer)
values
(#{name}, #{singer})
</insert>
<delete id="deleteMusic" parameterType="Integer">
delete from music
where
id=#{id}
</delete>
<update id="updateMusic" parameterType="Map">
update music
set name=#{musicBean.name}, singer=#{musicBean.singer}
where id=#{id}
</update>
</mapper>
mapper
public List<MusicBean> getAllMusic();
public MusicBean getMusic(Integer id, String name);
public Integer addMusic(MusicBean musicBean);
Integer deleteMusic(Integer id);
Integer updateMusic(Integer id, MusicBean musicBean);
(五) 拦截器 HandlerInterceptor
- HandlerInterceptor
-
preHandle
在目标方法执行 ( 前 ) 执行,即在 controller 中的目标方法执行前执行 -
postHandle
在目标方法执行 ( 完成后 ) 执行 -
afterCompletion
在 ( 页面渲染后 ) 执行
-
- 我之前的文章-拦截器
(5-1) 拦截器实现的具体过程
- interceptor
- 1.新建interceptor文件夹,然后新建 MusicInterceptor.java 文件
- 2.public class MusicInterceptor implements HandlerInterceptor
- 3.新建 preHandler等方法,在里面写拦截逻辑,return true放行,return false表示拦截
- config
- 1.新建一个config文件夹,然后新建一个实现类,AdminWebConfig.java 文件
- 2.public class AdminWebConfig implements WebMvcConfigurer
- 3.registry.addInterceptor(new MusicInterceptor())
- 4.
.addPathPatterns("/**")
// 拦截 => 拦截所有请求,包括静态资源 - 5.
.excludePathPatterns("css/**")
// 放行,放行了static文件夹下的css静态资源
(六) 静态资源
- resources/static
- resources/public
- resources/MATA-INF/resources
- resources/resources
- 以上四个文件夹中的文件就属于静态资源,通过访问
跟路径/静态资源名称
即可
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestStaticResources {
// 静态资源
// 1
// - resources/static
// - resources/public
// - resources/MATA-INF/resources
// - resources/resources
// - 以上四个文件夹中的文件就属于静态资源,通过访问 `跟路径/静态资源名称` 即可
// 2
// 原理:静态映射 /**
// 请求进来,先去 ( controller ) 中看能不能处理,如果不能处理再交给 ( 静态资源处理器去处理静态资源 )
// 3
// 问题:如果controller中有一个接口/mm.jpg,而我们的静态资源文件夹中同样有一个静态资源叫mm.jpg,会发生什么?
// 答案:会优先处理controller中的类,而不会去访问静态资源
// 4
// 静态资源前缀
// 静态资源设置前缀:spring.mvc.static-path-pattern=/resources/**
// 访问静态资源:当前项目 + 前缀 + 静态资源
// 例子:http://localhost:7777/resources/66.jpg
// 5
// 指定自定义的静态资源目录 ( 默认静态文件夹路径 )
// spring.web.resources.static-locations=[classpath:/7resources/]
@GetMapping("/mm.jpg")
public String getStaticResources() {
return "string, is not static resource mm.jpg";
}
}
(七) 文件上传
(7.1) 添加 spring-boot-start-thymeleaf
maven依赖
- spring-boot-start-thymeleaf 的主要作用是用来返回
html
<!-- spring-boot-starter-thymeleaf -->
<!-- 主要用于显示resources/templates中的html -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
(7.2) 在 resources/templates/
文件夹中新建 fileUpload.html
<!DOCTYPE html>
<!--注意:xmls:th 的值-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>测试页面</div>
<!-- th:action="@{/upload}" 提交的controller对应的path -->
<!-- enctype="multipart/form-data" -->
<form th:action="@{/upload}" method="post" enctype="multipart/form-data">
<div>
<span>单头像上传</span>
<input type="file" name="single">
</div>
<div>
<span>多头像上传</span>
<!-- multiple表示开启多个上传 -->
<input type="file" name="multiple" multiple>
</div>
<button type="submit">上传</button>
</form>
</body>
</html>
(7.3) 新建controller
@Controller
@Slf4j
public class FileUploadController {
@GetMapping("/fileUpload")
public String handleFile() {
return "fileUpload";
}
@PostMapping("/upload")
public String upload(
@RequestPart("single") MultipartFile single
) throws IOException {
if (!single.isEmpty()) {
String originalFilename = single.getOriginalFilename(); // 获取原始文件名
log.info("{}", originalFilename);
}
return "fileUpload";
}
}