程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Spring整合MyBatis完整示例,spring整合mybatis

Spring整合MyBatis完整示例,spring整合mybatis

編輯:JAVA綜合教程

Spring整合MyBatis完整示例,spring整合mybatis


為了梳理前面學習的內容《Spring整合MyBatis(Maven+MySQL)一》與《Spring整合MyBatis(Maven+MySQL)二》,做一個完整的示例完成一個簡單的圖書管理功能,主要使用到的技術包含Spring、MyBatis、Maven、MySQL及簡單MVC等。最後的運行效果如下所示:

 

項目結構如下:

 

一、新建一個基於Maven的Web項目

1.1、創建一個簡單的Maven項目,項目信息如下:

 1.2、修改層面信息,在項目上右鍵選擇屬性,再選擇“Project Facets”,先設置java運行環境為1.7,先去掉"Dynamic Web Module"前的勾,然後保存關閉;再打開勾選上"Dynamic Web Module",版本選擇“3.0”;這裡在左下解會出現一個超鏈接,創建“Web Content”,完成關閉。

1.3、修改項目的部署內容。項目上右鍵屬性,選擇“Deplyment Assembly”,刪除不需要發布的內容如:帶“test”的兩個目錄,WebContent目錄,再添加一個main下的webapp目錄。

修改後的結果如下所示:

1.4、修改項目內容。將WebContent下的內容復制到/src/main/webapp下,再刪除WebContent目錄,修改後的結果如下所示:

1.5、添加“服務器運行時(Server Runtime)”,添加後的結果如下:

二、創建數據庫與表

啟動MySQL,創建數據庫,新建表books,插入測試數據,完成後的表如下所示:

創建表的sql腳本如下:

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50536
Source Host           : localhost:3306
Source Database       : db1

Target Server Type    : MYSQL
Target Server Version : 50536
File Encoding         : 65001

Date: 2016-07-06 22:05:07
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `books`
-- ----------------------------
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號',
  `title` varchar(100) NOT NULL COMMENT '書名',
  `price` decimal(10,2) DEFAULT NULL COMMENT '價格',
  `publishDate` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '出版日期',
  PRIMARY KEY (`id`),
  UNIQUE KEY `title` (`title`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of books
-- ----------------------------
INSERT INTO `books` VALUES ('1', 'Java編程思想', '98.50', '2005-01-02 00:00:00');
INSERT INTO `books` VALUES ('2', 'HeadFirst設計模式', '55.70', '2010-11-09 00:00:00');
INSERT INTO `books` VALUES ('3', '第一行Android代碼', '69.90', '2015-06-23 00:00:00');
INSERT INTO `books` VALUES ('4', 'C++編程思想', '88.50', '2004-01-09 00:00:00');
INSERT INTO `books` VALUES ('5', 'HeadFirst Java', '55.70', '2013-12-17 00:00:00');
INSERT INTO `books` VALUES ('6', '瘋狂Android', '19.50', '2014-07-31 00:00:00');

需特別注意的是書名是唯一鍵。

三、添加依賴包

項目主要依賴的jar包有Spring核心包、Spring AOP包、MyBatis ORM包、MyBatis-Spring適配包、JSTL、JUnit、Log4j2等,具體的pom.xml文件如下:

<project xmlns="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>com.zhangguo</groupId>
    <artifactId>BookStore</artifactId>
    <version>0.0.1</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.3.0.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!--Spring框架核心庫 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- aspectJ AOP 織入器 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>
        <!-- Spring Web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--mybatis-spring適配器 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!--Spring java數據庫訪問包,在本例中主要用於提供數據源 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--mysql數據庫驅動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!--log4j日志包 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.6.1</version>
        </dependency>
        <!-- mybatis ORM框架 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!-- JUnit單元測試工具 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <!--c3p0 連接池 -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <!-- jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
</project>

如果是第一次依賴相關的包,則需要下載時間,請耐心等待,如果下載失敗請手動下載後復制到本地的資源庫中。依賴後的項目結果如下:

四、新建POJO實體層

為了實現與數據庫中的books表進行關系映射新建一個Book類,具體代碼如下:

package com.zhangguo.bookstore.entities;

import java.util.Date;

/**
 * 圖書實體
 */
public class Book {
    /**
     * 編號
     */
    private int id;
    /**
     * 書名
     */
    private String title;
    /**
     * 價格
     */
    private double price;
    /**
     * 出版日期
     */
    private Date publishDate;

    public Book(int id, String title, double price, Date publishDate) {
        this.id = id;
        this.title = title;
        this.price = price;
        this.publishDate = publishDate;
    }
    
    public Book() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public Date getPublishDate() {
        return publishDate;
    }

    public void setPublishDate(Date publishDate) {
        this.publishDate = publishDate;
    }
}

五、新建MyBatis SQL映射層

這個項目中我們采用接口與xml結束的形式完成關系與對象間的映射,在接口中定義一些數據訪問的方法,在xml文件中定義實現數據訪問需要的sql腳本。圖書數據訪問映射接口如下:

package com.zhangguo.bookstore.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import com.zhangguo.bookstore.entities.Book;

/**
 * 圖書數據訪問接口
 */
public interface BookDAO {
    /**
     * 獲得所有圖書
     */
    public List<Book> getAllBooks();
    /**
     * 根據圖書編號獲得圖書對象
     */
    public Book getBookById(@Param("id") int id);
    /**
     * 添加圖書
     */
    public int add(Book entity);
    /**
     * 根據圖書編號刪除圖書
     */
    public int delete(int id);
    /**
     * 更新圖書
     */
    public int update(Book entity);
}

為MyBatis ORM創建的映射文件BookMapper.xml(命名盡量都遵循一個規則,便於掃描,這裡約定以實體名+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.zhangguo.bookstore.mapper.BookDAO">
    <!--id應該是接口中的方法,結果類型如沒有配置別名則應該使用全名稱 -->
    <!--獲得所有圖書 -->
    <select id="getAllBooks" resultType="Book">
        select id,title,price,publishDate from books
    </select>
    <!--獲得圖書對象通過編號 -->
    <select id="getBookById" resultType="Book">
        select id,title,price,publishDate from books where id=#{id}
    </select>
    <!-- 增加 -->
    <insert id="add">
        insert into books(title,price,publishDate)
        values(#{title},#{price},#{publishDate})
    </insert>
    <!-- 刪除 -->
    <delete id="delete">
        delete from books where id=#{id}
    </delete>
    <!-- 更新 -->
    <update id="update">
        update books set title=#{title},price=#{price},publishDate=#{publishDate}
        where id=#{id}
    </update>
</mapper>

六、完成Spring整合MyBatis配置

6.1、在源代碼的根目錄下新建 db.properties文件,用於存放數據庫連接信息,文件內容如下:

#mysql jdbc
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8
jdbc.uid=root
jdbc.pwd=root

6.2、在源代碼的根目錄下新建 applicationContext.xml文件,用於整合MyBatis與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:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    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-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

    <!--1 引入屬性文件,在配置中占位使用 -->
    <context:property-placeholder location="classpath*:db.properties" />

    <!--2 配置C3P0數據源 -->
    <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <!--驅動類名 -->
        <property name="driverClass" value="${jdbc.driver}" />
        <!-- url -->
        <property name="jdbcUrl" value="${jdbc.url}" />
        <!-- 用戶名 -->
        <property name="user" value="${jdbc.uid}" />
        <!-- 密碼 -->
        <property name="password" value="${jdbc.pwd}" />
        <!-- 當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數  -->
        <property name="acquireIncrement" value="5"></property>
        <!-- 初始連接池大小 -->
        <property name="initialPoolSize" value="10"></property>
        <!-- 連接池中連接最小個數 -->
        <property name="minPoolSize" value="5"></property>
        <!-- 連接池中連接最大個數 -->
        <property name="maxPoolSize" value="20"></property>
    </bean>
    
    <!--3 會話工廠bean sqlSessionFactoryBean -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 數據源 -->
        <property name="dataSource" ref="datasource"></property>
        <!-- 別名 -->
        <property name="typeAliasesPackage" value="com.zhangguo.bookstore.entities"></property>
        <!-- sql映射文件路徑 -->
        <property name="mapperLocations" value="classpath*:com/zhangguo/bookstore/mapper/*Mapper.xml"></property>
    </bean>
    
    <!--4 自動掃描對象關系映射 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--指定會話工廠,如果當前上下文中只定義了一個則該屬性可省去 -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        <!-- 指定要自動掃描接口的基礎包,實現接口 -->
        <property name="basePackage" value="com.zhangguo.bookstore.mapper"></property>
    </bean>
    
    <!--5 聲明式事務管理 -->
    <!--定義事物管理器,由spring管理事務 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="datasource"></property>
    </bean>
    <!--支持注解驅動的事務管理,指定事務管理器 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!--6 容器自動掃描IOC組件  -->
    <context:component-scan base-package="com.zhangguo.bookstore"></context:component-scan>
    
    <!--7 aspectj支持自動代理實現AOP功能 -->
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>

共有7處配置,第7處配置非必要,另外關於事務管理可以選擇AOP攔截式事務管理。 

七、創建服務層

 創建BookService服務類,完成圖書管理業務,有些項目中也叫業務層,這裡我們叫服務層,具體實現如下:

package com.zhangguo.bookstore.service;

import java.util.List;
import javax.annotation.Resource;

import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zhangguo.bookstore.entities.Book;
import com.zhangguo.bookstore.mapper.BookDAO;

@Service
public class BookService{

    @Resource
    BookDAO bookdao;
    
    public List<Book> getAllBooks() {
        return bookdao.getAllBooks();
    }
    
    public Book getBookById(int id){
        return bookdao.getBookById(id);
    }
    
    public int add(Book entity) throws Exception {
        if(entity.getTitle()==null||entity.getTitle().equals("")){
            throw new Exception("書名必須不為空");
        }
        return bookdao.add(entity);
    }
    
    @Transactional
    public int add(Book entity1,Book entityBak){
        int rows=0;
        rows=bookdao.add(entity1);
        rows=bookdao.add(entityBak);
        return rows;
    }

    public int delete(int id) {
        return bookdao.delete(id);
    }
    
    /**
     * 多刪除
     */
    public int delete(String[] ids){
        int rows=0;
        for (String idStr : ids) {
            int id=Integer.parseInt(idStr);
            rows+=delete(id);
        }
        return rows;
    }

    public int update(Book entity) {
        return bookdao.update(entity);
    }

}

服務層不只是一個dao的接力棒,認為他可有可無,其實是因為我們現在的的示例中沒有涉及到更多的復雜業務,所以顯得比較空,實現開發可能有更多的業務邏輯要在這裡處理。另外給bookdao成員變量注解為自動裝配,service類注解為IOC組件。

八、JUnit測試服務類

為了確保服務類中的每個方法正確,先使用JUnit進行單元測試,測試代碼如下:

package com.zhangguo.bookstore.test;

import static org.junit.Assert.*;
import java.util.Date;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zhangguo.bookstore.entities.Book;
import com.zhangguo.bookstore.service.BookService;

public class TestBookService {

    static BookService bookservice;
    
    @BeforeClass
    public static void before(){
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        bookservice=ctx.getBean(BookService.class);
    }
    
    @Test
    public void testGetAllBooks() {
        List<Book> books=bookservice.getAllBooks();
        assertNotNull(books);
    }

    @Test
    public void testAdd() {
        Book entity=new Book(0, "Hibernate 第七版", 78.1, new Date());
        try {
            assertEquals(1, bookservice.add(entity));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testDeleteInt() {
        assertEquals(1, bookservice.delete(9));
    }

    @Test
    public void testDeleteStringArray() {
        String[] ids={"7","11","12"};
        assertEquals(3, bookservice.delete(ids));
    }

    @Test
    public void testUpdate() {
        Book entity=new Book(7, "Hibernate 第二版", 79.1, new Date());
        try {
            assertEquals(1, bookservice.update(entity));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    @Test
    public void testGetBookById()
    {
        assertNotNull(bookservice.getBookById(1));
    }
    
    @Test
    public void testAddDouble(){
        //因為書名相同,添加第二本會失敗,用於測試事務
        Book entity1=new Book(0, "Hibernate 第八版", 78.1, new Date());
        Book entity2=new Book(0, "Hibernate 第八版", 78.1, new Date());
        assertEquals(2, bookservice.add(entity1, entity2));
    }
}

所有的測試均通過,有一個想法就是能否測試完成後數據庫還原,如刪除的數據在測試後不被真正刪除。

九、加載Spring容器與獲得容器對象

9.1、修改web.xml文件,添加加載Spring容器用的監聽器,修改後的結果如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0" >
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    
    <listener>
        <description>Spring容器加載監聽器</description>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <description>設置Spring加載時的配置文件位置,默認位置在web-inf/lib下</description>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:applicationContext.xml</param-value>
    </context-param>
</web-app>

類org.springframework.web.context.ContextLoaderListener處在Spring-web.jar包中,要記得在pom.xml中添加依賴,測試是否加載成功的簡單辦法是:重新啟動tomcat查看控制信息。

9.2、為了方便獲得Spring容器實例,定義一個CtxUtil工具類,工具類的代碼如下:

package com.zhangguo.bookstore.action;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * Spring容器上下文工具類,用於獲取當前的Spring容器
 * 實現了接口ApplicationContextAware且該類被Spring管理
 *則會自動調用setApplicationContext方法獲取Spring容器對象
 */
@Component
public class CtxUtil implements ApplicationContextAware {

    public static ApplicationContext ctx;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx=applicationContext;
    }
    /**
     * 根據類型獲得bean
     */
    public static <T> T getBean(Class<T> clazz){
        return ctx.getBean(clazz);
    }
    /**
     * 根據名稱名稱獲得bean
     */
    public static Object getBean(String name){
        return ctx.getBean(name);
    }

}

十、簡單MVC控制器封裝

 為了實現一個簡單的MVC基礎控制器,定義了一個叫BaseController的Servlet,可以讓其它的Servlet繼承該Servlet獲得部分MVC功能,具體代碼如下:

package com.zhangguo.bookstore.action;

import java.io.IOException;
import java.lang.reflect.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet基類
 * 自定義控制器基類
 */
public class BaseController extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");

        // 獲得要執行的方法名
        String act = request.getParameter("act");

        // 如果用戶沒有提供方法名
        if (act == null || act.equals("")) {
            // 默認方法
            act = "execute";
        }

        // 根據方法名獲得方法信息獲得方法信息
        Method method;
        try {
            // 在對象中獲得類型信息,在類型中獲得方法通過方法名,與參數類型
            method = this.getClass().getMethod(act, HttpServletRequest.class, HttpServletResponse.class);
            // 調用方法,在當前對象中調用,傳遞參數request與response,獲得返回結果
            String targetUri = method.invoke(this, request, response) + "";
            // 如果返回的url是以redirect開始,則是重定向
            if (targetUri.startsWith("redirect:")) {
                response.sendRedirect(targetUri.substring(9, targetUri.length()));
            } else {
                // 轉發
                request.getRequestDispatcher(targetUri).forward(request, response);
            }
        } catch (Exception e) {
            response.sendError(400, e.getMessage());
            e.printStackTrace();
        }
    }

    public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.sendError(400, "請使用參數act指定您要訪問的方法");
    }
}

十一、完成圖書管理功能

11.1、定義BookController控制器

該控制器繼承BaseController,中間每一個參數為(HttpServletRequest request,HttpServletResponse response)的方法都充當一個Action,代碼如下:

package com.zhangguo.bookstore.action;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zhangguo.bookstore.entities.Book;
import com.zhangguo.bookstore.service.BookService;

@WebServlet("/BookController.do")
public class BookController extends BaseController {
    private static final long serialVersionUID = 1L;

    BookService bookservice;

    @Override
    public void init() throws ServletException {
        bookservice = CtxUtil.getBean(BookService.class);
    }

    // 圖書列表Action
    public String ListBook(HttpServletRequest request, HttpServletResponse response) {
        request.setAttribute("books", bookservice.getAllBooks());
        return "ListBook.jsp";
    }

    // 刪除圖書Action
    public String Delete(HttpServletRequest request, HttpServletResponse response) {
        int id = Integer.parseInt(request.getParameter("id"));
        request.setAttribute("message", bookservice.delete(id) > 0 ? "刪除成功!" : "刪除失敗!");
        request.setAttribute("books", bookservice.getAllBooks());
        return "ListBook.jsp";
    }

    // 多刪除圖書Action
    public String Deletes(HttpServletRequest request, HttpServletResponse response) {
        String[] ids = request.getParameterValues("ids");
        if (ids!=null&&ids.length > 0) {
            request.setAttribute("message", bookservice.delete(ids) > 0 ? "刪除成功!" : "刪除失敗!");
        } else {
            request.setAttribute("message", "請選擇刪除項!");
        }
        request.setAttribute("books", bookservice.getAllBooks());
        return "ListBook.jsp";
    }

    // 添加圖書Action
    public String AddBook(HttpServletRequest request, HttpServletResponse response) {
        return "AddBook.jsp";
    }

    // 保存添加圖書Action
    public String AddBookPost(HttpServletRequest request, HttpServletResponse response) {
        try {
            String title = request.getParameter("title");
            double price = Double.parseDouble(request.getParameter("price"));

            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date publishDate = simpleDateFormat.parse(request.getParameter("publishDate"));

            Book entity = new Book(0, title, price, publishDate);
            if (bookservice.add(entity) > 0) {
                request.setAttribute("model", new Book());
                request.setAttribute("message", "添加成功!");
            } else {
                request.setAttribute("model", entity);
                request.setAttribute("message", "添加失敗!");
            }
        } catch (Exception exp) {
            request.setAttribute("message", exp.getMessage());
            exp.printStackTrace();
        }
        return "AddBook.jsp";
    }
    
        //編輯圖書Action
        public String EditBook(HttpServletRequest request, HttpServletResponse response) {
            int id = Integer.parseInt(request.getParameter("id"));
            Book model=bookservice.getBookById(id);
            request.setAttribute("model", model);
            return "EditBook.jsp";
        }

        // 保存編輯圖書Action
        public String EditBookPost(HttpServletRequest request, HttpServletResponse response) {
            try {
                int id=Integer.parseInt(request.getParameter("id"));
                
                String title = request.getParameter("title");
                double price = Double.parseDouble(request.getParameter("price"));

                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                Date publishDate = simpleDateFormat.parse(request.getParameter("publishDate"));

                Book entity = new Book(id, title, price, publishDate);
                request.setAttribute("message", bookservice.update(entity) > 0 ? "更新成功!" : "更新失敗!");
                request.setAttribute("model", entity);
            } catch (Exception exp) {
                request.setAttribute("message", exp.getMessage());
                exp.printStackTrace();
            }
            return "EditBook.jsp";
        }

}

11.2、圖書列表與刪除

定義視圖ListBook.jsp,用於完成圖書管理,實現圖書的列表、刪除與多刪除功能,頁面腳本如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="styles/main.css" type="text/css" rel="stylesheet" />
<title>圖書管理</title>
</head>
<body>
    <div class="main">
        <h2 class="title"><span>圖書管理</span></h2>
        <form action="BookController.do?act=Deletes" method="post">
        <table border="1" width="100%" class="tab">
            <tr>
                <th><input type="checkbox" id="chbAll"></th>
                <th>編號</th>
                <th>書名</th>
                <th>價格</th>
                <th>出版日期</th>
                <th>操作</th>
            </tr>
            <c:forEach var="book" items="${books}">
                <tr>
                    <th><input type="checkbox" name="ids" value="${book.id}"></th>
                    <td>${book.id}</td>
                    <td>${book.title}</td>
                    <td>${book.price}</td>
                    <td><fmt:formatDate value="${book.publishDate}" pattern="yyyy年MM月dd日"/></td>
                    <td>
                    <a href="BookController.do?act=Delete&id=${book.id}" class="abtn">刪除</a>
                    <a href="BookController.do?act=EditBook&id=${book.id}" class="abtn">編輯</a>
                    </td>
                </tr>
            </c:forEach>
        </table>
        <p >${message}</p>
        <p>
            <a href="BookController.do?act=AddBook" class="abtn">添加</a>
            <input type="submit"  value="刪除選擇項" class="btn"/>
        </p>
    </form>
    </div>
</body>
</html>

運行時效果如下圖所示:

11.3、新增圖書功能

定義頁面AddBook.jsp完成添加圖書功能,在控制器中有兩個Action對應新增功能,一個是AddBook,完成頁面展示;另一個是AddBookPost處理保存事件,頁面腳本如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="styles/main.css" type="text/css" rel="stylesheet" />
<title>新增圖書</title>
</head>
<body>
    <div class="main">
        <h2 class="title"><span>新增圖書</span></h2>
        <form action="BookController.do?act=AddBookPost" method="post">
        <fieldset>
            <legend>圖書</legend>
            <p>
                <label for="title">圖書名稱:</label>
                <input type="text" id="title" name="title"  value="${model.title}"/>
            </p>
            <p>
                <label for="title">圖書價格:</label>
                <input type="text" id="price" name="price" value="${model.price}"/>
            </p>
            <p>
                <label for="title">出版日期:</label>
                <input type="text" id="publishDate" name="publishDate"  value="${model.publishDate}"/>
            </p>
            <p>
              <input type="submit" value="保存" class="btn">
            </p>
        </fieldset>
        </form>
        <p >${message}</p>
        <p>
            <a href="BookController.do?act=ListBook" class="abtn">返回列表</a>
        </p>
    </div>
</body>
</html>

運行成功時的狀態如下:

11.4、編輯圖書功能

定義頁面EditBook.jsp完成更新圖書功能,在控制器中有兩個Action對應更新功能,一個是EditBook,完成頁面展示與加載要編輯圖書實體的信息;另一個是EditBookPost處理保存事件,頁面腳本如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="styles/main.css" type="text/css" rel="stylesheet" />
<title>編輯圖書</title>
</head>
<body>
    <div class="main">
        <h2 class="title"><span>編輯圖書</span></h2>
        <form action="BookController.do?act=EditBookPost" method="post">
        <fieldset>
            <legend>圖書</legend>
            <p>
                <label for="title">圖書名稱:</label>
                <input type="text" id="title" name="title"  value="${model.title}"/>
            </p>
            <p>
                <label for="title">圖書價格:</label>
                <input type="text" id="price" name="price" value="${model.price}"/>
            </p>
            <p>
                <label for="title">出版日期:</label>
                <input type="text" id="publishDate" name="publishDate"  value="<fmt:formatDate value="${model.publishDate}" pattern="yyyy-MM-dd"/>"/>
            </p>
            <p>
               <input type="hidden" id="id" name="id" value="${model.id}"/>
              <input type="submit" value="保存" class="btn">
            </p>
        </fieldset>
        </form>
        <p >${message}</p>
        <p>
            <a href="BookController.do?act=ListBook" class="abtn">返回列表</a>
        </p>
    </div>
</body>
</html>

運行時的狀態如下所示:

11.5、首頁與樣式

定義index.jsp頁面,讓其轉發到指定的控制器(有點類似路由功能了),頁面代碼如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:forward page="BookController.do?act=ListBook"></jsp:forward>

定義了一個簡陋的樣式main.css,樣式表腳本如下:

 

@CHARSET "UTF-8";

* {
    margin: 0;
    padding: 0;
    font-family: microsoft yahei;
    font-size: 14px;
}

body {
    padding-top: 20px;
}

.main {
    width: 90%;
    margin: 0 auto;
    border: 1px solid #777;
    padding: 20px;
}

.main .title {
    font-size: 20px;
    font-weight: normal;
    border-bottom: 1px solid #ccc;
    margin-bottom: 15px;
    padding-bottom: 5px;
    color: blue;
}

.main .title span {
    display: inline-block;
    font-size: 20px; 
    background : blue;
    color: #fff;
    padding: 0 8px;
    background: blue;
}

a {
    color: blue;
    text-decoration: none;
}

a:hover {
    color: orangered;
}

.tab td, .tab, .tab th {
    border: 1px solid #777;
    border-collapse: collapse;
}

.tab td, .tab th {
    line-height: 26px;
    height: 26px;
    padding-left: 5px;
}

.abtn {
    display: inline-block;
    height: 20px;
    line-height: 20px;
    background: blue;
    color: #fff;
    padding: 0 5px;
}
.btn {
    height: 20px;
    line-height: 20px;
    background: blue;
    color: #fff;
    padding: 0 8px;
    border:0;
}

.abtn:hover,.btn:hover{
    background: orangered;
    color: #fff;
}
p{
    padding:5px 0;
}
fieldset{
        border: 1px solid #ccc;
        padding:5px 10px;
}
fieldset legend{
    margin-left:10px;
    font-size:16px;
}

十二、總結與示例下載

這個Demo起到了承前啟後的作用,通過該示例將前面學習過的Spring IOC、MyBatis、JSP、Servlet、Maven及Spring整合MyBatis的內容進行鞏固,也為後面學習Spring MVC作好了鋪墊。示例中隱約的實現了一些MVC的功能,這遠遠不夠,在URL的處理、表單驗證、自動映射表單等方面還可以完善,只想有一個拋磚引玉的作用就滿意了,謝謝您的閱讀,謝謝!

示例下載

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved