ssm整合CRUD(典藏版)

 

目录

 

前言

ssm框架整合之后,我们需要用其进行一个简单的CRUD。那么该如何进行呢?步骤是怎样的呢?本文将会从最开始环境搭建到最后所有功能的开发具体实现,一步步教会你改如何使用SSM框架进行CRUD。让我们开始吧。


1 准备工作

1.1 创建工程

本案例使用工具:

工具版本
IDEA 2021.3
MYSQL 5.0
maven 3.8.4
  1. IDEA中创建maven工程,准备好基础包。
    工程
包名作用
entity 存放实体类
handler 存放控制器类
service 存放service类和其实现类
mapper 存放mapper接口
test 存放测试类
  1. 注意设置maven本地仓库和使用自己的设置(防止都在默认的c盘,导致占用c盘空间过多)
    maven

1.2 物理建模

物理建模顾名思义就是在数据库中创建一个具体的table表,在数据库中实实在在存在的。那么本文以t-emp表为例。
下图给出数据库名称和表中字段名。
数据库与表

1.3 逻辑建模

物理建模完成之后,我们要在java代码中创建其实体类,即逻辑视图,以便将数据库与java代码进行绑定,便于后续操作。

public class Emp {
    private Integer empId;

    private String empName;

    private Double empSalary;

    public Emp() {
    }

    public Emp(Integer empId, String empName, Double empSalary) {
        this.empId = empId;
        this.empName = empName;
        this.empSalary = empSalary;
    }

    public Integer getEmpId() {
        return empId;
    }

    public void setEmpId(Integer empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Double getEmpSalary() {
        return empSalary;
    }

    public void setEmpSalary(Double empSalary) {
        this.empSalary = empSalary;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empId=" + empId +
                ", empName='" + empName + '\'' +
                ", empSalary=" + empSalary +
                '}';
    }
}

1.4引入依赖

将整个SSM整合需要的依赖全部用maven配置。其余按需添加

<?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>com.atguigu.ssm</groupId>
    <artifactId>demo-ssm-test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>


    <dependencies>
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- Spring 持久化层所需依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- 日志 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

        <!-- ServletAPI -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- Spring5和Thymeleaf整合包 -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>

        <!-- Mybatis核心 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>

        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.3</version>
        </dependency>

        <!-- 数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.31</version>
        </dependency>

        <!-- junit5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.7.0</version>
            <scope>test</scope>
        </dependency>

        <!-- Spring 的测试功能 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- Mybatis 和 Spring 的整合包 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        
        <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.3.1</version>
        </dependency>

    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>

1.5 加入日志配置文件

日志文件对于我们进行调试代码有很好的作用,我们可以使用日志配置文件进行更好的查询到异常问题所在。
注意:配置文件全部放在resources目录下。

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <!-- 指定日志输出的位置 -->
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志输出的格式 -->
            <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
        </encoder>
    </appender>

    <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->
    <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
    <root level="INFO">
        <!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
        <appender-ref ref="STDOUT" />
    </root>

    <!-- 根据特殊需求指定局部日志级别 -->
       <logger name="org.springframework.web.servlet.DispatcherServlet" level="DEBUG" />

</configuration>

全局日志级别我们一般都设置为debug。其余根据需求进行设置。比如说test测试类。


2 连接数据库并进行测试

2.1 创建jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:13306/mybatis-example
jdbc.username=root
jdbc.password=abc123

2.2 创建Spring配置文件

spring-persist.xml
创建spring-persist.xml配置文件引入jdbc.properties要注意引入context空间,如果不引入,接下来的操作会报各种错误。比如说:
在这里插入图片描述

引入名称空间:

 xmlns:context="http://www.springframework.org/schema/context"
 http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd

2.3 在Spring配置文件中引入jdbc.properties

<!--    引入外部文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

2.4 在spring配置文件中配置数据源

<!--    装配数据源(使用druid数据库连接池)-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
    </bean>

2.5 创建junit测试类测试

①在日志配置文件中为测试类设置日志级别

    <logger name="src/test/java/com/atguigu/ssm/SSMTest.java" level="DEBUG"/>

② 在test目录下创建一个测试类SSMTest

@SpringJUnitConfig(locations = {"classpath:spring-persist.xml"})
public class SSMTest {
    @Autowired
    private DruidDataSource dataSource;
    
    //使用日志进行输出,需要在logback.xml中设置类的日志级别为DUBUG
   Logger logger =  LoggerFactory.getLogger(getClass());
   
    @Test
    public void testConn() throws SQLException {
        DruidPooledConnection connection = dataSource.getConnection();
        //使用日志级别输出
        logger.debug(connection.toString());
    }
}

@SpringJUnitConfig -----spring整合junit5单元测试注解,指定spring配置文件位置,自动加载上下文。
注意:
我们使用的日志文件导入的包是:org.slf4j.Logge
日志
千万不要导错了。

3 spring整合mybatis

3.1 创建mybatis的配置文件

mybatis-config.xml
主要作用:

  • 设置驼峰式命名
  • 设置实体类所在包的别名
<?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>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- 设置实体类所在包的别名-->
    <typeAliases>
        <package name="com.atguigu.entity"/>
    </typeAliases>
</configuration>

3.2 测试mybatis

① 创建Mapper接口

public interface EmpMapper {
    List<Emp>  getAllEmp();
}

以查询全部数据为例。

② 创建mapper配置文件

<?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.atguigu.mapper.EmpMapper">
    <!--List<Emp>  getAllEmp();-->
<select id="getAllEmp" resultType="Emp">
    select * from t_emp
</select>
</mapper>

③ 在junit测试类中装配Mapper接口

@SpringJUnitConfig(locations = {"classpath:spring-persist.xml"})
public class SSMTest {
    @Autowired
    private DruidDataSource dataSource;
    
    @Autowired
    private EmpMapper empMapper;
    
   //使用日志进行输出,需要在logback.xml中设置类的日志级别为DUBUG
   Logger logger =  LoggerFactory.getLogger(getClass());

    @Test
    public void testList(){
        List<Emp> empList = empMapper.getAllEmp();
        for (Emp emp : empList) {
            System.out.println("emp=" +emp);
        }
    } 
}

3.3 配置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: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 ">

<!--    引入外部文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
<!--    装配数据源(使用druid数据库连接池)-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
    </bean>

<!--    设置自动扫描service的包-->
    <context:component-scan base-package="com.atguigu.service"/>

<!-- 整合mybatis-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 指定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--指定mapper.xml-->
        <property  name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
        <!--装配数据源-->
        <property name="dataSource" ref="druidDataSource"/>

        <!--配置分页插件-->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <props>
                            <!--设置reasonable为true表示将页码进行合理化ixuzheng,页码的有效范围是1-总页数-->
                            <prop key="reasonable">true</prop>
                            <!--数据库方言,即同样的sql语句在不同数据库中语法会有差异。默认mysql-->
                            <prop key="helperDialect">mysql</prop>
                        </props>
                    </property>
                </bean>
            </array>
        </property>
    </bean>
<!--配置扫描Mapper接口到IOC容器-->
  <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
      <property name="basePackage" value="com.atguigu.mapper"/>
  </bean>

<!--    配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>
    
        <!--    开启声明式事务-->
    <tx:annotation-driven  transaction-manager="transactionManager"/>
</beans>

注意:

  • 注意开启注解声明式事务需要引入的名称空间为
 xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd ">
  • 注意配置sqlsessionFactoryBean的时候,要将mapper.xml中开启对哪一个mapper接口的配置,如果不写,会报错

Error creating bean with name ‘sqlSessionFactory’ defined in class path resource [spring-persist.xml]: Invocation of init method failed; nested exception is org.springframework.core.NestedIOException: Failed to parse mapping resource

应该这样写

<?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.atguigu.mapper.EmpMapper">  
</mapper>

3.4 测试Spring

①创建Service接口

List<Emp> getALL();

② 创建Service类

在需要使用事务的方法上加@Transaction注解,readOnly ----只读

@Service
public class EmpServiceImpl implements EmpService {
    @Autowired
    private EmpMapper empMapper;
    @Override
    @Transactional(readOnly = true)
    public List<Emp> getALL() {
        return empMapper.getAllEmp();
    }
}

③ 测试

 	@Autowired
    private EmpService empService;
	
    @Test
    public void testtx(){
        List<Emp> empList = empService.getALL();
        for (Emp emp : empList) {
            System.out.println("emp=" +emp);
        }
    }

4 web.xml

4.1 生成web.xml

在pom.xml中将当前module的打包方式修改为war。

<packaging>war</packaging>

4.2 设置web工程

在这里插入图片描述

4.3 配置web.xml

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<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_4_0.xsd"
         version="4.0">

<!--    配置contextLoaderListener-->
<!--    使用contextConfigLocation读取配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-persist.xml</param-value>
    </context-param>
<!--    配置监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

<!--配置dispatcherServlet-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--    指定springmvc-config.xml-->
        <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc-config.xml</param-value>
    </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

<!--    配置字符集-->
    <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>

    <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>
</web-app>

5 创建SpringMVC的配置文件

springmvc-config.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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--配置自动扫描controller的包-->
    <context:component-scan base-package="com.atguigu.handler"/>

    <!-- 配置 Thymeleaf 的视图解析器 -->
    <bean id="thymeleafViewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <property name="suffix" value=".html"/>
                        <property name="characterEncoding" value="UTF-8"/>
                        <property name="templateMode" value="HTML5"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>


	<!--view-controller-->
    <mvc:view-controller path="/" view-name="index"/>
  <!--默认访问处理器-->
    <mvc:default-servlet-handler/>
    <!--注解驱动-->
    <mvc:annotation-driven/>

</beans>

6 显示首页

① 创建首页对应的视图模板文件

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body style="text-align: center">
<h1>首页</h1>
</body>
</html>

②配置访问首页的view-controller

 <mvc:view-controller path="/" view-name="index"/>

一般默认首页是index。


小结

经过前面的六个步骤,基本准备工作已经完成。其中1-3步骤是持久层操作,4-6是表述层操作。
在这里插入图片描述
在这里插入图片描述

下面让我们进行具体功能开发吧。
在此之前我们先将后面的地址使用Rest风格进行规范下吧。

功能地址请求方式
删除 /emp/{empId}/{pageNo} DELETE
前往新增页面 /emp/add view-controller
提交新增表单 /emp POST
前往更新页面 /emp/{empId}/{pageNo} GET
提交更新表单 /emp PUT

7 显示数据列表

在这里插入图片描述

7.1 创建EmpHandler类并完成编写

①首页上设置一个超链接,点击超链接跳转到显示全部数据页面

	<a th:href="@{/get/all}">显示全部数据</a><br>

②在类上标记@Controller注解

③在handler中装配EmpService

前面我们在进行测试的时候就已经将mapper接口和mapper.xml以及empService接口及实现类中查询全部数据的代码已经完成了,现在我们只需要编写EmpHandler。

@Controller
public class EmpHandler {
        @Autowired
        private EmpService empService;
        @RequestMapping("/get/all")
        public String getALLEmpList(Model model){
        	//调用EmployeeService的方法获取所需数据
            List<Emp> empList = empService.getALL();
            //将EmployeeService的方法返回的数据存入模型
            model.addAttribute("empList",empList);
            //返回逻辑视图
            return "emp-list";
        }

7.2 创建逻辑视图对应的视图模板页面

创建emp-list.html页面来展示全部数据页面。

① 从请求域 读取要显示的数据

②遍历数据集合显示数据

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <style type="text/css">
    table{
      border-collapse: collapse;
      margin: 0px auto 0px auto;
    }
    table th,td {
      border: 1px solid black;
      text-align: center;
    }
  </style>
</head>
<body>
<table>
  <tr>
    <td>ID</td>
    <td>empName</td>
    <td>empSalary</td>
  </tr>
  <tbody th:if="${#lists.isEmpty(empList)}">
  <tr>
    <td colspan="3">抱歉,没有查询到数据!</td>
  </tr>
  </tbody>
  <tbody th:if="${not #lists.isEmpty(empList)}">
  <tr th:each="emp:${empList}">
    <td th:text="${emp.empId}">这里显示员工ID</td>
    <td th:text="${emp.empName}">这里显示员工姓名</td>
    <td th:text="${emp.empSalary}">这里显示员工工资</td>
  </tr>
  </tbody>
</table>


<a th:href="@{/}">回首页</a>
</body>
</html>

我们还可以设置一个超链接返回首页。

8 分页显示数据列表

当数据很多的时候,我们适当分页并设置简单导航来使得查看数据更加便捷。
在这里插入图片描述
在这里插入图片描述

8.1 环境准备

① 导入依赖

 <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.3.1</version>
        </dependency>

②在SqlsessionFactoryBean中配置PageHelper插件

<!--配置分页插件-->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <props>
                            <!--设置reasonable为true表示将页码进行合理化ixuzheng,页码的有效范围是1-总页数-->
                            <prop key="reasonable">true</prop>
                            <!--数据库方言,即同样的sql语句在不同数据库中语法会有差异。默认mysql-->
                            <prop key="helperDialect">mysql</prop>
                        </props>
                    </property>
                </bean>
            </array>
        </property>

8.2在首页添加超链接,需要考虑页码值(pageNo)传入

<a th:href="@{/get/page/1}">显示分页数据</a>

这里我们默认设置点击超链接,跳转页面显示从第一页开始。

8.3 service方法中实现分页功能

①empservice接口

 ```java
 //分页实现
    PageInfo<Emp> getPageInfo(Integer pageNo);
```

②实现类

 @Override
    public PageInfo<Emp> getPageInfo(Integer pageNo) {
        //设置每页显示的数据条数
        int pageSize = 6;

        //设定分页数据,开启分页功能
        PageHelper.startPage(pageNo,pageSize);


        //执行查询功能
        List<Emp> empList = empMapper.getAllEmp();

        //封装为pageInfo对象返回
        return new PageInfo<>(empList);

    }

8.4 EmpHandler实现

 @RequestMapping("/get/page/{pageNo}")
         public String getPage(
        		 //传入页码值
                 @PathVariable("pageNo")Integer pageNo,
                 Model model
        ){
            PageInfo<Emp> pageInfo = empService.getPageInfo(pageNo);
            //分页数据存入模型
            model.addAttribute("pageInfo",pageInfo);
            //返回逻辑视图
            return "emp-page";
        }

注意映射文件中页码值不能写具体数据,那样就直接写死了。

8.5 完成页面显示

创建emp-page.html
在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
      table{
        border-collapse: collapse;
        margin: 0px auto 0px auto;
      }
      table th,td {
        border: 1px solid black;
        text-align: center;
      }
    </style>
</head>
<body>
<table>
  <tr>
    <td>ID</td>
    <td>empName</td>
    <td>empSalary</td>
  </tr>
  <tbody th:if="${#lists.isEmpty(pageInfo.list)}">
    <tr>
      <td colspan="3">抱歉,没有查询到数据!</td>
    </tr>
  </tbody>
  <tbody th:if="${not #lists.isEmpty(pageInfo.list)}">
  <tr th:each="emp:${pageInfo.list}">
    <td th:text="${emp.empId}">这里显示员工ID</td>
    <td th:text="${emp.empName}">这里显示员工姓名</td>
    <td th:text="${emp.empSalary}">这里显示员工工资</td>
  </tr>
  <tr>
    <td colspan="3">
      <!--判断是否有上一页-->
      <span th:if="${pageInfo.hasPreviousPage}">
        <a th:href="@{/get/page/1}">首页</a>
        <!-- 不能是@{/get/page/prePage},如果这样写就变成路径了。-->
      <a th:href="@{/get/page/}+${pageInfo.prePage}">上一页</a>
      </span>


      <!--循环页码,判断是否是当前页[1]-->
      <span th:each="navigator:${pageInfo.navigatepageNums}">
        <!--如果不是,显示可跳转的超链接-->
        <a th:if="${navigator != pageInfo.pageNum}"
           th:href="@{/get/page/}+${navigator}"
           th:text="'['+${navigator}+']'"></a>
        <!--如果是当前页,显示页码-->
        <span th:if="${navigator == pageInfo.pageNum}"
              th:text="'['+${navigator}+']'">
        </span>
      </span>

      <!--判读是否有下一页-->
      <span th:if="${pageInfo.hasNextPage}">
        <a th:href="@{/get/page/}+${pageInfo.nextPage}">下一页</a>
        <a th:href="@{/get/page/}+${pageInfo.pages}">最后一页</a>
      </span>

      <span th:text="${pageInfo.pageNum} + '/' +${pageInfo.pages}"></span>

    </td>
  </tr>
  </tbody>
  <tr>
    <td colspan="3">
      <!--绑定值改变事件响应函数-->
      <input id="jumpToPageNumInput" type="text" name="jumpToPageNum" placeholder="请输入你想直接跳转的页码"/>
    </td>
  </tr>
</table>
<!--编辑点击响应函数-->
<script type="text/javascript">
  // 获取页码文本框的元素对象
  var jumpPageNumEle = document.getElementById("jumpToPageNumInput");
  // 给页码文本框绑定至改变响应函数
  jumpPageNumEle.onchange = function () {
    // 触发值改变响应函数后,获取当前文本框中用户输入的值
    var targetNum = this.value;
    // 检测用户输入的数据是否是数字
    if(isNaN(targetNum)){
      // 如果不是数字则恢复文本框
      this.value="";
      // 当前函数结束
      return ;
    }

    //如果用户输入合法,则跳转页面
    //[[@{/get/page/}]] 表示解析thymeleaf表达式
    window.location.href="[[@{/get/page/}]]" + targetNum;
  }
</script>

<a th:href="@{/}">首页</a><br>

</body>
</html>

9 删除操作

在这里插入图片描述

9.1 在页面上给每一条记录编写超链接

 <tr>
    <th>ID</th>
    <th>NAME</th>
    <th>SALARY</th>
      <th>删除</th>
      <th>更新</th>
  </tr>
 <!--设置删除超链接并绑定事件-->
    <td>
      <a onclick="convertMethod(this,event)"
         th:href="@{/emp/}+${emp.empId}+'/'+${pageInfo.pageNum}">删除</a>
    </td>

9.2 转换请求方式,将点击超链接的GET请求转换为最终的DELETE请求

我们的思路是提供一个空表单,作为通用组件。
在这里插入图片描述

<!--提供一个空表单,实现请求转换-->
<!--id作用是通过js代码获取表单对象,rest风格要求将post请求,以_method为参数名,delete为参数值转换请求-->
<form id="convertFrom" method="post" >
  <input type="hidden" name="_method" value="delete">
</form>

配套的js代码

<!--给每一个删除超链接绑定单击响应函数-->
<script type="text/javascript">
  function convertMethod(anchorElement,event) {

    //获取超链接原本要访问的目标地址
     var targetURL =anchorElement.href;
    //获取表单对象
     var  formEle = document.getElementById("convertFrom");

     //把超链接要访问的地址设置给表单action属性
    formEle.action = targetURL;

    //提交表单
    formEle.submit();

    //取消控件的默认行为,让超链接不会跳转
    event.preventDefault();
  }
</script>

9.3 mapper接口及配置文件

void deleteEmpByPrimaryId(Integer empId);
<!--    void deleteEmpByPrimaryId(Integer empId);-->
<delete id="deleteEmpByPrimaryId">
    delete from t_emp where  emp_id = #{empId}
</delete>

9.4 service接口及实现类

//删除
    void doDeleteEmpByPrimaryId(Integer empId);
@Override
    public void doDeleteEmpByPrimaryId(Integer empId) {
        empMapper.deleteEmpByPrimaryId(empId);
    }

9.5 handler类

在这里插入图片描述

   @RequestMapping(value="/emp/{empId}/{pageNo}",method = RequestMethod.DELETE)
    public String doDelete(
            @PathVariable("empId")Integer empId,
            @PathVariable("pageNo")Integer pageNo
        ){
            empService.doDeleteEmpByPrimaryId(empId);
            return "redirect:/get/page/"+pageNo;
        }

10 新增操作

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

10.1 跳转到表单(edit-add.html)

① 编写超链接

<a th:href="@{/emp/add}">添加数据</a>

②在springmvc-config.xml中配置

<mvc:view-controller path="/emp/add" view-name="emp-add"/>

③创建表单所在的视图模板文件(edit-add.html)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        table{
            border-collapse: collapse;
            margin: 0px auto 0px auto;
        }
        table th,td {
            border: 1px solid black;
            text-align: center;
        }
    </style>
</head>
<body>
<form  th:action="@{/emp}" method="post">
    姓名:<input type="text" name="empName"/><br/>
    工资:<input type="text" name="empSalary"/><br/>
    <button type="submit">保存</button>
</form>

</body>
</html>

10.2 提交表单

①mapper接口及配置

void insert(Emp emp);
<!--     void insert(Emp emp);-->
    <insert id="insert">
        insert into t_emp values(null,#{empName},#{empSalary})
    </insert>

②serivce方法及实现类

//新增
    void doAdd(Emp emp);
 @Override
    public void doAdd(Emp emp) {
        empMapper.insert(emp);
    }

③handler方法

  @RequestMapping(value="/emp",method = RequestMethod.POST)
    public String doSave(
            //使用实体类接收发送过来的请求参数
            Emp emp ){
        empService.save(emp);
        //跳转到最后一页,Integer.MAX_VALUE---为了确保直接前往最后一页
        return "redirect:/get/page/"+Integer.MAX_VALUE;
    }

11 更新操作(回显+提交)

在这里插入图片描述

11.1 跳转到表单页面(emp-edit.html),回显数据(本质是查询)

①编写超链接,传参数:empId和pageNum

 <tr>
    <td>ID</td>
    <td>empName</td>
    <td>empSalary</td>
    <td>删除</td>
    <td>更新</td>
  </tr>
<td>
    <a th:href="@{/emp/}+${emp.empId}+'/'+${pageInfo.pageNum}">更新</a>
  </td>

②mapper接口及配置文件

 Emp selectedEmpByPrimaryId(Integer empId);
<!--    Emp selectedEmpByPrimaryId(Integer empId);-->
<select id="selectedEmpByPrimaryId" resultType="emp">
   select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}
</select>

③ service方法及实现类

//查询
    Emp  selectEmpById(Integer empId);
 @Override
    public Emp selectEmpById(Integer empId) {
        
        return empMapper.selectedEmpByPrimaryId(empId);
    }

④handler方法

在这里插入图片描述

 @RequestMapping(value="/emp/{empId}/{pageNo}",method = RequestMethod.GET)
    public String  doFormResisPlayer(
            @PathVariable("empId") Integer empId,
            @PathVariable("pageNo") Integer pageNo,
            Model model
    ){
        Emp emp = empService.getEmpById(empId);
        //将实体类对象存入模型
        model.addAttribute("emp",emp);
        //前往表单页面
        return "emp-edit";
    }

④ 创建表单所在的视图模板文件

emp-edit

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>更新</title>
</head>
<body>
<form th:action="@{/emp}" method="post">
    <!--id 页数等都要回显,但是用户不关心,所以用隐藏域-->
  <input type="hidden" name="_method" value="put"/>
  <input type="hidden" name="pageNo" th:value="${pageNo}"/>
  <input type="hidden" name="empId" th:value="${emp.empId}"/>

  姓名:<input type="text" name="empName" th:value="${emp.empName}"/><br/>
  工资:<input type="text" name="empSalary" th:value="${emp.empSalary}"/><br/>
  <button type="submit">更新</button>

</form>
</body>
</html>

11.2 提交表单

①mapper接口及配置文件

void updateByPrimaryKey(Emp emp);
<!--    void updateByPrimaryKey(Emp emp);-->
    <update id="updateByPrimaryKey">
        update t_emp  set emp_name=#{empName},emp_salary=#{empSalary} where emp_id = #{empId}
    </update>

② service方法及实现类

  void doUpdate(Emp emp);
 @Override
    public void doUpdate(Emp emp) {
        
        empMapper.updateByPrimaryKey(emp);
    }

③ handler方法

  @RequestMapping(value = "/emp",method = RequestMethod.PUT)
    public String doUpdate(
            Emp emp,
            @RequestParam("pageNo") Integer pageNo
    ){
        empService.doUpdate(emp);
		//	跳转到最后一页
        return "redirect:/get/page/"+pageNo;
    }

总结

至此我们已经完成了基于ssm框架基本的crud操作,可以将此案例作为一个练手项目。
不足之处还请多多指教。

posted @ 2022-10-26 18:01  hxld  阅读(64)  评论(0编辑  收藏  举报