<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] # 步驟 1 : 頁面 增加分類的頁面是做在上查詢結果頁面的· 需要注意幾點: 1. form的action="admin_category_add",會導致訪問CategoryServlet的add()方法 2. method="post" 用于保證中文的正確提交 3. 必須有enctype="multipart/form-data",這樣才能上傳文件 4. accept="image/*" 這樣把上傳的文件類型限制在了圖片 ![](https://box.kancloud.cn/68b914db7c091d7e589fc9e77f246f44_525x265.png) ~~~ <div class="panel panel-warning addDiv"> <div class="panel-heading">新增分類</div> <div class="panel-body"> <form method="post" id="addForm" action="admin_category_add" enctype="multipart/form-data"> <table class="addTable"> <tr> <td>分類名稱</td> <td><input id="name" name="name" type="text" class="form-control"></td> </tr> <tr> <td>分類圖片</td> <td> <input id="categoryPic" accept="image/*" type="file" name="image" /> </td> </tr> <tr class="submitTR"> <td colspan="2" align="center"> <button type="submit" class="btn btn-success">提 交</button> </td> </tr> </table> </form> </div> </div> ~~~ # 步驟 2: 為空判斷 對分類名稱和分類圖片做了為空判斷,當為空的時候,不能提交 其中用到的函數checkEmpty,在adminHeader.jsp 中定義 ![](https://box.kancloud.cn/bff31d7d842102149d3f299a1e96e3bd_566x158.png) ~~~ <script> $(function(){ $("#addForm").submit(function(){ if(!checkEmpty("name","分類名稱")) return false; if(!checkEmpty("categoryPic","分類圖片")) return false; return true; }); }); </script> ~~~ # 步驟 3 : 提交數據 當填寫了名稱,并且選中了圖片之后,就可以提交數據。 提交數據會導致CategoryServlet.add()方法被調用 # 步驟 4 : 獲取上傳文件的輸入流 前部分代碼是固定寫法,用來做一些準備工作。 ``` DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); // 設置上傳文件的大小限制為10M factory.setSizeThreshold(1024 * 10240); ``` 直到遍歷出Item,一個Item就是對應一個瀏覽器提交的數據。 ``` List items = upload.parseRequest(request); ``` 因為瀏覽器指定了以二進制的形式提交數據,那么就不能通過常規的手段獲取非File字段,比如: ``` request.getParameter("heroName") ``` 在遍歷Item時(Item即對應瀏覽器提交的字段),可以通過 ``` item.isFormField ``` 來判斷是否是常規字段還是提交的文件。 當item.isFormField返回true的時候,就表示是常規字段。 然后通過item.getFieldName()和item.getString()就知道分別是哪個字段,以及字段的值了。 ``` package com.dodoke.controller; import java.io.InputStream; import java.lang.reflect.Method; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import com.dodoke.dao.impl.CategoryDaoImpl; import com.dodoke.dao.inter.CategoryDao; import com.dodoke.util.Page; /** * Servlet implementation class BaseBackServlet */ @WebServlet("/BaseBackServlet") public abstract class BaseBackServlet extends HttpServlet { private static final long serialVersionUID = 1L; public abstract String add(HttpServletRequest request, HttpServletResponse response); public abstract String delete(HttpServletRequest request, HttpServletResponse response); public abstract String edit(HttpServletRequest request, HttpServletResponse response); public abstract String update(HttpServletRequest request, HttpServletResponse response); public abstract String list(HttpServletRequest request, HttpServletResponse response, Page page); public CategoryDao categoryDao = new CategoryDaoImpl(); public void service(HttpServletRequest request, HttpServletResponse response) { int start = 0; int count = 5; try { start = Integer.parseInt(request.getParameter("page.start")); count = Integer.parseInt(request.getParameter("page.count")); } catch (Exception e) { e.printStackTrace(); } Page page = new Page(start, count); try { /* 借助反射,調用對應的方法 */ String method = (String) request.getAttribute("method"); Method m; String redirect; if ("list".equals(method)) { m = this.getClass().getMethod(method, javax.servlet.http.HttpServletRequest.class, javax.servlet.http.HttpServletResponse.class, Page.class); redirect = m.invoke(this, request, response, page).toString(); } else { m = this.getClass().getMethod(method, javax.servlet.http.HttpServletRequest.class, javax.servlet.http.HttpServletResponse.class); redirect = m.invoke(this, request, response).toString(); } /* 根據方法的返回值,進行相應的客戶端跳轉,服務端跳轉,或者僅僅是輸出字符串 */ System.out.println(redirect); if (redirect.startsWith("@")) { response.sendRedirect(redirect.substring(1)); } else if (redirect.startsWith("%")) { response.getWriter().print(redirect.substring(1)); } else { request.getRequestDispatcher(redirect).forward(request, response); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * * @param request * @param params * @return */ public InputStream parseUpload(HttpServletRequest request, Map<String, String> params) { InputStream is = null; try { DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); // 設置上傳文件的大小限制為10M factory.setSizeThreshold(1024 * 10240); List items = upload.parseRequest(request); Iterator iter = items.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (!item.isFormField()) { // item.getInputStream() 獲取上傳文件的輸入流 is = item.getInputStream(); } else { String paramName = item.getFieldName(); String paramValue = item.getString(); paramValue = new String(paramValue.getBytes("ISO-8859-1"), "UTF-8"); params.put(paramName, paramValue); } } } catch (Exception e) { e.printStackTrace(); } return is; } } ``` # 步驟 5 : 接受數據并處理 在add()方法中做了如下操作: 1\. parseUpload 獲取上傳文件的輸入流 2\. parseUpload 方法會修改params 參數,并且把瀏覽器提交的name信息放在其中 3\. 從params 中取出name信息,并根據這個name信息,借助categoryDAO,向數據庫中插入數據。 4\. 根據request.getServletContext().getRealPath( "img/category"),定位到存放分類圖片的目錄 5\. 文件命名以保存到數據庫的分類對象的id+".jpg"的格式命名 6\. 根據步驟1獲取的輸入流,把瀏覽器提交的文件,復制到目標文件 7\. 借助ImageUtil.change2jpg()方法把格式真正轉化為jpg,而不僅僅是后綴名為.jpg > 注: > 1. 為什么不能直接使用request.getParameter("name")的方式來獲取數據? > 因為當瀏覽器提交的數據是二進制的時候,Servlet不能夠通過這種方式直接獲取參數。 > 2. 為什么要用request.getServletContext().getRealPath( )的方式定位d:/xxxxx/xxxx/x/xxx/img/category 這目錄,而不是用硬編碼寫死? 因為在部署到Linux 實際運行的時候,Linux上的目錄就有是其他的路徑了,比如 /usr/public/tmall/img/category,只有采用這種方式才能兼容 > 3. 第七步為什么要這么做? 因為瀏覽器提交來的圖片文件,有可能是png,gif,bmp等非jpg格式的圖片。 僅僅修改文件的后綴名有可能會導致顯示異常。 ``` package com.dodoke.controller; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.imageio.ImageIO; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.dodoke.bean.Category; import com.dodoke.util.ImageUtil; import com.dodoke.util.Page; /** * Servlet implementation class CategoryServlet */ @WebServlet("/CategoryServlet") public class CategoryServlet extends BaseBackServlet { /** * */ private static final long serialVersionUID = 1L; public String add(HttpServletRequest request, HttpServletResponse response) { Map<String, String> params = new HashMap<>(); // 獲取上傳文件的輸入流 InputStream is = super.parseUpload(request, params); // 獲取參數 String name = params.get("name"); Category c = new Category(); c.setName(name); // 新增分類 categoryDao.add(c); // 設置文件路徑 File imageFolder = new File(request.getSession().getServletContext().getRealPath("img/category")); // 根據文件目錄和文件名稱,創建文件對象 File file = new File(imageFolder, c.getId() + ".jpg"); // 創建目錄(若沒有category,則創建;否者,不做處理) file.getParentFile().mkdirs(); try { // inputStream.available()查看流的大小 if (null != is && 0 != is.available()) { // 復制文件 // 創建一個輸出流對象 try (FileOutputStream fos = new FileOutputStream(file)) { // 創建一個接受1024kb大小的byte數組 byte b[] = new byte[1024 * 1024]; int length = 0; // 循環從is流中每次讀取1024Kb大小的字節,并通過fs.read(b),將其存儲到byte數組b中 // read方法就是讀取輸入流到字節數組中,當返回值是0的時候,表示讀完了,再繼續讀就返回-1 while (-1 != (length = is.read(b))) { // 將b數組里指定長度length的內容寫入 fos.write(b, 0, length); } // 有的時候,需要立即把數據寫入到硬盤,而不是等緩存滿了才寫出去。 這時候就需要用到flush fos.flush(); // 通過如下代碼,把文件保存為jpg格式 BufferedImage img = ImageUtil.change2jpg(file); ImageIO.write(img, "jpg", file); } catch (Exception e) { e.printStackTrace(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return "@admin_category_list"; } public String delete(HttpServletRequest request, HttpServletResponse response) { int id = Integer.parseInt(request.getParameter("id")); categoryDao.delete(id); return "@admin_category_list"; } public String edit(HttpServletRequest request, HttpServletResponse response) { int id = Integer.parseInt(request.getParameter("id")); Category c = categoryDao.get(id); request.setAttribute("c", c); return "admin/editCategory.jsp"; } public String update(HttpServletRequest request, HttpServletResponse response) { Map<String, String> params = new HashMap<>(); InputStream is = super.parseUpload(request, params); System.out.println(params); String name = params.get("name"); int id = Integer.parseInt(params.get("id")); Category c = new Category(); c.setId(id); c.setName(name); categoryDao.update(c); File imageFolder = new File(request.getSession().getServletContext().getRealPath("img/category")); File file = new File(imageFolder, c.getId() + ".jpg"); file.getParentFile().mkdirs(); try { if (null != is && 0 != is.available()) { try (FileOutputStream fos = new FileOutputStream(file)) { byte b[] = new byte[1024 * 1024]; int length = 0; while (-1 != (length = is.read(b))) { fos.write(b, 0, length); } fos.flush(); BufferedImage img = ImageUtil.change2jpg(file); ImageIO.write(img, "jpg", file); } catch (Exception e) { e.printStackTrace(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return "@admin_category_list"; } public String list(HttpServletRequest request, HttpServletResponse response, Page page) { List<Category> cs = categoryDao.list(page.getStart(), page.getCount()); int total = categoryDao.getTotal(); page.setTotal(total); request.setAttribute("thecs", cs); request.setAttribute("page", page); return "admin/listCategory.jsp"; } } ``` # 步驟 6 : ImageUtil工具類 ImageUtil 工具類提供3個方法 1. change2jpg 確保圖片文件的二進制格式是jpg。 僅僅通過`ImageIO.write(img, "jpg", file);`不足以保證轉換出來的jpg文件顯示正常。這段轉換代碼,可以確保轉換后jpg的圖片顯示正常,而不會出現暗紅色( 有一定幾率出現)。 這也是百度上找到的。不過找了很多代碼哦,才找到這一段能真正生效,而且不會發生錯誤的。 2. 后兩種resizeImage用于改變圖片大小,在上傳產品圖片的時候會用到。 這里不展開,到時候再講 ~~~ package com.dodoke.tmall.util; import java.awt.Image; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferInt; import java.awt.image.DirectColorModel; import java.awt.image.PixelGrabber; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.WritableRaster; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class ImageUtil { /** * 把圖片強制轉換為jpg格式,獲得BufferedImage對象 * @param f 圖片文件 * @return BufferedImage */ public static BufferedImage change2jpg(File f) { try { Image i = Toolkit.getDefaultToolkit().createImage(f.getAbsolutePath()); PixelGrabber pg = new PixelGrabber(i, 0, 0, -1, -1, true); pg.grabPixels(); int width = pg.getWidth(), height = pg.getHeight(); final int[] RGB_MASKS = { 0xFF0000, 0xFF00, 0xFF }; final ColorModel RGB_OPAQUE = new DirectColorModel(32, RGB_MASKS[0], RGB_MASKS[1], RGB_MASKS[2]); DataBuffer buffer = new DataBufferInt((int[]) pg.getPixels(), pg.getWidth() * pg.getHeight()); WritableRaster raster = Raster.createPackedRaster(buffer, width, height, width, RGB_MASKS, null); BufferedImage img = new BufferedImage(RGB_OPAQUE, raster, false, null); return img; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } public static void resizeImage(File srcFile, int width,int height, File destFile) { try { if(!destFile.getParentFile().exists()) destFile.getParentFile().mkdirs(); Image i = ImageIO.read(srcFile); i = resizeImage(i, width, height); ImageIO.write((RenderedImage) i, "jpg", destFile); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static Image resizeImage(Image srcImage, int width, int height) { try { BufferedImage buffImg = null; buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); buffImg.getGraphics().drawImage(srcImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); return buffImg; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } } ~~~ # 步驟 7 : 中文問題 中文問題,統一交由EncodingFilter來進行處理 ``` request.setCharacterEncoding("UTF-8"); ``` 對提交的數據進行UTF-8編碼。 其他的配合動作 1. 在jsp中要加上 ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%> ``` 其中contentType="text/html; charset=UTF-8"的作用是告訴瀏覽器提交數據的時候,使用UTF-8編碼 2. 在form里method="post" 才能正確提交中文 EncodingFilter: ``` package com.dodoke.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class EncodingFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; request.setCharacterEncoding("UTF-8"); chain.doFilter(request, response); } @Override public void init(FilterConfig arg0) throws ServletException { } } ``` web.xml: ``` <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>tmall_j2ee</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <filter> <filter-name>EncodingFilter</filter-name> <filter-class>com.dodoke.filter.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>BackServletFilter</filter-name> <filter-class>com.dodoke.filter.BackServletFilter</filter-class> </filter> <filter-mapping> <filter-name>BackServletFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app> ``` # 步驟 8 : 客戶端跳轉 最后,add() 方法里返回了 return "@admin\_category\_list"; 這樣就客戶端跳轉到了頁面: http://127.0.0.1:8080/tmall/admin\_category\_list 為什么這樣就能進行客戶端跳轉? 這部分邏輯在BaseBackServlet的service() 方法的72-78行: 當返回值以"@"開頭的時候,就進行客戶端跳轉response.sendRedirect(redirect.substring(1)); ``` /* 根據方法的返回值,進行相應的客戶端跳轉,服務端跳轉,或者僅僅是輸出字符串 */ System.out.println(redirect); if (redirect.startsWith("@")) { response.sendRedirect(redirect.substring(1)); } else if (redirect.startsWith("%")) { response.getWriter().print(redirect.substring(1)); } else { request.getRequestDispatcher(redirect).forward(request, response); } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看