我的课程
需求分析
课程添加完成后可通过我的课程进入课程修改页面,此页面显示我的课程列表,如下图所示,可分页查询。
上边的查询要实现分页、会存在多表关联查询,所以建议使用mybatis实现我的课程查询。
API接口
输入参数:
页码、每页显示个数、查询条件
输出结果类型:
QueryResponseResult<自定义类型>
在api工程创建course包,创建CourseControllerApi接口。
//查询课程列表
@ApiOperation("查询我的课程列表")
public QueryResponseResult<CourseInfo> findCourseList(
int page,
int size,
CourseListRequest courseListRequest
);
课程管理服务
PageHelper
PageHelper是mybatis的通用分页插件,通过mybatis的拦截器实现分页功能,拦截sql查询请求,添加分页语句,
最终实现分页查询功能。
我的课程具有分页功能,本项目使用Pagehelper实现Mybatis分页功能开发,由于本项目使用springboot开发,在
springboot上集成pagehelper(https://github.com/pagehelper/pagehelper-spring-boot)
PageHelper的使用方法及原理如下:
在调用dao的service方法中设置分页参数:PageHelper.startPage(page, size),分页参数会设置在ThreadLocal中
PageHelper在mybatis执行sql前进行拦截,从ThreadLocal取出分页参数,修改当前执行的sql语句,添加分页
sql。
最后执行添加了分页sql的sql语句,实现分页查询。
1)添加依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>
2)配置pageHelper
在application.yml中配置pageHelper操作的数据库类型:
pagehelper:
helper-dialect: mysql
Dao
1)mapper 接口
CourseListRequest加上这个是为了后面如果有条件查询更方便
package com.xuecheng.manage_course.dao;
import com.github.pagehelper.Page;
import com.xuecheng.framework.domain.course.CourseBase;
import com.xuecheng.framework.domain.course.ext.CourseInfo;
import com.xuecheng.framework.domain.course.request.CourseListRequest;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
/**
* Created by Administrator.
*/
@Mapper
@Component
public interface CourseMapper {
CourseBase findCourseBaseById(String id);
Page<CourseInfo> findCourseListPage(CourseListRequest courseListRequest);
}
将courseBase加上图片属性二次封装,后期要根据课程信息关联查询课程图片
package com.xuecheng.framework.domain.course.ext;
import com.xuecheng.framework.domain.course.CourseBase;
import lombok.Data;
import lombok.ToString;
/**
* Created by admin on 2018/2/10.
*/
@Data
@ToString
public class CourseInfo extends CourseBase {
//课程图片
private String pic;
}
2)mapper.xml映射文件
<?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.xuecheng.manage_course.dao.CourseMapper">
<select id="findCourseBaseById" parameterType="java.lang.String"
resultType="com.xuecheng.framework.domain.course.CourseBase">
select * from course_base where id = #{id}
</select>
<!--关联查询图片表,获取图片信息,后期实现FastDFS后可直接从图片服务器获取 -->
<select id="findCourseListPage" parameterType="com.xuecheng.framework.domain.course.request.CourseListRequest"
resultType="com.xuecheng.framework.domain.course.ext.CourseInfo">
select course_base.*,
(select pic from course_pic where courseid=course_base.id) pic
from course_base
</select>
</mapper>
3)测试Dao
//测试分页
@Test
public void testPageHelper(){
PageHelper.startPage(2, 1);
CourseListRequest courseListRequest = new CourseListRequest();
Page<CourseInfo> courseListPage = courseMapper.findCourseListPage(courseListRequest); List<CourseInfo> result = courseListPage.getResult();
System.out.println(courseListPage);
}
测试前修改日志级别为debug,并跟踪运行日志,发现sql语句中已经包括分页语句
Service
定义CourseService.java类,用于课程管理的service定义:
/**
* 分页查询课程列表
* @param page
* @param size
* @param courseListRequest
* @return
*/
public QueryResponseResult<CourseInfo> findCourseList(int page, int size, CourseListRequest courseListRequest) {
//保证传过来的对象不为空
if (courseListRequest == null) {
courseListRequest = new CourseListRequest();
}
//分页参数
if (page<=0){
page = 1;
}
if (size <= 0) {
size = 10;
}
PageHelper.startPage(page, size);
Page<CourseInfo> listPage = courseMapper.findCourseListPage(courseListRequest);
if (listPage==null) {
ExceptionCast.cast(CommonCode.INVALID_PARAM);
}
List<CourseInfo> result = listPage.getResult();
QueryResult queryResult = new QueryResult();
queryResult.setList(result);
queryResult.setTotal(listPage.getTotal());
System.out.println(listPage.getTotal());
return new QueryResponseResult<CourseInfo>(CommonCode.SUCCESS,queryResult);
}
Controller
@RestController
@RequestMapping("/course")
public class CourseController implements CourseControllerApi {
@Autowired
CourseService courseService;
@Override
@GetMapping("/coursebase/list/{page}/{size}")
public QueryResponseResult<CourseInfo> findCourseList(
@PathVariable("page") int page,
@PathVariable("size") int size,
CourseListRequest courseListRequest) {
return courseService.findCourseList(page,size,courseListRequest);
}
}
前端
页面
创建course_list.vue
1)使用element 的card组件
页面布局代码如下:
<template>
<section>
<el-row >
<el-col :span="8" :offset=2 >
<el-card :body-style="{ padding: '10px' }">
<img src="/static/images/add.jpg" class="image" height="150px">
<div style="padding: 10px;">
<span>课程名称</span>
<div class="bottom clearfix">
<time class="time"></time>
<router-link class="mui-tab-item" :to="{path:'/course/add/base'}">
<el-button type="text" class="button" >新增课程</el-button>
</router-link>
</div>
</div>
</el-card>
</el-col>
<el-col :span="8" v-for="(course, index) in courses" :key="course.id" :offset="index > 0 ? 2 : 2">
<el-card :body-style="{ padding: '10px' }">
<img :src="course.pic!=null?imgUrl+course.pic:'/static/images/nonepic.jpg'" class="image" height="150px">
<div style="padding: 10px;">
<span>{{course.name}}</span>
<div class="bottom clearfix">
<time class="time"></time>
<el-button type="text" class="button" @click="handleManage(course.id)">管理课程</el-button>
</div>
</div>
</el-card>
</el-col>
<!--分页-->
<el-col :span="24" class="toolbar">
<el-pagination background layout="prev, pager, next" @current-change="handleCurrentChange" :page-size="size"
:total="total" :current-page="page"
style="float:right;">
</el-pagination>
</el-col>
</el-row>
</section>
</template>
<script>
import * as courseApi from '../api/course';
import utilApi from '../../../common/utils';
let sysConfig = require('@/../config/sysConfig')
export default {
data() {
return {
page:1,
size:5,
total: 0,
courses: [
{
id:'test01',
name:'test01',
pic:''
},
{
id:'test02',
name:'test02',
pic:''
}
],
sels: [],//列表选中列
imgUrl:sysConfig.imgUrl
}
},
methods: {
//分页方法
handleCurrentChange(val) {
this.page = val;
this.getCourse();
},
//获取课程列表
getCourse() {
courseApi.findCourseList(this.page,this.size,{}).then((res) => {
console.log(res);
if(res.success){
this.total = res.queryResult.total;
this.courses = res.queryResult.list;
}
});
},
handleManage: function (id) {
console.log(id)
this.$router.push({ path: '/course/manager/'+id})
}
},
created(){
},
mounted() {
//查询我的课程
this.getCourse();
}
}
</script>
<style scoped>
.el-col-8{
width:20%
}
.el-col-offset-2{
margin-left:2%
}
.time {
font-size: 13px;
color: #999;
}
.bottom {
margin-top: 13px;
line-height: 12px;
}
.button {
padding: 0;
float: right;
}
.image {
width: 100%;
display: block;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
</style>
6)路由
import course_list from '@/module/course/page/course_list.vue';
import Home from '@/module/home/page/home.vue';
export default [
{
path: '/course',
component: Home,
name: '课程管理',
hidden: false,
iconCls: 'el‐icon‐document',
children: [
{ path: '/course/list', name: '我的课程',component: course_list,hidden: false }
]
}
]
Api调用
1、定义Api方法
//我的课程列表
export const findCourseList = (page,size,params) => {
//对于查询条件,向服务端传入key/value串。
//使用工具类将json对象转成key/value
let queries = querystring.stringify(params)
return http.requestQuickGet(apiUrl+"/course/coursebase/list/"+page+"/"+size+"?"+queries);
}
2、在页面调用fifindCourseList方法:
//获取课程列表
getCourse() {
courseApi.findCourseList(this.page,this.size,{}).then((res) => {
console.log(res);
if(res.success){
this.total = res.queryResult.total;
this.courses = res.queryResult.list;
}
});
}
在mounted钩子中调用getCourse方法
mounted() {
//查询我的课程
this.getCourse();
}
在分页方法中调用getCourse方法
//分页方法
handleCurrentChange(val) {
this.page = val;
this.getCourse();
},
测试
页面效果如下:
注意:由于课程图片服务器没有搭建,这里图片暂时无法显示。