在JSP開發中模擬.NETWebForm(一)
|
WebForm是事件驅動的,控件狀態可以在http請求之間自動保持,并且使用后置代碼很好地實現了頁面外觀與頁面邏輯控制的分離,一改以往html,服務器段代碼、javaScript混雜在一起的web開發方式。stucts提供了大量的定制標簽,由tag、form、bean、action及配置文件構建了一個優秀的MVC模式的web開發方式。但相比較其WebForm來,竊以為stucts更為復雜,需要協同工作的元素較多,解決問題的效果不如WebForm顯著(僅是個人看法)。
在現實開發中,常常需要在某個頁面中處理很多Form控件,且要處理這個頁面可能引發的多個事件,在事件觸發后,又請求同一個頁面,又需要在請求之間保持狀態,在頁面中處理所有這些,真實不勝其煩。受到WebForm啟發,我在用JSP進行開發時,借鑒了了其一些思想。本質上我們就是想讓頁面顯示代碼與頁面控制代碼分離,要作到這一點并不困難,有很多辦法。
可以為頁面定義一個“頁面處理器(PageHandler)”,它類似WebForm的后置代碼,它的接口基本是下面這個樣子:
| public class PageHandler { protected HttpServletRequest request; protected HttpServletResponse response; protected JspWriter out; protected PageContext pageContext; protected HttpSession session = null; protected ServletContext application = null; protected ServletConfig config = null; protected String event_action = null; //頁面事件 protected String event_params = null; //頁面參數 //取得操作頁面的基本組件 public PageHandler(PageContext page) { this.pageContext = page; this.request = (HttpServletRequest) pageContext.getRequest(); this.response = (HttpServletResponse) pageContext.getResponse(); this.pageContext = page; out = pageContext.getOut(); application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); try{ request.setCharacterEncoding("gb2312");//設定頁面編碼 } catch(Exception e) { e.printStackTrace(); } } //初始化頁面的參數,具體的頁面處理器類可以重寫這 //個方法進行頁面初始化 protected void onLoad() throws Exception { } //根據頁面指定的事件進行處理 private final void eventBind() throws Exception { //event_action從從頁面的名為event_action的hidden字段取得,它意為事件的稱, //當此事件觸發時,他會尋找在"頁面處理器類中"與event_action同名的方法加 // 以調用。 if (event_action != null && !event_action.equals(Format.Empty)) { event_params = request.getParameter("parameters"); //事件參數參數,從頁面 //的名為parameters的hidden字段取得 if (paramTypes[0] == null) { paramTypes[0] = Class.forName("java.lang.String"); } Object paramValues[] = new Object[1]; paramValues[0] = event_params; Method method = null; try { method = this.getClass().getDeclaredMethod(event_action, paramTypes); method.setAccessible(true); } catch (Exception e) { throw new UserException("系統缺少對您的請求的處理機制: + event_action); } if (method != null) { method.invoke(this, paramValues); //調用web時間 } } } //處理頁面 public void process() throws Exception { try { event_action = request.getParameter("action"); //得頁面事件 onLoad();//頁面加載時的初始化 eventBind();//處理事件 } catch (Exception e) { e.printStackTrace(); /////////////// Format.alert(out, "發生了未知錯誤:" + Format.getString(e.getMessage())); } } } |
當然,實用的 PageHandler應提供更為復雜的功能。
具體的頁面處理器類從此類繼承下來,現在,我們用一個簡單的例子說明頁面處理器的用法:假設有這樣一個頁面,有一個文本框要求用戶輸入一個數字,有兩個按鈕,點擊一個要求計算出用戶輸入數字的2倍,點擊另外一個按鈕要求計算出用戶輸入數字的10倍。再假設此頁面的頁面處理器類為JspTest.
| //test.jsp <%@ page contentType="text/html; charset=GB2312" %> <%@ page import="youpackage.JspTest" %> <% JspTest handler=new JspTest(pageContext); handler.process();//調用頁面處理器 String formAction=request.getRequestURI()+"?"+request.getQueryString(); %> <html> <head> <title>測試頁面處理器</title> <script language="javascript"> function on_event(action,params) { window.form1.action.value=action; window.form1.parameters.value=params; window.form1.submit(); } </script> </head> <body bgcolor="#ffffff"> <form name="form1" method="post" action="<%=formAction%>"> 請輸入數字:<input type="text" name="t_value" value="<%=handler.t_value%>"> <br><br> <font color="red"><%=handler.result%></font> <br><br> <input type="button" name="b1" value="2倍" onclick="on_event('onTwo','')"> <input type="button" name="b2" value="10倍" onclick="on_event('onTen','')"> <input type="hidden" name="action" value=""/> <input type="hidden" name="parameters" value=""/> </form> </body> </html> 則,我們為以上頁面定義其頁面處理器:JspTest //JspTest.java public class JspTest extends PageHandler { //定義頁面變量 public int t_value;//用戶輸入的整數 public String result;//存儲計算結果 public JspTest(PageContext page) { super(page); } protected void onLoad() throws Exception { t_value=0; result=""; //在實際應用中,這里應作許多的初始化工作(如,得到頁面參數) } //雙倍 private void onTwo(String str_params) throws Exception { try { t_value=Integer.parseInt(request.getParameter("t_value")); } catch(Exception e) { out.println("<script language='javaScript'>alert('您輸入的不是有效的整數.');</script>"); } int i=2*t_value; result="計算結果為:"+i; } //10倍 private void onTen(String str_params) throws Exception { try { t_value=Integer.parseInt(request.getParameter("t_value")); } catch(Exception e) { out.println("<script language='javaScript'>alert('您輸入的不是有效的整數.');</script>"); } int i=10*t_value; result="計算結果為:"+i; } } |
WebForm的基本思想也就在于此,當然,WebForm中的服務器端控件的狀態可以自動保持(而我們的實現為保持狀態還需作一些工作),WebForm的控件屬性可以在后置代碼中進行操作,服務器端事件可以在后置代碼中進行邦定,服務器端控件支持數據邦定等等,我們的實現還無法做到。
如果能在Jsp中定義類似服務器端控件的東東,以上的功能在Jsp中可以得以實現。