SpringBoot学习03——RESTful/HTTP/JPA/Transaction

一、RESTful

RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。

RESTful的特性

  • 资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特性的URI。要获取这个资源,访问它的URI就可以,因此URI即为每一个资源的独一无二的识别符。
  • 表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式。
  • 状态转换(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转换”(State Transfer)。而这种转换是建立在表现层之上的,所以就是“表现层状态转换”。具体说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。他们分别对应四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。

二、SpringMvc对RESTful的支持

1. RESTful的URL路径变量

URL-PATTERN:设置为 / ,方便拦截RESTful请求。

@PathVariable:可以解析出来URL中的模板变量({id}/{name})

2. RESTful的CRUD

@RequestMapping:通过设置method属性的CRUD,可以将同一个URL映射不同HandlerMethod方法上。

@GetMapping、@PostMapping、@PutMapping、@DeleteMapping注解同@RequestMapping注解的method属性设置。

3. RESTful的资源表述

RESTful服务中一个重要的特性就是一种资源可以有多种表现形式,在SpringMvc中可以使用ContentNegotiatingManager这个内容协商管理器来实现这种方式。

4. 内容协商的方式有三种

  1. 扩展名,比如.json表示我要JSON格式数据、.xml表示我要xml格式数据
  2. 请求参数:默认是“format”
  3. 请求头设置Accept参数,比如设置Accept为application/json表示要JSON格式数据

现在一般RESTful风格响应的数据一般都是JSON格式,所以一般也不使用内容协商管理器,直接使用 @ResponseBody 注解将数据按照JSON格式返回

三、普通 API与RESTful API(示例)

普通API:

//添加用户
http://localhost/createuser
//删除id为1的用户
http://localhost/deleteuser?userid=1
//获取用户列表
http://localhost/getuser
//获取id为1的用户
http://localhost/getuser?userid=1
//更新id为1的用户
http://localhost/updateuser?userid=1

RESTful API:

  • 使用GET的方式请求http://localhost/user代表查询用户列表
  • 使用GET的方式请求http://localhost/user/1代表查询id为1的用户
  • 使用POST的方式请求http://localhost/user代表创建一个用户
  • 使用PUT的方式请求http://localhost/user/1代表修改id为1的用户
  • 使用DELETE的方式请求http://localhost/user/1代表删除id为1的用户

可以看到这种风格看起来要更为优雅与简洁,面向资源,一目了然,具有自解释性,充分的发挥了HTTP协议的优点。

四、HTTP状态码和描述

CODEHTTP OperationBody ContentsDecription
200GET,PUT资源操作成功
201POST资源,元数据对象创建成功
202POST,PUT,DELETE,PATCHN/A请求已被接受
204DELETE,PUT,PATCHN/A操作已经执行成功,但是没有返回结果
301GETlink资源已被移除
303GETlink重定向
304GETN/A资源没有被修改
400GET,POST,PUT,DELETE,PATCH错误提示(消息)参数列表错误(缺少,格式不匹配)
401GET,POST,PUT,DELETE,PATCH错误提示(消息)未授权
403GET,POST,PUT,DELETE,PATCH错误提示(消息)访问受限,授权过期
404GET,POST,PUT,DELETE,PATCH错误提示(消息)资源,服务未找到
405GET,POST,PUT,DELETE,PATCH错误提示(消息)不允许的HTTP方法
409GET,POST,PUT,DELETE,PATCH错误提示(消息)资源冲突,或资源被锁定
415GET,POST,PUT,DELETE,PATCH错误提示(消息)不支持的数据(媒体)类型
429GET,POST,PUT,DELETE,PATCH错误提示(消息)请求过多被限制
500GET,POST,PUT,DELETE,PATCH错误提示(消息)系统内部错误
501GET,POST,PUT,DELETE,PATCH错误提示(消息)接口未实现

五、JPA

  1. Java Persistence API(Java 持久层 API):用于对象持久化的 API
  2. 作用:使得应用程序以统一的方式访问持久层
  3. 前言中提到了 Hibernate,那么JPA 与 Hibernate究竟是什么关系呢:
    • JPA 是 Hibernate 的一个抽象,就像 JDBC 和 JDBC 驱动的关系
    • JPA 是一种 ORM 规范,是 Hibernate 功能的一个子集 (既然 JPA 是规范,Hibernate 对 JPA 进行了扩展,那么说 JPA 是 Hibernate 的一个子集不为过)
    • Hibernate 是 JPA 的一个实现
  4. JPA 包括三个方面的技术:
    • ORM 映射元数据,支持 XML 和 JDK 注解两种元数据的形式
    • JPA 的 API
    • 查询语言:JPQL
JPA的注解
注解解释
@Entity声明类为实体或表。
@Table声明表名。
@Basic指定非约束明确的各个字段。
@Embedded指定类或它的值是一个可嵌入的类的实例的实体的属性。
@Id指定的类的属性,用于识别(一个表中的主键)。
@GeneratedValue指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。
@Transient指定的属性,它是不持久的,即:该值永远不会存储在数据库中。
@Column指定持久属性栏属性。
@SequenceGenerator指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。
@TableGenerator指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。
@AccessType这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。
@JoinColumn指定一个实体组织或实体的集合。这是用在多对一和一对多关联。
@UniqueConstraint指定的字段和用于主要或辅助表的唯一约束。
@ColumnResult参考使用select子句的SQL查询中的列名。
@ManyToMany定义了连接表之间的多对多一对多的关系。
@ManyToOne定义了连接表之间的多对一的关系。
@OneToMany定义了连接表之间存在一个一对多的关系。
@OneToOne定义了连接表之间有一个一对一的关系。
@NamedQueries指定命名查询的列表。
@NamedQuery指定使用静态名称的查询。
依赖及配置
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
#数据源配置
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf8&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
接口约定命名规则:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e1mheBYa-1618797771605)(C:\Users\张淇囿\AppData\Roaming\Typora\typora-user-images\1618457187531.png)]

六、Transaction

是声明式事务管理 编程中使用的注解

事务的基本要素(ACID)
  1. 原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
  2. 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
  3. 隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
  4. 持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
@Transactional参数

value: 一般用来配置指定的事务管理器。

propagation: 事务的传播属性,有七种。见枚举Propagation,默认REQUIRED。

//支持当前事务,如果不存在就创建一个
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
//支持当前事务,如果不存在就以非事务的方式运行
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
//支持当前事务,不存在就抛出异常
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
//创建一个新事务,如果当前有事务就暂停当前事务
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
//以非事务方式运行,如果当前有事务就暂停当前事务
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
//以非事务的方式运行,如果当前有事务就抛出异常
NEVER(TransactionDefinition.PROPAGATION_NEVER),
//如果当前有事务,就加入当前事务。
NESTED(TransactionDefinition.PROPAGATION_NESTED);

isolation: 隔离级别。事务的隔离级别有4种。我们看一下Isolation枚举类。

//使用默认的隔离级别,取决于底层数据库的默认隔离级别
DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
//读未提交,这种隔离级别最低,会出现脏读,不可重复读,虚读(幻读)等情况。一般不用。
READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
//读已提交,这种隔离级别可以防止脏读的产生,但是无法避免不可重复读和虚读(幻读)的出现。
READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
//可重复读,这种隔离级别可以防止脏读、不可重复读的出现,但是无法避免虚读(幻读)的产生。
REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
//串行化,这种隔离级别最高,可以避免脏读、不可重复读和虚读(幻读)的产生。
SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。

Mysql默认隔离级别为可重复读。

关于事务的并发问题

  1. 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

  2. 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

  3. 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。

timeout : 事务的超时时间,默认为-1,即事务直到完成都不会超时。

readOnly: 是否只读,一般用来标识。拥有这个标识,写入操作不一定会失败,取决于数据库系统。

rollbackFor: 事务回滚条件。参数为继承Throwable的class类。

rollbackForClassName: 事务回滚条件。可以接受String数组。

noRollbackFor: 事务不会回滚条件。

noRollbackForClassName: 事务不会回滚条件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值