前后端分离
概念: 前后端分离开发,就是在项目开发过程中,对于前端代码的开发由专门的前端开发人员负责,后端代码则由后端开发人员负责
- 这样可以做到分工明确、各司其职,提高开发效率,前后端代码并行开发,可以加快项目开发进度。
- 目前,前后端分离开发方式已经被越来越多的公司所采用,成为当前项目开发的主流开发方式。
工程划分: 前后端分离开发后,从工程结构上也会发生变化,即前启端代码不再混合在同一个maven工程中,而是分为前端工程和后端工程。
开发流程: 前后端分离开发后,面临一个问题,就是前端开发人员和后端开发人员如何进行配合来共同开发一个项目
接口: API接口就是一个http的请求地址, 主要就是定义: 请求路径、请求方式、请求参数、响应数据等内容
Yapi
YApi 是高效、易用、功能强大的 api 管理平台,旨在开发、产品、测试人员提供更优雅的接口管理服务。
- 可以帮助开发人员轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理
- YApi让接口开发更简单高效,让接口的管理更具可读性可维护性,让团队协作更合理。
- 源码地址: https://github.com/YMFE/yapi
- 要使用YApi,需要自己进行部署。
使用YApi,可以执行下面操作
- 添加项目
- 添加分类
- 添加接口
- 编辑接口
- 查看接口
Swagger
使用Swagger你只需要按照它的规范去定义接口及接口相关的信息,再通过Swagger衍生出来的一系列项目和工具就可以做到生成各种格式的接口文档,以及在线接口调试页面等等
官网: API Documentation & Design Tools for Teams | Swagger
knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案
1、导入knife4j的maven坐标
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
2、导入knife4j相关配置类
... ...
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
... ...
@Bean
public Docket createRestApi() {
// 文档类型
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.itheima.reggie.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("瑞吉外卖")
.version("1.0")
.description("瑞吉外卖接口文档")
.build();
}
}
- Docket对象是swagger提供的对象,用于描述接口的相关信息,其中最重要的是指定controller位置
- ApiInfo对象是描述接口文档的相关信息
3、设置静态资源,否则接口文档页面无法访问
... ...
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* 设置静态资源映射
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始进行静态资源映射");
... ...
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
... ...
}
4、在LoginCheckFilter中设置不需要处理的请求路径
/**
* 过滤器: 检测用户是否登录
* 拦截的路径: urlPatterns = "/*"
*/
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
... ...
//定义不需要处理的请求路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**",
"/common/**",
"/user/sendMsg", //移动端发送短信
"/user/login", //移动端登录
"/doc.html",
"/webjars/**",
"/swagger-resources",
"/v2/api-docs",
};
... ...
}
... ...
}
5、访问swagger生成的接口文档页面: http://localhost:8080/doc.html
常用注解: 通过这些注解, 让生成的swagger文档可读性更强
/**
* 套餐
*/
@Data
@ApiModel("套餐")
public class Setmeal implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键")
private Long id;
//分类id
@ApiModelProperty("分类id")
private Long categoryId;
//套餐名称
@ApiModelProperty("套餐名称")
private String name;
//套餐价格
@ApiModelProperty("套餐价格")
private BigDecimal price;
//状态 0:停用 1:启用
@ApiModelProperty("状态 0:停用 1:启用")
private Integer status;
//编码
@ApiModelProperty("编码")
private String code;
//描述信息
@ApiModelProperty("描述信息")
private String description;
//图片
@ApiModelProperty("图片")
private String image;
}
/**
* 通用返回结果封装类
* @param <T>
*/
@Data
@ApiModel("返回结果")
public class R<T> implements Serializable {
@ApiModelProperty("编码")
private Integer code; //编码:1成功,0和其它数字为失败
@ApiModelProperty("错误信息")
private String msg; //错误信息
@ApiModelProperty("数据")
private T data; //数据
@ApiModelProperty("动态数据")
private Map map = new HashMap(); //动态数据
}
/**
* 套餐管理
*/
@Slf4j
@RestController
@RequestMapping("/setmeal")
@Api(tags="套餐相关接口")
public class SetmealController {
/**
* 新增套餐
* @param setmealDto
* @return
*/
@PostMapping
@CacheEvict(value = "setmealCache", allEntries = true)
@ApiOperation(value = "新增套餐")
public R<String> save(@RequestBody SetmealDto setmealDto) {
... ...
}
/**
* 套餐分页查询
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
@ApiOperation(value = "套餐分页查询")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "页码", required = true),
@ApiImplicitParam(name = "pageSize", value = "每页记录数", required = true),
@ApiImplicitParam(name = "name", value = "套餐名称", required = false)
})
public R<Page> page(int page, int pageSize, String name) {
... ...
}
}
项目部署
部署环境说明
部署架构
部署环境说明
- 192.168.138.100(服务器A)
- Nginx:部署前端项目、配置反向代理
- Mysql: 主从复制结构中的主库
- 192.168.138.101(服务器B)
- jdk: 运行Java项目
- git: 版本控制工具
- maven: 项目构建工具
- jar: Spring Boot项目打成jar包基于内置Tomcat运行
- Mysql: 主从复制结构中的从库
- 172.17.2.94(服务器C)
- Redis: 缓存中间件
部署前端项目
第一步: 在服务器A中安装Nginx,将课程资料中的dist目录上传到Nginx的html目录下
第二步:修改Nginx配置文件nginx.conf
- rewrite是路径重写指令, 后面跟的是正则表达式, 作用是去掉请求路径中的api字符串
部署后端项目
第一步: 在服务器B中安装jdk、git、maven、MySOL,使用git clone命令将git远程仓库的代码克隆下来
- 安装git的命令: yum install git
第二步: 将资料中提供的reggieStart.sh文件上传到服务器B,通过chmod命令设置执行权限
第三步: 执行自动部署脚本, 完成后端项目的部署, 并进行访问
第四步: 解决图片无法展示的问题
- 查看项目日志
- cd reggie_take_out/
- ll
- cd target/
- ll
- 动态查看文件: tail -f reggir_take_out.log
- 复现问题, 分析日志
- 问题原因: 图片路径存在问题
- 问题修改完成后上传代码, 重新部署后端项目
- 图片路径没问题之后, 可以把本地的图片上传到线上环境