vue路由打包文件部署tomcat 乱码_教育平台项目前端:项目前后端接口联调,项目上线部署发布...

44dd2e57661f755cb7e4e2a5cfa4a1da.png

项目前后端接口联调

联调准备

运行后台项目

clean 清空项目的编译文件

compile 重新编译项目

将项目部署到 Tomcat:项目名为 lagou_edu_home,端口号: 8080,使用 war 方式部署

部署图片上传路径为 Tomcat 的 webapps 目录下的 upload 目录

最后运行前端项目

首先导入前端项目到 VS Code

运行项目

课程管理首页

Courses.vue 的视图部分代码

                                                                                        ​              查询      ​              新建课程          ​                                ​                                                      ​                                        {{ scope.row.status == "1" ? "下架" : "发布" }}​                    营销信息​                    内容管理                    

获取课程列表

Courses.vue JS 部分代码

export default {    name: "Courses",    title: "课程管理",    // 定义数据部分    data() {        return {            filter: { course_name: "", status: "" }, // 查询对象            courses: [], // 课程信息集合            loading: false // 是否弹出加载        };    },    // 钩子函数    created() {        this.loadCourses();    },    methods: {        // 方法 1: 获取课程列表        loadCourses() {            this.loading = true;            // 请求后台查询课程列表接口            return axios                .get("/course", {                params: {                    methodName: "findCourseList"                }            })                .then(resp => {                console.log(resp);                this.loading = false; // 关闭加载                this.courses = resp.data; // 取出数据            })                .catch(error => {                this.$message.error("数据获取失败! ! !");            });        },    }};

条件查询课程信息

Courses.vue JS 代码的 methods

//方法 2: 条件查询课程信息filterQuery() {    this.loading = true;    // 定义查询条件对象    const search = {};    // 保存用户输入的条件    if (this.filter.course_name) search.course_name = this.filter.course_name;    if (this.filter.status) search.status = this.filter.status;    // 请求后台条件查询接口    return axios        .get("/course", {        // 准备参数        params: {            methodName: "findByCourseNameAndStatus",            course_name: search.course_name,            status: search.status        }    })        .then(resp => {        console.log(resp);        this.loading = false;        // 将响应数据保存到 courses        this.courses = resp.data;    })        .catch(error => {        this.$message.error("数据获取失败! ! !");    });},

跳转到新建课程页面

Courses.vue JS 代码的 methods

// 方法 3: 添加课程跳转方法 addCourse() {    // 路由跳转到 CourseItem.vue 组件    this.$router.push({ name: "CourseItem", params: { courseId: "new" } });},

修改课程状态

Courses.vue JS 代码的 methods

// 方法 4: 修改课程状态updateStatus(item) {    // item 表示选中的数据 = Course 对象    axios        .get("/course", {        params: {            methodName: "updateCourseStatus",            id: item.id        }    })        .then(res => {        console.log(res);        // 将返回的状态字段,封装到对象中        Object.assign(item, res.data);        // 重新加载页面        window.location.reload;    });},

跳转课程营销或内容管理

Courses.vue JS 代码的 methods

// 方法 5: 根据路由名称,导航到对应组件  handleNavigate(name, id) {    this.$router.push({ name, params: { courseId: id } });},

新建 & 修改课程

Course 组件中的跳转方法

营销信息
// 方法 3: 添加课程跳转方法addCourse() {    // 路由跳转到 CourseItem.vue 组件    this.$router.push({ name: "CourseItem", params: { courseId: "new" } });},

router.js 路由

找到 name 为: CourseItem 的路由

// 添加课程的路由{    path: "/courses/:courseId", // 路径,携带参数: 课程 ID    name: "CourseItem",    // 路由导航到的组件    component: () =>    import(/* webpackChunkName: 'courses' */ "../views/CourseItem.vue")},

CourseItem 组件

CourseItem.vue 的视图部分代码

          
            this.$router.back()"        :content="course.title"      />      保存    
​                      基本信息                                                                                                                                                  ​              销售信息                              元                                                元                                                  ​              分享信息                                                                点击上传                                                                                        ​              课程详情              ​      
       保存      
   ​      

CourseItem.vue 的 JS 部分代码

data() {    // 数据    return {        rules, //规则        course: {}, //课程        loading: false,        params: {} //参数对象    };},// 钩子函数created() {    // 1.显示当前页面在网站中的位置    this.$breadcrumbs = [      { name: "Courses", text: "课程管理" },      { text: "营销信息" }    ];​    // 2.从路由中获取传递的参数, 课程 id    const id = this.$route.params.courseId;​    // 3.判断 id 是否有值    if (!id) return this.redirectToError();​    // 4.判断是 new 还是具体的id    if (id === "new") {      // new 代表新增      this.course.title = "新增课程";    } else {      // 否则就是修改      this.loadCourse(id);    }},

图片上传分析

页面部分

                                点击上传            

FormData 使用演示

// 通过 FormData 构造函数创建一个空对象var formdata = new FormData();// 可以通过 append() 方法来追加数据formdata.append("name","laotie");// 通过 get 方法对值进行读取console.log(formdata.get("name")); // laotie// 通过 set 方法对值进行设置formdata.set("name","laoliu");console.log(formdata.get("name")); // laoliu
  1. 将 form 表单元素的 name 与 value 进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。
  2. 异步上传文件
  3. 创建 FormData 对象

CourseItem.vue 的 JS 的 methods的 created 部分的代码

//5.创建FormData对象,将图片与表单一同上传this.params = new FormData();

methods 添加方法

// 文件上传onchange(file) {    // 判断文件不为空    if (file != null) {        // 将文件信息保存到 params 中        this.params.append("file", file.raw, file.name);    }},

新建课程信息

CourseItem.vue 的 JS 的 methods 的代码

// 方法 1: 保存和修改课程信息handleSave() {    // 检查是否拿到了正确的需要验证的 form    this.$refs.form.validate(valid => {        if (!valid) return false;​        // 1.设置 Content-Type 为多部件上传        let config = {            headers: {                "Content-Type": "multipart/form-data"            }        };​        // 2.获取表单中的数据,保存到 params (params 就是 FromData对象)        for (let key in this.course) {            //debugger            console.log(key + "---" + this.course[key]);            this.params.append(key, this.course[key]);        }​        // 3.保存课程信息        axios            .post("/courseSalesInfo", this.params, config)            .then(res => {            //debugger            if (res.data.status == 0) {                // 保存成功,跳转到首页                this.$router.back();            } else if (res.data.status == 1) {                this.$message({                    type: "error",                    message: res.data.msg                });            }        })            .catch(err => {            this.$message.error("保存失败! ! !");        });    });},

修改课程信息

CourseItem.vue 的 JS 的 methods 的代码

// 方法 2: 根据 ID 回显课程信loadCourse(id) {    this.loading = true;    axios        .get("/course", {        params: {            methodName: "findCourseById",            id: id        }    })        .then(res => {        this.loading = false;        this.course = res.data;    })        .catch(() => {        this.$message.error("回显数据失败! ! !");    });},

内容管理

Course 组件中的跳转方法

内容管理
// 方法 5: 根据路由名称, 导航到对应组件handleNavigate(name, id) {    this.$router.push({ name, params: { courseId: id } });},

router.js 路由

// 内容管理的路由{    path: "/courses/:courseId/tasks",    name: "CourseTasks",    meta: { requireAuth: true },    component: () =>    import(/* webpackChunkName: 'courses' */ "../views/CourseTasks.vue")}

CourseTasks 组件

树形控件测试

  1. 打开之前编写 Element UI 的项目
  2. 在 component 目录下添加一个组件 TestTree.vue
  1. 在 Index.vue 组件中的导航菜单位置添加一个树形控件导航;注意要设置 index 的路径为 “/tree”
          导航菜单                    课程管理                    树形控件      
  1. 在 router/index.js 路由文件中进行配置,在布vue局路由中再添加一个子路由
// 导入树形控件组件import Tree from "@/components/TestTree.vue"​...  {    path: "/index",    name: "index",    component: Index,    children: [      {        path: "/course",        name: "course",        component: Course      },       // Tree控件测试路由      {        path: "/tree",        name: "tree",        component: Tree      }    ]  }...
  1. 在 ElementUI 官网中查找树形控件
  2. 先来查看基础用法,赋值代码到 TestTree.vue
    ​​
  1. Tree 组件属性分析

data:展示数据

props:配置树形结构;label - 设置节点名称,children - 指定生成子树的属性名称

  1. 自定义树节点内容:data - 数据对象,node - 节点对象
            {{ data.label }}         级别:{{node.level}}    
  1. 展示树形结构章节与课时
            {{ data.section_name || data.theme }}       级别:{{node.level}}      ​

显示当前课程的名称

 this.$router.back()"        :content="addSectionForm.course_name"      />

data 数据

data() {    // 定义章节信息    const addSectionForm = {        course_id: undefined,        course_name: "",        section_name: "",        description: "",        order_num: 0    };​    // 章节与课时信息,树形结构    const treeProps = {        label: item => {            return item.section_name || item.theme;        },        children: "lessonList"    };​    // 定义章节状态信息    const statusMapping = {        0: "已隐藏",        1: "待更新",        2: "已更新"    };​    const statusForm = {        status: 0    };​    return {        addSectionForm,        treeProps,        sections: [],        statusForm, // 状态表单        statusMapping,​        loading: false, // 树形控件        showAddSection: false, // 添加或修改章节        showStatusForm: false // 状态修改    };},

加载课程信息

created() {    // 1.显示当前页面在网站中的位置    this.$breadcrumbs = [        { name: "Courses", text: "课程管理" },        { text: "课程结构" }    ];​    // 2.从路由中获取传递的参数, 课程 id    const id = this.$route.params.courseId;    if (!id) return this.redirectToError();​    // 3.加载课程信息    this.loadCourse(id);​    // 4.加载课程对应的章节与课时    this.loadChildren(id);},methods: {    // 方法 1: 加载课程信息    loadCourse(id) {        axios            .get("/courseContent", {            params: {                methodName: "findCourseById",                course_id: id            }        })            .then(res => {            // 将数据保存到表单对象中            this.addSectionForm.course_id = res.data.id;            this.addSectionForm.course_name = res.data.course_name;        })            .catch(error => {            this.loading = false;            this.$message.error("数据获取失败! ! !");        });    },},

加载章节与课时信息

// 方法 2: 加载树 (章节与课程)loadChildren(id) {    this.loading = true;    axios        .get("/courseContent", {        params: {            methodName: "findSectionAndLessonByCourseId",            course_id: id        }    })        .then(resp => {        // 获取章节数据, 保存到 sections        this.sections = resp.data;        this.loading = false;    })        .catch(error => {        this.loading = false;        this.$message.error("数据获取失败! ! !");    });},

Element UI 树形控件 el-tree::data 列表数据;:props 配置选项。

        
       {{ data.section_name || data.theme }}       ...    
  ...

:props 配置选项:label - 指定节点标签为节点对象的某个属性值;children - 指定子树为节点对象的某个属性值。

// 章节与课时信息, 树形结构const treeProps = {    label: item => {        return item.section_name || item.theme;    },    children: "lessonList"}; 

操作按钮显示:node.level 获取当前节点的级别;@click.stop 事件冒泡,点击哪个元素就执行哪个元素绑定的事件

        编辑        {{ statusMapping[data.status] }}

回显信息

添加章节

JS 代码

// 方法 3: 显示添加章节表单, 回显课程信息handleShowAddSection() {    // 显示表单    this.showAddSection = true;},

添加章节

确 定

JS 代码

// 方法 4: 添加&修改章节操作handleAddSection() {    axios        .post("/courseContent", {        methodName: "saveOrUpdateSection",        section: this.addSectionForm    })        .then(resp => {        this.showAddSection = false;        // 重新加载列表        return this.loadChildren(this.addSectionForm.course_id);    })        .catch(error => {        this.loading = false;        this.$message.error("操作执行失败! ! !");    });},

后台接口问题解决

BaseServlet 中代码修改

if("application/json;charset=utf-8".equals(contentType)) {    ...}    // 修改为:​if("application/json;charset=utf-8".equalsIgnoreCase(contentType)) {    ...}

CourseContentServlet 中的 saveOrUpdateSection 方法修改

// 使用 BeanUtils 的 copyProperties 方法将 map 中的数据封装到 section 对象里BeanUtils.copyProperties(section,map.get("section"));

修改章节

编辑

JS 回显示方法

// 方法 5: 修改章节回显方法handleEditSection(section) {    // 对象拷贝    Object.assign(this.addSectionForm, section);    this.showAddSection = true;},

事件冒泡:当点击子元素的事件。如果父元素也有同样的事件的话。他就会一并的触发。

解决冒泡事件的方法:@click.stop

        
       事件冒泡    

章节状态回显

{{ statusMapping[data.status] }}

JS 代码

// data 函数中定义的章节状态const statusMapping = {    0: "已隐藏",    1: "待更新",    2: "已更新"};
// 方法 6: 显示章节状态showStatus(data) {    this.statusForm.id = data.id;    this.statusForm.status = data.status.toString();    this.statusForm.data = data;    this.showStatusForm = true;// 显示状态表单},

Select 选择器

  1. 打开之前编写 Element UI 的项目
  2. 在 component 目录下添加一个组件 TestSelect.vue
  1. 在 Index.vue 组件中的导航菜单位置添加一个 Select 选择器导航;注意要设置 index 的路径为 /select
    Select选择器
  1. 在 index.js 路由文件中进行配置,在布局路由中再添加一个子路由
import Select from "@/components/TestSelect.vue"{    path: "/select",    name: "select",    component: Select,},
  1. 在 Element UI 官网中查找 Select 选择器
  2. 查看基础用法,将代码复制到 TestSelect.vue 中
        ​​
  1. select 选择器属性分析

v-model 的值为当前被选中的 el-option 的 value 属性值

el-option 选项:label 选项的标签名;value 选择的值

  1. 使用 Select 选择器展示状态信息
        ​​

Object.keys()

var obj = { 0: 'a', 1: 'b', 2: 'c' };console.log(Object.keys(obj)); // console: ['0', '1', '2']

章节状态修改

确 定

JS 部分

//方法7: 修改章节状态updateStatus(statusForm) {    axios        .get("/courseContent", {        params: {            methodName: "updateSectionStatus",            status: this.statusForm.status,            id: this.statusForm.id        }    })        .then(resp => {        this.statusForm.data.status = this.statusForm.status;        this.statusForm = {};        this.showStatusForm = false;    })        .catch(error => {        this.showStatusForm = false;        this.$message.error("修改状态失败! ! !");    });},

v-for 里面数据层次太多, 修改过数据变了,页面没有重新渲染,需手动强制刷新。

    

项目上线部署发布

简介

服务器与操作系统

服务器是计算机的一种,它比普通计算机运行更快、负载更高、价格更贵。

服务器从硬件上等同于电脑 PC。而服务器跟 PC 都是由 CPU、内存、主板、硬盘、电源等组成;但服务器的性能要远远超过 PC,因为它要保证全年无休。

操作系统是作为应用程序与计算机硬件之间的一个接口。

没有安装操作系统的计算机,被称为裸机, 如果想在裸机上运行自己的程序,就需要使用机器语言。

安装操作系统之后,就可以配置一些高级语言的环境,进行高级语言的开发。

Linux 系统是最具稳定性的系统。

Linux 比 Windows 更具安全性。

Linux 服务器在应用开发上更能节约成本。

项目的发布部署

项目的开发流程大致要经过一下几个步骤:

  • 项目立项
  • 需求分析阶段
  • 原型图设计阶段
  • 开发阶段
  • 测试阶段
  • 系统上线

后台项目部署

安装虚拟机

在 Linux 阶段已经安装过了虚拟机,使用的是 Linux 操作系统 CentOS 7 版本。

安装软件环境

以下软件在 Linux 阶段都已安装完成:

  • JDK 11
  • Tomcat 8.5
  • MySQL 5.7

查看 Java 版本

java -version

查看 tomcat 是否能够正常启动

# 进入到 tomcat 目录cd /usr/tomcat/​# 启动 tomcat./bin/startup.sh ​# 关闭 tomcat./bin/shutdown.sh 

关闭防火墙

#查看已经开放的端口:firewall-cmd --list-ports​#开启端口    firewall-cmd --zone=public --add-port=8080/tcp --permanent​#命令含义:    –zone #作用域    –add-port=8080/tcp #添加端口,格式为:端口/通讯协议    –permanent #永久生效,没有此参数重启后失效​#重启防火墙firewall-cmd --reload​# 关闭防火墙# 停止 firewallsystemctl stop firewalld.service# 禁止 firewall 开机启动systemctl disable firewalld.service# 查看默认防火墙状态(关闭后显示 notrunning,开启后显示 running)firewall-cmd --state

登录 MySQL 检查数库连接是否正常

-- 创建用户CREATE USER 'JiuYuan'@'%' IDENTIFIED BY 'JiuYuan@123';​-- 授予所有权限GRANT ALL PRIVILEGES ON *.* TO 'JiuYuan'@'%' IDENTIFIED BY 'JiuYuan@123';​-- 刷新FLUSH PRIVILEGES;

使用 SQLYog 连接 Linux 上的 MySQL,导入 SQL 脚本创建项目所需的数据库

项目打包发布

  1. 修改项目的数据库配置文件:数据库的 IP、用户名、密码。
  2. 修改 Constants 常量类中的项目 URL
// 生产环境地址public static final String LOCAL_URL = "http://192.168.91.128:8080";
  1. 修改后启动项目,测试一下 保证数据库连接没有问题
  2. 检查 POM 文件打包方式必须是 war 编译版本为 JDK 11
war    UTF-8    11    11
  1. 执行打包命令
// 清除 target 文件夹clean // 打包跳过测试package
  1. 复制出 target 目录下的 war 包
  2. 修改一下 war 包名称为 lagou_edu_home.war
  3. 上传到 tomcat 的 webapps 目录中启动测试,访问接口:
http://192.168.91.128:8080/lagou_edu_home/course?methodName=findCourseList

前端项目部署

修改配置文件

前端项目的配置文件有两个:一个是开发环境的配置文件,一个是生产环境的配置文件。

先修改一下开发环境文件 .env.development 的后端服务器访问地址,然后进行一下测试:

VUE_APP_API_BASE =  http://192.168.91.128:8080/lagou_edu_home

修改生产环境的配置文件 .env.production:

VUE_APP_API_BASE = http://192.168.91.128:8080/lagou_edu_home

前端项目打包

修改 vue.config.js 配置文件

module.exports = {  // relative path for dev  publicPath: process.env.NODE_ENV === "production" ? "/edu-boss/" : "./",  // for gh-pages  indexPath: "index.html",  assetsDir: "static",  lintOnSave: process.env.NODE_ENV !== "production",  productionSourceMap: false,  css: {    // sourceMap: process.env.NODE_ENV !== 'production'  },  devServer: {    open: true,    port: 8081  }};

执行下面的打包命令:

npm run build

在项目下会生成一个 dist 目录

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

启动本地 Tomcat 访问前端项目路径为

http://localhost:8081/edu-boss/

前端项目发布

  1. 验证没有问题后将 edu-boss 项目压缩上传到 Tomcat 服务器
# 复制一份 Tomcatcp -r /usr/tomcat/ /usr/tomcat2# 上传 edu-boss.zip 并解压unzip edu-boss.zip # 删除 edu-boss.ziprm -rf edu-boss.zip
  1. 修改 tomcat2 的 server.xml 配置文件的 3 个端口避免与 tomcat 冲突,修改结果如下:
...  ...  ...    ...  
  1. 在部署后端项目的 tomcat1 的 webapps 目录下创建一个 upload 文件夹保存图片
  2. 运行前端项目:
# 进入 tomcat2,启动项目./bin/startup.sh# 动态查看日志tail -f logs/catalina.out
  1. 运行后端项目
# 进入 tomcat1,启动项目./bin/startup.sh # 动态查看日志tail -f logs/catalina.out 
  1. 前后端都启动后进行测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值