前言
SpringBoot+Vue是一款常见且适用性很强的组合,今天我们将会结合两者的优势,实现一个功能简单但很实用的公告功能。
前置知识介绍
在阅读本篇文章之前,您需要具备以下知识和技能:
- 熟悉SpringBoot框架;
- 熟悉Vue框架;
- 熟悉前后端交互过程;
- 了解axios库的使用;
- 熟悉HTML/CSS/JavaScript。
项目概述
项目的主要功能是实现一个公告展示页面,管理员可以在后台发布公告,前台用户可以浏览公告内容。具体实现包括后端的公告管理模块和前端的公告展示模块。
后端实现
创建SpringBoot项目
首先,我们需要新建一个SpringBoot项目,可以使用SpringBoot官方提供的脚手架工具——Spring Initializr来创建项目。在脚手架页面中,选择需要的依赖项,例如MySQL、Spring Web和MyBatis等,可以根据自己的需要来选择。完成创建后,可以打开主类文件进行简单配置:
@SpringBootApplication
@MapperScan("com.example.demo.mapper") // mapper类扫描路径
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
数据库表设计
本项目需要的数据库表只有一张,用于存放公告的信息。表的结构如下:
CREATE TABLE `notice` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` varchar(255) NOT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
其中,id为自增长主键,content为公告内容,create_time为公告发布时间。
DAO层实现
DAO(Data Access Object)即数据访问层,是作为数据访问的桥梁,与数据库进行交互。在我们这个项目中,需要通过DAO层来做增删改查等操作。
我们可以使用MyBatis框架来编写DAO层代码。具体实现过程如下:
首先,需要在resources目录下新建mapper文件夹,并在该文件夹下新建NoticeMapper.xml文件,该文件用于存放SQL语句。在该文件中,新建对照表结构的SQL语句,例如:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.NoticeMapper">
<select id="findAll" resultType="Notice">
select * from notice
</select>
<delete id="deleteById" parameterType="int">
delete from notice where id = #{id}
</delete>
<insert id="insert" parameterType="Notice">
insert into notice(content) values(#{content})
</insert>
</mapper>
注:这里只是一部分示例SQL语句,没有给全部。
其中,标签的namespace属性指定了要执行的mapper接口的全限定名。在该文件中,我们可以定义一些数据访问的方法,例如findAll(查询所有),deleteById(根据id删除),insert(插入一条记录)等。
接下来,在mapper目录下新建NoticeMapper.java文件,该文件为DAO层代码文件,用于与数据库交互执行SQL语句。
@Mapper
public interface NoticeMapper {
List<Notice> findAll();
Notice findById(int id);
int deleteById(int id);
int insert(Notice notice);
}
在接口中,定义了访问数据库的方法,例如findAll(查询所有),findById(根据id查询),deleteById(根据id删除),insert(插入一条记录)等。这些方法的实现由MyBatis框架自动生成,我们只需要声明即可。
Service和Controller层实现
Service层即服务层,一般包含业务逻辑,对数据进行处理并返回结果。Controller层即控制层,用于接收请求并响应结果,将前端请求传递给Service层。
在本项目中,我们需要完成的是公告的增删改查四个操作。因此,需要定义NoticeService接口,根据业务逻辑来编写代码。
public interface NoticeService {
List<Notice> findAll();
Notice findById(int id);
int deleteById(int id);
int insert(Notice notice);
}
在接口中,定义了访问数据库的方法,这些方法在Service层中实现。实现类中,通过调用NoticeMapper接口中的方法实现对数据库的访问。
@Service
public class NoticeServiceImpl implements NoticeService {
@Autowired
private NoticeMapper noticeMapper;
@Override
public List<Notice> findAll() {
return noticeMapper.findAll();
}
@Override
public Notice findById(int id) {
return noticeMapper.findById(id);
}
@Override
public int deleteById(int id) {
return noticeMapper.deleteById(id);
}
@Override
public int insert(Notice notice) {
return noticeMapper.insert(notice);
}
}
最后,在Controller层中,需要编写方法来响应前端请求。在本项目中,我们需要响应四个请求,分别是GET请求(查询所有公告)、GET请求(根据id查询)、DELETE请求(根据id删除)、POST请求(插入一条记录)。
@RestController
@RequestMapping("/api/notice")
public class NoticeController {
@Autowired
private NoticeService noticeService;
@GetMapping("/findAll")
public List<Notice> findAll() {
return noticeService.findAll();
}
@GetMapping("/findById/{id}")
public Notice findById(@PathVariable("id") int id) {
return noticeService.findById(id);
}
@DeleteMapping("/deleteById/{id}")
public int deleteById(@PathVariable("id") int id) {
return noticeService.deleteById(id);
}
@PostMapping("/insert")
public int insert(@RequestBody Notice notice) {
return noticeService.insert(notice);
}
}
在Controller层中,使用@Autowired注解来注入Service层对象,从而调用Service层中的方法,并通过@RequestMapping指定请求地址和请求方法。
至此,后端的代码就已经完成了。
前端实现
准备工作
在本项目中,前端采用Vue框架进行开发。我们需要先使用Vue脚手架工具——Vue CLI来创建项目。运行下面的命令来创建项目:
vue create notice-frontend
在项目创建完成后,进入项目文件夹并启动项目:
cd notice-frontend
npm run serve
页面布局
我们需要一个页面来展示公告列表,一个页面来展示单个公告的详细信息,并且可以点击“添加公告”按钮来添加新公告。
公告列表页面
在src/components目录下新建NoticeList.vue文件,该文件用于展示公告列表,并可点击任意一条公告的标题以查看详细信息。代码如下:
<template>
<div>
<h2>公告列表</h2>
<div v-for="notice in notices" :key="notice.id">
<router-link :to="'/notice-detail/'+notice.id">
<h3>{{notice.content}}</h3>
</router-link>
</div>
</div>
</template>
<script>
export default {
name: 'NoticeList',
data() {
return {
notices: [],
}
},
mounted() {
this.getNotices();
},
methods: {
getNotices() {
axios.get('/api/notice/findAll').then((res) => {
this.notices = res.data;
});
},
},
};
</script>
在页面中,我们使用了Vue的模板语法来动态渲染公告列表。使用v-for遍历notices数组,将每一条公告展示出来。其中,使用了Vue Router中的router-link组件将公告标题包装成一个超链接,点击后可以跳转到对应的公告详情页面。
在mounted方法中,调用getNotices方法来获取所有的公告信息。使用axios库发送GET请求,请求地址为“/api/notice/findAll”。接收后端返回的所有公告信息,并将其存储在notices数组中,最终在页面展示出来。
公告详情页面
在src/components目录下新建NoticeDetail.vue文件,该文件用于展示单条公告的详细信息,同时可以删除该条公告。代码如下:
<template>
<div>
<h2>公告详情</h2>
<h3>{{notice.content}}</h3>
<button @click="deleteNotice">删除</button>
</div>
</template>
<script>
export default {
name: 'NoticeDetail',
data() {
return {
notice: {},
}
},
mounted() {
this.getNotice();
},
methods: {
getNotice() {
axios.get('/api/notice/findById/' + this.$route.params.id).then((res) => {
this.notice = res.data;
});
},
deleteNotice() {
axios.delete('/api/notice/deleteById/' + this.$route.params.id).then((res) => {
if (res.data === 1) {
this.$router.push('/');
} else {
alert('删除失败!');
}
});
},
},
};
</script>
在页面中,我们先使用Vue模板语法来展示公告的内容,使用h3标签展示公告标题。
与公告列表页面类似,我们也需要使用axios发送GET请求来获取单条公告的详细信息,在mounted方法中调用getNotice方法。注意,在URL中使用$route.params.id来获取动态路由中的id参数。将返回的公告信息存储在notice对象中,最终在页面中展示出来。
再看deleteNotice方法,当用户点击删除按钮时,该方法会发送一个DELETE请求,请求地址为“/api/notice/deleteById/”+id。其中,id同样从动态路由中获取。如果删除成功,则跳转回公告列表页面;否则弹出“删除失败!”的提示。
添加公告页面
在src/components目录下新建AddNotice.vue文件,该文件用于添加一条新公告。代码如下:
<template>
<div>
<h2>添加公告</h2>
<form @submit.prevent="handleSubmit">
<textarea v-model="notice.content" placeholder="请输入公告内容"></textarea>
<button type="submit">提交</button>
</form>
</div>
</template>
<script>
export default {
name: 'AddNotice',
data() {
return {
notice: {
content: '',
},
};
},
methods: {
handleSubmit() {
axios.post('/api/notice/insert', this.notice).then((res) => {
if (res.data === 1) {
this.$router.push('/');
} else {
alert('添加失败!');
}
});
},
},
};
</script>
在页面中,我们使用Vue模板语法展示页面标题,并创建了一个表单用于获取用户输入的公告内容。通过textarea和v-model指令来实现数据双向绑定,表示公告内容由用户输入。
当用户点击提交按钮时,handleSubmit方法会发送一个POST请求,请求地址为“/api/notice/insert”。注意,请求数据需要传递notice对象。如果添加成功,则跳转回公告列表页面;否则弹出“添加失败!”的提示。
路由配置
在src/router/index.js文件中,配置路由信息:
import Vue from 'vue';
import VueRouter from 'vue-router';
import NoticeList from '../components/NoticeList.vue';
import NoticeDetail from '../components/NoticeDetail.vue';
import AddNoticefrom '../components/AddNotice.vue';
Vue.use(VueRouter);
const routes = [
{
path: '/',
component: NoticeList,
},
{
path: '/notice-detail/:id',
component: NoticeDetail,
},
{
path: '/add-notice',
component: AddNotice,
},
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
export default router;
在路由信息中,配置了三个路由:
- “/”表示公告列表页面,对应的组件为NoticeList;
- “/notice-detail/:id”表示公告详情页面,动态路由中包含一个id参数,对应的组件为NoticeDetail;
- “/add-notice”表示添加公告页面,对应的组件为AddNotice。
如果用户访问未定义的路由,则会跳转到默认的“/”页面。
页面引入
在App.vue文件中,将各个页面引入并渲染出来:
<template>
<div id="app">
<router-link to="/">公告列表</router-link>
<router-link to="/add-notice">添加公告</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
};
</script>
以上代码中,我们在页面中使用了Vue Router提供的router-link组件来实现页面跳转。同时,在页面中使用了Vue Router提供的router-view组件来动态展示不同页面的内容。
至此,前端的代码就已经完成了。
总结
本文介绍了如何使用SpringBoot+Vue框架来实现公告功能。在后端,使用了SpringBoot框架进行开发,并使用MyBatis框架实现数据访问层的操作。在前端,使用了Vue框架进行开发,并使用axios库进行前后端交互。通过具体实现,我们可以深入了解到SpringBoot和Vue的开发流程,掌握前后端交互的方式和方法。