JavaWeb企業實戰項目(五):後臺模塊1

1、任務總述

1、權限過濾器
2、查詢所有分類
3、修改分類信息
4、查詢商品信息
5、上傳商品信息(重點)
6、利用工廠模式解耦

2、權限過濾器

應用場景:
  項目運行過程,希望某些資源不能被用戶直接訪問到,只有登錄後纔可以訪問。例如:購物車頁面,購物詳情,購物列表等資源
解決方案:
  創建一個自定義過濾器,在過濾器中爲這些資源分別配置好路徑,在過濾器中判斷用戶是否登錄。登錄成功,放行;沒有登錄,返回提示信息並轉發到提示頁面
步驟實現:
  1、創建過濾器,爲過濾器配置不同的路徑
  2、實現過濾器代碼
  PS:一個過濾器可以配置不同的路徑

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
	//將request轉成HttpServletRequest
	HttpServletRequest myReq = (HttpServletRequest)request;
	//獲取當前session中的user數據
	User user = (User)myReq.getSession().getAttribute("userinfo");
	//如果用戶存在直接放行.不存在跳轉並提示
	if(user!=null){
		chain.doFilter(request, response);
	}else{
		String msg = "請先登錄之後再訪問!";
		request.setAttribute("msg", msg);
		myReq.getRequestDispatcher("/jsp/info.jsp").forward(request, response);
	}
}

3、查看所有分類

複習frameset框架:
其中frameset中的rows是Y軸分佈切割,cols是X軸分佈切割

<frameset rows="30%,60%,*">
	<frame src="work3/input.jsp">
	<frameset cols="50%,50%">
		<frame src="work2/carDemo1.jsp">
		<frame src="work2/carDemo2.jsp">
	</frameset>
	<frame src="6_2.jsp">
</frameset>

dtree組件:
由JS實現樹形菜單組件,開源免費,使用簡單
如何使用
1、導入dtree.js
2、導入dtree.css
3、導入dtree下所有的圖片
4、在頁面中實現以下語句

var d=new dTree(“d”);
d.openAll();  d.closeAll();
//param1: 當前節點id
//param2: 父節點id
//param3: 節點上的文字描述
//param4: 跳轉路徑
//param5: 提示信息
//param6: 發生變化的frame的name屬性值
d.add('010201','0102','分類管理’,'${pageContext.request.contextPath}/admin/category/list.jsp','','mainFrame');

查看所有分類原理分析:
查看所有分類
步驟實現:
1、準備工作
  *_創建AdminCategoryServlet
  *_修改鏈接 left.jsp
  d.add('010201','0102','分類管理','${pageContext.request.contextPath}/AdminCategoryServlet?method=findAllCats','','mainFrame');
2、AdminCategoryServlet -> findAllCats

public String findAllCats(HttpServletRequest request, HttpServletResponse response) throws Exception {
	//調用業務成對象並獲取所有分類
	CategoryService service = new CategoryServiceImpl();
	List<Category> allCats = service.getAllCats();
	//將全部分類信息放入request
	request.setAttribute("allCats", allCats);
	//轉發到/admin/category/list.jsp
	return "/admin/category/list.jsp";
}

3、service&dao(之前就實現過category的業務層和dao層了)
4、在/admin/category/list.jsp獲取分類信息,完成響應
  選中標籤元素Ctrl+K跳到對應尾標籤

<c:forEach items="${allCats}" var="c" varStatus="status">
	<tr onmouseover="this.style.backgroundColor = 'white'"
		onmouseout="this.style.backgroundColor = '#F5FAFE';">
		<td style="CURSOR: hand; HEIGHT: 22px" align="center"
			width="18%">
			${status.count}
		</td>
		<td style="CURSOR: hand; HEIGHT: 22px" align="center"
			width="17%">
			${c.cname}
		</td>
		<td align="center" style="HEIGHT: 22px">
			<a href="edit.jsp">
				<img src="${pageContext.request.contextPath}/img/admin/i_edit.gif" border="0" style="CURSOR: hand">
			</a>
		</td>

		<td align="center" style="HEIGHT: 22px">
			<a href="#">
				<img src="${pageContext.request.contextPath}/img/admin/i_del.gif" width="16" height="16" border="0" style="CURSOR: hand">
			</a>
		</td>
	</tr>
</c:forEach>

4、添加分類信息

頁面跳轉:
1、/admin/category/list.jsp js函數addCategory:
  window.location.href = "${pageContext.request.contextPath}/AdminCategoryServlet?method=addCategoryUI";
2、
/AdminCategoryServlet -> addCategoryUI
  return “/admin/category/add.jsp”;
原理分析:
添加分類信息
步驟實現:
1、/admin/category/add.jsp
  設置form -> method,action
  設置form表單下各種input標籤的name屬性
2、AdminCategoryServlet -> addCategory

public String addCategory(HttpServletRequest request, HttpServletResponse response) throws Exception {
	//獲取到分類名稱cname
	String cname = request.getParameter("cname");
	//創建分類ID,並設置分類對象的屬性
	Category category = new Category();
	category.setCname(cname);
	category.setCid(UUIDUtils.getId());
	//調用業務層添加分類功能
	CategoryService service = new CategoryServiceImpl();
	service.addCategory(category);
	//重定向到查詢全部分類信息
	response.sendRedirect("/store_v5/AdminCategoryServlet?method=findAllCats");
	return null;
}

3、CategoryService -> CategoryDaoImp

@Override
public void addCategory(Category category) throws SQLException {
	dao.addCategory(category);
	Jedis jedis = JedisUtils.getJedis();
	jedis.del("allCats");
	JedisUtils.closeJedis(jedis);
}

PS:在CategoryService及時更新redis中緩存的信息
總結:雖然使用redis可以提升項目性能,但是帶來開發量. 開發中,如果對redis緩存中的數據發生了更新操作,及時更新redis緩存信息,否則會造成數據不統一問題.
刪除分類思路:
問題:刪除分類的時候,由於分類被很多商品所參照,無法刪除
解決方案1
  先刪除所有向關聯的商品信息,刪除分類
解決方案2
  設置所有的商品上cid列的值爲null/其他分類ID
解決方案3
  設計分類表多增加一個列(有效/無效)

5、查看商品信息

原理分析:
查看商品信息
步驟實現:
1、修改連接 left.jsp 中商品管理分類的跳轉鏈接
d.add('010401','0104','商品管理', '/store_v5/AdminProductServlet?method=findAllProductsWithPage&num=1', '提示信息','mainFrame');
2、AdminProductServlet -> findAllProductsWithPage

public String findAllProductsWithPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
	//request獲取當前頁
	String curPage = request.getParameter("num");
	//調用業務層查看全部商品信息返回PageModel
	ProductService service = new ProductServiceImpl();
	PageModel pageModel = service.findAllProductsWithPage(Integer.parseInt(curPage));
	//將pageModel放入request中並轉發到admin/product/list.jsp
	request.setAttribute("page", pageModel);
	return "/admin/product/list.jsp";
}

3、ProductService

@Override
public PageModel findAllProductsWithPage(int curPage) throws SQLException {
	int totalRecords = dao.getAllProductsNum();
	//創建PageModel對象
	PageModel pm = new PageModel(curPage, totalRecords, 6);
	//關聯url和集合
	pm.setUrl("AdminProductServlet?method=findAllProductsWithPage");
	pm.setList(dao.findAllProductsWithPage(pm.getStartIndex(),pm.getPageSize()));
	return pm;
}

4、/admin/product/list.jsp獲取商品信息和分頁數據

6、上傳商品信息原理分析

上傳的準備工作:
1、表單method 必須爲post
2、提供file組件
3、設置form標籤的enctype屬性爲multipart/form-data
  如果沒有設置enctype瀏覽器是無法將文件自身傳遞到服務端
分析上傳時HTTP協議的格式:
POST 目標路徑 HTTP/1.1 + 請求頭 + 請求體
測試(JSP文件):

<form action="TestUpload" enctype="multipart/form-data" method="post">
	name:<input type="text" name="name">
	file:<input type="file" name="file">
	<input type="submit">
</form>

測試(TestUpload文件):

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding("utf-8");
	ServletInputStream inputStream = request.getInputStream();
	int read = -1;
	while((read = inputStream.read())!=-1){
		char c = (char)read;
		System.out.print(c);
	}
}

測試結果大致如下:
-----------------------------7e4b316306d8 爲分割線,分割線之間爲每個具體數據
-----------------------------7e4b316306d8-- 爲結尾分割線
測試結果
測試結論:
1、如果設置了表單form標籤的enctype屬性之後,請求體部分的內容的格式發生更改
2、如果設置了mutipart/form-data,在服務端是無法通過request.getParameter(name);獲取數據,因爲getParameter是典型的獲取鍵值對數據類型(以普通字符流傳輸),而mutipart/form-data則是用字節流傳輸(傳輸文件)
3、可以通過request.getInputStream();獲取請求體部分的數據,手動實現上傳功能是可行的

7、實現上傳商品信息

實現思路:
1、導入commons-fileupload-1.2.1.rar之後
2、執行很簡單的3行語句(包括第三步)
3、獲取到一個集合(對象)
  將每對分割線中間的內容封裝在FileItem對象上.
4、遍歷集合
5、如果當前的FileItem對象是普通項
  將普通項上name屬性的值作爲鍵,將獲取到的內容作爲值,放入MAP{username<==>tom,password<==>1234}
6、如果當前的FileItem對象是上傳項
  通過FileItem獲取到輸入流對象,通過輸入流可以獲取到圖片二進制數據
  在服務端創建一個空文件(後綴必須和上傳到服務端的文件名後綴一致)
  建立和空文件對應的輸出流
  將輸入流中的數據刷到輸出流中
  釋放資源
  向map中存入一個鍵值對的數據userhead<===>/image/11.bmp {username<==>tom,password<==>1234,userhead<===>image/11.bmp}
7、利用BeanUtils將MAP中的數據填充到user對象上
8、調用servcie_dao將user上攜帶的數據存入數據倉庫,重定向到查詢全部商品信息路徑
出現問題:
1、如果文件重名發生覆蓋問題
  UUID
2、同目錄下文件/目錄過多,性能問題
  在images下最多創建16個目錄,任意一個目錄進入之後最多創建16個目錄,最多創建8層目錄。可以創建16^8個目錄
實現代碼:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding("utf-8");
	/*ServletInputStream inputStream = request.getInputStream();
	int read = -1;
	while((read = inputStream.read())!=-1){
		char c = (char)read;
		System.out.print(c);
	}*/
	try {
		//1、執行File3行語句
		DiskFileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload fileUpload = new ServletFileUpload(factory);
		//2、獲取到每一個集合(對象)、創建map、Test
		List<FileItem> items = fileUpload.parseRequest(request);
		Map<String, String> map = new HashMap<String,String>();
		Test user = new Test();
		//3、遍歷集合
		for (FileItem fileItem : items) {
			if(fileItem.isFormField()){//4、當前的Fileitem對象是普通項
				//將普通項上name屬性作爲建,將獲取到的內容作爲值,放入
				map.put(fileItem.getFieldName(), fileItem.getString("utf-8"));
			}else{//5、當前的Fileitem爲上傳項
				//通過Fileitem獲取到輸入流對象,通過輸入流對象獲得二進制數據
				InputStream is = fileItem.getInputStream();
				//獲得一個項目工程的圖片目錄=路徑
				String dirPath = getServletContext().getRealPath("/img/");
				//獲取文件名(個別瀏覽器返回文件絕對路徑,需處理)
				String fileName = fileItem.getName();
				int index = fileName.lastIndexOf("\\");//獲取到最後的'\'下標
				if(index != -1){fileName = fileName.substring(index+1);}//如果存在'\',則截取最後文件名
				//System.out.println(dirPath+"\\"+fileName);	//測試輸出
				//在服務端創建一個空文件
				File file = new File(dirPath, fileName);
				if(!file.exists()){file.createNewFile();}
				//創建和空文件對應的輸出流
				OutputStream os = new FileOutputStream(file);
				//將輸入流中的數據刷到輸出流中
				IOUtils.copy(is, os);
				//釋放資源
				IOUtils.closeQuietly(is);
				IOUtils.closeQuietly(os);
				//向map中存入一個鍵值對的數據
				map.put(fileItem.getFieldName(), file.getPath());
			}
		}
		//6、利用BeanUtils將Map中的數據填充到user對象上
		BeanUtils.populate(user, map);
	} catch (Exception e) {
		e.printStackTrace();
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章