SSM整合(经典自我版)

SSM整合

提示:自我练习之后参考进行自主整合


文章目录

  • SSM整合
  • 前言
  • 一、SSM整合搭建环境持久化层操作(spring和mybatis)
    • 1 准备工作
      • 1.1 物理建模
      • 1.2 创建Project 或者 module
      • 1.3 逻辑建模
      • 1.4 引入依赖
      • 1.5 加入日志配置文件 logback.xml
    • 2 连接数据库
      • 2.1 创建jdbc.properties文件
      • 2.2 创建 Spring 配置文件
      • 2.3 在 Spring 配置文件中引入 jdbc.properties
      • 2.4 在 Spring 配置文件中配置数据源
      • 2.5 创建Junit测试类测试
        • ① 在日志配置文件中为测试类设置日志级别
        • ② 在 Junit 测试中装配数据源
        • ③ 类上面添加 @SpringJUnitConfig
    • 3 Spring整合MyBatis
      • 3.1 框架环境层面
        • 3.1.1 创建 MyBatis 的全局配置文件
        • 3.1.2 在 Spring 配置文件中配置 SqlSessionFactoryBean
          • ①指定mybatis全局配置文件的位置
          • ② 指定 Mapper 配置文件 /*Mapper.xml 的位置
          • ③装配数据源
        • 3.1.3 把 Mapper 接口所在的包扫描到IOC容器
      • 3.2 具体功能层面
        • ① 创建Mapper接口
        • ② 创建Mapper配置文件
        • ③ 在 Junit 测试类中装配 Mapper 接口并测试
    • 4 配置Spring声明式事务
      • 4.1 框架环境层面
        • ① 在 Spring 的配置文件中配置事务管理器
        • ② 在 Spring 的配置文件中开启基于 注解的声明式事务
        • ③ 配置针对 Service 类的自动扫描的包
      • 4.2 具体功能层面
        • 4.2.1 创建 Service 接口
        • 4.2.2 创建 Service 接口实现类
        • 4.3 在需要使用事务的方法上加 @Transactional 注解
        • 4.4 在 Junit 测试类中装配 Service 接口并测试
    • 5 最终bean图
  • 二、SSM整合搭建环境表述层操作(spring和springMVC)
    • 1 生成web.xml
    • 2 配置web.xml
    • 3 配置SpringMVC
    • 4 显示首页
      • ① 创建首页对应的视图模板文件
      • ② 在 spring-mvc.xml 中进行配置
    • 5 最终bean 图
  • 三、具体功能开发
    • 1 显示数据列表(全部数据)
      • 1.1 创建 EmpHandler 类
      • 1.2 在 EmpHandler 类中声明处理请求的方法
      • 1.3 创建逻辑视图对应的视图模板页面
        • ① 首先在首页先设置一个超链接能够跳转到显示全部数据的页面
        • ② 创建 emp-list.html页面
        • ③ 从请求域中读取要显示的数据
        • ④ 遍历数据
    • 2 分页显示数据列表
      • 2.1 准备环境
        • ① 导入依赖
        • ② 在 SqlSessionFactoryBean 中配置 PageHelper 插件
      • 2.2 开发功能
        • ① 在首页中添加一个超链接,需要考虑页码值传入
        • ② 在 EmpHandler 声明 handler 方法
        • ③在 Service 方法实现分页
        • ④ 完成页面显示
    • 3 删除操作
      • 3.1 在页面上给每一条记录编写超链接
      • 3.2 转换请求方式:把点击超链接的 GET 请求转换为最终的 DELETE 请求
        • ① 编写超链接对应的 handler 方法
        • ② 给每一个删除超链接绑定单击响应函数 @click
        • ③编写超链接对应的 handler 方法
        • ④编写 handler 方法要调用的 Service 方法
        • ④编写Mapper及其相关配置
    • 4 新增操作
      • 4.1 跳转到表单页面(emp-add.html)
        • ① 编写超链接
        • ② 配置view-controller
        • ③ 创建emp-add.html
      • 4.2 提交表单
        • ①handler方法
        • ② service方法
        • ③ Mapper及其配置文件
    • 5 更新操作
      • 5.1 跳转到表单页面,回显数据
        • ① 编写超链接
        • ② handler方法
        • ③ service方法
        • ④ Mapper及其配置文件
      • 5.2 提交表单
        • ①创建emp-edit 页面
        • ② 编写handler 方法
        • ③ 编写service方法
        • ④Mapper及其配置文件
  • 总结 相关知识合集


前言

代码要多练,自己练,独立练,才能有效,不能做脱离视频课件的三不知

这篇文章能够帮助你了解基础框架SSM的整合及进行相应的增删改查操作


一、SSM整合搭建环境持久化层操作(spring和mybatis)

本质Spring接管一切,代码更加简洁。

  • Spring管理数据源,连接数据库
  • Spring管理SqlSessionFactory,开启SqlSession的细节被屏蔽了
  • Spring的IOC容器负责注入Mapper接口
  • Spring管理声明式事务。

1 准备工作

SSM整合(经典自我版)_第1张图片

1.1 物理建模

所需工具:

工具 版本
IDEA 2021.3
mysql 5.7
maven 3.8.4

物理建模顾名思义就是在数据库中创建一个具体的table表,在数据库中实实在在存在的。本文以t-emp表为例。
下图给出数据库名称和表中字段名。
SSM整合(经典自我版)_第2张图片

1.2 创建Project 或者 module

在idea中创建对应工程或者模块

SSM整合(经典自我版)_第3张图片

包名 作用
entity 存放实体类
handler 存放控制器类
service 存放service类和其实现类
mapper 存放mapper接口
test 存放测试类

1.3 逻辑建模

entity包中创建和数据库对应的实体类Employee

代码示例如下:

package com.atguigu.ssm.entity;
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框架整合所需依赖添加,这里属于基础依赖,后续其他依赖需要按相应功能使用添加。

 <dependencies>

        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-webmvcartifactId>
            <version>5.3.1version>
        dependency>

        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-ormartifactId>
            <version>5.3.1version>
        dependency>

        
        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-classicartifactId>
            <version>1.2.3version>
        dependency>

        
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
            <version>3.1.0version>
            <scope>providedscope>
        dependency>

        
        <dependency>
            <groupId>org.thymeleafgroupId>
            <artifactId>thymeleaf-spring5artifactId>
            <version>3.0.12.RELEASEversion>
        dependency>

        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.5.7version>
        dependency>

        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.3version>
        dependency>

        
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.0.31version>
        dependency>

        
        <dependency>
            <groupId>org.junit.jupitergroupId>
            <artifactId>junit-jupiter-apiartifactId>
            <version>5.7.0version>
            <scope>testscope>
        dependency>

        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-testartifactId>
            <version>5.3.1version>
        dependency>

        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatis-springartifactId>
            <version>2.0.6version>
        dependency>


        
        <dependency>
            <groupId>com.github.pagehelpergroupId>
            <artifactId>pagehelperartifactId>
            <version>5.2.0version>
        dependency>

    dependencies>

1.5 加入日志配置文件 logback.xml

SSM整合(经典自我版)_第4张图片
加入配置文件主要是为了能够调试代码,输出日志,进而了解异常等问题所在根源。
注意:配置文件全部放在resources目录下。

loback.xml


<configuration debug="true">
    
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>

            
            
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%npattern>
        encoder>
    appender>

    
    
    <root level="INFO">
        
        <appender-ref ref="STDOUT" />
    root>


    
    <logger name="org.springframework.web.servlet.DispatcherServlet" level="DEBUG"/>
  
configuration>

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



2 连接数据库

SSM整合(经典自我版)_第5张图片

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-presist.xml
SSM整合(经典自我版)_第6张图片
创建spring-persist.xml配置文件引入jdbc.properties要注意引入context空间,如果不引入,接下来的操作会报各种错误。比如说:
在这里插入图片描述

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

 
    <context:property-placeholder location="classpath:jdbc.properties"/>

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

 
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">

        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>

    bean>

注意:这里使用的是druid 数据库连接池 DruidDataSource
并且 必须写成 driverClassName

2.5 创建Junit测试类测试

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

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

② 在 Junit 测试中装配数据源

 @Autowired
    private DataSource dataSource;

注意:引入的是import javax.sql.DataSource;

③ 类上面添加 @SpringJUnitConfig

@SpringJUnitConfig(locations = {"classpath:spring-persist.xml"})
public class SSMTest {

@SpringJUnitConfig -----spring整合junit5单元测试注解,指定spring配置文件位置,自动加载上下文。

完整代码如下:

@SpringJUnitConfig(locations = {"classpath:spring-persist.xml"})
public class SSMTest {

    @Autowired
    private DataSource dataSource;

	 //使用日志进行输出,需要在logback.xml中设置类的日志级别为DEBUG
    Logger logger = LoggerFactory.getLogger(getClass());
    
	@Test
    public void testConn() throws SQLException {
        Connection connection = dataSource.getConnection();
        //使用日志级别输出
        logger.debug(connection.toString());
    }
}

注意:
我们使用的日志文件导入的包是:org.slf4j.Logge
SSM整合(经典自我版)_第7张图片

3 Spring整合MyBatis

SSM整合(经典自我版)_第8张图片


3.1 框架环境层面

SSM整合(经典自我版)_第9张图片


3.1.1 创建 MyBatis 的全局配置文件


SSM整合(经典自我版)_第10张图片

mybatis-config.xml
主要作用:

  • 设置驼峰式命名
  • 设置实体类所在包的命名

代码示例如下:


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.ssm.entity"/>
    typeAliases>

configuration>

3.1.2 在 Spring 配置文件中配置 SqlSessionFactoryBean

①指定mybatis全局配置文件的位置
  • 方式一 configLocation
  
        <property name="configLocation" value="classpath:mybatis-config.xml"/>

  • 方式二 configuration
 
        <property name="configuration">
            <bean class="org.apache.ibatis.session.Configuration">
                
                <property name="mapUnderscoreToCamelCase" value="true"/>
            bean>
        property>
  
        
        <property name="typeAliasesPackage" value="com/atguigu/ssm/entity"/>

② 指定 Mapper 配置文件 /*Mapper.xml 的位置

        <property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>

/*Mapper.xml代表对所有的mapper配置文件有效

③装配数据源
   
        <property name="dataSource" ref="druidDataSource"/>

3.1.3 把 Mapper 接口所在的包扫描到IOC容器

  • 方式一 mybatis-spring:scan
 
    <mybatis-spring:scan base-package="com.atguigu.ssm.mapper"/>

  • 方式二 mapperScannerConfigurer
  
    
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
 <property name="basePackage" value="com.atguigu.ssm.mapper"/>
   bean>

完整配置如下:

 
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        
        

        
        <property name="configuration">
            <bean class="org.apache.ibatis.session.Configuration">
                
                <property name="mapUnderscoreToCamelCase" value="true"/>
            bean>
        property>

        
        
        <property name="typeAliasesPackage" value="com/atguigu/ssm/entity"/>

        
        <property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>

        
        <property name="dataSource" ref="druidDataSource"/>

    
    
    
    
    

    
    <mybatis-spring:scan base-package="com.atguigu.ssm.mapper"/>

3.2 具体功能层面

SSM整合(经典自我版)_第11张图片

① 创建Mapper接口


public interface EmpMapper {

    List<Emp> selectAll();

② 创建Mapper配置文件



DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">





<mapper namespace="com.atguigu.ssm.mapper.EmpMapper">

    
    <select id="selectAll" resultType="Emp">
        select emp_id,emp_name,emp_salary from t_emp
    select>

③ 在 Junit 测试类中装配 Mapper 接口并测试


@SpringJUnitConfig(locations = {"classpath:spring-persist.xml"})
public class SSMTest {


    @Autowired
    private DataSource dataSource;


    @Autowired
    private EmpMapper empMapper;


    //使用日志进行输出,需要在logback.xml中设置类的日志级别为DEBUG
    Logger logger = LoggerFactory.getLogger(getClass());


    @Test
    public void testTx(){
        List<Emp> empList = empService.getAll();
        for (Emp emp : empList) {
            System.out.println("emp = " + emp);//打  soutv 字母即为快捷键,可以快速生成foreach循环
        }
    }



4 配置Spring声明式事务

SSM整合(经典自我版)_第12张图片

4.1 框架环境层面

SSM整合(经典自我版)_第13张图片

① 在 Spring 的配置文件中配置事务管理器


    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        
        <property name="dataSource" ref="druidDataSource"/>
    bean>

② 在 Spring 的配置文件中开启基于 注解的声明式事务


    <tx:annotation-driven transaction-manager="transactionManager"/>

注意:引入tx名称空间时千万注意名称空间的值
SSM整合(经典自我版)_第14张图片

③ 配置针对 Service 类的自动扫描的包

 
    <context:component-scan base-package="com.atguigu.ssm.service"/>

4.2 具体功能层面

SSM整合(经典自我版)_第15张图片

4.2.1 创建 Service 接口

public interface EmpService {
    List<Emp> getAll();

4.2.2 创建 Service 接口实现类

@Service
public class EmpServiceImpl implements EmpService {
    @Autowired
   private EmpMapper empMapper;
   
    @Override
    public List<Emp> getAll() {
        return empMapper.selectAll();
    }

4.3 在需要使用事务的方法上加 @Transactional 注解

@Transactional(readOnly = true)  //为当前业务层添加事务 “只读”
    public List<Emp> getAll() {
    

4.4 在 Junit 测试类中装配 Service 接口并测试

@SpringJUnitConfig(locations = {"classpath:spring-persist.xml"})
public class SSMTest {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private EmpMapper empMapper;

    @Autowired
    private EmpService empService;

    //使用日志进行输出,需要在logback.xml中设置类的日志级别为DEBUG
    Logger logger = LoggerFactory.getLogger(getClass());

    @Test
    public void testTx(){
        List<Emp> empList = empService.getAll();
        for (Emp emp : empList) {
            System.out.println("emp = " + emp);//打  soutv 字母即为快捷键,可以快速生成foreach循环
        }
    }

注意
需要使用 @Autowired注解装配service接口

5 最终bean图

SSM整合(经典自我版)_第16张图片

二、SSM整合搭建环境表述层操作(spring和springMVC)

SSM整合(经典自我版)_第17张图片
本质:

  • ContextLoaderListener:读取 spring-persist.xml
  • DispatcherServlet:读取 spring-mvc.xml

1 生成web.xml

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

<packaging>warpackaging>

SSM整合(经典自我版)_第18张图片

2 配置web.xml

SSM整合(经典自我版)_第19张图片


<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">


    
    
    <context-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:spring-persist.xmlparam-value>
    context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
    listener>

    
    <servlet>
        <servlet-name>dispatcherServletservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:spring-mvc.xmlparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServletservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>

    
    
    <filter>
        <filter-name>characterEncodingFilterfilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>UTF-8param-value>
        init-param>
        <init-param>
            <param-name>forceRequestEncodingparam-name>
            <param-value>trueparam-value>
        init-param>
        <init-param>
            <param-name>forceResponseEncodingparam-name>
            <param-value>trueparam-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>characterEncodingFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

    
    <filter>
        <filter-name>hiddenHttpMethodFilterfilter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>hiddenHttpMethodFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>
web-app>

3 配置SpringMVC

SSM整合(经典自我版)_第20张图片


<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">

    
    
    <context:component-scan base-package="com.atguigu.ssm.handler"/>

    
    <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>

    
    <mvc:annotation-driven/>

    
    <mvc:default-servlet-handler/>

beans>

SSM整合(经典自我版)_第21张图片

4 显示首页

在这里插入图片描述

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

SSM整合(经典自我版)_第22张图片

  • portal.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>

② 在 spring-mvc.xml 中进行配置


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

5 最终bean 图

SSM整合(经典自我版)_第23张图片

小结:
经过以上SSM整合的准备工作后,主要是对框架环境的搭建,下面开始进行分页显示数据以及基本的增删改查操作。

三、具体功能开发

下面的操作使用 restful 风格,具体功能清单

功能 URL地址 请求方式
访问首页 / view-controller
查询全部数据 /get/all GET
查询分页数据 /get/page/{pageNo} GET
删除 /emp/{empId}/{pageNo} DELETE
跳转到添加页面 /emp/add view-controller
提交表单(执行保存) /emp POST
跳转到更新页面 /emp/{empId}/{pageNo} GET
执行更新 /emp PUT

1 显示数据列表(全部数据)

SSM整合(经典自我版)_第24张图片

SSM整合(经典自我版)_第25张图片

1.1 创建 EmpHandler 类

@Controller
public class EmpHandler {

    @Autowired
    private EmpService empService;

为了让springMVC找到控制器,当前的控制器就必须是IOC容器中的组件,因此需要加上注解 @Controller

1.2 在 EmpHandler 类中声明处理请求的方法

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

@Controller
public class EmpHandler {

    @Autowired
    private EmpService empService;

    @RequestMapping("/get/all")
    public String getAll(Model model) {

        //1.查询数据
        List<Emp> empList = empService.getAll();

        //2.存入模型
        model.addAttribute("empList", empList);


        return "emp-list";


    }

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

① 首先在首页先设置一个超链接能够跳转到显示全部数据的页面

portal.xml

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

② 创建 emp-list.html页面

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

从请求域中获取请求参数:
${ }
内置对象:
#lists

④ 遍历数据

th:each

emp-list.html完整代码如下:

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <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>
        <th>IDth>
        <th>NAMEth>
        <th>SALARYth>
    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}">这里显示员工IDtd>
        <td th:text="${emp.empName}">这里显示员工Nametd>
        <td th:text="${emp.empSalary}">这里显示员工SALARYtd>
    tr>
    tbody>
table>


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

body>
html>

添加了一个回到首页的超链接

提出想法:
当数据很多的时候,我们适当分页并设置简单导航来使得查看数据更加便捷。

2 分页显示数据列表

SSM整合(经典自我版)_第26张图片

在这里插入图片描述

SSM整合(经典自我版)_第27张图片

注意:
这里不详细介绍,可以去相关链接查看,此处只做相关功能测试。
代码重工-分页相关知识

2.1 准备环境

① 导入依赖

在pom.xml配置文件中

 
        <dependency>
            <groupId>com.github.pagehelpergroupId>
            <artifactId>pagehelperartifactId>
            <version>5.2.0version>
        dependency>

② 在 SqlSessionFactoryBean 中配置 PageHelper 插件

 
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <props>
                            
                            <prop key="reasonable">trueprop>

                            
                            
                            <prop key="helperDialect">mysqlprop>
                        props>
                    property>
                bean>
            array>
        property>

2.2 开发功能

SSM整合(经典自我版)_第28张图片

① 在首页中添加一个超链接,需要考虑页码值传入

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

rest风格: @{/get/page/{pageNo}}
这里我们默认设置点击超链接,跳转页面显示从第一页开始。

② 在 EmpHandler 声明 handler 方法

SSM整合(经典自我版)_第29张图片

  • EmpHandler 控制层
 //显示分页数据
    @RequestMapping("/get/page/{pageNo}")
    public String getPage(
            @PathVariable("pageNo") Integer pageNo,
            Model model) {

        //1. PageInfo 对象封装了和分页相关的所有信息
        PageInfo<Emp> pageInfo = empService.getPageInfo(pageNo);

        //2.将 PageInfo 对象存入模型
        model.addAttribute("pageInfo", pageInfo);


        //3.返回页面
        return "emp-page";


    }

③在 Service 方法实现分页

在这里插入图片描述

  • EmpService接口
 PageInfo<Emp> getPageInfo(Integer pageNo);
  • EmpServiceImpl实现类
@Override
    public PageInfo<Emp> getPageInfo(Integer pageNo) {

        //1、确定每页显示数据的条数
        int pageSize = 5;

        //2、设定分页数据:开启分页功能。开启后,后面执行的 SELECT 语句会自动被附加 LIMIT 子句,
        //而且会自动查询总记录数
        PageHelper.startPage(pageNo, pageSize);

        //3、正常执行查询
        List<Emp> empList = empMapper.selectAll();

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


    }

mapper接口和mapper.xml配置文件不用配置,利用查询数据的方法,只是做了分页显示。

④ 完成页面显示

SSM整合(经典自我版)_第30张图片

创建 emp-page.html

  • 显示主体数据 pageInfo.list
<tbody th:if="${#lists.isEmpty(pageInfo.list)}">
                <tr>
                    <td colspan="4">抱歉,没有查询到任何数据!td>
                tr>
 tbody>

 <tbody th:if="${not #lists.isEmpty(pageInfo.list)}">
                <tr th:each="emp : ${pageInfo.list}">
                    <td th:text="${emp.empId}">这里显示员工IDtd>
                    <td th:text="${emp.empName}">这里显示员工Nametd>
                    <td th:text="${emp.empSalary}">这里显示员工SALARYtd>
 				tr>
 tbody>
  • 显示简单导航 pageInfo.hasPreviousPage & pageInfo.hasNextPage
  <span th:if="${pageInfo.hasPreviousPage}">
                        <a th:href="@{/get/page/1}">首页a>
                        <a th:href="@{/get/page/}+${pageInfo.prePage}">上一页a>
 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>

  • 显示导航数字 navigator : ${pageInfo.navigatepageNums}
  <span th:each="navigator : ${pageInfo.navigatepageNums}">
           
           
           <a th:if="${navigator != pageInfo.pageNum}"
              th:href="@{/get/page/}+${navigator}"
              th:text="'['+${navigator}+']'">a>
 span>

         
        <span th:if="${navigator == pageInfo.pageNum}" th:text="'['+${navigator}+']'">span>
  • 通过输入文本框跳转到指定页面

输入文本框

<tr>
 <td colspan="4">
 
 
<input id="jumpToPageNumInput"  @click="jumpToPageNumInput"    type="text" name="jumpToPageNum"    placeholder="请输入你想直接跳转的页码"/>
 td>
tr>

配套js(使用了vue)

引入vue.js

 <script type="text/javascript" th:src="@{/static/js/vue.js}">script>

编辑点击响应函数

        <script type="text/javascript">
            var vue = new Vue({
                el: "#pageTable",                // el 指定Vue对象关联的HTML元素的id
                methods: {                       //配合 v-on 声明事件响应函数
                jumpToPageNumInput:function (event) {//表示当前事件
                        //获取页码文本框的元素对象
                        var jumpToPageNum = document.getElementById("jumpToPageNumInput");
                        //给页码文本框绑定值改变响应函数
                        jumpToPageNum.onchange = function (){
                            //触发值改变响应函数后,获取当前文本框中用户输入的值
                            var targetNum = this.value;

                            //检测用户输入的数据是否是数字
                            if(isNaN(targetNum)){
                                //如果不是数字则恢复文本框
                                this.value = "";
                                //当前函数结束
                                return ;
                            }
                            
                            //如果用户输入合法,则跳转页面
                            //[[@{/get/page/}]] 表示解析 thymeleaf 表达式
                            window.location.href = "[[@{/get/page/}]]" + targetNum;
                        }
                    }
                }
            });
        </script>

3 删除操作

SSM整合(经典自我版)_第31张图片

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



     <a class="deleteA" @click="deleteEmployee"
                          th:href="@{/emp/}+${emp.empId}+'/'+${pageInfo.pageNum}">deletea>

3.2 转换请求方式:把点击超链接的 GET 请求转换为最终的 DELETE 请求

SSM整合(经典自我版)_第32张图片

① 编写超链接对应的 handler 方法

SSM整合(经典自我版)_第33张图片

  
        <form id="delete_form" method="post">
            
            <input type="hidden" name="_method" value="delete"/>
        form>

② 给每一个删除超链接绑定单击响应函数 @click

在这里插入图片描述

  1. 引入vue.js(第一种方式)
    SSM整合(经典自我版)_第34张图片
  <script type="text/javascript" th:src="@{/static/js/vue.js}">script>
  1. 配套Js
    <script type="text/javascript">
            var vue = new Vue({
                el: "#pageTable",   // el 指定Vue对象关联的HTML元素的id
                methods: { //配合 v-on 声明事件响应函数
                    deleteEmp: function (event) { //event 表示当前事件
                        //通过document对象在整个文档范围内查找对象
                        //使用var 关键字接收document.getElementById("delete_form")方法的返回值
                        var delete_form = document.getElementById("delete_form");
                        //将触发事件的超链接的href属性为表单的action属性赋值
                        delete_form.action = event.target.href;
                        //提交表单
                        delete_form.submit();
                        //阻止超链接的默认跳转行为(点击超链接,会跳转页面,这是超链接的默认行为,需取消。)
                        event.preventDefault();
                    }
                }
            });
        </script>
  1. 不使用vue(第二种方式:原生Js)

超链接





<a onclick="convertMethod(this, event)" th:href="@{/emp/}+${emp.empId}+'/'+${pageInfo.pageNum}">删除a>

配套js

<script type="text/javascript">

            function convertMethod(anchorElement, event) {

                // 获取超链接原本要访问的目标地址
                var targetURL = anchorElement.href;

                // 获取表单对象
                var delete_form = document.getElementById("delete_form");

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

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

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

        </script>

delete删除操作中可能出现的错误

③编写超链接对应的 handler 方法

SSM整合(经典自我版)_第35张图片

 @RequestMapping(value = "/emp/{empId}/{pageNo}", method = RequestMethod.DELETE)
    // @DeleteMapping("/emp/{empId}/{pageNo}")
    public String deleteEmployee(
            @PathVariable("empId") Integer empId,
            @PathVariable("pageNo") Integer pageNo) {

        // 调用 Service 方法执行删除
        empService.deleteEmployee(empId);

        // 以重定向方式回到分页页面,避免刷新浏览器重新执行删除操作
        return "redirect:/get/page/" + pageNo;
    }

④编写 handler 方法要调用的 Service 方法

  • service接口 EmpService
 void deleteEmployee(@Param("empId") Integer empId);
  • service实现类 EmpServiceImpl
  @Transactional(
            propagation = Propagation.REQUIRES_NEW, //设置事务传播行为 :当前方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起
            rollbackFor = Exception.class  //出现哪些异常可以回滚
    )
    @Override
    public void deleteEmployee(Integer empId) {

        empMapper.deleteEmployee(empId);
    }

④编写Mapper及其相关配置

  • EmpMapper
 void deleteEmployee(Integer empId);
  • EmpMapper.xml
   
    <delete id="deleteEmployee">
        delete from t_emp where emp_id = #{empId}
    delete>


4 新增操作

SSM整合(经典自我版)_第36张图片
在这里插入图片描述

SSM整合(经典自我版)_第37张图片

4.1 跳转到表单页面(emp-add.html)

SSM整合(经典自我版)_第38张图片

① 编写超链接

在表头处添加一个添加按钮

 <tr>
      <th>OPTIONS(<a th:href="@{/emp/add}">adda>)th>
 tr>

② 配置view-controller

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

③ 创建emp-add.html

SSM整合(经典自我版)_第39张图片

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    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>

4.2 提交表单

在这里插入图片描述

①handler方法

 //提交添加的表单(保存数据),默认前往最后一页显示
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    public String addEmp(){

        empService.addEmployee();


        return "redirect:/get/page/"+ Integer.MAX_VALUE;
    }

② service方法

service接口

void addEmp(Emp emp);

service实现类

 @Transactional(
            propagation = Propagation.REQUIRES_NEW, //设置事务传播行为 :当前方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起
            rollbackFor = Exception.class  //出现哪些异常可以回滚
    )
    @Override
    public void addEmp(Emp emp) {
        empMapper.addEmp(emp);
    }

③ Mapper及其配置文件

EmpMapper

 void addEmp(Emp emp);

EmpMapper.xml


    <insert id="addEmp">
        insert into t_emp(emp_name,emp_salary) values(#{empName},#{empSalary})
    insert>

5 更新操作

SSM整合(经典自我版)_第40张图片

5.1 跳转到表单页面,回显数据

SSM整合(经典自我版)_第41张图片
在这里插入图片描述
SSM整合(经典自我版)_第42张图片

① 编写超链接

<a th:href="@{/emp/}+${emp.empId}+'/'+${pageInfo.pageNum}">updatea>

② handler方法

  //更新操作一:回显数据(在表单中显示数据,相当于查询,所以是GET)
    @RequestMapping(value = "/emp/{empId}/{pageNo}",method = RequestMethod.GET)
    public String updateEmp(
            @PathVariable("empId") Integer empId,
            @PathVariable("pageNo") Integer pageNo,
            Model model){

        //1.根据 empId 查询得到用来回显表单数据的实体类对象
        Emp emp = empService.selectEmpById(empId);

        //2.存入模型中,即向域对象中共享数据,方便获取
        model.addAttribute("emp",emp);

        //3.返回表单页面修改 emp-edit ,进行修改操作
        return "emp-edit";

    }

③ service方法

  • service接口
   Emp getEmpById(Integer empId);
  • service接口实现类
 @Transactional(readOnly = true)
    @Override
    public Emp getEmpById(Integer empId) {
         return  empMapper.getEmpById(empId);

    }

④ Mapper及其配置文件

  • EmpMapper
  Emp getEmpById(Integer empId);
  • 配置文件
 
    <select id="getEmpById" resultType="Emp">
        select emp_id,emp_name,emp_salary from t_emp where emp_id = #{empId}
    select>

5.2 提交表单

SSM整合(经典自我版)_第43张图片

①创建emp-edit 页面

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
        <form th:action="@{/emp}" method="post">
            <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>

② 编写handler 方法

  //更新操作二:提交表单
    @RequestMapping(value = "/emp",method = RequestMethod.PUT)
    public String update(Emp emp,
                         /*
                         因为请求路径中没有携带pageNo(占位符中没有)
                         所以不能通过@PathVariable来给控制器方法的形参赋值,所以只能通过@RequestParam将请求参数和控制器的
                         形参创建映射关系,因此需要我们在提交表单的时候,将pageNo随表单一起提交给服务器
                         因此需要有一个隐藏域来传输pageNo
                          */
                         @RequestParam("pageNo") Integer pageNo){
        empService.update(emp);

        return "redirect:/get/page/"+pageNo;

    }

③ 编写service方法

  • service接口
  void update(Emp emp);
  • service实现类
  @Transactional(
            propagation = Propagation.REQUIRES_NEW, //设置事务传播行为 :当前方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起
            rollbackFor = Exception.class  //出现哪些异常可以回滚
    )
    @Override
    public void update(Emp emp) {

        empMapper.updateByEmpId(emp);

    }

④Mapper及其配置文件

  • EmpMapper
 void updateByEmpId(Emp emp);
  • EmpMapper.xml 编写SQL语句
 
    <update id="updateByEmpId">
        update t_emp set emp_name = #{empName},emp_Salary=#{empSalary} where emp_id = #{empId}
    update>

总结 相关知识合集

在完成此案例中可能用到的相关知识合集:

thymeleaf之获取请求参数

thymeleaf之内置对象

thymeleaf-表达式语法

代码重工-thymeleaf详解

w3school-HTML知识详解

thymeleaf的简单用法-常用标签

restful风格

restful案例

springmvc-路径中的占位符

js中的window.onload

在dom元素加载前Cannot find element

springmvc获取请求参数

代码重工-分页相关知识

model.addattribute & request.setattribute区别

thymeleaf从入门到吃灰

delete删除操作中可能出现的错误

思维导图最终版

例如:以上就是今天要讲的内容,本文仅仅简单介绍了SSM整合及其ACRUD操作的使用。

你可能感兴趣的:(SSM整合,mybatis,spring,java)