从零开始搭建一个JavaSSM作业管理系统(二)

从零开始搭建 一个JavaSSM作业管理系统系列

从零开始搭建一个JavaSSM作业管理系统(一)
从零开始搭建一个JavaSSM作业管理系统(二)
从零开始搭建一个JavaSSM作业管理系统(三)
从零开始搭建一个JavaSSM作业管理系统(四)

项目下载地址

说明!!!

1.本系列的文章仅展示搭建SSM作业管理系统的大致流程,文章中不会提供该项目的完整代码,如果需要完整代码可以在提供的链接中自行下载

2.本系列只展示作业管理系统一小部分功能实现(登录功能、管理员界面的学生信息管理功能),大部分功能都是信息的增删改查基本操作,重复度较多,大体步骤也都相同,故不做过多展示,请大家见谅

3.博主本人也算是spring框架的初学者,写此系列的目的旨在分享个人在学习SSM过程中的一些经验,如果大家在博客中发现代码或一些解释有误,还望多多指正

前言

在之前我们已经完成了项目的设计,下面我们将对完成整个项目的框架搭建,配置Maven,并逐层完成SSM的各项配置

摘要

本文主要介绍搭建Java-SSM作业管理系统的第二个阶段

  1. 框架搭建
  2. 配置验证

一、Maven配置

来到pom.xml文件

下面我们需要在文件里面的dependencies下面添加所需要的依赖
注意:junit版本一定要大于4.12,否则无法进行UT测试

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
</dependency>

配置好之后的pom文件如下:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>bjtu.edu</groupId>
  <artifactId>HMS-mvc</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>HMS-mvc Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>

    <!--定义版本号   ${spring.version}-->
    <spring.version>5.2.7.RELEASE</spring.version>

    <org.mybatis.version>3.5.5</org.mybatis.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

      <!-- Spring -->
      <!-- 1)包含Spring 框架基本的核心工具类。Spring 其它组件要都要使用到这个包里的类,是其它组件的基本核心 -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <!-- 2)这个jar 文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean 以及进行Inversion of Control
          / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI 支持,引入spring-core.jar
          及spring-beans.jar 文件就可以了。 -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <!-- 3)这个jar 文件为Spring 核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI
          所需的全部类,instrumentation组件以及校验Validation 方面的相关类。 -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <!-- 4) 这个jar 文件包含对Spring 对JDBC 数据访问进行封装的所有类。 -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <!-- 5) 为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理。 -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <!-- 6)Spring web 包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。 -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <!-- 7)包含SpringMVC框架相关的所有类。 -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <!-- 8)Spring test 对JUNIT等测试框架的简单封装 -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
      </dependency>

      <!-- Servlet web -->
      <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
      </dependency>

      <!-- json解析 -->
      <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.11.1</version>
      </dependency>

      <!-- Map工具类 对标准java Collection的扩展 spring-core.jar需commons-collections.jar -->
      <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.2</version>
      </dependency>

      <!-- mybatis -->
      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${org.mybatis.version}</version>
      </dependency>
      <!--mybatis-spring-->
      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.5</version>
      </dependency>

      <!--数据库-->
      <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.21</version>
      </dependency>

      <!--连接池-->
      <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
      <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.5</version>
      </dependency>

      <!-- 图片处理 -->
      <!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
      <dependency>
        <groupId>net.coobird</groupId>
        <artifactId>thumbnailator</artifactId>
        <version>0.4.11</version>
      </dependency>

      <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
      </dependency>
  </dependencies>

  <build>
    <finalName>HMS-mvc</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
          <configuration>
            <skipTests>true</skipTests>
          </configuration>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

如果要添加最新版本的依赖或更新依赖版本,需要上maven官网去查找
Maven官网

二、dao层配置

下面我们开始dao层的配置

首先在src/main/resources目录下建立两个package

spring-主要写跟spring相关的配置(dao层、service层、web层)
mapper-主要写mybatis的配置,与dao层映射
建立两个package
建好之后,我们再在src/main/resources目录下建立一个资源配置文件-jdbc.properties,该文件主要写数据库相关的配置
建立一个资源配置文件
代码如下:

jdbc.driver 为数据库驱动名称,因为我的数据库是mysql8版本,需要加cj,如果为mysql5版本,可以把cj去掉
jdbc.url就是连接数据库的链接
jdbc.usernamejdbc,password为用户名和密码

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
jdbc.username=WnplV/ietfQ=
jdbc.password=bcVXuWjPZaIfJAfVsP+M2w==

在编写完jdbc,properties文件后,我们修改src/main/webapp/WEB-INF目录下的web.xml文件,修改如下

(这里我们添加了spring文件的扫描操作)

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1" metadata-complete="true">
  <display-name>Archetype Created Web Application</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <servlet>
    <servlet-name>spring-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-*.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring-dispatcher</servlet-name>
    <!--默认匹配所有的请求-->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

在完成以上两个配置之后,我们在src/main/resources/spring目录下面建立三个文件

  • spring-dao.xml(springMVC的dao层相关配置)
  • spring-service.xml(springMVC的service层相关配置)
  • spring-web.xml(springMVC的web层相关配置)

建立步骤如下:
建立步骤
下面我们编写spring-dao的代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 配置整合mybatis过程 -->
    <!-- 1.配置数据库相关参数properties的属性:${url} -->
    <context:property-placeholer location="classpath:jdbc.properties"/>

    <!-- 2.数据库连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 配置连接池属性 -->
        <property name="driverClass" value="${jdbc.driver}" />
        <property name="jdbcUrl" value="${jdbc.url}" />
        <property name="user" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />

        <!-- c3p0连接池的私有属性 -->
        <property name="maxPoolSize" value="30" />
        <property name="minPoolSize" value="10" />
        <property name="initialPoolSize" value="10"/>
        <!-- 关闭连接后不自动commit -->
        <property name="autoCommitOnClose" value="false" />
        <!-- 获取连接超时时间 -->
        <property name="checkoutTimeout" value="10000" />
        <!-- 当获取连接失败重试次数 -->
        <property name="acquireRetryAttempts" value="2" />
    </bean>

    <!-- 3.配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
        <!-- 配置MyBatis全局配置文件:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <!-- 扫描entity包 使用别名 -->
        <property name="typeAliasesPackage" value="com.bjtu.edu.entity" />
        <!-- 扫描sql配置文件:mapper需要的xml文件 -->
        <property name="mapperLocations" value="classpath:mapper/*.xml" />
    </bean>

    <!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <!-- 给出需要扫描Dao接口包 -->
        <property name="basePackage" value="com.bjtu.edu.dao" />
    </bean>
</beans>

上述代码中,数据库连接池方面我选择的是c3p0,关于数据库连接池有很多种,比如阿里云的数据库连接池,等等,这个可以自由选择,而且大体配置方法基本相同

扫描dao接口包的代码片段需要改成自己项目种dao接口包存放的位置(位置从java包的位置开始算起)

<!-- 给出需要扫描Dao接口包 -->
<property name="basePackage" value="com.bjtu.edu.dao" />

下面我们再在src/main/resources目录下建立一个mybatis-config.xml文件,该文件主要对mybatis进行相关的配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置全局属性 -->
    <settings>
        <!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
        <setting name="useGeneratedKeys" value="true" />

        <!-- 使用列标签替换列别名 默认:true -->
        <!--列标签(数据库中的字段名)-->
        <!--列别名(查询语句查询字段时给字段自定义的名称)-->
        <setting name="useColumnLabel" value="true" />

        <!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
        <setting name="mapUnderscoreToCamelCase" value="true" />
    </settings>
</configuration>

三、service层配置

修改spring-service.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- 扫描service包下所有使用注解的类型 -->
    <context:component-scan base-package="com.bjtu.edu.service" />

    <!-- 配置事务管理器 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 配置基于注解的声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

与dao层类似,扫描service包的地方同样需要改成自己项目里的service包的位置

<!-- 扫描service包下所有使用注解的类型 -->
    <context:component-scan base-package="com.bjtu.edu.service" />

四、web层配置

修改spring-web.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
    <!-- 配置SpringMVC -->
    <!-- 1.开启SpringMVC注解模式 -->
    <mvc:annotation-driven />

    <!-- 2.静态资源默认servlet配置 (1)加入对静态资源的处理:js,gif,png (2)允许使用"/"做整体映射 -->
    <mvc:resources mapping="/resources/**" location="/resources/" />
    <mvc:default-servlet-handler />

    <!-- 3.定义视图解析器 -->
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/html/"/>
        <property name="suffix" value=".html"/>
    </bean>
    <!--文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8"/>
        <!--1024 * 1024 * 20 = 20M-->
        <property name="maxUploadSize" value="20971520"/>
        <property name="maxInMemorySize" value="20971520"/>
    </bean>

    <!-- 4.扫描web相关的bean -->
    <context:component-scan base-package="com.bjtu.edu.web" />
</beans>

这里同样要修改web包的扫描部分

    <!-- 4.扫描web相关的bean -->
    <context:component-scan base-package="com.bjtu.edu.web" />

五、配置验证

在完成相关配置后,下面我们将对每一层进行验证

注意:在进行配置的验证之前,我们需要在之前已经设计好的数据库里面的每个表都添加一些数据,方便后续信息的读取

下面我们挑选一个实体类完成三个层级的验证(dao、service、web)
这里我们选择最简单的clazz实体类来进行三个层级的验证

(1) Clazz实体类dao层验证

编写dao层相关的代码

在dao层的目录下建立接口类-ClazzDao
建立接口类-ClazzDao

clazz实体类的dao层接口需要编写四个方法,四个方法的功能如下:

  • 查询所有班级列表
  • 通过clazzId查询指定班级
  • 批量新增班级
  • 通过clazzId删除指定班级

代码如下:

ClazzDao.java

public interface ClazzDao {
     //查询所有班级列表
    List<Clazz> queryClazz();

     //通过clazzId查询指定班级
    Clazz queryClazzById(long clazzId);

     //新增班级
     int addClazz(Clazz clazz);

     //更新班级
    int modifyClazz(Clazz aClazz);

     //通过clazzId删除指定班级
    int deleteClazz(long clazzId);
}

在编写完ClazzDao接口后,我们来编写mybatis映射的xml文件,在resources/mapper目录下新建一个ClazzDao.xml,名字一定要与dao层的接口名字相同

代码如下:

ClazzDao.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.bjtu.edu.dao.ClazzDao">
    <select id="queryClazz" resultType="com.bjtu.edu.entity.Clazz">
        SELECT clazz_id, clazz_number, clazz_desc, create_time, last_edit_time
        FROM clazz
    </select>

    <select id="queryClazzById" resultType="com.bjtu.edu.entity.Clazz">
        SELECT clazz_id, clazz_number, clazz_desc, create_time, last_edit_time
        FROM clazz
        WHERE clazz_id = #{clazzId}
    </select>

    <insert id="addClazz" useGeneratedKeys="true" keyColumn="clazz_id" keyProperty="clazzId">
        INSERT INTO
        clazz(clazz_id, clazz_number, clazz_desc, create_time)
        VALUES
        (#{clazzId},
        #{clazzNumber},
        #{clazzDesc},
        #{createTime})
    </insert>

    <update id="modifyClazz" parameterType="com.bjtu.edu.entity.Clazz"
            keyProperty="clazz_id" useGeneratedKeys="true">
        UPDATE clazz
        <set>
            <if test="clazzNumber != null">clazz_number=#{clazzNumber},</if>
            <if test="clazzDesc != null">clazz_desc=#{clazzDesc},</if>
            <if test="lastEditTime != null">last_edit_time=#{lastEditTime},</if>
        </set>
        WHERE clazz_id = #{clazzId}
    </update>

    <delete id="deleteClazz">
        DELETE FROM
            clazz
        WHERE
            clazz_id = #{clazzId}
    </delete>
</mapper>
配置验证

在编写完Clazz相关的dao层代码后,我们来对dao层进行验证,在src/test/java目录下建立两个package-dao、service,一个用于dao层UT测试,一个用于service层UT测试
在src/test/java目录下建立两个package
建好两个package后,在test/java目录下新建一个测试基类,名为BaseTest

代码如下:

BaseTest.java

@RunWith(SpringJUnit4ClassRunner.class)
//告诉Junit spring配置文件的位置
@ContextConfiguration
        ({
                "classpath:spring/spring-dao.xml",
                "classpath:spring/spring-service.xml"
        })
public class BaseTest {
}

在完成UT测试的相关配置后,下面我们正式开始UT测试,在刚才新建好的dao下面新建一个测试类,名为ClazzDaoTest,该类继承自BaseTest类(以后所有的测试类都继承该类)

代码如下:

ClazzDaoTest.java

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ClazzDaoTest extends BaseTest {
    @Autowired
    private ClazzDao clazzDao;

    @Test
    public void testAQueryClass(){
        List<Clazz> clazzList = clazzDao.queryClazz();
        assertEquals(2, clazzList.size());
        System.out.println(clazzList.size());
    }

    @Test
    public void testBQueryClassById(){
        Clazz clazz = clazzDao.queryClazzById(1701L);
        System.out.println(clazz.getClazzDesc());
    }

    @Test
    public void testCAddClazz(){
        Clazz clazz = new Clazz();
        clazz.setClazzId(1801L);
        clazz.setClazzNumber(40);
        clazz.setClazzDesc("软件学院1801班");
        clazz.setCreateTime(new Date());
        int effectedNum = clazzDao.addClazz(clazz);
        assertEquals(1,effectedNum);
        System.out.println(effectedNum);
    }

    @Test
    public void testDModifyClass(){
        Clazz clazz = new Clazz();
        clazz.setClazzId(1801L);
        clazz.setClazzNumber(80);
        clazz.setClazzDesc("计算机学院1801班");
        clazz.setLastEditTime(new Date());
        int effectedNum = clazzDao.modifyClazz(clazz);
        assertEquals(1,effectedNum);
        System.out.println(effectedNum);
    }

    @Test
    public void testEDeleteClass(){
        clazzDao.deleteClazz(1801L);
        clazzDao.deleteClazz(1802L);
    }
}

这是数据库里面clazz表的数据
数据库里面clazz表的数据

下面我们开始进行UT测试
开始进行UT测试
可以看到,UT测试成功

以上的UT测试设计成一个闭环测试,即按顺序依次执行查找、插入、更新、删除操作,最后数据库里面的信息不会有任何变化

部分代码说明

设置测试方法执行顺序为按字母升序执行

@FixMethodOrder(MethodSorters.NAME_ASCENDING)

这是我的测试方法定义,执行时,testA先执行,然后是testB等等,这种执行顺序正好可以实现闭环测试

testAQueryClass()
testBQueryClassById()
testCAddClass()
testDUpdateClass()

(2) Clazz实体类service层验证

编写service层相关的代码

下面我们来进行service层的验证,在src/main/service下面建立一个package-Impl,主要用来存放service接口的实现类,然后分别建立ClazzService的接口类和实现类

建立好之后的目录结构如下:
建立好之后的目录结构
在实现ClazzService类方法之前,我们需要在eums包(存放枚举类)、exception包(存放异常类)和dto包(存放构造类)下面建立Clazz实体类对应的枚举类、异常类、构造类
枚举类、异常类、构造类
代码如下:

ClazzStateEnum

public enum ClazzStateEnum {
     //状态枚举
    SUCCESS(1, "创建成功"),
    INNER_ERROR(-1001, "操作失败"),
    EMPTY(-1002, "班级信息为空");

    private int state;
    private String stateInfo;

    public int getState() {
        return state;
    }

    public String getStateInfo() {
        return stateInfo;
    }

    private ClazzStateEnum(int state, String stateInfo){
        this.state = state;
        this.stateInfo = stateInfo;
    }

     //依据传入的state返回相应的enum值
    public static ClazzStateEnum stateOf(int state){
        for (ClazzStateEnum stateEnum : values()){
            if (stateEnum.getState() == state){
                return stateEnum;
            }
        }
        return null;
    }
}

ClazzOperationException

public class ClazzOperationException extends RuntimeException{

    private static final long serialVersionUID = 1110885646012316735L;

    public ClazzOperationException(String msg){super(msg);}
}

ClazzExecution

public class ClazzExecution {
    // 结果状态
    private int state;

    // 状态标识
    private String stateInfo;

    // 操作的clazz(增删改班级的时候用)
    private Clazz clazz;

    // 获取的clazz列表(查询商品班级的时候用)
    private List<Clazz> clazzList;

    public ClazzExecution() {
    }

    // 失败的构造器
    public ClazzExecution(ClazzStateEnum clazzStateEnum) {
        this.state = clazzStateEnum.getState();
        this.stateInfo = clazzStateEnum.getStateInfo();
    }

    // 成功的构造器
    public ClazzExecution(ClazzStateEnum clazzStateEnum, Clazz clazz) {
        this.state = clazzStateEnum.getState();
        this.stateInfo = clazzStateEnum.getStateInfo();
        this.clazz = clazz;
    }

    // 成功的构造器
    public ClazzExecution(ClazzStateEnum clazzStateEnum, List<Clazz> clazzList) {
        this.state = clazzStateEnum.getState();
        this.stateInfo = clazzStateEnum.getStateInfo();
        this.clazzList = clazzList;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public String getStateInfo() {
        return stateInfo;
    }

    public void setStateInfo(String stateInfo) {
        this.stateInfo = stateInfo;
    }

    public Clazz getClazz() {
        return clazz;
    }

    public void setClazz(Clazz clazz) {
        this.clazz = clazz;
    }

    public List<Clazz> getClazzList() {
        return clazzList;
    }

    public void setClazzList(List<Clazz> clazzList) {
        this.clazzList = clazzList;
    }
}

在创建完成后,下面我们来实现ClazzService类方法,代码如下:

ClazzService接口类

public interface ClazzService {
     //查询全部班级信息
    List<Clazz> getClazzList();

     //通过班级Id查询唯一的班级信息
    Clazz getClazzById(long clazzId);

     //新增班级信息
    ClazzExecution addClazz(Clazz clazz);

     //修改班级信息
    ClazzExecution modifyClazz(Clazz clazz);

     //删除指定班级
    ClazzExecution deleteClazz(long clazzId);
}

ClazzService实现类

@Service
public class ClazzServiceImpl implements ClazzService {
    @Autowired
    private ClazzDao clazzDao;

     //查询班级列表
    @Override
    public List<Clazz> getClazzList() {
        return clazzDao.queryClazz();
    }

     //通过班级Id查询唯一的班级信息
    @Override
    public Clazz getClazzById(long clazzId) {
        return clazzDao.queryClazzById(clazzId);
    }

     //新增班级信息
    @Override
    public ClazzExecution addClazz(Clazz clazz){
        //判断传入的班级信息是否为空
        if (clazz != null) {
            try {
                //设置创建时间
                clazz.setCreateTime(new Date());
                //添加班级信息
                int effectedNum = clazzDao.addClazz(clazz);
                //判断是否添加成功
                if (effectedNum <= 0) {
                    throw new ClazzOperationException("班级创建失败");
                } else {
                    return new ClazzExecution(ClazzStateEnum.SUCCESS);
                }
            } catch (Exception e) {
                throw new ClazzOperationException("addClazz error: " + e.getMessage());
            }
        }else {
            return new ClazzExecution(ClazzStateEnum.EMPTY_LIST);
        }
    }

     //修改班级信息
    @Override
    public ClazzExecution modifyClazz(Clazz clazz){
        // 空值判断
        if (clazz != null && clazz.getClazzId() != null) {
            // 给clazz设置上默认属性
            clazz.setLastEditTime(new Date());
            try {
                // 更新商品信息
                int effectedNum = clazzDao.modifyClazz(clazz);
                if (effectedNum <= 0) {
                    throw new ClazzOperationException("更新班级信息失败");
                }
                return new ClazzExecution(ClazzStateEnum.SUCCESS, clazz);
            } catch (Exception e) {
                throw new ClazzOperationException("更新班级信息失败:" + e.toString());
            }
        } else {
            return new ClazzExecution(ClazzStateEnum.EMPTY);
        }
    }

     //删除指定班级
    @Override
    public ClazzExecution deleteClazz(long clazzId){
        // 删除该clazz
        try {
            int effectedNum = clazzDao.deleteClazz(clazzId);
            if (effectedNum <= 0) {
                throw new ClazzOperationException("班级信息删除失败");
            } else {
                return new ClazzExecution(ClazzStateEnum.SUCCESS);
            }
        } catch (Exception e) {
            throw new ClazzOperationException("deleteClazz error:" + e.getMessage());
        }
    }
}
配置验证

实现了ClazzService类后,下面我们来进行ClazzService的UT测试,在src/test/java/service目录下建一个新的测试类-ClazzServiceTest,该类同样继承自之前的BaseTest,测试方法基本与dao层测试相同
ClazzServiceTest
代码如下:

ClazzServiceTest

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ClazzServiceTest extends BaseTest {
    @Autowired
    private ClazzService clazzService;

    @Test
    public void testAQueryClazz(){
        List<Clazz> classList = clazzService.getClazzList();
        assertEquals(2,classList.size());
        System.out.println(classList.size());
    }

    @Test
    public void testBQueryClazzById(){
        Clazz clazz = clazzService.getClazzById(1701L);
        assertEquals("软件学院1701班",clazz.getClazzDesc());
        System.out.println(clazz.getClazzDesc());
    }

    @Test
    public void testCAddClazz(){
        Clazz clazz = new Clazz();
        clazz.setClazzId(1801L);
        clazz.setClazzNumber(40);
        clazz.setClazzDesc("软件学院1801班");
        clazz.setCreateTime(new Date());
        ClazzExecution clazzExecution = clazzService.addClazz(clazz);
        assertEquals(ClazzStateEnum.SUCCESS.getState(),clazzExecution.getState());
        System.out.println(clazzExecution.getStateInfo());
    }

    @Test
    public void testDUpdateClazz(){
        Clazz clazz = new Clazz();
        clazz.setClazzId(1801L);
        clazz.setClazzNumber(80);
        clazz.setClazzDesc("计算机学院1801班");
        ClazzExecution clazzExecution = clazzService.modifyClazz(clazz);
        assertEquals(ClazzStateEnum.SUCCESS.getState(),clazzExecution.getState());
        System.out.println(clazzExecution.getStateInfo());
    }

    @Test
    public void testEDeleteClazz(){
        ClazzExecution clazzExecution1 = clazzService.deleteClazz(1801L);
        assertEquals(ClazzStateEnum.SUCCESS.getState(),clazzExecution1.getState());
        System.out.println(clazzExecution1.getStateInfo());

        ClazzExecution clazzExecution2 = clazzService.deleteClazz(1802L);
        assertEquals(ClazzStateEnum.SUCCESS.getState(),clazzExecution2.getState());
        System.out.println(clazzExecution2.getStateInfo());
    }
}

从代码中可以看出,依然是一个闭环测试,而且测试流程基本与dao层相同

下面我们开始进行UT测试
ClazzServiceUT测试
可以看到,UT测试成功

(3) Clazz实体类web层验证

编写web层相关的代码

下面我们开始web层的验证,首先在src/main/java/web下面新建四个package-home、teacher、student、admin

home-主要存放与登录注册相关操作的类
teacher-主要存放与教师操作界面相关的类
student-主要存放与学生操作界面相关的类
admin-主要存放与管理员操作界面相关的类

目录结构如下:
web层目录结构
建好四个包之后,我们来明确一个问题,该系统哪个地方要用到与clazz即班级相关操作(增删改查)?

主要有两个地方-管理员操作界面、学生操作界面

  1. 管理员对大部分信息都有增删改查的功能,自然包括clazz实体类
  2. 学生可以查看自己的班级信息,但不能对班级信息进行增删改操作

由于学生操作界面的相关操作涉及到student表的处理,相对麻烦一些,所以这里我们只实现管理员操作界面有关clazz实体类的相关操作的代码

管理员可对clazz实体类(班级)进行的操作如下:

  1. 查询所有班级信息
  2. 添加班级信息
  3. 修改指定班级信息
  4. 删除指定班级

在明确好相关功能后,下面我们编写web层代码

在src/main/java/web/admin下面新建一个类-ClazzManagementController,该类主要负责班级信息的相关操作,就是管理员可以对clazz实体类可进行的操作

代码如下:

ClazzManagementController

@Controller
@RequestMapping("/admin")
public class ClazzManagementController {
    @Autowired
    private ClazzService clazzService;

     //返回班级信息列表
    @RequestMapping(value = "/listClazz",method = RequestMethod.GET)
    @ResponseBody
    private Map<String,Object> listClazz(){
        Map<String,Object> modelMap = new HashMap<>();
        List<Clazz> clazzList;
        try {
            clazzList = clazzService.getClazzList();
            modelMap.put("clazzList",clazzList);
            modelMap.put("success", true);
        }catch (Exception e){
            e.printStackTrace();
            modelMap.put("success",false);
            modelMap.put("errMsg",e.toString());
        }
        return modelMap;
    }

     //批量添加班级信息
    @RequestMapping(value = "/addClazz", method = RequestMethod.POST)
    @ResponseBody
    private Map<String,Object> addClazz(HttpServletRequest request){
        Map<String, Object> modelMap = new HashMap<>();
        String clazzStr = HttpServletRequestUtil.getString(request,"clazzStr");
        if (clazzStr == null){
            modelMap.put("success",false);
            modelMap.put("errMsg","请输入班级信息");
            return modelMap;
        }
        ObjectMapper mapper = new ObjectMapper();
        Clazz clazz;
        try {
            clazz = mapper.readValue(clazzStr, Clazz.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            modelMap.put("success",false);
            modelMap.put("errMsg",e.getMessage());
            return modelMap;
        }

        ClazzExecution clazzExecution = clazzService.addClazz(clazz);
        if (clazzExecution.getState() == ClazzStateEnum.SUCCESS.getState()){
            modelMap.put("success",true);
        }else{
            modelMap.put("success",false);
            modelMap.put("errMsg",clazzExecution.getStateInfo());
        }
        return modelMap;
    }

     //修改班级信息
    @RequestMapping(value = "/modifyClazz", method = RequestMethod.POST)
    @ResponseBody
    private Map<String,Object> modifyClazz(HttpServletRequest request){
        Map<String,Object> modelMap = new HashMap<String, Object>();
        //1.接受并转化相应的参数,包括班级信息
        //获取前端传过来的班级信息,并将它转换成实体类;
        String clazzStr = HttpServletRequestUtil.getString(request,"clazzStr");
        ObjectMapper mapper = new ObjectMapper();
        Clazz clazz = null;
        try {
            clazz = mapper.readValue(clazzStr,Clazz.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            modelMap.put("success",false);
            modelMap.put("errMsg",e.getMessage());
            return modelMap;
        }
        //2.修改班级
        if(clazz != null && clazz.getClazzId() != null){
            ClazzExecution clazzExecution;
            clazzExecution = clazzService.modifyClazz(clazz);
            if (clazzExecution.getState() == ClazzStateEnum.SUCCESS.getState()){
                modelMap.put("success",true);
            }else{
                modelMap.put("success",false);
                modelMap.put("errMsg",clazzExecution.getStateInfo());
            }
            return modelMap;
        }else {
            modelMap.put("success",false);
            modelMap.put("errMsg","请输入班级Id");
            return modelMap;
        }
        //3.返回结果
    }

     //删除指定班级信息
    @RequestMapping(value = "/deleteClazz", method = RequestMethod.POST)
    @ResponseBody
    private Map<String, Object> deleteClazz(Long clazzId, HttpServletRequest request) {
        Map<String, Object> modelMap = new HashMap<String, Object>();
        if (clazzId != null && clazzId > 0) {
            try {
                ClazzExecution clazzExecution = clazzService.deleteClazz(clazzId);
                if (clazzExecution.getState() == ClazzStateEnum.SUCCESS.getState()) {
                    modelMap.put("success", true);
                } else {
                    modelMap.put("success", false);
                    modelMap.put("errMsg", clazzExecution.getStateInfo());
                }
            } catch (ClazzOperationException e) {
                modelMap.put("success", false);
                modelMap.put("errMsg", e.toString());
                return modelMap;
            }
        } else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "未选择要删除的班级");
        }
        return modelMap;
    }
}

此外我还在util包(主要存放各种工具类)下面创建一个HttpServletRequestUtil类,主要用来处理各种类型的HttpServletRequest参数
存放工具类
具体代码如下:

HttpServletRequestUtil

public class HttpServletRequestUtil {
    public static int getInt(HttpServletRequest request, String key){
        try {
            return Integer.decode(request.getParameter(key));
        }catch (Exception e){
            return -1;
        }
    }

    public static long getLong(HttpServletRequest request, String key){
        try {
            return Long.valueOf(request.getParameter(key));
        }catch (Exception e){
            return -1;
        }
    }

    public static Double getDouble(HttpServletRequest request, String key){
        try {
            return Double.valueOf(request.getParameter(key));
        }catch (Exception e){
            return -1d;
        }
    }

    public static Boolean getBoolean(HttpServletRequest request, String key){
        try {
            return Boolean.valueOf(request.getParameter(key));
        }catch (Exception e){
            return false;
        }
    }

    public static String getString(HttpServletRequest request, String key){
        try {
            String result = request.getParameter(key);
            if (result != null){
                result = result.trim();
            }
            if ("".equals(result)){
                result = null;
            }
            return result;
        }catch (Exception e){
            return null;
        }
    }
}
配置验证

在编写好所有代码后,下面我们来对Clazz实体类的Web层进行验证

运行之前配置好的tomcat
运行之前配置好的tomcat
由于关于Clazz实体类的增删改操作涉及到 前端传值,这里我们只验证一下获取Clazz列表信息

在http://localhost:8080/后面输入路由名字
在这里插入图片描述
可以看到数据库里面所有的Clazz信息被读取到了,并以json格式返回,这说明我们web层的配置是成功的

(关于ClazzManagementController里面的其他方法我们会在后续进行验证)

六、补充

浏览器上Json的美化插件

首先来对比一下效果
效果对比1
效果对比2
可以看到,在我们前端调试时,将返回的json字段清晰的展示出来十分重要

关于json美化插件网上有很多,这里我使用的是FeHelper

FeHelper下载地址

七、总结

至此,我们完成了关于该系统的所有相关配置,并对配置进行了验证,下一步我们将编写所有实体相对应的枚举类、异常类和构造类代码

(枚举类存放在enums包下面,异常类存放在exception包下面,构造类存放在dto包下面)

下一篇:从零开始搭建一个JavaSSM作业管理系统(三)

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值