Spring Boot前后端分离开发之后端开发

  • 前后端分离开发概述
    • 相关术语
    • 前后端分离开发概述
  • 接口规范
    • RESTful API的理解
    • RESTful风格的特点
    • URI规范
      • 路径
      • 请求方式
      • 过滤条件
      • 其他说明
    • 返回结果
    • 状态码和信息
    • json介绍
    • 在线json校验
  • postman
    • 安装
    • 使用
  • Spring MVC的restful实现
    • 查询所有班级信息
    • 查询指定班级信息
    • 关于格式的说明
    • 根据id删除班级信息
    • 插入数据
    • 根据班级编号修改数据
  • 结束语

个人主页: 不断前进的皮卡丘
博客描述: 梦想也许遥不可及,但重要的是追梦的过程,用博客记录自己的成长,记录自己一步一步向上攀登的印记
系列专栏: Spring Boot专栏

前后端分离开发概述

相关术语

前端和后端:
前端和后端是针对于技术来说的。
前端: 负责页面展示相关的技术,比如html,css,js,jquery,vue,bookstrap等
后端:与数据,还有业务逻辑相关,比如Java,MySQL等
移动端:移动设置相关的技术,比如Android(java,kotilin),iOS(swift)
全栈工程师:前端,后端,移动端
全过程工程师:产品设计,代码开发,测试,运维

前台和后台
前台和后台是相对于使用者来说的
前台:它是相对于普通用户来说,比如用户可以看到的网站
后台:它是对应程序的管理人员和运维人员而言的,后台也包括前端(页面)和后端(数据和业务)

前后端分离开发概述

前后端分离模式概述

早期的时候,web应用中的数据,页面,渲染都在服务端完成,但是随着时代的发展,前端设备越来越多(手机,平板,桌面电脑等),后来就慢慢兴起前后端分离的思想:后端负责数据处理,前端负责数据渲染,前端静态页面调用指定api获取固定格式的数据
为了实现前后端分离,必须要有一种统一的机制,方便不同的前端设备和后端进行通信

接口规范

RESTful API的理解

  • RESTful是什么
    • RESTful是当前比较流行的一种互联网软件架构模型,通过统一的规范来完成不同终端的数据访问和交换,REST全称是Representaional State Transfer(资源表现层状态转换)
    • RESTful的优点:结构清晰,有统一的标准、扩展性好
    • 是前后端交互的规范
  • Resources
    • 资源指的是网络中的某一个具体文件,类型不限,可以是文本、图片、音频、视频、数据流等,也可能是一个学生的信息,添加,删除,查询等都被看成是不同资源操作。
    • 如何获取?可以通过统一资源标识符找到这个实体,URI,每一个资源都有特定的URI,通过URL可以找到一个具体的资源HTTP 协议详解 —— URI、HTTP protocol、HTTP headers
  • Pepresentation
    • 资源表现层,资源的具体表现形式,比如一段文字,可以使用TXT,JSON,HTML,XML等不同的形式来描述
    • 对互联网的任何操作,都看成是对资源的操作
  • State Transfer
    • 状态转化是指客户端和服务端之间的数据交换,因为HTTP请求不能传输数据的状态(HTTP协议是无状态请求),所有的状态都保存在服务端,如果客户端希望访问服务端的数据,就需要使其发生状态改变,同时这种状态转化是建立在表现层,完成转换就表示资源的表现形式发生了改变
    • 对于资源的操作行为的表现方式称为转换
    • 状态指的是对资源的操作行为

RESTful风格的特点

1.URL传参更加简洁

  • 传统形式URL:

    postman

    我们知道浏览器它只能发送GET请求,这样的话,其他的请求方式,我们是没法测试的。
    接下来就介绍前后端分离开发,经常用到的工具postman

    安装

    官网地址:https://www.postman.com/downloads/

    我们可以选择把exe文件放在指定文件家,然后双击


    然后可以去登录,或者跳过登录

    使用



    点击send(代码实现在后面介绍)

    Spring MVC的restful实现

    查询所有班级信息

    restful风格要求返回的字符串是json格式
    @ResponseBody可以把Java对象转化为json对象,并返回给客户端
    我们写一个小demo测试一下(数据是从数据库中查询出来的)
    实体类(班级表对应的实体类)

    @Data@NoArgsConstructor@AllArgsConstructorpublic class Cls {    private Integer id;    private String name;}

    Controller(可以直接用@RestController)

    @Controller@ResponseBodypublic class ClsController {    @Autowired    private ClsService clsService;    /**     * 查询所有班级信息     */    @GetMapping("/school/cls")    public List<Cls> queryAllCls() {        try {            List<Cls> clsList = clsService.queryAllCls();            return clsList;        } catch (Exception e) {            e.printStackTrace();        }        return null;    }}

    Service

    public interface ClsService {    /**     * 查询所有班级信息     * @return     */    List<Cls> queryAllCls() throws Exception;}

    Service实现类

    @Servicepublic class ClsServiceImpl implements ClsService {    @Autowired    private ClsMapper clsMapper;    @Override    public List<Cls> queryAllCls() throws Exception {        return clsMapper.queryAllCls();    }}

    Mapper

    @Mapperpublic interface ClsMapper {   /**    * 查询所有班级信息   */   @Select("select * from cls")   List<Cls> queryAllCls() throws Exception;}


    下面这张图片显示的数据和上面图片的不一样,是因为后来我把格式进行修改了,也就是对代码进行了修改,后面会进行说明

    单元测试

    @SpringBootTestclass ClsMapperTest {    @Autowired    private ClsMapper clsMapper;    @Test    public void testQueryAllCls() throws Exception {        List<Cls> cls = clsMapper.queryAllCls();        for (Cls c:cls){            System.out.println(c);        }    }}

    输出内容:

    Cls(id=1, name=计科1)Cls(id=2, name=计科2)Cls(id=3, name=软工1)Cls(id=4, name=软工2)

    查询指定班级信息

    @PathVariable:把请求路径的变量和形参名进行绑定
    Controller

    @RestControllerpublic class ClsController {    @Autowired    private ClsService clsService;    /**     * 查询所有班级信息     */    @GetMapping("/school/cls")    public List<Cls> queryAllCls() {        try {            List<Cls> clsList = clsService.queryAllCls();            return clsList;        } catch (Exception e) {            e.printStackTrace();        }        return null;    }     /**     * 查询指定编号的班级信息     */    @GetMapping("/school/cls/{id}")    public Cls queryClsById(@PathVariable("id") Integer id){        Cls cls= null;        try {            cls = clsService.queryClsById(id);        } catch (Exception e) {            e.printStackTrace();        }        return cls;    }}

    Service

    public interface ClsService {    /**     * 查询所有班级信息     * @return     */    List<Cls> queryAllCls() throws Exception;    /**     * 查询指定编号的班级信息     * @param id     * @return     * @throws Exception     */    Cls queryClsById(Integer id) throws Exception;}

    Service实现类

    @Servicepublic class ClsServiceImpl implements ClsService {    @Autowired    private ClsMapper clsMapper;    @Override    public List<Cls> queryAllCls() throws Exception {        return clsMapper.queryAllCls();    }    @Override    public Cls queryClsById(Integer id) throws Exception {        return clsMapper.queryClsById(id);    }}

    Mapper

    @Mapperpublic interface ClsMapper {   /**    * 查询所有班级信息   */   @Select("select * from cls")   List<Cls> queryAllCls() throws Exception;   /**    * 查询指定编号的班级信息    * @param id    * @return    */   @Select("select * from  cls where id=#{id}")   Cls queryClsById(@Param("id") Integer id);}


    关于格式的说明

    :::info
    接口返回类型:
    json格式
    ——code:状态码
    ——message:状态信息
    ——data:真实数据
    :::
    我们如果想要达到这样的效果的话,有两种方法,第一种就是我们写一个实体类,第二种方法就是通过map来存数据
    通过定义实体类

    通过map



    根据id删除班级信息

    /**     * 根据id来删除班级信息     * @param id     * @return     */    @RequestMapping(value = "/school/cls/{id}" ,method = RequestMethod.DELETE)    public ResultInfo deleteById(@PathVariable("id") Integer id){        ResultInfo info = new ResultInfo();        try {            clsService.deleteById(id);            info.setOk();        } catch (Exception e) {            e.printStackTrace();            info.setError();        }        return info;    }

    插入数据

    默认是接收key-value格式的数据,如果前端传入的是json格式的数据,那么数据就会接收失败,如果我们希望前端传送的数据是json格式的数据,那么,我们就需要在Controller中,在参数前面加上@RequestBody注解(把请求体中的json格式转换为对应Java实体类格式)
    Controller

      /**     * 添加班级 前端需要传参数进来     * @return     */   @PostMapping("/school/cls")    public ResultInfo addCls(Cls cls){        ResultInfo info = new ResultInfo();        try {            clsService.insert(cls);            info.setOk();            info.setData(cls);        } catch (Exception e) {            e.printStackTrace();            info.setError();        }        return info;    }

    Service

    public interface ClsService {    /**     * 查询所有班级信息     * @return     */    List<Cls> queryAllCls() throws Exception;    /**     * 查询指定编号的班级信息     * @param id     * @return     * @throws Exception     */    Cls queryClsById(Integer id) throws Exception;    void deleteById(Integer id) throws Exception;    void insert(Cls cls) throws Exception;}

    Service实现类

    @Servicepublic class ClsServiceImpl implements ClsService {    @Autowired    private ClsMapper clsMapper;    @Override    public List<Cls> queryAllCls() throws Exception {        return clsMapper.queryAllCls();    }    @Override    public Cls queryClsById(Integer id) throws Exception {        return clsMapper.queryClsById(id);    }    @Override    public void deleteById(Integer id) throws Exception {        clsMapper.deleteById(id);    }    //添加数据    @Override    public void insert(Cls cls) throws Exception {        clsMapper.insert(cls);    }}

    Mapper

    @Mapperpublic interface ClsMapper {   /**    * 查询所有班级信息   */   @Select("select * from cls")   List<Cls> queryAllCls() throws Exception;   /**    * 查询指定编号的班级信息    * @param id    * @return    */   @Select("select * from  cls where id=#{id}")   Cls queryClsById(@Param("id") Integer id);   /**    * 根据id删除数据    * @param id    */   @Delete("delete from  cls where id=#{id}")    void deleteById(@Param("id") Integer id);   /**    * 插入班级    * @param cls    */   @Insert("insert into cls values(default,#{name})")   @Options(useGeneratedKeys = true,keyColumn = "id",keyProperty = "id")   void insert(Cls cls);}


    通过数据库查询的前后两次对比可以很清楚的发现,插入数据成功了

    根据班级编号修改数据

    Controller

     @PutMapping("/school/cls/{id}")    public ResultInfo updateById(@PathVariable("id") Integer id,String name){        ResultInfo info = new ResultInfo();        try {            clsService.updateById(id,name);            info.setOk();            info.setData(new Cls(id,name));        } catch (Exception e) {            e.printStackTrace();            info.setError();        }        return info;    }

    Service

    public interface ClsService {    /**     * 查询所有班级信息     * @return     */    List<Cls> queryAllCls() throws Exception;    /**     * 查询指定编号的班级信息     * @param id     * @return     * @throws Exception     */    Cls queryClsById(Integer id) throws Exception;    void deleteById(Integer id) throws Exception;    void insert(Cls cls) throws Exception;    void updateById(Integer id, String name) throws Exception;}

    Service实现类

    @Servicepublic class ClsServiceImpl implements ClsService {    @Autowired    private ClsMapper clsMapper;    @Override    public List<Cls> queryAllCls() throws Exception {        return clsMapper.queryAllCls();    }    @Override    public Cls queryClsById(Integer id) throws Exception {        return clsMapper.queryClsById(id);    }    @Override    public void deleteById(Integer id) throws Exception {        clsMapper.deleteById(id);    }    @Override    public void insert(Cls cls) throws Exception {        clsMapper.insert(cls);    }    @Override    public void updateById(Integer id, String name) throws Exception {        clsMapper.updateById(id,name);    }}

    Mapper

    @Mapperpublic interface ClsMapper {   /**    * 查询所有班级信息   */   @Select("select * from cls")   List<Cls> queryAllCls() throws Exception;   /**    * 查询指定编号的班级信息    * @param id    * @return    */   @Select("select * from  cls where id=#{id}")   Cls queryClsById(@Param("id") Integer id);   /**    * 根据id删除数据    * @param id    */   @Delete("delete from  cls where id=#{id}")    void deleteById(@Param("id") Integer id);   /**    * 插入班级    * @param cls    */   @Insert("insert into cls values(default,#{name})")   @Options(useGeneratedKeys = true,keyColumn = "id",keyProperty = "id")   void insert(Cls cls);   /**    * 根据id修改数据    * @param id    * @param name    */   @Update("update cls set name=#{name} where id=#{id} ")   void updateById(@Param("id") Integer id, @Param("name") String name);}


    通过查询数据库中的数据,也可以发现数据改变了

    结束语

    在下一篇文章中会讲到跨域处理