SSM框架:SpringMVC+Spring+MyBatis
利用SSM框架设计教务管理系统,进行信息的CRUD(Create、Retrieve、Update、Delete)
学习来源:尚硅谷
实现功能:1.页面分页
2.数据校验:jQuery前端校验+后端校验
3.使用ajax无刷新的页面更新
4.对信息进行增删改查操作
相关技术:1.基础框架-SSM(SpringMVC+Spring+MyBatis)
2.数据库-MySQL
3.前端框架-bootstrap快速搭建界面
4.项目依赖管理-Maven
5.分页-pagehelper
6.MyBatis Generator
首先进行基础环境搭建:
1、创建一个maven工程
首先在eclipse中配置maven,打开eclipse,点开 windows-preferences-maven-Installations, 将安装的 maven 添加进去并选中, 然后apply,步骤如图。
说明一下,首先点击Add,然后点击Directory,找到当时安装maven的路径,点击Finish。
然后在Maven下找到 User Settings, 然后添加settings.xml文件路径设置,点击 apply。
到此,eclipse配置maven就完成了,然后使用maven创建项目。
2、引入项目依赖的jar包
在pom.xml中引入,包括Spring,SpringMVC,MyBatis,数据库连接池,驱动包以及其他包(JSTL,servlet-api,junit)
<!-- 引入项目依赖的jar包 -->
<!-- SpringMVC、Spring -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.7</version>
</dependency>
<!-- Spring-Jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.7</version>
</dependency>
<!-- Spring面向切面编程 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.7</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- MyBatis整合Spring的适配包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- 数据库连接池、驱动 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
<!-- (JSTL,servlet-api,junit) -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
3、引入bootstrap前端框架
首先,Bootstrap 是最受欢迎的 HTML、CSS 和 JS 框架,用于开发响应式布局、移动设备优先的 WEB 项目。可以去官网自行下载。对于bookstrap的使用方法,只需要引入Bootstrap 核心 CSS 文件 和Bootstrap 核心JavaScript文件 即可。
<!-- 引入jQuery -->
<script type="text/javascript" src="static/js/jquery-1.12.4.min.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="static/bootstrap-3.4.1-dist/css/bootstrap.min.css">
<!-- 引入js -->
<script src="static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
注意:src中的路径对应文件所在的路径。
到此,现在就可以快速搭建较美观的界面了。
使用bookstrap搭建界面时,举个例子,要为按钮添加一个好看的样式,首先在bookstrap中文网里找到喜欢的按钮对应的代码块,复制class属性里的内容即可。
4、编写SSM整合的关键配置文件
在web.xml中配置文件,给spring,springmvc,mybatis配置文件。
(1)启动Spring的容器
然后创建Spring的配置文件,名称为applicationContext.xml
提示:applicationContext.xml是Spring的配置文件,主要配置和与业务逻辑有关的。
(2)SpringMVC的前端控制器 拦截所有的请求
然后创建SpringMVC的配置文件,名称为dispatcherServlet-servlet.xml
(3)字符编码过滤器
注意:字符编码过滤器,一定要放在所有过滤器之前
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(4)使用Rest风格的URI
作用:将页面普通的post请求转换为指定的delete或put请求
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>HttpPutFormContentFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpPutFormContentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
到此,web.xml中的关键配置文件就配置完成了,接下来在各个关键配置文件中进行详细配置。
1)SpringMVC的配置文件(包含网站跳转逻辑的控制,配置)
<?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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
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-4.3.xsd">
<!-- SpringMVC的配置文件,包含网站跳转逻辑的控制,配置-->
<!-- 包扫描机制,扫描相应的控制器 -->
<context:component-scan base-package="com.atrjxy.crud.controller"></context:component-scan>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 两个标准配置 -->
<!-- 将SpringMVC不能处理的请求交给tomcat -->
<mvc:default-servlet-handler/>
<!-- 能支持SpringMVC一些高级的功能,如JSR303校验,快捷的ajax等映射动态请求 -->
<mvc:annotation-driven/>
</beans>
到此,SpringMVC的配置文件就完成了。
2)Spring的配置文件
<?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:aop="http://www.springframework.org/schema/aop"
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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 包扫描机制,扫描除控制器外的所有包 -->
<context:component-scan base-package="com.atrjxy">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- Spring的配置文件,主要配置和与业务逻辑有关的 -->
<!-- Srping配置文件的核心点(数据源、和mybatis的整合、事务控制) -->
<!-- 数据源的配置-->
<context:property-placeholder location="classpath:dbconfig.properties"/>
<bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 配置和MyBatis的整合 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定mybatis全局配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="dataSource" ref="pooledDataSource"></property>
<!-- 指定mybatis的mapper映射文件的位置 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean>
<!-- 配置扫描器,将mybatis接口的实现加入到ioc容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描所有dao接口的实现,加入到ioc容器中 -->
<property name="basePackage" value="com.atrjxy.crud.dao"></property>
</bean>
<!-- 事务控制的配置 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 控制住数据源的开启关闭等操作 -->
<property name="dataSource" ref="pooledDataSource"></property>
</bean>
<!-- 开启基于注解的事务,使用xml配置形式的事务(主要的都是使用配置式) -->
<aop:config>
<!-- 切入点表达式 -->
<aop:pointcut expression="execution(* com.atrjxy.crud.service..*(..))" id="txPoint"/>
<!-- 配置事务增强 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
</aop:config>
<!-- 配置事务增强,即事务如何切入 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 所有方法都是事务方法 -->
<tx:method name="*"/>
<!-- 以get开始的所有方法 -->
<tx:method name="get*" read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
在数据源的配置中,这里创建一个文件dbconfig.properties文件,将jdbc相关信息提取出来,单独放在一个文件中。
到此,Spring的配置就完成了。
3)MyBatis的配置文件(使用mybatis的逆向工程生成对应的bean和mapper)
首先在pom.xml中引入,mybatis generator的jar包。
<!-- mybatis generator -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
然后创建一个xml文件,名称为mbg.xml。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="DB2Tables" targetRuntime="MyBatis3">
<!-- 用于删除生成文件的所有注释 -->
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- 配置数据库连接 -->
<jdbcConnection
driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/ssm_crud"
userId="root"
password="123456">
</jdbcConnection>
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 指定JavaBean生成的位置 -->
<javaModelGenerator
targetPackage="com.atrjxy.crud.bean"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 指定sql映射文件生成的位置 -->
<sqlMapGenerator
targetPackage="mapper"
targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 指定dao接口生成的位置,mapper接口 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.atrjxy.crud.dao"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- table指定每个表的生成策略 -->
<table tableName="tbl_stu" domainObjectName="Student"></table>
<table tableName="tbl_dept" domainObjectName="Department"></table>
</context>
</generatorConfiguration>
接下来编写一个测试类来生成对应的bean和mapper文件.
package com.atrjxy.crud.test;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
public class MBGTest {
public static void main(String[] args) throws Exception {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("mbg.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
这里需要创建对应的数据库表(学生信息表、班级信息表)
学生信息表:
班级信息表:
创建完表后,运行代码,就生成了对应的bean和mapper文件。
接下来,就要进行修改生成的mapper文件了(对于查询学生信息的同时也查询对应所在的班级信息,所以对StudentMapper.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.atrjxy.crud.dao.StudentMapper">
<resultMap id="BaseResultMap" type="com.atrjxy.crud.bean.Student">
<id column="s_id" jdbcType="INTEGER" property="sId" />
<result column="s_name" jdbcType="VARCHAR" property="sName" />
<result column="s_sex" jdbcType="CHAR" property="sSex" />
<result column="s_sno" jdbcType="VARCHAR" property="sSno" />
<result column="d_id" jdbcType="INTEGER" property="dId" />
</resultMap>
<resultMap type="com.atrjxy.crud.bean.Student" id="WithDeptResultMap">
<id column="s_id" jdbcType="INTEGER" property="sId" />
<result column="s_name" jdbcType="VARCHAR" property="sName" />
<result column="s_sex" jdbcType="CHAR" property="sSex" />
<result column="s_sno" jdbcType="VARCHAR" property="sSno" />
<result column="d_id" jdbcType="INTEGER" property="dId" />
<association property="deptment" javaType="com.atrjxy.crud.bean.Deptment">
<id column="dept_id" property="deptId" />
<result column="dept_name" property="deptName" />
</association>
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
s_id, s_name, s_sex, s_sno, d_id
</sql>
<sql id="WithDept_Column_List">
s.s_id, s.s_name, s.s_sex, s.s_sno, s.d_id,d.dept_id,d.dept_name
</sql>
<!-- 查询学生信息时带班级信息 -->
<select id="selectByExampleWithDept" resultMap="WithDeptResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="WithDept_Column_List" />
from tbl_stu s
left join tbl_dept d on s.`d_id`=d.`dept_id`
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKeyWithDept" resultMap="WithDeptResultMap">
select
<include refid="WithDept_Column_List" />
from tbl_stu s
left join tbl_dept d on s.`d_id`=d.`dept_id`
where s.s_id = #{sId,jdbcType=INTEGER}
</select>
<!-- 查询学生信息时不带班级信息 -->
<select id="selectByExample" parameterType="com.atrjxy.crud.bean.StudentExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from tbl_stu
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from tbl_stu
where s_id = #{sId,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from tbl_stu
where s_id = #{sId,jdbcType=INTEGER}
</delete>
<delete id="deleteByExample" parameterType="com.atrjxy.crud.bean.StudentExample">
delete from tbl_stu
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="com.atrjxy.crud.bean.Student">
insert into tbl_stu (s_id, s_name, s_sex,
s_sno, d_id)
values (#{sId,jdbcType=INTEGER}, #{sName,jdbcType=VARCHAR}, #{sSex,jdbcType=CHAR},
#{sSno,jdbcType=VARCHAR}, #{dId,jdbcType=INTEGER})
</insert>
<insert id="insertSelective" parameterType="com.atrjxy.crud.bean.Student">
insert into tbl_stu
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="sId != null">
s_id,
</if>
<if test="sName != null">
s_name,
</if>
<if test="sSex != null">
s_sex,
</if>
<if test="sSno != null">
s_sno,
</if>
<if test="dId != null">
d_id,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="sId != null">
#{sId,jdbcType=INTEGER},
</if>
<if test="sName != null">
#{sName,jdbcType=VARCHAR},
</if>
<if test="sSex != null">
#{sSex,jdbcType=CHAR},
</if>
<if test="sSno != null">
#{sSno,jdbcType=VARCHAR},
</if>
<if test="dId != null">
#{dId,jdbcType=INTEGER},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="com.atrjxy.crud.bean.StudentExample" resultType="java.lang.Long">
select count(*) from tbl_stu
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update tbl_stu
<set>
<if test="record.sId != null">
s_id = #{record.sId,jdbcType=INTEGER},
</if>
<if test="record.sName != null">
s_name = #{record.sName,jdbcType=VARCHAR},
</if>
<if test="record.sSex != null">
s_sex = #{record.sSex,jdbcType=CHAR},
</if>
<if test="record.sSno != null">
s_sno = #{record.sSno,jdbcType=VARCHAR},
</if>
<if test="record.dId != null">
d_id = #{record.dId,jdbcType=INTEGER},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update tbl_stu
set s_id = #{record.sId,jdbcType=INTEGER},
s_name = #{record.sName,jdbcType=VARCHAR},
s_sex = #{record.sSex,jdbcType=CHAR},
s_sno = #{record.sSno,jdbcType=VARCHAR},
d_id = #{record.dId,jdbcType=INTEGER}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="com.atrjxy.crud.bean.Student">
update tbl_stu
<set>
<if test="sName != null">
s_name = #{sName,jdbcType=VARCHAR},
</if>
<if test="sSex != null">
s_sex = #{sSex,jdbcType=CHAR},
</if>
<if test="sSno != null">
s_sno = #{sSno,jdbcType=VARCHAR},
</if>
<if test="dId != null">
d_id = #{dId,jdbcType=INTEGER},
</if>
</set>
where s_id = #{sId,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.atrjxy.crud.bean.Student">
update tbl_stu
set s_name = #{sName,jdbcType=VARCHAR},
s_sex = #{sSex,jdbcType=CHAR},
s_sno = #{sSno,jdbcType=VARCHAR},
d_id = #{dId,jdbcType=INTEGER}
where s_id = #{sId,jdbcType=INTEGER}
</update>
</mapper>
4)进行Spring单元测试环境
首先创建一个名称为MapperTest的测试类,来测试dao层的工作,需要先导入SpringTest模块,所以在pom.xml中引入jar包。
<!-- Spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
然后在测试类上方编写@ContextConfiguration来指定Spring配置文件的位置,以及上方再编写一个@RunWith(SpringJUnit4ClassRunner.class)然后直接autowired注入需要的组件即可。下面测试了插入几个班级信息,插入学生信息,以及批量插入学生信息的操作。这里需要说明一下,对于进行批量操作时,需要在Spring配置文件中配置一个可以执行批量操作的sqlSession。配置代码如下:
<!-- 配置一个可以执行批量操作的sqlSession -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" ></constructor-arg>
<constructor-arg name="executorType" value="BATCH" ></constructor-arg>
</bean>
接下来在测试类里编写相应的测试方法。
package com.atrjxy.crud.test;
import java.util.UUID;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.atrjxy.crud.bean.Deptment;
import com.atrjxy.crud.bean.Student;
import com.atrjxy.crud.dao.DeptmentMapper;
import com.atrjxy.crud.dao.StudentMapper;
//测试dao层的工作
//Spring的项目可以使用Spring的单元测试,可以自动注入需要的组件
/**1、导入SpringTest模块
* 2、@ContextConfiguration指定Spring配置文件的位置
* 3、直接autowired注入需要的组件即可
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class MapperTest {
@Autowired
DeptmentMapper deptmentmapper;
@Autowired
StudentMapper studentmapper;
@Autowired
SqlSession sqlSession;
//测试DeptmentMapper
@Test
public void testCRUD() {
System.out.println(deptmentmapper);
/**插入几个班级信息
deptmentmapper.insertSelective(new Deptment(null, "软件1901班"));
deptmentmapper.insertSelective(new Deptment(null, "软件1902班"));
*/
//插入学生信息
//studentmapper.insertSelective(new Student(null, "fengrui", "男", "20191610000", 1));
//批量插入多个学生信息
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
for(int i=0;i<3;i++) {
String name = UUID.randomUUID().toString().substring(0, 5);
mapper.insertSelective(new Student(null, name, "男", "123123", 1));
}
}
}
测试之后,打开数据库表里就有了增加的学生和班级信息了,到此,就测试完成了。接下来开始增删改查的操作了。
进行CRUD相关操作:
1.查询
具体流程:1、访问首页面index.jsp
2、index.jsp页面发送查询学生信息列表的请求
3、控制器StudentController接收并处理请求,查询学生信息
4、结果页面list.jsp显示学生信息
因为要实现一个分页查询信息的功能,所以需要在pom.xml中引入PageHelper分页插件,具体代码如下:
<!-- 引入PageHelper分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.0</version>
</dependency>
具体的使用方法:然后在控制器类StudentController中使用,在查询前先调用方法PageHelper.startPage(pn, 5);这里的传入参数分别是:页码,以及每页的大小。然后可以使用PageInfo包装查询后的结果,只需要将这个PageInfo交给页面就可以,PageInfo封装了详细的分页信息和查询出来的结果。最后将PageInfo添加到model中,在页面进行显示。(可以参考PageHelper网站有具体的使用方法)。
控制器类中需要使用@Autowired注解进行依赖注入,调用Service层的方法查询学生信息,同样的,Service层使用@Autowired注解自动注入,调用dao层来返回数据。Seivice层代码如下:
package com.atrjxy.crud.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.atrjxy.crud.bean.Student;
import com.atrjxy.crud.dao.StudentMapper;
//业务逻辑组件
@Service
public class StudentService {
@Autowired
StudentMapper studentMapper;
//查询所有学生信息
public List<Student> getAll() {
// TODO Auto-generated method stub
return studentMapper.selectByExampleWithDept(null);
}
}
查询学生信息的控制器类StudentController具体代码如下:
package com.atrjxy.crud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.atrjxy.crud.bean.Student;
import com.atrjxy.crud.service.StudentService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
/*
* 处理学生信息CRUD请求
*/
@Controller
public class StudentController {
@Autowired
StudentService studentService;
//查询学生信息(分页查询)
@RequestMapping("/stus")
public String getStus(@RequestParam(value = "pn",defaultValue = "1")Integer pn,Model model) {
//引入PageHelper分页插件
//在查询前只需要调用,传入参数:页码,以及每页的大小
PageHelper.startPage(pn, 5);
//startPage后面紧跟的这个查询就是分页查询
List<Student> stus = studentService.getAll();
//使用PageInfo包装查询后的结果,只需要将PageInfo交给页面就可以,PageInfo封装了详细的分页信息和查询出来的结果
//5:代表显示的页数量
PageInfo page = new PageInfo(stus,5);
//将PageInfo添加到model中,在页面进行显示
model.addAttribute("pageInfo", page);
return "list";
}
}
这样,后台代码就完成了,接下来搭建bootstrap分页页面。(具体使用方法可以参考bootstrap网站)
显示分页数据的页面list.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>学生信息</title>
<%
pageContext.setAttribute("A_PATH",request.getContextPath());
%>
<!-- web路径
以/开始的路径,找资源,以服务器的路径为准(http://local:3306),需要加上项目名称
(http://local:3306/ssm-crud)
-->
<script type="text/javascript" src="${A_PATH }/static/js/jquery-1.12.4.min.js"></script>
<link rel="stylesheet" href="${A_PATH }/static/bootstrap-3.4.1-dist/css/bootstrap.min.css">
<script src="${A_PATH }/static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
</head>
<body>
<!-- 搭建显示页面 -->
<div class="container">
<!-- 显示标题 -->
<div class="row">
<div class="col-md-6"><h2>学生信息管理系统</h2></div>
</div>
<div class="row">
<div class="col-md-6">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search for...">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Go</button>
</span>
</div>
</div>
</div>
<!-- 显示按钮 -->
<div class="row">
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-success btn-sm">添加信息</button>
<button class="btn btn-danger btn-sm">删除信息</button>
</div>
</div>
<!-- 显示表格信息 -->
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">学生信息列表</div>
<table class="table table-hover">
<tr>
<th>#</th>
<th>姓名</th>
<th>性别</th>
<th>学号</th>
<th>班级</th>
<th>操作</th>
</tr>
<c:forEach items="${pageInfo.list }" var="stu">
<tr>
<th>${stu.sId }</th>
<th>${stu.sName }</th>
<th>${stu.sSex }</th>
<th>${stu.sSno }</th>
<th>${stu.deptment.deptName }</th>
<th>
<button class="btn btn-success btn-sm">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
编辑</button>
<button class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
删除</button>
</th>
</tr>
</c:forEach>
</table>
</div>
</div>
</div>
<!-- 显示分页信息 -->
<div class="row">
<!-- 分页文字信息 -->
<div class="col-md-6">
当前第${pageInfo.pageNum}页,共${pageInfo.pages}页,共${pageInfo.total}条记录
</div>
<!-- 分页条信息 -->
<div class="col-md-6">
<nav aria-label="Page navigation">
<ul class="pagination">
<li><a href="${A_PATH }/stus?pn=1">首页</a></li>
<c:if test="${pageInfo.hasPreviousPage }">
<li>
<a href="${A_PATH }/stus?pn=${pageInfo.pageNum-1 }" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
</c:if>
<c:forEach items="${pageInfo.navigatepageNums }" var="page_Num">
<c:if test="${page_Num == pageInfo.pageNum }">
<li class="active"><a href="#">${page_Num }</a></li>
</c:if>
<c:if test="${page_Num != pageInfo.pageNum }">
<li><a href="${A_PATH }/stus?pn=${page_Num }">${page_Num }</a></li>
</c:if>
</c:forEach>
<c:if test="${pageInfo.hasNextPage }">
<li>
<a href="${A_PATH }/stus?pn=${pageInfo.pageNum+1 }" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</c:if>
<li><a href="${A_PATH }/stus?pn=${pageInfo.pages }">末页</a></li>
</ul>
</nav>
</div>
</div>
</div>
</body>
</html>
到此,显示分页查询数据就完成了。
为了实现客户端的无关性,接下来使用ajax让index.jsp页面直接发送ajax请求进行员工分页数据的查询,然后服务器将查询出的数据,以json字符串的格式返回给浏览器。浏览器收到json字符串,可以使用js对json字符串进行解析,使用js通过dom对页面数据进行增删改查。
在使用json字符串返回数据的时候,@ResponseBody注解可以自动将返回对象转换为json字符串,并且需要导入jackson包,所以在pom.xml添加依赖,具体代码如下:
<!-- 返回json字符串的支持 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.8</version>
</dependency>
为了进行增删改查后是否操作成功,定义一个json通用的返回的类名称为Msg,包含状态码,提示信息以及用户返回给浏览器的数据,并且含有它们的get和set方法,处理成功和处理失败的方法,以及add方法(主要用于添加pageInfo分页对象)。然后在StudentController控制器中,对查询学生信息的方法getStusWithJson的返回类型为Msg类型。类Msg的代码如下:
package com.atrjxy.crud.bean;
import java.util.HashMap;
import java.util.Map;
//json通用的返回的类
public class Msg {
//状态码 例如100-成功 200-失败
private int code;
//提示信息
private String msg;
//用户返回给浏览器的数据
private Map<String, Object> extend = new HashMap<String, Object>();
public static Msg success() {
Msg result = new Msg();
result.setCode(100);
result.setMsg("处理成功");
return result;
}
public static Msg fail() {
Msg result = new Msg();
result.setCode(200);
result.setMsg("处理失败");
return result;
}
public Msg add(String key,Object value) {
this.getExtend().put(key, value);
return this;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Map<String, Object> getExtend() {
return extend;
}
public void setExtend(Map<String, Object> extend) {
this.extend = extend;
}
}
控制器类StudentCotroller相关代码如下:
//@ResponseBody注解可以自动将返回对象转换为json字符串,并且需要导入jackson包
@RequestMapping("/stus")
@ResponseBody
public Msg getStusWithJson(@RequestParam(value = "pn",defaultValue = "1")Integer pn) {
//引入PageHelper分页插件
//在查询前只需要调用,传入参数:页码,以及每页的大小
PageHelper.startPage(pn, 5);
//startPage后面紧跟的这个查询就是分页查询
List<Student> stus = studentService.getAll();
//使用PageInfo包装查询后的结果,只需要将PageInfo交给页面就可以,PageInfo封装了详细的分页信息和查询出来的结果
//5:代表显示的每页大小
PageInfo page = new PageInfo(stus,5);
return Msg.success().add("pageInfo", page);
}