谷粒学院之讲师管理模块

第一个页面展示讲师数据,以及增删改操作(数据回显等)

数据库表是edu_teacher


service_edu模块

先代码生成器生成

然后在controller里@Autowired注入service,调用方法来实(@RestController,@RequestMapping在类上)

写application.properties配置文件

创建启动类@SpringBootApplication,内容为SpringApplication.run(当前类.class,args)

创建一个配置类@Configuration,加上@MapperScan("")扫描路径


细节

1.返回的json数据的时间和我们的时间差八小时,需要在配置文件设置

#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

2.需要获取路径中的值,要在xxxMapping("{xxx}")

在方法的参数里用@PathVariable来获取值

3.浏览器测试只能测get提交,其他方式比如post,delete得用测试工具比如swagger测

4.分页查询需要在路径里输入当前页和每页记录数,用@PathVariable来获取


条件组合查询带分页功能

先创建一个vo类,用来封装前端得到的条件。然后通过对象的方式传递给后端的接口

 在对象前加@RequestBody会将条件都封装进一个json对象里来传递,而不加则是一个个单独的数据,required=false表示可以不填写,但是这种注解的方式必须是post提交。

     //条件查询并分页,以对象形式得到条件
    @PostMapping("pageTeacherCondition/{current}/{limit}")//用RequestBody传递json对象到对象中,需要使用post
    public R pageTeacherCondition(@PathVariable long current,
                                  @PathVariable long limit,
                                  @RequestBody(required = false) TeacherQuery teacherQuery) {

         //创建page对象
         Page<EduTeacher> pageTeacher = new Page<>(current, limit);


         //构建条件
         QueryWrapper<EduTeacher> wrapper = new QueryWrapper<>();
        //多条件组合查询
         //动态sql,判断条件值是否为空,不为空就拼接条件
         String name = teacherQuery.getName();
         Integer level = teacherQuery.getLevel();
         String begin = teacherQuery.getBegin();
         String end = teacherQuery.getEnd();
         if (!StringUtils.isEmpty(name)) {
             wrapper.like("name", name);
         }
         if (!StringUtils.isEmpty(level)) {
             wrapper.eq("level", level);
         }
         if (!StringUtils.isEmpty(begin)) {
             wrapper.ge("gmt_create", begin);//大于等于
         }
         if (!StringUtils.isEmpty(end)) {
             wrapper.le("gmt_create", end);//小于等于
         }

         //排序,按时间降序
        wrapper.orderByDesc("gmt_create");

         //调用方法查询并分页
         teacherService.page(pageTeacher, wrapper);
         long total = pageTeacher.getTotal();//总记录数
         List<EduTeacher> records = pageTeacher.getRecords();//数据集合
            return R.ok().data("total",total).data("rows",records);
        }

在实际开发中,这些具体的代码应该写在serviceimpl里,controller里不写具体代码,只是调用service的方法。


前端部分

框架默认的登录页面的登录请求访问的是config里的dev.env.js里的BASE_API加上src的api的login.js里的login方法的url。

在后端EduLoginController里写登录以及用户信息的接口,再在前端的api的login.js里调用接口

完成后会出现一个问题,跨域问题(一个地址去访问另一个地址,协议、ip、端口号任一不同都是跨域)

解决方法:

在controller上加@CrossOrigin,可以允许跨域访问

之后会通过gataway网关来解决这个问题

添加路由(模仿):

  {
    //这里是讲师管理菜单(路由)
    path: '/teacher',
    component: Layout,
    redirect: '/teacher/table',//默认是显示这个而不是save
    name: '讲师管理',
    meta: { title: '讲师管理', icon: 'example' },//icon是图标
    children: [
      {
        path: 'table',
        name: '讲师列表',
        component: () => import('@/views/edu/teacher/list'),
        meta: { title: '讲师列表', icon: 'table' }
      },
      {
        path: 'save',
        name: '添加讲师',
        component: () => import('@/views/edu/teacher/save'),//引入路由对应的页面 ( @/相当于./)
        meta: { title: '添加讲师', icon: 'tree' }
      },
      //隐藏路由,由修改按钮跳转
      {
        path:'edit/:id',
        name:'EduTeacherEdit',
        component:() => import('@/views/edu/teacher/save'),
        meta: { title: '编辑讲师',noCache:true },//不缓存
        hidden:true //隐藏路由
      }
    ]
  }

调用接口(类似):

export default{

   //显示课程分类列表
    getSubjectList(){
        return request({
            url: `/eduservice/subject/getAllSubject`,//用的是piao
            method: 'get',
          })
    }

}

页面.vue引入api的js文件

import xxx from '  '

export default{

        data:{

        },
//data可以写为data(){return{}}

        created(){

        },

        methods:{

        }

}

分页接口

    //1.讲师列表(条件分页)
    //current当前页,limit每页记录数,teacherQuery条件对象,通过对象获取类的全部参数
    getTeacherListPage(current,limit,teacherQuery){
        return request({
            //方式一url: '/eduservice/teacher/pageTeacherCondition/'+current+"/"+limit,
            url: `/eduservice/teacher/pageTeacherCondition/${current}/${limit}`,//用的是piao
            method: 'post',
            //teacherQuery条件对象,由于后端使用requestbody获取数据
            //要用到data,data表示把对象转换成json传递到接口(不是requestbody直接用params:参数)
            data:teacherQuery
          })
    }

第二个页面根据文件添加课程分类,以树形显示

实体:

public class EduSubject implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "课程类别ID")
    @TableId(value = "id", type = IdType.ID_WORKER_STR)
    private String id;

    @ApiModelProperty(value = "类别名称")
    private String title;

    @ApiModelProperty(value = "父ID")
    private String parentId;

    @ApiModelProperty(value = "排序字段")
    private Integer sort;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)//自动填充
    private Date gmtCreate;

    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)//自动填充
    private Date gmtModified;


}
//一级分类
@Data
public class OneSubject {
    private String id;
    private String title;

    //一个一级分类里有多个二级分类
    private List<TwoSubject> children = new ArrayList<>();
}
//二级分类
@Data
public class TwoSubject {

    private String id;
    private String title;

}

根据文件添加课程分类

    //添加课程分类
    @Override
    public void saveSubject(MultipartFile file,EduSubjectService subjectService) {

        try {
            //文件输入流
            InputStream in = file.getInputStream();
            //读取Excel
            EasyExcel.read(in, SubjectData.class,new SubjectExcelListener(subjectService)).sheet().doRead();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

得到数据库的课程列表

//课程分类列表
    @Override
    public List<OneSubject> getAllOneTwoSubject() {
        //查询所有一级分类 parent_id=0,eq表示等于
        QueryWrapper<EduSubject> wrapperOne = new QueryWrapper<>();
        wrapperOne.eq("parent_id", "0");
        List<EduSubject> oneSubjectList = baseMapper.selectList(wrapperOne);

        //查询所有二级分类,ne表示不等于
        QueryWrapper<EduSubject> wrapperTwo = new QueryWrapper<>();
        wrapperTwo.ne("parent_id", "0");
        List<EduSubject> twoSubjectList = baseMapper.selectList(wrapperTwo);

        //创建list集合存储最终封装数据
        List<OneSubject> finalSubjectList = new ArrayList<>();

        //封装一级分类
        //把查询出来的一级分类的集合遍历,得到每个一级分类对象,放到最终集合里
        for (int i = 0; i < oneSubjectList.size(); i++) {
            //得到oneSubjectList里的每个edusubject对象
            EduSubject eduSubject = oneSubjectList.get(i);
            //把edusubject对象的值取出来放到oneSubject对象里面

            OneSubject oneSubject = new OneSubject();
//            oneSubject.setId(eduSubject.getId());
//            oneSubject.setTitle(eduSubject.getTitle());
            //这个spring框架的工具作用和上面两行一样,但是当要设置的数据过多时,一个个写不现实用封装工具更便利
            BeanUtils.copyProperties(eduSubject,oneSubject);

            //多个Onesubject对象放到finalSubjectList集合里
            finalSubjectList.add(oneSubject);

            //封装二级分类
            //把二级分类遍历放到一级分类集合中(二级分类的循环要放在一级分类的循环里)
            List<TwoSubject> twoFinalSubjectList = new ArrayList<>();
            //遍历二级分类list集合
            for (int m = 0; m < twoSubjectList.size(); m++) {
                EduSubject tSubject = twoSubjectList.get(m);
                //判断二级分类属于哪个一级分类
                if (tSubject.getParentId().equals(eduSubject.getId())) {
                    TwoSubject twoSubject = new TwoSubject();
                    //把tsubject的值放到twosubject里,再放到twoFinalSubjectList里
                    BeanUtils.copyProperties(tSubject,twoSubject);
                    twoFinalSubjectList.add(twoSubject);
                }

            }

            //把二级分类放到一级分类里
            oneSubject.setChildren(twoFinalSubjectList);
        }
        return finalSubjectList;
    }


eduvideocontroller里有一个删除小节同时删除视频

需要通过edu模块调用vod 模块的接口方法来实现

将两个服务都在nacos注册中心里注册,才能互相调用

依赖

    <!--熔断器hystrix依赖,主要是用 @HystrixCommand -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <!--服务注册-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!--服务调用-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

# 服务端口
server.port=8001
# 服务名
spring.application.name=service-edu
# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#配置熔断器,开启熔断机制
feign.hystrix.enabled=true
# 设置hystrix超时时间,默认1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000

启动类上加

@EnableDiscoveryClient//nacos注册

当服务启动,nacos里就会有这个服务名(账号密码都是nacos,8848端口)

@EnableFeignClients//服务调用

在调用方启动类加上这个注解

然后

import java.util.List;
//调用的服务的名称,以及熔断后执行方法的类
@FeignClient(name="service-vod",fallback = VodClientDefeat.class)
@Component
public interface VodClient {

    //定义调用的方法的完全路径和方法
    //根据视频id删除阿里云视频
    @DeleteMapping("/eduvod/video/removeAlyVideo/{id}")
    public R removeAlyVideo(@PathVariable("id") String id);

    //删除章节的时候删除所属的多个视频
    @DeleteMapping("/eduvod/video/delete-batch")
    public R deleteBatch(@RequestParam("videoIdList") List<String> videoIdList);

}
//当服务器故障导致熔断器起作用断开连接,就会执行这个实现类里的方法
@Component
public class VodClientDefeat implements VodClient{
    @Override
    public R removeAlyVideo(String id) {
        return R.error().message("删除视频出错");
    }

    @Override
    public R deleteBatch(List<String> videoIdList) {
        return R.error().message("删除多个视频出错");
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值