生活随笔
收集整理的這篇文章主要介紹了
自己动手写一个Struts2
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
使用Struts2或webwork2有一段時(shí)間了,想把Struts2框架的思路簡(jiǎn)單的與大家分享一下,之前我是看過(guò)Struts2源代碼的,所以本文算是它的一個(gè)功能非常有限的壓縮版本。我也不打算重復(fù)發(fā)明輪子,只想讓Struts2或Webwork2的新手更多的了解框架本身,而不僅僅是應(yīng)用。廢話少說(shuō),開(kāi)始吧。
?
?
本文采用基本Xml來(lái)配置Action,如果有時(shí)間會(huì)繼續(xù)寫(xiě)Annotation的實(shí)現(xiàn)。Xml文件結(jié)構(gòu)與Struts2的配置文件struts.xml幾乎一樣,這樣大家都比較熟悉,不過(guò)我簡(jiǎn)寫(xiě)了某些地方:
?
Struts.xml
Xml代碼??
<?xml?version="1.0"?encoding="UTF-8"??>?? ?? <struts>?? ????<package>?? ????????<action?name="hello"?method="hello"?? ????????????class="com.leo.action.HelloAction">?? ????????????<result?name="success">/index.jsp</result>?? ????????</action>?? ????</package>?? </struts>??
?
?
是不是很熟悉啊,不過(guò)為了簡(jiǎn)單我都給簡(jiǎn)化了,否則這是一個(gè)沒(méi)有盡頭的工作。核心部分仍然是Filter,Struts2所有工作都是通過(guò)一個(gè)Filter來(lái)完成的(struts1.*是通過(guò)一個(gè)Action實(shí)現(xiàn)的)。我們先來(lái)看代碼:
?
Java代碼??
public?class?StrutsFilter?implements?Filter?{?? ????public?void?doFilter(ServletRequest?req,?ServletResponse?res,?? ????????????FilterChain?chain)?throws?IOException,?ServletException?{?? ?????????? ????????HttpServletRequest?request?=?(HttpServletRequest)?req;?? ????????HttpServletResponse?response?=?(HttpServletResponse)?res;?? ????????ServletContext?servletContext?=?filterConfig.getServletContext();?? ?????????? ????????String?actionName?=?StringUtil.parseServletPath(request?? ????????????????.getServletPath());?? ?? ?????????? ????????if?(StringUtil.isEmpty(actionName))?{?? ????????????chain.doFilter(request,?response);?? ????????}?else?{?? ?????????????? ????????????ActionClass?clas?=?this.getActionClass(actionName);?? ?????????????? ????????????Map<String,?String[]>?params?=?request.getParameterMap();?? ?????????????? ????????????setBeforeActionValue(clas,?params);?? ?????????????? ????????????setResultValue(clas,?request);?? ?????????????? ????????????servletContext.getRequestDispatcher(clas.getResult()).forward(?? ????????????????????request,?response);?? ????????}?? ????}?? }??
?
?沒(méi)錯(cuò)一些因果都因doFilter方法而起。我的作法是:
?
- 解析URL路徑,從而得到相應(yīng)action在struts.xml配置文件中所配置的方法。如果不為合法的action后綴,直接chain.doFilter(request, response)放行。
- 將URL上的參數(shù)通過(guò)request.getParameterMap()取出,在調(diào)用action執(zhí)行方法之前,將具有set**屬性的字段賦值。這里利用了反射。
- 繼續(xù)利用反射,執(zhí)行Action的方法。結(jié)束前將具有g(shù)et**屬性的字段存于request域中,供頁(yè)面使用。大家記得在每次執(zhí)行Action的方法時(shí)都會(huì)返回一個(gè)String字符串,比如SUCCESS,INPUT,ERROR等,我們可以將這個(gè)值與struts.xml的<result name="success" ....>/index.jsp</result> 結(jié)點(diǎn)進(jìn)行匹配,取出返回頁(yè)面/index.jsp
- 一切準(zhǔn)備就緒后,調(diào)用servletContext.getRequestDispatcher().forward()方法到相應(yīng)的頁(yè)面上去。
這就是大概的流程。因?yàn)槭且粋€(gè)入門(mén)的框架所以很不完善,攔截器,result type的各種類(lèi)型都沒(méi)有去實(shí)現(xiàn),因?yàn)槲覊焊鶝](méi)想過(guò)要重復(fù)發(fā)明輪子。好,我們開(kāi)始一步一步的看。
?
?
?
我們先來(lái)看這一句:ActionClass clas = this.getActionClass(actionName);
其中ActionClass的結(jié)構(gòu)如下:
?
Java代碼??
public?class?ActionClass?{?? ????? ? ?? ????private?String?className;?? ????? ? ?? ????private?String?method;?? ????? ? ?? ????private?String?result;?? ????? ? ?? ????private?List<Element>?elements?=?new?ArrayList<Element>();?? ?? ????? ? ?? ????private?Object?action;?? ?? ?????? }???
?
ActionClass主要是用來(lái)存放解析struts.xml文件一些有用的值,以及反射時(shí)所調(diào)用的Action本身對(duì)象,其實(shí)就是一個(gè)簡(jiǎn)單的JavaBean,存儲(chǔ)臨信息。
?
?
getActionClass(actionName)方法就是將URL上的actionName取出與struts.xml中的<action>結(jié)點(diǎn)匹配,可以得到Action的類(lèi)全名,Action所調(diào)用的具體哪個(gè)方法名,Action的所有result結(jié)點(diǎn)(因?yàn)榉椒ㄟ€沒(méi)有執(zhí)行,還不知道是具體哪一個(gè)result結(jié)點(diǎn),所以先存起來(lái),后面來(lái)解析)分別存在ActionClass對(duì)象中相應(yīng)的屬性中去。具體的解析代碼我就不打出來(lái)了,否則文章太長(zhǎng)。
?
?
再來(lái)看看setBeforeActionValue(clas, params)這一句。其實(shí)就是將得到的ActionClass對(duì)象與提交的參數(shù)全部傳進(jìn)去,給Action的那些set屬性賦值:
?
Java代碼??
? ? ? ? ? ? ?? ????public?Object?setActionValues(ActionClass?actionClass,?? ????????????Map<String,?String[]>?params)?{?? ????????try?{?? ?????????????? ????????????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();?? ?????????????????????? ????????????????????String?setMethodName?=?"set"?+?upperFirstLetter?? ????????????????????????????+?key.substring(1);?? ????????????????????Method?method?=?null;?? ?????????????????????? ????????????????????try?{?? ????????????????????????method?=?clas.getMethod(setMethodName,?? ????????????????????????????????new?Class[]?{?String.class?});?? ????????????????????}?catch?(NoSuchMethodException?e)?{?? ????????????????????????System.out.println("警告?"?+?actionClass.getClassName()?? ????????????????????????????????+?"."?+?setMethodName?+?"("?? ????????????????????????????????+?String.class.getName()?+?")?不存在");?? ????????????????????}?? ????????????????????if?(method?!=?null)?{?? ?????????????????????????? ????????????????????????String?result?=?StringUtil.StringArrayToString(value);?? ????????????????????????method.invoke(obj,?new?String[]?{?result?});?? ????????????????????}?? ?? ????????????????}?? ?? ????????????}?? ????????????return?obj;?? ????????......?? ????}??
?
?
這樣就順利的將頁(yè)面的值賦給了Action的相應(yīng)屬性,接下來(lái)就是Action調(diào)用工作了。通過(guò)setActionValues方法,我們已經(jīng)可以得到Action對(duì)象本身了,可以存在ActionClass對(duì)象clas中去,我們直接調(diào)用setResultValue(clas, request)在Action執(zhí)行后,同時(shí)也把有g(shù)et方法的屬性一并存于request域中:
?
?
Java代碼??
? ? ? ? ? ? ? ?? ????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;?? ????????????????????????????????????????????????......?? ????????}?? ????}??
?
很簡(jiǎn)單的代碼——調(diào)用Action那個(gè)無(wú)參執(zhí)行方法,得到返回String類(lèi)型的返回結(jié)果,然后我們可以再次利用ActionClass將最終的返回結(jié)果也給解析出來(lái),看this.setInvokeResult(result, actionClass)方法
?
?
Java代碼??
? ? ? ? ? ? ?? ????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("請(qǐng)確定在xml配置文件中是否有名叫?["?+?result?? ????????????????+?"] 的返回類(lèi)型結(jié)點(diǎn)?");?? ????}??
?
?
?
一切大功告成,將剛剛得到的返回結(jié)果用servletContext.getRequestDispatcher(clas.getResult()).forward(
request, response)轉(zhuǎn)發(fā)出去,編碼部分完畢。
?
?
別忘記了在web.xml中配置這個(gè)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>??
?
?
?
?
最后寫(xiě)個(gè)測(cè)試Action吧,就按照本文最開(kāi)始的那個(gè)struts.xml配置編寫(xiě)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;?? ????}?? ?? } ?
總結(jié)
以上是生活随笔為你收集整理的自己动手写一个Struts2的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。