文章目录

  • 一、RESTful
  • 二、SpringMvc对RESTful的支持
  • 1. RESTful的URL路径变量
  • 2. RESTful的CRUD
  • 3. RESTful的资源表述
  • 4. 内容协商的方式有三种
  • 三、普通 API与RESTful API(示例)
  • 四、HTTP状态码和描述
  • 五、JPA
  • JPA的注解
  • 依赖及配置
  • 接口约定命名规则:
  • 六、Transaction
  • 事务的基本要素(ACID)
  • @Transactional参数


一、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状态码和描述

CODE

HTTP Operation

Body Contents

Decription

200

GET,PUT

资源

操作成功

201

POST

资源,元数据

对象创建成功

202

POST,PUT,DELETE,PATCH

N/A

请求已被接受

204

DELETE,PUT,PATCH

N/A

操作已经执行成功,但是没有返回结果

301

GET

link

资源已被移除

303

GET

link

重定向

304

GET

N/A

资源没有被修改

400

GET,POST,PUT,DELETE,PATCH

错误提示(消息)

参数列表错误(缺少,格式不匹配)

401

GET,POST,PUT,DELETE,PATCH

错误提示(消息)

未授权

403

GET,POST,PUT,DELETE,PATCH

错误提示(消息)

访问受限,授权过期

404

GET,POST,PUT,DELETE,PATCH

错误提示(消息)

资源,服务未找到

405

GET,POST,PUT,DELETE,PATCH

错误提示(消息)

不允许的HTTP方法

409

GET,POST,PUT,DELETE,PATCH

错误提示(消息)

资源冲突,或资源被锁定

415

GET,POST,PUT,DELETE,PATCH

错误提示(消息)

不支持的数据(媒体)类型

429

GET,POST,PUT,DELETE,PATCH

错误提示(消息)

请求过多被限制

500

GET,POST,PUT,DELETE,PATCH

错误提示(消息)

系统内部错误

501

GET,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 的一个实现
  1. 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
接口约定命名规则:

spring response添加cookie_API

六、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: 事务不会回滚条件。