1. 程式人生 > >淘淘商城第二天—完成商品新增功能 商品類目選擇 圖片上傳 圖片伺服器搭建 kindEditor富文字編輯器的使用 商品新增功能

淘淘商城第二天—完成商品新增功能 商品類目選擇 圖片上傳 圖片伺服器搭建 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圖片伺服器的搭建

需要的軟體

  1. linux centos6.5
  2. nginx
  3. vsftpd

2.1.2.1 安裝nginx

(1)nginx安裝環境

nginx是C語言開發,建議在linux上執行,本教程使用Centos6.5作為安裝環境。

  1. gcc

安裝nginx需要先將官網下載的原始碼進行編譯,編譯依賴gcc環境,如果沒有gcc環境,需要安裝gcc:yum install gcc-c++

  1. PCRE

PCRE(Perl Compatible Regular Expressions)是一個Perl庫,包括 perl 相容的正則表示式庫。nginx的http模組使用pcre來解析正則表示式,所以需要在linux上安裝pcre庫。

yum install -y pcre pcre-devel

注:pcre-devel是使用pcre開發的一個二次開發庫。nginx也需要此庫。

  1. zlib

zlib庫提供了很多種壓縮和解壓縮的方式,nginx使用zlib對http包的內容進行gzip,所以需要在linux上安裝zlib庫。

yum install -y zlib zlib-devel

  1. 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

  1. 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目錄

  1. 編譯makefile

make

make  install

編譯完後會在 /usr/local/sbin目錄下有一個nginx可執行檔案

  1. nginx的使用

啟動:./nginx

關閉:./nginx -s stop

重新載入配置檔案:./nginx -s reload

(4)開放Linux的對外訪問的埠80nginx預設埠號為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

  1. 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群英匯