目录树
零时尚商城–业务流程分析设计
1.前后端分离与单体架构的区别
2.接口介绍
3.Swagger
4.RESTful四大规范
1.前后端分离与单体架构的区别
单体架构
:页面和控制器(前后端)之间可以进行跳转,同步请求控制器,流程控制由后端的控制器完成。
前后端分离架构
:前端和后端分离开发和部署。前端只能通过异步(Ajax)请求向后端发送请求,后端只负责接受请求及参数,处理请求,返回处理结果,但是后端并不负责流程控制,流程控制由前端完成。
由后端进行校验,成功,就跳转到主界面。
后端只负责返回结果,其他的前端自己去弄。
2.接口介绍
2.1 接口
狭义的理解:控制器中可以接受用户请求的某个方法。
正规说明:应用程序编程接口,简称API,即
软件系统
不同组成部分衔接的约定。
2.2 接口规范
作为一个后端开发者,不仅要完成接口的开发,还要编写接口的说明文档----即
接口规范
2.2.1 接口规范实例
1.后端接口
2.接口文档
3.Swagger
前后端分离开发,后端需要编写接口说明文档,会耗费较多时间。
Swagger是一个用于生成服务器接口的规范性文档、并且能够对接口进行测试的工具。
3.1 作用
- 生成接口说明文档
- 对接口进行测试
3.2 整合
- 在api子工程添加依赖(Swagger2/Swagger UI)
<!--Swagger接口信息搜集-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--Swagger说明文档生成-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
- 在
api子工程
创建swagger的配置(Java配置方式)
@Configuration
@EnableSwagger2
public class SwaggerConfig {
/*swagger会帮助我们生成的接口文档
* 1:配置生成的文档信息
* 2:配置生成规则*/
@Bean
public Docket getDocket(){
//创建封面信息对象
ApiInfoBuilder apiInfoBuilder = new ApiInfoBuilder();
apiInfoBuilder.title("《零时尚商城》后端接口说明")
.description("此文档详细说明该项目后端接口规范")
.version("V-2.0.1")
.contact(new Contact("凡哥","湖南省岳阳市汨罗市研究院","123FanGe@qq.com"));
ApiInfo apiInfo1 = apiInfoBuilder.build();
//指定生成策略,使用链式调用
Docket docket = new Docket(DocumentationType.SWAGGER_2) //指定文档风格
.apiInfo(apiInfo1) //指定生成的文档中的封面信息:文档标题、版本、作者、联系方式
.select()
.apis(RequestHandlerSelectors.basePackage("com.yty.controller")) //需要生成文档的处理器
.paths(PathSelectors.any()) //any代表所有的请求产生说明
// .paths(PathSelectors.regex("/users")) //代表为所有users开头的请求去产生说明
.build();
return docket;
}
}
- 测试
直接在端口号后面+swagger-ui.html即可进入到我们的swagger自生成的页面上去
进入UserController里测试
3.3 ❤Swagger注解说明❤
Swagger提供了一套注解,可以对每个接口进行详细的中文
说明
1.
@Api
:类注解,在控制器类添加此注解,可以对控制器进行功能说明
代码:
页面显示:
2.
@ApiOperation
:方法注解,说明接口方法的作用
@ApiImplicitParams
和@ApiImplicitParam
:方法注解,说明接口方法的参数
代码:
//1.登录
@ApiOperation("用户登录接口")
@ApiImplicitParams({
@ApiImplicitParam(dataType = "string",name = "username",value = "用户登录账号",required = true),
@ApiImplicitParam(dataType = "string",name = "password",value = "用户登录密码",required = false,defaultValue = "123123")
})
@RequestMapping(value = "/login",method = RequestMethod.GET)
public ResultVO login(@RequestParam("username") String name,
@RequestParam(value = "password",defaultValue = "123123") String pwd){
return userService.checkLogin(name, pwd);
}
两者对比:
@ApiModel
和@ApiModelPropety
:当接口参数和返回值为对象类型时,在实体类中添加注解说明。
例子1:返回的是自定义的VO对象
ResultVO
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "ResultVO",description = "封装接口中返回给前端的数据")
public class ResultVO {
//响应给前端的状态码
@ApiModelProperty(value = "响应状态码",dataType = "int")
private int code;
//响应给前端的提示信息
@ApiModelProperty(value = "响应提示信息",dataType = "string")
private String msg;
//响应给前端的数据
@ApiModelProperty(value = "响应数据")
private Object data;
}
测试页面:
例子2:只有一个传入参数,但是这个参数是一个User实体类对象,这时候注解就需要加到对象上面
去,而不是接口方法上
。
代码(伪):
//2.注册
@ApiOperation("用户注册接口")
@RequestMapping(value = "/register",method = RequestMethod.POST)
public ResultVO register(User user){
System.out.println("register");
return new ResultVO(10000,"成功!",null);
}
User实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "User对象",description = "用户/买家信息")
public class User {
@ApiModelProperty(dataType = "int",required = false)
private int userId;
@ApiModelProperty(dataType = "string",required = true,value = "用户注册账号")
private String userName;
@ApiModelProperty(dataType = "string",required = true,value = "用户注册密码")
private String userPwd;
@ApiModelProperty(dataType = "int",required = true,value = "用户注册年龄")
private int userAge;
}
测试页面:
4.
@ApiIgnore
:接口方法注解,添加了此注解的方法将不会生成到接口文档中。
这个easy!
3.4 swagger-ui插件
功能还是一样,只是改了前端的接口文档页面,就是换了一个皮肤。
- api的pom中导入插件的依赖
<!--swagger-ui美化插件-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>
- 直接启动项目即可
访问路径:http://ip:port/doc.html,就是之前的swagger-ui.html换成doc.html
个人认为更好用一点!
4.❤RESTful四大规范❤
前后端分离开发的项目中,前后端之间是通过接口进行请求和响应,后端向前端提供请求时就得对外暴露一个URL,URL得遵循设计规范–RESTful
RESTful是一种Web api的标准,也就是一种url的设计风格。
4.1
每个URL请求路径代表服务器上的唯一资源
传统的URL设计:
http://localhost:8080/goods/delete?goodId=1 删除商品1
http://localhost:8080/goods/delete?goodId=2 删除商品2
RESTful设计:
http://localhost:8080/goods/delete/1 删除商品1
http://localhost:8080/goods/delete/2 删除商品2
@RequestMapping("/delete/{gid}")
public ResultVO deleteGoods(@PathVariable("gid") int goodsId){
System.err.println("------------"+goodsId);
return new ResultVO(10000,"delete success",null);
}
测试:
控制台:
4.2
使用不同的请求方式表示不同的操作
- post 特指 添加
- get 查询
- put 修改
- delete 删除
- option (预检)
比如:
通过id查询某个商品url:http://localhost:8080/goods/get/1 查询商品1
通过id删除某个商品url:http://localhost:8080/goods/delete/1 删除商品1
会发现两个路径都是代表商品1,但是为两个不同的url,设计就不合理,虽然没错。
这时就换个写法,直接淦掉前面的goods。
@RequestMapping("/{gid}") 删除商品1
@RequestMapping("/{gid}") 查询商品1
//这时候这两个不同操作的请求路径一样,就不知道去执行哪一个。所以,请求方法的不同就能正确做出执行判断。
所以一定
要在控制器里指定请求方式
。即用不同的请求方式代表不同的请求。
@RequestMapping(value = "/{gid}",method = RequestMethod.DELETE) 删除商品1
@RequestMapping(value = "/{gid}",method = RequestMethod.GET) 查询商品1
完成实例如下:
根据ID删除一个商品1:
//http://localhost:8080/goods/1 [delete]
@RequestMapping(value = "/{gid}",method = RequestMethod.DELETE)
public ResultVO deleteGoods(@PathVariable("gid") int goodsId){
System.err.println("------------"+goodsId);
return new ResultVO(10000,"delete success",null);
}
根据ID查询一个商品1:
//http://localhost:8080/goods/get/1 [get]
@RequestMapping(value = "/{gid}",method = RequestMethod.GET)
public ResultVO getGoods(@PathVariable("gid") int goodsId){
return null;
}
SpringMVC对RESTful风格提供了很好的支持,在我们定义一个接口的url时,可以通过
@RequestMapping(value="/{gid}",method=RequestMethod.Post)
形式指定请求方式,
也可以使用特定请求方式的注解设定url
@PostMapping("/add")
@DeleteMapping("{gid}")
@GetMapping("{gid}")
@GetMapping("/list")
@PutMapping("{gid}")
每次都要不同的请求方法都要去定义method,比较麻烦,所以进一步优化就是:
@RequestMapping(value = "/add",method = RequestMethod.POST)
@RequestMapping(value = "/{gid}",method = RequestMethod.DELETE)
@RequestMapping(value = "/update",method = RequestMethod.PUT)
@RequestMapping(value = "list",method = RequestMethod.GET) //查询所有
@RequestMapping(value = "/{gid}",method = RequestMethod.GET) //通过id查询
==》
@PostMapping("/add")
@DeleteMapping("/{gid}")
@PutMapping("/{gid}}")
@GetMapping("/list")
@GetMapping("{gid}")
其中的{gid}是自己随便定义的,意思是通过id进行某个操作,gid是我的示例,即商品id。
4.3
接口响应的资源的表现形式采用JSON
----- 在控制器类
或者每个接口
上添加@ResponseBody
注解,作用:将返回的对象格式为json
----- 直接在控制器类
使用@RestController
注解声明控制器(@ResponseBody+@Controller)
4.4
前端(Android/ios/PC)
通过无状态
HTTP协议与后端接口进行交互
无状态:前端向后端发送请求,后端响应后,两者的关系就断了。下一次再请求我的时候,我不知道上次你有没有请求过我。两次请求没有关联性,每次请求都是独立的,无状态的。