在taotao-manager-web項目中的jsp下的item-add.jsp中:php
item-add.jsp做爲首頁index.jsp一個片斷
,因此在item-add.jsp中咱們一樣可使用common.js。
初始化tree請求的url:/item/cat/list
參數:id 父節點的id值。
初始化tree時只須要把第一級節點展現,子節點異步加載展現。
返回值:json格式數據
[{
"id": 1,
"text": "Node 1",
"state": "closed"
},{
"id": 2,
"text": "Node 2",
"state": "closed"
}]
state:若是節點下有子節點則state的值爲"closed",若是節點下沒有子節點則state的值爲"open"。
因此咱們須要建立一個pojo來描述tree的節點信息,包含三個屬性id、text、state。
放到taotao-common工程中。因爲是服務端響應回來的pojo數據,因此須要實現序列化接口。
EasyUITreeNode.javacss
package com.taotao.common.pojo;
import java.io.Serializable;
/**
* 類目查詢時的返回的數據類
* @author chenmingjun
* @date 2018年11月12日下午5:01:23
* @version 1.0
*/
public class EasyUITreeNode implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String text;
private String state;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
@Override
public String toString() {
return "EasyUITreeNode [id=" + id + ", text=" + text + ", state=" + state + "]";
}
}
查詢的表:
tb_item_cat
查詢的列:
id、name、is_parent
查詢條件:
parentId前端
Dao層只須要查詢商品分類表tb_item_cat便可,屬於單表查詢,單表查詢咱們沒有必要本身寫Mapper了,使用Mybatis逆向工程生成的Mapper便可。java
參數:
Long parentId
業務邏輯:
一、根據parentId查詢節點列表。
二、轉換成EasyUITreeNode列表。
三、返回。
返回值:
List<EasyUITreeNode>
node
先寫接口,在taotao-manager-interface工程中:nginx
package com.taotao.service;
import java.util.List;
import com.taotao.common.pojo.EasyUITreeNode;
/**
* 商品類目管理接口
* @author chenmingjun
* @date 2018年11月12日下午8:15:24
* @version 1.0
*/
public interface ItemCatService {
/**
* 根據商品類目的父節點id,查詢該節點的子類目列表
* @param parentId
* @return
*/
List<EasyUITreeNode> getItemCatList(Long parentId);
}
再寫實現類,在taotao-manager-service工程中:web
/**
* 商品類目管理Service
* @author chenmingjun
* @date 2018年11月12日下午8:15:58
* @version 1.0
*/
@Service
public class ItemCatServiceImpl implements ItemCatService {
@Autowired
private TbItemCatMapper itemCatMapper;
@Override
public List<EasyUITreeNode> getItemCatList(Long parentId) {
TbItemCatExample example = new TbItemCatExample();
// 設置查詢條件
Criteria criteria = example.createCriteria();
criteria.andParentIdEqualTo(parentId);
List<TbItemCat> list = itemCatMapper.selectByExample(example);
// 將list轉換成EasyUITreeNode列表
List<EasyUITreeNode> resultList = new ArrayList<>();
for (TbItemCat tbItemCat : list) {
EasyUITreeNode node = new EasyUITreeNode();
node.setId(tbItemCat.getId());
node.setText(tbItemCat.getName());
// 若是節點下有子節點則state的值爲"closed",若是節點下沒有子節點則state的值爲"open"
node.setState(tbItemCat.getIsParent() ? "closed" : "open");
// 將節點添加到list集合(列表)
resultList.add(node);
}
return resultList;
}
}
在taotao-manager-service中的applicationContext-service.xml中發佈服務:spring
在taotao-manager-web中的springmvc.xml中引用服務:數據庫
初始化tree請求的url:
/item/cat/list
參數:
Long id(父節點id,表現層須要使用註解@RequestParam進行映射成parentId)
返回值:json格式的數據,使用註解@ResponseBody
List<EasyUITreeNode>
json
/**
* 商品類目管理Controller
* @author chenmingjun
* @date 2018年11月12日下午9:02:03
* @version 1.0
*/
@Controller
public class ItemCatController {
@Autowired
private ItemCatService itemCatService;
@RequestMapping("/item/cat/list")
@ResponseBody
public List<EasyUITreeNode> getItemCatList(@RequestParam(value="id", defaultValue="0") Long parentId) {
// 注意:第一次請求是沒有參數傳過來的,咱們給id一個默認值0,defaultValue="0"
List<EasyUITreeNode> list = itemCatService.getItemCatList(parentId);
return list;
}
}
好比:產品經理提供需求
商品屬性以下:
public static void main(String[] args) {
float a = 1.3f;
double b = 1.3d;
float aa = a * 3;
double bb = b * 3;
System.out.println(aa);
System.out.println(bb);
}
打印結果是:
3.8999999
3.9000000000000004
存在的問題:
前端顯示是元,兩位小數,保存在數據庫是分,因此保存數據須要把顯示的數據乘以100。
傳統方式:
分佈式文件系統FastDFS(國產:淘寶)
。
圖片服務器的要求:
一、存儲空間可擴展。
二、提供一個統一的訪問方式。
三、若是想安裝,可參考文檔,暫時不推薦本身搭建(耗費時間很長,有空再搭建),直接使用提供的虛擬機。
使用FastDFS,分佈式文件系統。存儲空間能夠橫向擴展,能夠實現服務器的高可用
。支持每一個節點有備份機
。
FastDFS是用
c語言編寫
的一款開源的分佈式文件系統
(國產軟件)。FastDFS爲互聯網量身定製,充分考慮了冗餘備份(高可用)
、負載均衡(高併發量)
、線性擴容(添加服務器或者磁盤)
等機制,並注重高可用、高性能等指標,使用FastDFS很容易搭建一套高性能的文件服務器集羣提供文件上傳、下載等服務。
FastDFS架構包括
Tracker server
和Storage server
。客戶端請求 Tracker server 進行文件上傳、下載,經過Tracker server調度最終由 Storage server 完成文件上傳和下載。
Tracker server 做用是負載均衡和調度
,經過 Tracker server 在文件上傳時能夠根據一些策略找到 Storage server 提供文件上傳服務。能夠將 tracker 稱爲追蹤服務器
或調度服務器
。
Storage server 做用是文件存儲
,客戶端上傳的文件最終存儲在Storage服務器上,Storage server 沒有實現本身的文件系統而是利用操做系統的文件系統來管理文件
。能夠將storage稱爲存儲服務器
。
FastDFS架構圖以下所示:
服務端兩個角色:
Tracker:管理集羣,tracker也能夠實現集羣。每一個tracker節點地位平等(沒有主從的概念)。
收集Storage集羣的狀態。
Storage:實際保存文件。
Storage分爲多個組(卷),每一個組之間保存的文件是不一樣的。每一個組內部能夠有多個成員,組內的成員內部保存的內容是同樣的,組成員的地位是一致的,沒有主從的概念。
文件ID
返回給客戶端,此文件ID用於之後訪問該文件的索引信息。
暫時不推薦本身搭建FastDFS圖片服務器(耗費時間很長,有空再搭建),直接使用提供的虛擬機。
使用提供的虛擬機,須要注意幾個問題,以下圖所示:
/**
* 使用DastDFS的Java客戶端上傳圖片
* @author chenmingjun
* @date 2018年11月13日下午4:14:01
* @version 1.0
*/
public class FastDFSTest {
@Test
public void FileUploadTest() throws Exception {
// 0、向工程中添加jar包。目前咱們使用的是maven工程,不能直接添加jar包,須要建立maven工程,安裝到本地,再在使用的工程中添加依賴。
// 一、加載配置文件,配置文件中的內容就是tracker服務的地址。配置文件內容:tracker_server=192.168.25.133:22122
ClientGlobal.init("D:/learn/Java/eclipse-jee-mars-2-win32_x64/eclipse-workspace/taotao/taotao-manager-web/src/main/resources/resource/fdfs_client.conf");
// 二、建立一個TrackerClient對象,咱們直接new一個。
TrackerClient trackerClient = new TrackerClient();
// 三、使用TrackerClient對象建立鏈接,得到一個TrackerServer對象。
TrackerServer trackerServer = trackerClient.getConnection();
// 四、建立一個StorageServer的引用(不用new出來),值爲null。不建立這個引用也能夠,直接引用。
StorageServer storageServer = null;
// 五、建立一個StorageClient對象,該對象須要兩個參數:TrackerServer對象、StorageServer的引用
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
// 六、使用StorageClient對象上傳圖片。
// 擴展名不帶「.」
String[] strings = storageClient.upload_file("C:/Users/Bruce/Desktop/個人頭像.jpg", "jpg", null);
// 七、返回數組。包含組名和圖片的路徑。
for (String string : strings) {
System.out.println(string);
}
}
}
/**
* DastDFS的Java客戶端上傳圖片工具類,用於上傳圖片至DastDFS服務器
* @author chenmingjun
* @date 2018年11月13日下午4:58:48
* @version 1.0
*/
public class FastDFSClientUtil {
private TrackerClient trackerClient = null;
private TrackerServer trackerServer = null;
private StorageServer storageServer = null;
private StorageClient1 storageClient = null;
public FastDFSClientUtil(String conf) throws Exception {
if (conf.contains("classpath:")) {
conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
}
ClientGlobal.init(conf);
trackerClient = new TrackerClient();
trackerServer = trackerClient.getConnection();
storageServer = null;
storageClient = new StorageClient1(trackerServer, storageServer);
}
/**
* 上傳文件方法(文件方式)
* @param fileName 文件全路徑
* @param extName 文件擴展名,不包含(.)
* @param metas 文件擴展信息
* @return
* @throws Exception
*/
public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
String result = storageClient.upload_file1(fileName, extName, metas);
return result;
}
public String uploadFile(String fileName) throws Exception {
return uploadFile(fileName, null, null);
}
public String uploadFile(String fileName, String extName) throws Exception {
return uploadFile(fileName, extName, null);
}
/**
* 上傳文件方法(字節方式)
* @param fileContent 文件的內容,字節數組
* @param extName 文件擴展名
* @param metas 文件擴展信息
* @return
* @throws Exception
*/
public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {
String result = storageClient.upload_file1(fileContent, extName, metas);
return result;
}
public String uploadFile(byte[] fileContent) throws Exception {
return uploadFile(fileContent, null, null);
}
public String uploadFile(byte[] fileContent, String extName) throws Exception {
return uploadFile(fileContent, extName, null);
}
}
分析仍是有幾個地方須要用到圖片上傳的,因此將工具類拷貝到:taotao-common工程下,如圖:
@Test
public void FastDFSClientUtilsTest() throws Exception {
// 生產環境下咱們使用classpath,如今學習階段使用全路徑名,因爲工具類寫的不夠好
FastDFSClientUtil fastDFSClientUtils = new FastDFSClientUtil("D:/learn/Java/eclipse-jee-mars-2-win32_x64/eclipse-workspace/taotao/taotao-manager-web/src/main/resources/resource/fdfs_client.conf");
String string = fastDFSClientUtils.uploadFile("C:/Users/Bruce/Desktop/個人頭像.jpg");
System.out.println(string);
}
請求的url:/pic/upload
參數:MultiPartFile uploadFile
返回值:
圖片上傳跟服務層沒有什麼關係,表現層就能夠將這件事作了。
表現層使用的是SpringMVC,須要加入文件上傳的jar包,若是沒有添加jar包,則須要把commons-io
、fileupload
的jar包添加到taotao-manager-web工程中。
在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>
開發controller實現圖片上傳。
將圖片服務器的前綴放入屬性文件中:
@Controller
public class PictureController {
@Value("${TAOTAO_IMAGE_SERVER_URL}") // 使用註解取出配置文件的值
private String TAOTAO_IMAGE_SERVER_URL;
/**
* 上傳圖片
* @param uploadFile
* @return
*/
@RequestMapping(value="/pic/upload")
@ResponseBody // 在後臺,把JavaBean強制轉換成json格式數據返回給前臺頁面。
public Map<String, Object> pictureUpload(MultipartFile uploadFile) {
try {
// 一、取出文件的擴展名
String originalFilename = uploadFile.getOriginalFilename();
String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
// 二、使用工具類建立一個FastDFS的客戶端
FastDFSClientUtil fastDFSClientUtil = new FastDFSClientUtil("classpath:resource/fdfs_client.conf");
// 三、執行上傳處理,返回的字符串:group1/M00/00/01/wKgZhVjnAd6AKj_RAAvqH_kipG8211.jpg
String path = fastDFSClientUtil.uploadFile(uploadFile.getBytes(), extName);
// 四、拼接返回的url和ip地址,拼裝成完整的url
// String url = "http://192.168.25.133/" + path;
String url = TAOTAO_IMAGE_SERVER_URL + path;
// 五、返回map,設置上傳成功後的圖片的路徑
Map<String, Object> result = new HashMap<>();
result.put("error", 0);
result.put("url", url);
// 六、返回
return result;
} catch (Exception e) {
e.printStackTrace();
// 五、返回map,設置上傳失敗錯誤信息
Map<String, Object> result = new HashMap<>();
result.put("error", 1);
result.put("message", "圖片上傳失敗");
return result;
}
}
}
KindEditor的圖片上傳插件,對瀏覽器兼容性很差,不能使用JSON響應。
JsonUtils工具類
將
對象轉換成JSON格式的字符串
。將其拷貝到
taotao-common
項目中,
安裝到本地倉庫
。
@Controller
public class PictureController {
@Value("${TAOTAO_IMAGE_SERVER_URL}") // 使用註解取出配置文件的值
private String TAOTAO_IMAGE_SERVER_URL;
/**
* 上傳圖片
* @param uploadFile
* @return
*/
@RequestMapping(value="/pic/upload", produces=MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8")
@ResponseBody // 在後臺,把JavaBean強制轉換成json格式數據返回給前臺頁面。
public String PictureUpload(MultipartFile uploadFile) {
try {
// 一、取出文件的擴展名
String originalFilename = uploadFile.getOriginalFilename();
String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
// 二、使用工具類建立一個FastDFS的客戶端
FastDFSClientUtil fastDFSClientUtil = new FastDFSClientUtil("classpath:resource/fdfs_client.conf");
// 三、執行上傳處理,返回的字符串:group1/M00/00/01/wKgZhVjnAd6AKj_RAAvqH_kipG8211.jpg
String path = fastDFSClientUtil.uploadFile(uploadFile.getBytes(), extName);
// 四、拼接返回的url和ip地址,拼裝成完整的url
// String url = "http://192.168.25.133/" + path;
String url = TAOTAO_IMAGE_SERVER_URL + path;
// 五、返回map,設置上傳成功後的圖片的路徑
Map<String, Object> result = new HashMap<>();
result.put("error", 0);
result.put("url", url);
// 六、返回
return JsonUtils.objectToJson(result);
} catch (Exception e) {
e.printStackTrace();
// 五、返回map,設置上傳失敗錯誤信息
Map<String, Object> result = new HashMap<>();
result.put("error", 1);
result.put("message", "圖片上傳失敗");
return JsonUtils.objectToJson(result);
}
}
}
textarea控件
。是一個富文本編輯器的載體
。相似數據源。同步
到textarea控件中。 即將編輯器中的數據放到textarea
中,最終提交數據是textarea提交到後臺。要求pojo的屬性名稱和input的name屬性值要一致
。TbItem對象
接收表單的商品基本數據
,使用字符串
接收表單中的商品描述的數據
。Incr命令
。推薦使用。暫時還沒用到。工具類IDUtils
生成商品id。安裝到本地倉庫。向tb_item, tb_item_desc表中插入數據,可使用逆向工程生成的代碼。
/**
* 根據商品的基礎數據和商品的描述信息插入商品(插入商品表和商品描述表)
* @param item
* @param desc
* @return
*/
TaotaoResult saveItem(TbItem item, String desc);
@Override
public TaotaoResult saveItem(TbItem item, String desc) {
// 一、生成商品id,本例中使用工具類IDUtils生成商品id
Long itemId = IDUtils.genItemId();
item.setId(itemId);
// 二、補全商品表TbItem的其餘屬性
// 商品狀態,1-正常,2-下架,3-刪除
item.setStatus((byte) 1);
Date date = new Date();
item.setCreated(date);
item.setUpdated(date);
// 三、向商品表中插入數據
itemMapper.insert(item);
// 四、建立一個商品描述表TbItemDesc對象
TbItemDesc itemDesc = new TbItemDesc();
// 五、補全商品描述表TbItemDesc的其餘屬性
itemDesc.setItemId(itemId);
itemDesc.setItemDesc(desc);
itemDesc.setCreated(date);
itemDesc.setUpdated(date);
// 六、向商品描述表中插入數據
itemDescMapper.insert(itemDesc);
// 七、返回TaotaoResult.ok()
return TaotaoResult.ok();
}
在taotao-manager-service工程中的applicationContext-service.xml中發佈服務:
在taotao-manager-web工程中的springmvc.xml中引用服務:
請求的url:/item/save
參數:TbItem item, String desc
返回值:TaotaoResult
/**
* 根據商品的基礎數據和商品的描述信息添加商品,返回服務器插入成功的響應狀態
* @param item
* @param desc
* @return
*/
@RequestMapping(value="/item/save", method=RequestMethod.POST)
@ResponseBody
public TaotaoResult savetItem(TbItem item, String desc) {
TaotaoResult result = itemService.saveItem(item, desc);
return result;
}
商品修改、商品刪除、上架下架。