RestFul面向资源的架构
URI
URI,通一资源标志符(Uniform Resource Identifier, URI),表示的是web上每一种可用的资源,如 HTML文档、图像、视频片段、程序等都由一个URI进行定位的。
- URL 是URI的一个子集。它是Uniform Resource Locator的缩写,译为“统一资源定位 符”。
- URN (Uniform Resource Locator)
具体可以到查看链接: URL和URI的区别,链接: URI和URL的区别比较与理解。本文描述rest这种资源架构。
REST
(Representational State Tranfer)表述性状态转移
原则:
- 网络上所有的事物都可以抽象为资源
- 每个资源都有唯一的资源标识符(URI)
- 每一个资源都有不同的表现形式如(json,xml等)
- 对资源的操作不会改变资源的标识符
- 所有的操作都是无状态的
RestFul
restful就是rest原则的web服务,此服务是一种ROA 面向资源的架构。restful核心概念就是面向资源。
互联网中,客户端于服务器端之间相互传递的就是资源的表述我们上网的过程中就是调用资源的url,获取它不同的资源表现的过程,这种互动只能使用无状态协议的http协议也就是说服务器必须保存所有状态。客户端可以使用http的几个基本操作包括GET,POST,PUT,PATCH,DELETE。使得服务器上的资源发生状态转移。
概念抽象,直接上代码:
使用SpringDataJPA数据库框架,方便生成持久层代码。
首先引入jpa,mysql的依赖。(此处使用2.2.6.RELEASE版本Springboot)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
此处没有对应版本号也不需要害怕,
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
Springboot starter中已经在帮我们把对应的版本号定义了。
然后找到配置文件,配置好数据源。
再用idea链接数据库。
接下来在idea页面找到这个页面。添加jpsa。
添加完后会在IDEA的左下角多一个persistence模块。
找到对应的项目,右键根据数据库生成对应的映射类。
这样在对应的包下就可以找到生成的数据库映射类。
创建一个UserRepository接口继承JpaRepository,JpaRepository<刚才的映射类类名,映射类的主键类型>
public interface Userrepository extends JpaRepository<User,Integer> {
}
接口不需要注解,底层会生成一个代理类,在Controller中会装配代理类的实例。
创建controller处理类。
@RestController
public class UserController {
@Autowired
private Userrepository userrepository;
@GetMapping("/users/{id}")
public Optional<User> findUsersOne(@PathVariable Integer id){
return userrepository.findById(id);
}
@GetMapping("/users")
public List<User> findUsers(){
return userrepository.findAll();
}
@PostMapping("/users")
public User SaveUsers(User users){
return userrepository.save(users);
}
@PostMapping("/users/{id}")
public User UpdateUsers(User users){
System.out.println("id::::::::::::::"+users.getId());
return userrepository.save(users);
}
@PutMapping("/users")
public User SaveAndFlushUsers(User users){
return userrepository.saveAndFlush(users);
}
@PatchMapping("/users")
public User createUser(User user){
return userrepository.save(user);
}
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Integer id){
userrepository.deleteById(id);
}
@DeleteMapping("/users")
public void deleteUserAll(){
userrepository.deleteAll();
}
}
在处理过程中直接调用注入的userrepository实例的API就可以完成对数据的修改。
启动项目,测试效果。
GET,POST,PUT,PATCH,DELETE都可以完成对应的功能。
使用SpringDataRest简化以上过程
创建一个新Springboot项目。
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
SpringDataRest作为SpringData项目的子集开发者只需要使用注解@RepositoryRestSource标记就可以把整个Repository转换成HAL分割的REST资源。目前已支持SpringDataJPA,SpringDataMongo,SpringData neo4j等。
简单来说SpringDataRest吧我们需要编写的大量的Rest接口模块(可以理解为Controller层代码)做了自动实现。并符合HAL的规范。
HAL规范示例
目前github提供的API就是这种风格在返回结果中添加了额外的信息(链接)。服务端提供的表达可以更好的发现服务器端所支持的动作。
重复之前的JPA操作,生成与数据库对应的映射类。
在创建Repository接口时添加对应的注解@RepositoryRestSource
@RepositoryRestResource//此注解可以生成restful所必须的规范,如controller层的一些接口,get,post,dete,patch都有,而且跟自己写的post、put的性质一样
public interface UserRepository extends JpaRepository<User,Integer> {
/**
* 此方法用自动实现,只需要在用postman调用时,传localhosy:8080/users/search/findByName?username=...即可
* @param username
* @return
*/
public List<User> findByName(@Param("username") String username);
}
在没有写Controller层代码的情况下,启动项目,用postman做测试。
在路径后直接加/1,1默认为id。
还可以使用我们之前定义的方法进行查找,路径为
http://localhost:8080/users/search/findByName?name=孔明
加具体的方法名,定义此方法需要注意的是,如果我们的方法是findByName,我们的sql语句就会是select * from user where name =?
如果是findByUsername就会是select * from user where username =?
jps识别的是我们的方法名。
另外还提供了分页操作,只需要改变访问路径即可。
page是页数从0开始,size是每页显示的内容,会更具数据条数和页数调整,sort是数据的排序,aes,desc 。
post
在使用POST/PUT增加数据时。
不传id,会默认增加一条数据。id生成的话会根据数据库id生成策略。
传id的话,会先判断此id值在数据库中是够存在,不存在的话直接将该数据插入,存在的话就会执行修改此条数据操作。并且会根据此次传的值情况将之前数据库中所有的字段全覆盖掉。范围很广。也比较浪费资源。
delete
能成功删除数据。
这些只是JPA简单的CURD操作。如果有复杂的还需要自己定义。