日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

自己动手写一个Struts2

發布時間:2025/6/15 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自己动手写一个Struts2 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用Struts2或webwork2有一段時間了,想把Struts2框架的思路簡單的與大家分享一下,之前我是看過Struts2源代碼的,所以本文算是它的一個功能非常有限的壓縮版本。我也不打算重復發明輪子,只想讓Struts2或Webwork2的新手更多的了解框架本身,而不僅僅是應用。廢話少說,開始吧。

?

?

本文采用基本Xml來配置Action,如果有時間會繼續寫Annotation的實現。Xml文件結構與Struts2的配置文件struts.xml幾乎一樣,這樣大家都比較熟悉,不過我簡寫了某些地方:

?

Struts.xml

Xml代碼??
  • <?xml?version="1.0"?encoding="UTF-8"??>??
  • <!--?為簡化框架,package的屬性都沒有實現;而且所有的元素都是簡化版的?-->??
  • <struts>??
  • ????<package>??
  • ????????<action?name="hello"?method="hello"??
  • ????????????class="com.leo.action.HelloAction">??
  • ????????????<result?name="success">/index.jsp</result>??
  • ????????</action>??
  • ????</package>??
  • </struts>??
  • ?

    ?

    是不是很熟悉啊,不過為了簡單我都給簡化了,否則這是一個沒有盡頭的工作。核心部分仍然是Filter,Struts2所有工作都是通過一個Filter來完成的(struts1.*是通過一個Action實現的)。我們先來看代碼:

    ?

    Java代碼??
  • public?class?StrutsFilter?implements?Filter?{??
  • ????public?void?doFilter(ServletRequest?req,?ServletResponse?res,??
  • ????????????FilterChain?chain)?throws?IOException,?ServletException?{??
  • ????????//?TODO?Auto-generated?method?stub??
  • ????????HttpServletRequest?request?=?(HttpServletRequest)?req;??
  • ????????HttpServletResponse?response?=?(HttpServletResponse)?res;??
  • ????????ServletContext?servletContext?=?filterConfig.getServletContext();??
  • ????????//?解析Request的URL和傳過來的參數??
  • ????????String?actionName?=?StringUtil.parseServletPath(request??
  • ????????????????.getServletPath());??
  • ??
  • ????????//?如果后綴不為.action,那么直接放過,不進行攔截??
  • ????????if?(StringUtil.isEmpty(actionName))?{??
  • ????????????chain.doFilter(request,?response);??
  • ????????}?else?{??
  • ????????????//?解析得到ActionClass,里面包括Action的類全名,返回頁面值,Action執行的方法??
  • ????????????ActionClass?clas?=?this.getActionClass(actionName);??
  • ????????????//?得到頁面的所有parameters參數(沒考慮上傳情況)??
  • ????????????Map<String,?String[]>?params?=?request.getParameterMap();??
  • ????????????//?為要調用的Action的set**方法設值,并返回要調用的Action對象本身??
  • ????????????setBeforeActionValue(clas,?params);??
  • ????????????//?調用的Action執行方法,并返回值設置在request域中??
  • ????????????setResultValue(clas,?request);??
  • ????????????//?返回相應的JSP頁面??
  • ????????????servletContext.getRequestDispatcher(clas.getResult()).forward(??
  • ????????????????????request,?response);??
  • ????????}??
  • ????}??
  • }??
  • ?

    ?沒錯一些因果都因doFilter方法而起。我的作法是:

    ?

    • 解析URL路徑,從而得到相應action在struts.xml配置文件中所配置的方法。如果不為合法的action后綴,直接chain.doFilter(request, response)放行。
    • 將URL上的參數通過request.getParameterMap()取出,在調用action執行方法之前,將具有set**屬性的字段賦值。這里利用了反射。
    • 繼續利用反射,執行Action的方法。結束前將具有get**屬性的字段存于request域中,供頁面使用。大家記得在每次執行Action的方法時都會返回一個String字符串,比如SUCCESS,INPUT,ERROR等,我們可以將這個值與struts.xml的<result name="success" ....>/index.jsp</result> 結點進行匹配,取出返回頁面/index.jsp
    • 一切準備就緒后,調用servletContext.getRequestDispatcher().forward()方法到相應的頁面上去。

    這就是大概的流程。因為是一個入門的框架所以很不完善,攔截器,result type的各種類型都沒有去實現,因為我壓根沒想過要重復發明輪子。好,我們開始一步一步的看。

    ?

    ?

    ?

    我們先來看這一句:ActionClass clas = this.getActionClass(actionName);
    其中ActionClass的結構如下:

    ?

    Java代碼??
  • public?class?ActionClass?{??
  • ????/**?
  • ?????*?類名?
  • ?????*/??
  • ????private?String?className;??
  • ????/**?
  • ?????*?要調用的方法名?
  • ?????*/??
  • ????private?String?method;??
  • ????/**?
  • ?????*?返回結果頁面?
  • ?????*/??
  • ????private?String?result;??
  • ????/**?
  • ?????*?臨時存儲Action下的所有result結點?
  • ?????*/??
  • ????private?List<Element>?elements?=?new?ArrayList<Element>();??
  • ??
  • ????/**?
  • ?????*?要調用的Action本身?
  • ?????*/??
  • ????private?Object?action;??
  • ??
  • ????//省略所有的set,get方法??
  • }???
  • ?

    ActionClass主要是用來存放解析struts.xml文件一些有用的值,以及反射時所調用的Action本身對象,其實就是一個簡單的JavaBean,存儲臨信息。

    ?

    ?

    getActionClass(actionName)方法就是將URL上的actionName取出與struts.xml中的<action>結點匹配,可以得到Action的類全名,Action所調用的具體哪個方法名,Action的所有result結點(因為方法還沒有執行,還不知道是具體哪一個result結點,所以先存起來,后面來解析)分別存在ActionClass對象中相應的屬性中去。具體的解析代碼我就不打出來了,否則文章太長。

    ?

    ?

    再來看看setBeforeActionValue(clas, params)這一句。其實就是將得到的ActionClass對象與提交的參數全部傳進去,給Action的那些set屬性賦值:

    ?

    Java代碼??
  • /**?
  • ?????*?調用Action,并執行Action的無參方法?
  • ?????*??
  • ?????*?@param?actionClass?
  • ?????*?@param?request.getParameterMap()?
  • ?????*?@return?
  • ?????*/??
  • ????public?Object?setActionValues(ActionClass?actionClass,??
  • ????????????Map<String,?String[]>?params)?{??
  • ????????try?{??
  • ????????????//?得到Action的Class,并根據無參構造函數生成一個Action對象??
  • ????????????Class?clas?=?Class.forName(actionClass.getClassName());??
  • ????????????Object?obj?=?clas.newInstance();??
  • ??
  • ????????????if?(params?!=?null?&&?params.size()?>?0)?{??
  • ????????????????Iterator<String>?it?=?params.keySet().iterator();??
  • ????????????????while?(it.hasNext())?{??
  • ????????????????????String?key?=?it.next();??
  • ????????????????????String[]?value?=?params.get(key);??
  • ????????????????????String?upperFirstLetter?=?key.substring(0,?1).toUpperCase();??
  • ????????????????????//?獲得和屬性對應的setXXX()方法的名字??
  • ????????????????????String?setMethodName?=?"set"?+?upperFirstLetter??
  • ????????????????????????????+?key.substring(1);??
  • ????????????????????Method?method?=?null;??
  • ????????????????????//?看看該頁面提交的參數名中,是否在Action有set方法??
  • ????????????????????try?{??
  • ????????????????????????method?=?clas.getMethod(setMethodName,??
  • ????????????????????????????????new?Class[]?{?String.class?});??
  • ????????????????????}?catch?(NoSuchMethodException?e)?{??
  • ????????????????????????System.out.println("警告?"?+?actionClass.getClassName()??
  • ????????????????????????????????+?"."?+?setMethodName?+?"("??
  • ????????????????????????????????+?String.class.getName()?+?")?不存在");??
  • ????????????????????}??
  • ????????????????????if?(method?!=?null)?{??
  • ????????????????????????//?如果有set方法,就調用set方法,進行賦值操作??
  • ????????????????????????String?result?=?StringUtil.StringArrayToString(value);??
  • ????????????????????????method.invoke(obj,?new?String[]?{?result?});??
  • ????????????????????}??
  • ??
  • ????????????????}??
  • ??
  • ????????????}??
  • ????????????return?obj;??
  • ????????......??
  • ????}??
  • ?

    ?

    這樣就順利的將頁面的值賦給了Action的相應屬性,接下來就是Action調用工作了。通過setActionValues方法,我們已經可以得到Action對象本身了,可以存在ActionClass對象clas中去,我們直接調用setResultValue(clas, request)在Action執行后,同時也把有get方法的屬性一并存于request域中:

    ?

    ?

    Java代碼??
  • /**?
  • ?????*?調用Action,并執行Action的無參方法?
  • ?????*??
  • ?????*?@param?actionClass?
  • ?????*?@param?obj?
  • ?????*????????????要處理的對象?
  • ?????*?@return?
  • ?????*/??
  • ????public?Object?invokeAction(ActionClass?actionClass)?{??
  • ????????try?{??
  • ????????????Object?obj?=?actionClass.getAction();??
  • ????????????Class?clas?=?obj.getClass();??
  • ????????????Method?method?=?clas.getMethod(actionClass.getMethod(),?null);??
  • ????????????String?result?=?(String)?method.invoke(obj,?null);??
  • ????????????this.setInvokeResult(result,?actionClass);??
  • ????????????actionClass.setAction(obj);??
  • ????????????return?obj;??
  • ????????????????????????????????????????????????......??
  • ????????}??
  • ????}??
  • ?

    很簡單的代碼——調用Action那個無參執行方法,得到返回String類型的返回結果,然后我們可以再次利用ActionClass將最終的返回結果也給解析出來,看this.setInvokeResult(result, actionClass)方法

    ?

    ?

    Java代碼??
  • /**?
  • ?????*?匹配<result?name="success">/index.jsp</result>?Xml中的result?
  • ?????*?name屬性,如果匹配成功,設置返回結果"/index.jsp"?
  • ?????*??
  • ?????*?@param?result?
  • ?????*?@param?actionClass?
  • ?????*/??
  • ????private?void?setInvokeResult(String?result,?ActionClass?actionClass)?{??
  • ????????List<Element>?elements?=?actionClass.getElements();??
  • ????????for?(Element?elem?:?elements)?{??
  • ????????????Attribute?name?=?XmlUtil.getAttributeByName(elem,?"name");??
  • ????????????if?(StringUtil.equals(result,?name.getText()))?{??
  • ????????????????actionClass.setResult(elem.getText());??
  • ????????????????return;??
  • ????????????}??
  • ??
  • ????????}??
  • ????????throw?new?RuntimeException("請確定在xml配置文件中是否有名叫?["?+?result??
  • ????????????????+?"] 的返回類型結點?");??
  • ????}??
  • ?

    ?

    ?

    一切大功告成,將剛剛得到的返回結果用servletContext.getRequestDispatcher(clas.getResult()).forward(
    request, response)轉發出去,編碼部分完畢。

    ?

    ?

    別忘記了在web.xml中配置這個Filter:

    ?

    ?

    Xml代碼??
  • <filter>??
  • ????<filter-name>struts</filter-name>??
  • ????<filter-class>com.framework.core.StrutsFilter</filter-class>??
  • </filter>??
  • <filter-mapping>??
  • ????<filter-name>struts</filter-name>??
  • ????<url-pattern>/*</url-pattern>??
  • </filter-mapping>??
  • ?

    ?

    ?

    ?

    最后寫個測試Action吧,就按照本文最開始的那個struts.xml配置編寫HelloAction.java

    ?

    ?

    Java代碼??
  • public?class?HelloAction?{??
  • ??
  • ????private?String?message;??
  • ??
  • ????public?String?hello()?{??
  • ????????message?=?"superleo?"?+?this.message;??
  • ????????return?"success";??
  • ????}??
  • ??
  • ????public?String?getMessage()?{??
  • ????????return?message;??
  • ????}??
  • ??
  • ????public?void?setMessage(String?message)?{??
  • ????????this.message?=?message;??
  • ????}??
  • ??
  • } ?
  • 總結

    以上是生活随笔為你收集整理的自己动手写一个Struts2的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。