SSM整合步骤(超详细)

939 阅读4分钟

SSM整合(超详细)

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

我们整合ssm,并实现一个查询数据库里的博客,并展示在页面上的功能。

一、工具

  • idea
  • MySQL 8.0.22
  • Tomcat 9

项目结构:

image.png

二、数据库准备

  1. 创建一个存放博客的数据库表,并插入一些数据
create table blog(
	id int primary key comment '博客id',
	title varchar(100) not null comment '博客标题',
	author varchar(30) not null comment '博客作者',
	create_time varchar(50) not null comment '创建时间',
	views int(30) not null comment '浏览量'
) 

insert into blog values(1,'javaWeb教程','黑马程序员',now(),1000) 
insert into blog values(2,'安卓软件开发','周世凯,陈小龙',now(),1000) 
insert into blog values(3,'数据结构','清华大学出版社',now(),10000) 
insert into blog values(4,'人文基础与应用','毛灿月',now(),560)
insert into blog values(5,'java教程','小钱',now(),123456)
insert into blog values(6,'C语言','谭浩强',now(),10000)
insert into blog values(7,'C语言','小毛',now(),10000)

三、基本环境搭建

1. 新建一个Maven项目,并添加web的支持

image.png

image.png

2. 在pom.xml导入我们需要用到的依赖

如果我们的MySQL版本高于8.0,就需要导入高于MySQL以上的版本,否则可能会报Connections could not be acquired from the underlying database!

 <dependencies>
        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <!--        数据库连接池-->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <!--        junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        <!-- Servlet - JSP-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.1</version>
        </dependency>

        <!--spring-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

3. 在pom.xml中添加Maven资源过滤,预防资源无法导出

 <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

4. 建立基本结构和配置框架!

image.png

  • com.mq.controller
  • com.mq.dao
  • com.mq.pojo
  • com.mq.service
  • 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核心配置文件-->
<configuration>
    
  
</configuration>

  • 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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

</beans>

四、MyBatis层编写

1. 数据库配置文件 database.properties

注意: 数据库连接可能会碰到:驱动问题、SSL安全访问的问题和时区问题。 MySQL 8.0以上的版本要配置时区,serverTimezone=GMT%2B8

高版本的驱动已经由:"com.mysql.jdbc.Driver" 变为:"com.mysql.cj.jdbc.Driver"

否则会报500错误:Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Connections could not be acquired from the underlying database!

jdbc.driver=com.mysql.cj.jdbc.Driver
# mysql 8.0+,要配置时区
jdbc.url=jdbc:mysql://localhost:3306/firend_mq?useSSL=false&useUnicode=&characterEncodeing=UTF-8&serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=root

2. 使用idea连接数据库

image.png

image.png 如果连接失败检查是不是没有配置时区。

3. 编写实体类

在pojo包下创建Blog实体类,使用lombok插件要导入依赖。

package com.mq.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
    private int id;
    private String title;
    private String author;
    private String create_time;
    private int views;
}

4. 编写dao层接口和Mapper.xml

如果只是单纯整合,那么不用写接口,我这里为了测试。

  1. 在dao包下创建BlogMapper接口
package com.mq.dao;

import com.mq.pojo.Blog;

import java.util.List;

public interface BlogMapper {

    //查询所有的博客
    List<Blog> queryAllBLog();
}

  1. 编写BlogMapper对应的mapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.mq.dao.BlogMapper">
<!--查询全部Blog-->
        <select id="queryAllBLog" resultType="Blog">
                select * from firend_mq.blog
        </select>
</mapper>

5. 编写MyBatis的核心配置文件

我们把配置数据源的步骤交给spring去做。

关于Mybatis的配置详情可以看MyBatis的配置详解

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--        configuration核心配置文件-->
<configuration>

    <!--配置数据源,交给spring做-->

<!--扫描pojo包下的实体类,并取别名-->
    <typeAliases>
        <package name="com.mq.pojo"/>
    </typeAliases>

<!--注册mapper-->
    <mappers>
        <mapper class="com.mq.dao.BlogMapper"/>
    </mappers>
</configuration>

6. 编写Service层的接口和实现类

接口:

package com.mq.service;

import com.mq.pojo.Blog;

import java.util.List;

public interface BlogService {
    //查询所有的博客
    List<Blog> queryAllBLog();
}

实现类:

package com.mq.service;

import com.mq.dao.BlogMapper;
import com.mq.pojo.Blog;

import java.util.List;

public class BlogServiceImpl implements BlogService{

    //调用dao层的操作,设置一个set接口,方便Spring管理
    private BlogMapper blogMapper;

    public BlogServiceImpl(BlogMapper blogMapper) {
        this.blogMapper = blogMapper;
    }

    
    @Override
    public List<Blog> queryAllBLog() {
        return blogMapper.queryAllBLog();
    }

    public void setBlogMapper(BlogMapper blogMapper) {
    }
}

五、Spring层编写

这里我们将spring编写拆成三个配置的编写,每一个相当于整合两种。方便理解。 在这里插入图片描述

1.spring-dao.xml

Spring整合Mybatis的相关的配置文件,主要就是我们以前在mybatis-config.xml需要配置数据源的工作,现在交给spring去做了,以及获取到SqlSessionFactory对象等全部由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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
    <!-- 1.关联数据库文件 -->
    <context:property-placeholder location="classpath:database.properties"/>

    <!-- 2.数据库连接池 -->
    <!--数据库连接池
        dbcp  半自动化操作  不能自动连接
        c3p0  自动化操作(自动的加载配置文件 并且设置到对象里面)
    -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 配置连接池属性 -->
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!-- c3p0连接池的私有属性 -->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!-- 关闭连接后不自动commit -->
        <property name="autoCommitOnClose" value="false"/>
        <!-- 获取连接超时时间 -->
        <property name="checkoutTimeout" value="10000"/>
        <!-- 当获取连接失败重试次数 -->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>

    <!-- 3.配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    <!-- 4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 -->
    <!--解释 :https://www.cnblogs.com/jpfss/p/7799806.html-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- 给出需要扫描Dao接口包 -->
        <property name="basePackage" value="com.mq.dao"/>
    </bean>
</beans>

2. spring-service.xml

编写spring Ioc的依赖注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 扫描service相关的bean -->
    <context:component-scan base-package="com.mq.service" />

    <!--BlogServiceImpl注入到IOC容器中-->
    <bean id="BlogServiceImpl" class="com.mq.service.BlogServiceImpl">
        <property name="blogMapper" ref="blogMapper"/>
    </bean>
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 注入数据库连接池 -->
    <property name="dataSource" ref="dataSource" />
    </bean>
</beans>

六、SpringMVC层编写

1. spring-mvc.xml

主要编写注册视图解析器 :InternalResourceViewResolver 注解驱动。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!-- 注解驱动-->
    <mvc:annotation-driven/>
<!--静态资源过滤-->
    <mvc:default-servlet-handler/>
<!-- 扫描包-->
    <context:component-scan base-package="com.mq.controller"/>

<!--视图解析器-->
    <!-- 配置jsp 显示ViewResolver视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

2. 编写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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <import resource="spring-mvc.xml"/>
    <import resource="spring-dao.xml"/>
    <import resource="spring-service.xml"/>
</beans>

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">
    <!--DispatcherServlet-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!--一定要注意:我们这里加载的是总的配置文件,之前被这里坑了!-->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.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>

    <!--encodingFilter过滤器-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encodeing</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--session过期时间-->
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>
</web-app>

到这里我们的整合就已经结束了!

我们来测试一下

七、测试

1. 在controller新建BlogController类测试

package com.mq.controller;

import com.mq.pojo.Blog;
import com.mq.service.BlogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping("/blog")
public class BlogController {

    @Autowired
    @Qualifier("BlogServiceImpl")
    private BlogService service;

    @RequestMapping("/allblog")
    public String alllist(Model model){
        List<Blog> blogs = service.queryAllBLog();
        model.addAttribute("blog",blogs);
        return "allblog";
    }
}

2. 编写视图层

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: hp
  Date: 2021/5/21
  Time: 13:18
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
    <style type="text/css">
      a {
        text-decoration: none;
     color: black;
        font-size: 18px;
      }
      h3 {
        width: 180px;
        height: 38px;
        margin: 100px auto;
        text-align: center;
        line-height: 38px;
       background: deepskyblue;
        border-radius: 4px;
        }
      </style>
  </head>
  <body>
  <h3>
    <a href="${pageContext.request.contextPath}/blog/allblog">进入博客页面</a>
  </h3>
  </body>
</html>

allblog.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: hp
  Date: 2021/5/21
  Time: 14:28
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <!-- 引入 Bootstrap -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

    <title>博客展示</title>
</head>
<body>
<div class="container">
    <div class="row clearfix">
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small>博客列表 </small>
                </h1>
            </div>
        </div>
    </div>
  
    <div class="row clearfix">
        <div class="col-md-12 column">
            <table class="table table-hover table-striped">
                <thead>
                <tr>
                    <th>博客编号</th>
                    <th>博客标题</th>
                    <th>博客作者</th>
                    <th>博客创建时间</th>
                    <th>博客浏览量</th>
                </tr>
                </thead>
                <tbody>
                    <c:forEach var="blog" items="${blog}">
                        <tr>
                            <td>${blog.id}</td>
                            <td>${blog.title}</td>
                            <td>${blog.author}</td>
                            <td>${blog.create_time}</td>
                            <td>${blog.views}</td>
                        </tr>
                    </c:forEach>
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

  1. 运行结果:

image.png

image.png

到这里我们的整合并且测试已经完成了!

完美收工!

写在最后

如果有误,欢迎大佬指出,不胜感激。

💌 低级的欲望通过放纵就可获得,高级的欲望通过困自律方可获得,顶级的欲望通过煎熬才可获得

一个心怀浪漫宇宙,也珍惜人间日常的码农

6ed39a100413ca58ab65d70d5165d65.jpg