likes
comments
collection
share

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

作者站长头像
站长
· 阅读数 80

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

技术栈

SSM 项目【前后端分离】

- 说明: 前后端分离开发, 前端框架Vue + 后端框架SSM 1. 前端框架Vue 2. 后台框架-SSM(SpringMVC+Spring+MyBatis) 3. 数据库-MySQL 4. 项目的依赖管理-Maven 5. 分页-pagehelper。 6. 逆向工程-MyBatis Generator。 7. 其它...

-前端框架Vue 1. 使用了ElementPlus 来展示数据。 2. 使用Axios 对象来请求数据/走接口。

-后端框架SSM 1. 使用经典的三层结构。 2. 使用MyBatis Generator 和MyBatis pageHelper。

实现功能04-添加家居信息

需求分析/图解

 SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

思路分析

1. 完成后台代码从dao -> serivce -> controller , 并对每层代码进行测试, 到controller 这一层,使用Postman 发送http post 请求完成测试 2. 完成前端代码, 使用axios 发送ajax(json 数据)给后台, 实现添加家居信息 

代码实现

创建\service\FurnService.java 和\service\FurnServiceImpl.java, 增加添加方法

FurnService接口

public interface FurnService {
    //添加
    public void save(Furn furn);
}

FurnServiceImpl

@Service
public class FurnServiceImpl implements FurnService {


    //注入/装配FurnMapper接口对象(代理对象)
    @Resource
    private FurnMapper furnMapper;

    @Override
    public void save(Furn furn) {
        //解读
        //1. 使用insertSelective
        //2. 因为我们的furn表的id是自增的,就使用insertSelective
        furnMapper.insertSelective(furn);
    }

修改Furn.java , 当创建Furn 对象imgPath 为null 时, imgPath 给默认值 

private String imgPath = "assets/images/product-image/1.jpg"; public Furn(Integer id, String name, String maker, BigDecimal price,Integer sales, Integer stock, String imgPath) { this.id = id; this.name = name; this.maker = maker; this.price = price; this.sales = sales; this.stock = stock; if(!(imgPath == null || imgPath.equals("")) ){ this.imgPath = imgPath; } }

创建FurnServiceTest.java  测试方法

public class FurnServiceTest {

    //属性
    private ApplicationContext ioc;
    //从spring容器中,获取的是FurnService接口对象/代理对象
    private FurnService furnService;

    @Before
    public void init() {
        ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        //说明
        //1. 通过FurnService.class 类型获取 FurnService接口对象/代理对象
        furnService = ioc.getBean(FurnService.class);
        //com.sun.proxy.$Proxy21
        System.out.println("furnService-" + furnService.getClass());
    }

    @Test
    public void save() {

        Furn furn =
                new Furn(null, "小风扇", "wyx家居", new BigDecimal(180), 10,
                        70, "assets/images/product-image/1.jpg");

        furnService.save(furn);

        System.out.println("添加成功~");
    }
}

创建Msg.java用来返回json 的数据的通用类

package com.wyxdu.furn.bean;

import java.util.HashMap;
import java.util.Map;

/**

 * Msg: 后端程序返回给前端的json数据的Msg对象=》本质就是数据规则
 */
public class Msg {

    //状态码 200-成功 400-失败
    private int code;
    //信息-说明
    private String msg;
    //返回给客户端/浏览器的数据-Map集合
    private Map<String, Object> extend =
            new HashMap<>();

    //编写几个常用的方法-封装好msg
    //返回success对应的msg
    public static Msg success() {
        Msg msg = new Msg();
        msg.setCode(200);
        msg.setMsg("success");
        return msg;
    }

    //返回fail对应的msg
    public static Msg fail() {
        Msg msg = new Msg();
        msg.setCode(400);
        msg.setMsg("fail");
        return msg;
    }

    //给返回的msg设置数据-不难应该可以看懂
    public Msg add(String key, Object value) {
        extend.put(key, value);
        return this;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Map<String, Object> getExtend() {
        return extend;
    }

    public void setExtend(Map<String, Object> extend) {
        this.extend = extend;
    }
}

创建FurnController.java , 处理添加请求

@Controller
public class FurnController {

    //注入配置FurnService
    @Resource
    private FurnService furnService;

    /**
     * 解读
     * 1、响应客户端的添加请求
     * 2、@RequestBody: 使用 SpringMVC 的 @RequestBody 将客户端提交的 json 数据,封装成 JavaBean 对象
     * 3、@ResponseBody: 服务器返回的数据格式是按照 json 来返回的(底层是按照http协议进行协商)
     */
    @PostMapping("/save")
    @ResponseBody
    public Msg save(@RequestBody Furn furn) {
            furnService.save(furn);
            return Msg.success();

    }

使用Postman 来完成Controller 层的测试, 通过Postman 添加Furn 数据

使用Postman 测试时,因为我们前台是发送的json 数据,被服务器接收到后,转成javabean 数据,因此pom.xml 需要引入jackson,处理json 数据,

否则后台会报错.Content type 'application/json;charset=UTF-8' not supported

<!-- 引入jackson,处理json 数据-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.4</version>
</dependency>

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

点击添加按钮, 可以出现添加家居的对话框, 修改

SSM-Vue 整合项目\HomeView.vue ,

说明el-dialog 从Dialog 对话框获取, 表单代码从Form 表单获取,组合一下并调整一下即可

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

<!-- 添加家居的弹窗
说明:
1. el-dialog :v-model="dialogVisible" 表示对话框, 和dialogVisible 变量双向
绑定,控制是否显示对话框
2. el-form :model="form" 表示表单,数据和form 数据变量双向绑定
3. el-input v-model="form.name" 表示表单的input 空间,名字为name 需要和
后台Javabean 属性一致
-->
<el-dialog title="提示" v-model="dialogVisible" width="30%">
    <el-form :model="form" label-width="120px">
        <el-form-item label="家居名">
            <el-input v-model="form.name" style="width: 80%"></el-input>
        </el-form-item>
        <el-form-item label="厂商">
            <el-input v-model="form.maker" style="width: 80%"></el-input>
        </el-form-item>
        <el-form-item label="价格">
            <el-input v-model="form.price" style="width: 80%"></el-input>
        </el-form-item>
        <el-form-item label="销量">
            <el-input v-model="form.sales" style="width: 80%"></el-input>
        </el-form-item>
        <el-form-item label="库存">
            <el-input v-model="form.stock" style="width: 80%"></el-input>
        </el-form-item>
    </el-form>
    <template #footer>
        <span class="dialog-footer">
            <el-button @click="dialogVisible = false">取消</el-button>
            <el-button type="primary" @click="save">确定</el-button>
        </span>
    </template>
</el-dialog>
</div>
</template>
//增加数据, 一定要, 否则你会发现,在后面弹出的表单不能输入数据
data() {
    return {
        form: {},
//增加方法
methods: {
    add() {
        this.dialogVisible = true
        this.form = {}
    }
}
//增加点击新增的按钮事件
<div style="margin: 10px 0">
    <el-button type="primary" @click="add">新增</el-button>
    <el-button>其它</el-button>
</div>

完成测试: 看看点击新增按钮,能否正常的弹窗添加家居的对话框(含有表单)

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

项目前端安装axios, 用于发送Ajax 请求给后台, 一定要注意 

 SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

创建工具文件D:\idea_java_projects\ssm_vue\src\utils\request.js , 用于创建axios 

// 引入axios 包
// 重要提示:如果在启动前端项目,提示找不到axios , 把光标放在import axios from 'axios' 的'axios', 会有一个修复提示, 导入axios, 小伙伴点击, 导入即可正常使用
import axios from 'axios'
// 通过axios 创建对象
const request = axios.create({
    timeout: 5000
})
// request 拦截器
// 1. 可以对请求做一些处理
// 2. 比如统一加token,Content-Type 等
request.interceptors.request.use(config => {
    config.headers['Content-Type'] = 'application/json;charset=utf-8';
    return config
}, error => {
    return Promise.reject(error)
});
//导出
export default request

修改HomeView.vue , 在methods 编写save 方法, 并测试会出现跨域问题

<script>
// 引入request 组件
import request from "@/utils/request";
//methods 增加方法.
    save() {
        // =======说明====...
        request.post("http://localhost:10001/save", this.form).then(res => {
            console.log(res)
            this.dialogVisible = false
        })
    }
</script>

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

创建vue.config.js 解决跨域问题, 因为修改了配置文件

npm serve 需要重启, 否则不能识别.

const {defineConfig} = require('@vue/cli-service')
module.exports = defineConfig({
    transpileDependencies: true
})
module.exports = {
    devServer: {
        port: 10000, // 启动端口
        //解读如果我们请的地址 /api/save => 代理到 http://localhost:8080/ssm/save
        proxy: {                    //设置代理,必须填
            '/api': {               //设置拦截器  拦截器格式   斜杠+拦截器名字,名字可以自己定
                target: 'http://localhost:8080/ssm',  //代理的目标地址, 就是/api 代替 http://localhost:10001/
                changeOrigin: true,                 //是否设置同源,输入是的, 浏览器就允许跨域
                pathRewrite: {                      //路径重写
                    '/api': ''                      //选择忽略拦截器里面的单词
                }
            }
        }
    }
}

修改Home.vue, 使用跨域请求, 并完成测试, 查看数据库,是否有新数据添加成功

1. 将form 表单提交给/api/save 的接口

2. /api/save 等价http∶//locaLhost∶10001/save

3. 如果成功,就进入then 方法

4.res 就是返回的信息

5.查看mysql 看看数据是否保存

request.post("/api/save", this.form).then(res => {
        console.log(res)
        this.dialogVisible = false
    })
}

提醒, 这里容易出现的问题

1) 一定要确定request.post("/api/save") 被代理后的url , 是项目后台服务对应提供的API接口url ,  否则报404

2) 当跨域执行时请求,浏览器还是提示http://localhost:5927/api/xxx , 所以不要认为是api没有替换你的配置.

注意事项和细节

1. Postman 测试时, 要指定content-type ,否则会报错415

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

2. 如果需要将提交的json 数据, 封装到对应的Javabean, 需要配置@RequestBody , 否则会报错500

3. 如果需要返回json 数据, 需要在方法上, 配置@ResponseBody , 否则会报错404 


实现功能05-显示家居信息

需求分析/图解

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 思路分析

1. 完成后台代码从dao -> serivce -> controller , 并对每层代码进行测试 2. 完成前台代码, 使用axios 发送http 请求,返回所有家居数据, 将数据绑定显示

代码实现 

修改FurnService.java 和FurnServiceImpl.java, 增加findAll 方法 

 FurnService.java

    //查询所有的家居信息
    public List<Furn> findAll();

 FurnServiceImpl

  @Override
    public List<Furn> findAll() {
        //查看分析FurnMapper.xml 文件
        //传入是null, 表示返回所有的家居信息
        return furnMapper.selectByExample(null);
    }

修改FurnServiceTest.java ,测试findAll.

 @Test
    public void findAll() {

        List<Furn> furns = furnService.findAll();
        for (Furn furn : furns) {
            System.out.println("furn-" + furn);
        }
    }

修改FurnController.java , 处理显示请求, 并使用Postman 完成测试

    @RequestMapping("/furns")
    @ResponseBody
    public Msg listFurns() {

        List<Furn> furnList = furnService.findAll();
        //Msg msg = Msg.success();
        把家居信息,封装到msg对象
        //msg.add("furnList", furnList);
        return Msg.success().add("furnList", furnList);

    }

修改HomeView.vue , 编写list 方法

//修改一下el-table
<el-table : data="tableData" stripe style="width: 100%">
    <el-table-column
        prop="id"
        label="ID"
        sortable
    >
    </el-table-column>
    <el-table-column
        prop="name"
        label="家居名"
    >
    </el-table-column>
    <el-table-column
        prop="maker"
        label="厂家">
    </el-table-column>
    <el-table-column
        prop="price"
        label="价格">
    </el-table-column>
    <el-table-column
        prop="sales"
        label="销量">
    </el-table-column>
    <el-table-column
        prop="stock"
        label="库存">
    </el-table-column>
    <el-table-column fixed="right" label="操作" width="100">
        <template #default="scope">
            <el-button @click="handleEdit(scope.row)" type="text">编辑</el-button>
        <el-button type="text">删除</el-button>
    </template>
</el-table-column>
</el - table >
    //修改一下tableData: []
    data() {
    return {
        form: {},
        dialogVisible: false,
        search: '',
        tableData: []
    }
}
//在created() 调用list() 完成页面数据获取
created() {
    this.list()
}
//编写list() method
list() { //请求显示家居列表-带检索
    request.get("/api/furns").then(res => {
        //绑定tableData, 显示在表格
        this.tableData = res.data.extend.furnsList
    })
}
//在save() 调用后,调用list() 刷新页面
save() {
    // =======说明====...
    request.post("/api/save", this.form).then(res => {
        console.log(res)
        this.dialogVisible = false
        this.list()
    })
}

 完成测试,看看是否可以显示家居列表信息.

 SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

修改src\utils\request.js 增加response 拦截器, 统一处理响应后结果 

//引入axios
import axios from "axios";
//通过axios创建对象-request对象,用于发送请求到后端
const request = axios.create({
    timeout: 5000
})

//request拦截器的处理
//1. 可以对请求做统一的处理
//2. 比如统一的加入token, Content-Type等
request.interceptors.request.use(config => {
    config.headers['Content-Type'] = 'application/json;charset=utf-8'
    return config
}, error => {
    return Promise.reject(error)
})


//response拦截器
//可以在调用接口响应后,统一的处理返回结果
request.interceptors.response.use(
    response => {
        let res = response.data
        //如果返回的是文件,就返回
        if (response.config.responseType === 'blob') {
            return res
        }
        //如果是string, 就转成json对象
        if (typeof res === 'string') {
            //如果res 不为null, 就进行转换成json对象
            res = res ? JSON.parse(res) : res
        }
        return res;
    },
    error => {
        console.log("err", error)
        return Promise.reject(error);
    }
)

//导出request对象, 在其它文件就可以使用
export default request

 修改Home.vue , 简化返回处理

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 完成测试.

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现


实现功能06-修改家居信息 

需求分析/图解 

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

思路分析

1. 完成后台代码从dao -> serivce -> controller , 并对每层代码进行测试 2. 完成前台代码, 回显家居信息,再使用axios 发送http / ajax 请求,更新数据, 将数据绑定显示 

 代码实现

修改FurnService.java接口 和FurnServiceImpl.java, 增加update 方法

修改FurnService.java接口 

    //修改家居
    public void update(Furn furn);

修改FurnServiceImpl.java

    @Override
    public void update(Furn furn) {

        furnMapper.updateByPrimaryKeySelective(furn);
    }

修改FurnServiceTest.java ,测试update

 @Test
    public void update() {

        Furn furn = new Furn();
        furn.setId(1);
        furn.setName("北欧风格小桌子~~");
        furn.setMaker("小猪家居");
        //因为imgPath属性有一个默认值,
        //所以如果我们不希望生成update 语句有对imgPath 字段修改,就显式的设置null

        furn.setImgPath(null);
        furnService.update(furn);

        System.out.println("修改OK");

    }

修改FurnController.java , 处理修改请求, 并使用Postman 完成测试

   @PutMapping("/update")
    @ResponseBody
    public Msg update(@RequestBody Furn furn) {

        furnService.update(furn);
        return Msg.success();

    }

 修改HomeView.vue , 编写handleEdit 方法, 回显数据并测试

handleEdit(row) {
    //说明
    //1. JSON.stringify(row) 将row 转成json 字符串
    //2. JSON.parse(xx) 将字符串转成json 对象
    //3. 为什么这样做? 其实JSON.parse(JSON.stringify(row)) 就是对row 进行了深拷贝
    //4. 这样表格中的行数据和弹出框的数据就是独立的了
    this.form = JSON.parse(JSON.stringify(row))
    this.dialogVisible = true
    }
    //触发handleEdit 方法
    <el-button size="mini" @click="handleEdit(scope.row)" type="primary">编辑</el-button>

可以测试一下, 点击编辑, 回显数据

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

修改HomeView.vue , 修改save 方法,

处理修改请求, 说明更新成功的消息框, 不需要做额外处理, 直接使用this.$message 即可.

save() {
    //增加处理修改逻辑
    if (this.form.id) {
        request.put("/api/update", this.form).then(res => {
            if (res.code === 200) {//如果code 为200
                this.$message({ //弹出更新成功的消息框
                    type: "success",
                    message: "更新成功"
                })
            } else {
                this.$message({//弹出更新失败信息
                    type: "error",
                    message: res.msg
                })
            }
            this.list() //刷新列表
            this.dialogVisible = false
        })
    } else {//添加
        //=======说明======
        //1. 将form 表单提交给/api/save 的接口
        //2. /api/save 等价http://localhost:10001/save
        //3. 如果成功,就进入then 方法
        //4. res 就是返回的信息
        //5. 查看Mysql 看看数据是否保存
        request.post("/api/save", this.form).then(res => {
            this.dialogVisible = false
            this.list()
        })
    }
}

完成测试

浏览器http://localhost:10000


实现功能07-删除家居信息

需求分析/图解

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

思路分析

1. 完成后台代码从dao -> serivce -> controller , 并对每层代码进行测试 2. 完成前台代码,使用axios 发送http Ajax 请求,删除数据, 将数据绑定显示

代码实现

修改FurnService.java 和FurnServiceImpl.java, 增加del 方法

修改FurnService.java接口 

    //删除家居
    public void del(Integer id);

修改FurnServiceImpl.java

    @Override
    public void del(Integer id) {
        furnMapper.deleteByPrimaryKey(id);
    }

修改FurnServiceTest.java ,测试del

    @Test
    public void del() {

        furnService.del(17);
        System.out.println("删除OK");
    }

修改FurnController.java , 处理删除请求, 并使用Postman 完成测试

    @DeleteMapping("/del/{id}")
    @ResponseBody
    public Msg del(@PathVariable Integer id) {
        furnService.del(id);
        return Msg.success();
    }

修改HomeView.vue , 编写handleDel 方法, 完成删除

//处理删除方法
handleDel(id) {
    request.delete("/api/del/" + id).then(res => {
        if (res.code === 200) {
            this.$message({
                type: "success",
                message: "删除成功"
            })
        } else {
            this.$message({
                type: "error",
                message: res.msg
            })
        }
        this.list() // 刷新列表
    })
}
    //响应删除点击
    <template #default="scope">
    <el-button size="mini" @click="handleEdit(scope.row)" type="primary">编辑</el-button>
    <!--增加popcomfirm 控件,确认删除-- >
    <el-popconfirm
        title="确定删除吗?" @confirm="handleDel(scope.row.id)" >
            <template #reference>
                <el-button size="small" type="danger">删除</el-button>
            </template>
    </el-popconfirm>
    </template >

 完成测试测试

 SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

将修改家居信息功能, 回显家居表单数据, 改成从后端-DB 获取 

修改FurnService.java接口 和FurnServiceImpl.java, 增加根据id返回数据

修改FurnService.java接口 

    //根据id返回Furn
    public Furn findById(Integer id);

修改FurnServiceImpl.java

    @Override
    public Furn findById(Integer id) {
        return furnMapper.selectByPrimaryKey(id);
    }

修改FurnServiceTest.java ,处理根据id返回对应的furn对象 

    @Test
    public  void findById(){
        Furn byId = furnService.findById(2);
        System.out.println(byId);
    }

 修改FurnController.java , 处理根据id返回对应的furn对象, 并使用Postman 完成测试

    //提供接口,根据id返回对应的furn对象-封装Msg
    @GetMapping("/find/{id}")
    @ResponseBody
    public Msg findById(@PathVariable Integer id) {
        Furn furn = furnService.findById(id);
        return Msg.success().add("furn", furn);
    }

 修改HomeView.vue , 编写handleEdit 第二种方法, 回显数据并测试 

    handleEdit(row) {
      //console.log("row--", row)

      //将当前的家居信息绑定到弹出对话框的form
      //1. 方式1: 可以通过row.id 到后端-DB去获取对应的家居信息, 返回后将其绑定 this.form[这个是小伙伴可以解决-思考]
      //2. 方式2: 把获取的row的数据通过处理,绑定到this.form 进行显示
      //3. JSON.stringify(row): 将row 转成json字符串
      //4. JSON.parse(JSON.stringify(row)) 将json字符串转成json对象
      //this.form = JSON.parse(JSON.stringify(row))

      //可以通过row.id 到后端-DB去获取对应的家居信息
      request.get("/api/find/" + row.id).then(res => {
        // console.log("家居信息-", res.extend.furn)
        this.form = res.extend.furn
      })

      this.dialogVisible = true
    }

实现功能08-分页显示列表

需求分析/图解

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 思路分析

1. 后台使用MyBatis PageHelper 插件完成分页查询, 前端我们使用分页组件 2. 修改FurnController , 增加处理分页显示代码API/接口 3. 完成前台代码,加入分页导航,并将分页请求和后台接口结合 4.  说明:有了现在的MyBatis PageHelper和前端的分页组件,完成分页就非常的方便,但是底层的分页模型和前面我们的java web原生项目一样

代码实现

1. 修改pom.xml 加入分页插件

<!-- 引入mybatis pageHelper 分页插件-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.1</version>
</dependency>

2. 修改mybatis-config.xml, 配置分页拦截器

<!-- plugins 标签要放在typeAliases 标签后面-->
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!-- 分页合理化,如果pageNum > pages,就让他查询最后一页。
        如果pageNum < 0,就查询第一页-->
        <property name="reasonable" value="true"/>
    </plugin>
</plugins>

3. 修改FurnController.java 增加分页查询处理

 /**
     * 分页请求接口
     *
     * @param pageNum:  要显示第几页 : 默认为1
     * @param pageSize: 每页要显示几条记录:默认为5
     * @return
     */
    @ResponseBody
    @RequestMapping("/furnsByPage")
    public Msg listFurnsByPage(@RequestParam(defaultValue = "1") Integer pageNum,
                               @RequestParam(defaultValue = "5") Integer pageSize) {

        //设置分页参数
        //解读
        //1.调用findAll是完成查询,底层会进行物理分页,而不是逻辑分页
        //2.会根据分页参数来计算 limit ?, ?, 在发出SQL语句时,会带limit
        PageHelper.startPage(pageNum, pageSize);

        List<Furn> furnList = furnService.findAll();


        //将分页查询的结果,封装到PageInfo
        //PageInfo 对象包含了分页的各个信息,比如当前页面pageNum , 共有多少记录
        //...

        PageInfo pageInfo = new PageInfo(furnList, pageSize);
        //将pageInfo封装到Msg对象,返回
        return Msg.success().add("pageInfo", pageInfo);
    }

修改FurnServiceTest.java ,测试分页查询是否OK 

    @Test
    public  void findById(){
        Furn byId = furnService.findById(2);
        System.out.println(byId);
    }

使用Postman 进行测试,看看分页查询是否OK 

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

修改HomeView.vue , 完成分页导航显示、分页请求 

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

增加element-plus 分页控件 

//增加element-plus 分页控件
<div style="margin: 10px 0">
    <el-pagination
@size-change="handlePageSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="[5,10]"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"

:total="total">
</el-pagination>
</div >
</div >
</template >
    //增加分页初始化数据
    data() {
    return {
        currentPage: 1,
        pageSize: 5,
        total: 10,
        //修改list(), 换成分页请求数据
        list() { //请求显示家居列表-不带检索
            request.get("/api/furnsByPage", {
                params: {
                    pageNum: this.currentPage,
                    pageSize: this.pageSize

                }
            }).then(res => {
                //绑定tableData, 显示在表格
                this.tableData = res.extend.pageInfo.list
                this.total = res.extend.pageInfo.total
            })
        }
//增加方法, 处理记录的变化, 这两个方法是和分页控件绑定的.
//处理每页显示多少条记录变化
handlePageSizeChange(pageSize) {
            this.pageSize = pageSize
            this.list()
        }
        ,
        //处理当前页变化, 比如点击分页连接,或者go to 第几页
        handleCurrentChange(pageNum) {
            this.currentPage = pageNum
            this.list()
        }

完成测试

启动项目后台服务furns_ssm 启动项目前台ssm_vue 浏览器: http://localhost:10000/

分页显示效果

● 测试分页显示效果, 浏览器: http://localhost:10000/

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现


实现功能09-带条件查询分页显示列表

需求分析/图解 SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 思路分析

1. 完成后台代码从dao -> serivce -> controller , 并对每层代码进行测试 2. 完成前台代码,使用axios 发送http 请求,完成带条件查询分页显示

代码实现

修改FurnService.java 和FurnServiceImpl.java , 增加条件查询

修改FurnService.java接口 

    //根据家居名称进行查询
    public List<Furn> findByCondition(String name);

修改FurnServiceImpl.java

 @Override
    public List<Furn> findByCondition(String name) {

        FurnExample furnExample = new FurnExample();
        //通过Criteria 对象可以设置查询条件
        FurnExample.Criteria criteria = furnExample.createCriteria();

        //判断name是有具体的内容
        if (StringUtils.hasText(name)) {
            criteria.andNameLike("%" + name + "%");
        }
        //说明:如果name没有传值null ,"", "   ", 依然是查询所有的记录
        return furnMapper.selectByExample(furnExample);
    }

修改FurnController.java , 处理带条件分页查询 

 /**
     * 根据家居名进行分页查询-条件
     *
     * @param pageNum
     * @param pageSize
     * @return
     */
    @ResponseBody
    @RequestMapping("/furnsByConditionPage")
    public Msg listFurnsByConditionPage(@RequestParam(defaultValue = "1") Integer pageNum,
                                        @RequestParam(defaultValue = "5") Integer pageSize,
                                        @RequestParam(defaultValue = "") String search) {

        PageHelper.startPage(pageNum, pageSize);
        List<Furn> furnList = furnService.findByCondition(search);

        PageInfo pageInfo = new PageInfo(furnList, pageSize);

        //将pageInfo封装到Msg对象,返回
        return Msg.success().add("pageInfo", pageInfo);
    }
    @Test
    public void findByCondition() {

        List<Furn> furns = furnService.findByCondition("风格");

        for (Furn furn : furns) {
            System.out.println("furn--" + furn);
        }

    }

修改FurnServiceTest.java ,测试条件分页查询是否OK  

    @Test
    public void findByCondition() {

        List<Furn> furns = furnService.findByCondition("风格");

        for (Furn furn : furns) {
            System.out.println("furn--" + furn);
        }
    }

 使用Postman 测试,是否通过

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

修改HomeView.vue , 完成带条件分页查询

========增加搜索区========== 

< !--功能区域-->
    <div style="margin: 10px 0">
        <i class="el-icon-add-location"></i>
        <el-button type="primary" @click="add">新增</el-button>
</div>

< !--搜索区域-->
    <div style="margin: 10px 0">
        <el-input v-model="search" placeholder=" 请输入关键字" style="width: 20%"
            clearable></el-input>
        <el-button type="primary" style="margin-left: 5px" @click="list">检索</el-button>
</div>

 ===========在数据池,增加search 变量=====

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 ==========修改list 方法,请求带条件分页的API 接口===

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 测试分页条件查询

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现


 实现功能10-添加家居表单前端校验

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

说明: 参考element-plus 表单验证

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

思路分析

1. 完成前台代码,使用ElementPlus 的表单rules 验证即可 2. 参考ElementPlus 的表单验证文档 

代码实现

修改HomeView.vue , 增加表单验证处理代码

==========增加对表单各个字段的校验规则=========

tableData: [],
    rules: {
    name: [
        { required: true, message: '请输入称家居名', trigger: 'blur' }
    ],
        maker: [
            { required: true, message: '请输入称制造商', trigger: 'blur' }
        ],
            price: [
                { required: true, message: '请输入价格', trigger: 'blur' },
                { pattern: /^(([1-9]\d*)|(0))(\.\d+)?$/, message: '请输入数字', trigger: 'blur' }
            ],
                sales: [
                    { required: true, message: '请输入销量', trigger: 'blur' },
                    { pattern: /^(([1-9]\d*)|(0))$/, message: '请输入数字', trigger: 'blur' }
                ],
                    stock: [
                        { required: true, message: '请输入库存', trigger: 'blur' },
                { pattern: /^(([1-9]\d*)|(0))$/, message: '请输入数字', trigger: 'blur' }
                    ]
}

==========指定将创建的规则应用到form 表单, 注意名称要对应========= 添加家居的弹窗 说明: 1. el-dialog :v-model="dialogVisible" 表示对话框, 和dialogVisible 变量双向绑定,控制是否显示对话框

2. el-form :model="form" 表示表单,数据和form 数据变量双向绑定

3. el-input v-model="form.name" 表示表单的input 空间, 名字为name 需要和后台Javabean 属性一致

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

测试

就可以看到验证规则生效了【是光标离开输出框时,出现校验效果,因为是trigger:'blur' 事件】, 但是用户提交还是能成. 

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

修改Homeview.vue 当表单验证不通过时,不提交表单 

========修改save()===========

save() {
    //增加处理修改逻辑
    if (this.form.id) {
        request.put("/api/update", this.form).then(res => {
            if (res.code === 200) {//如果code 为200
                this.$message({ //弹出更新成功的消息框
                    type: "success",
                    message: "更新成功"
                })
            } else {
                this.$message({//弹出更新失败信息
                    type: "error",
                    message: res.msg
                })
            }
            this.list() //刷新列表
            this.dialogVisible = false
        })
    } else {//添加
        //表单数据校验是否
        this.$refs['form'].validate((valid) => {
            if (valid) {
                //=======说明======
                //1. 将form 表单提交给/api/save 的接口
                //2. /api/save 等价http://localhost:10001/save
                //3. 如果成功,就进入then 方法
                //4. res 就是返回的信息
                //5. 查看Mysql 看看数据是否保存
                request.post("/api/save", this.form).then(res => {
                    this.dialogVisible = false
                    this.list()
                })
            } else {
                this.$message({//弹出更新失败信息
                    type: "error",
                    message: "验证失败,不提交"
                })
                return false
            }
        })
    }
}

===========修改add()============

add() {
    this.dialogVisible = true
    this.form = {}
    this.$refs['form'].resetFields()//将添加验证提示消息,清空
}

完成测试

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现


 实现功能11-添加家居表单后端校验

 需求分析/图解

1. 为什么前端校验了,后端还需要校验?-看使用Postman 添加数据, 破前端校验机制... 

 SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

 2. 后端校验-需求分析, 当后端校验没有通过,会出现灰色框提示, 后台不真正入库数据

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

思路分析

1. 后台使用JSR303 数据校验,引入hibernate-validator.jar ,在SpringMVC的博客有详细的 链接  2. 前台使用ElementPlus 进行数据绑定,并显示错误信息 

代码实现

1. 修改pom.xml 引入hibernate-validator jar 文件 

<!-- JSR303 数据校验支持 引入hibernate-validator-->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.0.Final</version>
</dependency>

 2. 修改Furn.java , 使用hibernate-validator

package com.wyxdu.furn.bean;

import org.hibernate.validator.constraints.Range;
import org.springframework.util.StringUtils;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;

public class Furn {
    private Integer id;

    @NotEmpty(message = "请输入家居名")
    private String name;

    @NotEmpty(message = "请输入制造厂商")
    private String maker;

    @NotNull(message = "请输入数字")
    @Range(min = 0, message = "价格不能小于0")
    private BigDecimal price;

    @NotNull(message = "请输入数字")
    @Range(min = 0, message = "销量不能小于0")
    private Integer sales;

    @NotNull(message = "请输入数字")
    @Range(min = 0, message = "库存不能小于0")
    private Integer stock;

    //说明: 修改Furn.java ,
    // 当创建Furn对象 imgPath 为null时, imgPath 给默认值(默认图片路径)
    private String imgPath = "assets/images/product-image/1.jpg";


    //增加一个全参构造器

    public Furn(Integer id, String name, String maker, BigDecimal price, Integer sales, Integer stock, String imgPath) {
        this.id = id;
        this.name = name;
        this.maker = maker;
        this.price = price;
        this.sales = sales;
        this.stock = stock;
        //解读
        //如果imgPath 不为null ,而且是有数据,就设置给 this.imgPath,否则就使用默认值
        //imgPath != null && !imgPath.equals("") =>使用一个工具类方法完成
        /**
         * public static boolean hasText(@Nullable String str) {
         *         return str != null && !str.isEmpty() && containsText(str);
         *     }
         */
        //StringUtils.hasText(imgPath) 就是要求imgPath 不是 null ,而且不是"", 而且不是"     "
        //该方法后面小伙伴会常常使用
        if (StringUtils.hasText(imgPath)) {
            this.imgPath = imgPath;
        }
    }

    //声明无参构造器
    public Furn() {
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }

    public String getMaker() {
        return maker;
    }

    public void setMaker(String maker) {
        this.maker = maker == null ? null : maker.trim();
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public Integer getSales() {
        return sales;
    }

    public void setSales(Integer sales) {
        this.sales = sales;
    }

    public Integer getStock() {
        return stock;
    }

    public void setStock(Integer stock) {
        this.stock = stock;
    }

    public String getImgPath() {
        return imgPath;
    }

    public void setImgPath(String imgPath) {
        this.imgPath = imgPath == null ? null : imgPath.trim();
    }

    @Override
    public String toString() {
        return "Furn{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", maker='" + maker + '\'' +
                ", price=" + price +
                ", sales=" + sales +
                ", stock=" + stock +
                ", imgPath='" + imgPath + '\'' +
                '}';
    }
}

 3. 修改FurnController.java , 对save 方法进行完善  

   @PostMapping("/save")
    @ResponseBody
    public Msg save(@Validated @RequestBody Furn furn, Errors errors) {

        Map<String, Object> map = new HashMap<>();

        List<FieldError> fieldErrors = errors.getFieldErrors();
        for (FieldError fieldError : fieldErrors) {
            map.put(fieldError.getField(), fieldError.getDefaultMessage());
        }

        if (map.isEmpty()) {//说明后端校验通过,因为没有发现校验错误
            furnService.save(furn);
            //返回成功msg
            return Msg.success();
        } else {
            //校验失败,把校验错误信息封装到Msg对象,并返回
            return Msg.fail().add("errorMsg", map);
        }

    }

4. 修改HomeView.vue , 显示服务器校验返回的提示信息

===========在数据池,增加显示错误信息变量========

data() {
    return {
    //存放错误信息
    serverValidErrors: {},

================修改save()方法,显示错误提示============

save() {
    //增加处理修改逻辑
    if (this.form.id) {
        request.put("/api/update", this.form).then(res => {
            if (res.code === 200) {//如果code 为200
                this.$message({ //弹出更新成功的消息框
                    type: "success",
                    message: "更新成功"
                })
            } else {
                this.$message({//弹出更新失败信息
                    type: "error",
                    message: res.msg
                })
            }
            this.list() //刷新列表
            this.dialogVisible = false
        })
    } else {//添加
        //表单数据校验是否
        this.$refs['form'].validate((valid) => {
            if (valid) {
                //=======说明======
                //1. 将form 表单提交给/api/save 的接口
                //2. /api/save 等价http://localhost:10001/save
                //3. 如果成功,就进入then 方法
                //4. res 就是返回的信息
                //5. 查看Mysql 看看数据是否保存
                request.post("/api/save", this.form).then(res => {
                    if (res.code === 200) {
                        this.dialogVisible = false
                        this.list()
                    } else if (res.code === 400) {
                        this.serverValidErrors.name = res.extend.errorMsg.name;
                        this.serverValidErrors.sales = res.extend.errorMsg.sales;
                        this.serverValidErrors.price = res.extend.errorMsg.price;
                        this.serverValidErrors.maker = res.extend.errorMsg.maker;
                        this.serverValidErrors.stock = res.extend.errorMsg.stock;
                    }
                })
            } else {
                this.$message({//弹出更新失败信息
                    type: "error",
                    message: "验证失败,不提交"
                })
                return false
            }
        })
    }
}

==========修改add()方法,清空错误信息=========

add() {
    this.dialogVisible = true
    this.form = {}
    this.$refs['form'].resetFields()//将上传验证消息,清空
    this.serverValidErrors = {}
    },

========修改对话框,显示后台返回的校验错误信息========

<!--添加家居的弹窗
说明:
1. el-dialog :v-model="dialogVisible" 表示对话框, 和dialogVisible 变量双向绑定,控制是否
显示对话框
2. el-form :model="form" 表示表单,数据和form 数据变量双向绑定
3. el-input v-model="form.name" 表示表单的input 空间,名字为name 需要和后台Javabean
属性一致
-->
<el-dialog title="提示" v-model="dialogVisible" width="30%">
    <el-form :model="form" :rules="rules" ref="form" label-width="120px">
        <el-form-item label="家居名" prop="name">
            <el-input v-model="form.name" style="width: 60%"></el-input>
            {{ serverValidErrors.name }}
        </el-form-item>
        <el-form-item label="厂商" prop="maker">
            <el-input v-model="form.maker" style="width: 60%"></el-input>
            {{ serverValidErrors.maker }}
        </el-form-item>
        <el-form-item label="价格" prop="price">
            <el-input v-model="form.price" style="width: 60%"></el-input>
            {{ serverValidErrors.price }}
        </el-form-item>
        <el-form-item label="销量" prop="sales">
            <el-input v-model="form.sales" style="width: 60%"></el-input>
            {{ serverValidErrors.sales }}
        </el-form-item>
        <el-form-item label="库存" prop="stock">
            <el-input v-model="form.stock" style="width: 60%"></el-input>
            {{ serverValidErrors.stock }}
        </el-form-item>
    </el-form>
    <template #footer>
        <span class="dialog-footer">
            <el-button @click="dialogVisible = false">取消</el-button>
            <el-button type="primary" @click="save">确定</el-button>
        </span>
    </template>
</el-dialog>

完成测试: 添加家居表单后端校验

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

2、这时, 后台返回添加失败的提示信息 

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

启动项目前台ssm_vue 

浏览器: http://localhost:10000/

测试页面效果 

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

测试完毕后, 记得恢复valid 的正确写法 

本项目就已经全部完成

转载自:https://juejin.cn/post/7241161381981716539
评论
请登录