JavaEE-05 分頁與文件上傳
學習要點
- 新聞分頁顯示數據
- 新聞圖片上傳
JSP分頁顯示數據
分頁
- 數據信息較多的的時候一般采用列表顯示,方便展示信息;
- 數據量較大的時候一般采用列表加分頁的方式顯示,便於閱讀。
- 分頁方式:集合或者session、存儲過程、SQL語句分頁
分頁步驟
- 確定每頁顯示的數據數量
- 確定分頁顯示所需的總頁數
- 編寫SQL查詢語句,實現數據查詢
- 在JSP頁面中進行分頁顯示設置
- 對分頁過程中的數據進行封裝,封裝到Page類中
實現過程
- 確定每頁顯示的數據量:例如:每頁顯示5條數據
- 計算顯示的頁數:使用count()函數查詢數據庫中的記錄數;通過記錄數和每頁數據量計算總頁數,把信息封裝到Page類中。
- Page類代碼
/**分頁泛型類*/ public class Page<T> { // 總頁數 private int totalPageCount = 1; // 頁面大小,即每頁顯示記錄數 private int pageSize = 0; // 記錄總數 private int totalCount = 0; // 當前頁號 private int currPageNo = 1; // 每頁數據集合 private List<T> List; public List<T> getList() { return List; } public void setList(List<T> list) { List = list; } public int getCurrPageNo() { if (totalPageCount == 0) return 0; return currPageNo; } public void setCurrPageNo(int currPageNo) { if (this.currPageNo > 0) this.currPageNo = currPageNo; } public int getTotalPageCount() { return totalPageCount; } public void setTotalPageCount(int totalPageCount) { this.totalPageCount = totalPageCount; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { if (pageSize > 0) this.pageSize = pageSize; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { if (totalCount > 0) { this.totalCount = totalCount; // 計算總頁數 totalPageCount = this.totalCount % pageSize == 0 ? (this.totalCount / pageSize) : this.totalCount / pageSize + 1; } } }
JavaBean的概念:JavaEE項目中對數據或者業務進行封裝的簡單類。
類似於Page或者News新聞實體類。
News類實現了數據的封裝,Page類實現了業務的封裝,並且這兩個類都沒有繼承除Object類外的其他類或者實現接口,所有屬性進行了封裝,有無參構造方法。
4.設計SQL語句
MySQL分頁語句:
SELECT * FROM news ORDER BY NID ASC LIMIT (pageindex-1)*pagesize,pagesize;
5.數訪問層實現
NewsDao:
public abstract int getTotalCount(); public List<News> getPageNewsList(int pageIndex,int pageSize);
NewsDaoImpl:
/** 獲取分頁新聞信息 */ public List<News> getPgeNewsList(int pageNo, int pageSize) { List<News> newsList = new ArrayList<News>(); String sql = "select NID,NTITLE,NCREATEDATE from NEWS order by NCREATEDATE desc LIMIT ?,?"; Object[] args = { (pageNo - 1) * pageSize, pageSize }; ResultSet rs = this.executeQuery(sql, args); try { while (rs.next()) { int nId = rs.getInt("NID"); String nTitle = rs.getString("NTITLE"); Timestamp times = rs.getTimestamp("NCREATEDATE"); SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss"); String nCreateDate = sdf.format(times); // String nCreateDate = rs.getString("NCREATEDATE"); News news = new News(); news.setNid(nId); news.setNtitle(nTitle); news.setNcreatedate(nCreateDate); newsList.add(news); } } catch (Exception e) { e.printStackTrace(); } return newsList; } /**查詢總記錄數*/ public int getTotalCount() { int count = 0; Connection conn = this.getConnection(); PreparedStatement pstmt = null; ResultSet rs = null; String sql = "select count(1) from news"; try { pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); if (rs.next()) { count = rs.getInt(1); } } catch (SQLException e) { e.printStackTrace(); } finally { this.closeAll(rs, pstmt, conn); } return count; }
6.測試方法
public static void main(String[] args) { NewsDaoImpl newsDao = new NewsDaoImpl(); int totalCount = newsDao.getTotalCount(); Page<News> page = new Page<News>(); page.setCurrPageNo(3); // 設置當前頁面 page.setPageSize(3); // 設置每頁條數 page.setTotalCount(totalCount); // 設置總記錄數 System.out.println("新聞總數量是:" + page.getTotalCount()); System.out.println("每頁條數是:" + page.getPageSize()); System.out.println("總頁數:" + page.getTotalPageCount()); System.out.println("當前是第" + page.getCurrPageNo() + "頁:"); List<News> newsList = newsDao.getPgeNewsList(page.getCurrPageNo(), page.getPageSize()); page.setList(newsList);// 設置每頁顯示的集合 for (News news : page.getList()) { System.out.println(news.getNid() + "\t" + news.getNtitle() + "\t" + news.getNcreatedate()); } }
7.JSP頁面信息頁控制代碼
當前頁數:[<%=pageIndex%>/<%=totalpages%>] <% if(pageIndex > 1){ //控制頁面顯示風格 %> <a href="pageControl.jsp?pageIndex=1">首頁</a> <a href="pageControl.jsp?pageIndex=<%= pageIndex -1%>">上一頁</a> <% } if(pageIndex < totalpages){ //控制頁面顯示風格 %> <a href="pageControl.jsp?pageIndex=<%= pageIndex +1%>">下一頁</a> <a href="pageControl.jsp?pageIndex=<%=totalpages%>">末頁</a> <%}%>
8.信息處理頁參考代碼
String pageIndex = request.getParameter("pageIndex");//獲得當前頁數 if (pageIndex == null) { pageIndex = "1"; } int currPageNo = Integer.parseInt(pageIndex); NewsDaoImpl newsDao = new NewsDaoImpl(); int totalCount = newsDao.getTotalCount();//獲得總記錄數 Page<News> pages = new Page<News>(); pages.setPageSize(3); //設置每頁條數 pages.setTotalCount(totalCount); //設置總記錄數 int totalpages = pages.getTotalPageCount(); /*對首頁與末頁進行控制*/ if (currPageNo < 1) { currPageNo = 1; } else if (currPageNo > pages.getTotalPageCount()) { currPageNo = totalpages; } pages.setCurrPageNo(currPageNo); //設置當前頁面 List<News> newsList = newsDao.getPgeNewsList(pages.getCurrPageNo(), pages.getPageSize()); pages.setList(newsList); //設置每頁顯示的集合 request.setAttribute("pages", pages); request.getRequestDispatcher("index.jsp").forward(request, response);
上機練習:實現新聞分頁顯示
需求說明
編寫代碼實現首頁新聞標題的分頁顯示,要求能夠執行首頁、下一頁、上一頁、末頁的操作,並在頁面中顯示總頁數和當前頁
實現思路
- 確定每頁顯示的新聞數量
- 編寫數據庫訪問類,聲明查詢方法
- 編寫SQL語句
- 編寫JavaBean封裝分頁信息(Page類)
- 在JSP中調用JavaBean
使用Commons-FileUpload上傳文件
需求
網頁應用中,經常需要上傳文件到服務器。上傳文件網頁代碼:
<form action="doupload.jsp" enctype="multipart/form-data" method="post"> <p>姓名:<input type="text" name="user"></p> <p>選擇圖片:<input type="file" name="nfile"></p> <p><input type="submit" value="提交"></p> </form>
表單要上傳文件,需要註意兩點:
1、設置enctype屬性,值必須為multipart/form-data
2、表單的提交方式必須為post
上傳文件組件
- Commons-FileUpload組件可以方便地嵌入到JSP文件中,在JSP文件中僅編寫少量代碼即可完成文件的上傳功能,十分方便。
- 能夠全程控制上傳內容:可以獲得全部上傳文件的信息,包括文件名稱、類型、大小等,方便操作。
- 能夠對上傳文件的大小、類型進行控制:為了避免在上傳過程中出現異常數據,在Commons-FileUpload組件中,專門提供了相應的方法用於對上傳文件進行控制。
獲取Commons-FileUpload組件的方式
- http://commons.apache.org/fileupload下載Commons-FileUpload組件
Commons-FileUpload組件類庫:commons-fileupload-1.3.2.jar
Commons-FileUpload組件的API文檔: apidocs
- http://commons.apache.org/io下載Commons-IO組件
Commons-IO組件類庫:commons-io-2.5.jar
Commons-IO組件的API文檔: commons-io-2.5\docs
Commons-FileUpload組件的API
- ServletFileUpload類的常用方法
方法名稱 |
方法描述 |
public void setSizeMax(long sizeMax) |
設置請求信息實體內容的最大允許的字節數 |
public List parseRequest(HttpServletRequest req ) |
解析form表單中的每個字符的數據,返回一個FileItem對象的集合 |
public static final boolean isMultipartContent (HttpServletRequest req ) |
判斷請求信息中的內容 是否是“multipart/form-data”類型 |
public void setHeaderEncoding(String encoding) |
設置轉換時所使用的字符集編碼 |
- FileItem接口的常用方法
方法名稱 |
方法描述 |
public boolean isFormField() |
判斷FileItem對象封裝的數據類型(普通表單字段返回true,文件表單字段返回false) |
public String getName() |
獲得文件上傳字段中的文件名(普通表單字段返回null) |
public String getFieldName() |
返回表單字段元素的name屬性值 |
public void write() |
將FileItem對象中保存的主體內容保存到指定的文件中 |
public String getString() |
將FileItem對象中保存的主體內容以一個字符串返回。其重載方法public String getString(String encoding)中的參數用指定的字符集編碼方式 |
public long getSize() |
返回單個上傳文件的字節數 |
- FileItemFactory接口與實現類
實現類:DefaultFileItemFactory, DiskFileItemFactory
方法名稱 |
方法描述 |
public void setSizeThreshold(int sizeThreshold) |
設置內存緩沖區的大小 |
public void setRepositoryPath(String path ) |
設置臨時文件存放的目錄 |
文件上傳的實現
- 實現步驟
//創建FileItemFactory對象 //創建ServletFileUpload對象 //解析form表單中所有文件 if (普通表單字段){ //獲取表單字段的name屬性值 if (此屬性是“user”)){ //輸出XXX上傳了文件 } }else{ //文件表單字段 //獲取上傳文件的名字 if (名字不為空) { //保存此文件並輸出保存成功 } }
- 示例代碼
<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@page import="java.io.File"%> <%@page import="org.apache.commons.fileupload.FileItem"%> <%@page import="org.apache.commons.fileupload.FileItemFactory"%> <%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%> <%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <% request.setCharacterEncoding("utf-8"); String uploadFileName = ""; //上傳的文件名 String fieldName = ""; //表單字段元素的name屬性值 //請求信息中的內容是否是multipart類型 boolean isMultipart = ServletFileUpload.isMultipartContent(request); //上傳文件的存儲路徑(服務器文件系統上的絕對文件路徑) String uploadFilePath = request.getSession().getServletContext() .getRealPath("upload/"); if (isMultipart) { FileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); try { //解析form表單中所有文件 List<FileItem> items = upload.parseRequest(request); Iterator<FileItem> iter = items.iterator(); while (iter.hasNext()) { //依次處理每個文件 FileItem item = (FileItem) iter.next(); if (item.isFormField()) { //普通表單字段 fieldName = item.getFieldName(); //表單字段的name屬性值 if (fieldName.equals("user")) { //輸出表單字段的值 out.print(item.getString("UTF-8") + "上傳了文件。<br/>"); } } else { //文件表單字段 String fileName = item.getName(); if (fileName != null && !fileName.equals("")) { File fullFile = new File(item.getName()); File saveFile = new File(uploadFilePath, fullFile.getName()); item.write(saveFile); uploadFileName = fullFile.getName(); out.print("上傳成功後的文件名是:" + uploadFileName); out.print("<br>文件保存絕對路徑為:"+saveFile.getPath()); out.print("<br>文件保存相對路徑為:"+"upload\\"+uploadFileName); } } } } catch (Exception e) { e.printStackTrace(); } } %>
上機練習
需求描述
完成新聞發布信息的添加圖片功能
實現思路
1. 添加commons-fileupload.jar和commons-io-2.5.jar
2. 在JSP文件中使用page指令導入Commons-FileUpload類
3. 調用Commons-FileUpload組件相關類的方法獲取文件信息並實現保存
控制上傳文件的屬性
控制文件上傳的類型
代碼框架
List<String> filType=Arrays.asList("gif","bmp","jpg"); String ext=fileName.substring(fileName.lastIndexOf(".")+1); if(!filType.contains(ext)){ //判斷文件類型是否在允許範圍內 out.print("上傳失敗,文件類型只能是gif、bmp、jpg"); }else{ //上傳文件 }
控制文件上傳的大小
代碼框架
ServletFileUpload upload = new ServletFileUpload(factory); //設置單個文件的最大限制 upload.setSizeMax(1024*30); try { //……省略上傳代碼 }catch(FileUploadBase.SizeLimitExceededException ex){ out.print(“上傳失敗,文件太大,單個文件的最大限制是:"+ upload.getSizeMax()+"bytes!");
完整代碼示例
<%@page import="org.apache.commons.fileupload.FileUploadBase"%> <%@page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@page import="java.io.File"%> <%@page import="org.apache.commons.fileupload.FileItem"%> <%@page import="org.apache.commons.fileupload.FileItemFactory"%> <%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%> <%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <% request.setCharacterEncoding("utf-8"); String uploadFileName = ""; //上傳的文件名 String fieldName = ""; //表單字段元素的name屬性值 //請求信息中的內容是否是multipart類型 boolean isMultipart = ServletFileUpload.isMultipartContent(request); //上傳文件的存儲路徑(服務器文件系統上的絕對文件路徑) String uploadFilePath = request.getSession().getServletContext() .getRealPath("upload/"); //創建臨時文件目錄路徑 File tempPatchFile = new File("d:\\temp\\buffer\\"); if (!tempPatchFile.exists()) //判斷文件或目錄是否存在 tempPatchFile.mkdirs(); //創建指定的目錄,包括所有必需但不存在的父目錄 if (isMultipart) { DiskFileItemFactory factory = new DiskFileItemFactory(); //設置緩沖區大小4kb factory.setSizeThreshold(4096); //設置上傳文件用到臨時文件存放路徑 factory.setRepository(tempPatchFile); ServletFileUpload upload = new ServletFileUpload(factory); //設置單個文件的最大限制 upload.setSizeMax(1024 * 30); try { //解析form表單中所有文件 List<FileItem> items = upload.parseRequest(request); Iterator<FileItem> iter = items.iterator(); while (iter.hasNext()) { //依次處理每個文件 FileItem item = (FileItem) iter.next(); if (!item.isFormField()) { //文件表單字段 String fileName = item.getName(); //通過Arrays類的asList()方法創建固定長度的集合 List<String> filType = Arrays.asList("gif", "bmp", "jpg"); String ext = fileName.substring(fileName .lastIndexOf(".") + 1); if (!filType.contains(ext)) //判斷文件類型是否在允許範圍內 out.print("上傳失敗,文件類型只能是gif、bmp、jpg"); else { if (fileName != null && !fileName.equals("")) { File fullFile = new File(item.getName()); File saveFile = new File(uploadFilePath, fullFile.getName()); item.write(saveFile); uploadFileName = fullFile.getName(); out.print("上傳成功後的文件名是:" + uploadFileName + ",文件大小是:" + item.getSize() + "bytes!"); } } } } } catch (FileUploadBase.SizeLimitExceededException ex) { out.print("上傳失敗,文件太大,單個文件的最大限制是:" + upload.getSizeMax() + "bytes!"); } catch (Exception e) { e.printStackTrace(); } } %>
上機練習
需求描述
- 管理員在發布新聞時,可以同時實現新聞圖片的上傳
- 允許上傳的圖片類型為:GIF文件、JPG文件、JPEG文件、PNG文件
- 上傳圖片的大小不能超過5MB完成新聞發布信息的添加圖片功能
- 管理員選擇某一條新聞,單擊修改鏈接後,在新聞編輯頁面顯示此條新聞內容。
- 編輯好新聞內容後,單擊提交按鈕更新此條新聞。
上機練習
需求描述
- 管理員選擇某一條新聞,單擊修改鏈接後,在新聞編輯頁面顯示此條新聞內容。
- 編輯好新聞內容後,單擊提交按鈕更新此條新聞。
JavaEE-05 分頁與文件上傳