- hanwesley
- 等级: 初级会员
- 性别:
- 文章: 91
- 积分: 30
- 来自: 杭州
|
发表时间:2010-05-10
最后修改:2010-05-13
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)在配置文件中配置<controller processorClass="**.*Controller"/>
========strut1.x源码分析==========
一、Struts1.x 1、ActionServlet init方法中初始化ActionMapping,ActionForward doGet,doPost方法调用ActionServlet.process方法,其间接调用RequestProcessor.process方法 2、RequestProcessor process processPreProcess 设计上是一个钩子 可以在Action调用之前做一些动作。
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); private static Log log = LogFactory.getLog(ActionMapping.class); processActionCreate Action 是单实例的,因为其存在一个HashMap中 Action instance = (Action) actions.get(className); if (instance != null) { if (log.isTraceEnabled()) { log.trace(" Returning existing Action instance"); } return (instance); } ServletContext.getRequestDispatcher(String url) url为绝对地址 ServletRequest.getRequestDispatcher(String url) url为相对地址
HashMap中keySet方法返回key值集合,values方法返回value集合
http://localhost:8088/news/main/list.jsp news是应用程序的名字 则执行下面向行代码后打印出如下结果: 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:\Tomcat 6.0\webapps\news\test
struts1.x配置细节:Action中配置ActionForm,实例化ActionForm根据attribute配置
processPopulate中定义了处理ActionForm的定义
ModuleConfigImpl implements ModuleConfig public ModuleConfigImpl(String prefix) { super(); this.prefix = prefix; this.actionConfigs = new HashMap(); this.actionConfigList = new ArrayList(); 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 = new HashMap(); this.exceptions = new HashMap(); this.formBeans = new HashMap(); this.forwards = new HashMap(); this.messageResources = new HashMap(); this.plugIns = new ArrayList(); } 二、struts2 1、Action 普通POJO类 Struts2为Action的执行,准备了完整的数据环境和执行环境。而这个执行环境,就保证了Action在Web容器中的顺利运行。 2、Interceptor Interceptor init(); destory(); String intercept(ActionInvocation invocation) throws Exception{//核心方法 //doSomething.... String result=invocation.invoke(); //invocation.invoke()这个方法其实是整个拦截器框架的实现核心 //ActionInvocation作为Action的调度者 //doSomething.... return result; } 3、result类型 Interface Result { public void execute (ActionInvocation invocation) throws Exception{ } } 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之前可以做一些事情 RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation); if(dispatcher==null){ response.sendError(404,"result not found!!"); }
struts2标签
<s:iterator value="books" id="book" status="stat"> <tr> <td><s:property value="#stat.count"/></td> <td><s:property value="#book.name"/></td> <td><s:property value="#book.author"/></td> <td><s:property value="#book.publisher"/></td> <td><s:property value="#book.price"/></td> <td><s:date name="#book.publishDate" format="yyyy年MM月dd"></s:date></td> <td><a onclick="return confirm('确认删除《${book.name }》')" href="book!delete.action?id=${book.id }">删除</a></td> <td><a href=<s:url action="book" method="delete"></s:url>>更新</a></td> </tr> </s:iterator>
<!-- 如何使用ognl表达式对集合过滤 返回books集合中符合price>100的所有元素对象 ?:表示返回所有满足条件的对象 ^:表示返回第一个满足条件的对象 $:表示返回最后一个满足条件的对象 --> <s:iterator value="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:set name="age" value="28"></s:set> <!-- test属性指定一个ognl表达式 --> <s:if test="age > 20"> 成年人 </s:if> <s:else> 未成年 </s:else> OGNL表达式 </h1><hr> <h1> action:<s:property value="name"/><br> request:<s:property value="#request.name"/> :<s:property value="#request.name1"/> <br> session:<s:property value="#session.name"/><br> application:<s:property value="#application.name"/><br> <hr> <s:property value="person.name"/> <s:property value="person.address"/><br> <s:property value="user.name"/> <s:property value="user.address"/> <hr>EL表达式在Struts2中的使用<br> ${name } </h1>
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
返回顶楼 |
|
|
- mercyblitz
- 等级: 初级会员
- 性别:
- 文章: 1004
- 积分: 60
- 来自: 长沙->杭州
|
前台验证太臃肿,不要使用。
还有一个是线程安全方面的实践。
|
返回顶楼 |
|
|
- hanwesley
- 等级: 初级会员
- 性别:
- 文章: 91
- 积分: 30
- 来自: 杭州
|
mercyblitz 写道 前台验证太臃肿,不要使用。
还有一个是线程安全方面的实践。
但是我发现很多网站都用JS做前台验证的啊,比如163邮箱等
线程安全方面的实践,谢谢提醒。
|
返回顶楼 |
|
|
- mercyblitz
- 等级: 初级会员
- 性别:
- 文章: 1004
- 积分: 60
- 来自: 长沙->杭州
|
mercyblitz 写道 前台验证太臃肿,不要使用。
还有一个是线程安全方面的实践。
但是我发现很多网站都用JS做前台验证的啊,比如163邮箱等
你误会我意思啦,Struts会把所有的验证方法全部压倒客户端,不是说不要JS验证。
|
返回顶楼 |
|
|
- make_miracles
- 等级: 初级会员
- 性别:
- 文章: 187
- 积分: 0
- 来自: 天朝
|
这种古董还有人研究呀
|
返回顶楼 |
|
|
- giginet
- 等级:
- 性别:
- 文章: 222
- 积分: 429
- 来自: 南京
|
这个不只是structs1.x吧。任何三层框架都应该是这样的啦。
|
返回顶楼 |
|
|
- hanwesley
- 等级: 初级会员
- 性别:
- 文章: 91
- 积分: 30
- 来自: 杭州
|
恩 我们不能局限于框架本身~
|
返回顶楼 |
|
|
- chrisx
- 等级:
- 性别:
- 文章: 42
- 积分: 120
- 来自: 天津
|
发表下个人看法
1. 任何MVC框架关于前台UI的那部分我感觉都比较鸡肋,前台可以自己去实现,比如jQuery, ext, flex, 用他们提供的很不灵活,不可控。前台验证可以用jquery提供的验证,如果是ext或flex项目,框架自身提供验证。
2. Struts2的Action可以是线程安全的,与Spring集成时,定义bean的时候要定义成非单利模式,即可线程安全,每次实例化。
3. S1与S2虽说是一个公司的产品,但是两个时代的产物,可以当做只是名一样而已
|
返回顶楼 |
|
|
- babbyyang
- 等级: 初级会员
- 性别:
- 文章: 15
- 积分: 30
- 来自: 北京
|
struts1.x我只用他的formbean 和 action 控制,感觉是最简单好用的框架了。
|
返回顶楼 |
|
|