RestFul的认识

前言

RestFul的认识_第1张图片

RESTful 是 Representational State Transfer 的缩写,是一种软件架构风格,用于在网络上构建和整合应用程序。它基于 HTTP 协议,并定义了一组约束和规范,用于规范客户端和服务器之间的通信。

RESTful API 是遵循 REST 架构规范的 API,它允许客户端以标准化的方式与服务器进行交互。RESTful API 通常用于构建 Web 服务,并已被广泛应用于各种领域,包括电子商务、社交媒体、物联网等。

Rest API设计风格原则

1.使用名词而不是动词

  • 不要使用:
    如:
    /getAllUsers get /users get /users/002
    /createNewUser post /users
    /deleteAllUser delete /users/001

2.Get方法和查询参数不应该涉及状态改变

  • 使用PUT, POST 和DELETE 方法 而不是 GET 方法来改变状态,不要使用GET 进行状态改变。

3.使用复数名词

  • 不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。
    如:
    /cars 而不是 /car
    /users 而不是 /user
    /products 而不是 /product
    /settings 而不是 /setting
    /orders 而不是 /order

4. 使用子资源表达关系

  • 如果一个资源与另外一个资源有关系,使用子资源:
    如:
    GET /cars/711/drivers/ 返回 car 711的所有司机
    GET /cars/711/drivers/4 返回 car 711的4号司机
    GET /users/11/pets 返回 user 11的所有宠物
    GET /users/11/pets/2 返回 user 11的2号宠物

5.使用Http头声明序列化格式

  • 在客户端和服务端,双方都要知道通讯的格式,格式在HTTP-Header中指定
    如:
    Content-Type 定义请求格式
    Accept 定义系列可接受的响应格式

6.为集合提供过滤 排序 选择和分页等功能

  • Filtering过滤:使用唯一的查询参数进行
    GET /cars?color=red 返回红色的cars
    GET /cars?seats<=2 返回小于两座位的cars集合

  • Sorting排序:允许针对多个字段排序
    GET /cars?sort=-manufactorer,+model
    这是返回根据生产者降序和模型升序排列的car集合

  • Field selection
    移动端能够显示其中一些字段,它们其实不需要一个资源的所有字段,给API消费者一个选择字段的能力,这会降低网络流量,提高API可用性。
    GET /cars?fields=manufacturer,model,id,color

  • Paging分页
    使用 limit 和offset.实现分页,缺省limit=20 和offset=0;
    GET /cars?offset=10&limit=5
    为了将总数发给客户端,使用订制的HTTP头: X-Total-Count.
    链接到下一页或上一页可以在HTTP头的link规定,遵循Link规定:
    Link: https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5; rel=“next”,https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3; rel=“last”,https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5; rel=“first”,https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5; rel=“prev”,

7.版本化你的API 支付宝 v1 v2 v3

  • 使得API版本变得强制性,不要发布无版本的API,使用简单数字,避免小数点如2.5.
    一般在Url后面使用?v
    /blog/api/v1

8. 使用Http状态码处理错误

  • 如果你的API没有错误处理是很难的,只是返回500和出错堆栈不一定有用
  • Http状态码提供70个出错,我们只要使用10个左右:
    200 – OK – 一切正常
    201 – OK – 新的资源已经成功创建
    204 – OK – 资源已经成功删除
    304 – Not Modified – 客户端使用缓存数据
    400 – Bad Request – 请求无效,需要附加细节解释如 “JSON无效”
    401 – Unauthorized – 请求需要用户验证
    403 – Forbidden – 服务器已经理解了请求,但是拒绝服务或这种请求的访问是不允许的。
    404 – Not found – 没有发现该资源
    422 – Unprocessable Entity – 只有服务器不能处理实体时使用,比如图像不能被格式化,或者重要字段丢失。
    500 – Internal Server Error – API开发者应该避免这种错误。
    使用详细的错误包装错误: 状态码 数据 header头信息
    {
    “errors”: [
    {
    “userMessage”: “Sorry, the requested resource does not exist”,
    “internalMessage”: “No car found in the database”,
    “code”: 34,
    “more info”: “http://dev.mwaysolutions.com/blog/api/v1/errors/12345”
    }
    ]
    }

Rest API案例

没有使用RestFul的规范之前的设计

@Controller
@RequestMapping("user")
public class DemoController {

    private static final Logger log = LoggerFactory.getLogger(DemoController.class);
    //查询一个
    @RequestMapping("findUserById")
    public String findUserById(Integer id){
        log.info("查询用户id为:{}",id);
        //存储到作用域
        return "showOne";
    }
    //查询所有
    @RequestMapping("findAll")
    public String findAll(){
        log.info("查询所有");
        List<User>  userList =new ArrayList<User>();
        userList.add(new User(21,"xiaochen",2300,new Date()));
        //存储到作用域
        return "showAll";
    }
    //保存
    @RequestMapping("saveUser")
    public String save(User user){
        log.info("user: {}",user);
        return "redirect:/user/findAll";
    }
    //修改
    @RequestMapping("updateUser")
    public String update(User user){
        log.info("user: {}",user);
        return "redirect:/user/findAll";
    }
    @RequestMapping("deleteUser")
    public String delete(User user){
        log.info("user: {}",user);
        return "redirect:/user/findAll";
    }
    
}

这里我们就完全没有按照我们前面所说的RestFul的架构去规范我们的API,下面我们将采用RestFul的设计去规范。

使用了RestFul的设计

@RestController
@RequestMapping("/v1/users") //符合使用复数名词
public class UserController {

    private static final Logger log = LoggerFactory.getLogger(UserController.class);


    // ResponeEntity: springmvc 封装一个专用于restful 响应类   这个类在响应时可以提供响应的状态码,同时还可以自定义响应头信息

    // HttpStatus:   springmvc 封住一个枚举类型类 这个类中都是网络中状态码



    /**
     * 查询某个用户详细
     * @param id
     * @return
     */
    //@RequestMapping(value = "/{id}",method = RequestMethod.GET)
    @GetMapping("/{id}")  //@RequestMapping:子类注解 使用GETMapping代表只能使用GET方式访问到当前请求
    //注解: PathVariable:代表在路径中获取请求参数
    //@ResponseBody //将控制器方法返回值转为json
    public ResponseEntity<User> user(@PathVariable("id") Integer id){
        log.info("本次id: {}",id);
        User user = null;
        try {
            user = new User(id, "小陈", 2300.23, new Date());
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<User>(user,HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return new ResponseEntity<>(user,HttpStatus.OK);
    }


    /**
     * 用户列表
     * @return
     */
    @GetMapping
    //@ResponseBody
    public ResponseEntity<List<User>> users(){
        ArrayList<User> users = new ArrayList<>();
        users.add(new User(21,"小王",2300.23,new Date()));
        users.add(new User(24,"小金豆",3400.23,new Date()));
        return  new ResponseEntity<>(users,HttpStatus.OK);
    }


    /**
     * 添加用户
     */
    @PostMapping
    //@ResponseBody  //@ResponseBody 将方法返回值转为json格式数据 并响应请求   @RequestBody: 接收请求json格式数据 将json格式数据转为对象
    public ResponseEntity<Void> save(@RequestBody  User user){
        log.info("name:{} salary:{} bir:{}",user.getName(),user.getSalary(),user.getBir());
        //调用业务方法
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);//没有内容
    }


    /**
     * 更新用户
     * @param user
     */
    @PutMapping("/{id}")
    //@ResponseBody
    public ResponseEntity<Void> update(@PathVariable("id") Integer id,@RequestBody  User user){
        log.info("id:{} ",id);
        log.info("name:{} salary:{} bir:{}",user.getName(),user.getSalary(),user.getBir());
        //调用业务方法
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);//没有内容
    }

    /**
     * 删除用户信息
     * @param id
     */
    @DeleteMapping("/{id}")
    //@ResponseBody
    public ResponseEntity<Void> delete(@PathVariable("id") Integer id){
        log.info("本次id: {}",id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);//没有内容
    }


    /**
     * 获取这个人所有宠物
     */
    @GetMapping("/{id}/pets")
    public ResponseEntity<List<Pet>> pets(@PathVariable("id") Integer id){
        log.info("查询那个人id: {}",id);
        List<Pet> pets = Arrays.asList(new Pet(21, "小红帽", 23), new Pet(22, "小猪", 22));
        return new ResponseEntity<>(pets, HttpStatus.OK);
    }

    /**
     * 获取这个人某个宠物
     */
    @GetMapping("/{id}/pets/{pid}")
    public ResponseEntity<Pet> pet(@PathVariable("id") Integer id,@PathVariable("pid") Integer petId){
        log.info("查询那个人id: {}",id);
        Pet pet = new Pet(21, "小红帽", 23);
        return new ResponseEntity<>(pet, HttpStatus.OK);
    }



}

上述方法就

代码示例的设计特点总结

  1. 使用了 @RestController 注解
    @RestController 注解表示该类是一个 RESTful 控制器,它可以将方法返回值自动转换为 JSON 格式数据并响应请求。

  2. 使用了标准的 HTTP 方法
    @GetMapping:用于处理 GET 请求
    @PostMapping:用于处理 POST 请求
    @PutMapping:用于处理 PUT 请求
    @DeleteMapping:用于处理 DELETE 请求

  3. 使用了 @PathVariable 注解
    @PathVariable 注解用于获取路径中的参数。

  4. 使用了 @RequestBody 注解
    @RequestBody 注解用于接收请求中的 JSON 格式数据并将其转换为对象。

  5. 使用了 ResponseEntity 类
    ResponseEntity 类用于封装响应数据,包括响应状态码和响应体。

你可能感兴趣的:(restful,后端)