淘淘商城第二天—完成商品新增功能 商品類目選擇 圖片上傳 圖片伺服器搭建 kindEditor富文字編輯器的使用 商品新增功能
1、實現商品類目選擇功能
1.1需求
在商品新增頁面,點選“選擇類目”顯示商品類目列表:
請求初始化樹形控制元件的url:/item/cat/list
1.2 EasyUI tree資料結構
資料結構中必須包含:
Id:節點id
Text:節點名稱
State:如果不是葉子節點就是close,葉子節點就是open。Close的節點點選後會在此傳送請求查詢子專案。
可以根據parentid查詢分類列表。
1.3思路
1.3.1 dao層
SQL語句:select * from tb_item_cat where parent_id=0
單表查詢,可以使用逆向工程生成的程式碼。
1.3.2 service層
功能:接受parentid的引數,根據parentid查詢子類目類別。返回一個分類列表,可以建立一個pojo來描述一個節點的格式,返回一個pojo列表。
包含id、text、state屬性。因為其他工程也有可能用到此pojo所以應該放到taoatao-common工程中。
建立一個介面ItemCatServic,編寫介面getCatList
service
/** * 商品分類管理 * @author Administrator * */ @Service public class ItemCatServicImpl implements ItemCatService { @Autowired private TbItemCatMapper itemcatmapper; @Override public List<EUTreeNode> getCatList(long parentId) { //建立查詢條件 TbItemCatExample example=new TbItemCatExample(); Criteria criteria=example.createCriteria(); criteria.andParentIdEqualTo(parentId); //根據條件查詢 List<TbItemCat> list=itemcatmapper.selectByExample(example); List<EUTreeNode> resultlist=new ArrayList<>(); //把列表轉換為treeNodelist for (TbItemCat tbItemCat : list) { EUTreeNode node=new EUTreeNode(); node.setId(tbItemCat.getId()); node.setText(tbItemCat.getName()); node.setState(tbItemCat.getIsParent()?"closed":"open"); resultlist.add(node); } return resultlist; } }
1.3.3 controller層
功能:接受頁面請求的引數,名為id。呼叫service查詢分類列表。返回的是JSON格式的列表,需要使用@ResponseBody註解。
@Controller @RequestMapping("/item/cat") public class ItemCatController { @Autowired private ItemCatService itemCatService; @RequestMapping("/list") @ResponseBody //如果id為null是使用預設值,也就是parentid為0的分類列表 public List<EUTreeNode> getCatList(@RequestParam(value="id",defaultValue="0")long parentId) { List<EUTreeNode> list=itemCatService.getCatList(parentId); return list; } }
2、上傳圖片
2.1圖片伺服器
2.1.1分散式環境的圖片管理
2.1.2圖片伺服器的搭建
需要的軟體
- linux centos6.5
- nginx
- vsftpd
2.1.2.1 安裝nginx
(1)nginx安裝環境
nginx是C語言開發,建議在linux上執行,本教程使用Centos6.5作為安裝環境。
- gcc
安裝nginx需要先將官網下載的原始碼進行編譯,編譯依賴gcc環境,如果沒有gcc環境,需要安裝gcc:yum install gcc-c++
- PCRE
PCRE(Perl Compatible Regular Expressions)是一個Perl庫,包括 perl 相容的正則表示式庫。nginx的http模組使用pcre來解析正則表示式,所以需要在linux上安裝pcre庫。
yum install -y pcre pcre-devel
注:pcre-devel是使用pcre開發的一個二次開發庫。nginx也需要此庫。
- zlib
zlib庫提供了很多種壓縮和解壓縮的方式,nginx使用zlib對http包的內容進行gzip,所以需要在linux上安裝zlib庫。
yum install -y zlib zlib-devel
- openssl
OpenSSL 是一個強大的安全套接字層密碼庫,囊括主要的密碼演算法、常用的金鑰和證書封裝管理功能及SSL協議,並提供豐富的應用程式供測試或其它目的使用。
nginx不僅支援http協議,還支援https(即在ssl協議上傳輸http),所以需要在linux安裝openssl庫。
yum install -y openssl openssl-devel
(2)編譯安裝
將nginx-1.8.0.tar.gz拷貝至linux伺服器。
解壓:
tar -zxvf nginx-1.8.0.tar.gz
cd nginx-1.8.0
- configure
./configure --help查詢詳細引數(參考本教程附錄部分:nginx編譯引數)
引數設定如下:
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi
注意:上邊將臨時檔案目錄指定為/var/temp/nginx,需要在/var下建立temp及nginx目錄
- 編譯makefile
make
make install
編譯完後會在 /usr/local/sbin目錄下有一個nginx可執行檔案
- nginx的使用
啟動:./nginx
關閉:./nginx -s stop
重新載入配置檔案:./nginx -s reload
(4)開放Linux的對外訪問的埠80(nginx預設埠號為80)
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
/etc/rc.d/init.d/iptables save
(5)訪問nginx服務成功!
2.1.2.2配置ftp服務
2.1.2.2.1安裝ftp元件
(1)安裝vsftpd元件
安裝完後,有/etc/vsftpd/vsftpd.conf 檔案,是vsftp的配置檔案。
[[email protected] ~]# yum -y install vsftpd
(2)新增一個ftp使用者
此使用者就是用來登入ftp伺服器用的。
[[email protected] ~]# useradd ftpuser
這樣一個使用者建完,可以用這個登入,記得用普通登入不要用匿名了。登入後預設的路徑為 /home/ftpuser.
(3)給ftp使用者新增密碼。
[[email protected] ~]# passwd ftpuser
輸入兩次密碼後修改密碼。
(4)防火牆開啟21埠
因為ftp預設的埠為21,而centos預設是沒有開啟的,所以要修改iptables檔案
[[email protected] ~]# vim /etc/sysconfig/iptables
在行上面有22 -j ACCEPT 下面另起一行輸入跟那行差不多的,只是把22換成21,然後:wq儲存。
還要執行下,重啟iptables
[[email protected] ~]# service iptables restart
(5)修改selinux
外網是可以訪問上去了,可是發現沒法返回目錄(使用ftp的主動模式,被動模式還是無法訪問),也上傳不了,因為selinux作怪了。
修改selinux:
執行以下命令檢視狀態:
[[email protected] ~]# getsebool -a | grep ftp
allow_ftpd_anon_write --> off
allow_ftpd_full_access --> off
allow_ftpd_use_cifs --> off
allow_ftpd_use_nfs --> off
ftp_home_dir --> off
ftpd_connect_db --> off
ftpd_use_passive_mode --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off
[[email protected] ~]#
執行上面命令,再返回的結果看到兩行都是off,代表,沒有開啟外網的訪問
[[email protected] ~]# setsebool -P allow_ftpd_full_access on
[[email protected] ~]# setsebool -P ftp_home_dir on
這樣應該沒問題了(如果,還是不行,看看是不是用了ftp客戶端工具用了passive模式訪問了,如提示Entering Passive mode,就代表是passive模式,預設是不行的,因為ftp passive模式被iptables擋住了,下面會講怎麼開啟,如果懶得開的話,就看看你客戶端ftp是否有port模式的選項,或者把passive模式的選項去掉。如果客戶端還是不行,看看客戶端上的主機的電腦是否開了防火牆,關吧)
FileZilla的主動、被動模式修改:
選單:編輯→設定
(6)關閉匿名訪問
修改/etc/vsftpd/vsftpd.conf檔案:
重啟ftp服務:
[[email protected] ~]# service vsftpd restart
(7)開啟被動模式
預設是開啟的,但是要指定一個埠範圍,開啟vsftpd.conf檔案,在後面加上
pasv_min_port=30000
pasv_max_port=30999
表示埠範圍為30000~30999,這個可以隨意改。改完重啟一下vsftpd
由於指定這段埠範圍,iptables也要相應的開啟這個範圍,所以像上面那樣開啟iptables檔案。
也是在21上下面另起一行,更那行差不多,只是把21 改為30000:30999,然後:wq儲存,重啟下iptables。這樣就搞定了。
(8)設定開機啟動vsftpd ftp服務
[[email protected] ~]# chkconfig vsftpd on
- FileZilla連線成功!
密碼:ftpuser 埠:21
2.1.2.2.2訪問ftp服務
使用Java程式碼訪問,用到Apache提供的一個工具包common-net
web已依賴了common中的這個包
需要把ftp上傳功能封裝成一個工具類,可以供其他專案使用。提高程式碼的複用性。
編寫測試類
測試時出錯
解決辦法:
給ftpuser目錄新增許可權
命令:chmod 777 /home/ftpuser/
附:linux許可權命令解釋
Linux的許可權命令
許可權是Linux中的重要概念,每個檔案/目錄等都具有許可權,通過ls -l命令我們可以 檢視某個目錄下的檔案或目錄的許可權
示例:在隨意某個目錄下ls -l
第一列的內容的資訊解釋如下:
檔案的型別:
d:代表目錄
-:代表檔案
l:代表連結(可以認為是window中的快捷方式)
後面的9位分為3組,每3位置一組,分別代表屬主的許可權,與當前使用者同組的 使用者的許可權,其他使用者的許可權
r:代表權限是可讀,r也可以用數字4表示
w:代表權限是可寫,w也可以用數字2表示
x:代表權限是可執行,x也可以用數字1表示
修改檔案/目錄的許可權的命令:chmod
示例:修改/test下的aaa.txt的許可權為屬主有全部許可權,屬主所在的組有讀寫許可權,
其他使用者只有讀的許可權
chmod u=rwx,g=rw,o=r aaa.txt
上述示例還可以使用數字表示:
chmod 764 aaa.txt
成功訪問ftp上的圖片!
2.2圖片上傳的實現
2.2.1需求分析
參考文件:http://kindeditor.net/doc.php
請求的url:/pic/upload
請求的引數:uploadfile
響應的結果:
2.2.2 dao層
無
2.2.3 service層
功能:接受controller傳過來的引數,一個檔案multipartfile物件。把檔案上傳到ftp伺服器。生成一個新的檔名。返回檔案url路徑。需要包裝成圖片上傳外掛要求的資料格式。
使用map來實現:
map中的內容:
key value
--------------------------------------------------
error 1/0
url 圖片的URL(成功時)
message 錯誤資訊(失敗時)
在PictureService建立一個介面uploadPicture,返回的是一個map
impl:
匯入生成隨機檔名的工具類IDUtils
在web工程下的resourse建立resource.properties,寫入相關配置資訊。修改spring檔案,使之能夠讀取該檔案。
/**
* 圖片上傳服務
* @author Administrator
*
*/
@Service
public class PictureServiceImpl implements PictureService {
//spring容器自動注入名稱相同的屬性
@Value("${FTP_ADDRESS}")
private String FTP_ADDRESS;
@Value("${FTP_PORT}")
private Integer FTP_PORT;
@Value("${FTP_USERNAME}")
private String FTP_USERNAME;
@Value("${FTP_PASSWORD}")
private String FTP_PASSWORD;
@Value("${FTP_BASEPATH}")
private String FTP_BASEPATH;
@Value("${IMAGE_BASE_URL}")
private String IMAGE_BASE_URL;
@Override
public Map uploadPicture(MultipartFile uploadFile) {
Map resultMap=new HashMap<>();
try {
//生成一個新的檔名
//先取原始檔名
String oldName=uploadFile.getOriginalFilename();
//生成新檔名
//方法一:使用UUID
//UUID.randomUUID();
//方法二:使用時間加隨機數生成,已寫好工具類IDUtils
String newName=IDUtils.genImageName();
//檔名=newName+oldName點後面的擴張名
newName=newName+oldName.substring(oldName.lastIndexOf("."));
//圖片上傳
//使用.joda.time元件按時間生成檔名路徑
String imagePath=new DateTime().toString("/yyyy/MM/dd");
boolean result=FtpUtil.uploadFile(FTP_ADDRESS, FTP_PORT, FTP_USERNAME, FTP_PASSWORD, FTP_BASEPATH,
imagePath, newName, uploadFile.getInputStream());
//返回結果
if(!result)
{
resultMap.put("error", 1);
resultMap.put("message", "檔案上傳失敗!");
return resultMap;
}
resultMap.put("error", 0);
resultMap.put("url", IMAGE_BASE_URL + imagePath+ "/" +newName);
return resultMap;
} catch (Exception e) {
resultMap.put("error", 1);
resultMap.put("message", "檔案上傳發生異常!");
return resultMap;
}
}
}
#FTP相關配置
#FTP的ip地址
FTP_ADDRESS=192.168.201.130
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/home/ftpuser/www/images
#圖片伺服器的相關配置
#伺服器的基礎URL
IMAGE_BASE_URL=http://192.168.204.130/images
2.2.4 controller層
功能:接受MultiPartFile物件。呼叫service上傳圖片返回的Json格式。使用@ResponseBody註解。
需要引入fie-load、和common-io包
需要在springMVC中配置檔案上傳解析器,新增如下內容:
<!-- 定義檔案上傳解析器 -->
<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>
contrleer層程式碼:
/**
*上傳圖片處理
* @author Administrator
*
*/
@Controller
public class PictureCntroller {
@Autowired
PictureService pictureService;
@RequestMapping("/pic/upload")
@ResponseBody
public String pictureUpload(MultipartFile uploadFile)
{
Map result=pictureService.uploadPicture(uploadFile);
//為了保證功能的相容性,需要把result轉換成json格式的字串,需要匯入jsonUtil工具類
String json=JsonUtils.objectToJson(result);
return json;
}
}
注意:ftp生成新的資料夾,需要重新新增許可權
chmod 777 /home/ftpuser
上傳成功!
2.3富文字編輯器
使用方法:
第一步:需要在jsp中新增富文字編輯器js的引用。
第二步:在jsp中新增一個textarea域
第三步:初始化富文字編輯器
在common.js中呼叫create
第四步:提交表單之前,先把富文字編輯器中的內容和textarea中的內容進行同步
2.4新增商品的實現
2.4.1需求分析
請求的url:/item/save
引數:表單中的內容,序列化成key-value形式的字串。post請求。
響應的內容:可以自定義。封裝在taotaoresult.java中
2.4.2 dao層
把商品資訊插入到商品表。單表操作,使用逆向工程生成的程式碼。
2.4.3 service層
接收商品的pojo,把pojo的內容補全。把商品資料寫入到表中(tb_item)。返回taotaoResult。
在itemservice介面中寫一個createItem方法
@Override
public TaotaoResult createItem(TbItem item)
{
//item補全
//生成商品id,使用IDUtils工具類
Long itemid=IDUtils.genItemId();
item.setId(itemid);
item.setStatus((byte) 1);
item.setCreated(new Date());
item.setUpdated(new Date());
//插入到資料庫
itemMapper.insert(item);
return TaotaoResult.ok();
2.4.4 controller層
接收表單中的內容。使用一個pojo接收。呼叫service,返回TaoTaoResult物件。返回Json資料,需要使用ResponseBody註解。
@RequestMapping(value="/item/save",method=RequestMethod.POST)
@ResponseBody
private TaotaoResult createItem(TbItem item)
{
TaotaoResult result=itemService.createItem(item);
return result;
}
歡迎進群交流258897306或關注公眾號“IT群英匯”