基于springboot+spring cloud+jpa+vue实现学生成绩管理系统

1、基本技术

   通过之前的微服务入门,这次不再mybatis上开发,改为基于spring jpa开发一个简单的学生成绩管理系统,基本SpringBoot + SpringCloud + JPA + VUE框架开发

2、需求说明

使用微服务架构完成《学生成绩管理系统》,它包含学生表和成绩表(科目是动态保存和动态展示)。

具体思路是:

  1. 使用Eureka搭建注册中心,并实现高可用。
  2. 开发学生成绩管理业务服务,并向注册中心注册。
  3. 使用ZUUL或Spring Cloud Gateway开发网关服务。
  4. 使用VUE+element-ui开发前端工程。

3、页面效果

   页面需求

  1、学生成绩列表页面

  科目是动态列表

学生姓名:

 

 

学号

 

 

查询

 

新增

 

 

 

 

 

 

 

 

 

学生姓名

语文

数学

英语

物理

化学

生物

总成绩

操作

张三

87

45

98

56

78

55

419

修改,删除

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分页

1,2,3

 

 

 

 

2、修改和新增页面

成绩可以动态添加一行

学生姓名

李四

 

学生学号

3458986

 

 

 

 

 

 

 

 

 

科目

语文

分数

90

 

新增

删除

科目

数学

分数

80

 

新增

删除

科目

历史

分数

100

 

新增

删除

 

 

 

 

 

 

 

 

 

 

保存

 

 

 

 

 

4、数据库设计

                                                                                 学生表:(student)

字段名

字段说明

字段类型

为空

备注

id

主键

int

唯一主键,自增长

sname 

学生姓名

varchar(50)

 

sno

学号

varchar(50)

学号唯一

 

                                                                                       成绩表:(score)

字段名

字段说明

字段类型

为空

备注

id

主键

int

唯一主键,自增长

cname

课程名称

varchar(50)

 

fraction

课程分数

int

 

sid

学生ID

int

学生表外键

 

5、后台实现

后端

                                                            

提供者(grade-service-provider)项目结构

 

 

后端实体类,本次采用spring jpa自动生成表的方法,需要在yml配置

贴出yml代码

server:
  port: 8081
spring:
  application:
    name: grade-provider
    main:
      allow-bean-definition-overriding: true
  profiles:
    active: '@profiles.active@'
  datasource:
    url: jdbc:mysql://localhost:3306/grade?serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
mybatis:
  type-aliases-package: cn.grade.service.entity
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

 

jpa内部封装了很多的方法,所以我们直接可以调用就行了,非常方便

给出StudentDao接口的代码

@Repository
public interface StudentDao extends JpaRepository<Student,Long>, JpaSpecificationExecutor<Student> {

    //带条件分页查询
    Page<Student> findAllBySnameContainingAndSnoContaining(String name, String sno, Pageable pageable);

    //根据学号查询学生是否存在
    Student findBySno(String sno);

}

给出StudentService代码

/**
 * @program: grade-service-provider
 * @author: Mr.M
 * @create: 2020-07-14
 **/
@Service
public class StudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private StudentDao studentDao;

    public Student queryById(Long id) {
        return this.studentMapper.selectByPrimaryKey(id);
    }


    /*分页学生成绩以及根据姓名与学号查询*/
    public R findAllBySnameContainingAndSnoContaining(PageStudentREQ req) {

        //获取每页条数
        req.setPageSize(req.getPageSize() < 1 ? 3 : req.getPageSize());
        //获取起始页
        req.setPageNow(req.getPageNow() < 1 ? 0 : (req.getPageNow() - 1));
        //定义分页条件
        System.out.println("service分页:"+req.getPageNow());
        PageRequest pageRequest = PageRequest.of(req.getPageNow(), req.getPageSize());
        System.out.println(req.getPageNow()+"----------"+req.getPageSize());

        //获取分页数据
        //在jpa方法调用中,由于传进来的数据不能为null,所以将其设置为""
        if(req.getSname() == null) {
            req.setSname("");
        }
        if(req.getSno()==null) {
            req.setSno("");
        }
        Page<Student> page = studentDao.findAllBySnameContainingAndSnoContaining(req.getSname(), req.getSno(), pageRequest);
        //System.out.println("stuName:"+req.getStuName()+"------------"+"stuNo:"+req.getStuNo());
        //新建一个map集合,用来存放返回的数据
        Map map = new HashMap<>();
        //新建一个科目的集合,用来存放所有的科目
        Set courseNames = new HashSet<>();
        //将分页总条数放入map集合中
        map.put("count",page.getTotalElements());
        //创建一个PageStudentRESQ集合
        List<PageStudentRESQ> resqList = new ArrayList<>();
        //定义一个PageStudentRESQ对象
        PageStudentRESQ resq;
        //定义一个成绩的集合
        Map scoreMap;
        //循环分页数据中的list
        for (Student s:page.getContent()) {
            resq = new PageStudentRESQ();
            scoreMap = new HashMap();
            // 将获取到的学生信息赋值到resq中
            resq.setId(s.getId());
            resq.setSname(s.getSname());
            resq.setSno(s.getSno());

            int score = 0;
            // 将成绩循环放入成绩集合中
            for (Score h:s.getScores()) {
                //通过键值对的方式存入成绩
                scoreMap.put(h.getCname(),h.getFraction());
                //通过set集合的特性存入科目名称并去重
                courseNames.add(h.getCname());
                //计算学生总分
                score += h.getFraction();
            }
            resq.setScore(score);
            //将成绩存入resq中
            resq.setScores(scoreMap);
            //将赋值后的StudentPageRESQ放入resqList中
            resqList.add(resq);
        }
        //将分页数据存入map中
        map.put("list",resqList);
        //将所有科目的名称的集合存入map中
        map.put("courseNames",courseNames);
        //System.out.println("map:"+map);
        return R.ok().data("map",map);
    }


    @Transactional
    /*新增或修改学生成绩*/
    public R add(Student stu){

        /*遍历获取学生相应科目成绩*/
        Set<Score> scores =stu.getScores();
        scores.forEach(h->{
            h.setStudent(stu);
        });

        /*保存新增或者修改后的学生信息*/
        Student save = studentDao.save(stu);
        return R.ok().data("stu",save);

    }

    /**
    * @Author: M
    * @Description: 根据ID查询学生信息
    * @DateTime: 2020/7/14
    * @Params: [id]
    * @Return cn.grade.service.entity.R
    */
    public R findById(Long id) {
        Student one = studentDao.getOne(id);

        return R.ok().data("one",one);
    }

    /**
    * @Author: M
    * @Description: 根据id删除
    * @DateTime: 2020/7/14
    * @Params: [id]
    * @Return void
    */
    public boolean del(Long id){
        studentDao.deleteById(id);
        return true;
    }

    /**
    * @Author: M
    * @Description: 检查学号是否存在
    * @DateTime: 2020/7/14
    * @Params: [sno]
    * @Return boolean
    */
    public boolean stuNoValid(String sno){
        //调用学号的接口
        Student stu = studentDao.findBySno(sno);
        //如果返回值为空,说明不存在该学号,则返回true
        if(stu == null) {
            return true;
        }else {
            //如果返回值不为空,则已经存在该学号,则返回false
            return false;
        }
    }


}

给出Student实体类代码

@Entity
@Table(name = "student")
@ApiModel(value="学生表",description = "这是学生表")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer"})
public class Student implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    // 学生姓名
    @Column(name = "sname")
    private String sname;

    // 学生学号
    @Column(name = "sno")
    private String sno;

    //targetEntity属性表示默认关联的实体类型,默认为当前标注的实体类;
    //cascade属性表示与此实体一对一关联的实体的联级样式类型。联级样式上当对实体进行操作时的策 
    略。
    //·CascadeType.PERSIST (级联新建)
    //·CascadeType.REMOVE (级联删除)
    //·CascadeType.REFRESH (级联刷新)
    //·CascadeType.MERGE (级联更新)中选择一个或多个。
    //·还有一个选择是使用CascadeType.ALL ,表示选择全部四项

    //fetch属性是该实体的加载方式,有两种:LAZY和EAGER。

    //optional属性表示关联的实体是否能够存在null值。默认为true,表示可以存在null值。如果为false,则要同时配合使用@JoinColumn标记。

    //mappedBy属性用于双向关联实体时,标注在不保存关系的实体中。

    @OneToMany(targetEntity = Score.class,mappedBy = "student",cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Score> scores = new HashSet<>();

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getSno() {
        return sno;
    }

    public void setSno(String sno) {
        this.sno = sno;
    }

    public Set<Score> getScores() {
        return scores;
    }

    public void setScores(Set<Score> scores) {
        this.scores = scores;
    }
}

 

给出Score实体类代码

@Entity
@Table(name = "score")
@ApiModel(value="成绩表",description = "这是成绩表")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer"})
public class Score implements Serializable {

    private static final long SerialVersionUID = 1L;



//    @JsonFormat可以帮我们完成格式转换。例如对于Date类型字段,如果不适用JsonFormat默认在rest返回的是long
//    ,如果我们使用@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm:ss”)
//    ,就返回"2020-07-13 22:58:15"




    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private Long id;            //成绩表ID

    @Column(name = "cname")
    private String cname;       //课程名称

    @Column(name = "fraction")
    private Integer fraction;    //课程分数


    //mappedBy = "Studeent" 用来级联
    @JsonIgnoreProperties(value={"scores"})
    @ManyToOne(targetEntity = Student.class)
    @JoinColumn(name="sid",referencedColumnName = "id") //设置外键
    private Student student;

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    public Integer getFraction() {
        return fraction;
    }

    public void setFraction(Integer fraction) {
        this.fraction = fraction;
    }

}

 

 

给出StudentController层的代码

@RestController
@RequestMapping("student/")
@CrossOrigin
public class StudentController {

    @Autowired
    private StudentService studentService;


    /**
    * @Author: M
    * @Description: 根据id查询,此方法调用mybatis实现
    * @DateTime: 2020/7/14
    * @Params: [id]
    * @Return cn.grade.service.entity.Student
    */
    @GetMapping("getByid/{id}")
    public Student queryById(@PathVariable("id") Long id) {
        return this.studentService.queryById(id);
    }

    /**
    * @Author: M
    * @Description: 根据ID查询,此方法为JPA实现
    * @DateTime: 2020/7/14
    * @Params: [id]
    * @Return cn.grade.service.entity.R
    */
    @GetMapping("findByid/{id}")
    public R findById(@PathVariable("id") Long id){
        return studentService.findById(id);
    }

    /**
    * @Author: M
    * @Description: 带条件分页查询
    * @DateTime: 2020/7/14
    * @Params: [current, limit, req]
    * @Return cn.grade.service.entity.R
    */
    @PostMapping("list/{current}/{limit}")
    public R list(@PathVariable int current, @PathVariable int limit,@RequestBody PageStudentREQ req){
        req.setPageNow(current);
        req.setPageSize(limit);
        System.out.println("开始页:"+req.getPageNow());
        return studentService.findAllBySnameContainingAndSnoContaining(req);
    }

    /**
    * @Author: M
    * @Description: 添加或者更新操作
    * @DateTime: 2020/7/14 
    * @Params: [stu]
    * @Return cn.grade.service.entity.R
    */
    @PostMapping("addOrUpdate")
    public R addOrUpdate(@RequestBody Student stu){
        return studentService.add(stu);
    }


    /**
    * @Author: M
    * @Description: 根据ID删除学生
    * @DateTime: 2020/7/14 
    * @Params: [id]
    * @Return cn.grade.service.entity.R
    */
    @DeleteMapping("delete/{id}")
    public R deleteById(@PathVariable("id") Long id){
        if(studentService.del(id)){
            return R.ok();
        }else {
            return R.error();
        }
    }

    /**
    * @Author: M
    * @Description: 验证学号是否存在
    * @DateTime: 2020/7/14
    * @Params: [sno]
    * @Return cn.grade.service.entity.R
    */
    @GetMapping("stuNoValid/{sno}")
    public R stuNoValid(@PathVariable String sno){
        //如果不存在,则为真,返回R.ok
        if(studentService.stuNoValid(sno)) {
            return R.ok().data("info","没有该用户");
        }else {
            //否则返回R.error()
            return R.error();
        }
    }


}

6、前端实现

前端采用vue+element-ui实现

官方网站:https://element.eleme.cn/#/zh-CN

里面有许多的组件,对于开发是非常方便快速的

 

 

页面实现效果

学生成绩管理页面

前端开发工具,采用VS code,运用element-ui提供的模板可以进行快速开发

实现功能

1、带添加分页查询

2、动态显示科目

3、删除

添加页面,可以实现动态添加

 

动态显示

 

也可以对刚刚添加的进行修改操作

 

 

修改成功

 

注:此次前端采用分页带条件模糊查询,因为是动态显示科目

所以每次调用分页方法的时候,都需要初始化一下存放科目的数组

例如,用postman测得后台返回的数据,以第一页为例

{
    "success": true,
    "code": 20000,
    "message": "成功",
    "data": {
        "map": {
            "count": 7,
            "courseNames": [
                "生物",
                "恋爱学",
                "佛系教学",
                "数学",
                "化学",
                "语文",
                "英语",
                "五号恋爱学"
            ],
            "list": [
                {
                    "id": 1,
                    "sname": "张无忌",
                    "sno": "001",
                    "score": 627,
                    "scores": {
                        "恋爱学": 100,
                        "佛系教学": 120,
                        "数学": 150,
                        "语文": 124,
                        "英语": 133
                    }
                },
                {
                    "id": 2,
                    "sname": "李亦非",
                    "sno": "002",
                    "score": 227,
                    "scores": {
                        "化学": 77,
                        "数学": 150
                    }
                },
                {
                    "id": 3,
                    "sname": "小古",
                    "sno": "003",
                    "score": 270,
                    "scores": {
                        "生物": 80,
                        "化学": 90,
                        "五号恋爱学": 100
                    }
                }
            ]
        }
    }
}

 data定义数据

 

调用列表方法

因为此次是动态显示,所以每次分页调用,都需要初始化一下数组对象

分页代码

<!-- 分页 -->
      <el-pagination
        :current-page="page"
        :page-size="limit"
        :total="total"
        style="padding: 30px 0; text-align: center;"
        layout="total, prev, pager, next, jumper"
        @current-change="init"
        @size-change="findSize"
      />

其中,@current-change="init"就是每次改变,调用的方法

init是自定义的方法

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值