@ResponseBody
Controller程序除了接收请求外,还可以进行响应。
controller方法中的return的结果,使用@ResponseBody注解
@ResponseBody注解:
-
类型:方法注解、类注解
-
位置:书写在Controller方法上或类上
-
作用:将方法返回值直接响应给浏览器,如果返回值类型是实体对象/集合,将会转换为JSON格式后在响应给浏览器
但是在我们所书写的Controller中,只在类上添加了@RestController注解、方法添加了@RequestMapping注解,并没有使用@ResponseBody注解,怎么给浏览器响应呢?
这是因为,我们在类上加了@RestController注解,而这个注解是由两个注解组合起来的,分别是:@Controller 、@ResponseBody。 那也就意味着,我们在类上已经添加了@ResponseBody注解了,而一旦在类上加了@ResponseBody注解,就相当于该类所有的方法中都已经添加了@ResponseBody注解。
提示:前后端分离的项目中,一般直接在请求处理类上加@RestController注解,就无需在方法上加@ResponseBody注解了。
-
三层架构
-
介绍
在我们进行程序设计以及程序开发时,尽可能让每一个接口、类、方法的职责更单一些(单一职责原则)。
单一职责原则:一个类或一个方法,就只做一件事情,只管一块功能。
这样就可以让类、接口、方法的复杂度更低,可读性更强,扩展性更好,也更利于后期的维护。
-
控制反转: Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。
-
对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC容器或Spring容器。
-
-
依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。
-
程序运行时需要某个资源,此时容器就为其提供这个资源。
-
例:EmpController程序运行时需要EmpService对象,Spring容器就为其提供并注入EmpService对象。
-
-
bean对象:IOC容器中创建、管理的对象,称之为:bean对象。
-
Controller:控制层。接收前端发送的请求,对请求进行处理,并响应数据。
-
Service:业务逻辑层。处理具体的业务逻辑。
-
Dao:数据访问层(Data Access Object),也称为持久层。负责数据访问操作,包括数据的增、删、改、查。
将Service及Dao层的实现类,交给IOC容器管理
在实现类加上 @Component
注解,就代表把当前类产生的对象交给IOC容器管理。
要把某个对象交给IOC容器管理,需要在类上添加一个注解:@Component
数据库sql语句:
delete 删除
insert添加
select查询
updata修改
请求方式:
-
GET方式:@GetMapping
-
POST方式:@PostMapping
-
PUT方式:@PutMapping
-
DELETE方式:@DeleteMapping
而Spring框架为了更好的标识web应用程序开发当中,bean对象到底归属于哪一层,又提供了@Component的衍生注解:
注解 | 说明 | 位置 |
---|---|---|
@Component | 声明bean的基础注解 | 不属于以下三类时,用此注解 |
@Controller | @Component的衍生注解 | 标注在控制层类上 |
@Service | @Component的衍生注解 | 标注在业务层类上 |
@Repository | @Component的衍生注解 | 标注在数据访问层类上(由于与mybatis整合,用的少) |
可以使用 @Service
注解声明Service层的bean。 使用 @Repository
注解声明Dao层的bean。
-
前面声明bean的四大注解,要想生效,还需要被组件扫描注解
@ComponentScan
扫描。 -
该注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解
@SpringBootApplication
中,默认扫描的范围是启动类所在包及其子包。
依赖注入,是指IOC容器要为应用程序去提供运行时所依赖的资源,而资源指的就是对象。
我们使用了@Autowired这个注解,完成了依赖注入的操作,而这个Autowired翻译过来叫:自动装配。
@Autowired
注解,默认是按照类型进行自动装配的(去IOC容器中找某个类型的对象,然后完成注入操作)
入门程序举例:在EmpController运行的时候,就要到IOC容器当中去查找EmpService这个类型的对象,而我们的IOC容器中刚好有一个EmpService这个类型的对象,所以就找到了这个类型的对象完成注入操作。
那如果在IOC容器中,存在多个相同类型的bean对象,会报错。
如何解决上述问题呢?Spring提供了以下几种解决方案:
-
@Primary
-
@Qualifier
-
@Resource
方案一:使用@Primary注解
当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。
方案二:使用@Qualifier注解
指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。 @Qualifier注解不能单独使用,必须配合@Autowired使用。
方案三:使用@Resource注解
是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。
面试题:@Autowird 与 @Resource的区别
-
@Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
-
@Autowired 默认是按照类型注入,而@Resource是按照名称注入
SQL:结构化查询语言。一门操作关系型数据库的编程语言,定义操作所有关系型数据库的统一标准。SQL语句根据其功能被分为四大类:DDL、DML、DQL、DCL 。
-
创建表
-
语法:
-
create table 表名( 字段1 字段1类型 [约束] [comment 字段1注释 ], 字段2 字段2类型 [约束] [comment 字段2注释 ], ...... 字段n 字段n类型 [约束] [comment 字段n注释 ] ) [ comment 表注释 ] ;
-
注意: [ ] 中的内容为可选参数; 最后一个字段后面没有逗号
-
约束
注意:约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束。
大家有没有发现一个问题:id字段下存储的值,如果由我们自己来维护会比较麻烦(必须保证值的唯一性)。MySQL数据库为了解决这个问题,给我们提供了一个关键字:auto_increment(自动增长)
主键自增:auto_increment
-
每次插入新的行记录时,数据库自动生成id字段(主键)下的值
-
具有auto_increment的数据列是一个正数序列开始增长(从1开始自增)
-
表操作-其他操作
上面讲解了表结构的创建、数据类型、设计表的流程,接下来,再来讲解表结构的查询、修改、删除操作 。
-
查询数据库表的具体的语法:
-- 查询当前数据库的所有表 show tables; -- 查看指定的表结构 desc 表名 ; -- 可以查看指定表的字段、字段的类型、是否可以为NULL、是否存在默认值等信息 -- 查询指定表的建表语句 show create table 表名 ;
-
修改数据库表结构的具体语法:
添加字段
-- 添加字段 alter table 表名 add 字段名 类型(长度) [comment 注释] [约束]; -- 比如: 为tb_emp表添加字段qq,字段类型为 varchar(11) alter table tb_emp add qq varchar(11) comment 'QQ号码';
修改字段
-- 修改字段类型 alter table 表名 modify 字段名 新数据类型(长度); -- 比如: 修改qq字段的字段类型,将其长度由11修改为13 alter table tb_emp modify qq varchar(13) comment 'QQ号码'; -- 修改字段名,字段类型 alter table 表名 change 旧字段名 新字段名 类型(长度) [comment 注释] [约束]; -- 比如: 修改qq字段名为 qq_num,字段类型varchar(13) alter table tb_emp change qq qq_num varchar(13) comment 'QQ号码';
删除字段
-- 删除字段 alter table 表名 drop 字段名; -- 比如: 删除tb_emp表中的qq_num字段 alter table tb_emp drop qq_num;
修改表名
-- 修改表名 rename table 表名 to 新表名; -- 比如: 将当前的emp表的表名修改为tb_emp rename table emp to tb_emp;
删除表结构
-- 删除表 drop table [ if exists ] 表名; -- 比如:如果tb_emp表存在,则删除tb_emp表 drop table if exists tb_emp; -- 在删除表时,表中的全部数据也会被删除。
-
DML语句
DML英文全称是Data Manipulation Language(数据操作语言),用来对数据库中表的数据记录进行增、删、改操作。
-
添加数据(INSERT)
-
修改数据(UPDATE)
-
删除数据(DELETE)
-
查询关键字:**SELECT
在REST风格的URL中,通过四种请求方式,来操作数据的增删改查。
-
GET : 查询
-
POST :新增
-
PUT : 修改
-
DELETE :删除
insert操作的注意事项:
-
插入数据时,指定的字段顺序需要与值的顺序是一一对应的。
-
字符串和日期型数据应该包含在引号中。
-
插入的数据大小,应该在字段的规定范围内。
update注意事项:
-
修改语句的条件可以有,也可以没有,如果没有条件,则会修改整张表的所有数据。
-
在修改数据时,一般需要同时修改公共字段update_time,将其修改为当前操作时间。
delete注意事项:
-
DELETE 语句的条件可以有,也可以没有,如果没有条件,则会删除整张表的所有数据。
-
DELETE 语句不能删除某一个字段的值(可以使用UPDATE,将该字段值置为NULL即可)。
-
当进行删除全部数据操作时,会提示询问是否确认删除所有数据,直接点击Execute即可。
-
DQL语句
-
介绍
DQL英文全称是Data Query Language(数据查询语言),用来查询数据库表中的记录。
查询关键字:SELECT
查询操作是所有SQL语句当中最为常见,也是最为重要的操作。在一个正常的业务系统中,查询操作的使用频次是要远高于增删改操作的。当我们打开某个网站或APP所看到的展示信息,都是通过从数据库中查询得到的,而在这个查询过程中,还会涉及到条件、排序、分页等操作。
DQL查询语句,语法结构如下:
SELECT 字段列表 FROM 表名列表 WHERE 条件列表 GROUP BY 分组字段列表 HAVING 分组后条件列表 ORDER BY 排序字段列表 LIMIT 分页参数
我们今天会将上面的完整语法拆分为以下几个部分学习:
-
基本查询(不带任何条件)
-
条件查询(where)
-
分组查询(group by)
-
排序查询(order by)
-
分页查询(limit)
-
条件查询
语法:
select 字段列表 from 表名 where 条件列表 ; -- 条件列表:意味着可以有多个条件
-
聚合函数
之前我们做的查询都是横向查询,就是根据条件一行一行的进行判断,而使用聚合函数查询就是纵向查询,它是对一列的值进行计算,然后返回一个结果值。(将一列数据作为一个整体,进行纵向计算)
常用聚合函数:
注意 : 聚合函数会忽略空值,对NULL值不作为统计。
-
count :按照列去统计有多少行数据。
-
在根据指定的列统计的时候,如果这一列中有null的行,该行不会被统计在其中。
-
-
sum :计算指定列的数值和,如果不是数值类型,那么计算结果为0
-
max :计算指定列的最大值
-
min :计算指定列的最小值
-
avg :计算指定列的平均值
-
分组查询
-
分组: 按照某一列或者某几列,把相同的数据进行合并输出。
-
分组其实就是按列进行分类(指定列下相同的数据归为一类),然后可以对分类完的数据进行合并计算。
-
分组查询通常会使用聚合函数进行计算。
-
语法:
select 字段列表 from 表名 [where 条件] group by 分组字段名 [having 分组后过滤条件];
注意事项:
-
分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无任何意义
-
执行顺序:where > 聚合函数 > having
where与having区别(面试题)
-
执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组之后对结果进行过滤。
-
判断条件不同:where不能对聚合函数进行判断,而having可以。
-
排查查询
排序在日常开发中是非常常见的一个操作,有升序排序,也有降序排序。
语法:
select 字段列表 from 表名 [where 条件列表] [group by 分组字段 ] order by 字段1 排序方式1 , 字段2 排序方式2 … ;
-
排序方式:
-
ASC :升序(默认值)
-
DESC:降序
-
注意事项:如果是升序, 可以不指定排序方式ASC
注意事项:如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序
-
分页查询
分页操作在业务系统开发时,也是非常常见的一个功能,日常我们在网站中看到的各种各样的分页条,后台也都需要借助于数据库的分页操作。
分页查询语法:
select 字段列表 from 表名 limit 起始索引, 查询记录数 ;
注意事项:
-
起始索引从0开始。 计算公式 :起始索引 = (查询页码 - 1)* 每页显示记录数
-
分页查询是数据库的方言,不同的数据库有不同的实现,MySQL中是LIMIT
-
如果查询的是第一页数据,起始索引可以省略,直接简写为 limit 条数
JDBC:(Java DataBase Connectivity),就是使用Java语言操作关系型数据库的一套API。 【是操作数据库最为基础、底层的技术】
但是使用JDBC来操作数据库,会比较繁琐,所以现在在企业项目开发中呢,一般都会使用基于JDBC的封装的高级框架,比如:Mybatis、MybatisPlus、Hibernate、SpringDataJPA。
如果在测试时,需要传递一组参数,可以使用 @CsvSource
注解。
-
预编译SQL
其实我们在编写SQL语句的时候,有两种风格:
1.静态SQL(参数硬编码):这种呢,就是参数值,直接拼接在SQL语句中,参数值是写死的。
2.预编译SQL(参数动态传递)
这种呢,并未将参数值在SQL语句中写死,而是使用 ? 进行占位,然后再指定每一个占位符对应的值是多少,而最终在执行SQL语句的时候,程序会将SQL语句(SELECT * FROM user WHERE username = ? AND password = ?),以及参数值("daqiao", "123456")都发送给数据库,然后在执行的时候,会使用参数值,将?占位符替换掉。
那这种预编译的SQL,也是在项目开发中推荐使用的SQL语句。主要的作用有两个:
-
防止SQL注入
-
性能更高
什么是MyBatis?
-
MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
-
MyBatis本是 Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
-
持久层:指的是就是数据访问层(dao),是用来操作数据库的。
-
框架:是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。在框架的基础上进行软件开发更加高效、规范、通用、可拓展。
注解说明:
-
@Mapper注解:表示是mybatis中的Mapper接口
程序运行时,框架会自动生成接口的实现类对象(代理对象),并给交Spring的IOC容器管理
-
@Select注解:代表的就是select查询,用于书写select查询语句
单元测试
在创建出来的SpringBoot工程中,在src下的test目录下,已经自动帮我们创建好了测试类 ,并且在测试类上已经添加了注解 @SpringBootTest
,代表该测试类已经与SpringBoot整合。
该测试类在运行时,会自动通过引导类加载Spring的环境(IOC容器)。我们要测试那个bean对象,就可以直接通过@Autowired
注解直接将其注入进行,然后就可以测试了。
-
JDBC VS Mybatis
JDBC程序的缺点:
-
url、username、password 等相关参数全部硬编码在java代码中。
-
查询结果的解析、封装比较繁琐。
-
每一次操作数据库之前,先获取连接,操作完毕之后,关闭连接。 频繁的获取连接、释放连接造成资源浪费。
分析了JDBC的缺点之后,我们再来看一下在mybatis中,是如何解决这些问题的:
-
数据库连接四要素(驱动、链接、用户名、密码),都配置在springboot默认的配置文件 application.properties中
-
查询结果的解析及封装,由mybatis自动完成映射封装,我们无需关注
-
在mybatis中使用了数据库连接池技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪费。
使用SpringBoot+Mybatis的方式操作数据库,能够提升开发效率、降低资源浪费
数据库连接池是个容器,负责分配、管理数据库连接(Connection)
-
程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象
允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
-
客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)
释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏
-
客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象
数据库连接池的好处:
-
资源重用
-
提升系统响应速度
-
避免数据库连接遗漏
@param注解的作用是为接口的方法形参起名字的。(由于用户名唯一的,所以查询返回的结果最多只有一个,可以直接封装到一个对象中)
说明:基于官方骨架创建的springboot项目中,接口编译时会保留方法形参名,@Param注解可以省略 (#{形参名})。
-
XML配置文件规范
使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。
在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:
-
XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
-
XML映射文件的namespace属性为Mapper接口全限定名一致
-
XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
标签:就是用于编写select查询语句的。
-
resultType属性,指的是查询返回的单条记录所封装的类型。
编写XML映射文件
xml映射文件中的dtd约束,直接从mybatis官网复制即可; 或者直接AI生成。
配置
** XML映射文件的namespace属性为Mapper接口全限定名**
XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致
resultType 属性的值,与查询返回的单条记录封装的类型一致。
注意:一个接口方法对应的SQL语句,要么使用注解配置,要么使用XML配置,切不可同时配置。
MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生。
-
语法
简单的了解过springboot所支持的配置文件,以及不同类型配置文件之间的优缺点之后,接下来我们就来了解下yml配置文件的基本语法:
-
大小写敏感
-
数值前边必须有空格,作为分隔符
-
使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(idea中会自动将Tab转换为空格)
-
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
-
#
表示注释,从这个字符一直到行尾,都会被解析器忽略
而在前后端进行交互的时候,我们需要基于当前主流的REST风格的API接口进行交互。
什么是REST风格呢?
-
REST(Representational State Transfer),表述性状态转换,它是一种软件架构风格。
基于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的用户
其中总结起来,就一句话:通过URL定位要操作的资源,通过HTTP动词(请求方式)来描述具体的操作。
在REST风格的URL中,通过四种请求方式,来操作数据的增删改查。
-
GET : 查询
-
POST :新增
-
PUT : 修改
-
DELETE :删除
我们看到如果是基于REST风格,定义URL,URL将会更加简洁、更加规范、更加优雅。
注意事项:
-
REST是风格,是约定方式,约定不是规定,可以打破
-
描述模块的功能通常使用复数,也就是加s的格式来描述,表示此类资源,而非单个资源。如:users、emps、books…