Java--servlet + ThreadLocal解決多線程併發問題及實例

思維導圖 – Servlet+ThreadLocal分包管理實例


一:本文思維導圖
文件結構圖


二:ThreadLocal原理圖
ThreadLocal原理圖



三:代碼:


實體層entity Book.java

package entity;

public class Book {
    /*私有屬性*/
    private int id;
    private String name;
    private String author;
    private String publisher;
    private int price;

    /*默認構造函數*/
    public Book() {
        super();
    }

    public Book(String name, String author, String publisher, int price) {
        super();
        this.name = name;
        this.author = author;
        this.publisher = publisher;
        this.price = price;
    }

    public Book(int id, String name, String author, String publisher, int price) {
        super();
        this.id = id;
        this.name = name;
        this.author = author;
        this.publisher = publisher;
        this.price = price;
    }

    /*對象屬性操作*/
    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }

    public int getPrice() {
        return price;
    }

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

數據訪問層data access object(dao)—BaseDao.java

package dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class BaseDao {
    // 數據庫驅動
    private static final String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";

    // 連接數據庫的url路徑
    private static final String url = "jdbc:sqlserver://localhost:1433;DatabaseName=MyDB";

    // 用戶名
    private static final String user = "sa";

    // 密碼
    private static final String password = "sqlpass";

    // 在靜態塊中完成驅動的加載
    // 靜態塊中的業務邏輯在類加載器加載類的時候執行
    // 只會執行一次
    static {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected Connection conn;

    protected PreparedStatement pstmt;

    protected ResultSet rs;

    // 該函數負責創建Connection對象
    protected void getConnection() {
        if (conn == null) {
            try {
                conn = DriverManager.getConnection(url, user, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    protected void getPreparedStatement(String sql) {
        if (conn == null) {
            getConnection();
        }
        try {
            pstmt = conn.prepareStatement(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // 該函數適合沒有佔位符的查詢語句
    protected void getResultSet(String sql) {
        if (pstmt == null) {
            getPreparedStatement(sql);
        }

        try {
            rs = pstmt.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    protected void close() {

        if (rs != null) {
            try {
                rs.close();
                rs = null;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (pstmt != null) {
            try {
                pstmt.close();
                pstmt = null;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
                conn = null;
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }

    }
}

dao層實例接口–IBookDao.java

package dao;

import java.util.ArrayList;

import entity.Book;

public interface IBookDao {
    public ArrayList<Book> queryBooksByPublihser(String publisher);
}

dao層接口實現 \impl\BookDaoImpl.java–

package dao.impl;

import dao.BaseDao;
import entity.Book;
import dao.IBookDao;

import java.sql.SQLException;
import java.util.ArrayList;

public class BookDaoImpl extends BaseDao implements IBookDao {
    @Override
    public ArrayList<Book> queryBooksByPublihser(String publisher) {

        ArrayList<Book> bookList = new ArrayList<Book>();
        String sql = "select * from tbook where publisher=?";
        getPreparedStatement(sql);
        try {
            pstmt.setString(1, publisher);
            rs = pstmt.executeQuery();
            /*循環讀取數據*/
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String author = rs.getString("author");
                String publisherval = rs.getString("publisher");
                int price = rs.getInt("price");

                Book book = new Book(id, name, author, publisherval, price);
                bookList.add(book);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 釋放連接資源
            close();
        }
        /*返回bookList*/
        return bookList;
    }
}

本文精華Mark:線程池 – datasource\ThreadLocalData.java

package datasource;

import dao.*;
import service.*;

public class ThreadLocalData {
    //與控制層相連,靜態對象
    public static ThreadLocal<IBookService> threadLocalBookService = new ThreadLocal<IBookService>();
    //與業務邏輯層相連,靜態對象
    public static ThreadLocal<IBookDao> threadLocalBookDao = new ThreadLocal<IBookDao>();
}

業務邏輯層service – IBookService接口

package service;

import java.util.ArrayList;

import entity.Book;

public interface IBookService {
    public ArrayList<Book> queryBooksByPublihser(String publisher);
}

本文精華Mark:業務邏輯層service – BookServiceImpl接口的實現

package service.impl;

import java.util.ArrayList;

import dao.IBookDao;
import dao.impl.BookDaoImpl;
import datasource.ThreadLocalData;

import entity.Book;

import service.IBookService;

public class BookServiceImpl implements IBookService {
    @Override
    public ArrayList<Book> queryBooksByPublihser(String publisher) {

        IBookDao bookDao;
        //在線程池中獲取key-value的鍵值,不存在新建threadLocal對象
        if (ThreadLocalData.threadLocalBookDao.get() == null) {

            bookDao = new BookDaoImpl();

            ThreadLocalData.threadLocalBookDao.set(bookDao);

        }
        //從threadLocal對象中取值
        bookDao = ThreadLocalData.threadLocalBookDao.get();
        //返回BookList列表
        return bookDao.queryBooksByPublihser(publisher);
    }

}

本文精華Mark:控制層control control\BookServlet.java

package control;

import java.awt.print.Book;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

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

import datasource.ThreadLocalData;
import service.IBookService;
import service.impl.BookServiceImpl;

@SuppressWarnings("serial")
public class BookServlet extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        /*中文編碼UTF-8*/
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        String publisher = request.getParameter("publisher");

        /*Book接口對象service*/
        IBookService bookService;
        /*如果線程池中找不到實例對象,則新建*/
        if (ThreadLocalData.threadLocalBookService.get() == null) {
            bookService = new BookServiceImpl();
            ThreadLocalData.threadLocalBookService.set(bookService);
        }
        /*從線程池中取值*/
        bookService = ThreadLocalData.threadLocalBookService.get();
        /*bookService調用queryBookByPublisher方法後返回BookList列表*/
        ArrayList<entity.Book> books = bookService.queryBooksByPublihser(publisher);
        /*綁定對象*/
        request.setAttribute("books", books);

        /*重定向*/     request.getRequestDispatcher("/result.jsp").forward(request, response);

        out.flush();
        out.close();
    }
}

result.jsp [JSTL庫]

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>My JSP 'result.jsp' starting page</title>

    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
    <style type="text/css">
        div{
            width:800px;
            height: 600px;
            margin:0 auto;
        }
    </style>
  </head>

  <body>
    <div>
        <h1>查詢結果</h1>
    <table width="600px" border="1px">
        <tr>
            <td>ID</td>
            <td>NAME</td>
            <td>AUTHOR</td>
            <td>PUBLISHER</td>
            <td>PRICE</td>
        </tr>
        <c:forEach items="${requestScope.books}" var="book">
            <tr>
                <td>${book.id}</td>
                <td>${book.name}</td>
                <td>${book.author}</td>
                <td>${book.publisher}</td>
                <td>${book.price}</td>
            </tr>
        </c:forEach>
    </table>
    </div>
  </body>
</html>

四:小結

1)服用方式:結合前篇博文一起服用,記得參考思維導圖,效果更佳;
2)有效日期:2XXX-XX-XX;
3)詳情諮詢:[email protected] 歡迎打擾;
4)版權所有:如有雷同,純屬巧合;
5)如何修改:如有更好的實現方法或者實例,請fork;
6)本人撰博純屬巧合;
7)如有不足之處,提出必改正;
8)後續內容:Ajax[異步js and xml]引擎訪問數據數內容;
9)附上層與層之間的邏輯圖[request,response],請參見下圖;
邏輯圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章