0


基于SSM框架的项目:图书管理系统

目录:

1 总体要求

总体任务:整合 SpringMVC + Spring + MyBatis 框架,实现书城项目的增删改查以及检索功能。

网站架构依然采用前端 JSP + 控制层 Controller + 业务层 Service + 持久层 Dao + 数据库的形式。

其中:

  • 数据库由 MySQL 管理;
  • MyBatis 作为 持久层用来操作数据库;
  • SpringMVC 作为控制层与前端就行数据交互;
  • Spring 作为大杂烩托管持久层、业务层和控制层;
  • 前端页面使用了 Bootstrap 这个 JavaScript 框架进行编写。

采用自底向上的设计流程,具体步骤如下:

  1. 数据库表的创建;
  2. 基本环境搭建;
  3. Mybatis 层编写;
  4. Spring 层编写;
  5. SpringMVC 层编写;
  6. 逻辑功能的编写。

1.1 演示视频

点击:传送门


2 数据库的创建

# 其中 `ssmbook` 为该项目数据库的名称,`book` 为对应的表名CREATEDATABASEIFNOTEXISTS`ssmbook`;USE`ssmbook`;CREATETABLEIFNOTEXISTS`book`(`bookId`INT(10)NOTNULLPRIMARYKEYAUTO_INCREMENTCOMMENT'书id',`bookName`VARCHAR(100)NOTNULLCOMMENT'书名',`bookCount`INT(11)NOTNULLCOMMENT'数量',`detail`VARCHAR(200)NOTNULLCOMMENT'描述')ENGINE=INNODBDEFAULTCHARSET=utf8;USE`ssmbook`;INSERTINTO`book`(`bookName`,`bookCount`,`detail`)VALUES('人生',8,'作者为路遥,描述了一个人在人生各处的选择'),('高效能人士的七个习惯',10,'作者为史蒂芬,描述了普通人所需要的七个习惯'),('剑指 Offer ',9,'用来刷题');

3 基本环境搭建

1 新建一个 Maven 普通项目,并将该项目添加 Web 支持。

2 导入相关的 Maven 依赖,对应的 pom.xml 文件为:

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>sharm</groupId><artifactId>ssmbuild</artifactId><version>1.0-SNAPSHOT</version><!-- 经过实践证明,这段代码确实是必须要写的 --><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.encoding>UTF-8</maven.compiler.encoding><java.version>11</java.version><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties><!-- 导入依赖 --><dependencies><!--Junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><!--数据库驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!-- 数据库连接池 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</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.2</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.2</version></dependency><!--Spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.9.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.1.9.RELEASE</version></dependency></dependencies><!-- 静态资源导出 --><build><resources><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources></build></project>

3 建立基本结构和配置框架

请添加图片描述


4 Mybatis 层编写

该部分主要编写底层业务逻辑。

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

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbook?useUnicode=true&characterEncoding=utf8&useSSL=false
jdbc.username=root
jdbc.password=123456

2 编写数据库对应的实体类:sharm.pojo.Book

packagesharm.pojo;publicclassBook{publicint bookId;publicString bookName;publicint bookCount;publicString detail;// 省略无参和有参构造方法// 省略各个属性的 getter 和 setter 方法// 省略 toString 方法的重写}

3 编写 Dao 层的 Mapper 接口:sharm.dao.BookMapper

packagesharm.dao;importorg.apache.ibatis.annotations.Param;importsharm.pojo.Book;importjava.util.List;/**
 * 接口约束的是方法
 */publicinterfaceBookMapper{// 增加一本书publicintaddBook(Book book);// 根据 id 删除一本书// 好奇怪,明明对应的 sql 语句是不返回内容的,为什么还可以接收到 int 型的 1,难怪 SQL 语句执行成功会返回 1publicintdeleteBookById(int id);// 更新书publicintupdateBook(Book book);// 根据 id,返回一本书publicBookqueryBookById(int id);// 查询全部的书List<Book>queryAllBook();// 根据书籍名进行检索// 可能存在同名书籍,所以这里使用 List 进行接收// 可以在接口上加上 @Param 注解,这样出错的概率会小很多List<Book>queryBookByName(@Param("bookName")String name);}

4 编写该接口对用的 mapper.xml 文件:sharm.dao.BookMapper.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--关于 MyBatis 的配置文件和针对于接口的配置文件,只需要将 config 改为 mapper 即可。--><mappernamespace="sharm.dao.BookMapper"><!--增加一个Book--><insertid="addBook"parameterType="book">
        INSERT INTO ssmbook.book(bookName, bookCount, detail)
        VALUES(#{bookName}, #{bookCount}, #{detail})
    </insert><!--根据id删除一个Book--><deleteid="deleteBookById"parameterType="int">
        DELETE FROM ssmbook.book WHERE bookId=#{bookId}
    </delete><!--更新Book--><updateid="updateBook"parameterType="book">
        UPDATE ssmbook.book
        SET bookName = #{bookName}, bookCount = #{bookCount}, detail = #{detail}
        WHERE bookId = #{bookId}
    </update><!-- 根据id查询,返回一个 Book --><selectid="queryBookById"resultType="book">
        SELECT * FROM ssmbook.book
        WHERE bookId = #{bookId}
    </select><!-- 查询全部Book --><selectid="queryAllBook"resultType="book">
        SELECT * FROM ssmbook.book
    </select><!-- 根据书籍名查询 Book --><selectid="queryBookByName"parameterType="String"resultType="book">
        SELECT * FROM ssmbook.book WHERE bookName = #{bookName}
    </select></mapper>

5 编写 MyBatis 的核心配置文件:resources/mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 增加 MyBatis 日志 --><settings><!-- 没想到 name 属性的值必须是 logImpl,否则就找不到  --><settingname="logImpl"value="STDOUT_LOGGING"/></settings><!-- 取别名,此时,pojo 下的类名可以用首字母小写代替 --><typeAliases><packagename="sharm.pojo"/></typeAliases><mappers><mapperresource="sharm/dao/BookMapper.xml"/></mappers></configuration>

6 编写 Service 层的接口:sharm.service.BookService

packagesharm.service;importsharm.pojo.Book;importjava.util.List;publicinterfaceBookService{//增加一个BookintaddBook(Book book);//根据id删除一个BookintdeleteBookById(int id);//更新BookintupdateBook(Book book);//根据id查询,返回一个BookBookqueryBookById(int id);//查询全部Book,返回list集合List<Book>queryAllBook();// 根据书籍名进行检索List<Book>queryBookByName(String name);}

7 编写 Service 层的实现类:sharm.service.BookServiceImp

packagesharm.service;importsharm.dao.BookMapper;importsharm.pojo.Book;importjava.util.List;publicclassBookServiceImpimplementsBookService{//1. 一般来说 Dao 与 Service 的内容是相似的,只不过业务层可以在 Dao 层上增加一些其它的操作,类似于开闭原则;//2. 所以说是只将 Dao 层修改为 xml 形式,service 层还是接口加实现类的形式。// 调用 dao 层的操作,设置一个 set 接口,方便 Spring 管理privateBookMapper bookMapper;publicvoidsetBookMapper(BookMapper bookMapper){this.bookMapper = bookMapper;}@OverridepublicintaddBook(Book book){return bookMapper.addBook(book);}@OverridepublicintdeleteBookById(int id){return bookMapper.deleteBookById(id);}@OverridepublicintupdateBook(Book book){return bookMapper.updateBook(book);}@OverridepublicBookqueryBookById(int id){return bookMapper.queryBookById(id);}@OverridepublicList<Book>queryAllBook(){return bookMapper.queryAllBook();}@OverridepublicList<Book>queryBookByName(String name){return bookMapper.queryBookByName(name);}}

5 Spring 层编写

Spring 在这里主要起到一个整合的作用。

Spring 接管 Dao 和 Service 层,同时 MyBatis 的一些配置文件,也可以在 Spring 中配置。

1 利用 Spring 整合 MyBatis 的配置文件:resources/spring-dao.xml

利用 Spring 整合 MyBatis,其中包括了原本需要在 MyBatis 配置文件中配置的数据库参数和 SqlSessionFactory对象;

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:util="http://www.springframework.org/schema/util"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/util https://www.springframework.org/schema/util/spring-util.xsd"><!-- 配置整合mybatis --><!-- 1.关联数据库文件 --><context:property-placeholderlocation="classpath:database.properties"/><!-- 2.数据库连接池 --><!-- 数据库连接池有很多,当然也可以用 Spring 自带的,下面两种也比较常用:
        dbcp 半自动化操作 不能自动连接
        c3p0 自动化操作(自动的加载配置文件 并且设置到对象里面)
        这里我们选择 c3p0。
    --><beanid="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource"><!-- 数据库连接池中核心的四个属性肯定是不变的  --><propertyname="driverClass"value="${jdbc.driver}"/><propertyname="jdbcUrl"value="${jdbc.url}"/><propertyname="user"value="${jdbc.username}"/><propertyname="password"value="${jdbc.password}"/><!-- 那下面就是 c3p0 自己私有的属性,也可以不加 --><!-- c3p0连接池的私有属性 --><propertyname="initialPoolSize"value="10"/><propertyname="maxPoolSize"value="30"/><propertyname="minPoolSize"value="10"/><!-- 关闭连接后不自动commit --><propertyname="autoCommitOnClose"value="false"/><!-- 获取连接超时时间 --><propertyname="checkoutTimeout"value="10000"/><!-- 当获取连接失败重试次数 --><propertyname="acquireRetryAttempts"value="2"/></bean><!-- 3.配置SqlSessionFactory对象 --><beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean"><!-- ref是引用(指针),value是 boolean、string等,用 ref 还是 value,需要看源码里这个 name 是什么类型的 --><!-- 注入数据库连接池 --><propertyname="dataSource"ref="dataSource"/><!-- 配置 MyBatis 全局配置文件:mybatis-config.xml --><propertyname="configLocation"value="classpath:mybatis-config.xml"/></bean><!-- 4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 --><beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer"><!-- 注入sqlSessionFactory --><propertyname="sqlSessionFactoryBeanName"value="sqlSessionFactory"/><!-- 给出需要扫描Dao接口包 --><propertyname="basePackage"value="sharm.dao"/></bean></beans>

2 利用 Spring 整合 service 层:resources/spring-service.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context.xsd"><!-- 1.扫描 service 下的 bean --><context:component-scanbase-package="sharm.service"/><!-- 2.将我们所有的业务类,注入到 Spring 中,可以通过配置实现,也可以通过注解实现,这里我们通过配置实现 --><beanid="bookServiceImp"class="sharm.service.BookServiceImp"><propertyname="bookMapper"ref="bookMapper"/></bean><!-- 3.声明式事务配置 --><beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 所以说 Spring 的事务支持,底层还是通过 SQL 实现的--><!-- 注入数据源 --><propertyname="dataSource"ref="dataSource"/></bean><!-- 4.设置 AOP 横切事务支持 --></beans>

6 SpringMVC 层编写

6.1 配置文件的书写

1 Web 项目的 web.xml 配置

<?xml version="1.0" encoding="UTF-8"?><web-appxmlns="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"><!-- 1.DispatchServlet 的配置 --><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 还需要配置一些初始参数,比如总的 xml 配置文件 --><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><!-- 2. 乱码过滤 --><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><!-- 3.Session过期时间 --><session-config><session-timeout>15</session-timeout></session-config></web-app>

2 SpringMVC 的配置文件:resources/spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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.自动扫描包,让指定包下的注解生效,由IOC容器统一管理 --><context:component-scanbase-package="sharm.controller"/><!-- 2.让 Spring MVC 不处理 html、css 等静态资源,防止资源占用 --><mvc:default-servlet-handler/><!-- 3.支持mvc注解驱动,这样就不需要写处理器映射器和处理器适配器,
         而 annotation-driven 配置帮助我们自动完成上述两个实例的注入。--><mvc:annotation-driven/><!-- 4.配置 jsp 显 示ViewResolver 视图解析器 --><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/><propertyname="prefix"value="/WEB-INF/jsp/"/><propertyname="suffix"value=".jsp"/></bean></beans>

3 Spring配置整合文件:resources/applicationContext.xml

将所有配置文件都注册在同一个 ApplicationContext 下。

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

6.2 逻辑功能的编写

当上述代码编写完后,接下来我们只需要关心前端页面与后端控制器之间的逻辑操作即可。

6.2.1 首页编写

文件路径:

web/index.jsp
<%@ page contentType="text/html; charset=UTF-8" isELIgnored="false" language="java" %>
<html><head><title>首页</title><styletype="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>
    <%-- 配置了 Tomcat 服务器后就会自动补全了 --%>
    <ahref="${pageContext.request.contextPath}/book/allBook">进入书籍页面</a></h3></body></html>

6.2.2 逻辑功能的实现

1 显示全部书籍的前端文件:web/WEB-INF/jsp/allBook.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>书籍列表</title><metaname="viewport"content="width=device-width, initial-scale=1.0"><!-- 引入 Bootstrap 框架的 cdn --><linkhref="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"rel="stylesheet"></head><body><divclass="container"><divclass="row clearfix"><divclass="col-md-12 column"><divclass="page-header"><h1><small>书籍列表 —— 显示所有书籍</small></h1></div></div></div><divclass="row"><divclass="col-md-4 column"><aclass="btn btn-primary"href="${pageContext.request.contextPath}/book/toAddBook">新增书籍</a><aclass="btn btn-primary"href="${pageContext.request.contextPath}/book/allBook">显示全部书籍</a></div><divclass="col-md-8 column"><formclass="form-inline"action="${pageContext.request.contextPath}/book/queryBookByName"method="post"style="float:right">
                <%-- span 标签就是用来接收传回前端的错误信息 --%>
                <spanstyle="color:red;font-weight: bold">${error}</span><inputtype="text"name="bookName"class="form-control"placeholder="请输入要查询的书籍的名称"><inputtype="submit"value="查询"class="btn btn-primary"></form></div></div><divclass="row clearfix"><divclass="col-md-12 column"><tableclass="table table-hover table-striped"><thead><tr><th>书籍编号</th><th>书籍名字</th><th>书籍数量</th><th>书籍详情</th><th>操作</th></tr></thead><tbody>
                <%-- requestScope 是 EL 表达式获取到的 request 域中的数据 --%>
                <c:forEachvar="book"items="${requestScope.get('books')}"><tr>
                        <%-- setter 方法要和实体类中的 setter 方法一致 --%>
                        <td>${book.getBookId()}</td><td>${book.getBookName()}</td><td>${book.getBookCount()}</td><td>${book.getDetail()}</td><td><ahref="${pageContext.request.contextPath}/book/toUpdateBook?id=${book.getBookId()}">更改</a>
                            |
                            <ahref="${pageContext.request.contextPath}/book/deleteBook?id=${book.getBookId()}">删除</a>
<%--                            <ahref="#">更改</a> |--%>
<%--                            <ahref="#">删除</a>--%>
                        </td></tr></c:forEach></tbody></table></div></div></div>

2 增加书籍功能的前端文件:web/WEB-INF/jsp/addBook.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html><head><title>新增书籍</title><metaname="viewport"content="width=device-width, initial-scale=1.0"><!-- 引入 Bootstrap --><linkhref="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"rel="stylesheet"><!-- 原来还必须引入 JQuery 这个 js 的库 --><scriptsrc="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script><scripttype="text/javascript">// 页面加载完成之后$(function(){$("#sub_btn").click(function(){// 正则表达式参考:https://zhuanlan.zhihu.com/p/83080230var bookNameText =$("#bookName").val();// 只能为汉字var bookNamePatt =/^[\u4e00-\u9fa5]{0,}$/;if(!bookNamePatt.test(bookNameText)){$("span.errorMsg").text("书籍名不合法,必须为汉字!");returnfalse;}var bookCountText =$("#bookCount").val();// 非负整数var bookCountPatt =/^[1-9]\d*|0$/;if(!bookCountPatt.test(bookCountText)){$("span.errorMsg").text("书籍数量不合法,必须为非负整数!");returnfalse;}// 去掉错误信息$("span.errorMsg").text("");});})</script></head><body><divclass="container"><divclass="row clearfix"><divclass="col-md-12 column"><divclass="page-header"><h1><small>新增书籍</small></h1><spanclass="errorMsg"style="color:red;font-weight: bold">
                    ${ requestScope.msg }
                </span></div></div></div><formaction="${pageContext.request.contextPath}/book/addBook"method="post">
        书籍名称:<inputtype="text"name="bookName"id="bookName"required><br><br><br>
        书籍数量:<inputtype="text"name="bookCount"id="bookCount"required><br><br><br>
        书籍详情:<inputtype="text"name="detail"id="detail"required><br><br><br><inputtype="submit"value="添加"id="sub_btn"></form></div>

3 更新书籍功能的前端文件:web/WEB-INF/jsp/updateBook.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@ page contentType="text/html;charset=UTF-8" language="java"%><html><head><title>修改信息</title><meta name="viewport" content="width=device-width, initial-scale=1.0"><!-- 引入 Bootstrap--><link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"></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><form action="${pageContext.request.contextPath}/book/updateBook" method="post"><%-- 只有在表单提交时在隐藏域中增加 bookId 信息,保存到数据库的时候才不会出错 --%><%-- 不能使用 ${book.bookId()} 来获得数据,因为 bookId 是私有变量  --%><input type="hidden" name="bookId" value="${book.getBookId()}"/>
        书籍名称:<input type="text" name="bookName" value="${book.getBookName()}"/>
        书籍数量:<input type="text" name="bookCount" value="${book.getBookCount()}"/>
        书籍详情:<input type="text" name="detail" value="${book.getDetail() }"/><input type="submit" value="提交"/></form></div>

4 后端控制器对应的逻辑为:sharm.controller.BookController

packagesharm.controller;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Qualifier;importorg.springframework.stereotype.Controller;importorg.springframework.ui.Model;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importsharm.pojo.Book;importsharm.service.BookService;importjava.util.List;@Controller@RequestMapping("/book")publicclassBookController{// Controller 层调用 Service 层@Autowired// 这里实现类要和 spring-service.xml 配置的内容对应@Qualifier("bookServiceImp")privateBookService bookService;// 1.查询全部的数据,并且返回一个书籍展示页面@RequestMapping("/allBook")publicStringlist(Model model){List<Book> books = bookService.queryAllBook();
        model.addAttribute("books", books);return"allBook";}// 2.添加书籍// 2.1 跳转到添加书籍页面:web-inf下的文件不能直接访问,因此需要跳转@RequestMapping("/toAddBook")publicStringtoAddPaper(){// 转发,用的还是 /toAddBook 这个 urlreturn"addBook";}// 上面这个 "addBook" 的 url 是 http://localhost:8080/ssmbuild_war_exploded/addBook// 下面这个 "addBook" 的 url 是 http://localhost:8080/ssmbuild_war_exploded/book/addBook// 2.2 修改页面@RequestMapping("/addBook")publicStringaddPaper(Book book){
        bookService.addBook(book);return"redirect:allBook";}// 3.修改书籍// 3.1 跳转到修改书籍页面@RequestMapping("/toUpdateBook")publicStringtoUpdateBook(Model model,int id){Book book = bookService.queryBookById(id);
        model.addAttribute("book", book);return"updateBook";}@RequestMapping("/updateBook")publicStringupdateBook(Book book){System.out.println(book);int i = bookService.updateBook(book);if(i ==1){System.out.println("修改数据成功");}return"redirect:allBook";}// 4.删除数据// 4.1 跳转到修改书籍页面@RequestMapping("/deleteBook")publicStringdeleteBook(int id){int i = bookService.deleteBookById(id);if(i ==1){System.out.println("删除成功。");}return"redirect:allBook";}// 5.根据书籍名检索信息(拓展功能)@RequestMapping("/queryBookByName")// 如果需要将数据往下传的话,需要来一个 modelpublicStringqueryBookByName(@RequestParam("bookName")String name,Model model){// 由于是新增的功能,且没有使用切面编程,因此需要自底向上进行编写List<Book> books = bookService.queryBookByName(name);assert books !=null;if(books.isEmpty()){System.out.println("未查到,未查到,未查到");
            model.addAttribute("error","未查到该书籍");}else{
            model.addAttribute("books", books);}return"allBook";}}

6.2.3 修改书籍功能实现的流程

由于代码部分增删改查的代码糅合在一起了,因此专门拿出修改书籍功能的实现来介绍前后端联调的流程

  1. allBook 页面点击修改时,首先转到控制器的 /book/toUpdateBook 页面,同时将对应的 Id 也上传上去;
  2. 该方法将对应的书籍保存到 model 域中,并且将页面转发给 /updateBook,由于是转发,所以浏览器显示的 url 是 /book/toUpdateBook;
  3. updateBook 页面根据域中的信息显示书籍;用户根据这些原始数据来修改,并且再次提交表单给控制器的 /book/updateBook;
  4. 该方法对数据库进行操作,并且重定向到 /allBook 页面进行显示;

6.2.4 查询书籍的测试代码

当前端页面无法显示书籍列表时,通过后端测试来排除错误。

importorg.junit.Test;importorg.springframework.context.support.ClassPathXmlApplicationContext;importsharm.pojo.Book;importsharm.service.BookService;publicclassMyTest{@Testpublicvoidtest1(){// 对配置文件建立一个对象// 查询书籍ClassPathXmlApplicationContext context =newClassPathXmlApplicationContext("applicationContext.xml");BookService bookServiceImp =(BookService) context.getBean("bookServiceImp");for(Book books : bookServiceImp.queryAllBook()){System.out.println(books);}}}

6.3 该项目全部文件的位置

请添加图片描述


7 遇到的问题以及拓展的功能

1 在实现增加书籍功能时,为什么不直接加载到添加数据页面,而是通过 DispatchedServlet 重定向到增加书籍页面?

因为 web-inf 下的文件不能直接访问,直接访问会造成可以在未登录状态下跳转进去修改数据库,从而造成安全问题 。

2 SQL 日志功能的实现

在 resources/mybatis-config.xml 中加入如下配置即可实现:

<!-- 增加 MyBatis 日志 --><settings><!-- 没想到 name 属性的值必须是 logImpl,否则就找不到  --><settingname="logImpl"value="STDOUT_LOGGING"/></settings>

3 数据库字段名和实体类属性名的映射问题

当实体类的属性为 bookCount,数据库表中的字段名为 bookCounts 时,尽管在 BookMapper.xml 中的语句为:

<!--更新Book--><updateid="updateBook"parameterType="book">
    UPDATE ssmbook.book
    SET bookName = #{bookName}, bookCounts = #{bookCount}, detail = #{detail}
    WHERE bookId = #{bookId}
</update>

其中:

bookCounts = #{bookCount}

,然而在实际使用中无法修改数据库对应字段的值,且不会报错!!!

将两者的名称设置相同,即解决。

4 为什么在 Maven 的配置文件中需要将静态资源导出的代码也写进去

标准的 Maven 项目都会有一个 resources 目录来存放我们所有的资源配置文件,但是我们往往在项目中不仅仅会把所有的资源配置文件都放在resources中,同时我们也有可能放在项目中的其他位置,比如说在使用MyBatis 框架时,往往会将 mapper.xml 与dao 接口一起放在 dao 包中,那么执行程序的时候,其中的 xml 配置文件就一定会读取失败,不会生成到 maven 的 target 目录中,所以建议是每新建一个 Maven 项目,就把静态资源到处设置进去。

5 IDEA报错:不再支持源选项 5 请使用 6 或更高版本。怎么解决

参考文献:传送门 https://cloud.tencent.com/developer/article/1587537。

其实就是在 pom.xml 中加入 java 版本的说明

6 数据库连接失败时,可能的解决办法

将数据库连接属性中的 useSSL = true 改为 false 即连接成功;

7 需要注意的地方

  1. 默认作用域确实是同包内有效,如果同个包内,那么还是可以直接使用的;
  2. 老是将代码写在 main 方法之外,导致每次都花费时间找出这个错误;
  3. 打包项目时,Artifacts 中的 lib 目录又忘记添加了。

8 项目源码

传送门


本文转载自: https://blog.csdn.net/weixin_44262126/article/details/121337478
版权归原作者 是志明呀 所有, 如有侵权,请联系我们删除。

“基于SSM框架的项目:图书管理系统”的评论:

还没有评论