REST是软件架构的规范体系结构,它将资源的状态以适合客户端的形式从服务端发送到客户端(或相反方向)。在REST中,通过URL进行资源定位,用HTTP动作(GET、POST、DELETE、PUSH等)描述操作,完成功能。可以查看另一篇博客:Spring MVC对RESTful的支持
遵循RESTful风格,可以使开发的接口通用,以便调用者理解接口的作用。基于REST构建的API就是RESTful(REST风格)API。这样可以统一规范,减少沟通、学习和开发的成本。
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方法来区别增加、删除、修改、查询。
HTTP的返回状态一般有以下几种
详细请看:图解HTTP知识点
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;
}
/**
* 增
* @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
添加文章接口
为了便于编写和维护稳定,可以使用Swagger来编写API接口文档,提升团队开发效率。
添加相关依赖
<!-- 添加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);
}
}
完成上述配置之后,就生成了文档,但还是需要自己增加一些说明丰富文档内容,可以添加以下注释来增加说明。
详细请看:swagger注释API详细说明
测试
在浏览器输入:http://localhost:8080/swagger-ui.html,效果如下: