通過Struts瞭解MVC框架,兼說如何在面試中利用Struts證明自己

来源:http://www.cnblogs.com/JavaArchitect/archive/2017/10/31/7759769.html
-Advertisement-
Play Games

雖然目前Struts MVC框架不怎麼用了,但它確是個能幫助大家很好地入門Web MVC框架,而且,一些歷史項目可能還用Struts,反正技多不壓身,大家如果能在面試中通過項目證明自己Struts這塊也很熟,這也是個非常好的加分項。 這裡我們就從搭建Struts基本框架入手,再深入講解些面... ...


    雖然目前Struts MVC框架不怎麼用了,但它確是個能幫助大家很好地入門Web MVC框架,而且,一些歷史項目可能還用Struts,反正技多不壓身,大家如果能在面試中通過項目證明自己Struts這塊也很熟,這也是個非常好的加分項。

    這裡我們就從搭建Struts基本框架入手,再深入講解些面試中常會靠到的Struts知識點,本文的文字和案例根據java web輕量級開發麵試教程改編。

///////////////////////////////////////////////////////////////////////////////////////

1 搭建Struts框架

1.1 開發前端的JSP代碼

    創建一個Java Web項目,名為strutsDemo,在其中的WebRoot目錄下,創建前端的JSP代碼calSum.jsp。    

 1 1    <%@ page language="java" pageEncoding="GBK" %>
 2 2    <%@ taglib prefix="s" uri="/struts-tags"%>
 3 3    <html>
 4 4    <head>
 5 5    <title>輸入操作數</title>
 6 6    </head>
 7 7    <body>
 8 8    求和<br/>
 9 9    <s:form action="mystruts/calSum" >
10 10    <s:textfield name="num1" label="數1"/>
11 11    <s:textfield name="num2"  label="數2" />
12 12    <s:submit value="求和" />
13 13    </s:form>
14 14    </body>
15 15    </html>

    這個頁面的效果下圖所示。

 

    在第2行里引入了Struts的標簽,首碼是s,所以可以用s:form和s:textfield來定義form和文本框。

    在第9行到第13行的form里,定義了兩個輸入框和一個提交按鈕。當用戶輸入兩個數字後,單擊“求和”按鈕後,本頁面將根據定義在第9行的定義,跳轉到mystruts/calSum.action。

1.2 在web.xml里聲明使用Struts

    如果要使用基於Struts的MVC,則必須要在web.xml里聲明,否則系統伺服器是不會知道在項目里用到了基於Struts的MVC處理器。web.xml的代碼如下。

1    <?xml version="1.0" encoding="UTF-8"?>
2    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
3    <filter>
4    <filter-name>struts2</filter-name>
5    <filter-class>
6            org.apache.struts2.dispatcher.FilterDispatcher            
7    </filter-class>
8    </filter>
9    <filter-mapping>
10    <filter-name>struts2</filter-name>
11    <url-pattern>/*</url-pattern>
12    </filter-mapping>
13    </web-app>

    從第2行到第13行之間的web-app元素里,我們聲明瞭兩件事:

    (1)通過第11行的url-pattern,說明/*,也就是任何請求,都將由名為struts2的過濾器來處理。

    (2)在第3行到第8行之間,指定了struts2這個過濾器它的後臺處理類。

綜合上述兩點可知,本項目的任何請求,都將由Struts的後臺處理類來處理。     

1.3 配置struts.xml文件 

    在calSum.jsp里指定了form跳轉的目的地。

    <s:form action="mystruts/calSum" >

    那麼這個目的地究竟是哪裡?一起來看一下struts.xml這個配置文件。    

1    <?xml version="1.0" encoding="UTF-8" ?>
2    <!DOCTYPE struts PUBLIC
      "-//Apache Software Foundation//DTD Struts Configuration2.0//EN"
      "http://struts.apache.org/dtds/struts-2.0.dtd">
3    <struts>
4    <package name="struts2" namespace="/mystruts"
5       extends="struts-default">
6    <action name="calSum" class="action.myAction">
7    <result name="Positive">/positive.jsp</result>
8    <result name="Negative">/negative.jsp</result>
9    </action>
10    </package>
11    </struts>   

    在第4和第5行里,能看到名為calSum的action處於/mystruts這個命名空間里,它所對應的是action.myAction這個處理類。也就是說,calSum.jsp的請求最終是由action.myAction接收和處理。

1.4 開發Action類

     隨後開發myAction.java,它是放在action這個package下的。    

1	package action;
2	import com.opensymphony.xwork2.ActionSupport;
3	public class myAction extends ActionSupport
4	{
5	    private int num1;
6	    private int num2;
7	
8	    public String execute() throws Exception
9	    {
10		// 如果和大於等於0,則跳到positive.jsp頁面
11		if (getSum() >= 0)  
12	        {
13	            return "Positive";
14	        }
15		//否則跳到negative.jsp頁面
16	        else  
17	        {
18	            return "Negative";
19	        }
20	    }   
21	    public int getNum1() {
22			return num1;
23		}
24		public void setNum1(int num1) {
25			this.num1 = num1;
26		}
27		public int getNum2() {
28			return num2;
29		}
30		public void setNum2(int num2) {
31			this.num2 = num2;
32		}
33		public int getSum()
34	    {
35	        return num1 + num2;  // 計算兩個整數的代碼數和
36	    }
37	}

    作為一個Struts的Action,本類繼承了ActionSupport類。當一個請求最終到達本Action時,如果沒有額外的配置,就會如同本類一樣,由execute方法來處理請求。

    在第8行的execute方法里可能看到,如果兩個數的和大於0,則返回Positive字元串,反之則返回Negative。這兩個返回是和struts.xml里的配置相對應的。

    在struts.xml的第6行和第7行里,看到有如下的配置。

    <result name="Positive">/positive.jsp</result>

    <result name="Negative">/negative.jsp</result>

    這說明根據不同的字元串,Struts處理容器將會跳轉到兩個不同的jsp里。在這個Action代碼里,並沒有給num1和num2賦值,這是因為它們和calSum.jsp里form中的兩個輸入框同名,所以會自動拿到我們輸入的值。

1.5 開發兩個跳轉結果頁面

    上文提到過,Action的execute方法里返回的不同字元串後,Struts MVC處理器會讀取struts.xml里的配置,並相應地,跳轉到不同的頁面。下麵就來編寫這兩個頁面的代碼。先來看一下positive.jsp。   

1	<%@ page language="java" pageEncoding="GBK"%>
2	<%@ taglib prefix="s" uri="/struts-tags" %>
3	<html>
4	<head>
5	<title>顯示和</title>
6	</head>
7	<body>
8	結果大於或等於0,<h1><s:property value="sum" /></h1>
9	</body>
10	</html>

     這裡的關鍵代碼是在第8行,通過一個Struts的標簽,來獲取在Action里名為”sum”的屬性對象。在myAction.java里,定義了一個getSum的方法,所以就會自動生成一個sum的屬性。結果是兩個操作數之和。

    Negative.jsp代碼和positive.jsp很相似。唯一的差別在第8行,這裡的敘述文字是“結果小於0”。   

1	<%@ page language="java" pageEncoding="GBK"%>
2	<%@ taglib prefix="s" uri="/struts-tags" %>
3	<html>
4	<head>
5	<title>顯示和</title>
6	</head>
7	<body>
8	結果小於0,<h1><s:property value="sum" /></h1>
9	</body>
10	</html>

2 通過運行,瞭解Struts的工作流程

   現在來總結一下整個程式的運行和跳轉流程。

    第一,打開Tomcat伺服器,併在瀏覽器里輸入http://localhost:8080/strutsDemo/calSum.jsp,能看到如下圖所示的頁面

   

    當輸入兩個數字,並單擊“求和”按鈕後,根據如下form里的定義,會跳轉到mystruts/calSum里。

    <s:form action="mystruts/calSum" >    

    第二,根據web.xml的定義,可知這個跳轉請求將由struts來處理。再根據struts.xml的定義,得知這個請求最終將由myAction.java來處理。

    <action name="calSum" class="action.myAction">

        <result name="Positive">/positive.jsp</result>

       <result name="Negative">/negative.jsp</result>

    </action>

    第三,在myAction.java的execute方法里,根據最終sum的值,分別返回兩個不同的字元串,從上文struts.xml片段的第3行和第4行得知,根據兩個不同的返回值,會跳轉到兩個不同的頁面里。

3 和JSP+Servlet+JavaBean框架的比較

    在一個項目里,我們應更關註“業務該怎麼處理”這個問題,而不應把大多數精力放在調試JSP到Servlet之類的跳轉上。

    Struts給我們提供了一套跳轉機制,我們可以簡單地通過編寫struts.xml和web.xml,就能比較省心地實現從前端JSP跳轉到具體業務處理類的功能。而且,也只需在Action類里編寫返回字元串,同時在struts.xml里編寫返回字元串和跳轉頁面的對應關係,就能根據業務執行結果方便地跳轉回前端頁面。

    Struts框架是基於MVC的,它的View部分主要由JSP頁面實現。Controler部分主要由Action類來承擔,而Model部分主要由ActionForm組成。需要說明的是,在Struts2.0以上的版本里,開發者不需要額外定義ActionForm,由用戶在前端Form里傳入的數據將被自動封裝成ActionFrom對象,並被最終轉發給Action。

    通過下表對比一下Struts和前文提到的JSP+Servlet+JavaBean框架,綜合各項對比的指標,Struts略優於JSP+Servlet+JavaBean框架。

比較項

Struts

JSP+Servlet+JavaBean

結論

如何在後端接收前端傳來的參數

參數組裝成ActionForm,並自動發送到Action里

需要在Servlet里編寫接收參數的代碼

Struts比較省心

如何把前端的請求發送到合適的處理頁面

可以在struts.xml里統一定義請求和處理類的對應關係

可以在web.xml里統一定義請求和處理類的對應關係

基本持平

後端處理請求的方式

定義在Action里

大多定義在Servlet類的doPost或doGet方法里

基本持平

如何把後端的處理結果再回傳到前端

可以在struts.xml里統一地定義處理結果和返回頁面的對應關係

需要在Servlet里手動地跳轉

Struts略優

項目的開發方式

程式員的工作量比較少,在必要的地方(比如Action類和Struts.xml)里填寫必要的代碼即可,Struts處理器能方便地實現MVC之間的跳轉

程式員可能得操心必要的細節,比如Servlet里如何接收參數,如何跳轉到前端,等等

Struts的開發流程比較省心

4 對Struts框架的進一步瞭解

    Struts作為一個基於MVC的框架,能很好地處理跳轉業務,能讓程式員把精力更多地集中到業務開發上,通過它,程式員能很好地瞭解框架編程的思路和一般方法。

    不過任何框架都不是十全十美的,當你比較熟悉Struts框架後,一定能感受到它在項目開發里的一些缺陷。對於Struts的局限性,不同的人有不同的觀點。但是請大家記住,在面試時,當你結合你的項目自信地說出Struts框架的局限時,即使面試官和你的觀點不一致,他也一定會認為你對Struts有足夠的認識。這裡羅列出一些局限性供大家參考,如表所示。

局限性

結合項目說明

為每個請求創建一個Action

Struts2里,會為每個http請求實例化一個Action 對象,這對處理高併發會有些難度

對Action 執行前和後的處理支持不大好

比如每次進到Action前我們需要列印記憶體使用量,執行後需要記錄跳轉目標URL,這個當然可以直接寫到Action里,但大家比較下Spring的AOP處理方式,就會發現單純把前後處理寫到Action里有什麼不足

對跳轉的支持

如果在一個Action里,根據處理結果可能會跳轉到10個頁面,那麼代碼可能會比較煩瑣。而且一旦跳轉目標頁面出現變更,比如換了目錄,那麼在修改配置文件後,可能要求重新部署和重啟Web伺服器,無法實現輕量級修改

安全性上的瑕疵

我們可以通過類似方式直接執行Action里的方法:http://url:8080/proName/userLogin!list

但事實上,該系統需要用戶先登錄才能開放用戶列表。雖然我們可以通過定義攔截器來彌補這個缺陷,但畢竟屬於額外的工作量

屬於侵入式

在使用Struts時,需要繼承struts的類,而且要編寫execute方法。這樣Struts框架就侵入到項目里了。比如做的是銀行業務,如果哪天要把這套業務移植到其他Spring等框架項目里,可能工作量就比較大了

5 關於Struts面試點的歸納

   Struts的地位似乎有些尷尬,一些小型(比如10個頁面左右)的商業項目可能直接會用JSP+Servlet+JavaBean+DB的開發模式,一些大型基於企業級的項目往往採用Spring+MyBatis的框架。

    我們在面試初級程式員時,如果候選人沒有在商業項目里用過Struts框架,這很正常,如果他在學校或者培訓機構學過Struts,這或許也可以成為一個加分項。但如果我們看到某人在最近的商業項目里用過,那麼就會詳細問原因,為什麼這個公司現在還要用Struts框架?反而有不少人,在這個問題上會弄巧成拙。我們聽到的最多的合理回答是,基於某種原因,比如歷史原因或者客戶要求,這個項目還是得用Struts框架。

    具體到面試題,大家可以從網上找,在必要的時候,大家也可以多多益善地突擊準備。我們給大家推薦回答問題的方式是“結合項目”,請大家看如下的問題點。

    第一,說明在這個項目里,都用到了Struts的哪些組件,比如攔截器或者驗證器,你是怎麼用的?

    第二,結合項目,說明自己做了哪些工作,比如在Action里,你怎麼和業務以及資料庫代碼耦合?

    第三,能結合項目,告訴考官一些技術細節,比如攔截器是怎麼用的,在該項目里結合一個需求,告訴考官攔截器的工作流程和開發方式。或者結合項目說明下驗證器的用法。

    也就是說,任何技術都別停留在紙上,需要結合項目說明。

    第四,說明使用Struts框架給這個項目帶來哪些痛點?

    第五,和Spring框架相比,你感覺各自有什麼優缺點,請結合項目說明,不要空談。

    當你學好了Spring框架後就知道該怎麼說?

    第六,你的項目經常會擴展,業務實現方式也經常會變更,結合Struts框架說明一旦出現變更了你需要做哪些事?

    比如需要更改業務,你該更改哪些文件?一旦更改了代碼,如何部署到伺服器上?

    第七,這個項目的訪問量是多少?最高的併發訪問量能達到多少?Struts框架能否很好地處理高併發的情況?

    關於常用的技術問題,在本章里都已經提到,我們通過如下問題點來對本章做個總結。

    ①在Struts2里,如何實現一個Action?

    ②怎麼指定進入Action後該調用哪個方法?

    ③定義驗證器的步驟是什麼?

    ④定義攔截器的步驟是什麼?

    ⑤Struts2中的type類型有哪些?如果不寫type,預設是什麼?

    ⑥如何通過配置type類型,實現一個Action往另外一個Action的跳轉?

    ⑦描述下Struts MVC的工作流程和開發模式。

    ⑧和JSP+Servlet+JavaBean的開發模式相比,Struts MVC有哪些好處,同時,說明下Struts框架有哪些不足。     

    

    

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...