SpringMVC/Spring/MyBatis框架的整合与综合实例

1、框架介绍

1.1 SpringMVC框架

SpringMVC是一款基于MVC架构模式的轻量级Web框架,其目的是将Web开发模块化,对整体架构进行解耦,简化Web开发流程。SpringMVC基于请求驱动,即使用请求一响应模型。由于SpringMVC遵循MVC架构规范,因此分层开发数据模型层(Model)、响应视图层(View)和控制器层(Controller),可以让开发者设计出结构规整的Web层。

1.2 Spring框架

Spring的出现改变了Java世界。它的目标是使现有的JavaEE技术更易用和促进良好的编程习惯。它是一个轻量级的框架,渗透了JavaEE技术的方方面面。它主要作为依赖注入容器和AOP实现存在。还提供了声明事务、对DAO层的支持等简化开发的功能。Spring还可以很方便地与Struts、Hibernate、MyBatis等技术集成。

1.3 MyBatis框架

MyBatis是Apache的一个Java开源项目,是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解来配置和映射原生信息,将接口和Java的POJO(Plain Ordinary Java Object,普通的Java对象)映射成数据库中的记录。MyBatis的特点是,采用配置文件动态管理SQL语句,并含有输入映射、输出映射机制以及数据库连接池配置的持久层框架。

2、导入相关框架包

使用Maven进行项目的构建,pom.xml文件的配置如下:

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <spring.version>5.2.3.RELEASE</spring.version>
  <logging.log4j.version>2.13.0</logging.log4j.version>
  <dbcp.pool.version>2.7.0</dbcp.pool.version>
  <jackson.version>2.10.2</jackson.version>
</properties>

<dependencies>
  <!-- servlet-api -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
  </dependency>

  <!-- Spring框架 -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <!-- SpringMVC框架 -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <!-- MyBatis框架 -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.4</version>
  </dependency>
  <!-- MyBatis与Spring整合 -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.3</version>
  </dependency>

  <!-- MySQL的JDBC数据库驱动 -->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.17</version>
  </dependency>

  <!-- DBCP数据库连接池 -->
  <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>${dbcp.pool.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>${dbcp.pool.version}</version>
  </dependency>

  <!-- Log4j2日志记录框架 -->
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>${logging.log4j.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>${logging.log4j.version}</version>
  </dependency>

  <!-- JUnit5单元测试框架 -->
  <dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <version>1.6.0</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.6.0</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.6.0</version>
    <scope>test</scope>
  </dependency>

  <!-- JSTL标签库 -->
  <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
  </dependency>
  <dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>jstl-impl</artifactId>
    <version>1.2</version>
  </dependency>
  <dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
  </dependency>

  <!-- jackson依赖 -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${jackson.version}</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${jackson.version}</version>
  </dependency>

  <!-- 文件的上传 -->
  <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
  </dependency>
  <dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
  </dependency>
</dependencies>

3、构建项目结构

如何使用IDEA与Maven创建JavaWeb项目并部署Tomcat服务:

请点击浏览本博客的文章:《使用IDEA和Maven创建JavaWeb项目并部署Tomcat服务》

创建JavaWeb项目,并构建项目结构,如下图:

(1)项目结构

在项目的src/main/java目录中,创建如下目录与文件:

说明 类型 创建类/接口
com.pjb.ssm.entity 实体层 UserInfo.java
com.pjb.ssm.dao 数据库访问接口层 接口 UserDao.java
com.pjb.ssm.service 业务逻辑接口层 接口 UserService.java
com.pjb.ssm.service.impl 业务逻辑接口层 UserServiceImpl.java
com.pjb.ssm.model 模型层 UserModel.java
com.pjb.ssm.util 公共方法层 UtilHelper.java
com.pjb.ssm.controller 控制器层 UserController.java

(2) 配置文件

在src/main/resources资源目录中,创建如下目录与文件:

文件名称 说明
log4j2.xml Log4j2日志记录框架的配置文件。
db.properties 数据库连接属性文件。
mybatis/mybatis-config.xml MyBatis全局配置文件。
spring/applicationContext.xml Spring核心配置文件。
spring/spring-mvc.xml SpringMVC配置文件。
spring/spring-mybatis.xml Spring与MyBatis整合配置文件。
mapping/UserMapper.xml MyBatis与数据对象的Mapper映射文件。

3.1 实体层(Entity层)

在com.pjb.ssm.entity包中,创建UserInfo.java(用户信息持久化类)。

UserInfo.java(用户信息实体类)代码如下:

package com.pjb.ssm.entity;

/**
 * 用户信息实体类
 * @author pan_junbiao
 **/
public class UserInfo
{
    private int userId; //用户编号
    private String userName; //用户姓名
    private String blogUrl; //博客地址
    private int sex; //性别(1:男;2:女;)
    private String provinceName; //省份
    private String hobby; //兴趣爱好
    private String remark; //备注

    public int getUserId()
    {
        return userId;
    }

    public void setUserId(int userId)
    {
        this.userId = userId;
    }

    public String getUserName()
    {
        return userName;
    }

    public void setUserName(String userName)
    {
        this.userName = userName;
    }

    public String getBlogUrl()
    {
        return blogUrl;
    }

    public void setBlogUrl(String blogUrl)
    {
        this.blogUrl = blogUrl;
    }

    public int getSex()
    {
        return sex;
    }

    public void setSex(int sex)
    {
        this.sex = sex;
    }

    public String getProvinceName()
    {
        return provinceName;
    }

    public void setProvinceName(String provinceName)
    {
        this.provinceName = provinceName;
    }

    public String getHobby()
    {
        return hobby;
    }

    public void setHobby(String hobby)
    {
        this.hobby = hobby;
    }

    public String getRemark()
    {
        return remark;
    }

    public void setRemark(String remark)
    {
        this.remark = remark;
    }
}

3.2 数据库访问层(Dao层)

在项目的数据库访问层中使用MyBatis动态代理

(1)在配置文件目录(/resources/mapping目录)中创建SQL配置文件UserMapper.xml,注意其中namespace中的路径为即将创建的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.pjb.ssm.dao.UserDao">
    <!-- 查询用户 -->
    <select id="getUserById" parameterType="int" resultType="userInfo">
        SELECT * FROM tb_user WHERE user_id = #{userId}
    </select>

    <!-- 新增用户 -->
    <insert id="addUser" parameterType="userInfo">
        INSERT INTO tb_user(user_name,blog_url,sex,province_name,hobby,remark)
        VALUES(#{userName},#{blogUrl},#{sex},#{provinceName},#{hobby},#{remark});
    </insert>

    <!-- 修改用户 -->
    <update id="updateUser" parameterType="userInfo">
        UPDATE tb_user SET user_name=#{userName},blog_url=#{blogUrl},sex=#{sex},province_name=#{provinceName},hobby=#{hobby},remark=#{remark}
        WHERE user_id = #{userId}
    </update>

    <!-- 删除用户 -->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        DELETE FROM tb_user WHERE user_id = #{userId}
    </delete>
</mapper>

(2)编写Mapper代理接口,在com.pjb.ssm.dao包中,创建UserDao.java(用户信息数据库访问接口)。

package com.pjb.ssm.dao;

import com.pjb.ssm.entity.UserInfo;

/**
 * 用户信息数据库访问接口
 * @author pan_junbiao
 **/
public interface UserDao
{
    /**
     * 查询用户
     */
    public UserInfo getUserById(int userId);

    /**
     * 新增用户
     */
    public int addUser(UserInfo userInfo);

    /**
     * 修改用户
     */
    public int updateUser(UserInfo userInfo);

    /**
     * 删除用户
     */
    public int deleteUser(int userId);
}

3.3 业务逻辑层Service层)

(1)在com.pjb.ssm.service包中,创建UserService.java(用户信息业务逻辑接口)。

package com.pjb.ssm.service;

import com.pjb.ssm.entity.UserInfo;

/**
 * 用户信息业务逻辑接口
 * @author pan_junbiao
 **/
public interface UserService
{
    /**
     * 查询用户
     */
    public UserInfo getUserById(int userId);

    /**
     * 新增用户
     */
    public int addUser(UserInfo userInfo);

    /**
     * 修改用户
     */
    public int updateUser(UserInfo userInfo);

    /**
     * 删除用户
     */
    public int deleteUser(int userId);
}

(2)在com.pjb.ssm.service.impl包中,创建UserServiceImpl.java(用户信息业务逻辑类),该类实现UserService接口。

package com.pjb.ssm.service.impl;

import com.pjb.ssm.dao.UserDao;
import com.pjb.ssm.entity.UserInfo;
import com.pjb.ssm.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 用户信息业务逻辑类
 * @author pan_junbiao
 **/
@Service
public class UserServiceImpl implements UserService
{
    @Autowired
    private UserDao userDao;

    /**
     * 查询用户
     */
    public UserInfo getUserById(int userId)
    {
        return userDao.getUserById(userId);
    }

    /**
     * 新增用户
     */
    public int addUser(UserInfo userInfo)
    {
        return userDao.addUser(userInfo);
    }

    /**
     * 修改用户
     */
    public int updateUser(UserInfo userInfo)
    {
        return userDao.updateUser(userInfo);
    }

    /**
     * 删除用户
     */
    public int deleteUser(int userId)
    {
        return userDao.deleteUser(userId);
    }
}

3.4 公共方法层(Util层)

在com.pjb.ssm.util包中,创建UtilHelper.java(公共处理类)。

package com.pjb.ssm.util;

/**
 * 公共处理类
 * @author pan_junbiao
 */
public class UtilHelper
{
    /**
     * 将数组转换成为字符串
     *
     * @param arr    字符串数组
     * @param symbol 连接符号
     * @return 字符串
     */
    public static String arrToStr(String[] arr, String symbol)
    {
        // 实例化StringBuffer
        StringBuffer sb = new StringBuffer();
        // 判断arr是否为有效数组
        if (arr != null && arr.length > 0)
        {
            // 遍历数组
            for (String s : arr)
            {
                // 将字符串追加到StringBuffer中
                sb.append(s);
                // 将字符串追加到StringBuffer中
                sb.append(symbol);
            }
            // 判断字符串长度是否有效
            if (sb.length() > 0)
            {
                // 截取字符
                sb = sb.deleteCharAt(sb.length() - 1);
            }
        }
        // 返回字符串
        return sb.toString();
    }
}

3.5 模型层(Model层)

在com.pjb.ssm.model包中,创建UserModel.java(用户信息模型类)。

package com.pjb.ssm.model;

/**
 * 用户信息模型类
 * @author pan_junbiao
 **/
public class UserModel
{
    private int userId; //用户编号
    private String userName; //用户姓名
    private String blogUrl; //博客地址
    private int sex; //性别(1:男;2:女;)
    private String provinceName; //省份
    private String hobbyStr; //兴趣爱好(字符串)
    private String[] hobbyArray; //兴趣爱好(数组)
    private String remark; //备注

    public int getUserId()
    {
        return userId;
    }

    public void setUserId(int userId)
    {
        this.userId = userId;
    }

    public String getUserName()
    {
        return userName;
    }

    public void setUserName(String userName)
    {
        this.userName = userName;
    }

    public String getBlogUrl()
    {
        return blogUrl;
    }

    public void setBlogUrl(String blogUrl)
    {
        this.blogUrl = blogUrl;
    }

    public int getSex()
    {
        return sex;
    }

    public void setSex(int sex)
    {
        this.sex = sex;
    }

    public String getProvinceName()
    {
        return provinceName;
    }

    public void setProvinceName(String provinceName)
    {
        this.provinceName = provinceName;
    }

    public String getHobbyStr()
    {
        return hobbyStr;
    }

    public void setHobbyStr(String hobbyStr)
    {
        this.hobbyStr = hobbyStr;
    }

    public String[] getHobbyArray()
    {
        return hobbyArray;
    }

    public void setHobbyArray(String[] hobbyArray)
    {
        this.hobbyArray = hobbyArray;
    }

    public String getRemark()
    {
        return remark;
    }

    public void setRemark(String remark)
    {
        this.remark = remark;
    }
}

3.6 控制器层(Controller层)

在com.pjb.ssm.controller包中,创建UserController.java(用户信息控制器)。

package com.pjb.ssm.controller;

import com.pjb.ssm.entity.UserInfo;
import com.pjb.ssm.model.UserModel;
import com.pjb.ssm.service.UserService;
import com.pjb.ssm.util.UtilHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

/**
 * 用户信息控制器
 * @author pan_junbiao
 **/
@Controller
@RequestMapping("user")
public class UserController
{
    @Autowired
    private UserService userService;

    /**
     * 用户注册页面
     */
    @RequestMapping("toUserRegisterView")
    public String toUserRegisterView()
    {
        return "/user_register.jsp";
    }

    /**
     * 新增用户
     */
    @RequestMapping("addUser")
    public ModelAndView addUser(UserModel userModel)
    {
        ModelAndView modelAndView = new ModelAndView();

        //参数验证
        if (userModel.getUserName() == null || userModel.getUserName().equals(""))
        {
            modelAndView.addObject("message","参数错误");
            modelAndView.setViewName("/error.jsp");
            return modelAndView;
        }

        //将Model对象转换为实体对象
        UserInfo userInfo = new UserInfo();
        userInfo.setUserName(userModel.getUserName());
        userInfo.setBlogUrl(userModel.getBlogUrl());
        userInfo.setSex(userModel.getSex());
        userInfo.setProvinceName(userModel.getProvinceName());
        userInfo.setHobby(UtilHelper.arrToStr(userModel.getHobbyArray(), ";"));
        userInfo.setRemark(userModel.getRemark());

        //调用业务逻辑层方法,执行新增操作
        int resultExecute = userService.addUser(userInfo);

        //返回结果页面
        if(resultExecute>0)
        {
            modelAndView.addObject("message","新增用户成功");
            modelAndView.setViewName("/success.jsp");
        }
        else
        {
            modelAndView.addObject("message","新增用户失败");
            modelAndView.setViewName("/error.jsp");
        }
        return modelAndView;
    }

    /**
     * 用户详情页面
     */
    @RequestMapping("toUserDetailView")
    public ModelAndView toUserDetailView(@RequestParam(value="user_id",defaultValue="0") int userId)
    {
        ModelAndView modelAndView = new ModelAndView();

        //获取用户信息
        UserInfo userInfo = userService.getUserById(userId);
        if(userInfo==null)
        {
            modelAndView.addObject("message","未找到用户信息");
            modelAndView.setViewName("/error.jsp");
            return modelAndView;
        }

        //用户实体对象转换为Model对象
        UserModel userModel = new UserModel();
        userModel.setUserId(userInfo.getUserId());
        userModel.setUserName(userInfo.getUserName());
        userModel.setBlogUrl(userInfo.getBlogUrl());
        userModel.setSex(userInfo.getSex());
        userModel.setProvinceName(userInfo.getProvinceName());
        userModel.setHobbyStr(userInfo.getHobby());
        userModel.setRemark(userInfo.getRemark());

        //返回结果
        modelAndView.addObject("userModel",userModel);
        modelAndView.setViewName("/user_detail.jsp");
        return modelAndView;
    }
}

4、项目配置文件

4.1 log4j2.xml 配置文件

在资源目录(resources目录)中,创建名称为 log4j2.xml 的配置文件,用于配置Log4j2日志功能,具体配置信息如下:

<?xml version="1.0" encoding="UTF-8"?>
<!-- log4j2 配置文件 -->
<!-- 日志级别 trace<debug<info<warn<error<fatal -->
<configuration status="debug">
    <!-- 自定义属性 -->
    <Properties>
        <!-- 日志格式(控制台) -->
        <Property name="pattern1">[%-5p] %d %c - %m%n</Property>
        <!-- 日志格式(文件) -->
        <Property name="pattern2">
            ==========================%n 日志级别:%p%n 日志时间:%d%n 所属类名:%c%n 所属线程:%t%n 日志信息:%m%n
        </Property>
        <!-- 日志文件路径 -->
        <Property name="filePath">logs/myLog.log</Property>
    </Properties>

    <appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${pattern1}"/>
        </Console>
        <RollingFile name="RollingFile" fileName="${filePath}"
                     filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout pattern="${pattern2}"/>
            <SizeBasedTriggeringPolicy size="5 MB"/>
        </RollingFile>
    </appenders>
    <loggers>
        <root level="debug">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFile"/>
        </root>
    </loggers>
</configuration>

4.2 db.properties属性文件

在资源目录(resources目录)中,创建db.properties数据库连接配置文件,配置包含数据库的驱动,数据库的连接地址,登录名、登录密码、数据库连接池信息。具体配置信息如下:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_admin?useSSL=false&amp
jdbc.username=root
jdbc.password=123456
dbcp.pool.maxTotal=10
dbcp.pool.maxIdle=5

4.3 MyBatis配置

创建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>
        <!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!-- 开启自动驼峰命名规则(camel case)映射 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- 开启延时加载开关 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 将积极加载改为消极加载(即按需加载),默认值就是false -->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!-- 打开全局缓存开关(二级环境),默认值就是true -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 开启自动驼峰命名规则(camel case)映射 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!-- 别名定义 -->
    <typeAliases>
        <package name="com.pjb.fms.entity"/>
    </typeAliases>
</configuration>

4.4 Spring配置

4.4.1 Spring核心配置文件(applicationContext.xml)

创建applicationContext.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: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-3.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-3.0.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    <!-- 该配置文件暂时为空 -->
</beans>

4.4.2 Spring与MyBatis整合配置文件(spring-mybatis.xml)

创建spring-mybatis.xml配置文件,在其中加载数据库连接配置文件“db.properties”中的数据,建立数据源,配置sqlSessionFactory会话工厂对象,具体配置信息如下:

<?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-3.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-3.0.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <!-- 1.加载用于数据库配置的属性文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
    <!-- 2.包扫描:entity,dao,service -->
    <context:component-scan base-package="com.pjb.ssm.entity,com.pjb.ssm.dao,com.pjb.ssm.service"/>
    <!-- 3.dataSource数据源,使用DBCP数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <!-- 数据库驱动名称 -->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <!-- 数据库连接底座 -->
        <property name="url" value="${jdbc.url}"/>
        <!-- 登录数据库的用户名 -->
        <property name="username" value="${jdbc.username}"/>
        <!-- 登录数据库的密码 -->
        <property name="password" value="${jdbc.password}"/>
        <!-- 连接池的最大数据库连接数,设置默认值0表示无限 -->
        <property name="maxTotal" value="${dbcp.pool.maxTotal:0}"/>
        <!-- 最大空闲数,即数据库连接的最大空闲时间。当超过空闲时间时,数据库连接将被标记为不可用,然后被释放,设置默认值0表示无限 -->
        <property name="maxIdle" value="${dbcp.pool.maxIdle:0}"/>
    </bean>

    <!-- 4.配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource" />
        <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" />
        <!-- 扫描entity包 使用别名 -->
        <property name="typeAliasesPackage" value="com.pjb.ssm.entity" />
        <!-- 扫描sql配置文件:mapper需要的xml文件 -->
        <property name="mapperLocations" value="classpath:mapping/*.xml" />
    </bean>

    <!-- 5.事务管理 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="all*" propagation="REQUIRED"/>
            <tx:method name="*" read-only="true"/>
        </tx:attributes>
    </tx:advice>
    <!-- 配置事务的代理 -->
    <aop:config>
        <!-- 定义一个切面 -->
        <aop:pointcut id="allManagerMethod" expression="execution(* com.pjb.ssm.service.impl.*.*(..))"/>
        <!-- 将事务通知与切面组合 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod"/>
    </aop:config>

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

4.4.3 SpringMVC配置文件(spring-mvc.xml)

创建spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
       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-3.0.xsd
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-3.0.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <!-- 配置SpringMVC -->
    <!-- 1.开启SpringMVC注解模式(设置注解映射器、注解适配器) -->
    <mvc:annotation-driven />

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

    <!-- 3.内部资源视图解析器,prefix为空,方便跟参数url?id=xxx -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages"/>
        <property name="suffix" value=""/>
    </bean>

    <!-- 4.使用扫描配置,对某一个包下的所有类进行扫描,找出所有使用@Controller注解的Handler控制器类 -->
    <context:component-scan base-package="com.pjb.ssm.controller"></context:component-scan>

    <!-- 多类型文件解析器、文件上传 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置上传文件的最大尺寸为1MB -->
        <property name="maxUploadSize" value="1048576"/>
    </bean>
</beans>

4.5 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">
  <!--  自定义Spring主配置文件的位置 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/*.xml</param-value>
  </context-param>
  <!-- 使用ContextLoaderListener初始化Spring容器 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- SpringMVC前端控制器 -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-mvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.action</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>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!-- 默认页面 -->
  <welcome-file-list>
    <welcome-file>/index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

5、综合实例

【实例】使用SSM框架,实现用户信息的增删改查操作。

Web层和Test层的项目结构如下:

在MySQL数据库中创建 tb_user(用户信息数据表),脚本如下:

-- 判断数据表是否存在,存在则删除
DROP TABLE IF EXISTS tb_user;
 
-- 创建“用户信息”数据表
CREATE TABLE IF NOT EXISTS tb_user
( 
	user_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户编号',
	user_name VARCHAR(50) NOT NULL COMMENT '用户姓名',
	blog_url VARCHAR(50) NOT NULL COMMENT '博客地址',
	sex CHAR(2) DEFAULT '2' COMMENT '性别(1:男;2:女;)',
	province_name VARCHAR(20) COMMENT '省份',
	hobby VARCHAR(50) COMMENT '兴趣爱好',
	remark VARCHAR(50) COMMENT '备注'
) COMMENT = '用户信息表';

5.1 新增用户信息

执行结果如下:

(1)首页:

(2)用户注册页面:

(3)操作成功页面

程序代码:

(1)在UserController.java(用户信息控制器类)中编写进入用户注册页面和执行新增用户操作的方法。

@Autowired
private UserService userService;

/**
 * 用户注册页面
 */
@RequestMapping("toUserRegisterView")
public String toUserRegisterView()
{
    return "/user_register.jsp";
}

/**
 * 新增用户
 */
@RequestMapping("addUser")
public ModelAndView addUser(UserModel userModel)
{
    ModelAndView modelAndView = new ModelAndView();

    //参数验证
    if (userModel.getUserName() == null || userModel.getUserName().equals(""))
    {
        modelAndView.addObject("message","参数错误");
        modelAndView.setViewName("/error.jsp");
        return modelAndView;
    }

    //将Model对象转换为实体对象
    UserInfo userInfo = new UserInfo();
    userInfo.setUserName(userModel.getUserName());
    userInfo.setBlogUrl(userModel.getBlogUrl());
    userInfo.setSex(userModel.getSex());
    userInfo.setProvinceName(userModel.getProvinceName());
    userInfo.setHobby(UtilHelper.arrToStr(userModel.getHobbyArray(), ";"));
    userInfo.setRemark(userModel.getRemark());

    //调用业务逻辑层方法,执行新增操作
    int resultExecute = userService.addUser(userInfo);

    //返回结果页面
    if(resultExecute>0)
    {
        modelAndView.addObject("message","新增用户成功");
        modelAndView.setViewName("/success.jsp");
    }
    else
    {
        modelAndView.addObject("message","新增用户失败");
        modelAndView.setViewName("/error.jsp");
    }
    return modelAndView;
}

(2)创建 index.jsp(首页)。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页</title>
    <meta name="author" content="pan_junbiao的博客">
</head>
<body>
<h1>首页</h1>
<a href="user/toUserRegisterView.action">用户注册</a></br>
<a href="user/toUserDetailView.action?user_id=1">用户详情</a>
</body>
</html>

(3)创建 user_register.jsp(用户注册页面)。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户注册</title>
    <meta name="author" content="pan_junbiao的博客">
</head>
<body>
<style>
    table{border-top: 1px solid #000000; border-left: 1px solid #000000; border-collapse: collapse;}
    th, td{border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 5px 10px;}
    select{width: 100px; padding: 3px;}
    .txtBox{padding: 3px;width: 300px;font-size: 16px;}
</style>
<form action="${pageContext.request.contextPath}/user/addUser.action" method="post" name="myForm">
    <table align="center">
        <caption>用户注册</caption>
        <tr>
            <th>用户姓名:</th>
            <td>
                <input class="txtBox" type="text" name="userName" value="pan_junbiao的博客"/>
            </td>
        </tr>
        <tr>
            <th>博客地址:</th>
            <td>
                <input class="txtBox" type="text" name="blogUrl" value="https://blog.csdn.net/pan_junbiao"/>
            </td>
        </tr>
        <tr>
            <th>性别:</th>
            <td>
                <input id="male" name="sex" type="radio" value="1" checked="checked"/>
                <label for="male">男</label>
                <input id="female" name="sex" type="radio" value="2"/>
                <label for="female">女</label>
            </td>
        </tr>
        <tr>
            <th>省份:</th>
            <td>
                <select name="provinceName">
                    <option value="">请选择</option>
                    <option value="广东省">广东省</option>
                    <option value="江苏省">江苏省</option>
                    <option value="安徽省">安徽省</option>
                </select>
            </td>
        </tr>
        <tr>
            <th>兴趣爱好:</th>
            <td>
                <input id="lq" name="hobbyArray" type="checkbox" value="篮球">
                <label for="lq">篮球</label>
                <input id="zq" name="hobbyArray" type="checkbox" value="足球">
                <label for="zq">足球</label>
                <input id="ymq" name="hobbyArray" type="checkbox" value="羽毛球">
                <label for="ymq">羽毛球</label>
                <input id="ppq" name="hobbyArray" type="checkbox" value="乒乓球">
                <label for="ppq">乒乓球</label>
                <input id="yy" name="hobbyArray" type="checkbox" value="游泳">
                <label for="yy">游泳</label>
            </td>
        </tr>
        <tr>
            <th>备注信息:</th>
            <td>
                <input class="txtBox" type="text" name="remark" value="您好,欢迎访问 pan_junbiao的博客"/>
            </td>
        </tr>
        <!-- 以下是提交、取消按钮 -->
        <tr>
            <td colspan="2" style="text-align: center; padding: 5px;">
                <input type="submit" value="提交" />
                <input type="reset" value="重置" />
            </td>
        </tr>
    </table>
</form>
</body>
</html>

(4)创建 success.jsp(操作成功页面)。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>操作成功</title>
    <meta name="author" content="pan_junbiao的博客">
</head>
<body>
<h1>恭喜,操作成功!</h1>
<span style="color:red"><%=request.getAttribute("message") == null ? "" : request.getAttribute("message")%></span>
</body>
</html>

(5)创建 error.jsp(操作失败页面)。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>操作失败</title>
    <meta name="author" content="pan_junbiao的博客">
</head>
<body>
<h1>对不起,操作失败!</h1>
<span style="color:red"><%=request.getAttribute("message") == null ? "" : request.getAttribute("message")%></span>
</body>
</html>

5.2 获取用户信息

执行结果如下:

程序代码:

(1)在UserController.java(用户信息控制器类)中编写获取用户信息的方法。

/**
 * 用户详情页面
 */
@RequestMapping("toUserDetailView")
public ModelAndView toUserDetailView(@RequestParam(value="user_id",defaultValue="0") int userId)
{
    ModelAndView modelAndView = new ModelAndView();

    //获取用户信息
    UserInfo userInfo = userService.getUserById(userId);
    if(userInfo==null)
    {
        modelAndView.addObject("message","未找到用户信息");
        modelAndView.setViewName("/error.jsp");
        return modelAndView;
    }

    //用户实体对象转换为Model对象
    UserModel userModel = new UserModel();
    userModel.setUserId(userInfo.getUserId());
    userModel.setUserName(userInfo.getUserName());
    userModel.setBlogUrl(userInfo.getBlogUrl());
    userModel.setSex(userInfo.getSex());
    userModel.setProvinceName(userInfo.getProvinceName());
    userModel.setHobbyStr(userInfo.getHobby());
    userModel.setRemark(userInfo.getRemark());

    //返回结果
    modelAndView.addObject("userModel",userModel);
    modelAndView.setViewName("/user_detail.jsp");
    return modelAndView;
}

(2)创建 user_detail.jsp(用户详情页面)。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户详情</title>
    <meta name="author" content="pan_junbiao的博客">
    <style>
        table { border-collapse: collapse;}
        table,table tr th, table tr td { border:1px solid #000000; padding: 5px 10px;}
    </style>
</head>
<body>

<body>
<table align="center">
    <caption>用户信息</caption>
    <tr>
        <th>用户编号</th>
        <td>${userModel.userId}</td>
    </tr>
    <tr>
        <th>用户姓名</th>
        <td>${userModel.userName}</td>
    </tr>
    <tr>
        <th>博客地址</th>
        <td>${userModel.blogUrl}</td>
    </tr>
    <tr>
        <th>性别</th>
        <td>${userModel.sex==1?"男":"女"}</td>
    </tr>
    <tr>
        <th>省份</th>
        <td>${userModel.provinceName}</td>
    </tr>
    <tr>
        <th>兴趣爱好</th>
        <td>${userModel.hobbyStr}</td>
    </tr>
    <tr>
        <th>备注信息</th>
        <td>${userModel.remark}</td>
    </tr>
</table>
</body>
</body>
</html>

5.3 修改用户和删除用户

执行修改用户和删除用户操作,使用Junit5框架进行测试,在com.pjb.ssm.test包中,创建UserTest.java(用户业务测试类)。

package com.pjb.ssm.test;

import com.pjb.ssm.entity.UserInfo;
import com.pjb.ssm.service.UserService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 用户业务测试类
 * @author pan_junbiao
 **/
public class UserTest
{
    private ApplicationContext applicationContext;
    private UserService userService;

    @Before
    public void setUp() throws Exception
    {
        //初始化Spring容器(上下文对象)
        applicationContext = new ClassPathXmlApplicationContext("classpath:spring/spring-mybatis.xml");
        //获取Bean对象
        userService = (UserService) applicationContext.getBean("userServiceImpl");
    }

    @After
    public void tearDown() throws Exception
    {
        System.out.println("测试完成!");
    }

    /**
     * 修改用户
     */
    @Test
    public void updateUser()
    {
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(1);
        userInfo.setUserName("pan_junbiao的博客");
        userInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao");
        userInfo.setSex(2);
        userInfo.setProvinceName("广东省");
        userInfo.setHobby("篮球;足球;羽毛球;乒乓球;游泳");
        userInfo.setRemark("您好,欢迎访问 pan_junbiao的博客");
        //调用业务逻辑层方法,执行修改操作
        int result = userService.updateUser(userInfo);

        //打印结果
        if(result>0)
        {
            System.out.println("修改成功");
        }
        else
        {
            System.out.println("修改失败");
        }
    }

    /**
     * 删除用户
     */
    @Test
    public void deleteUser()
    {
        //调用业务逻辑层方法,执行删除操作
        int result = userService.deleteUser(1);

        //打印结果
        if(result>0)
        {
            System.out.println("删除成功");
        }
        else
        {
            System.out.println("删除失败");
        }
    }
}

5.4 日志功能

测试Log4j2日志记录功能,在com.pjb.ssm.test包中,创建LogTest.java(日志功能测试类)。

package com.pjb.ssm.test;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * 日志功能测试类
 * @author pan_junbiao
 **/
public class LogTest
{
    Logger logger = LogManager.getLogger(LogTest.class);

    @Before
    public void setUp() throws Exception
    {
        logger.info("测试开始@Before");
    }

    @After
    public void tearDown() throws Exception
    {
        logger.info("测试结束@After");
    }

    @Test
    public void writeLogInfo()
    {
        logger.trace("trace level");
        logger.debug("debug level");
        logger.info("info level");
        logger.warn("warn level");
        logger.error("error level");
        logger.fatal("fatal level");
    }
}

执行结果:

发布了377 篇原创文章 · 获赞 278 · 访问量 180万+

猜你喜欢

转载自blog.csdn.net/pan_junbiao/article/details/104511047