2.1-学成在线内容管理之课程查询

内容管理模块

3. 课程查询

3.1 需求分析

3.1.1 业务流程

课程查询的业务流程如下:
1、教学机构人员点击课程管理首先进入课程查询界面,如下:
在这里插入图片描述
在这里插入图片描述

2.在课程进行列表查询页面输入查询条件查询课程信息
当不输入查询条件时输入全部课程信息。
输入查询条件查询符合条件的课程信息。
约束:本教学机构查询本机构的课程信息。

3.1.2 数据模型
下边从查询条件、查询列表两个方面分析数据模型
1、查询条件:
包括:课程名称、课程审核状态、课程发布状态
课程名称:可以模糊搜索
课程审核状态:未提交、已提交、审核通过、审核未通过
课程发布状态:未发布、已发布、已下线
因为是分页查询所以查询条件中还要包括当前页码、每页显示记录数。
2、查询结果:
查询结果中包括:课程id、课程名称、任务数、创建时间、是否付费、审核状态、类型,操作
任务数:该课程所包含的课程计划数,即课程章节数。
是否付费:课程包括免费、收费两种。
类型:录播、直播。
因为是分页查询所以查询结果中还要包括总记录数、当前页、每页显示记录数。

3.2 创建数据库表及PO类型

3.2.1 创建数据库表

1、创建内容管理数据库

用惯了navicat的同学接着用就行,没什么区别

在这里插入图片描述
2、向创建的内容管理数据库导入数据
选择课程资料中的xc_content.sql脚本,这里使用DataGrid 客户端工具连接mysql并执行脚本。
在这里插入图片描述

执行成功,查询course_base数据表,如下:
在这里插入图片描述

3.2.2 生成PO类

PO即持久对象(Persistent Object),它们是由一组属性和属性的get和set方法组成,PO对应于数据库的表。
在开发持久层代码时需要根据数据表编写PO类,在实际开发中通常使用代码生成器(工具)生成PO类的代码。
由于在需求分析阶段对数据模型进行分析,PO类对应于数据模型,所以在需求分析阶段即可使用工具生成PO类,为下面的接口定义准备好模型类。
在企业开发中通常使用代码生成工具去自动生成这些文件,
本项目使用mybatis-plus的generator工程生成PO类、Mapper接口、Mapper的xml文件,地址在:https://github.com/baomidou/generator
将课程资料目录下的xuecheng-plus-generator.zip解压后拷贝至项目工程根目录,如下图:
在这里插入图片描述

打开IDEA将其导入项目工程 ,打开xuecheng-plus-generator工程的pom.xml,右键 点击“Add as Maven Project” 自动识别maven工程。
本次生成内容管理模块的PO类、Mapper接口和Mapper的xml文件 ,找到ContentCodeGenerator类,如下图:
在这里插入图片描述

修改ContentCodeGenerator类中的信息,包括:数据库地址、数据库账号、数据库密码、生成的表、生成路径,如下:

Java
        //数据库账号
        private static final String DATA_SOURCE_USER_NAME  = "root";
        //数据库密码
        private static final String DATA_SOURCE_PASSWORD  = "mysql";
        //生成的表
        private static final String[] TABLE_NAMES = new String[]{
                "course_base",
                "course_market",
                "course_teacher",
                "course_category",
                "teachplan",
                "teachplan_media",
                "course_publish",
                "course_publish_pre"
        };
        // TODO 默认生成entity,需要生成DTO修改此变量
        // 一般情况下要先生成 DTO类 然后修改此参数再生成 PO 类。
        private static final Boolean IS_DTO = false;

        public static void main(String[] args) {
                ....
                //生成路径
                gc.setOutputDir(System.getProperty("user.dir") + "/xuecheng-plus-generator/src/main/java");
                
        ....
        // 数据库配置
                DataSourceConfig dsc = new DataSourceConfig();
                dsc.setDbType(DbType.MYSQL);
                dsc.setUrl("jdbc:mysql://192.168.101.65:3306/xcplus_" + SERVICE_NAME+"166"
                                + "?serverTimezone=UTC&useUnicode=true&useSSL=false&characterEncoding=utf8");
                ...

修改完成,执行该类的main方法,自动生成content包,如下:
在这里插入图片描述

在该包下自动生成了内容管理模块的controller、mapper、po及service相关代码,这里我们只需要po类。
将po类拷贝到model工程

打开一个PO类发现编译报错,这是缺少依赖包导致,本项目使用的持久层框架是MyBatisPlus,在生成的po类中加了一些MyBatisPlus框架的注解,这里需要添加MyBatisPlus框架的依赖,消除错误。
下边在model工程添加依赖

Java
<dependencies>
        <dependency>
            <groupId>com.xuecheng</groupId>
            <artifactId>xuecheng-plus-base</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!--存在mybatisplus注解添加相关注解保证不报错-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-annotation</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-core</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
</dependencies>

3.3 设计接口

3.3.1 接口设计分析

设计一个接口需要包括以下几个方面:
1)协议
通常协议采用HTTP,查询类接口通常为get或post,查询条件较少的使用get,较多的使用post。
本接口使用 http post。
还要确定content-type,参数以什么数据格式提交,结果以什么数据格式响应。
一般情况没有特殊情况结果以json 格式响应。
2)分析请求参数
根据前边对数据模型的分析,请求参数为:课程名称、课程审核状态、当前页码、每页显示记录数。
根据分析的请求参数定义模型类。
3)分析响应结果
根据前边对数据模型的分析,响应结果为数据列表加一些分页信息(总记录数、当前页、每页显示记录数)。
数据列表中数据的属性包括:课程id、课程名称、任务数、创建时间、审核状态、类型。
注意:查询结果中的审核状态为数据字典中的代码字段,前端会根据审核状态代码 找到对应的名称显示。
根据分析的响应结果定义模型类。
4)分析完成,使用SpringBoot注解开发一个Http接口。
5)使用接口文档工具查看接口的内容。
6)接口中调用Service方法完成业务处理。

4)接口请求示例

Java
POST /content/course/list?pageNo=2&pageSize=1
Content-Type: application/json

{
  "auditStatus": "202002",
  "courseName": "",
  "publishStatus":""
}
###成功响应结果
{
  "items": [
    {
      "id": 26,
      "companyId": 1232141425,
      "companyName": null,
      "name": "spring cloud实战",
      "users": "所有人",
      "tags": null,
      "mt": "1-3",
      "mtName": null,
      "st": "1-3-2",
      "stName": null,
      "grade": "200003",
      "teachmode": "201001",
      "description": "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud 基础入门 3.实战Spring Boot 4.注册中心eureka。",
      "pic": "https://cdn.educba.com/academy/wp-content/uploads/2018/08/Spring-BOOT-Interview-questions.jpg",
      "createDate": "2019-09-04 09:56:19",
      "changeDate": "2021-12-26 22:10:38",
      "createPeople": null,
      "changePeople": null,
      "auditStatus": "202002",
      "auditMind": null,
      "auditNums": 0,
      "auditDate": null,
      "auditPeople": null,
      "status": 1,
      "coursePubId": null,
      "coursePubDate": null
    }
  ],
  "counts": 23,
  "page": 2,
  "pageSize": 1
}
3.3.2 定义模型类

根据接口分析需要定义模型类接收请求的参数,并定义模型类用于响应结果。
1、分页查询模型类
由于分页查询这一类的接口在项目较多,这里针对分页查询的参数(当前页码、每页显示记录数)单独在xuecheng-plus-base基础工程中定义。
PageParams
内容如下:

Java
package com.xuecheng.base.model;

import lombok.Data;
import lombok.ToString;
import lombok.extern.java.Log;

/**
 * @description 分页查询通用参数
 * @author Mr.M
 * @date 2022/9/6 14:02
 * @version 1.0
 */
@Data
@ToString
public class PageParams {

  //当前页码
  private Long pageNo = 1L;

  //每页记录数默认值
  private Long pageSize =10L;

  public PageParams(){

  }

  public PageParams(long pageNo,long pageSize){
      this.pageNo = pageNo;
      this.pageSize = pageSize;
  }



}

由于上边类中用到了lombok注解所以在base工程添加依赖包如下:

Java
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

2、查询条件模型类
除了分页查询参数,剩下的就是课程查询的特有参数,此时需要在内容管理的model工程中定义课程查询参数模型类。QueryCourseParamsDto

内容如下:

Java
package com.xuecheng.content.model.dto;

import lombok.Data;
import lombok.ToString;

/**
 * @description 课程查询参数Dto
 * @author Mr.M
 * @date 2022/9/6 14:36
 * @version 1.0
 */
 @Data
 @ToString
public class QueryCourseParamsDto {

  //审核状态
 private String auditStatus;
 //课程名称
 private String courseName;
  //发布状态
 private String publishStatus;

}

3、响应模型类
根据接口分析,下边定义响应结果模型类。
针对分页查询结果经过分析也存在固定的数据和格式,所以在base工程定义一个基础的模型类。

内容如下:

Java
package com.xuecheng.base.model;

import lombok.Data;
import lombok.ToString;

import java.io.Serializable;
import java.util.List;

/**
 * @description 分页查询结果模型类
 * @author Mr.M
 * @date 2022/9/6 14:15
 * @version 1.0
 */
@Data
@ToString
public class PageResult<T> implements Serializable {

    // 数据列表
    private List<T> items;

    //总记录数
    private long counts;

    //当前页码
    private long page;

    //每页记录数
    private long pageSize;

    public PageResult(List<T> items, long counts, long page, long pageSize) {
        this.items = items;
        this.counts = counts;
        this.page = page;
        this.pageSize = pageSize;
    }



}

我们发现此模型类中定义了List属性,此属性存放数据列表,且支持泛型,课程查询接口的返回类型可以是此模型类型。
List中的数据类型用什么呢?根据需求分析使用生成的PO类即可,所以课程查询接口返回结果类型如下:

Java
泛型中填写CourseBase类型。
PageResult<CourseBase>
3.3.3 定义接口

根据分析,此接口提供 HTTP post协议,查询条件以json格式提交,响应结果为json 格式。
可使用SpringBoot注解在Controller类中实现。
1、首先在api工程添加依赖

Java
<dependencies>
    <dependency>
        <groupId>com.xuecheng</groupId>
        <artifactId>xuecheng-plus-content-service</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <!--cloud的基础环境包-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-context</artifactId>
    </dependency>
    <!-- Spring Boot 的 Spring Web MVC 集成 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    
    <!-- 排除 Spring Boot 依赖的日志包冲突 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
    <!-- Spring Boot 集成 log4j2 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

    <!-- Spring Boot 集成 swagger -->
    <dependency>
        <groupId>com.spring4all</groupId>
        <artifactId>swagger-spring-boot-starter</artifactId>
        <version>1.9.0.RELEASE</version>
    </dependency>


</dependencies>

2、定义controller方法

Java
package com.xuecheng.content.api;

import com.xuecheng.base.model.PageParams;
import com.xuecheng.base.model.PageResult;
import com.xuecheng.content.model.dto.QueryCourseParamsDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @description 课程信息编辑接口
 * @author Mr.M
 * @date 2022/9/6 11:29
 * @version 1.0
 */
 @RestController
public class CourseBaseInfoController {

 @RequestMapping("/course/list")
  public PageResult<CourseBase> list(PageParams pageParams, @RequestBody QueryCourseParamsDto queryCourseParams){

      return null;

  }

}

说明:pageParams分页参数通过url的key/value传入,queryCourseParams通过json数据传入,使用@RequestBody注解将json转成QueryCourseParamsDto对象。
3、定义启动类

Java
package com.xuecheng;


import com.spring4all.swagger.EnableSwagger2Doc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
public class ContentApplication {
   public static void main(String[] args) {
      SpringApplication.run(ContentApplication.class, args);
   }
}

3、添加配置文件
创建 log4j2-dev.xml、bootstrap.yml文件。
log4j2-dev.xml:从课程资料/项目工程 获取.
bootstrap.yml内容如下:

一定要注意上一下行的对其格式

Java
server:
  servlet:
    context-path: /content
  port: 63040
#微服务配置
spring:
  application:
    name: content-api
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.101.65:3306/xcplus_content148?serverTimezone=UTC&userUnicode=true&useSSL=false&
    username: root
    password: mysql

日志文件配置路径

logging:
  config: classpath:log4j2-dev.xml

4、下边启动服务,测试接口是否可以正常请求
在controller方法中打断点,debug启动微服务,在浏览器访问http://localhost:63040/content/course/list
浏览器报400错误,400错误通常由于你访问的页面域名不存在或者请求错误。一般是因为我们输入的语法格式有错误,服务器无法理解用户的请求,不知道要表达的是什么。这个时候我们需要认真检查下语义、请求参数是否有误,不然再怎么刷新都没有用。
接口接收两部分参数,一部分是分页参数,它是通过http url传递key/value串,另一部分是业务查询条件,通过http body传入json内容。
服务端使用RequestBody接收json内容,我们在测试并没有传递json内容这里导致错误。
下边在@RequestBody后添加(required=false)表示此参数不是必填项,如下:

 @PostMapping("/course/list")
  public PageResult<CourseBase> list(PageParams pageParams, @RequestBody(required=false) QueryCourseParamsDto queryCourseParams){

      return null;

  }

再次测试,运行到 断点处暂停。

3.3.4 模型类的作用

现在项目中有两类模型类:DTO数据传输对象、PO持久化对象,DTO用于接口层向业务层之间传输数据,PO用于业务层与持久层之间传输数据,有些项目还会设置VO对象,VO对象用在前端与接口层之间传输数据,如下图:
在这里插入图片描述

当前端有多个平台且接口存在差异时就需要设置VO对象用于前端和接口层传输数据。
比如:
课程列表查询接口,根据需求用户在手机端也要查询课程信息,此时课程查询接口是否需要编写手机端和PC端两个接口呢?如果用户要求通过手机和PC的查询条件或查询结果不一样,此时就需要定义两个Controller课程查询接口,每个接口定义VO对象与前端传输数据。
手机查询:根据课程状态查询,查询结果只有课程名称和课程状态。
PC查询:可以根据课程名称、课程状态、课程审核状态等条件查询,查询结果也比手机查询结果内容多。
此时,Service业务层尽量提供一个业务接口,即使两个前端接口需要的数据不一样,Service可以提供一个最全查询结果,由Controller进行数据整合。
如下图:
在这里插入图片描述

如果前端的接口没有多样性且比较固定,此时可以取消VO,只用DTO即可。
如下图:

3.4 生成接口文档

黑马给的是Swagger,大家可以自己去试试knife4j

在前后端分离开发中通常由后端程序员设计接口,完成后需要编写接口文档,最后将文档交给前端工程师,前端工程师参考文档进行开发。
可以通过一些工具快速生成接口文档 ,本项目通过Swagger生成接口在线文档 。
什么是Swagger?
OpenAPI规范(OpenAPI Specification 简称OAS)是Linux基金会的一个项目,试图通过定义一种用来描述API格式或API定义的语言,来规范RESTful服务开发过程,目前版本是V3.0,并且已经发布并开源在github上。
(https://github.com/OAI/OpenAPI-Specification)
Swagger是全球最大的OpenAPI规范(OAS)API开发工具框架,Swagger是一个在线接口文档的生成工具,前后端开发人员依据接口文档进行开发。 (https://swagger.io/)
Spring Boot 可以集成Swagger,Swaager根据Controller类中的注解生成接口文档 ,只要添加Swagger的依赖和配置信息即可使用它。
1、在API工程添加swagger-spring-boot-starter依赖

Java
<!-- Spring Boot 集成 swagger -->
<dependency>
    <groupId>com.spring4all</groupId>
    <artifactId>swagger-spring-boot-starter</artifactId>
</dependency>

2、在 bootstrap.yml中配置swagger的扫描包路径及其它信息,base-package为扫描的包路径,扫描Controller类。

Java
swagger:
  title: "学成在线内容管理系统"
  description: "内容系统管理系统对课程相关信息进行管理"
  base-package: com.xuecheng.content
  enabled: true
  version: 1.0.0

3、在启动类中添加@EnableSwagger2Doc注解
再次启动服务,工程启动起来,访问http://localhost:63040/content/swagger-ui.html查看接口信息
下图为swagger接口文档的界面:
在这里插入图片描述

这个文档存在两个问题:
1、接口名称显示course-base-info-controller名称不直观
2、课程查询是post方式只显示post /course/list即可。
下边进行修改,添加一些接口说明的注解,并且将RequestMapping改为PostMapping,如下:

Bash
 @Api(value = "课程信息编辑接口",tags = "课程信息编辑接口")
 @RestController
public class CourseBaseInfoController {

  @ApiOperation("课程查询接口")
 @PostMapping("/course/list")
  public PageResult<CourseBase> list(PageParams pageParams, @RequestBody(required=false) QueryCourseParamsDto queryCourseParams){

     //....

  }

}

5、再次启动服务,工程启动起来,访问http://localhost:63040/content/swagger-ui.html查看接口信息
下图为swagger接口文档的界面:

接口文档中会有关于接口参数的说明,在模型类上也可以添加注解对模型类中的属性进行说明,方便对接口文档的阅读。
比如:下边标红的属性名称,可以通过swaager注解标注一个中文名称,方便阅读接口文档。

标注的方法非常简单:
找到模型类,在属性上添加注解:

Java
 public class PageParams {
 ...
 @ApiModelProperty("当前页码")
private Long pageNo = 1L;

@ApiModelProperty("每页记录数默认值")
private Long pageSize = 30L;
...
public class QueryCourseParamsDto {

  //审核状态
@ApiModelProperty("审核状态")
 private String auditStatus;
 //课程名称
 @ApiModelProperty("课程名称")
 private String courseName;

}

重启服务,再次进入接口文档,如下图:

Swaager的常用注解如下:
在Java类中添加Swagger的注解即可生成Swagger接口,常用Swagger注解如下:

Java
@Api:修饰整个类,描述Controller的作用
 @ApiOperation:描述一个类的一个方法,或者说一个接口
 @ApiParam:单个参数描述
 @ApiModel:用对象来接收参数
 @ApiModelProperty:用对象接收参数时,描述对象的一个字段
 @ApiResponse:HTTP响应其中1个描述
 @ApiResponses:HTTP响应整体描述
 @ApiIgnore:使用该注解忽略这个API
 @ApiError :发生错误返回的信息
 @ApiImplicitParam:一个请求参数
 @ApiImplicitParams:多个请求参数

@ApiImplicitParam属性如下:
属性	取值	作用
paramType		查询参数类型
	path	以地址的形式提交数据
	query	直接跟参数完成自动映射赋值
	body	以流的形式提交 仅支持POST
	header	参数在request headers 里边提交
	form	以form表单的形式提交 仅支持POST
dataType		参数的数据类型 只作为标志说明,并没有实际验证
	Long	
	String	
name		接收参数名
value		接收参数的意义描述
required		参数是否必填
	true	必填
	false	非必填
defaultValue		默认值

使用Swagger可以进行接口的测试。
修改接口内容,添加一些测试代码
Java

@ApiOperation("课程查询接口")
@PostMapping("/course/list")
public PageResult<CourseBase> list(PageParams pageParams, @RequestBody(required=false) QueryCourseParamsDto queryCourseParams){

    CourseBase courseBase = new CourseBase();
    courseBase.setName("测试名称");
    courseBase.setCreateDate(LocalDateTime.now());
    List<CourseBase> courseBases = new ArrayList();
    courseBases.add(courseBase);
    PageResult pageResult = new PageResult<CourseBase>(courseBases,10,1,10);
    return pageResult;

}

debug方式启动,在 return 处打断点,再用swagger请求接口。
通过下图可以看到请求参数已经正常请求至controller方法

放行继续运行,观察swagger界面,结果可以正常返回

不过存在一个问题就是LocalDateTime类型的数据转json后数据格式并不是我们要的年月日时分秒
在base工程com.xuecheng.base.config包下加配置LocalDateTimeConfig 类实现转json时字符串与LocalDateTime类型的转换,LocalDateTimeConfig 类可从课程资料下的项目工程目录中直接拷贝。

3.5 开发持久层

3.5.1 生成mapper

本项目使用MyBatis-Plus开发持久层,需要创建PO类、Mapper接口、Mapper的xml文件,每个PO类对应数据库的每张表,每张表需要创建一个Mapper接口和Mapper的xml映射文件 。
下边将使用generator工程生成的mapper接口和mapper映射文件 拷贝到service工程 ,如下图:
在这里插入图片描述

service工程即业务层为api接口工程提供业务处理支撑,本项目业务层包括了持久层的代码,一些大型公司的团队职责划分更细,会将持久层和业务层分为两个工程,不过这需要增加成本。
本项目使用持久层框架MyBatis-Plus进行开发,下边将mapper接口和xml文件 拷贝到 service工程 ,拷贝后如下图所示:
在这里插入图片描述

到此mapper接口与mapper映射文件生成完毕。

3.5.2 测试mapper

下边对mapper进行单元测试,测试course_base表的查询接口。
1、下边在service工程的pom.xml中添加依赖

XML
<dependencies>
    <dependency>
        <groupId>com.xuecheng</groupId>
        <artifactId>xuecheng-plus-content-model</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- mybatis plus的依赖 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
    </dependency>
   <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-context</artifactId>
  </dependency>
    <!-- Spring Boot 集成 Junit -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- 排除 Spring Boot 依赖的日志包冲突 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- Spring Boot 集成 log4j2 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

</dependencies>

2、配置扫描mapper及分页插件
从课程资料/工程目录下拷贝MybatisPlusConfig 到 service工程的com.xuecheng.content.config包下:

Java
package com.xuecheng.content.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * <P>
 *        Mybatis-Plus 配置
 * </p>
 */
@Configuration
@MapperScan("com.xuecheng.content.mapper")
public class MybatisPlusConfig {
   /**
    * 定义分页拦截器
    */
   @Bean
   public MybatisPlusInterceptor mybatisPlusInterceptor() {
      MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
      interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
      return interceptor;
   }
   

}

分页插件的原理:
首先分页参数放到ThreadLocal中,拦截执行的sql,根据数据库类型添加对应的分页语句重写sql,例如:(select * from table where a) 转换为 (select count(*) from table where a)和(select * from table where a limit ,)
计算出了total总条数、pageNum当前第几页、pageSize每页大小和当前页的数据,是否为首页,是否为尾页,总页数等。

4、单元测试所需要的配置文件
在test/resources下创建 log4j2-dev.xml、bootstrap.yml:

log4j2-dev.xml:从课程资料/项目工程 获取.
bootstrap.yml:

YAML
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
    username: root
    password: mysql

日志文件配置路径

logging:
  config: classpath:log4j2-dev.xml

5、编写启动类:
单元测试工作在test目录,在test下添加启动类

代码如下:

Java
package com.xuecheng;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ContentApplication {
    public static void main(String[] args) {
        SpringApplication.run(ContentApplication.class, args);
    }
}

6、编写测试类

代码如下:
Java

package com.xuecheng.content;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuecheng.base.model.PageParams;
import com.xuecheng.base.model.PageResult;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.model.dto.QueryCourseParamsDto;
import com.xuecheng.content.model.po.CourseBase;
import org.apache.commons.lang.StringUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class CourseBaseMapperTests {

    @Autowired
    CourseBaseMapper courseBaseMapper;


    @Test
    void testCourseBaseMapper() {
        CourseBase courseBase = courseBaseMapper.selectById(74L);
        Assertions.assertNotNull(courseBase);

        //测试查询接口
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        //查询条件
        QueryCourseParamsDto queryCourseParamsDto = new QueryCourseParamsDto();
        queryCourseParamsDto.setCourseName("java");
        queryCourseParamsDto.setAuditStatus("202004");
        queryCourseParamsDto.setPublishStatus("203001");

        //拼接查询条件
        //根据课程名称模糊查询  name like '%名称%'
        queryWrapper.like(StringUtils.isNotEmpty(queryCourseParamsDto.getCourseName()),CourseBase::getName,queryCourseParamsDto.getCourseName());
        //根据课程审核状态
        queryWrapper.eq(StringUtils.isNotEmpty(queryCourseParamsDto.getAuditStatus()),CourseBase::getAuditStatus,queryCourseParamsDto.getAuditStatus());



        //分页参数
        PageParams pageParams = new PageParams();
        pageParams.setPageNo(1L);//页码
        pageParams.setPageSize(3L);//每页记录数
        Page<CourseBase> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());

        //分页查询E page 分页参数, @Param("ew") Wrapper<T> queryWrapper 查询条件
        Page<CourseBase> pageResult = courseBaseMapper.selectPage(page, queryWrapper);

        //数据
        List<CourseBase> items = pageResult.getRecords();
        //总记录数
        long total = pageResult.getTotal();

        //准备返回数据 List<T> items, long counts, long page, long pageSize
        PageResult<CourseBase> courseBasePageResult = new PageResult<>(items, total, pageParams.getPageNo(), pageParams.getPageSize());
        System.out.println(courseBasePageResult);
    }

}

运行测试类的测试方法进行测试,测试成功:

3.6 开发业务层

3.6.1 创建数据字典表

课程基本信息查询的主要数据来源是课程基本信息表,这里有一个点需要注意,就是课程的审核状态、发布状态。
审核状态在查询条件和查询结果中都存在,审核状态包括:未审核、审核通过、审核未通过三种,下边思考一个问题:一个课程的审核状态如果是“审核未通过”那么在课程基本信息表记录“审核未通过”三个字合适吗?
如果将“审核未通过”五个字记录在课程基本信息表中,显示出来的审核状态就是“审核未通过”这五个字,看起来没有什么问题,如果有一天客户想要将审核未通过的记录在显示时改为“未通过”三个字,怎么办?
这时你可以需要批量处理数据库中记录了,写一个 update 语句,审核状态等于“审核未通过”的全部更新 为“未通过”。看起来解决了问题,如果有一天客户又让改了呢?
和审核状态同类的有好多这样的信息,比如:课程状态、课程类型、用户类型等等,这一类数据有一个共同点就是它有一些分类项,且这些分类项较为固定。针对这些数据,为了提高系统的可扩展性,专门定义数据字典表去维护。
下边是课程审核状态的定义:

[
{“code”:“202001”,“desc”:“审核未通过”},
{“code”:“202002”,“desc”:“未审核”},
{“code”:“202003”,“desc”:“审核通过”}
]

每一项都由代码和名称组成。
此时我们好像要干 什么了 ,该课程 的审核状态为审核未通过,那么我们在课程基本信息表存储202001,也就是审核未通过对应的代码,这样查询出的数据在前端展示时根据代码取出它对应的内容显示给用户。如果用户要修改“审核未通过”的显示内容只需要在数据字典表修改,无法修改课程基本信息表。
数据字典表在系统管理数据库中存储,首先导入系统管理数据库,创建系统管理服务的数据库

创建成功如下图:
在这里插入图片描述

创建系统管理的数据库,导入课程资料中的xcplus_system.sql脚本。

3.6.2 编写Service

接下来开发Service方法,首先创建Service接口:

Java
package com.xuecheng.content.service;

import com.xuecheng.base.model.PageParams;
import com.xuecheng.base.model.PageResult;
import com.xuecheng.content.model.dto.QueryCourseParamsDto;
import com.xuecheng.content.model.po.CourseBase;

/**
 * @description 课程基本信息管理业务接口
 * @author Mr.M
 * @date 2022/9/6 21:42
 * @version 1.0
 /
public interface CourseBaseInfoService  {

 /*
  * @description 课程查询接口
  * @param pageParams 分页参数
  * @param queryCourseParamsDto 条件条件
  * @return com.xuecheng.base.model.PageResult<com.xuecheng.content.model.po.CourseBase>
  * @author Mr.M
  * @date 2022/9/6 21:44
 */
  PageResult<CourseBase> queryCourseBaseList(PageParams pageParams, QueryCourseParamsDto queryCourseParamsDto);

 }

再创建接口实现类

Java
package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuecheng.base.model.PageParams;
import com.xuecheng.base.model.PageResult;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.model.dto.QueryCourseParamsDto;
import com.xuecheng.content.model.po.CourseBase;
import com.xuecheng.content.service.CourseBaseInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @description 课程信息管理业务接口实现类
 * @author Mr.M
 * @date 2022/9/6 21:45
 * @version 1.0
 */
@Service
public class CourseBaseInfoServiceImpl  implements CourseBaseInfoService {


 @Autowired
 CourseBaseMapper courseBaseMapper;

 @Override
 public PageResult<CourseBase> queryCourseBaseList(PageParams pageParams, QueryCourseParamsDto queryCourseParamsDto) {


  //构建查询条件对象
  LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
  //构建查询条件,根据课程名称查询
     queryWrapper.like(StringUtils.isNotEmpty(queryCourseParamsDto.getCourseName()),CourseBase::getName,queryCourseParamsDto.getCourseName());
  //构建查询条件,根据课程审核状态查询
     queryWrapper.eq(StringUtils.isNotEmpty(queryCourseParamsDto.getAuditStatus()),CourseBase::getAuditStatus,queryCourseParamsDto.getAuditStatus());
//构建查询条件,根据课程发布状态查询
//todo:根据课程发布状态查询 

  //分页对象
  Page<CourseBase> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());
  // 查询数据内容获得结果
  Page<CourseBase> pageResult = courseBaseMapper.selectPage(page, queryWrapper);
  // 获取数据列表
  List<CourseBase> list = pageResult.getRecords();
  // 获取数据总数
  long total = pageResult.getTotal();
  // 构建结果集
  PageResult<CourseBase> courseBasePageResult = new PageResult<>(list, total, pageParams.getPageNo(), pageParams.getPageSize());
  return courseBasePageResult;


 }


}
3.6.3 测试service

下边对service进行单元测试,编写单元测试类:

Java
package com.xuecheng.content;

import com.xuecheng.base.model.PageParams;
import com.xuecheng.base.model.PageResult;
import com.xuecheng.content.model.dto.QueryCourseParamsDto;
import com.xuecheng.content.model.po.CourseBase;
import com.xuecheng.content.service.CourseBaseInfoService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class CourseBaseInfoServiceTests {

    @Autowired
    CourseBaseInfoService courseBaseInfoService;


    @Test
    void testCourseBaseInfoService() {
        //查询条件
        QueryCourseParamsDto queryCourseParamsDto = new QueryCourseParamsDto();
        queryCourseParamsDto.setCourseName("java");
        queryCourseParamsDto.setAuditStatus("202004");
        queryCourseParamsDto.setPublishStatus("203001");

        //分页参数
        PageParams pageParams = new PageParams();
        pageParams.setPageNo(1L);//页码
        pageParams.setPageSize(3L);//每页记录数

        PageResult<CourseBase> courseBasePageResult = courseBaseInfoService.queryCourseBaseList(pageParams, queryCourseParamsDto);
        System.out.println(courseBasePageResult);
    }

}
3.6.4 完善todo

课下完成service方法中的todo:根据课程发布状态查询课程信息。

3.7 接口测试

3.7.1 接口完善

控制层、业务层以及持久层三层通常可以面向接口并行开发,比如:业务层开发的同事可以先只编写一个Service接口,接口层的同事即可面向Service接口去开发,待接口层和业务层完成后进行连调。
下边课程查询接口的实现。

Java
 @ApiOperation("课程查询接口")
@PostMapping("/course/list")
 public PageResult<CourseBase> list(PageParams pageParams, @RequestBody QueryCourseParamsDto queryCourseParams){
     PageResult<CourseBase> pageResult = courseBaseInfoService.queryCourseBaseList(pageParams, queryCourseParams);
    return pageResult;
 }

代码编辑完毕,再次打开Swagger进行测试。
输入查询条件:

测试,观察结果是否正确。

3.7.2 Httpclient测试

Swagger是一个在线接口文档,虽然使用它也能测试但需要浏览器进入Swagger,最关键的是它并不能保存测试数据。
在IDEA中有一个非常方便的http接口测试工具httpclient,下边介绍它的使用方法,后边我们会用它进行接口测试。
如果IDEA版本较低没有自带httpclient,需要安装httpclient插件
在这里插入图片描述

进入controller类,找到http接口对应的方法
在这里插入图片描述

点击Generate request in HTTP Client即可生成的一个测试用例。
在这里插入图片描述

可以看到自己生成了一个.http结尾的文件
我们可以添加请求参数进行测试
在这里插入图片描述

参数添加完毕可以运行它
在这里插入图片描述

观察控制台,测试通过。

Java
http://localhost:63040/course/list?pageNo=2&pageSize=10

HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 07 Sep 2022 00:54:50 GMT
Keep-Alive: timeout=60
Connection: keep-alive

{
  "items": [
    {
      "id": 88,
      "companyId": 1232141425,
      "companyName": null,
      "name": "1",
      "users": "1",
      "tags": "1",
      "mt": "1-1",
      "mtName": null,
      "st": "1-1-1",
      "stName": null,
      "grade": "204001",
      "teachmode": "200002",
      "description": "1",
      "pic": "http://r3zc5rung.hd-bkt.clouddn.com/cb1b6038-ef68-4362-8c29-a966886d1dc5sakUiFHLb5sRFdIK",
      "createDate": "2021-12-27 20:14:53",
      "changeDate": "2021-12-27 20:28:58",
      "createPeople": null,
      "changePeople": null,
      "auditStatus": "202002",
      "auditMind": null,
      "auditNums": 0,
      "auditDate": null,
      "auditPeople": null,
      "status": 1,
      "coursePubId": null,
      "coursePubDate": null
    },
   ....
  ],
  "counts": 14,
  "page": 2,
  "pageSize": 10
}
Response file saved.
> 2022-09-07T085450.200.json

Response code: 200; Time: 392ms (392 ms); Content length: 1916 bytes (1.92 kB)

.http文件即测试用例文档 ,它可以随着项目工程一起保存,这样测试的数据就可以保存下来,方便进行测试。
为了方便保存.http文件 ,我们单独在项目工程的根目录创建一个目录单独存放它们。

我们以模块为单位创建.http文件。

打开内容管理模块的 http文件 ,把刚才测试数据拷贝上去

为了方便将来和网关集成测试,这里我们把测试主机地址在配置文件http-client.env.json 中配置

注意:文件名称http-client.env.json保持一致,否则无法读取dev环境变量的内容。
内容如下:

Java
{
  "dev": {
    "access_token": "",
    "gateway_host": "localhost:63010",
    "content_host": "localhost:63040",
    "system_host": "localhost:63110",
    "media_host": "localhost:63050",
    "search_host": "localhost:63080",
    "auth_host": "localhost:63070",
    "checkcode_host": "localhost:63075",
    "learning_host": "localhost:63020"
  }
}

再回到xc-content-api.http文件,将http://localhost:63040 用变量代替

到此就完成了httpclient的配置与使用测试。

3.8 前后端联调

3.8.1准备环境

什么是前后端联调?
通常由后端工程师将接口设计好并编写接口文档,将接口文档交给前端工程师,前后端的工程师就开始并行开发,前端开发人员会使用mock数据(假数据)进行开发,当前后端代码完成后开始进行接口联调,前端工程师将mock数据改为请求后端接口获取,前端代码请求后端服务测试接口是否正常,这个过程是前后端联调。
当前后端联调出现问题需要根据测试环境下接口的请求及响应数据内容去判断是否符合接口文档的要求。查出是前端或后端的问题由具体的工程师负责修改缺陷,修改后再次回归测试。
在教学中进行前后端联调,首先配置前端环境,下边我们安装前端工程运行的环境。
首先从软件工具目录找到node-v16.17.0-x64.msi安装nodejs
安装完成,查看版本号

对于node.js的版本管理可以看mvn的管理

在这里插入图片描述

在idea中配置node.js的路径
在这里插入图片描述

我个人觉得,就用vscode就行了,还简单一些

下边启动前端工程,从前端工程拷贝project-xczx2-portal-vue-ts.zip到代码目录并解压,并使用IDEA或VS Code打开project-xczx2-portal-vue-ts目录,下边以IDEA为例进行说明:
右键点击project-xczx2-portal-vue-ts目录下的package.json文件,
在这里插入图片描述

点击Show npm Scripts打开npm窗口
在这里插入图片描述

点击“Edit ‘serve’” setting,下边对启动项目的一些参数进行配置,选择nodejs、npm。
在这里插入图片描述

右键点击Serve,点击“Run serve”启动工程。
在这里插入图片描述

出现如下访问链接说明启动成功
在这里插入图片描述

访问http://localhost:8601即可访问前端工程。

如果存在问题通过以下命令启动:
1、cmd进入工程根目录
2、运行以下命令

npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm i
npm run serve

3.8.2 安装系统管理服务

启动前端工程成功,在浏览器通过http://localhost:8601/地址访问前端工程。
前端工程报错如下:
在这里插入图片描述

http://localhost:8601/system/dictionary/all 指向的是系统管理服务。在前端讲解内容管理模块的需求时我们提到一个数据字典表,此链接正是在前端请求后端获取数据字典数据的接口地址。
数据字典表中配置了项目用的字典信息,此接口是查询字典中的全部数据 ,在此我们不再开发,按照下边的步骤安装系统管理服务即可。
从课程资料/项目工程目录获取xuecheng-plus-system.zip,并解压
将xuecheng-plus-system目录拷贝到项目工程根目录,刷新maven,或进入pom.xml右键转为pom工程。
在这里插入图片描述

进入xuecheng-plus-system-service工程,找到resources下的application.yml修改数据库连接参数。
启动系统管理服务,启动成功,在浏览器请求:http://localhost:63110/system/dictionary/all
系统服务的端口是63110
如果可以正常读取数据字典信息则说明系统管理服务安装成功。

3.8.3 解决跨域问题

在浏览器通过http://localhost:8601/地址访问前端工程。
chrome浏览器报错如下:

Access to XMLHttpRequest at
‘http://localhost:63110/system/dictionary/all’ from origin
‘http://localhost:8601’ has been blocked by CORS policy: No
‘Access-Control-Allow-Origin’ header is present on the requested
resource.

firefox浏览器报错如下:

已拦截跨源请求:同源策略禁止读取位于 http://localhost:63110/system/dictionary/all
的远程资源。(原因:CORS 头缺少 ‘Access-Control-Allow-Origin’)。状态码:200。

提示:从http://localhost:8601访问http://localhost:63110/system/dictionary/all被CORS
policy阻止,因为没有Access-Control-Allow-Origin 头信息。CORS全称是 cross origin
resource share 表示跨域资源共享。

出这个提示的原因是基于浏览器的同源策略,去判断是否跨域请求,同源策略是浏览器的一种安全机制,从一个地址请求另一个地址,如果协议、主机、端口三者全部一致则不属于跨域,否则有一个不一致就是跨域请求。
比如:
从http://localhost:8601 到 http://localhost:8602 由于端口不同,是跨域。
从http://192.168.101.10:8601 到 http://192.168.101.11:8601 由于主机不同,是跨域。
从http://192.168.101.10:8601 到 https://192.168.101.10:8601 由于协议不同,是跨域。
注意:服务器之间不存在跨域请求。
浏览器判断是跨域请求会在请求头上添加origin,表示这个请求来源哪里。
比如:

Plaintext GET / HTTP/1.1 Origin: http://localhost:8601
服务器收到请求判断这个Origin是否允许跨域,如果允许则在响应头中说明允许该来源的跨域请求,如下: Plaintext
Access-Control-Allow-Origin:http://localhost:8601
如果允许任何域名来源的跨域请求,则响应如下: Plaintext Access-Control-Allow-Origin:*

解决跨域的方法:
1、JSONP
通过script标签的src属性进行跨域请求,如果服务端要响应内容则首先读取请求参数callback的值,callback是一个回调函数的名称,服务端读取callback的值后将响应内容通过调用callback函数的方式告诉请求方。如下图:
在这里插入图片描述

2、添加响应头
服务端在响应头添加 Access-Control-Allow-Origin:*

3、通过nginx代理跨域
由于服务端之间没有跨域,浏览器通过nginx去访问跨域地址。
在这里插入图片描述

1)浏览器先访问http://192.168.101.10:8601 nginx提供的地址,进入页面
2)此页面要跨域访问http://192.168.101.11:8601 ,不能直接跨域访问http://www.baidu.com:8601 ,而是访问nginx的一个同源地址,比如:http://192.168.101.11:8601/api ,通过http://192.168.101.11:8601/api 的代理去访问http://www.baidu.com:8601。
这样就实现了跨域访问。
浏览器到http://192.168.101.11:8601/api 没有跨域
nginx到http://www.baidu.com:8601通过服务端通信,没有跨域。

我们准备使用方案2解决跨域问题。在内容管理的api工程config包下编写GlobalCorsConfig.java,
或直接从课程资料/项目工程下拷贝,
代码如下:

Java
package com.xuecheng.system.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * @description 跨域过虑器
 * @author Mr.M
 * @date 2022/9/7 11:04
 * @version 1.0
 */
 @Configuration
 public class GlobalCorsConfig {

  /**
   * 允许跨域调用的过滤器
   */
  @Bean
  public CorsFilter corsFilter() {
   CorsConfiguration config = new CorsConfiguration();
   //允许白名单域名进行跨域调用
   config.addAllowedOrigin("*");
   //允许跨越发送cookie
   config.setAllowCredentials(true);
   //放行全部原始头信息
   config.addAllowedHeader("*");
   //允许所有请求方法跨域调用
   config.addAllowedMethod("*");
   UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
   source.registerCorsConfiguration("/**", config);
   return new CorsFilter(source);
  }
 }

此配置类实现了跨域过虑器,在响应头添加Access-Control-Allow-Origin。
重启系统管理服务,前端工程可以正常进入http://localhost:8601,观察浏览器记录,成功解决跨域。
在这里插入图片描述

3.8.4 前后端联调

这里进行前后联调的目的是体会前后端联调的流程,测试的功能为课程查询功能。
1、启动前端工程,再启内容管理服务端。
2、修改服务端地址
前端默认连接的是项目的网关地址,由于现在网关工程还没有创建,这里需要更改前端工程的参数配置文件 ,修改网关地址为内容管理服务的地址。
在这里插入图片描述

启动前端工程,用前端访问后端接口,观察前端界面的数据是否正确。
访问前端首页,进入课程管理:http://localhost:8601/#/organization/course-list
在这里插入图片描述

更改课程条件及分页参数测试课程查询列表是否正常显示。
跟踪内容管理服务的输出日志,查看是否正常。
到此基本完成了前后端连调。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
课程设计说明书 NO. "学生成绩管理系统 " "1学习成绩管理系统的设计目的 " "(1)进一步掌握和利用Visual FoxPro进行设计的能力; " "(2)进一步理解和运用结构化程设计的思想和方法; " "(3)初步掌握开发一个小型实用系统的基本方法; " "(4)学会设计一个较长数据库的基本方法; " "(5)学会设计E-R图和把E-R图转化成关系模式; " "(6)掌握书写程序设计开发菜单等模块的能力(书写课程设计报告)。 " "2需求分析 " "该部分是通过对系统的终端用户和客户进行调研后编写的,充分明确系统的终端用" "户和客户对本系统提出的要求。 " "(1)要求系统提供学生信息和成绩信息的录入、修改、删除等功能,从而对考生 " "的信息和成绩进行日常管理。 " "(2)要求系统提供可以按学校、姓名和考号中的任何一种方式,对考生的成绩进 " "行查询、统计。 " "(3)退出系统应保留考生的历史信息,以备日后查询。 " "(4)要求能够打印出学生成绩。 " "2.1数据需求 " "在调研过程中,用户提供了所需数据表。这些数据表包括:学生信息、班级信息、" "院系信息、课程、教师、成绩等。 " "2.2功能需求 " "信息录入 " "录入以上数据表中的数据,还要求能进行修改。这些数据包括:学生信息、班级信" "息、院系信息、课程、教师、成绩等。 " "查询 " "能查询学生基本信息、学生成绩。可以计算学生数据、统计学生中,及格的人数、" "不及格人数、平均成绩。 " "打印 " "打印需要的学生的成绩表。 " 沈 阳 大 学 课程设计说明书 NO. "2.4系统功能图 " " " "图(1) " "3数据库设计 " "3.1概念设计 " "照用户的观点来对数据和信息建模。从上面的需求分析中可以归纳出了4个实体, " "其分别为:学生、班级、系、教师。其属性以下进行说明。 " 沈 阳 大 学 课程设计说明书 NO. "为方便学生信息的查找,学生的属性应该设有:学号、姓名、性别。所以在E-R图 " "中学生实体应如图(2)所示 " " " "图(2) " "实体:学生被分配到不同的班级,因此,我们把班级的属性归纳为:班级编号、班" "级名称。 " " " "图(3) " "如上面分析,把系的属性设为系编号、系名称、系主任,如图(4)。把教师属性 " "设为教师编号、教师姓名、性别、所属系,如图(5)。 " " " 沈 阳 大 学 课程设计说明书 NO. " " " " "课程的属性E-R图如图(6)所示。 " " " 沈 阳 大 学 课程设计说明书 NO. "因此,此系统的课程设计如图(7)所示。 " " " 沈 阳 大 学 课程设计说明书 NO. "3.2逻辑设计 " "给出系统的关系模式。 " "学生(学号,姓名,性别,班级编号) " "班级(班级编号,班级名称,所属系) " "课程课程编号,课程名称,教师编号,学分) " "教师(教师编号,教师姓名,性别,系编号) " "成绩(学生编号,课程编号,成绩) " "3.3物理设计 " "3.3.1数据表的设计 " ""学生"表 " "学生表的字段名、类型、宽度、小数位数等如图(8)所示。 " " " " " " " ""班级"表 " "班级表的字段名、类型、宽度、小数位数等如图(9)所示。 " 沈 阳 大 学 课程设计说明书 NO. " " " " ""系"表 " " " " " ""教师"表 " "教师表字段名、类型、宽度、小数位数等如图(11)所示。 " 沈 阳 大 学 课程设计说明书 NO. " " " " ""课程"表 " " " " " ""成绩"表 " "成绩表字段名、类型、宽度、小数位数等如图(13)所示。 " 沈 阳 大 学 课程设计说明书 NO. " " " " "3.3.2建立索引 " "学生表中学号为主索引 " " " 沈 阳 大 学 课程设计说明书 NO. "班级表中主索引为班级编号 " " " " " "课程表中主索引为课程编号 " " " 沈 阳 大 学 课程设计说明书 NO. " " "教师表中主索引为教师编号 " " " " " "系表中的主索引为系编号 " " " 沈 阳 大 学 课程设计说明书 NO. "成绩表中无主索引 " " " " " "各表之间关系如图(20)所示 " " " 沈 阳 大 学 课程设计说明书 NO. "4各功能模块的创建 " "4.1菜单模块设计 " "菜单以分类分级别的形式来例举应用程序的主要功能,方便用户的使用。根据学生 " "成绩管理系统要实现的功能,应包含以下菜单。 " "查询:通过该菜单的子菜单来浏览数据库中各种信息,但是不能修改。 " "维护:通过该菜单的子菜单来添加、修改或者删除数据库中的
软件课程设计-员工信息管理系统 枣 庄 学 院 信息科学与工程学院课程设计任务书 题 目: 企业员工信息管理系统 学 生1: 贺 佳 学 生2: 安 新 学 生3: 武 艳 飞 学 生4: 区 丽 君 专 业: 计算机科学与技术 课 程: 软件工程 指导教师: 姜振凤 职 称: 讲 师 完成时间: 2013年 5 月----2013 年 6月 课程设计任务书及成绩评定 "课程设计的任务和具体要求 " "任务: " "综合运用软件工程的思想和先修课程的相关知识,完成一个信息系统的开" "发,掌握软件工程生命周期的技术和方法。 " "具体要求: " "1.学生2-4人组成一个项目小组,第一人为组长,其他人为组员,组内成" "员分工明确、团结协作、相互配合,共同完成课程设计; " "2.要求每组成员对本小组自选系统首先进行认真分析,写出详细的设计 " "步骤; " "3.课程设计必须按照软件开发的具体过程进行设计,每个阶段都要有详 " "细的文字、数据、图进行说明; " "4.各设计阶段的模型请采用专门工具Visio、PowerDesigner来完成; " "5.课程设计要思想清晰、明确,排版整齐,严格按照模板要求进行组织 " "撰写。 " "6.课程设计时间为4周。 " "7.课程设计报告要求不少于2000字; " "8. 请选择面向过程的设计方法或面向对象的设计方法。 " "9.课程设计要有总结:总结课程设计的过程、体会。 " "10. 其他:参考文献等。 " " " "指导教师签字: 日期: " "指导教师评语 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "成绩: 指导教师签字: 日期: " " " " " " " "课程设计所需软件、硬件等 " "Windows操作系统. " "Microsoft Office Visio 2003 " "SQL server数据库. " "PowerDesigner " " " " " " " " " " " "课程设计进度计划 " "起至日期 "工作内容 "备注 " "2013.05.15-05.16 " 确定研究课题 " " "2013.05.17-05.21 "收集课题相关资料 " " "2013.05.22-05.25 "进行可行性分析 " " "2013.05.26-05.30 "进行需求分析 " " "2013.06.01-06.10 "软件设计及测试 " " "2013.06.11-06.14 "撰写课程设计报告 " " "参考文献、资料索引 " "序号 "文献、资料名称 "编著者 "出版单位 " "[1] 曾长军,朱剑锋,刘坤.SQL Server数据库原理及应用[M].人民邮电 " "出版社,2005年02月. " "[2] 刘慧宁,那盟.JAVA程序设计[M].机械工业出版社,2006年01月. " "[3] Christopher Allen, Simon Chatwin, Catherine A.Creary[美]著, " "皮人杰,任鸿译.关系数据库和SQL编程[M].清华大学出版社,2005年12月" ". " " " " " " " 目 录 1 概述 1 1.1 设计目的 1 1.2 设计背景 1 1.3开发环境 2 1.4小组分工 2 2 可行性分析 2 2.1技术可行性分析 2 2.2社会可行性分析 2 2.3经济可行性分析 2 2.4操作可行性分析 3 3需求分析 3 3.1需分析的任务求 3 3.1.1界面要求 3 3.1.2功能要求 3 3.2子功能需求 3 3.3数据流图DFD 5 3.3.1顶层数据流图 5 3.3.2一层数据流图 5 3.3.3二层数据流图 6 3.4数据字典 7 3.4.1数据源点描述: 7 3.4.2加工逻辑词条描述 7 3.4.3数据流名词条描述: 7 3.4.4数据文件词条描述: 8 4.软件设计 8 4.1概要设计 8 4.1.1 系统层次结构图 8 4.1.2系统IPO图 9 4.2 详细设计 11 4.2.1登录模块 11 4.2.2 人事管理模块 11 4.2.3 工资管理模块 12 4.2.4系统管理模块 13 4.3数据库设计 14 5 软件实现 15 5.1登陆界面 15 5.2添加员工基本信息 16 5.3修改员工基本信息 17 5.4 查询员工基本信息 18 6 软件测试报告 18 6.1.测试方案 18 6.2. 测试条目 18 6.3设计测试用例 19 6.4. 测试结论 20 7 总结 20 参考文献 21 1 概述 自上个世纪90年代以来,计算机技术的迅猛发展和推广普及,为各行各业突飞猛进的 发展带来
C语言程序设计 课 程 设 计 题 目 图书馆管理系统 系 (部) 信息工程系 班 级 姓 名 学 号 指导教师 2015年 月 日至 月 日 共 周 年 月 日 C语言程序设计 课程设计任务书 "一、设计题目、内容及要求 " "题目:图书馆管理系统设计 " "内容:本题目适合于学校图书馆的资料管理和检索。要求程序实现分级管理" ",管理员可对图书和学生信息进行录入、查询、修改、输出、删除、插入、" "保存等操作。 " "要求:程序结构合理、算法准确、语法正确,并生成可执行文件。 " "二、要求的设计成果(课程设计说明书、设计实物、图纸等) " "1. 课程设计说明书:课程设计说明书1份,不少于2000字。说明书中要包含 " "需求分析、总体设计、详细设计以及主要的算法描述等内容。 " "2. 源代码:图书馆管理系统程序清单 " "三、进程安排 " "星期1(7.6):完成需求分析和程序总体设计。 " "星期2(7.7):完成数据录入、删除、修改、插入和浏览功能模块的设计。 " "星期3(7.8):完成密码设置和数据检索模块,程序调试无误,生成可执行文" "件。 " "星期4(7.9):撰写课程设计说明书初稿。 " "星期5(7.10):提交课程设计说明书、程序和数据。 " "四、主要参考资料 " "[1] 谭浩强,张基温.C语言程序设计教程(第3版)[M].北京:高等教育出 " "版社,2006 " "[2] " "吕凤煮.C语言基础教程——基础理论与案例[M].北京:清华大学出版社,20" "05 " "[3] " "黄明、梁旭、万洪莉.C语言课程设计[M].北京:电子工业出版社,2006 " "[4] 郭宁,郑小玲.管理信息系统[M].北京:人民邮电出版社,2006 " "[5] " "赵池龙,杨林,陈伟.实用软件工程[M].北京:电子工业出版社,2006 " "指导教师(签名): "教研室主任(签名): " 课程设计成绩评定表 "出勤 "出勤天数 " " "情况 " " " " "缺勤天数 " " "成 "出勤情况及设计过程表现(20分) " " "绩 " " " "评 " " " "定 " " " " "课设答辩(20分) " " " "设计成果(60分) " " " "总成绩(100分) " " "提问 " " "(答辩) " " "问题 " " "情况 " " " " " " " " " " " " " " "综 " " "合 " " "评 " " "定 " " " " " " " " " " " " "指导教师签名: " " "年 月 日 " 引言 图书馆管理系统的需求分析主要确定系统的主要功能,对系统进行概要描述,对系统 的各个主要功能分别进行需求描述,目的是使软件在设计过程中尽量符合客户的需要。 图书馆管理系统是一个对学生和图书信息进行录入、查询、修改、输出、删除、插入 、保存等操作的管理应用软件,用户可以对文件中存储的学生和图书信息进行查找和浏 览。该软件提供了一个简单的人机界面,管理员可以根据提示输入操作项并进行一系列 对学生和图书的信息资料的管理操作 本系统主要应用结构化的设计思想实现学生和图书信息的增、删、改和查等典型管理 功能。各主要模块的数据均存储在文件中,因此包含对文件的读、写等基本操作。在软 件开发过程中应用了高级语言程序设计中的基本控制结构,如选择、循环、顺序结构。 系统的设计方法是结构化设计方法,采用C语言进行开发。 2 总体设计 图书馆的信息管理和检索系统的需求分析主要确定系统的主要功能,对系统进行概要 描述,对系统的各个主要功能分别进行需求描述,目的是使软件在设计过程中尽量符合 客户的需要。 2.1 系统概述 将程序整体进行模块化处理,使程序编译思路更加清晰,降低了编译程序的难度。图 书信息中包含学生姓名、性别、系别、班级、学号、借书时间、还书时间和图书的书名 、作者、图书编号等基本信息,程序具有信息录入、删除、修改、浏览、检索和保存功 能。 2.2 功能需求 该软件提供了一个对图书和学生信息进行管理和查看的平台,给用户提供了一个简单 友好的用户接口,功能需求如下: 2.2.1密码系统 通过已定密码进入对应管理目录,从而进行相应的操作功能。 2.2.2信息录入 根据提示输入学生的姓名、性别、系别、班级、学号和图书书名、作者、图书编号等 信息要素。 2.2.3信息查询 使用者可以根据系统提示按学生姓名、系别、班级、学号查询学生信息或按图书书名、 作者、图书编号查询图书信息。 2.2.4信息修改 使用者可以根据系统提示对系统中存在的学生的姓名、性别、系别、班级、学号、借 书时间、还书时间和图书书名、作者、图书编号等信息进行修改。 2.2.5信息输出 可输出学生姓名,性别,系别,班级,学号
郑州大学西亚斯国际学院 《数据库原理与应用》 课程设计报告 课程名称 数据库原理与应用 设计题目 人事管理系统 专业班级 软件工程1班 学生姓名 XXXX 学 号 2015XXXX44 指导教师 XXXX 2016年 12 月 14 日 前言 数据库技术是计算机科学技术发展最快,应用最为广泛的技术之一.其在计算机设计,人 工智能,电子商务,企业管理,科学计算等诸多领域均得到了广泛的应用,已经成为计 算机信息系统和应用的核心技术和重要基础。 随着信息技术的飞速发展,信息化的大环境给各成人高校提出了实现校际互联,国际互 联,实现静态资源共享,动态信息发布的要求; 信息化对学生个人提出了驾驭和掌握最新信息技术的素质要求;信息技术提供了对教学进 行重大革新的新手段;信息化也为提高教学质量,提高管理水平,工作效率创造了有效途 径. 校园网信息系统建设的重要性越来越为成人高校所重视。 利用计算机支持教学高效率,完成教学管理的日常事务,是适应现代教学制度要求、推动 教学管理走向科学化、规范化的必要条件;而教学管理是一项琐碎、复杂而又十分细致的 工作,工资计算、发放、核算的工作量很大,不允许出错,如果实行手工操作,每月须手工 填制大量的表格,这就会耗费工作人员大量的时间和精力,计算机进行教学管理工作, 不仅能够保证各项准确无误、快速输出,而且还可以利用计算机对有关教学的各种信息 进行统计,同时计算机具有手工管理所无法比拟的优点. 例如:检索迅速、查找方便、可靠性高、存储量大、保密性好、寿命长、成本低等。这 些优点能够极大地提高员工工资管理的效率,也是教学的科学化、正规化管理,与世界接 轨的件. 在软件开发的过程中,随着面向对象程序设计和数据库系统的成熟,数计成为软件开发的 核心,程序的设计要服从数据,因此教学管理系统的数据库设计尤其重要。本文主要介 绍教学管理系统的数据库方面的设计,从需求分析到数据库的运行与维护都进行详细的 叙述. 目录 —-—-—-———-——--——---——--—--—-—-----—--—————--—---—————-——--——-———----——————-- ——------——-—----—--—-—--—— 1. —-————-—————-—----—--基本情况与需求分析 二、———-—--——-———--—-——-----——-—功能模块划分 三、——-—----——————————-------—--概念结构设计 四、--——-—-———---——-—-——-------—逻辑结构设计 五、--—--—-——--—-——----———课程设计的心得体会 ---—-———-—---—-——--—-----—--—————--————--—--——-—-----—------—----—----—————- ---—----—---—-——--—————-- 第一部分:基本情况与需求分析 1.基本情况 "题目 " 教学管理系统 " "同组队员信 "学号 "姓名 "专业 "课题负责部分 " "息 " " " " " "学生 " 01 "XXXXX "软件工程 "设计与实践 " 2。需求分析的任务 需求分析的任务是调查应用领域,对应用领域中的信息要求和操作要求进行详细分析,形 成需求分析说明书。重点是调查,收集与分析用户在数据管理中的信息要求,处理要求 ,数据的安全性与完整性要求. 为了完成需求分析的任务,要详细调查待开发的数据库应用部门的情况,了解原系统工作 概况,分析用户的各种需求,在此基础上确定新系统的功能。新系统必须考虑今后的扩 充和改变,不能仅仅按当前应用需求来设计数据库。 3. 需求分析的过程 (1)登录管理 (2)人员管理 (3)部门管理 ( 其中人员管理包括:添加,浏览,修改,撤销,删除,查询等:部门管理包括添加、修 改,删除) 4. 数据字典 经过可行性分析和初步需求调查,抽象出该子系统业务流程图,如图2.1 所 示。下面,结合该实例具体情况,给出教务处、后勤部和各个系各部门的具体需 求。 图2.1 某公司人事管理业务流程图 调查用户需求 企业部门需求 员工基本信息处理: 员工基本信息的录入 员工基本信息的处理包括插入,删除以及修改 员工基本信息的查询 统计功能: 按学历、婚姻状况、岗位、参加工作时间等统计各自的员工信息 分析用户需求 在调查完了用户需求之后,就要开始分析用户需求。在此,我们采用自顶向 下的结构化分析方法(SA 方法)。首先,定义全局概念结构的框架。 经分析之后,本系统要用到九个基本表:系表,班级,学生表,课程表,选 课表、教室表、占用表、教师表,教授表。数据结构定义如表2.1 所示。 表2.1 数据结构定义 数据结构名 1. 员工基本情况。包括的数据项有员工号、员工姓名、性
数据库课程设计报告--教室信息管理系统 东北大学秦皇岛分校 数据库原理课程设计报告 教室信息管理系统 "学 院 "数学与统计学院 " "专 业 " " "学 号 " " "姓 名 " " "指导教师 " " "成 绩 " " 教师评语 指导教师签字: 2014年1月5日 1 绪论 1.1 课题背景与需求分析 教室管理信息化是学校教务系统应用信息技术及其产品的过程,是信息技术应用于教室 管理的过程。教育信息化的实施,自上而下而言,必须与学校的制度创新、组织创新和 管理创新结合;自下而上而言,必须以作为学校主体的工作人员使用信息技术水平的逐 步提高为基础。 学校信息系统是现存信息系统中较为复杂的一类,这是由学校本身的目标、任务和性 质决定的;它应用于学校的学生管理、教师管理、教室管理以及招生就业管理等各个方 面,牵涉的信息种类十分庞杂。它融合了学校的管理思想和各职能部门的工作经验,是 学校当前运作方式和业务流程的具体体现,同时又在一定程度上反作用于学校当前的运 作方式和业务流程。而教室管理信息系统正是这样庞大的系统中的一个系统。教室之于 教师、学生、教学,都有极其重要的作用。 因此,学校信息化建设工作具有长期性、复杂性和内容的多变性;正因为如此,教室 管理信息系统也不是一个简单的、封闭的、静止的系统,而是一个复杂的、开放的、在 应用的深度和广度上,随着时间的推移会逐步变化和发展的系统。 1.2 业务流程及系统功能分析 系统应当完成以下的信息处理: 1.教师查询; 学生通过这个功能,可以查询相关院系相关教师的个人信息,授课地点等信息,以便 能更好地了解教师及其开课情况。 2.教室查询; 学生通过这个功能,可以查询相关教学楼相关教室的信息以及该教室在每天任一时段 的使用情况,或者有课,或者有讲座、或者有活动等等。这个功能以便使同学能更好地 了解教室及其使用情况。 3.教室借用; 学生通过这个功能,可以借教室,即获得教室在某段时间的使用权,办讲座,开展社 团活动等等。 1.3 系统开发工具 1.数据库后台开发软件:SQL Server 2005 2.台开发软件:Java Eclipse 2 概念结构设计 2.1 E-R图设计 一间教室在不同的时间段可以由多个老师上课,一个老师可以在多个教室上课。一间 教室可以有多个人申请使用,一个申请人可以申请多个教室。所以教师与教室是多对多 关系,教室和申请人是多对多关系。故设计E-R图如图2.1所示。 图2.1 E-R图 3逻辑结构设计 3.1、关系模式 用户(用户编号,用户密码,用户类别)主键:用户编号 教师(教师编号,教师姓名,教师职称,教授课程,授课时间,授课地点)主键:教 师编号 教室(教室号,教室容量,教室类型,周一空闲时间,周二空闲时间,周三空闲时间 ,周四空闲时间,周五空闲时间,周六空闲时间,周日空闲时间)主键:教室号 预定教室(教室号,用户编号,使用时间,使用时长,申请结果)主键,教室号,用 户编号 外键:教室号,用户编号 3.2、关系表设计 表3.1 user表 "字段名 "字段类型 "长度 "可否为空 "默认值 "主键 "说明 " "user_id "varchar "50 "not null " "是 "用户编号 " "user_ps "varchar "50 "not null " " "用户密码 " "user_type "varchar "50 "not null " " "用户类型 " 表3.2 Teacher表 "字段名 "字段类型 "长度 "可否为空 "默认值 "主键 "说明 " "Teacher_id "varchar "50 "not null " "是 "教师编号 " "Teacher_name "varchar "50 "not null " " "教师姓名 " "Teacher_proft "varchar "50 "not null " " "教师职称 " "course "varchar "50 "not null " " "教授课程 " "time "varchar "50 "not null " " "授课时间 " "classroom "Varchar "50 "not null " " "授课地点 " 表3.3 Classroom表 "字段名 "字段类型"长度 "可否为空 "默认值 "主键 "说明 " "Classroom_id "varchar "50 "not null " "是 "教室号 " "Classroom_capaci"varchar "max "not null " " "教室容量 " "ty " " " " " " " "Classroom_type "varchar "50 "not null " " "教室类型 " "Mo
hibernate-jpa-2.1-api 1.0.2是一个Java持久化规范的实现库。它是基于JPA(Java Persistence API)2.1规范的Hibernate实现。Hibernate是一个流行的ORM(对象关系映射)框架,用于在Java应用程序和关系数据库之间进行数据持久化。 该版本的hibernate-jpa-2.1-api是对JPA 2.1规范的实现,并且是Hibernate团队为了确保应用程序与Java EE 7兼容性而发布的一个版本。 JPA是一种使用对象模型操作数据库的标准规范,它提供了一组API,使开发人员可以使用面向对象的方式访问和操作数据库。Hibernate作为一个JPA的实现,提供了许多附加的功能和特性,使得开发人员可以更加简化和灵活地进行数据库操作。 通过使用hibernate-jpa-2.1-api,开发人员可以使用JPA的标准API,以及Hibernate提供的独有特性,来实现应用程序的数据持久化需求。它提供了实体管理器,用于管理实体对象的生命周期,以及CRUD操作。此外,它还提供了用于查询和各种持久化注解的支持。 通常情况下,使用hibernate-jpa-2.1-api需要将其添加到项目的依赖中,并与其他必需的Hibernate库一起使用。开发人员需要熟悉JPA的基本概念和API,并且理解Hibernate特有的扩展和配置选项。 总的来说,hibernate-jpa-2.1-api 1.0.2提供了开发人员在使用JPA进行数据持久化时的基本工具和功能。它是Hibernate团队为了支持JPA 2.1规范而发布的一个版本,开发人员可以使用它来简化和灵活地操作数据库。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值