SpringBoot总结(十五)——接口架构风格(RESTful)

【第一部分】历史文章:
SpringBoot总结(一)——第一个SpringBoot项目
SpringBoot总结(二)——Spring Boot的自动配置
SpringBoot总结(三)——SpringBoot的配置文件
SpringBoot总结(四)——@Value和@ConfigurationProperties的区别
SpringBoot总结(五)——@PropertySource注解与@ImportResource注解
SpringBoot总结(六)——SpringBoot配置文件占位符
SpringBoot总结(七)——Profile的使用
SpringBoot总结(八)——配置文件的加载位置
SpringBoot总结(九)——@Conditional注解与自动配置报告
SpringBoot总结(十)——SpringBoot+Mybatis实现数据库的CRUD(从创建到实现【超详细附代码】)
SpringBoot总结(十一)——SpringBoot的静态资源映射规则
SpringBoot总结(十二)——登录界面的实现
SpringBoot总结(十三)——修改嵌入式Servlet容器配置
SpringBoot总结(十四)——SpringBoot整合JDBCTemplate及Druid连接池


接口架构风格(RESTful)



前言

本篇文章主要介绍了RESTful的一些知识点,以及基于RESTful风格的CRUD的例子,和基于SpringBoot为手机APP、PC、构建统一风格的Restful API。


一、什么是REST

REST是软件架构的规范体系结构,它将资源的状态以适合客户端的形式从服务器端发送到客户端(或者相反的方向)。在REST中,通过URL进行资源定位,用HTTP动作(GET、POST、DELETE、PUT等)描述操作完成功能。

遵循RESTful风格,可以使得开发的接口通用,以便调用者理解接口的作用。因此,基于REST构建的API就是RESTful(REST风格)API。
各大机构提供的API基本都是RESTful风格的。这样可以统一规范,减少沟通,学习和开发的成本。

二、HTTP动作与CRUD动作映射

RESTful风格使用同一个URL,通过约定不同的HTTP方法来实施不同的业务。
下面是普通网页的CRUD和RESTful风格的CRUD的区别:

动作普通CRUD的URL普通CRUD的HTTP方法ReSTful的URLRESTful的CRUD的HTTP方法
查询Article/id=1GETArticle/{id}GET
添加Article?title=xxx&body=xxxGET/POSTArticlePOST
修改Article/update?id=xxxGETArticle/{id}PUT或者PATCH
删除Article/delete?id=xxxGETArticle/{id}DELETE

三、基于RESTful风格的CRUD例子

3.1、主要代码

下面是基于RESTful风格的CRUD的例子,并且定义了统一的数据返回格式。
操作数据库的方式采用了SpringBootSpringDataJPA整合的方式;具体这里将不再详细介绍,下面附上一些主要的代码。

ArticleController.java

package com.example.controller;
import com.example.entity.Article;
import com.example.repository.ArticleRepository;
import com.example.result.ExceptionMsg;
import com.example.result.Response;
import com.example.result.ResponseData;
import io.github.yedaxia.apidocs.ApiDoc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 文章接口类
 */
@RequestMapping("/article")
@RestController
public class ArticleController {

    protected Response result(ExceptionMsg msg){
        return new Response(msg);
    }
    protected Response result(){
        return new Response();
    }

    @Autowired
    private ArticleRepository articleRepository;


    /**
     * 查询所有文章
     * @return
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ResponseData getArticleList() {
        List<Article> list = new ArrayList<Article>(articleRepository.findAll());
        return new ResponseData(ExceptionMsg.SUCCESS,list);

    }

    /**
     * 增加文章信息
     * @param article  文章对象
     * @return
     */
    @RequestMapping(value = "/", method = RequestMethod.POST)
    public ResponseData add(@RequestBody Article article) {
        articleRepository.save(article);
        return new ResponseData(ExceptionMsg.SUCCESS,article);
    }


    /**
     * 删除文章信息
     * @param id  文章id
     * @return  Response
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public Response delete(@PathVariable("id") int id) {
        articleRepository.deleteById(id);
        return result(ExceptionMsg.SUCCESS);

    }


    /**
     * 修改文章信息
     * @param model  文章对象
     * @return ResponseData
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public ResponseData update(@RequestBody Article model) {
        articleRepository.save(model);
        return new ResponseData(ExceptionMsg.SUCCESS,model);
    }

    /**
     * 根据文章id 查询文章信息
     * @param id
     * @return ResponseData
     * @throws IOException
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public ResponseData findArticle(@PathVariable("id") int id) throws IOException {
        Article article = articleRepository.findById(id);
        if (article != null) {
            return new ResponseData(ExceptionMsg.SUCCESS,article);
        }
        return new ResponseData(ExceptionMsg.FAILED,article);
    }

}

3.2、测试数据

启动项目,进行如下的测试。

四、为手机APP、PC、H5网页提供统一风格的API

4.1、实现响应的枚举类


package com.example.result;
//实现响应的枚举类
public enum ExceptionMsg {
	SUCCESS("200", "操作成功"),
	FAILED("999999","操作失败"),
    ParamError("000001", "参数错误!"),
    FileEmpty("000400","上传文件为空"),
    LimitPictureSize("000401","图片大小必须小于2M"),
    LimitPictureType("000402","图片格式必须为'jpg'、'png'、'jpge'、'gif'、'bmp'")
    ;
   private 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;
	}

    
}

4.2、实现返回的对象实体

package com.example.result;

/**
 * @author 2017810402084
 * 实现返回对象实体
 */
public class Response {
	/** 返回信息码*/
	private String rspCode="000000";
	/** 返回信息内容*/
	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 String getRspCode() {
		return rspCode;
	}
	public void setRspCode(String rspCode) {
		this.rspCode = rspCode;
	}
	public String getRspMsg() {
		return rspMsg;
	}
	public void setRspMsg(String rspMsg) {
		this.rspMsg = rspMsg;
	}

	@Override
	public String toString() {
		return "Response{" +
				"rspCode='" + rspCode + '\'' +
				", rspMsg='" + rspMsg + '\'' +
				'}';
	}
}

4.3、封装返回结果

package com.example.result;

import com.example.exception.BusinessException;

/**
 * @author 2017810402084
 * 返回结果数据格式封装
 */
public class ResponseData extends Response {
    private Object data;


    public ResponseData() {

    }

    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;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }


    /**
     * 自定义异常的返回结果
     * @param de
     * @return
     */
    public static ResponseData defineBusinessException(BusinessException de) {
        ResponseData responseData = new ResponseData();
        responseData.setRspCode(de.getCode());
        responseData.setRspMsg(de.getMsg());
        responseData.setData(null);
        return responseData;
    }
}

4.4、统一处理异常

package com.example.exception;
import com.example.result.ResponseData;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
 * @author 2017810402084
 * 定义全局异常处理类:来处理各种的异常,包括自己定义的异常和内部的异常
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * (1)处理自定义异常BusinessException
     */

    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public ResponseData bizBusinessException(BusinessException e) {
        return  ResponseData.defineBusinessException(e);
    }


    /**
     * (2)处理其他的异常
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseData exceptionHandler(Exception e) {
        return new ResponseData(e);
    }
}

4.5、自定义异常

package com.example.exception;
/**
 * @author 2017810402084
 * 创建自定义异常处理类:BusinessException.java
 */

public class BusinessException extends RuntimeException{

    private String code;
    private String msg;

    public BusinessException(String code, String msg) {
       this.msg = msg;
        this.code = code;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

4.6、进行测试

package com.example.controller;
import com.example.exception.BusinessException;
import com.example.exception.UserNameNotMatchPasswordException;
import com.example.result.ResponseData;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
/**
 *
 * 统一异常测试类
 */

@RestController
@RequestMapping("/test")

public class TestController {

    /**
     * 自定义异常测试
     * @return
     */
    @RequestMapping("/BusinessException")
    public ResponseData DeException() {
        throw new BusinessException("40000000", "出错了!");
    }


    /**
     * 处理其他的异常
     * @return
     */
    @RequestMapping("/getException")
    public ResponseData Exception() {

        ResponseData responseData = new ResponseData();
        responseData.setRspCode("400");
        responseData.setRspMsg("出错");

        return responseData;
    }
}

在这里插入图片描述
在这里插入图片描述


总结

以上就是本篇所介绍的内容,以一个简单的例子,来演示了基于RESTful风格的CRUD操作,以及构造统一风格的RESTful API。希望通过这个例子能给予大家帮助。😊

关于本项目代码获取方式:关注+私信并回复:【RESTful项目】即可获取哦
在这里插入图片描述

  • 15
    点赞
  • 175
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小Java开发者

“是一种鼓励,你懂的”

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值