IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> vue项目实战 -> 正文阅读

[Java知识库]vue项目实战

从0开始搭建一个项目

用到的技术:springboot+vue+mybatis+elementui+mysql

1.创建springboot项目

1.引入pom依赖

    <dependencies>
<!--        模板引擎-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
<!--        web项目依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
<!--        简化实体类,自动创建get set等方法-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
<!--        测试相关-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
<!--        mybatis依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
<!--        mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
<!--        json数据处理-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.15</version>
        </dependency>
<!--        分页助手 mybatis分页查询需要的依赖-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.13</version>
        </dependency>
    </dependencies>

2.配置文件

#项目端口
server.port=8899

#mysql数据库
spring.datasource.hikari.max-lifetime=120000
spring.datasource.url= jdbc:mysql://47.98.252.xxx:xxxx/atguigudb
spring.datasource.username=数据库用户名
spring.datasource.password=数据库密码
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.hikari.max_lifetime=120000

#mysql字段驼峰命名 数据库中下划线的字段会被自动分隔变成大写字母
mybatis.configuration.map-underscore-to-camel-case=true
#指定xml文件路径
mybatis.mapper-locations=classpath:mapper/*.xml

#解析时间变为东8区
spring.jackson.time-zone=GMT+8
#时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

#打印sql
logging.level.com.lzp=debug

#pagehelper传递分页参数 根据参数自动分页
pagehelper.support-methods-arguments=true

3.创建欢迎页

此工程欢迎页就是登录页
templates文件夹下index.html文件
页面代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
<!--    引入需要的文件-->
    <script src="/vue/vue.js" rel="stylesheet" type="text/javascript"></script>
    <script src="/element-ui/lib/index.js"></script>
    <link rel="stylesheet" href="/element-ui/lib/theme-chalk/index.css">
    <script src="/axios/axios.min.js"></script>
    <script src="/vue-router/vue-router.min.js"></script>
</head>
<body style="background: linen">
<div id="test" >
    <h1 align="center">请输入账号和密码</h1>
    <br>
    <br>
    <br>
    <br>
<!--    <el-button size="mini" type="primary">登录</el-button>-->
<!--    账号密码输入错误时提示信息-->
    <h5 align="center" style="color: red">{{errorMsg}}</h5>
<!--    表单 两个输入框 一个登录按钮-->
    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="800px"
             class="demo-ruleForm" >
        <h5 align="center" style="color: #C0C4CC">账号:admin 密码:任意</h5>
        
        <el-form-item label="账号" prop="username">
            <el-input style="width:285px;" v-model="ruleForm.username" prefix-icon="el-icon-user"
                      placeholder="请输入账号" clearable></el-input>
        </el-form-item>

        <el-form-item label="密码" prop="password">
            <el-input style="width:285px;" v-model="ruleForm.password"
                      prefix-icon="el-icon-unlock" placeholder="请输入密码" show-password clearable></el-input>
        </el-form-item>

        <el-form-item>
            <el-button type="primary" @click="submitForm('ruleForm')">立即登录</el-button>
        </el-form-item>
    </el-form>
</div>
<script>
    //定义路由,登陆成功后进行页面跳转
    let rt = new VueRouter({
         mode: 'history',
        routes: [{
            path: "/item",
            name: "ok",
        }, {
            path: "/reg",
        }]
    })
    //创建vue实例
    new Vue ({
    el:"#test",
    router: rt,
    data: {
        //错误信息
        errorMsg:'',
        //表单数据 账号和密码
        ruleForm: {
            username: '',
            password:'',
        },
        //校验规则
        rules: {
            name: [
                { required: true, message: '请输入用户名', trigger: 'blur' },
                { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
            ],
            password: [
                { required: true, message: '请输入密码', trigger: 'blur' },
                { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
            ],
        }
    }, 
    //方法
    methods: {
          //提交账号密码
          submitForm(formName) {
              //执行数据校验
              this.$refs[formName].validate((valid) => {
                  //校验通过发送请求 通过axios.post方法
                  if (valid) {
                       //发送请求,处理登录
                       axios.post("/doLogin", this.ruleForm).then(res => {
                           console.log(res);
                           //登录成功判断
                           if(res.data===123 && res.status===200)
                           //路径修改
                           this.$router.push("item");
                           else this.errorMsg="账号:admin~"
                       })
                       // alert('submit!');
                  } else {
                      console.log('error submit!!');
                      return false;
                  }
              });
          }
    },
        //路径变了页面不跳转,路径变了强制刷新页面
        watch: {
            '$route' (to, from) {
                this.$router.go(0);
            }
        },
  })
</script>
</body>
</html>

页面效果:
在这里插入图片描述

4.处理登录请求

正常逻辑是去数据库根据用户名获取用户信息,然后进行密码匹配,匹配正确正常返回,异常返回异常信息。
这里处理逻辑很简单,判断传过来的username是不是admin,是的话返回123,不是的话返回0。

    @RequestMapping("/doLogin")
    @ResponseBody
    public String doLogin(@RequestBody User user){
        System.out.println(user);
        if(user.getUsername().equals("admin"))
        return "123";
        else return "0";
    }

5.登录成功进行页面跳转

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

设置路径为item,然后进行页面刷新,跳转到localhost:8899/item,展示employee信息

6.接收item请求

跳转到item.html页面

    @RequestMapping("/item")
    public String afterLogin(){
        return "item";
    }

7.item.html

展示员工信息

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>employees</title>
    <script src="/vue/vue.js" rel="stylesheet" type="text/javascript"></script>
    <script src="/element-ui/lib/index.js"></script>
    <link rel="stylesheet" href="/element-ui/lib/theme-chalk/index.css">
    <script src="/axios/axios.min.js"></script>
    <script src="/vue-router/vue-router.min.js"></script>
</head>
<body>
        <div  id="item" class="item" >
            <h3 align="right" >你好:{{username}}</h3>
                <h3 style="color: #a0cfff;"  align="left" >
                    员工信息展示
                </h3>
            <!--    展示数据-->
            <div>
                入职日期:
                <div class="block" style="display: inline-block">
<!--                    时间选择,条件搜索使用-->
                    <el-date-picker
                            style="width: 195px"
                            value-format="yyyy-MM-dd"
                            v-model="search.searchDate"
                            type="date"
                            placeholder="请选择入职日期起点">
                    </el-date-picker>
                    <el-date-picker
                            style="width: 195px"
                            value-format="yyyy-MM-dd"
                            v-model="search.searchDateEnd"
                            type="date"
                            placeholder="请选择入职日期终点">
                    </el-date-picker>
                </div>
                姓名:
                <el-input
                        style="width: 185px"
                        placeholder="请输入部分姓名"
                        prefix-icon="el-icon-search"
                        v-model="search.searchName">
                </el-input>
<!--                搜索按钮,条件分页查询-->
                <el-button type="primary" round @click="getEmployees()" icon="el-icon-search">
                    条件搜索
                </el-button>
<!--                按钮,查询所有部门信息-->
                <el-button  type="primary" round @click="getDepartments()" icon="el-icon-menu">
                    部门总览
                </el-button>
            </div>
            <template>
<!--                表格,展示employee信息-->
                <el-table
                        :data="employeesData"
                        style="width: 100%"
                        :row-class-name="tableRowClassName">
                    <el-table-column
                            prop="employeeId"
                            label="编号"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="firstName"
                            label="姓氏"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="lastName"
                            label="名字"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="email"
                            label="邮箱"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="phoneNumber"
                            label="电话"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="hireDate"
                            label="入职日期"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="salary"
                            label="工资"
                            width="180">
                    </el-table-column>

                    <el-table-column
                            prop="departmentName"
                            label="部门名称"
                            >
                    </el-table-column>
<!--                    按钮,展示此员工的部门信息-->
                    <el-table-column>
                        <template slot-scope="scope">
                            <el-button type="text" @click="getDepartmentInfo(scope.row.departmentId)">
                                部门信息
                            </el-button>
                        </template>
                    </el-table-column>
                </el-table>
<!--                弹框,展示员工所在的部门信息-->
                <el-dialog title="部门信息" :visible.sync="dialogTableVisible">
                    <el-table :data="departmentData">
                        <el-table-column prop="departmentId" label="部门编号" width="150"></el-table-column>
                        <el-table-column prop="departmentName" label="部门名称" width="200"></el-table-column>
                    </el-table>
                </el-dialog>
<!--                分页工具展示-->
                <div class="block">
                    <!--            <span class="demonstration">完整功能</span>-->
                    <el-pagination
                            @size-change="handleSizeChange"
                            @current-change="handleCurrentChange"
                            :current-page="page.pageNum"
                            :page-sizes="[5, 10, 15, 20,25,30,35,40,45,50]"
                            :page-size="page.pageSize"
                            layout="total, sizes, prev, pager, next, jumper"
                            :total="page.total">
                    </el-pagination>
                </div>
            </template>
        </div>
 <script>
     // 定义路由
     let rt = new VueRouter({
         mode: 'history',
         routes: [{
             path: "/departments",
             name: "ok",
         }, {
             path: "/reg",

         }]
     })
    // 创建vue实例
     new Vue({
         el:"#item",
         router: rt,
         //   数据
         data() {
             return {
                 username: '',
                 tableData: [],
                 employeesData: [],
                 page:{
                     pageNum: 1,
                     pageSize: 10,
                     total:0,
                 },
                 search:{
                     searchName: '',
                     searchDate: '',
                     searchDateEnd:'',
                 },
                 departmentData: [],
                 dialogTableVisible: false,
             }
         },
         //方法
         methods: {
             //获取用户信息,页面展示
             getUser() {
                 axios.post("/getUser").then(res => {
                     this.username=res.data
                     console.log(res.data)
                 })
             },
             getData(){
                 axios.post("/getData").then(res => {
                     this.tableData=res.data.data
                     console.log(this.tableData)
                 })
             },
             // 获取员工信息,传入分页参数,条件参数
             getEmployees(){
                 axios.get("/getEmployees",{
                     params:{
                         pageNum:this.page.pageNum,
                         pageSize:this.page.pageSize,
                         searchName:this.search.searchName,
                         searchDate:this.search.searchDate,
                         searchDateEnd:this.search.searchDateEnd,
                     }
                 }).then(res => {
                     this.employeesData=res.data.data.list;
                     this.page.pageNum=res.data.data.pageNum;
                     this.page.pageSize=res.data.data.pageSize;
                     this.page.total=res.data.data.total;
                     console.log(res.data.data)
                 })
             },
             //展示所有部门信息
             getDepartments(){
                 this.$router.push("departments");
             },
             //表格项样式
             tableRowClassName({row, rowIndex}) {
                 if (rowIndex === 0) {
                     return 'success-row';
                 } else if (rowIndex === 1) {
                     return 'warning-row';
                 }
                 return '';
             },
             //处理每页显示条数
             handleSizeChange(val) {
                 this.page.pageSize=val;
                 this.getEmployees();
                 console.log(`每页 ${val}`);
             },
             //处理页面切换
             handleCurrentChange(val) {
                 this.page.pageNum=val;
                 this.getEmployees();
                 console.log(`当前页: ${val}`);
             },
             //获取单个部门信息
             getDepartmentInfo(depId){
                 console.log(depId);
                 axios.get("/getDepartmentById",{
                     params:{
                         depId:depId,
                     }
                 }).then(res => {
                     this.departmentData=res.data.data;
                     console.log(this.departmentData)
                     this.dialogTableVisible = true;
                 })
             }
         },
         //页面创建完执行,获取用户,获取员工信息
         created: function () {
             this.getUser(),
             this.getEmployees()
         },
         //路径变了页面不跳转,强制刷新页面
         watch: {
             '$route' (to, from) {
                 this.$router.go(0);
             }
         },
     })
 </script>

</body>
<style>
    .el-table .warning-row {
        background: oldlace;
    }

    .el-table .success-row {
        background: #f0f9eb;
    }
    .el-container {
        padding: 0px;
        margin: 0px;
        height: 100%;
    }
    .item{
        margin-left: 200px;
        /*margin:0 auto;*/
    }
</style>
</html>

页面效果:
在这里插入图片描述

8.接收getEmployees请求

controller:
传入分页参数和条件查询参数,调用service处理。

    @GetMapping("/getEmployees")
    public R findEmployees(@RequestParam Map<String, Object>params) throws ParseException {
        System.out.println(params);
        PageInfo<EmployeeVo> employees = empService.findEmployees(params);
        return R.ok().setData(employees);
    }

service:
使用PageHelper进行分页查询,调用mapper方法进行查询

    @Override
    public PageInfo<EmployeeVo> findEmployees(Map<String, Object>params) throws ParseException {
        PageHelper.startPage(params);
        PageInfo<EmployeeVo> employeesPageInfo = new PageInfo<>(empMapper.findEmployees(params));
        return employeesPageInfo;
    }

mapper:

List<EmployeeVo> findEmployees(@Param("params") Map<String, Object> params);

xml:

    <!--  关联查询时,不要查重复的字段,比如连接键-->
    <!--  有or条件要记得加括号-->
    <!--  前端时间选择器选完时间再删除时间 ,这个参数就会变为空,后台需要注意-->
    <select id="findEmployees" resultType="com.lzp.vo.EmployeeVo">
        select e.*,d.department_name from employees e
        LEFT JOIN departments d
        ON d.`department_id`=e.`department_id`
        where 1=1
            <if test=" params.searchName != null and params.searchName!='' ">
               and ( first_name like "%"#{params.searchName}"%" or
               last_name like "%"#{params.searchName}"%" )
            </if>
            <if test=" params.searchDate != null and params.searchDate!='' ">
                and hire_date <![CDATA[ > ]]> #{params.searchDate}
            </if>
            <if test=" params.searchDateEnd != null and params.searchDateEnd!='' ">
                and hire_date <![CDATA[ < ]]> #{params.searchDateEnd}
            </if>
    </select>

9.处理部门信息

点击部门信息,根据department_id查询部门信息
在这里插入图片描述
controller:
根据部门id查询

    @GetMapping("/getDepartmentById")
    public R findDepartmentById(@RequestParam("depId") Integer depId) throws ParseException {
        System.out.println(depId);
        List<DepatmentVo> depatmentVo = empService.findDepartmentById(depId);
        return R.ok().setData(depatmentVo);
    }

service:
根据id查询

    @Override
    public List<DepatmentVo> findDepartmentById(Integer depId) {
        List<DepatmentVo>  departmentById = empMapper.findDepartmentById(depId);
        return departmentById;
    }

mapper:

List<DepatmentVo> findDepartmentById(@Param("depId") Integer depId);

xml:

    <select id="findDepartmentById" resultType="com.lzp.vo.DepatmentVo">
        select department_id,department_name from departments where department_id=#{depId}
    </select>

10.查询所有部门

点击部门总览,查询部门总信息,进行页面跳转。
页面效果:

在这里插入图片描述
页面内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>departments</title>
    <script src="/vue/vue.js" rel="stylesheet" type="text/javascript"></script>
    <script src="/element-ui/lib/index.js"></script>
    <link rel="stylesheet" href="/element-ui/lib/theme-chalk/index.css">
    <script src="/axios/axios.min.js"></script>
    <script src="/vue-router/vue-router.min.js"></script>
</head>
<body>
<div id="department" class="department">
    <h3 align="right" >你好:{{username}}</h3>
<!--    按钮,展示地址总信息-->
    <div>
        <el-button size="small" type="primary" round @click="getLocationInfo()" icon="el-icon-menu">
            地址总览
        </el-button>
    </div>
    <h3 style="color: #a0cfff"  align="left" >
        部门信息展示
    </h3>
    <template>
<!--        表格,展示部门信息-->
        <el-table
                :data="departmentsData"
                style="width: 100%"
                :row-class-name="tableRowClassName">
            <el-table-column
                    prop="departmentId"
                    label="部门编号"
                    width="180">
            </el-table-column>
            <el-table-column
                    prop="departmentName"
                    label="部门名称"
                    width="180">
            </el-table-column>
            <el-table-column
                    prop="managerName"
                    label="部门领导"
                    width="180">
            </el-table-column>
            <el-table-column
                    prop="streetAddress"
                    label="部门地址"
                    width="180">
            </el-table-column>
<!--            按钮,弹窗展示,这个部门的地址信息-->
            <el-table-column>
                <template slot-scope="scope">
                    <el-button type="text" @click="getLocationInfo(scope.row.locationId)">地址信息
                    </el-button>
                </template>
            </el-table-column>
        </el-table>
<!--        弹窗,地址信息-->
        <el-dialog title="地址信息" :visible.sync="dialogTableVisible" class="pop-up">
            <el-table :data="locationsData">
                <el-table-column prop="locationId" label="地址编号" width="150"></el-table-column>
                <el-table-column prop="streetAddress" label="部门地址" width="200"></el-table-column>
                <el-table-column prop="postalCode" label="邮编" width="150"></el-table-column>
                <el-table-column prop="city" label="所在城市" width="150"></el-table-column>
                <el-table-column prop="stateProvince" label="所在州省" width="150"></el-table-column>
            </el-table>
        </el-dialog>
<!--        分页工具-->
        <div class="block">
            <!--            <span class="demonstration">完整功能</span>-->
            <el-pagination
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange"
                    :current-page="page.pageNum"
                    :page-sizes="[5, 10, 15, 20,25,30,35,40,45,50]"
                    :page-size="page.pageSize"
                    layout="total, sizes, prev, pager, next, jumper"
                    :total="page.total">
            </el-pagination>
        </div>
    </template>
</div>
<script>
<!--        创建vue实例-->
        new Vue({
            el:"#department",
            //数据
            data() {
                return{
                    username:'',
                    departmentsData: [],
                    locationsData: [],
                    dialogTableVisible: false,
                    page:{
                        pageNum: 1,
                        pageSize: 10,
                        total:0,
                    },
                }
            },
            //方法
            methods:{
                tableRowClassName({row, rowIndex}) {
                    if (rowIndex === 0) {
                        return 'success-row';
                    } else if (rowIndex === 1) {
                        return 'warning-row';
                    }
                    return '';
                },
                handleSizeChange(val) {
                    this.page.pageSize=val;
                    this.getDepartments();
                    console.log(`每页 ${val}`);
                },
                handleCurrentChange(val) {
                    this.page.pageNum=val;
                    this.getDepartments();
                    console.log(`当前页: ${val}`);
                },
                getUser() {
                    axios.post("/getUser").then(res => {
                        this.username=res.data
                        console.log(res.data)
                    })
                },
                //获取部门信息
                getDepartments(){
                    axios.get("/getDepartments",{
                        params:{
                            pageNum:this.page.pageNum,
                            pageSize:this.page.pageSize,
                            // searchName:this.search.searchName,
                            // searchDate:this.search.searchDate,
                            // searchDateEnd:this.search.searchDateEnd,
                        }
                    }).then(res => {
                        this.departmentsData=res.data.data.list;
                        this.page.pageNum=res.data.data.pageNum;
                        this.page.pageSize=res.data.data.pageSize;
                        this.page.total=res.data.data.total;
                        console.log(res.data.data)
                    })
                },
                //获取地址信息
                getLocationInfo(locationId){
                    console.log(locationId);
                    axios.get("/getLocations",{
                        params:{
                            locationId:locationId,
                        }
                    }).then(res => {
                        this.locationsData=res.data.data;
                        console.log(this.locationsData)
                        this.dialogTableVisible = true;
                    })
                }
            },
            created: function () {
                this.getUser(),
                this.getDepartments()
            },
        })
</script>

</body>
<style>
    .el-table .warning-row {
        background: oldlace;
    }

    .el-table .success-row {
        background: #f0f9eb;
    }
    .department{
        margin-left: 200px;
        /*margin:0 auto;*/
    }
    /*弹窗增加滚动条*/
    .pop-up .el-dialog__body {
        padding: 3px 30px;
        overflow-y: auto;
        height: 40vh;
    }
</style>
</html>

11.接收getDepartments请求

controller:
传入分页参数,调用service方法查询

    @GetMapping("/getDepartments")
    @ResponseBody
    public R getDepartments(@RequestParam Map<String, Object> params ){
        PageInfo<DepartmentsVo> departments = depService.getDepartments(params);
        return R.ok().setData(departments);
    }

service:
分页查询查出所有部门信息,遍历集合,根据manager_id查询领导名字。返回PageInfo。

    @Override
    public PageInfo<DepartmentsVo> getDepartments(Map<String, Object>params) {
        //分页查询
        PageHelper.startPage(params);
        PageInfo<DepartmentsVo> departmentsVoPageInfo = new PageInfo<>(depMapper.getDepartments(params));
        //PageInfo类型的数据,实际数据都在list集合中
        //List<DepartmentsVo> departments = depMapper.getDepartments(params);
        //遍历list集合
        List<DepartmentsVo> departmentsVoList = departmentsVoPageInfo.getList().stream().map((item) -> {
            //获取到部门领导的名字 根据manager id 去employees表查询
            String managerNameById = empMapper.findManagerNameById(item.getManagerId());
            item.setManagerName(managerNameById);
            return item;
        }).collect(Collectors.toList());
        //将新的list集合放入PageInfo对象中
        departmentsVoPageInfo.setList(departmentsVoList);
        return departmentsVoPageInfo;
    }

mapper:

List<DepartmentsVo> getDepartments(@Param("params") Map<String, Object> params);
String findManagerNameById(@Param("id") Integer id);

xml:

    <select id="getDepartments" resultType="com.lzp.vo.DepartmentsVo">
        SELECT   d.*,l.street_address
        FROM departments d
        LEFT JOIN locations l
        ON d.`location_id`=l.`location_id`
    </select>
    
    <select id="findManagerNameById" resultType="String">
        select first_name from employees where employee_id=#{id}
    </select>

这里也可以使用两次关联查询

SELECT d.`department_id`,d.`department_name`,e.`first_name`,l.street_address
FROM departments d
LEFT JOIN employees e
ON d.`manager_id`=e.`employee_id`
LEFT JOIN locations l
ON d.`location_id`=l.`location_id`

12.地址信息和地址总览

页面效果:
地址信息:
在这里插入图片描述
地址总览:
在这里插入图片描述
这里都采用了弹窗,未新增页面。
两个查询方式采用同一个方法接收,有id的话根据id查询,没有的话查询全部
controller:

    @GetMapping("/getLocations")
    public R getLocations(@RequestParam(required = false)Integer locationId){
        System.out.println(locationId);
        List<Location> locations = localService.getLocations(locationId);
        return R.ok().setData(locations);
    }

service:

    @Override
    public List<Location> getLocations(Integer locationId) {
        return localMapper.getLocations(locationId);
    }

mapper:

List<Location> getLocations(@Param("locationId") Integer locationId);

xml:

    <select id="getLocations" resultType="com.lzp.entity.Location">
        select location_id,street_address,postal_code,city,state_province from locations
        where 1=1
        <if test=" locationId > 0 ">
            and location_id=#{locationId}
        </if>
    </select>

至此,就完成了简单的vue整合

2.项目部署的问题

1.内存占用问题

想把项目部署到服务器,服务器内存所剩不多,引出第一个问题,怎么确定这个程序占用多大内存呢?
默认情况:最大内存为物理内存的1/4,初始内存为物理内存的1/64,这个内存指的是堆内存,由新生代和老年代两部分,比例为1:2,所以我的远程服务器内存为8g,最大内存就会占2g。所以启动时要指定内存,先设置了256m看下情况。
metaspace为元空间大小,默认为20M左右,需要增大,不然会进行fullGC.
在这里插入图片描述
启动程序,打开jvisualvm.exe(在jdk的bin目录下)

在这里插入图片描述
可以看到总数为256m。
这里看出内存使用量,可以看出新生代使用较多,老年代使用很少,所以可以确定256m内存是完全满足要求的(128m应该也能满足–)。

在这里插入图片描述
至此,困扰的问题就大概解决了,这个小项目的内存占用为100m左右。当然这是没有请求进来的情况下,youngGC的频率不高,大概几十秒一次(在linux下频率还要更低)。

这是在idea打开的结果,采用jar包部署的方式,新生代内存增加没这么快
下面是采用jar包部署的方式(windows)
在这里插入图片描述
linux
更为平缓~
在这里插入图片描述

2.jmeter测试

测试1s10线程,每秒进行5次youngGC。
在这里插入图片描述
这里是在windows部署的项目,又尝试在阿里云部署,然后做了jmeter测试,发现GC频率并不高。这是windows和linux的区别么,有待大神指教-----

生成了jmeter文件,数据有点恐怖,最长的响应时间为15s。。。,感觉应该和本地网络有很大关系,需要再做测试。(网络良好的时候又做了一次测试,每秒线程数为25时,最大响应时间在1000ms以内,每秒线程数为30时,最大响应时间就是秒级别的了,所以可以确定,在这个256m内存配置下,网络条件良好的情况下,程序最多每秒可以处理25次请求)
在这里插入图片描述

jmeter测试方式
在软件中设置好参数,添加好请求,然后保存测试文件
在这里插入图片描述
然后进到jmeter的bin目录,打开cmd
执行 jmeter -n -t HTTP请求2.jmx -l testplan/result/result.txt -e -o testplan/webreport

  • HTTP请求2.jmx 测试文件的名字,我这里在bin目录下,可以单独指定文件夹
  • testplan/result 请求执行记录的文件夹
  • testplan/webreport 生成html报告的文件夹

3.VisualVM监控阿里云服务器部署的项目

1.linux服务器配置

1.在java bin目录下新建文件 jstatd.all.policy
文件内容:
grant codebase “file:/home/mysoftware/myjava/jdk1.8.0_171/lib/tools.jar” {
permission java.security.AllPermission;
};
2.然后启动jstatd
nohup jstatd -J-Djava.security.policy=/home/mysoftware/myjava/jdk1.8.0_171/bin/jstatd.all.policy -J-Djava.rmi.server.hostname=47.98.xxx.xxx &

3.然后netstat -lutnp |grep jstatd 查看jstad占用的端口(有两个) 防火墙添加

4.然后在xshell就可以使用 jps jmap 等命令了

2.windows下配置

打开VisualVM,添加远程主机(在jdk的bin目录下)
总结: jvm方面的知识还需要提高,加油!

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-06-16 21:31:54  更:2022-06-16 21:32:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 18:55:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码