SpringBoot+Vue项目实战之前后端开发实现增删改查

共 12091字,需浏览 25分钟

 ·

2021-03-09 16:12

场景:公司要开发一个新的项目,但是我们的前端就一个,还要忙着维护处理其他的项目,但是后端人员比较多,所以就要求后台管理系统的页面由后端人员开发,实在不会的找前端协助,这就没办法了,只能自己上了!

前言:登录页面实现好后,这次实现和后端的交互,实现我们经常使用的增删改查,其实就是简单的实现发送请求调用后端编写好的接口,再根据返回的结果动态渲染页面。本次代码有点多,粘贴主要部分,需要的可在文章末尾下载项目

前端项目

先看下这次实现主要用到的页面



接下来就是粘贴主要代码

EditForm.vue

<template>
<div>
<i class="el-icon-circle-plus-outline" @click="dialogFormVisible = true"></i>
<el-dialog
title="添加/修改图书"
:visible.sync="dialogFormVisible"
@close="clear">

<el-form v-model="form" style="text-align: left" ref="dataForm">
<el-form-item label="书名" :label-width="formLabelWidth" prop="title">
<el-input v-model="form.title" autocomplete="off" placeholder="不加《》"></el-input>
</el-form-item>
<el-form-item label="作者" :label-width="formLabelWidth" prop="author">
<el-input v-model="form.author" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="出版日期" :label-width="formLabelWidth" prop="date">
<el-input v-model="form.date" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="出版社" :label-width="formLabelWidth" prop="press">
<el-input v-model="form.press" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="封面" :label-width="formLabelWidth" prop="cover">
<el-input v-model="form.cover" autocomplete="off" placeholder="图片 URL"></el-input>
<img-upload @onUpload="uploadImg" ref="imgUpload"></img-upload>
</el-form-item>
<el-form-item label="简介" :label-width="formLabelWidth" prop="abs">
<el-input type="textarea" v-model="form.abs" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="分类" :label-width="formLabelWidth" prop="cid">
<el-select v-model="form.category.id" placeholder="请选择分类">
<el-option label="文学" value="1"></el-option>
<el-option label="流行" value="2"></el-option>
<el-option label="文化" value="3"></el-option>
<el-option label="生活" value="4"></el-option>
<el-option label="经管" value="5"></el-option>
<el-option label="科技" value="6"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="id" style="height: 0">
<el-input type="hidden" v-model="form.id" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="onSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
</template>

<script>
import ImgUpload from '../upload/ImgUpload'
export default {
name: 'EditForm',
components: {ImgUpload},
data () {
return {
dialogFormVisible: false,
form: {
id: '',
title: '',
author: '',
date: '',
press: '',
cover: '',
abs: '',
category: {
id: '',
name: ''
}
},
formLabelWidth: '120px'
}
},
methods: {
clear () {
this.form = {
id: '',
title: '',
author: '',
date: '',
press: '',
cover: '',
abs: '',
category: ''
}
},
onSubmit () {
this.$axios
.post('/books', {
id: this.form.id,
cover: this.form.cover,
title: this.form.title,
author: this.form.author,
date: this.form.date,
press: this.form.press,
abs: this.form.abs,
category: this.form.category
}).then(resp => {
if (resp && resp.status === 200) {
this.dialogFormVisible = false
this.$emit('onSubmit')
}
})
},
uploadImg () {
this.form.cover = this.$refs.imgUpload.url
}
}
}
</script>

<style scoped>
.el-icon-circle-plus-outline {
margin: 50px 0 0 20px;
font-size: 100px;
float: left;
cursor: pointer;
}
</style>

LibraryIndex.vue

<template>
<el-container>
<el-aside style="width: 200px;margin-top: 20px">
<switch></switch>
<SideMenu @indexSelect="listByCategory" ref="sideMenu"></SideMenu>
</el-aside>
<el-main>
<books class="books-area" ref="booksArea"></books>
</el-main>
</el-container>
</template>

<script>
import SideMenu from './SideMenu'
import Books from './Books'
export default {
name: "LibraryIndex",
components: {SideMenu,Books},
methods: {
listByCategory () {
var _this = this
var cid = this.$refs.sideMenu.cid
var url = 'categories/' + cid + '/books'
this.$axios.get(url).then(resp => {
if (resp && resp.status === 200) {
_this.$refs.booksArea.books = resp.data
}
})
}
}
}
</script>

<style scoped>
.books-area {
width: 990px;
margin-left: auto;
margin-right: auto;
}
</style>

后端

LibraryController

package org.jeemp.api.controller;

import org.jeemp.api.pojo.Book;
import org.jeemp.api.service.BookService;
import org.jeemp.api.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
* @author JackRen
* @date 2021-03-07 17:17
* @description:
*/

@RestController
public class LibraryController {

@Autowired
BookService bookService;

@GetMapping("/api/books")
public List<Book> list() throws Exception {
return bookService.list();
}

@PostMapping("/api/books")
public Book addOrUpdate(@RequestBody Book book) throws Exception {
bookService.addOrUpdate(book);
return book;
}

@PostMapping("/api/delete")
public void delete(@RequestBody Book book) throws Exception {
bookService.deleteById(book.getId());
}

@GetMapping("/api/categories/{cid}/books")
public List<Book> listByCategory(@PathVariable("cid") int cid) throws Exception {
if (0 != cid) {
return bookService.listByCategory(cid);
} else {
return list();
}
}

@GetMapping("/api/search")
public List<Book> searchResult(@RequestParam("keywords") String keywords) {
// 关键词为空时查询出所有书籍
if ("".equals(keywords)) {
return bookService.list();
} else {
return bookService.Search(keywords);
}
}


}

FastDfsController

package org.jeemp.api.controller;

import org.apache.commons.io.IOUtils;
import org.jeemp.api.util.FastDfsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.logging.Logger;

/**
* @author JackRen
* @date 2021-02-05 16:26
* @description:
*/

@RestController
@RequestMapping("/fastDfs")
public class FastDfsController {

private static Logger logger = Logger.getLogger("FastDfsController");

@Autowired
private FastDfsUtil fastDfsUtil;

@PostMapping("/upload")
public String uploadFile(MultipartFile file) throws IOException {
String s = fastDfsUtil.uploadFile(file);
String resAccessUrl = fastDfsUtil.getResAccessUrl(s);
System.out.println(resAccessUrl);
return resAccessUrl;
}

@GetMapping("/download")
public void downloadFile(String filePath, HttpServletResponse response) throws IOException {
byte[] bytes = fastDfsUtil.downloadFile(filePath);
String fileName = "哈哈.jpg";
response.setContentType("application/force-download");// 设置强制下载不打开
//方式一
// fileName=new String(fileName.getBytes(), "ISO8859-1")
//方式二
fileName = URLEncoder.encode(fileName, "utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
IOUtils.write(bytes, response.getOutputStream());
}

/**
* 流媒体的方式播放视频,只能从头看到尾,不能手动点击重新看已经看过的内容
* @param filePath
* @param response
* @throws IOException
*/

@GetMapping("/play")
public void streamMedia(String filePath, HttpServletResponse response) throws IOException {
byte[] bytes = fastDfsUtil.downloadFile(filePath);
IOUtils.copy(new ByteArrayInputStream(bytes), response.getOutputStream());
response.flushBuffer();
}

@GetMapping("/delete")
public void deleteFile(String filePath) {
Boolean result = fastDfsUtil.deleteFile(filePath);
}

}

项目启动后会出现跨域请求问题,加上下面的类:

CorsConfig

package org.jeemp.api.config;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* @author JackRen
* @date 2021/3/7
* 解决跨域问题
**/

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsConfig implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
//允许所有的域访问
response.setHeader("Access-Control-Allow-Origin", "*");
//允许所有方式的请求
response.setHeader("Access-Control-Allow-Methods", "*");
//头信息缓存有效时长(如果不设 Chromium 同时规定了一个默认值 5 秒),没有缓存将已OPTIONS进行预请求
response.setHeader("Access-Control-Max-Age", "3600");
//允许的头信息
response.setHeader("Access-Control-Allow-Headers", "*");

response.setStatus(HttpServletResponse.SC_OK);

if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(request,response);
}


}

@Override
public void destroy() {

}
}

测试




项目下载地址

链接:https://pan.baidu.com/s/1VtsiBvkNpicODIHbS_sRIw 
提取码:2gby
复制这段内容后打开百度网盘手机App,操作更方便哦


浏览 83
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报