SpringBoot+Vue项目实战之前后端开发实现增删改查
场景:公司要开发一个新的项目,但是我们的前端就一个,还要忙着维护处理其他的项目,但是后端人员比较多,所以就要求后台管理系统的页面由后端人员开发,实在不会的找前端协助,这就没办法了,只能自己上了!
前言:登录页面实现好后,这次实现和后端的交互,实现我们经常使用的增删改查,其实就是简单的实现发送请求调用后端编写好的接口,再根据返回的结果动态渲染页面。本次代码有点多,粘贴主要部分,需要的可在文章末尾下载项目
前端项目
先看下这次实现主要用到的页面
接下来就是粘贴主要代码
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,操作更方便哦
评论