来做一个ssm整合项目

1. 来整合mybatis

  1. 我们首先想到的是配置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>
    <typeAliases>
        <package name="com.pojo"/>
    </typeAliases>
</configuration>
  1. 然后我们要通过数据库字段来创建一个pojo类。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
    private int bookID;
    private String bookName;
    private int bookCounts;
    private String detail;
}

3.mybatis操作数据库我们要有一个dao层(mapper)来写对于数据库的操作,创建mapper接口以及xml文件。

public interface BookMapper {
    int addBook(Books books);
    int deleteBook(@Param("bookID") int id);
    int updateBook(Books books);
    Books queryBookById(@Param("bookID") int id);
    List<Books> queryAllBook();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.BookMapper">
    <insert id="addBook" parameterType="Books">
        insert into ssmbuild.books (bookName,bookCounts,detail)
         values (#{bookName},#{bookCounts},#{detail)};
    </insert>
    <delete id="deleteBook" parameterType="int">
        delete from ssmbuild.books where bookID = #{bookID}
    </delete>
    <update id="updateBook" parameterType="Books">
        update ssmbuild.books
         set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail)
         where bookID = #{bookID};
    </update>
    <select id="queryBookById" parameterType="int">
        select * from ssmbuild.books where bookID = #{bookID};
    </select>
    <select id="queryAllBook" parameterType="Books">
        select * from ssmbuild.books;
    </select>
</mapper>
  1. 别忘了把这个mapper放到配置文件中。
<?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>
    <typeAliases>
        <package name="com.pojo"/>
    </typeAliases>

    <mappers>
        <mapper class="com.dao.BookMapper"/>
    </mappers>
</configuration>

既然有了dao层当然少不了调用的service层,首先写一个接口

public interface BookService {
    int addBook(Books books);
    int deleteBook(int id);
    int updateBook(Books books);
    Books queryBookById(int id);
    List<Books> queryAllBook();
}

然后我们来实现它,由于我们要调用dao层这里要注入dao接口。

public class BookServiceImpl implements BookService{
    private BookMapper bookMapper;

    public void setBookMapper(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }

    public int addBook(Books books) {
        return bookMapper.addBook(books);
    }

    public int deleteBook(int id) {
        return bookMapper.deleteBook(id);
    }

    public int updateBook(Books books) {
        return bookMapper.updateBook(books);
    }

    public Books queryBookById(int id) {
        return bookMapper.queryBookById(id);
    }

    public List<Books> queryAllBook() {
        return bookMapper.queryAllBook();
    }
}

这样mybatis就整合完成。

2.整合Spring层

  1. 首先来整一个总的配置文件。application.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">


</beans>
  1. 通过分层思想来给配置文件分层,在此之前我们先给我们数据库配置文件单独提取成properties。
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc01?useSSL=false&useUnicode=true&characterEncoding=UTF8&serverTimezone=Asia/Shanghai
username=root
password=123456789

来一层层写,我们最先写的dao层就从这开始,来吧,spring-dao.xml,这层要关联数据库配置文件(一般找文件都是上下文寻找也就是context),配置数据库连接池,mybatis里的sqlsessionfactory(导入mybatis配置文件),扫描dao包并注入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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!--  关联数据库配置文件-->
    <context:property-placeholder location="classpath:database.properties"/>
<!--    数据库连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driver}"/>
        <property name="user" value="${username}"/>
        <property name="password" value="${password}"/>
        <property name="jdbcUrl" value="${url}"/>
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <property name="autoCommitOnClose" value="false"/>
        <property name="checkoutTimeout" value="10000"/>
        <property name="acquireRetryAttempts" value="2"/>
    </bean>

<!--    sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

<!--    配置dao扫描包-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--        注入sqlsessionfactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--        要扫描的dao包-->
        <property name="basePackage" value="com.dao"/>
    </bean>
</beans>
  1. dao层写完后,接下来轮到了service层,都逃不掉的是扫描包,将所有的业务类注入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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!--    扫描service下的包-->

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

<!--    将所有业务类注入到Spring-->
    <bean id="BookServiceImpl" class="com.service.BookServiceImpl">
        <property name="bookMapper" ref="bookMapper"/>
    </bean>
<!--    声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

3. 整合Springmvc层

在web.xml中配置dispatcherservlet,配置乱码过滤(开始没找到包很烦),配置session。

<?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>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:application.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
<!--    乱码过滤-->
    <filter>
        <filter-name>encodingFilter</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>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

<!--    session-->
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>
</web-app>

写mvc层的配置文件,spring-mvc.xml,这层专注于controller层的控制。配置注解驱动,静态资源过滤 ,扫描包,配置视图解析器。

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

    <!--    注解驱动-->
    <mvc:annotation-driven/>

    <!--    静态资源过滤-->
    <mvc:default-servlet-handler/>
    <!--    扫描包-->
    <context:component-scan base-package="com.controller"/>
    <!--    视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

这样的分层思想容易理解,但是我还是记不得

对了这些写完别忘了在总的配置文件中将它们导入。

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


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


</beans>

开始写业务代码

  1. 先构思需要那些部分,查询所有书籍,增加书籍,修改书籍,删除书籍,通过模糊查询查询书籍,添加分页功能
  2. 业务代码要自下而上写,所以我们要从下pojo层开始写。上面已经写过。
  3. 接下来要跟数据库交互,我们开始写dao层,由于使用了mybatis我们需要mapper.xml,由于增加模糊查询功能再贴一遍代码。
public interface BookMapper {
    int addBook(Books books);
    int deleteBookById(@Param("bookID") int id);
    int updateBook(Books books);
    Books queryBookById(@Param("bookID") int id);
    List<Books> queryAllBook();
    List<Books> queryBookByName(String name);
}
<?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.dao.BookMapper">

    <!--增加一个Book-->
    <insert id="addBook" parameterType="Books">
      insert into ssmbuild.books(bookName,bookCounts,detail)
      values (#{bookName}, #{bookCounts}, #{detail})
   </insert>

    <!--根据id删除一个Book-->
    <delete id="deleteBookById" parameterType="int">
      delete from ssmbuild.books where bookID=#{bookID}
   </delete>

    <!--更新Book-->
    <update id="updateBook" parameterType="Books">
      update ssmbuild.books
      set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail}
      where bookID = #{bookID}
   </update>

    <!--根据id查询,返回一个Book-->
    <select id="queryBookById" resultType="Books">
      select * from ssmbuild.books
      where bookID = #{bookID}
   </select>

    <!--查询全部Book-->
    <select id="queryAllBook" resultType="Books">
      SELECT * from ssmbuild.books
   </select>
    <select id="queryBookByName" resultType="Books">
        select * from ssmbuild.books where bookName like "%"#{bookName}"%";
    </select>
</mapper>
  1. dao层写完需要一个service层,这里需要调用dao层。使用set注入。
public interface BookService {
    int addBook(Books books);
    int deleteBookById(int id);
    int updateBook(Books books);
    Books queryBookById(int id);
    List<Books> queryAllBook();
    List<Books> queryBookByName(String name);
}
public class BookServiceImpl implements BookService{
    private BookMapper bookMapper;

    public void setBookMapper(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }

    public int addBook(Books books) {
        return bookMapper.addBook(books);
    }

    public int deleteBookById(int id) {
        return bookMapper.deleteBookById(id);
    }

    public int updateBook(Books books) {
        return bookMapper.updateBook(books);
    }

    public Books queryBookById(int id) {
        return bookMapper.queryBookById(id);
    }

    public List<Books> queryAllBook() {
        return bookMapper.queryAllBook();
    }

    public List<Books> queryBookByName(String name) { return  bookMapper.queryBookByName(name); }
}
  1. 我们要开始考虑再controller层数据交互。

    • 查询所有书籍:直接调用service层,查询所有书籍,将返回值添加进model中,在前端使用el表达式循环输出。(这里可以使用分页插件)
    • 添加功能:写好前端表单,由于对象字段会一一对应,我们这里参数直接写Books就行了,通过调用service层的addBook方法将接收的books存在数据库中,然后我们把页面重定向到全部书籍。
    • 修改功能:写好前端表单,从id跳转,通过value属性把修改的值全部拿出来,直接在表单中修改,通过调用service层的updateBook方法将接收的books修改数据库,然后我们把页面重定向到全部书籍。由于要实现字段对应,我们将id设为隐藏属性。
    • 删除功能:接受前端返回的id,通过调用service层的deleteBookById方法直接从数据库中删除,然后我们把页面重定向到全部书籍。
    • 模糊查询功能:接收前端传入的字段,通过调用service层的queryBookByName方法,把返回的参数带入allbook页面。
    package com.controller;
    
    
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    import com.pojo.Books;
    import com.service.BookService;
    import org.apache.ibatis.annotations.Param;
    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.*;
    
    import java.util.List;
    
    @Controller
    @RequestMapping("/book")
    public class BookController {
        @Autowired
        @Qualifier("BookServiceImpl")
        private BookService bookService;
    
        @RequestMapping("/allBook")
        public String list(Model model,@RequestParam(defaultValue = "1") Integer pageNum){
            PageHelper.startPage(pageNum,3);
            List<Books> books = bookService.queryAllBook();
            PageInfo<Books> PageInfo = new PageInfo<Books>(books);
            model.addAttribute("books",books);
            model.addAttribute("pageInfo",PageInfo);
            return "allBook";
        }
        @GetMapping("/addBook")
        public String toAddBook(){
            return "addBook";
        }
        @PostMapping("/addBook")
        public String addBook(Books books){
            bookService.addBook(books);
            return "redirect:/book/allBook";
        }
        @GetMapping("/updateBook/{bookId}")
        public String updateBook(@PathVariable("bookId") int id,Model model){
            Books books = bookService.queryBookById(id);
            model.addAttribute("QBooks",books);
            return "updateBook";
        }
        @PostMapping("/updateBook")
        public String uupdateBook(Books books){
            bookService.updateBook(books);
            return "redirect:/book/allBook";
        }
        @RequestMapping("/deleteBook/{bookId}")
        public String deleteBook(@PathVariable("bookId") int id){
            bookService.deleteBookById(id);
            return "redirect:/book/allBook";
        }
        @RequestMapping("/byBookName")
        public String queryBookByName(String bookName,Model model){
            List<Books> book = bookService.queryBookByName(bookName);
            model.addAttribute("books",book);
            return "allBook";
        }
    }
<%--
  Created by IntelliJ IDEA.
  User: quanwu
  Date: 2020/7/28
  Time: 3:44 下午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/book/allBook">点击跳转</a>
  </body>
</html>

allBook

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: quanwu
  Date: 2020/7/28
  Time: 5:14 下午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>书籍展示</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet">
</head>
<body>
<div class="ui container">
   <div class="ui  basic segments">

       <div class="ui left floated basic segment">
           <a class="ui button" href="${pageContext.request.contextPath}/book/addBook">添加书籍</a>
           <a class="ui button" href="${pageContext.request.contextPath}/book/allBook">全部书籍</a>
       </div>

        <div class="ui right floated basic segment">
            <form class="ui form" action="${pageContext.request.contextPath}/book/byBookName" method="post">
                <div class="inline fields">
                    <div class="field">
                        <input type="text" name="bookName" placeholder="(xxx)">
                        <input class="ui button" type="submit" value="查询书籍">
                    </div>
                </div>
            </form>
        </div>
    </div>


<table class="ui celled table">
    <thead>
    <tr><th>bookID</th>
        <th>bookName</th>
        <th>BookCounts</th>
        <th>detail</th>
        <th>操作</th>
    </tr></thead>
    <tbody>
        <c:forEach var="book" items="${books}">
            <tr><td>${book.bookID}</td>
                <td>${book.bookName}</td>
                <td>${book.bookCounts}</td>
                <td>${book.detail}</td>
                <td>
                    <a href="${pageContext.request.contextPath}/book/updateBook/${book.bookID}">修改</a>&nbsp;&nbsp;|&nbsp;&nbsp;
                    <a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">删除</a>
                </td>
            </tr>
        </c:forEach>

    </tbody>
</table>
    <div class="ui basic segments">
        <div class="ui right floated basic segment">
            <c:if test="${pageInfo.hasPreviousPage}">
                <a class="ui right labeled icon button" href="/book/allBook?pageNum=${pageInfo.pageNum-1}">
                    <i class="left arrow icon"></i> 上一个
                </a>
            </c:if>
            <c:if test="${pageInfo.hasNextPage}">
                <a class="ui right labeled icon button" href="/book/allBook?pageNum=${pageInfo.pageNum+1}">
                    <i class="right arrow icon"></i> Next
                </a>
            </c:if>
        </div>
        <div class="ui left floated basic segment">
            第${pageInfo.pageNum}页,共${pageInfo.pages}页,共${pageInfo.total}条记录
        </div>
    </div>
</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
</body>
</html>

addBook

<%--
  Created by IntelliJ IDEA.
  User: quanwu
  Date: 2020/7/29
  Time: 10:10 上午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>添加书籍</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet">

</head>
<body>
    <div class="ui container">

        <form class="ui form" action="${pageContext.request.contextPath}/book/addBook" method="post">
            <div class="field">
                <label>bookName</label>
                <input type="text" name="bookName" placeholder="bookName" required>
            </div>
            <div class="field">
                <label>bookCounts</label>
                <input type="text" name="bookCounts" placeholder="bookCounts" required>
            </div>
            <div class="field">
                <label>detail</label>
                <input type="text" name="detail" placeholder="detail" required>
            </div>
            <button class="ui button" type="submit">Submit</button>
        </form>
    </div>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
</body>
</html>

updatebook

<%--
  Created by IntelliJ IDEA.
  User: quanwu
  Date: 2020/7/29
  Time: 11:13 上午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>修改书籍</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet">
</head>
<body>
<div class="ui container">
    <form class="ui form" action="${pageContext.request.contextPath}/book/updateBook" method="post">
        <div class="field">
            <input type="hidden" name="bookID" value="${QBooks.bookID}">
        </div>
        <div class="field">
            <label>bookName</label>
            <input type="text" name="bookName" value="${QBooks.bookName}" required>
        </div>
        <div class="field">
            <label>bookCounts</label>
            <input type="text" name="bookCounts" value="${QBooks.bookCounts}" required>
        </div>
        <div class="field">
            <label>detail</label>
            <input type="text" name="detail" value="${QBooks.detail}" required>
        </div>
        <button class="ui button" type="submit">Submit</button>
    </form>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
</div>
</body>
</html>

来讲讲PageHelper的简单用法

public String list(Model model,@RequestParam(defaultValue = "1") Integer pageNum){
    PageHelper.startPage(pageNum,3);
    List<Books> books = bookService.queryAllBook();
    PageInfo<Books> PageInfo = new PageInfo<Books>(books);
    model.addAttribute("books",books);
    model.addAttribute("pageInfo",PageInfo);
    return "allBook";
}

@RequestParam(defaultValue = "1") Integer pageNum,这段定义一下初始的页数。

PageHelper.startPage(pageNum,3); 这段的意思是每页显示几个数据。

PageInfo<Books> PageInfo = new PageInfo<Books>(books); 我们把数据传入进去。

model.addAttribute("pageInfo",PageInfo); 将我们的数据打包发给前端。

 <div class="ui basic segments">
        <div class="ui right floated basic segment">
            <c:if test="${pageInfo.hasPreviousPage}">
                <a class="ui right labeled icon button" href="/book/allBook?pageNum=${pageInfo.pageNum-1}">
                    <i class="left arrow icon"></i> 上一个
                </a>
            </c:if>
            <c:if test="${pageInfo.hasNextPage}">
                <a class="ui right labeled icon button" href="/book/allBook?pageNum=${pageInfo.pageNum+1}">
                    <i class="right arrow icon"></i> Next
                </a>
            </c:if>
        </div>
        <div class="ui left floated basic segment">
            第${pageInfo.pageNum}页,共${pageInfo.pages}页,共${pageInfo.total}条记录
        </div>
    </div>

pageInfo.hasPreviousPage如果还有上一页就显示,否则则隐藏。
href="/book/allBook?pageNum=${pageInfo.pageNum-1}"通过参数pageNum实现分页。
下面同理。