功能实现02
后端:https://github.com/liyuelian/furniture-back-end.git
前端:https://github.com/liyuelian/furniture-front-end.git
3.功能03-添加家居信息
3.1需求分析
浏览器页面点击添加按钮,弹出提示框,填写家居信息,点击确定,可以把数据添加到数据库中。
3.2思路分析
- 完成后台代码 dao->service->controller,并对每层代码进行测试,到controller层使用postman发送http post请求完成测试
- 完成前端代码,使用axios 发送ajax请求(json数据)给后台,实现添加家居信息
3.3代码实现
后端项目使用的是 ssm 框架,src 下分为 bean,dao,service,controller,utils层,其中 controller 层由springmvc 接管,service 层由 spring 接管,dao 层由 mybatis 接管。
相比于传统的 Javaweb 项目,它的三层结构并没有发生根本变化,仅仅是框架化了,各组件由框架接管。原本的 jsp 则页面变成了 vue 前端项目。
3.3.1后端代码
由于使用了逆向工程,bean 层、dao 层以及dao层接口对应的mapper映射文件已经生成,因此暂时不必在这两层编写代码了。
(1)Service层,创建对应的接口和实现类
FurnService.java(接口)- package com.li.furn.service;
- import com.li.furn.bean.Furn;
- /**
- * @author 李
- * @version 1.0
- */
- public interface FurnService {
- //添加
- public void save(Furn furn);
- }
复制代码 FurnServiceImpl.java(实现类)- package com.li.furn.service.impl;
- import com.li.furn.bean.Furn;
- import com.li.furn.dao.FurnMapper;
- import com.li.furn.service.FurnService;
- import org.springframework.stereotype.Service;
- import javax.annotation.Resource;
- /**
- * @author 李
- * @version 1.0
- */
- @Service //注入spring容器
- public class FurnServiceImpl implements FurnService {
- //自动装配 FurnMapper接口对象(代理对象)
- @Resource
- private FurnMapper furnMapper;
- //已经在spring配置文件中开启事务
- @Override
- public void save(Furn furn) {
- furnMapper.insertSelective(furn);
- }
- }
复制代码 测试代码:- package com.li.furn.test.service;
- import com.li.furn.bean.Furn;
- import com.li.furn.service.FurnService;
- import org.junit.Before;
- import org.junit.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import java.math.BigDecimal;
- /**
- * @author 李
- * @version 1.0
- */
- public class FurnServiceTest {
- //spring容器
- private ApplicationContext ioc;
- //从spring容器中获取的是FurnService接口的代理对象
- private FurnService furnService;
- @Before
- public void init() {
- ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
- //通过FurnService.class类型获取FurnService接口对象的代理对象
- furnService = ioc.getBean(FurnService.class);
- }
- @Test
- public void FurnServiceTest() {
- //添加数据
- Furn furn = new Furn(null, "复古沙发", "森林之家",
- new BigDecimal(1088), 12, 28,
- "/assets/images/product-image/7.jpg");
- furnService.save(furn);
- System.out.println("添加成功");
- //关闭sqlSession的动作底层会自动释放
- }
- }
复制代码 测试成功:
 (2)关于家居图片路径
给新增的家居增加一个默认图片的路径值,修改Furn.java(部分代码):- //默认图片路径
- 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 && !imgPath.equals("")
- // =>使用StringUtils.hasText()代替,该方法要求传入的字符串不是null,并且不是"",并且不能全为空格
- if (StringUtils.hasText(imgPath)) {
- this.imgPath = imgPath;
- }
- }
复制代码 (3)bean层创建Msg.java,用来返回给前端 Json 数据的通用类,本质就是一个”协议“
 - package com.li.furn.bean;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * @author 李
- * @version 1.0
- * 用来返回给前端Json数据的通用类
- */
- 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;//返回的是当前Msg对象
- }
- //省略setter,getter方法
- }
复制代码 (4)创建FurnController.java,处理添加家居请求- package com.li.furn.controller;
- import com.li.furn.bean.Furn;
- import com.li.furn.bean.Msg;
- import com.li.furn.service.FurnService;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.ResponseBody;
- import javax.annotation.Resource;
- /**
- * @author 李
- * @version 1.0
- */
- @Controller//由springmvc来处理
- public class FurnController {
- @Resource
- private FurnService furnService;
- /**
- * 1.响应客户端添加家居的请求
- * 2.@RequestBody 注解将客户端提交的json数据封装成 Javabean 对象。
- * 3.@ResponseBody 服务器返回的数据是按照json来返回的(底层是按照 http协议进行协商)
- *
- * @param furn
- * @return
- */
- @ResponseBody
- @PostMapping("/save")
- public Msg save(@RequestBody Furn furn) {
- furnService.save(furn);
- //如果没有出现异常,就返回成功
- Msg success = Msg.success();
- return success;
- }
- }
复制代码 (5)Postman对Controller层进行测试
使用postman测试时,因为我们前台发送的是json数据,被服务器接收到后,转成Javabean数据,因此pom.xml需要引入jackson,处理json数据,否则后台会报错。- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.12.4</version>
- </dependency>
复制代码 请求结果:
 
3.3.2前端代码
(1)修改HomeView.vue页面,代码略。- <template>
-
-
-
- <el-button type="primary" @click="add">新增</el-button>
- <el-button>其他</el-button>
-
-
- <el-input v-model="search" placeholder="请输入关键字"/>
- <el-button type="primary">查找</el-button>
-
-
- ...
-
- <el-dialog title="提示" v-model="dialogVisible" width="40%">
- <el-form :model="form" label-width="120px">
- <el-form-item label="家居名">
- <el-input v-model="form.name" ></el-input>
- ...
- ...
- </el-form>
- <template #footer>
-
- <el-button @click="dialogVisible=false">取 消</el-button>
- <el-button type="primary" @click="save">确 定</el-button>
-
- </template>
- </el-dialog>
-
- </template>
复制代码 效果如下:
(2)安装axios,用于发送ajax请求给后台
(3)在前端项目的src目录下创建utlis目录,utils目录下创建工具文件request.js,用于创建axios request对象,发送ajax请求。- //引入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)
- })
- //导出request对象,在其他文件引入即可使用
- export default request;
复制代码 如果启动前端项目,提示找不到axios,需要把光标放在import axios from ‘axios’ 的提示上,会有一个修复提示,点击导入axios即可。
(4)修改HomeView.vue,在methods编写save方法,并测试。- ...
- save() {//将填写的表单数据发送给后端
- //第一个参数为url,第二个参数是请求携带的数据
- request.post('http://localhost:8080/save', this.form).then(res => {
- console.log("res-", res)
- this.dialogVisible = false;//隐藏表单
- })
- }
- ...
复制代码 测试向后端项目发送请求,因为前后端的服务ip不一致,会出现跨域问题,浏览器会阻止访问:
(5)在项目目录下的vue.config.js,解决跨域问题- ...
- module.exports = {
- devServer: {
- port: 10001,//启动端口
- proxy: {//设置代理,必须填
- '/api': {//设置拦截器 拦截器格式
- target: 'http://localhost:8080/',//代理的目标地址,就是/api代替的地址
- changeOrigin: true,//是否设置同源,如果为true,就允许跨域
- pathRewrite: {//路径重写
- '/api': ''//选择忽略拦截器里面的单词
- }
- }
- }
- }
- }
复制代码 因为修改了配置文件,npm serve 需要重启,否则不能识别。
再次测试,成功发送数据:
3.4注意事项和细节
- 一定要确定request.post("/api/save")被代理后的url是项目后台服务对应提供的api接口url,否则报404
- postman测试时,要指定content-type,否则会出错(415错误)
- 如果后端需要将json提交的数据封装到对应的Javabean中,需要配置@RequestBody,否则会报错500
- 如果后端需要返回json数据,需要在方法上配置@ResponseBody,否则会报错404
4.功能04-显示家居信息
4.1需求分析
在页面中展示数据库的家居信息。
4.2思路分析
- 完成后台代码从dao-service-controller,并对每层代码进行测试
- 完成前台代码,使用axios发送http请求,返回所有家居数据,将数据绑定展示
4.3代码实现
4.3.1后端代码
分层完成,由于使用了逆向工程,bean 层、dao 层以及dao层接口对应的mapper映射文件已经生成,因此暂时不必在这两层编写代码了。
(1)service层,修改FurnService.java和FurnServiceImpl.java,增加findAll()方法。(展示不考虑分页问题)
FurnService.java:- //查询所有的家居信息
- public List<Furn> findAll();
复制代码 FurnServiceImpl.java:- @Override
- public List<Furn> findAll() {
- //如果传入为null表示返回所有的家居信息
- return furnMapper.selectByExample(null);
- }
复制代码 (2)controller层,FurnController.java 处理现实家居的请求- @RequestMapping("/furns")
- @ResponseBody
- public Msg listFurns() {
- List<Furn> furnList = furnService.findAll();
- //将数据封装到 Meg对象中返回
- Msg msg = Msg.success();
- msg.add("furnList", furnList);
- return msg;
- }
复制代码 (3)postman测试成功
 4.3.2前端代码
(1)修改src/utils/request.js,增加response拦截器,统一处理响应后的结果- //response拦截器,可以在调用接口响应后,统一的处理返回结果
- request.interceptors.response.use(
- response => {
- let res = response.data;
- //如果返回的是文件
- if (response.config.responseType === 'blob') {
- return res;
- }
- //如果返回的是string,就转成json对象
- if (typeof res === 'string') {
- //如果不为空,就转成json对象
- res = res ? JSON.parse(res) : res;
- }
- return res;
- }, error => {
- //如果失败
- console.log("err=", error);
- return Promise.reject(error);
- })
复制代码 (2)修改HomeView.vue,当现实页面之前就发出请求,然后将接收的数据显示到页面上- <template>
-
- ...
-
- <el-table :data="tableData" stripe >
- <el-table-column prop="id" label="ID" sortable></el-table-column>
- <el-table-column prop="name" label="家居名"></el-table-column>
- ...
- ...
- <el-table-column fixed="right" label="操作" width="100">
- <template #default="scope">
- <el-button link type="primary" size="small"
- @click="handleEdit(scope.row)">编辑
- </el-button>
- <el-button link type="primary" size="small">删除</el-button>
- </template>
- </el-table-column>
- </el-table>
- ...
-
- </template>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |