SpringBoot系列五:接口架构风格——RESTful

文章目录

    • 什么是REST
    • HTTP方法与CRUD动作映射
    • HTTP的返回状态
    • 通过实例展示RESTful
      • 响应枚举类
      • 响应对象实体
      • 封装返回结果
      • 统一异常处理
      • CRUD控制器
      • 测试
    • 用Swagger实现接口文档
      • 配置Swagger
      • 编写接口文档


什么是REST

REST是软件架构的规范体系结构,它将资源的状态以适合客户端的形式从服务端发送到客户端(或相反方向)。在REST中,通过URL进行资源定位,用HTTP动作(GET、POST、DELETE、PUSH等)描述操作,完成功能。可以查看另一篇博客:Spring MVC对RESTful的支持

遵循RESTful风格,可以使开发的接口通用,以便调用者理解接口的作用。基于REST构建的API就是RESTful(REST风格)API。这样可以统一规范,减少沟通、学习和开发的成本。
SpringBoot系列五:接口架构风格——RESTful_第1张图片

HTTP方法与CRUD动作映射

RESTful风格使用同一个URL,通过约定不同HTTP方法来实施不同业务。

普通网页CRUD和RESTful风格的CRUD的区别如下表:

动作 普通CRUD的URL 普通CRUD的HTTP方法 RESTful的URL RESTful的CRUD的HTTP方法
查询 Article/id=1 GET Article/{id} GET
添加 Article?title=xxx&body=xxx GET/POST Article POST
删除 Article/update?id=xxx GET Article/{id} PUT/PATCH
修改 Article/delete?id=xxx GET Article/{id} DELETE

通过以上的对比看出,RESTful风格的CRUD比传统的CRUD简单明了,通过HTTP方法来区别增加、删除、修改、查询。
SpringBoot系列五:接口架构风格——RESTful_第2张图片


SpringBoot系列五:接口架构风格——RESTful_第3张图片

SpringBoot系列五:接口架构风格——RESTful_第4张图片

SpringBoot系列五:接口架构风格——RESTful_第5张图片

SpringBoot系列五:接口架构风格——RESTful_第6张图片

HTTP的返回状态

HTTP的返回状态一般有以下几种

  • 200:成功
  • 400:错误请求
  • 404:没找到资源
  • 403:禁止
  • 500:服务器内部错误

详细请看:图解HTTP知识点

通过实例展示RESTful

响应枚举类

public enum  ExceptionMsg {
     
    SUCCESS("200", "操作成功"),
    FAILED("999999","操作失败"),
    ParamError("000001", "参数错误!"),
    FileEmpty("000400","上传文件为空"),
    LimitPictureSize("000401","图片大小必须小于2M"),
    LimitPictureType("000402","图片格式必须为'jpg'、'png'、'jpge'、'gif'、'bmp'")
    ;
    ExceptionMsg(String code, String msg) {
     
        this.code = code;
        this.msg = msg;
    }
    private String code;
    private String msg;
    public String getCode() {
     
        return code;
    }
    public String getMsg() {
     
        return msg;
    }
}

响应对象实体

public class Response {
     
    /** 返回信息码*/
    private String rspCode="200";
    /** 返回信息内容*/
    private String rspMsg="操作成功";
	public Response() {
     
	    }
    public Response(ExceptionMsg msg){
     
        this.rspCode=msg.getCode();
        this.rspMsg=msg.getMsg();
    }
    public Response(String rspCode) {
     
        this.rspCode = rspCode;
        this.rspMsg = "";
    }
    public Response(String rspCode, String rspMsg) {
     
        this.rspCode = rspCode;
        this.rspMsg = rspMsg;
    }

封装返回结果

public class ResponseData extends Response {
     
    private Object data;
    public ResponseData(Object data) {
     
        this.data = data;
    }
    public ResponseData(ExceptionMsg msg) {
     
        super(msg);
    }
    public ResponseData(String rspCode, String rspMsg) {
     
        super(rspCode, rspMsg);
    }
    public ResponseData(String rspCode, String rspMsg, Object data) {
     
        super(rspCode, rspMsg);
        this.data = data;
    }
    public ResponseData(ExceptionMsg msg, Object data) {
     
        super(msg);
        this.data = data;
    }

统一异常处理

400 - Bad Request

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MissingServletRequestParameterException.class)
public Map<String, Object> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
     
    logger.error("缺少请求参数", e);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("rspCode", 400);
    map.put("rspMsg", e.getMessage());
    //发生异常进行日志记录,写入数据库或者其他处理,此处省略
    return map;
}

 @ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public Map<String, Object> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
     
    logger.error("参数解析失败", e);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("rspCode", 400);
    map.put("rspMsg", e.getMessage());
    //发生异常进行日志记录,写入数据库或者其他处理,此处省略
    return map;
}

除了以上两种还有参数验证失败、参数绑定失败等异常。

415 - Unsupported Media Type

@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
public Map<String, Object> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
     
    logger.error("不支持当前媒体类型", e);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("rspCode", 415);
    map.put("rspMsg", e.getMessage());
    //发生异常进行日志记录,写入数据库或者其他处理,此处省略
    return map;
}

405 - Method Not Allowed

@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public Map<String, Object> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
     
    logger.error("不支持当前请求方法", e);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("rspCode", 405);
    map.put("rspMsg", e.getMessage());
    //发生异常进行日志记录,写入数据库或者其他处理,此处省略
    return map;
}

CRUD控制器

/**
 * 增
 * @param article
 * @return
 */
@RequestMapping(value = "/", method = RequestMethod.POST)
public ResponseData add(Article article) {
     
    articleRepository.save(article);
    // return "{success:true,message: \"添加成功\" }";
    return new ResponseData(ExceptionMsg.SUCCESS,article);
}


/**
 * 删
 * @param id
 * @return
 */
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public Response delete(@PathVariable("id") long id) {
     
    articleRepository.deleteById(id);
    return result(ExceptionMsg.SUCCESS);
    //return new ResponseData(ExceptionMsg.SUCCESS,"");
}


/**
 * 改
 * @param model
 * @return
 */
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public ResponseData update(Article model) {
     
    articleRepository.save(model);
    return new ResponseData(ExceptionMsg.SUCCESS,model);
}

/**
 * 查
 * @param id
 * @return
 * @throws IOException
 */
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ResponseData findArticle(@PathVariable("id") Integer id) throws IOException {
     
    Article article = articleRepository.findById(id);
    if (article != null) {
     
        return new ResponseData(ExceptionMsg.SUCCESS,article);
    }
    return new ResponseData(Exceptio

测试

添加文章接口

SpringBoot系列五:接口架构风格——RESTful_第7张图片
查询文章接口

SpringBoot系列五:接口架构风格——RESTful_第8张图片
修改文章接口

SpringBoot系列五:接口架构风格——RESTful_第9张图片
删除文章接口

SpringBoot系列五:接口架构风格——RESTful_第10张图片

用Swagger实现接口文档

为了便于编写和维护稳定,可以使用Swagger来编写API接口文档,提升团队开发效率。

配置Swagger

添加相关依赖

<!-- 添加Swagger依赖 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<!-- 添加Swagger-UI依赖 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

Swagger配置类

@Configuration
public class SwaggerConfig {
     
  @Bean
  public Docket createRestApi() {
     
      return new Docket(DocumentationType.SWAGGER_2)
              .apiInfo(apiInfo())
              .select()
              .apis(RequestHandlerSelectors.basePackage("cn.lwz.restful.controller"))
              .paths(PathSelectors.any())
              .build();
  }
  private ApiInfo apiInfo() {
     
      return new ApiInfoBuilder()
              .title(" RESTful APIs")
              .description("RESTful APIs")
              .termsOfServiceUrl("http://localhost:8080/")
              .contact("long")
              .version("1.0")
              .build();
  }
}

在Java目录下添加SwaggerApplication类

@SpringBootApplication
@EnableSwagger2
public class SwaggerApplication {
     
    public static void main(String[] args) {
     
        SpringApplication.run(SwaggerApplication.class, args);
    }
}

编写接口文档

完成上述配置之后,就生成了文档,但还是需要自己增加一些说明丰富文档内容,可以添加以下注释来增加说明。
SpringBoot系列五:接口架构风格——RESTful_第11张图片
详细请看:swagger注释API详细说明

测试

在浏览器输入:http://localhost:8080/swagger-ui.html,效果如下:

SpringBoot系列五:接口架构风格——RESTful_第12张图片
可以查看方法说明详情:

SpringBoot系列五:接口架构风格——RESTful_第13张图片

你可能感兴趣的:(SpringBoot,restful,springboot,java)