瑞吉外卖项目学习笔记-P27-项目优化-前后端分离

1.为什么进行前后端分离

在这里插入图片描述

  • 开发人员同时负责前端和后端代码开发,分工不明确
  • 开发效率低
  • 前后端代码混合在一个工程中,不便于管理
  • 对开发人员要求高,人员招聘困难

2.前后端分离开发

2.1介绍

前后端分离开发,就是在项目开发过程中,对于前端代码的开发由专门的前端开发人员负责,后端代码则由后端开发人员负责,这样可以做到分工明确、各司其职,提高开发效率,前后端代码并行开发,可以加快项目开发进度。目前,前后端分离开发方式已经被越来越多的公司所采用,成为当前项目开发的主流开发方式。
前后端分离开发后,从工程结构上也会发生变化,即前后端代码不再混合在同一个maven工程中,而是分为前端工程后端工程
在这里插入图片描述

2.2开发流程

前后端分离开发后,面临一一个问题,就是前端开发人员和后端开发人员如何进行配合来共同开发一一个项目?
可以按照如下流程进行:
在这里插入图片描述

接口(API接口)一个http的请求,主要就是去定义:

  • 请求路径
  • 请求方式
  • 请求参数
  • 响应数据

等内容。

接口例子
在这里插入图片描述

2.3前端技术栈

2.3.1开发工具

  • Visual Studio Code
  • hbuilder .

2.3.2技术框架

  • nodejs
  • VUE
  • ElementUI
  • mock
  • webpack 前端打包工具

3.Yapi-用来定义接口

3.1介绍

YApi是高效、易用、功能强大的api管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助.开发者轻松创建、发布、维护API, YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理。
YApi让接口开发更简单高效,让接口的管理更具可读性、可维护性,让团队协作更合理。

要使用YApi,需要自己进行部署。

3.2使用

3.2.1添加项目

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

3.2.2添加分类

在这里插入图片描述

3.2.3添加接口

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

3.2.4编辑接口

在这里插入图片描述请求参数设置
在这里插入图片描述
返回参数设置
在这里插入图片描述在这里插入图片描述

3.2.5查看接口

在这里插入图片描述
接口设置好,在编辑里面设置状态为完成
在这里插入图片描述

3.2.6导出定义的接口

在这里插入图片描述

3.2.7导入接口

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

4.Swagger

4.1介绍

使用Swagger你只需要按照它的规范去定义接口及接口相关的信息,再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,以及在线接口调试页面等等。

knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案。

<dependency>
	<groupld>com.github.xiaoymin</ groupld>
	<artifactld>knife4j-spring-boot-starter</ artifactld>
	<version>3.0.2</version>
</dependency>

4.2使用方式

4.2.1导入knife4j的maven坐标

<dependency>
	<groupld>com.github.xiaoymin</ groupld>
	<artifactld>knife4j-spring-boot-starter</ artifactld>
	<version>3.0.2</version>
</dependency>

4.2.2导入knife4j相关配置类-WebMvcConfig

package com.jq.config;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.jq.commom.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.List;

/**
 * 配置类,映射静态资源
 */
@Slf4j
@Configuration
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
    /**
     * 设置静态资源映射
     * @param registry
     */
    @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/");
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
    }

    /**
     * 扩展 Spring Mvc 的消息转换器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器...");
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转换为JSON
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //将上面的消息转换器对象追加到spring MVC框架的转换器集合中
        converters.add(0,messageConverter);
    }
    @Bean
    public Docket createRestApi() {
        // 文档类型
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.jq.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("瑞吉外卖")
                .version("1.0")
                .description("瑞吉外卖接口文档")
                .build();
    }
}

4.2.3设置静态资源,否则接口文档页面无法访问-WebMvcConfig

 /**
     * 设置静态资源映射
     * @param registry
     */
    @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/");
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
    }

4.2.4在LoginCheckFilter中设置不需要处理的请求路径

package com.jq.filter;

import com.alibaba.fastjson.JSON;
import com.jq.commom.BaseContext;
import com.jq.commom.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 自定义过滤器
 * 检查用户是否已经完成登录
 */
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
    //路径匹配器,支持通配符
    public static final AntPathMatcher PATH_MATCHER=new AntPathMatcher();
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request=(HttpServletRequest) servletRequest;
        HttpServletResponse response=(HttpServletResponse) servletResponse;
        /**
         * 1、获取本次请求的URI
         * 2、判断本次请求是否需要处理
         * 3、如果不需要处理,则直接放行
         * 4、判断登录状态,如果已登录,则直接放行
         * 5、如果未登录则返回未登录结果
         */
        //1、获取本次请求的URI
        String requestURI =request.getRequestURI();// /backend/index.html
        log.info("拦截到请求:{}",requestURI);
        //定义不需要处理的请求路径
        String []urls=new String[]{
                "/employee/login",
                "/employee/logout",
                "/backend/**",
                "/front/**",
                "/common/**",
                "/user/sendMsg",
                "/user/login",
                "/doc.html",
                "/webjars/**",
                "/swagger-resources",
                "/v2/api-docs"
        };

        //2、判断本次请求是否需要处理
        boolean check = check(urls, requestURI);
        //3、如果不需要处理,则直接放行
        if (check){
            log.info("本次请求{}不需要处理",requestURI);
            filterChain.doFilter(request,response);
            return;
        }
        //4-1、后台管理系统:判断登录状态,如果已登录,则直接放行
        if(request.getSession().getAttribute("employee")!=null){
            log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));

            //获取用户id
            Long empId=(Long) request.getSession().getAttribute("employee");
            //调用BaseContext来设置当前用户登录的id
            BaseContext.setCurrentId(empId);

            filterChain.doFilter(request,response);
            return;
        }
        //4-2、前端移动端用户系统:判断登录状态,如果已登录,则直接放行
        if(request.getSession().getAttribute("user")!=null){
            log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("user"));

            //获取用户id
            Long userId=(Long) request.getSession().getAttribute("user");
            //调用BaseContext来设置当前用户登录的id
            BaseContext.setCurrentId(userId);

            filterChain.doFilter(request,response);
            return;
        }
        log.info("用户未登录");
        //5、如果未登录则返回未登录结果,通过输出流的方式向客户端页面响应数据
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));

        return;


    }

    /**
     * 路径匹配,检查本次请求是否需要放行
     * @param urls
     * @param requestURI
     * @return
     */
    public boolean check(String [] urls,String requestURI){
        for (String url : urls) {
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match){
                return true;
            }
        }
        return false;
    }
}

在这里插入图片描述

4.3常用注解

在这里插入图片描述加入注解后的swagger文档
在这里插入图片描述

5.项目部署

5.1部署架构

在这里插入图片描述

5.2部署环境

服务器:

5.2.1服务器A- 192.168.138.100 [192.168.112.100(Linux)自己虚拟机端口]

  • Nginx:部署前端项目、配置反向代理
  • Mysql:主从复制结构中的主库

5.2.1服务器B-192.168.138.101 [127.0.0.1(Windows) 自己ipv4地址]

  • jdk:运行Java项目
  • git:版本控制工具
  • maven:项目构建工具
  • jar: Spring Boot项目打成jar包基于内置Tomcat运行
  • Mysql:主从复制结构中的从库

5.2.1服务器C-172.17.2.94 [(Linux)]

  • Redis:缓存中间件

5.3部署前端项目

5.3.1第一步:在服务器A中安装Nginx,将dist目录上传到Nginx的html目录下

在这里插入图片描述
进入nginx目录下的html目录

cd /usr/local/nginx/html/

上传dist目录
在这里插入图片描述

5.3.2修改Nginx配置文件nginx.conf

记得关闭防火墙,要不然外部浏览器访问不到

#反向代理配置
location ^~ /api/ { 
	rewrite ^/api/(.*)$ /$1 break;  //url重写
	proxy_pass http://192.168.138.101:8080;
	}

自己的配置文件如下
在这里插入图片描述在这里插入图片描述

  • 访问的 192.168.112.100
  • 反向代理的结果 :192.168.112.100/api/employee/login
  • 反向代理URL重写 :/api/employee/login —》/employee/login
  • 后端正常访问是 192.168.137.1:8080/employee/login

5.4部署后端项目

5.4.1第一步:在服务器B中安装jdk、git、 maven、MySQL,使用git clone命令将git远程仓库的代码克隆下来

在这里插入图片描述

5.4.2运行 springboot项目

  • Windows ,直接运行 springboot项目即可

  • Linux环境下,运行 springboot项目
    第二步:将reggiesStart.sh文件.上传到服务器B,通过chmod命令设置执行权限.

    #!/bin/sh
    echo =================================
    echo  自动化部署脚本启动
    echo =================================
    
    echo 停止原来运行中的工程
    APP_NAME=reggie_take_out
    
    tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
    if [ ${tpid} ]; then
        echo 'Stop Process...'
        kill -15 $tpid
    fi
    sleep 2
    tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
    if [ ${tpid} ]; then
        echo 'Kill Process!'
        kill -9 $tpid
    else
        echo 'Stop Success!'
    fi
    
    echo 准备从Git仓库拉取最新代码
    cd /usr/local/javaapp/reggie_take_out
    
    echo 开始从Git仓库拉取最新代码
    git pull
    echo 代码拉取完成
    
    echo 开始打包
    output=`mvn clean package -Dmaven.test.skip=true`
    
    cd target
    
    echo 启动项目
    nohup java -jar reggie_take_out-1.0-SNAPSHOT.jar &> reggie_take_out.log &
    echo 项目启动完成
    
    
    

    修改权限

    chmod 777 reggiesStart.sh
    

    在这里插入图片描述
    Windows下运行springboot,修改图片的路径
    在这里插入图片描述
    如果是在Linux运行springboot,修改图片的路径

    # 文件上传后保存路径
    rj:
      path: /usr/local/img/
    
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值