赞
踩
目录
码字不易,喜欢就点个关注❤,持续更新技术内容。相关资料请私信。
相关内容:
第一篇:SpringBoot项目的创建和开发_Maxlec的博客-CSDN博客
第一篇:原生JS到Vue前端工程化开发_Maxlec的博客-CSDN博客
Servlet原理和简单的案例编写_Maxlec的博客-CSDN博客
现在将后台管理页面(前端)和后台服务服务端进行集成,之前都是通过MockJS拦截前端请求随机生成数据来模拟服务器的数据响应的。当服务端接口开发完成后,前端就可以通过连接服务端程序指定的端口,然后向指定功能接口发送请求。
如当我们要进入后台管理页面中,需要通过导航守卫进行登录权限验证,如token认证,用户信息请求,路由跳转等,在讲解Vue技术那篇文章中已经做了更详细的描述。
如下登录过程,向服务端发送POST请求,此时请求的URL中没有IP地址和端口号,我们需要在.env.development配置文件中添加URL前缀。
- export function login(data) {
- return request({
- url: '/user/login',
- method: 'post',
- data: data
- })
- }
- ENV = 'development'
-
- # base api
- VUE_APP_BASE_API = 'http://localhost:xxxx'
请求会服务器交给到以下控制器进行处理,然后返回包含token的结果集:
- @RestController
- @RequestMapping("/user")
- public class UserController {
- @Autowired
- private UserMapper userMapper;
-
- @PostMapping("/login")
- //前端一般传递的数据是json格式,必须使用对象接收,同时需要添加@RequestBody注解
- public Result login(@RequestBody User user){
- //生成token
- String token = JwtUtils.generateToken(user.getUname());
-
- //返回包含token的结果集
- return Result.ok().data("token", token);
- }
- }
接下来我们进行登录操作的讲解:
首先我们先启动前端项目:
进入登录组件页面,然后点击登录,导航守卫进行拦截走一遍权限认证,如没有token进入登录页登录,输入后点击登录会发送一次请求,传递账号和密码到服务端生成token后放在响应数据response在action中存储token,最后才进入首页。(实际上进入首页前还发送一次获取用户信息的请求。)
如果没有token想直接进入非白名单页面(一般是除登录页面以外的),则需要进入登录页进行上面过程后再重定向到想去的页面。
因为此时后端未启动,不能与服务端端口建立连接,也就发送不了网络请求:
启动服务端,与服务端端口建立连接,发送网络请求(注意跨域问题,在文首有相关内容的链接):
如图成功获取token和用户信息:
初步进行前后端联调后,如果有的页面组件不符合我们的需求,我们要改成我们想要的样子,然后通过Axios完成数据异步加载。
修改组件页面。
异步加载列表数据,并渲染到页面组件上。
首先在路由模块中找出组件与路由的关联,对路由对应的组件进行更改。
- {
- path: '/example',
- component: Layout,
- redirect: '/example/table',
- name: 'Example',
- meta: { title: '用户管理', icon: 'el-icon-s-help' },
- children: [
- {
- path: 'table',
- name: 'Table',
- component: () => import('@/views/table/index'),
- meta: { title: '用户列表', icon: 'table' }
- },
- {
- path: 'tree',
- name: 'Tree',
- component: () => import('@/views/tree/index'),
- meta: { title: '添加用户', icon: 'tree' }
- }
- ]
- },
所以要在在Table组件的进行更改,包括表单,表格,以及分页条,选择适当的组件后进行修改为符合自己需求的表单表格,注意需要在该表格用于展示用户的信息。
首先我们添加一个<el-main>来包含整个组件页面(template中只能有一个根标签),然后在其中添加elementui的表格标签<el-table :data="tableData">,在其中再添加表格列表,可以通过普通列<el-table-column prop="name" label="姓名" width="120">定义其属性,方便进行渲染,还可以定义普通列的标签名以及调整适当的宽度。
注意如果响应数据打他中的性别值是0或1,则需要进行判断然后再渲染,在需要进行判断后渲染的普通列中加入一个插槽:
- <template slot-scope="scope">
- {{ scope.row.gender == 1 ? '男':'女' }}
- </template>
表示判断每一条对象中的gender为"1"则显示为"男",否则为"女"。表格全部代码如下(注意还需要在数据模型返回绑定数据标签才会生效):
- <el-table :data="tableData" border>
- <el-table-column prop="id" label="序号" width="50"></el-table-column>
- <el-table-column prop="classes" label="班级" width="120"></el-table-column>
- <el-table-column prop="uname" label="姓名" width="120"></el-table-column>
-
- <el-table-column prop="gender" label="性别" width="50">
- <template slot-scope="scope">
- {{ scope.row.gender == 1 ? '男':'女' }}
- </template>
- </el-table-column>
-
- <el-table-column prop="birthday" label="生日"></el-table-column>
-
- <el-table-column label="操作">
- <el-button type="primary" size="mini">编辑</el-button>
- <el-button type="primary" size="mini">删除</el-button>
- </el-table-column>
- </el-table>
剩下的表单和分页条可查看文档加入到Table组件中。
最后向服务端发送axios异步请求然后完成数据的渲染。
然后我们定义一个组件生命周期函数created(钩子),当组件被创建展示为页面前调用,在该方法中我们可以向后端发送axios请求数据。如在fetchData方法中封装了getList方法,该方法负责向后端指定接口发送请求:
前端发送的异步请求的方法,一般在api目录下定义。如在getList方法封装的request方法中定义请求路径url,以及请求方法GET,以及要向后端传递的参数。(该参数是后面分页请求要传递的页号)。这样后端就能接收到该请求并响应对应的结果集。
所以当我们想在单页面应用模板vue-admin-template中向后端发送请求时,可以在api目录下定义对应的方法,在request方法中定义对应的属性。
- <script>
- import { getList } from '@/api/table'
- export default {
- data() {
- return {
- tableData: [],
- searchForm: {
- "name":"",
- gengder:""
- },
- value1:""
- }
- },
- created: function() {
- this.fetchData()
- },
- methods: {
- fetchData() {
- getList().then(response => {
- this.tableData = response.data.data
- })
- },
- }
- }
- </script>
如下图在前后端联调后,前端向后端发送请求后,后端返回响应数据data,通过赋值渲染到组件页面中:
上面只展现了各个组件的修改,简单地响应的数据,并未实现分页、编辑以及删除等功能。
先分析,当我们点击分页的页号时,需要请求后端响应该页号的几条数据,如果是升序排序,就是向下读取几条数据作为一页;降序则是向上读取几条数据作为一页。然后返回响应数据然后进行赋值渲染。
- <!-- 分页条 -->
- <el-pagination background layout="total, prev, pager, next"
- @size-change="handleSizeChange"
- @current-change="changePage"
- :page-size="pageSize"
- v-if="isShow"
- :total="total"></el-pagination>
可以看到第一次进入页面,当组件创建完毕时自动向后端发送请求,后端读取几条数据作为第一页返回,然后赋值渲染给组件页面;而当我们点击分页号时,会在分页组件中触发changePage方法(依然是调用getList方法向后端发送异步请求)。可以看到,该方法重新向后端发送请求,并传递分页的页号,后端接收到后根据该页号进行分页查询,最后封装到结果集中返回,然后前端接收后进行赋值和渲染。这就完成了数据的分页显示。
- <script>
- import { getList } from '@/api/table'
- export default {
- data() {
- return {
- tableData: [],
- searchForm: {
- "name":"",
- gengder:"",
- },
- value1:"",
- total: 1,
- pageSize: 1,
- isShow: false //默认当为响应数据时不显示分页条
- }
- },
- created: function() {
- this.fetchData()
- },
- methods: {
- fetchData() {
- getList().then(response => {
- this.tableData = response.data.items.records
- //总记录
- this.total = response.data.items.total
- //每页显示条数
- this.pageSize = response.data.items.size
- //当响应回数据时才显示分页
- this.isShow = true
- })
- },
-
- changePage(pageNum){
- getList(pageNum).then((response => {
- this.tableData = response.data.items.records
- }))
- },
-
- }
- }
- </script>
如下后端后端的网络接口,观察理解以下,可以看到如果前端没有传递参数(也就是我们第一次打开页面时),后端默认响应第一页的数据,另外在查询条件中,通过id升序查询(如果用的是Sqlserver必须加该条件,否则报"@P0"附近有语法错误),最后封装到结果集中返回:
- @GetMapping("/getAll")
- public Result getAl(@RequestParam(defaultValue = "1") int pageNum){
- //分页对象
- Page<User> page = new Page<>(pageNum, 3);
- //Sqlserver中需要加一个唯一字段排序,否则系统排序结果不唯一
- QueryWrapper<User> wrapper = new QueryWrapper();
- wrapper.orderByAsc("id");
- Page<User> userPage = userMapper.selectPage(page, wrapper);
-
- return Result.ok().data("items", userPage);
- }
在介绍编辑和删除之前,先对用户数据表进行添加用户。添加用户较简,只需在前端获取到用户数据就可以发送给后台进行插入。
在在用户表格中点击添加,触发doAdd方法。在doAdd方法中通过编程式路由跳转到添加页面。
<el-button type="primary" @click="doAdd">添加</el-button>
- doAdd(){
- //通过编程式路由跳转到添加页面
- this.$router.push("/users/add");
- },
在添加页面的表单中输入要添加的用户数据后确认添加,触发onSubmit方法,在方法中调用导入的网络请求方法add并传递表单数据。
- onSubmit() {
- add(this.form).then(res=>{
- this.$message({
- message: '添加成功',
- type: 'success'
- })
- });
- }
在add网络请求方法中向url发送post请求并发送填入的用户表单数据:
- export function add(data) {
- return request ({
- url: '/user/add',
- method: 'post',
- data
- })
- }
后端服务器接收请求后调用相应控制器的接口进行处理:
- @ApiOperation("添加用户")
- @PostMapping("/add")
- public Result addUser(@RequestBody User user) {
- userMapper.insertUser(user);
- return Result.ok();
- }
在用户控制器中定义了一个接收post请求的接口,通过@RequestBody注解接收实体类对象,调用UserMapper用户映射接口中自定义的insertUser方法添加用户。因为如果直接调用MybatisPlus的insert方法,该方法会根据用户User类定义的属性自动生成插入的sql语句,这样包括id在内的所有属性都作为字段插入数据。但是在sqlsever中自增长的id字段不能显示插入并报错。所以在进行插入操作时,需要在UserMapper用户映射接口中定义Mybatis发送手写的sql插入语句。
另外,在自定义插入sql语句时,需要字段和只一一对应,否则会出现混插的情况。
- @Insert("insert into t_user values(#{uname}, #{pwd}, #{birthday}, #{gender}), #{classes}")
- //或者
- @Insert("insert into t_user(uname, pwd, birthday, gender, classes)
- values(#{uname}, #{pwd}, #{birthday}, #{gender}), #{classes}")
另另外,其实MybatisPlus对sqlsever数据库进行插入操作的问题可以通过@TableField(exist = false)注解来说明id属性不作为字段处理,但是后面的查询、更新和删除操作又需要用到id,所以不能去掉,只能委屈一下插入操作了。
编辑用户与添加用户类似,不过还要在前台展示要编辑的用户数据,方便编辑;在后台,接收到传递来的用户对象时,需要提取用户id作为条件进行用户的删除。
首先进行较删除功能难一点的编辑功能。
在用户表格中点击编辑,调用handleEdit方法并传递当前行的对象:
<el-button type="primary" size="mini" @click="handleEdit(scope)">编辑</el-button>
在handleEdit方法中,将flag设置为true显示编辑浮窗,然后将传递的对象赋值给form表单对象进行展示,方便用户对比编辑。
- handleEdit(scope) {
- //首先打开浮窗
- this.flag=true;
- //1.将传递的对象数据赋值给要编辑的表单,这种方式直接影响用户表格数据的显示
- this.form = scope.row
-
- //2.或者是将对象里面属性展开,不用原来的对象赋值,避免影响用户表格数据的显示
- // this.form = {...scope.row}
- },
- <!--定义浮窗的标签-->
- <el-dialog title="编辑" width="50%" :visible.sync="flag"></el-dialog>
修改完表单数据后,点击浮窗的确定按钮调用doEdit方法,并关掉浮窗:
<el-button type="primary" @click="doEdit();flag=false">确 定</el-button>
在doEdit方法中,调用从api目录导入的edit方法发送异步请求,将编辑好的表单作为参数传递。
- doEdit(){
- edit(this.form).then(res=>{
- this.$message({
- message: '编辑成功',
- type: 'success'
- })
- });
- },
在api目录下js文件中的edit网络请求方法中定义请求的url、请求操作以及传递的参数:
- export function edit(data) {
- return request ({
- url: '/user/edit',
- method: 'put',
- data // data: {data}
- })
- }
然后后端服务器接收请求后调用相应控制器的接口进行处理:
- @RestController
- @RequestMapping("/user")
- @CrossOrigin
- public class UserController {
- @Autowired
- private UserMapper userMapper;
-
- @PutMapping("/edit")
- public Result editById(@RequestBody User user) {
- UpdateWrapper<User> wrapper = new UpdateWrapper<>();
- int id = user.getId();
- System.out.println(user);
- wrapper.eq("id",id);
- userMapper.update(user, wrapper);
- return Result.ok();
- }
- }
在用户控制器中定义了一个接收put请求的接口,通过@RequestBody注解接收实体类对象,然后提取对象中的id作为条件对象传给MybatisPlus中的update更新方法进行修改。因是更新数据,数据库只返回影响行数,我们只需要返回请求成功的结果集即可。
删除比较简单,在表格中点击删除,直接调用doDelete方法传递该行数据的id:
<el-button type="primary" size="mini" @click="doDelete(scope.row.id)">删除</el-button>
在doDelete方法中直接调用网络请求方法:
- doDelete(id) {
- del(id).then(res => {
- this.$message({
- message: '删除成功',
- type: 'success'
- })
- })
- },
在del方法中发送异步请求:
- export function del(id) {
- return request ({
- url: '/user/del',
- method: 'delete',
- params: { id } //跟data一样,如果参数为params也可以简写为params
- })
- }
后端控制器中定义的delete请求接口直接根据传递过来的id参数,调用BaseMapper接口中的deleteById删除用户:
- @ApiOperation("根据id删除用户")
- @DeleteMapping("/del")
- public Result deleteUser(int id){
- userMapper.deleteById(id);
- return Result.ok();
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。