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


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获取固定格式的数据
为了实现前后端分离,必须要有一种统一的机制,方便不同的前端设备和后端进行通信
Spring|Spring Boot前后端分离之后端开发
文章图片

Spring|Spring Boot前后端分离之后端开发
文章图片

接口规范 RESTful API的理解
  • RESTful是什么
    • RESTful是当前比较流行的一种互联网软件架构模型,通过统一的规范来完成不同终端的数据访问和交换,REST全称是Representaional State Transfer(资源表现层状态转换)
    • RESTful的优点:结构清晰,有统一的标准、扩展性好
    • 是前后端交互的规范
  • Resources
    • 资源指的是网络中的某一个具体文件,类型不限,可以是文本、图片、音频、视频、数据流等,也可能是一个学生的信息,添加,删除,查询等都被看成是不同资源操作。
    • 如何获取?可以通过统一资源标识符找到这个实体,URI,每一个资源都有特定的URI,通过URL可以找到一个具体的资源HTTP 协议详解 —— URI、HTTP protocol、HTTP headers
    • Spring|Spring Boot前后端分离之后端开发
      文章图片
  • Pepresentation
    • 资源表现层,资源的具体表现形式,比如一段文字,可以使用TXT,JSON,HTML,XML等不同的形式来描述
    • 对互联网的任何操作,都看成是对资源的操作
  • State Transfer
    • 状态转化是指客户端和服务端之间的数据交换,因为HTTP请求不能传输数据的状态(HTTP协议是无状态请求),所有的状态都保存在服务端,如果客户端希望访问服务端的数据,就需要使其发生状态改变,同时这种状态转化是建立在表现层,完成转换就表示资源的表现形式发生了改变
    • 对于资源的操作行为的表现方式称为转换
    • 状态指的是对资源的操作行为
RESTful风格的特点 1.URL传参更加简洁
  • 传统形式URL: http://localhost:8080/findById?id=1
  • RESTful风格URL: http://localhost:8080/findById/1
2.完成不同终端之间的资源共享,RESTful提供了一套规范,不同终端之间只要遵守这个规范,就可以实现数据交互。
RESTful具体来说是四种表现形式,HTTP请求中四种请求类型(GET、POST、PUT、DELETE)分别表示四种常规操作,CRUD。通过不同的请求方式来完成不同的操作
  • GET用来获取资源
  • POST用来创建资源
  • PUT用来修改资源
  • DELETE用来删除资源
两个终端要完成数据交互,基于RESTful的方式,增删改查操作分别需要使用不同的HTTP请求类型来访问。
传统的web开发中form表单只支持GET和POST请求,如何解决呢?我们可以通过添加HiddenHttpMethodFilter过滤器,可以把POST请求转为PUT或者DELETE
RESTful风格的话,响应的数据格式要求是json
URI规范
  • uri是统一资源标识符
路径
  • 只能有名词,要求和数据库中的表名对应
  • 建议名词使用复数
  • 在URI中使用小写字母
  • 不要在末尾使用/
  • 使用连字符(-),每个公司可能要求不一样
http://api.example.com/school/students http://api.example.com/school/students/{100}

请求方式
  • GET用来获取资源
  • POST用来创建资源
  • PUT用来修改资源
  • DELETE用来删除资源
GEThttp://api.example.com/school/students 查询所有学生信息 GEThttp://api.example.com/school/students/{id} 查询指定id的学生信息 POSThttp://api.example.com/school/students 添加学生信息 PUThttp://api.example.com/school/students/{id} 修改指定id的学生信息 DELETE http://api.example.com/school/students/{id} 删除指定id的学生信息

过滤条件
如果记录数量很多,服务器不可能返回所有信息给用户,API需要提供参数,来过滤返回的结果
?limit=10 指定返回记录的数量 ?offset=10 指定返回记录的开始位置 ?page=2&pageCount=100 指定第几页,以及每页的记录数 ?orderby=name&order=asc 指定返回结果按照哪一个属性排序,以及排序顺序 ?age>=20指定筛选条件

其他说明
有的公司的请求方式还是使用GET和POST请求,然后通过路径来区分目的
/stus/query查询操作 /stus/delete/{sid} 根据id删除

返回结果 返回数据的格式必须要使用json格式,返回结果建议包含三个部分的信息,状态码,提示信息和真实数据
状态码和信息 常见的HTTP状态码
json介绍 JSON(JavaScript Object Notation, JS对象标记)是一种轻量级的数据交换格式,目前使用特别广泛。
json的数据格式分成json Object(json对象)和json array(json数组)
json Object数据格式:
  • 外层加大括号
  • 内层是k:v的形式(属性名:属性值的格式),属性之间用逗号间隔
  • 属性名必须是字符串
  • 比如{“id”:100,“name”:“tom”}
  • 数值支持的数据类型:数值,字符串,布尔,null,json对象,json数组
学生信息: { "id":100, "name":"tom", "cls":{ "id":1, "name":"计算机一班" } }

json array数据格式
  • 外层中括号
  • 数组元素的数据类型:数值,字符串,布尔,null,json对象,json数组
所有班级信息的数组: ["计算机一班","计算机二班","软件一班", "软件二班"]

在线json校验 Spring|Spring Boot前后端分离之后端开发
文章图片

Spring|Spring Boot前后端分离之后端开发
文章图片

postman 我们知道浏览器它只能发送GET请求,这样的话,其他的请求方式,我们是没法测试的。
接下来就介绍前后端分离开发,经常用到的工具postman
安装 官网地址:https://www.postman.com/downloads/
Spring|Spring Boot前后端分离之后端开发
文章图片

我们可以选择把exe文件放在指定文件家,然后双击
Spring|Spring Boot前后端分离之后端开发
文章图片

Spring|Spring Boot前后端分离之后端开发
文章图片

然后可以去登录,或者跳过登录
Spring|Spring Boot前后端分离之后端开发
文章图片

使用 Spring|Spring Boot前后端分离之后端开发
文章图片

Spring|Spring Boot前后端分离之后端开发
文章图片

Spring|Spring Boot前后端分离之后端开发
文章图片

点击send(代码实现在后面介绍)
Spring|Spring Boot前后端分离之后端开发
文章图片

Spring MVC的restful实现 查询所有班级信息 restful风格要求返回的字符串是json格式
@ResponseBody可以把Java对象转化为json对象,并返回给客户端
我们写一个小demo测试一下(数据是从数据库中查询出来的)
实体类(班级表对应的实体类)
@Data @NoArgsConstructor @AllArgsConstructor public class Cls { private Integer id; private String name; }

Controller(可以直接用@RestController)
Spring|Spring Boot前后端分离之后端开发
文章图片

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

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

Service实现类
@Service public class ClsServiceImpl implements ClsService { @Autowired private ClsMapper clsMapper; @Override public List queryAllCls() throws Exception { return clsMapper.queryAllCls(); } }

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

Spring|Spring Boot前后端分离之后端开发
文章图片

下面这张图片显示的数据和上面图片的不一样,是因为后来我把格式进行修改了,也就是对代码进行了修改,后面会进行说明
Spring|Spring Boot前后端分离之后端开发
文章图片

单元测试
@SpringBootTest class ClsMapperTest { @Autowired private ClsMapper clsMapper; @Test public void testQueryAllCls() throws Exception { List 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
@RestController public class ClsController { @Autowired private ClsService clsService; /** * 查询所有班级信息 */ @GetMapping("/school/cls")public List queryAllCls() { try { List 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 queryAllCls() throws Exception; /** * 查询指定编号的班级信息 * @param id * @return * @throws Exception */ Cls queryClsById(Integer id) throws Exception; }

Service实现类
@Service public class ClsServiceImpl implements ClsService { @Autowired private ClsMapper clsMapper; @Override public List queryAllCls() throws Exception { return clsMapper.queryAllCls(); }@Override public Cls queryClsById(Integer id) throws Exception { return clsMapper.queryClsById(id); } }

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

Spring|Spring Boot前后端分离之后端开发
文章图片

Spring|Spring Boot前后端分离之后端开发
文章图片

关于格式的说明 :::info
接口返回类型:
json格式
------code:状态码
------message:状态信息
------data:真实数据
:::
我们如果想要达到这样的效果的话,有两种方法,第一种就是我们写一个实体类,第二种方法就是通过map来存数据
通过定义实体类
Spring|Spring Boot前后端分离之后端开发
文章图片

通过map
Spring|Spring Boot前后端分离之后端开发
文章图片

Spring|Spring Boot前后端分离之后端开发
文章图片

Spring|Spring Boot前后端分离之后端开发
文章图片

Spring|Spring Boot前后端分离之后端开发
文章图片

根据id删除班级信息
/** * 根据id来删除班级信息 * @param id * @return */ @RequestMapping(value = "https://www.it610.com/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 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实现类
@Service public class ClsServiceImpl implements ClsService { @Autowired private ClsMapper clsMapper; @Override public List 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
@Mapper public interface ClsMapper { /** * 查询所有班级信息 */ @Select("select * from cls") List queryAllCls() throws Exception; /** * 查询指定编号的班级信息 * @param id * @return */ @Select("select * fromcls where id=#{id}") Cls queryClsById(@Param("id") Integer id); /** * 根据id删除数据 * @param id */ @Delete("delete fromcls 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); }

Spring|Spring Boot前后端分离之后端开发
文章图片

通过数据库查询的前后两次对比可以很清楚的发现,插入数据成功了
Spring|Spring Boot前后端分离之后端开发
文章图片

根据班级编号修改数据 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 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实现类
@Service public class ClsServiceImpl implements ClsService { @Autowired private ClsMapper clsMapper; @Override public List 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
@Mapper public interface ClsMapper { /** * 查询所有班级信息 */ @Select("select * from cls") List queryAllCls() throws Exception; /** * 查询指定编号的班级信息 * @param id * @return */ @Select("select * fromcls where id=#{id}") Cls queryClsById(@Param("id") Integer id); /** * 根据id删除数据 * @param id */ @Delete("delete fromcls 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); }

Spring|Spring Boot前后端分离之后端开发
文章图片

通过查询数据库中的数据,也可以发现数据改变了
Spring|Spring Boot前后端分离之后端开发
文章图片

结束语 【Spring|Spring Boot前后端分离之后端开发】在下一篇文章中会讲到跨域处理

    推荐阅读