1、課程介紹
2、簡單功能實現
3、圖片上傳功能實戰
4、項目源碼與資料下載
5、參考文章前端
一共14天課程
(1)第一天:電商行業的背景。淘淘商城的介紹。搭建項目工程。Svn的使用。
(2)次日:框架的整合。後臺管理商品列表的實現。分頁插件。
(3)第三天:後臺管理。商品添加。商品類目的選擇、圖片上傳、富文本編輯器的使用。
(4)第四天:商品規格的實現。
(5)第五天:商城前臺系統的搭建。首頁商品分類的展現。Jsonp。
(6)第六天:cms系統的實現。前臺大廣告位的展現。
(7)第七天:cms系統添加緩存。Redis。緩存同步。
(8)第八天:搜索功能的實現。使用solr實現搜索。
(9)第九天:商品詳情頁面的展現。
(10)第十天:單點登陸系統。Session共享。
(11)第十一天:購物車訂單系統的實現。
(12)第十二天:nginx。反向代理工具。
(13)第十三天:redis集羣的搭建、solr集羣的搭建。系統的部署。
(14)項目總結。java
因爲jsp在實際項目中已經比較少使用,如今更多的是先後端分離,因此文章重點關注於後端技術實現,該模塊詳細功能,請移步項目源碼與資料下載內容中進行學習。linux
因爲jsp在實際項目中已經比較少使用,如今更多的是先後端分離,因此文章重點關注於後端技術實現,該模塊詳細功能,請移步項目源碼與資料下載內容中進行學習。nginx
傳統項目中,能夠在web項目中添加一個文件夾,來存放上傳的圖片。例如在工程的根目錄WebRoot下建立一個images文件夾。把圖片存放在此文件夾中就能夠直接使用在工程中引用。
優勢:引用方便,便於管理
缺點:
(1)若是是分佈式環境圖片引用會出現問題。
(2)圖片的下載會給服務器增長額外的壓力web
傳統圖片管理方式在分佈式環境中的問題redis
分佈式環境通常都有一個專門的圖片服務器存放圖片。
咱們使用虛擬機搭建一個專門的服務器來存放圖片。在此服務器上安裝一個nginx來提供http服務,安裝一個ftp服務器來提供圖片上傳服務。spring
3.1 圖片服務器相關服務
圖片服務器兩個服務:
http:可使用nginx作靜態資源服務器。也可使用apache。推薦使用nginx,效率更高。
Nginx功能:
(1)http服務
(2)反向代理
(3)負載均衡數據庫
ftp服務:
使用linux作服務器,在linux中有個ftp組件vsftpd。
ngnix服務器的安裝過程包括配置資源、啓動、中止、重啓、開機自動啓動等,FTP服務安裝包括添加vsftpd組件、添加ftp用戶、分配ftp用戶密碼、開啓防火牆21端口、關閉匿名訪問、開啓被動模式等,具體教程請參考資料下載中的內容。apache
4.1 工具類編寫
taotao-common項目中編寫上傳圖片的返回結果的實體類PictureResult.javajson
public class PictureResult { private int error;//判斷是否成功 0位成功,1爲失敗 private String url;//若是成功 該參數爲圖片的請求地址 失敗則爲null private String message;//若是失敗,該參數是描述緣由,若是成功,則爲null private PictureResult(int error, String url, String message) { this.error = error; this.url = url; this.message = message; } //成功時調用的方法 public static PictureResult ok(String url) { return new PictureResult(0, url, null); } //失敗時調用的方法 public static PictureResult error(String message) { return new PictureResult(1, null, message); } public int getError() { return error; } public void setError(int error) { this.error = error; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
taotao-common項目中編寫ftp上傳下載工具類FtpUtil.java
public class FtpUtil { /** * Description: 向FTP服務器上傳文件 * @param host FTP服務器hostname * @param port FTP服務器端口 * @param username FTP登陸帳號 * @param password FTP登陸密碼 * @param basePath FTP服務器基礎目錄 * @param filePath FTP服務器文件存放路徑。例如分日期存放:/2015/01/01。文件的路徑爲basePath+filePath * @param filename 上傳到FTP服務器上的文件名 * @param input 輸入流 * @return 成功返回true,不然返回false */ public static boolean uploadFile(String host, int port, String username, String password, String basePath, String filePath, String filename, InputStream input) { boolean result = false; FTPClient ftp = new FTPClient(); try { int reply; ftp.connect(host, port);// 鏈接FTP服務器 // 若是採用默認端口,可使用ftp.connect(host)的方式直接鏈接FTP服務器 ftp.login(username, password);// 登陸 reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); return result; } //切換到上傳目錄 if (!ftp.changeWorkingDirectory(basePath+filePath)) { //若是目錄不存在建立目錄 String[] dirs = filePath.split("/"); String tempPath = basePath; for (String dir : dirs) { if (null == dir || "".equals(dir)) continue; tempPath += "/" + dir; if (!ftp.changeWorkingDirectory(tempPath)) { if (!ftp.makeDirectory(tempPath)) { return result; } else { ftp.changeWorkingDirectory(tempPath); } } } } //設置上傳文件的類型爲二進制類型 ftp.setFileType(FTP.BINARY_FILE_TYPE); //上傳文件 if (!ftp.storeFile(filename, input)) { return result; } input.close(); ftp.logout(); result = true; } catch (IOException e) { e.printStackTrace(); } finally { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException ioe) { } } } return result; } /** * Description: 從FTP服務器下載文件 * @param host FTP服務器hostname * @param port FTP服務器端口 * @param username FTP登陸帳號 * @param password FTP登陸密碼 * @param remotePath FTP服務器上的相對路徑 * @param fileName 要下載的文件名 * @param localPath 下載後保存到本地的路徑 * @return */ public static boolean downloadFile(String host, int port, String username, String password, String remotePath, String fileName, String localPath) { boolean result = false; FTPClient ftp = new FTPClient(); try { int reply; ftp.connect(host, port); // 若是採用默認端口,可使用ftp.connect(host)的方式直接鏈接FTP服務器 ftp.login(username, password);// 登陸 reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); return result; } ftp.changeWorkingDirectory(remotePath);// 轉移到FTP服務器目錄 FTPFile[] fs = ftp.listFiles(); for (FTPFile ff : fs) { if (ff.getName().equals(fileName)) { File localFile = new File(localPath + "/" + ff.getName()); OutputStream is = new FileOutputStream(localFile); ftp.retrieveFile(ff.getName(), is); is.close(); } } ftp.logout(); result = true; } catch (IOException e) { e.printStackTrace(); } finally { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException ioe) { } } } return result; } public static void main(String[] args) { try { FileInputStream in=new FileInputStream(new File("D:\\temp\\image\\gaigeming.jpg")); boolean flag = uploadFile("192.168.25.133", 21, "ftpuser", "ftpuser", "/home/ftpuser/www/images","/2015/01/21", "gaigeming.jpg", in); System.out.println(flag); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
編寫完成後的文件結構以下:
4.2 Service層編寫
taotao-manager-web項目編寫資源文件resource.properties,用於存放於FTP相關的變量
#FTP\u7684\u76f8\u5173\u914d\u7f6e FTP_ADDRESS=192.168.101.6 FTP_PORT=21 FTP_USER_NAME=haha FTP_PASSWORD=147258qq FTP_BASE_PATH=/home/ftpuser/www/images #\u56fe\u7247\u670d\u52a1\u5668\u7684url IMAGE_BASE_URL=http://192.168.101.6/images
taotao-manager-service項目中編寫上傳圖片處理接口PictureService.java
/** * 上傳圖片處理 */ public interface PictureService { PictureResult uploadPicture(MultipartFile uploadFile); }
taotao-manager-service項目中編寫上傳圖片處理實現類PictureServiceImpl.java
/** * 上傳圖片處理服務實現類 */ @Service public class PictureServiceImpl implements PictureService { //使用@Value註解時候,當配置文件中內容修改時候,映射過來的內容會自動更改的 @Value("${FTP_ADDRESS}") private String FTP_ADDRESS; @Value("${FTP_PORT}") private Integer FTP_PORT; @Value("${FTP_USER_NAME}") private String FTP_USER_NAME; @Value("${FTP_PASSWORD}") private String FTP_PASSWORD; @Value("${FTP_BASE_PATH}") private String FTP_BASE_PATH; @Value("${IMAGE_BASE_URL}") private String IMAGE_BASE_URL; @Override public PictureResult uploadPicture(MultipartFile uploadFile) { //判斷上傳圖片是否爲空 if (null == uploadFile || uploadFile.isEmpty()) { return PictureResult.error("上傳圖片爲空"); } //取文件擴展名 String originalFilename = uploadFile.getOriginalFilename(); String ext = originalFilename.substring(originalFilename.lastIndexOf(".")); //生成新文件名 //可使用uuid生成新文件名。 //UUID.randomUUID() //能夠是時間+隨機數生成文件名 String imageName = IDUtils.genImageName(); //把圖片上傳到ftp服務器(圖片服務器) //須要把ftp的參數配置到配置文件中 //文件在服務器的存放路徑,應該使用日期分隔的目錄結構 DateTime dateTime = new DateTime(); String filePath = dateTime.toString("/yyyy/MM/dd"); try { FtpUtil.uploadFile(FTP_ADDRESS, FTP_PORT, FTP_USER_NAME, FTP_PASSWORD, FTP_BASE_PATH, filePath, imageName + ext, uploadFile.getInputStream()); } catch (Exception e) { e.printStackTrace(); return PictureResult.error(ExceptionUtil.getStackTrace(e)); } //返回結果,生成一個能夠訪問到圖片的url返回 return PictureResult.ok(IMAGE_BASE_URL + filePath + "/" + imageName + ext); } }
編寫完成後的項目結構以下
功能:接收controller層傳遞過來的圖片對象,把圖片上傳到ftp服務器。給圖片生成一個新的名字。
參數:MultiPartFile uploadFile
返回值:返回一個pojo,應該是PictureResult。
舒適提示:在resource.properties文件中編寫的變量內容,與service層中@Value註解的內容一一對應,若resource.properties中內容變了,@Value會隨之變化
4.3 Controller層編寫
在taotao-manager-web項目的springmvc.xml文件中添加如下內容
<!-- 定義文件上傳解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 設定默認編碼 --> <property name="defaultEncoding" value="UTF-8"></property> <!-- 設定文件上傳的最大值5MB,5*1024*1024 --> <property name="maxUploadSize" value="5242880"></property> </bean>
在taotao-manager-web項目中編寫接收的圖片的PictureController.java
package com.taotao.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import com.taotao.common.pojo.PictureResult; import com.taotao.common.utils.JsonUtils; import com.taotao.service.PictureService; /** * 圖片上傳controller */ @Controller public class PictureController { @Autowired private PictureService pictureService; @RequestMapping("/pic/upload") @ResponseBody public String upload(MultipartFile uploadFile) { PictureResult result = pictureService.uploadPicture(uploadFile); //將對象轉化成json字符串 return JsonUtils.objectToJson(result); } }
在實際開發中,咱們圖片管理的方式能夠有多種,好比:
(1)本身搭建圖片服務器,以後將圖片上傳後的訪問路徑保存在數據庫中,以後返回給前端進行渲染
(2)採用第三方提供的OSS存儲空間(阿里雲、騰訊雲等),將圖片託管在雲端,以後上傳時候,本身備份一份在本身服務器,全部的操做以第三方文檔爲準
連接:https://pan.baidu.com/s/12lllAj4PdrGV6_b2WsrhfQ
提取碼:f5qm