struts1.x & struts2对比学习及源码分析

Struts1.x综述

一、业务逻辑

应包含在POJO类或EJB中,完全独立于Action。这样做的优点就是不依赖与框架本身,更好复用。

原则:类和类的方法应该有自己独立的职责,能够完成所建领域的特定任务(如ActionForm)

二、处理Exception

原则:1)在异常离开业务层之前捕获,处理,记录业务层抛出的所有异常;

2)在业务层捕获一个异常时,作为一个通用的异常类型重新抛出。

编制定制ExceptionHandler(如加入邮件通知,log记录等功能)

1、扩展org.apache.struts.action.ExceptionHandler,并重写execute方法

2、配置exception时,加入handle选项

三、ActionForm与Action

1、将ActionForm与业务逻辑分离,将ActionForm收集的数据copy到VO对象中,可以借助BeanUtils类完成该项功能。

2、将ActionForm中的公共属性设置为String类型(用户处理数字类型或Date类型,ActionForm默认会做类型转化,如果不能转化会抛出异常,可以用JS在前台处理数据或后台转化,后台转化不成抛出自定义异常信息)

3、将Action作为业务逻辑的调用点,而不是插入点。

4、在ActionForm的reset方法中注意清空checkbox,应为在没有选中checkbox时,HTTP协议发送的数据为空,而页面中原来被选中的不会改变。

四、验证

ActionForm的validate方法

Struts验证框架

JS前台验证

五、扩展Struts

1、扩展RequestProcessor,实现自己的控制器实际上struts的控制器是RequestProcessor,而不是ActionServlet

a)继承org.apache.struts.action.RequestProcessor

b)重写process,processActionPerform,processPreProcess方法

一般不重写processPreProcess方法,主要是其抛出了ServletException和IOException

c)在配置文件中配置<controllerprocessorclass="**.*Controller"/>

========strut1.x源码分析==========

一、Struts1.x

1、ActionServlet

init方法中初始化ActionMapping,ActionForward

doGet,doPost方法调用ActionServlet.process方法,其间接调用RequestProcessor.process方法

2、RequestProcessor

process

processPreProcess设计上是一个钩子可以在Action调用之前做一些动作。

ClassLoaderclassLoader=Thread.currentThread().getContextClassLoader();

privatestaticLoglog=LogFactory.getLog(ActionMapping.class);

processActionCreateAction是单实例的,因为其存在一个HashMap中

Actioninstance=(Action)actions.get(className);

if(instance!=null){

if(log.isTraceEnabled()){

log.trace("ReturningexistingActioninstance");

}

return(instance);

}

ServletContext.getRequestDispatcher(Stringurl)url为绝对地址

ServletRequest.getRequestDispatcher(Stringurl)url为相对地址

HashMap中keySet方法返回key值集合,values方法返回value集合

http://localhost:8088/news/main/list.jspnews是应用程序的名字

则执行下面向行代码后打印出如下结果:

1、System.out.println(request.getContextPath());打印结果:/news

2、System.out.println(request.getServletPath());打印结果:/main/list.jsp

3、System.out.println(request.getRequestURI());打印结果:/news/main/list.jsp

4、System.out.println(request.getRealPath("/"));打印结果:F:\Tomcat6.0\webapps\news\test

struts1.x配置细节:Action中配置ActionForm,实例化ActionForm根据attribute配置

processPopulate中定义了处理ActionForm的定义

ModuleConfigImplimplementsModuleConfig

publicModuleConfigImpl(Stringprefix){

super();

this.prefix=prefix;

this.actionConfigs=newHashMap();

this.actionConfigList=newArrayList();

this.actionFormBeanclass="org.apache.struts.action.ActionFormBean";

this.actionMappingclass="org.apache.struts.action.ActionMapping";

this.actionForwardclass="org.apache.struts.action.ActionForward";

this.configured=false;

this.controllerConfig=null;

this.dataSources=newHashMap();

this.exceptions=newHashMap();

this.formBeans=newHashMap();

this.forwards=newHashMap();

this.messageResources=newHashMap();

this.plugIns=newArrayList();

}

二、struts2

1、Action普通POJO类

Struts2为Action的执行,准备了完整的数据环境和执行环境。而这个执行环境,就保证了Action在Web容器中的顺利运行。

2、Interceptor

Interceptor

init();

destory();

Stringintercept(ActionInvocationinvocation)throwsException{//核心方法

//doSomething....

Stringresult=invocation.invoke();

//invocation.invoke()这个方法其实是整个拦截器框架的实现核心

//ActionInvocation作为Action的调度者

//doSomething....

returnresult;

}

3、result类型

InterfaceResult{

publicvoidexecute(ActionInvocationinvocation)throwsException{

}

}

dispatcher

redirect

4、测试

单元测试

Interceptor借助ActionProxy

Dispatcher

ObjectFactory可配置,即struts.objectFactory=spring

action=objectFactory.buildAction(proxy.getActionName(),proxy.getNamespace(),proxy.getConfig(),contextMap);

5、Struts2源码分析

ActionMapper

其实是HttpServletRequest和Action调用请求的一个映射,屏蔽了Action对于容器的依赖

ActionProxy&ActionInvocation

Action的一个代理,由ActionProxyFactory创建,它本身不包括Action实例,默认实现DefaultActionProxy是由ActionInvocation持有Action实例。

ActionProxy作用是如何取得Action,无论是本地还是远程。

而ActionInvocation的作用是如何执行Action,拦截器的功能就是在ActionInvocation中实现的。

ConfigurationProvider&Configuration

ConfigurationProvider就是Struts2中配置文件的解析器

Struts2中的配置文件主要是尤其实现类XmlConfigurationProvider及其子类StrutsXmlConfigurationProvider来解析。

6.Struts2请求流程

1、客户端发送请求

2、请求先通过ActionContextCleanUp-->FilterDispatcher

3、FilterDispatcher通过ActionMapper来决定这个Request需要调用哪个Action

4、如果ActionMapper决定调用某个Action,FilterDispatcher把请求的处理交给ActionProxy,这儿已经转到它的Delegate--Dispatcher来执行

5、ActionProxy根据ActionMapping和ConfigurationManager找到需要调用的Action类

6、ActionProxy创建一个ActionInvocation的实例

7、ActionInvocation调用真正的Action,当然这涉及到相关拦截器的调用

8、Action执行完毕,ActionInvocation创建Result并返回,当然,如果要在返回之前做些什么,可以实现PreResultListener。添加PreResultListener可以在Interceptor中实现。

java.util.concurrent包

preResultListeners在处理Request之前可以做一些事情

RequestDispatcherdispatcher=request.getRequestDispatcher(finalLocation);

if(dispatcher==null){

response.sendError(404,"resultnotfound!!");

}

struts2标签

<s:iteratorvalue="books"id="book"status="stat">

<tr>

<td><s:propertyvalue="#stat.count"/></td>

<td><s:propertyvalue="#book.name"/></td>

<td><s:propertyvalue="#book.author"/></td>

<td><s:propertyvalue="#book.publisher"/></td>

<td><s:propertyvalue="#book.price"/></td>

<td><s:datename="#book.publishDate"format="yyyy年MM月dd"></s:date></td>

<td><aonclick="returnconfirm('确认删除《${book.name}》')"href="book!delete.action?id=${book.id}">删除</a></td>

<td><ahref=<s:urlaction="book"method="delete"></s:url>>更新</a></td>

</tr>

</s:iterator>

<!--如何使用ognl表达式对集合过滤

返回books集合中符合price>100的所有元素对象

?:表示返回所有满足条件的对象

^:表示返回第一个满足条件的对象

$:表示返回最后一个满足条件的对象

-->

<s:iteratorvalue="books.{?#this.price>100}"id="book">

<tr>

<td>${book.name}</td>

<td>${book.author}</td>

<td>${book.publisher}</td>

<td>${book.price}</td>

</tr>

</s:iterator>

</table>

<hr>

<!--定义一个age变量,可使用scope属性指定变量所属范围,

scope属性值可为page、request、session、application、action。

如果不加scope属性,则默认范围是context中-->

<s:setname="age"value="28"></s:set>

<!--test属性指定一个ognl表达式-->

<s:iftest="age>20">

成年人

</s:if>

<s:else>

未成年

</s:else>

OGNL表达式

</h1><hr>

<h1>

action:<s:propertyvalue="name"/><br>

request:<s:propertyvalue="#request.name"/>

:<s:propertyvalue="#request.name1"/>

<br>

session:<s:propertyvalue="#session.name"/><br>

application:<s:propertyvalue="#application.name"/><br>

<hr>

<s:propertyvalue="person.name"/>

<s:propertyvalue="person.address"/><br>

<s:propertyvalue="user.name"/>

<s:propertyvalue="user.address"/>

<hr>EL表达式在Struts2中的使用<br>

${name}

</h1>

相关推荐