從零開始寫javaweb框架筆記9-細節完善與程式碼優化-完善控制器層
在這一小節中,我們開始寫jsp頁面
開啟/WEB-INF/view/customer.jsp檔案,完成如下程式碼:
<%-- Created by IntelliJ IDEA. User: jack Date: 2015/12/5 Time: 23:02 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:set var="BASE" value="${pageContext.request.contextPath}"/> <html> <head> <title>客戶管理</title> </head> <body> <h1>客戶列表</h1> <table> <thead> <tr> <th>客戶名稱</th> <th>聯絡人</th> <th>電話號碼</th> <th>郵箱地址</th> <th>操作</th> </tr> </thead> <tbody> <c:forEach var="customer" items="${customerList}"> <tr> <td>${customer.name}</td> <td>${customer.contact}</td> <td>${customer.telephone}</td> <td>${customer.email}</td> <td> <a href="${BASE}/customer_edit?id=${customer.id}">編輯</a> <a href="${BASE}/customer_delete?id=${customer.id}">刪除</a> </td> </tr> </c:forEach> </tbody> </table> </body> </html>
小技巧:在IDEA中,查詢檔案三種方法,ctrl+n,根據java類名進行查詢,ctrl+shift+n,根據任意檔名進行查詢,在project目錄樹中,使用ctrl+shift+f在指定路徑下查詢檔案
我們已經完成了第一個jsp頁面的編寫了,現在我們部署到Tomcat中,具體的部署方法,參考http://blog.csdn.net/j903829182/article/details/50097471,然後再IDEA中啟動tomcat,我在啟動tomcat的時候,爆錯了,錯誤關鍵資訊如下:
Caused by: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed
to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/chapter2]]
Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> customer_create in servlet mapping
然後,我通過網上找資料,看到資料上說是web.xml裡面的路徑配置有問題,但是我這裡使用的是servlet3,沒有在web.xml裡面配置啊, 但是我使用了annotation來進行配置,當看到Invalid <url-pattern> customer_create in servlet mapping這個資訊的時候,我就想是不是以前customer_create裡面的註解配置,錯誤了,然後仔細檢查的確配置錯誤了,
正確的應該是:
@WebServlet("/customer_create")我配置錯誤的為:
@WebServlet("customer_create")
解決錯誤後,開啟瀏覽器,輸入地址http://localhost:8080/chapter2/customer然後,我們就會看到下面的介面,如下圖:
現在CutomerServlet已經開發完畢了,但是還有四個Servlet等待著我們去完成。
我們可以想象,隨著業務需求的不斷擴充套件,請求個數一定會不段增長,那麼Servlet的數量一定會不斷增多,勢必會增加我們日後維護的工作量,因此我們應該想一個辦法減少Servlet的數量。
是否將同一個業務模組的Servlet合併到一個類中去呢?比如我們正在開發的這五個Servlet:CustomerServlet,CustomerShowServlet,CustomerCreateServlet,CustomerEditServlet,CustomerDeleteServlet,合併到一個名為CustomerController類中。
也就是說,在CustomerController中包含了若干方法,每個方法都處理一種特定的請求,就像下面這樣:
package org.jack.com.controller;
/**
* Created by jack on 2016/1/10.
*/
import org.jack.com.model.Customer;
import org.jack.com.service.CustomerService;
import java.util.List;
import java.util.Map;
/**
* 處理客戶管理相關請求
*/
@Controller
public class CustomerController {
@Inject
private CustomerService customerService;
/**
* 進入客戶列表介面
*/
@Action("get:/customer")
public view index(Param param){
List<Customer> customerList=customerService.getCustomerList();
return new view("customer_show.jsp").addModel("customerList",customerList);
}
/**
* 顯示客戶資訊
*/
@Action("get:/customer_show")
public view show(Param param){
long id=param.getLong("id");
Customer customer=customerService.getCustomer(id);
return new view("customer_show.jsp").addModel("customer",customer);
}
/**
* 進入建立客戶 介面
*/
@Action("get:/customer_create")
public view create(Param param){
return new view("customer_create.jsp");
}
/**
* 處理建立客戶請求
*/
@Action("post:/customer_create")
public Data createSubmit(Param param){
Map<String,Object> fieldMap=param.getMap();
boolean result=customerService.createCustomer(fieldMap);
return new Data(result);
}
/**
* 進入編輯客戶介面
*/
@Action("get:/customer_edit")
public view edit(Param param){
long id=param.getLong("id");
Customer customer=customerService.getCustomer(id);
return new View("customer_edit.jsp").addModel("customer",customer);
}
/**
* 處理編輯客戶請求
*/
@Action("put:/customer_edit")
public Data editSubmit(Param param){
long id=param.getLong("id");
Map<String,Object> fieldMap=param.getMap();
boolean result=customerService.updateCustomer(id,fieldMap);
return new Data(result);
}
/**
* 處理編輯客戶請求
*/
@Action("delete:/customer_edit")
public view delete(Param param){
long id=param.getLong("id");
boolean result=customerService.deleteCustomer(id);
return new Data(result);
}
}
1)在控制器類上,使用Controller註解,標明該類是一個控制器。
2)在成員變數上,使用Inject註解,自動建立該成員變數的例項,有一種流行的名稱叫注入
3)在控制器類中包含若干方法(稱為Action),每個方法都會只用Get/Post/Put/Delete註解,用於指定請求型別與請求路徑。
4)在Action的引數中,通過Param物件封裝所有請求引數,可根據getLong/getFieldMap等方法獲取具體型別或所有的請求引數。
5)在Action的返回值,使用View封裝一個jsp頁面,使用Data封裝一個JSON資料。
有了這個CustomerController以後,Servlet數量一下子就降下來了,而且還遮蔽了技術細節,這種方式將MVC架構變得更加輕量級。那怎麼開發這樣一個輕量級的框架呢?在後面我們我們來慢慢學習。
總結:在前面,我們針對業務需求進行了簡單的分析,找出了核心的功能點,並設計了相關的用例額,根據業務實體確定了表結構,通過介面原型設計了URL規範這些設計工作可以用來以後的開發中來。在開發階段,我們藉助了MVC架構,將開發過程分解。我們對服務層進行了細化,使用Apache Commons DbUtils類庫開發了一個輕量級JDBC框架。此外還是用了JUnit對每個服務方法進行了單元測試,並提供了一種資料庫初始化的解決方案,讓單元測試更加具備可測性。針對一個具體業務需求,從後端到前端一次整合,使資料得到了實現,但介面有些醜陋,在以後的我會慢慢的完善,使用bootstrap來美化介面。