• 阶段六模块五 SSM项目前端开发


    导读

    写了这么多篇笔记,感觉画思维导图,更明目了然一点,所以打算开始画思维导图,让自己印象更深刻一点。

    https://www.processon.com/view/link/604222c4079129054f9de56e

    工程目录结构

    |--- edu-boss 项目名称
      |--- node_modules 存放依赖包的目录
      |--- public 静态资源管理目录
      |--- src 组件源码目录(我们写的代码)
        |--- assets 存放静态图片资源(CSS也可以放在这里)
        |--- components 存放基础组件,可复用
        |--- router 存放了项目路由文件
        |--- services 存放请求后台的 JS文件,
        |--- store 保存组件之间的共享数据
        |--- utils 管理公用的JS文件
        |--- views 放置的为公共组件(各个主要页面)
        |--- App.vue app.vue可以当做是网站首页,是一个vue项目的主组件,页面入口文件
        |--- main.js 打包运行的入口文件,引入了vue模块和app.vue组件以及路由route
      |--- babel.config.js babel配置文件, 对源代码进行转码(把es6=>es5)
      |--- package.json 项目及工具的依赖配置文件
      |--- paxkage-lock.json 依赖配置文件
      |--- README.md 项目说明
      |--- vue.config.js 自定义配置文件

    vue组件化开发

    每一个*.vue 文件都可以看做是一个组件.
    组件的组成部分

    template : 组件的HTML部分
    script: 组件的JS脚本 (使用ES6语法编写)
    style: 组件的CSS样式

    el-upload(上传图片)

    https://element.eleme.cn/#/zh-CN/component/upload

    属性说明

    组件的引入

    //1.导入组件 
    import UploadImage from "@/components/UploadImage";
    export default {
    //2.注册组件
    components: { UploadImage } };

    组件的传参

    接收方:

    /*
    组件传参
        uploadUrl:图片上传路径,
        getUrl: 函数
    */
    props: ["uploadUrl", "getUrl"],

    传递方:

    <template>
        <div>
            <!-- 使用组件,注意使用短横线连接 ,向父组件传递了两个参数
            uploadUrl: 图片上传地址
            :get-url:传递了一个函数
            -->
            <upload-image
            uploadUrl="https://jsonplaceholder.typicode.com/posts/"
            :get-url="show">
            </upload-image>
        </div>
    </template>    

    ElementUI 分页组件

    • 广告列表的展示,使用到了分页组件, 接下来通过一个案例演示一下分页插件的使用.
    https://element.eleme.cn/#/zh-CN/component/pagination
     
    <template>
        <div>
            <div class="block">
                <span class="demonstration">完整功能</span>
                <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="currentPage4"
                :page-sizes="[100, 200, 300, 400]"
                :page-size="100"
                layout="total, sizes, prev, pager, next, jumper"
                :total="400"
                ></el-pagination>
            </div>
        </div>
    </template>
    <script>
        export default {
            methods: {
            handleSizeChange(val) {
                console.log(`每页 ${val} 条`);
            },
            handleCurrentChange(val) {
                console.log(`当前页: ${val}`);
            }
        },
        data() {
            return {
                currentPage4: 4
            };
        }
    };
    </script>        

    属性介绍

    分析:

    • page-size 与 current-page 是需要前端传给后端的数据
    • total 和 列表数据 是需要后端返回给前端的.

    事件介绍

     案例演示

    <template>
        <div class="app-container"> 
            <div class="table-container"> 
                <el-table ref="homeAdvertiseTable" :data="list" style=" 100%;" border> 
                    <el-table-column label="id" width="220" align="center"> 
                        <template slot-scope="scope">{{scope.row.id}}</template> 
                    </el-table-column> 
                    <el-table-column label="广告名称" align="center" width="320"> 
                        <template slot-scope="scope">{{scope.row.name}}</template> 
                    </el-table-column> 
                    <el-table-column label="广告图片" width="420" align="center"> 
                        <template slot-scope="scope"> 
                            <img style="height: 80px" :src="scope.row.img" /> 
                        </template> 
                    </el-table-column> 
                </el-table> 
            </div> 
            <div class="pagination-container"> 
                <el-pagination background @size-change="handlePageSizeChange" 
                        @current-change="handleCurrentPageChange" 
                        layout="total, sizes,prev, pager, next,jumper" 
                        :current-page="page" 
                        :page-sizes="[5,10, 20]" 
                        :page-size="size" :total="total" >
                </el-pagination> 
            </div> 
        </div> 
    </template>

    js部分代码

    <script> export default { 
        data() { 
            return { 
                total: 0, //总条数 
                size: 5, //每页显示条数
                page: 1, //当前页 
                list: [] //广告数据 
            }; 
        },
        created() { 
            this.loadList(); 
        },
        methods: { 
            //加载广告数据 
            loadList() { 
                return this.axios 
                    .get("http://localhost:8080/ssm-web/PromotionAd/findAllPromotionAd", { 
                        params: { 
                            currentPage: this.page, 
                            pageSize: this.size 
                        }
                    }).then(res => { 
                        this.list = res.data.content.list; 
                        this.total = res.data.content.total; 
                        this.listLoading = false; 
                    }).catch(error => { 
                        this.$message.error("数据获取失败! ! !"); 
                    }); 
            },
                
            //每页显示条数发生变化 
            handlePageSizeChange(size) { 
                this.size = size; 
                this.loadList(); 
            },
                
            //当前页发生变化 
            handleCurrentPageChange(page) { 
                this.page = page; 
                this.loadList(); 
            } 
        } 
    };
    </script>

    el-switch 开关组件

    active-value: switch:打开时的值
    inactive-value : switch 关闭时的值

    <!-- 上线与下线 --> 
    <el-table-column label="上线/下线" width="120" align="center"> 
        <template slot-scope="scope"> 
            <el-switch 
                @change="handleUpdateStatus(scope.row)" 
                :active-value="1" 
                :inactive-value="0" 
                v-model="scope.row.status">
            </el-switch> 
        </template> 
    </el-table-column>
    
    
    //方法4: 修改状态 
    handleUpdateStatus(row) { 
        this.$confirm("是否要修改上线/下线状态?", "提示", { 
            confirmButtonText: "确定", 
            cancelButtonText: "取消",
            type: "warning" 
        }).then(() => { 
            //请求后台 
            axios .get("/PromotionAd/updatePromotionAdStatus", { 
                params: { 
                    id: row.id, 
                    status: row.status 
                }
            }).then(res => { 
                this.loadPromotionAd(); 
            }).catch(err => { 
                this.$message("修改状态失败! ! !"); 
            }); 
        }); 
    },

    日期选择器组件(DatePicker)

    https://element.eleme.cn/#/zh-CN/component/date-picker#mo-ren-xian-shi-ri-qi
    <template>
        <div>
            <div class="block">
                <span class="demonstration">带快捷选项</span>
                <el-date-picker
                    v-model="dateTime"
                    type="daterange"
                    align="right"
                    unlink-panels
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期"
                    :picker-options="pickerOptions"
                ></el-date-picker>
                <el-button type="primary" @click="getDate">查询</el-button>
            </div>
        </div>
    </template>
    <script>
    export default {
        data() {
            return {
                pickerOptions: {
                    shortcuts: [
                        {
                            text: "最近一周",
                            onClick(picker) {
                            const end = new Date();
                            const start = new Date();
                            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
                            picker.$emit("pick", [start, end]);
                            }
                        },
                        {
                            text: "最近一个月",
                            onClick(picker) {
                            const end = new Date();
                            const start = new Date();
                            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
                            picker.$emit("pick", [start, end]);
                            }
                        },
                        {
                            text: "最近三个月",
                            onClick(picker) {
                            const end = new Date();
                            const start = new Date();
                            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
                            picker.$emit("pick", [start, end]);
                            }
                        }
                    ]
                },
                dateTime: ""
            };
        },
        methods: {
            getDate() {
                const params = {};
                params.startCreateTime = this.dateTime[0];
                params.startCreateTime.setHours(0);
                params.startCreateTime.setMinutes(0);
                params.startCreateTime.setSeconds(0);
                params.endCreateTime = this.dateTime[1];
                params.endCreateTime.setHours(23);
                params.endCreateTime.setMinutes(59);
                params.endCreateTime.setSeconds(59);
                console.log(params);
            }
        }
    };
    </script>

    作为查询条件功能实现

    //数据部分
    return {
        pickerOptions,//日期选择器选项设置
        total: 0, //总条数
        size: 10, //每页显示条数
        page: 1, //当前页
        filter,
        users: [],
        loading: false,
        allocAdminId: "",
        allocDialogVisible: false,
        allocRoleIds: [],
        allRoleList: []
    };
    
    // JS部分
    created() {
        //初始化用户数据
        this.loadUsers();
    }
    //方法1: 加载用户数据
    loadUsers() {
        this.loading = true;
        //设置参数
        const params = { currentPage: this.page, pageSize: this.size };
        //过滤条件
        if (this.filter.username) params.username = this.filter.username;
        //设置日期参数
        if (this.filter.resTime) {
            params.startCreateTime = this.filter.resTime[0];
            params.startCreateTime.setHours(0);
            params.startCreateTime.setMinutes(0);
            params.startCreateTime.setSeconds(0);
            params.endCreateTime = this.filter.resTime[1];
            params.endCreateTime.setHours(23);
            params.endCreateTime.setMinutes(59);
            params.endCreateTime.setSeconds(59);
        }
        //请求后台接口
        return axios
            .post("/user/findAllUserByPage", params)
            .then(res => {
            this.users = res.data.content.list; //用户数据
            this.total = res.data.content.total;
            this.loading = false;
        })
        .catch(err => {
            this.$message("获取数据失败! ! !");
        });
    },

    MessageBox 弹框

    https://element.eleme.cn/#/zh-CN/component/message-box#options
    handleDelete(row) {
        this.$confirm("是否要删除该角色?", "提示", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning"
        }).then(() => {
            axios("/role/deleteRole?id=" + row.id)
                .then(res => {
                this.loadRoles();
            })
            .catch(err => {
                this.$message.error("操作失败! ! !");
            });
        });
    },

     用户登录

    //提交登录表单
        submit(ref) {
          //校验
          this.$refs[ref].validate(valid => {
            if (!valid) return false;
    
            this.error = null;
            this.loading = true;
    
            //发送登录请求
            this.$store.dispatch("createToken", this.model)
              .then(res => {
                if (res.state !== 1) {
                  this.error = {
                    title: "Error occurred",
                    message: "Abnormal, please try again later!"
                  };
                }
                this.$router.replace({ path: this.$route.query.redirect || "/" });
                this.loading = false;
              })
              .catch(err => {
                this.loading = false;
              });
          });
        }
      }

    this.$store.dispatch("createToken", this.model)

    • 这段代码的意思是调用 store仓库的actions.js中的createToken方法
    •  发送登录请求,进行登录的代码

     

      /**
       * 创建新的客户端令牌
       */
      createToken: async ({ commit }, { username, password }) => {
        //请求后台登录接口
        const res = await TokenService.userLogin({
          phone: username.trim(),
          password: password.trim()
        });
    
        console.log(res);
    
        //判断结果不等于1,登录失败
        if (res.state !== 1) {
          return Promise.resolve(res);
        }
    
        //获取到content
        const result = res.content;
    
        //将token保存
        commit(CHANGE_SESSION, {
          accessToken: result.access_token
        });
          
        return res;
      },
    //登录请求 async ES6语法, 作用: 发送异步请求
    export const userLogin =  async (data) => {
     //await 表示等待接收返回的数据
     return await PostRequest(`${process.env.VUE_APP_API_FAKE}/user/login${Serialize(data)}`)
    }

    验证Token

     // 导航守卫 to要访问的url, from从哪个路径跳转过来, next() 放行
      router.beforeHooks.unshift((to, from, next) => {
        //不需要验证直接放行
        if (!to.meta.requireAuth) return next();
    
        //需要验证token,调用 store中的checkToken方法
        store.dispatch("checkToken").then(valid => {
          //判断是否存在token
          if (valid) {
            //发送请求到后台,在后台再次判断token是否存在
            store.dispatch("getUserPermissions").then(res => {
            
              if (!res) {
                //失效 清除token
                store.dispatch("deleteToken");
    
                //跳转到登录页面
                return next({ name: "ToLogin" });
              }
    
              //token正确, 导航到对应的页面
              const { memusMap } = res;
              if (memusMap.Courses && to.name === "Home") {
                return next();
              } else if (memusMap[to.name]) {
                return next();
              } else if (Object.keys(memusMap).length > 0) {
                return next({ name: memusMap[Object.keys(memusMap)[0]].name });
              } else {
                next({ name: "PermissionDenied" });
              }
            });
            return next();
          }
          // unauthorized
          console.log("Unauthorized");
    
          //用户没有登录 跳转到登录页面
          next({ name: "Login", query: { redirect: to.fullPath } });
        });
      });

    检查token是否可用

    checkToken: async ({ commit, getters }) => {
        //取出token
        const token = getters.session.accessToken;
    
        if (!token) {
          //不可用
          return Promise.resolve(false);
        }
    
        return Promise.resolve(true);
      },

    nginx

      Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev(伊戈尔·西索夫)所开发,供俄国大型的入口网站及搜索引擎Rambler(漫步者)(俄文:Рамблер)使用。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:新浪、网易、 腾讯等。

    优点:

    1. 占用内存少,并发能力强

    2. Nginx专为性能优化而开发, 在高连接并发的情况下,能够支持高达 50,000 个并发连接数的响应.

    3. Nginx支持热部署, 可以在不间断服务的情况下,对软件版本进行升级.

    应用场景

    1. http服务器: Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。

    2. 虚拟主机: 可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。

    3. 反向代理,负载均衡 : 当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。

    Nginx安装

    安装环境配置

    因为Nginx是C语言编写的,所以需要配置C语言编译环境 (一定要在联网状态下安装)

    yum install gcc-c++

    第三方的开发包, 在编译之前需要安装这些第三方包。

    • PCRE
      • nginx的http模块使用pcre来解析正则表达式,所以需要在linux上安装pcre库
    yum install -y pcre pcre-devel
    • zlib
      • nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库。
    yum install -y zlib zlib-devel
    • openssl
      • OpenSSL 是一个强大的安全套接字层密码库,nginx不仅支持http协议,还支持https,所以需要在linux安装openssl库。
    yum install -y openssl openssl-devel

    安装Nginx 步骤

    1. 将Nginx的源码包上传到 Linux

    2. 解压Nginx

    tar -xvf nginx-1.17.8.tar 

    3. 进入到解压之后的目录 nginx-1.17.8

     4. 执行命令 configure,生成 Mikefile 文件

    ./configure

     

     5. 创建临时文件目录

    mkdir /var/temp/nginx/client -p

    6. 执行make命令,进行编译

    make

    7. 安装

    make install

    启动并访问 Nginx

    1. 进入到nginx 安装目录

    cd /usr/local/nginx/

     2. 进入到 sbin目录,执行 nginx 命令

    ./nginx 启动
    ./nginx -s stop 关闭
    ps aux | grep nginx 查看进程

     3. 通过浏览器进行访问 ,默认端口 80 (注意:是否关闭防火墙。)

     配置虚拟主机

    虚拟主机指的是,在一台服务器中,我们使用Nginx,来配置多个网站.

    如何区分不同的网站:

    1. 端口不同

    2. 域名不同

    通过端口区分不同的虚拟主机

    Nginx配置文件

    1. Nginx配置文件的位置

    cd /usr/local/nginx/conf
    nginx.conf 就是Nginx的配置文件

    2. Nginx核心配置文件说明

    worker_processes  1; #work的进程数,默认为1
    #配置 影响nginx服务器与用户的网络连接
    events {
        worker_connections  1024; #单个work 最大并发连接数
    }
    
    # http块是配置最频繁的部分 可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能
    http {
        # 引入mime类型定义文件
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65; # 超时时间
        
        #server 配置虚拟主机的相关参数 可以有多个,一个server就是一个虚拟主机
        server {
            # 监听的端口
            listen       80; 
            #监听地址
            server_name  localhost;         
    
            # 默认请求配置
            location / {
                root   html; # 默认网站根目录
                index  index.html index.htm; # 欢迎页
            }
    
            # 错误提示页面
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    }
    使用Notpad,连接Linux

    使用notepad++来连接linux,好处是使用notepad++来编辑linux中文件的批量文字,会比直接在linux中操作方便快捷很多.

    1. Notepad 插件中安装NppFTP

        2. 复制一份 html目录

    cp -r html html81

     3. 重新加载配置文件

    sbin/nginx -s reload

    4. 访问

    http://192.168.52.100 访问第一个server

    http://192.168.52.100:81/ 访问第二个server

    通过域名区分不同的虚拟主机

    域名绑定
    • 一个域名对应一个ip地址,一个ip地址可以被多个域名绑定。

    • 通过 DNS服务器去解析域名

    配置域名映射
    1. 本地测试可以修改hosts文件。修改window的hosts文件:(C:WindowsSystem32driversetc)

    • 可以配置域名和ip的映射关系,如果hosts文件中配置了域名和ip的对应关系,不需要走dns服务器。

    配置一下nginx的映射
    192.168.52.100 www.ng.com

    配置nginx.conf
    #通过域名区分虚拟主机
        server {
            listen       80;
            server_name  www.t1.com;
    
            location / {
                root   html-t1;
                index  index.html index.htm;
            }
        }
        
        server {
            listen       80;
            server_name  www.t2.com;
    
            location / {
                root   html-t2;
                index  index.html index.htm;
            }
        }

    反向代理

    客户机在发送请求时,不会直接发送给目的主机,而是先发送给代理服务器,代理服务接受客户机请求之后,再向主机发出,并接收目的主机返回的数据再发送给客户机。

    比如我们国内访问谷歌,直接访问访问不到,我们可以通过一个正向代理服务器,先将请求发送到到代理服,代理服务器能够访问谷歌,这样由代理去谷歌取到返回数据,再返回给我们,这样我们就能访问谷歌了

    正向代理代理的是客户端, 服务端不知道实际发起请求的客户端.

     反向代理

    反向代理和正向代理的区别就是:正向代理代理客户端,反向代理代理服务器。

    反向代理是指用代理服务器接收客户端的请求,然后将请求转发给网站内部应用服务器,并将从服务器上得到的结果返回给客户端.

     Nginx实现反向代理

     配置步骤

    第一步:简单的使用2个tomcat实例模拟两台http服务器,分别将tomcat的端口改为8080和8081

     第二步:启动两个tomcat。

    ./bin/startup.sh
    访问两个tomcat
    http://192.168.52.100:8080/
    http://192.168.52.100:8081/

    第三步:反向代理服务器的配置

    #反向代理配置 
        #upstream中的server是真正处理请求的应用服务器地址
        upstream lagou1{
            #用server定义HTTP地址
            server 192.168.52.100:8080;
        }
        
        
        server {
            listen       80;
            server_name  www.lagou1.com;
            location / {
                # 利用 proxy_ pass可以将请求代理到upstream命名的HTTP服务
                proxy_pass http://lagou1;  #转发到的地址
                index  index.html index.htm;
            }
        }
        
        upstream lagou2{
            #用server定义HTTP地址
            server 192.168.52.100:8081;
        }
        
        
        server {
            listen       80;
            server_name  www.lagou2.com;
            location / {
                proxy_pass http://lagou2; 
                index  index.html index.htm;
            }
      }

    第四步:nginx重新加载配置文件

    nginx -s reload

    第五步:配置域名, 在hosts文件中添加域名和ip的映射关系

     通过浏览器输入域名, 访问Nginx代理服务器, Nginx根据域名将请求转发给对应的目标服务器,作为用户我们看到的是服务器的响应结果页面,在整个过程中目标服务器相对于客户端是不可见的,服务端向外暴露的就是Nginx的地址.

    负载均衡

    什么是负载均衡

    当一个请求发送过来的时候,Nginx作为反向代理服务器,会根据请求找到后面的目标服务器去处理请求,这就是反向代理. 那么, 如果目标服务器有多台的话,找哪一个服务器去处理当前请求呢 ? 这个合理分配请求到服务器的过程就叫做负载均衡.

     当系统面临大量用户访问,负载过高的时候,通常会使用增加服务器数量来进行横向扩展, 负载均衡主要是为了分担访问量,将请求合理分发给不同的服务器, 避免临时的网络堵塞

    负载均衡策略

    轮询
    • 默认策略, 每个请求按照时间顺序逐一分配到不同的服务器,如果某一个服务器下线,能自动剔除

    配置方式

    #负载均衡 upstream lagouServer{
    
    #用server定义 HTTP地址
    
    server 192.168.52.100:8081; server 192.168.52.100:8082; }
    
    server {
    
             listen 80; server_name www.lagouNB.com;
    
            location / {
                # 利用 proxy_ pass可以将请求代理到upstream命名的HTTP服务
                proxy_pass   http://lagouServer;
                index  index.html index.htm;
            }
          }
    
          #负载均衡
    
          upstream lagouServer{
    
            #用server定义 HTTP地址
    
            server 192.168.52.100:8081; server 192.168.52.100:8082; }
    
            server {
    
              listen 80; server_name www.lagouNB.com;
    
               location / {
                  # 利用 proxy_ pass可以将请求代理到upstream命名的HTTP服务
                  proxy_pass   http://lagouServer;
        i         index  index.html index.htm;
            }
          }
    weight

    可以根据服务器的实际情况调整服务器权重。权重越高分配的请求越多,权重越低,请求越少。默认是都是1.

    #负载均衡
    upstream lagouServer{
      # 用server定义 HTTP地址
      server 192.168.52.100:8081 weight=1;
      server 192.168.52.100:8082 weight=10;
    }

    项目打包发布

    在平常开发的过程中,不同的环境中项目的相关配置也会有相关的不同,我们在不同的环境中部署就要手动修改为对应环境的配置,这样太麻烦了以及这样也会很容易出错。

    接下来我们就通过maven的相关配置来在打包时指定各个环境对应配置文件

    1. 修改ssm_dao 子模块
    • 修改后的目录结构

     2. 第一步: 创建配置文件

     在项目的src/main/resources 下面创建filter目录, 再创建 development.properties , product.properties 两个文件

    development是开发配置内容。

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///ssm_lagou_edu?characterEncoding=UTF-8
    jdbc.username=root
    jdbc.password=123456

    product是正式配置内容

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://192.168.52.100:3306/ssm_lagou_edu?characterEncoding=UTF-8
    jdbc.username=JiuYuan
    jdbc.password=JiuYuan@123

    3. 第二步:配置jdbc.properties 文件

    jdbc.properties中的内容不再写死,而是从上面两个文件中获取

    第三步: 配置dao模块的的 pom.xml文件
     <profiles>
            <profile>
                <id>dev</id>
                <properties>
                    <!-- 测试环境 -->
                    <env>development</env>
                </properties>
                <activation>
                    <activeByDefault>true</activeByDefault>
                </activation>
            </profile>
            <profile>
                <id>prod</id>
                <properties>
                    <!-- 正式环境 -->
                    <env>product</env>
                </properties>
            </profile>
        </profiles>
    
        <build>
            <finalName>web</finalName>
            <filters>
                <filter>src/main/resources/filter/${env}.properties</filter>
            </filters>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <excludes>
                        <exclude>filter/*.properties</exclude>
    
                    </excludes>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    profile说明

    profile可以让我们定义一系列的配置信息,然后指定其激活条件。这样我们就可以定义多个profile,然后每个profile对应不同的激活条件和配置信息,从而达到不同环境使用不同配置信息的效果

    默认启用的是dev环境配置:

     <profiles>
            <profile>
                <id>dev</id>
                <properties>
                    <!-- 测试环境 -->
                    <env>development</env>
                </properties>
                <activation>
                    <activeByDefault>true</activeByDefault>
                </activation>
            </profile>
            <profile>
                <id>prod</id>
                <properties>
                    <!-- 正式环境 -->
                    <env>product</env>
                </properties>
            </profile>
        </profiles>

    指定数据库配置文件路径,此路径可以自定义:

    <filters>
        <filter>src/main/resources/filter/${env}.properties</filter>
    </filters>
    第四步: 打包

    命令打包

    打本地包 mvn -Pdev install 或者mvn install(因为本例activeByDefault配的为true)
    打产品包 mvn -Pprod install

    结果:src/main/resources/config/jdbc.properties根据 mvn -P 参数决定值

    使用idea打包

     上传至服务器

    前端项目部署

    生产环境配置文件,配置后台URL

    VUE_APP_NAME = Edu Boss
    VUE_APP_TITLE = Lagou Edu Boss (Dev)

    VUE_APP_STORAGE_PREFIX = lagou_edu_boss_dev

    #VUE_APP_API_FAKE = /front
    VUE_APP_API_FAKE = http://192.168.52.100:8080/ssm-web

    #VUE_APP_API_BASE = /boss
    VUE_APP_API_BASE = http://192.168.52.100:8080/ssm-web

    将下面内容拷贝到 vue.config.js

    module.exports = {
      publicPath: process.env.NODE_ENV === "production" ? "/edu-boss/" : "/",
      indexPath: "index.html",
      assetsDir: "static",
      lintOnSave: process.env.NODE_ENV !== "production",
      productionSourceMap: false,
      devServer: {
        open: true,
        port: 8081
      }
    };

    打包测试操作

    打包命令

    npm run build
    • 在项目下会生成一个 dist 目录

     

    •  在本地tomcat的webapps目录下,创建一个edu-boss文件夹,将dist目录中的文件拷贝到里面

     发布前端项目

    1. 解压一个新的tomcat, 修改端口号

    2. 上传前端项目到 webapps

    3. 运行前端项目,并访问

    修改tomcat默认访问项目

     使用notpad打开前端tomcat的配置文件 server.xml, 找到 Host 标签,在Host标签内加入

     在Host标签内加入

    <Context path="" docBase="edu-boss" reloadable="true" debug="0" privileged="true">
    </Context>

    重新启动 并访问前端项目,这个时候只需要直接访问 8081即可

    http://192.168.52.100:8081/

    配置反向代理

    在/usr/local/nginx/conf/nginx.conf中配置反向代理

    #配置ssm项目 反向代理
        upstream lagouedu{
            server 192.168.52.100:8081;
        }
        
        server {
            listen       80;
            server_name  www.edu-boss.com;
    
            location / {
                
                proxy_pass http://lagouedu;  #转发的地址
                index  index.html index.htm;
            }
        }

    修改本地hosts, 配置域名映射

    访问 www.edu-boss.com

  • 相关阅读:
    第一次考核代码及1000字感想
    假期周进度报告2
    《大道至简》读后感
    FileInputFormat看这一段源码
    hadoop源码学习(-)
    linux下的文件解压命令
    Hadoop工作原理
    hadoop程序实例
    linux常用命令
    hadoop的输入和输出文件
  • 原文地址:https://www.cnblogs.com/zhf123/p/14475966.html
Copyright © 2020-2023  润新知