Showing posts with label struts. Show all posts
Showing posts with label struts. Show all posts

Sunday, January 11, 2009

struts2笔记(1)--工作流程

更多精彩请到 http://www.139ya.com


转自: struts2笔记(1)--工作流程

关键字: struts2 流程 核心类
核心控制器FilterDispatcher

核心控制器FilterDispatcher是Struts 2框架的基础,包含了框架内部的控制流程和处理机制。业务控制器Action和业务逻辑组件是需要用户来自己实现的。用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件,供核心控制器FilterDispatcher来使用。

Struts 2的工作流程相对于Struts 1要简单,与WebWork框架基本相同,所以说Struts 2是WebWork的升级版本。Struts 2框架按照模块来划分,可以分为Servlet Filters、Struts核心模块、拦截器和用户实现部分。Struts 2框架结构图如图3.1所示。











图3.1 Struts 2框架结构图

一个请求在Struts 2框架中的处理大概分为以下几个步骤。


* 客户端提交一个(HttpServletRequest)请求,如上文在浏览器中输入
http://localhost: 8080/bookcode/ch2/Reg.action就是提交一个(HttpServletRequest)请求。

* 请求被提交到一系列(主要是3层)的过滤器(Filter),如(ActionContextCleanUp、其他过滤器(SiteMesh 等)、 FilterDispatcher)。注意:这里是有顺序的,先ActionContext CleanUp,再其他过滤器(Othter Filters、SiteMesh等),最后到FilterDispatcher。
* FilterDispatcher是控制器的核心,就是MVC的Struts 2实现中控制层(Controller)的核心。
* FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(HttpServlet Request)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher则把请求的处理交给 ActionProxy。
* ActionProxy通过Configuration Manager(struts.xml)询问框架的配置文件,找到需要调用的Action类。例如,用户注册示例将找到UserReg类。
* ActionProxy创建一个ActionInvocation实例,同时ActionInvocation通过代理模式调用Action。但在调用之前,ActionInvocation会根据配置加载Action相关的所有Interceptor(拦截器)。
* 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果result。


Struts 2的核心控制器是FilterDispatcher,有3个重要的方法:destroy()、doFilter()和Init(),可以在Struts 2的下载文件夹中找到源代码,如代码3.1所示。

代码3.1 核心控制器FilterDispatcher

1. public class FilterDispatcher implements StrutsStatics, Filter {
2.
3. /**
4.
5. * 定义一个Log实例
6.
7. */
8.
9. private static final Log LOG = LogFactory.getLog(FilterDispatcher.class);
10.
11. /**
12.
13. * 存放属性文件中的.STRUTS_I18N_ENCODING值
14.
15. */
16.
17. private static String encoding;
18.
19. /**
20.
21. * 定义ActionMapper实例
22.
23. */
24.
25. private static ActionMapper actionMapper;
26.
27. /**
28.
29. * 定义FilterConfig实例
30.
31. */
32.
33. private FilterConfig filterConfig;
34.
35. protected Dispatcher dispatcher;
36.
37. /**
38.
39. * 创建一个默认的dispatcher,初始化filter
40.
41. * 设置默认的packages *
42.
43. */
44.
45. public void init(FilterConfig filterConfig) throws ServletException {
46.
47. this.filterConfig = filterConfig;
48.
49. dispatcher = createDispatcher(filterConfig);
50.
51. dispatcher.init();
52.
53. String param = filterConfig.getInitParameter("packages");
54.
55. String packages = "org.apache.struts2.static template org.apache.struts2.interceptor.debugging";
56.
57. if (param != null) {
58.
59. packages = param + " " + packages;
60.
61. }
62.
63. this.pathPrefixes = parse(packages);
64.
65. }
66.
67. //销毁filter方法
68.
69. public void destroy() {
70.
71. if (dispatcher == null) {
72.
73. LOG.warn("something is seriously wrong, Dispatcher is not initialized (null) ");
74.
75. } else {
76.
77. dispatcher.cleanup();
78.
79. }
80.
81. }
82.
83. /**
84.
85. * 处理一个Action或者资源请求
86.
87. *


88.
89. * filter尝试将请求同action mapping相匹配
90.
91. * 如果找到,将执行dispatcher的serviceAction方法
92.
93. * 如果Action处理失败, doFilter将建立一个异常
94.
95. *


96.
97. * 如果请求静态资源
98.
99. * 资源将被直接复制给 response
100.
101. *


102.
103. * 如果找不到匹配Action 或者静态资源,则直接跳出
104.
105. public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
106.
107. HttpServletRequest request = (HttpServletRequest) req;
108.
109. HttpServletResponse response = (HttpServletResponse) res;
110.
111. ServletContext servletContext = getServletContext();
112.
113. String timerKey = "FilterDispatcher_doFilter: ";
114.
115. try {
116.
117. UtilTimerStack.push(timerKey);
118.
119. request = prepareDispatcherAndWrapRequest(request, response);
120.
121. ActionMapping mapping;
122.
123. try {
124.
125. mapping=actionMapper.getMapping(request, dispatcher.getConfigurationManager());
126.
127. } catch (Exception ex) {
128.
129. LOG.error("error getting ActionMapping", ex);
130.
131. dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
132.
133. return;
134.
135. }
136.
137. if (mapping == null) {
138.
139. String resourcePath = RequestUtils.getServletPath(request);
140.
141. if ("".equals(resourcePath) && null != request.getPathInfo()) {
142.
143. resourcePath = request.getPathInfo();
144.
145. }
146.
147. if (serveStatic && resourcePath.startsWith("/struts")) {
148.
149. String name = resourcePath.substring("/struts".length());
150.
151. findStaticResource(name, request, response);
152.
153. } else {
154.
155. //为一个普通的request, 则通过
156.
157. chain.doFilter(request, response);
158.
159. }
160.
161. return;
162.
163. }
164.
165. /**
166.
167. *这个方法询问ActionMapper是否需要调用某个Action来处理这个(request)请求,
168.
169. *如果ActionMapper决定需要调用某个Action,
170.
171. *FilterDispatcher则把请求的处理交给ActionProxy
172.
173. dispatcher.serviceAction(request, response, servletContext, mapping);
174.
175. } finally {
176.
177. try {
178.
179. ActionContextCleanUp.cleanUp(req);
180.
181. } finally {
182.
183. UtilTimerStack.pop(timerKey);
184.
185. }
186.
187. }
188.
189. }
190.
191. … …
192.
193. }



在doFilter()方法中,将调用dispatcher.serviceAction,该方法如果找到相应的Action,将把用户请求交给ActionProxy。serviceAction()代码在Dispatcher.java中,如代码3.2所示。

代码3.2 Dispatcher类



1. public class Dispatcher {
2.
3. ...
4.
5. /**
6.
7. * 为mapping加载类,并调用相应的方法或者直接返回result
8.
9. *


10.
11. * 根据用户请求的参数,建立Action上下文
12.
13. * 根据指定的Action’名称和包空间名称,加载一个Action代理 ActionProxy
14.
15. * 然后Action的相应方法将被执行,
16.
17. */
18.
19. public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context, ActionMapping mapping) throws ServletException {
20.
21. Map extraContext = createContextMap(request, response, mapping, context);
22.
23. //如果存在一个值栈,则建立一个新的并复制以备Action使用
24.
25. ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
26.
27. if (stack!= null) {
28.
29. extraContext.put(ActionContext.VALUE_STACK, ValueStackFactory.getFactory().createValueStack(stack));
30.
31. }
32.
33. String timerKey = "Handling request from Dispatcher";
34.
35. try {
36.
37. UtilTimerStack.push(timerKey);
38.
39. String namespace = mapping.getNamespace();
40.
41. String name = mapping.getName();
42.
43. String method = mapping.getMethod();
44.
45. Configuration config = configurationManager.getConfiguration();
46.
47. //FilterDispatcher把请求的处理交给ActionProxy
48.
49. ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, extraContext, true, false);
50.
51. proxy.setMethod(method);
52.
53. request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
54.
55. //ActionMapping 直接返回一个result
56.
57. if (mapping.getResult() != null) {
58.
59. Result result = mapping.getResult();
60.
61. result.execute(proxy.getInvocation());
62.
63. } else {
64.
65. proxy.execute();
66.
67. }
68.
69. if (stack != null) {
70.
71. request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
72.
73. }
74.
75. } catch (ConfigurationException e) {
76.
77. LOG.error("Could not find action or result", e);
78.
79. sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
80.
81. } catch (Exception e) {
82.
83. throw new ServletException(e);
84.
85. } finally {
86.
87. UtilTimerStack.pop(timerKey);
88.
89. }
90.
91. }
92.
93. …
94.
95. }



从上面代码中可以看出来,Struts 2用于处理用户请求的Action实例,并不是用户实现的业务控制器,而是Action代理。关于Action代理相关内容,读者可以参考拦截器章节的介绍。


前面一直在说Action可以是一个普通的Java类,与Servlet API完全分离,但是为了实现业务逻辑,Action需要使用HttpServletRequest内容。


Struts 2设计的精巧之处就是使用了Action代理,Action代理可以根据系统的配置,加载一系列的拦截器,由拦截器将 HttpServletRequest参数解析出来,传入Action。同样,Action处理的结果也是通过拦截器传入 HttpServletResponse,然后由HttpServletRequest传给用户。

其实,该处理过程是典型的AOP(面向切面编程)的方式。Struts 2处理过程模型如图3.2所示。

图3.2 Struts 2处理过程模型

拦截器是Struts 2框架的核心,通过拦截器,实现了AOP(面向切面编程)。使用拦截器,可以简化Web开发中的某些应用,例如,权限拦截器可以简化Web应用中的权限检查。


3.1.2 业务控制器Action
业务控制器Action是由开发者自己编写实现的,Action类可以是一个简单的Java类,与Servlet API完全分离。Action一般都有一个execute()方法,也可以定义其他业务控制方法,详细内容将在后面介绍。

Action的execute()返回一个String类型值,这与Struts 1返回的ActionForward相比,简单易懂。Struts 2提供了一个ActionSupport工具类,该类实现了Action接口和validate()方法,一般开发者编写Action可以直接继承 ActionSupport类。编写Action类后,开发者还必须在配置文件中配置Action。一个Action的配置应该包含下面几个元素:


* 1、该Action的name,即用户请求所指向的URL。
* 2、Action所对应的class元素,对应Action类的位置。
* 3、指定result逻辑名称和实际资源的定位。



Action是业务控制器,笔者建议在编写Action的时候,尽量避免将业务逻辑放到其中,尽量减少Action与业务逻辑模块或者组件的耦合程度。






Struts1 VS Struts2

更多精彩请到 http://www.139ya.com


1.Action classes :

* Struts1:Struts 1 requires Action classes to extend an abstract base class. A common problem in Struts 1 is programming to abstract classes instead of interfaces.
* Struts2:An Struts 2 Action may implement an Action interface, along with other interfaces to enable optional and custom services. Struts 2 provides a base ActionSupport class to implement commonly used interfaces. Albeit, the Action interface is not required. Any POJO object with a execute signature can be used as an Struts 2 Action object.



2.Threading Model :

* Struts1:Struts 1 Actions are singletons and must be thread-safe since there will only be one instance of a class to handle all requests for that Action. The singleton strategy places restrictions on what can be done with Struts 1 Actions and requires extra care to develop. Action resources must be thread-safe or synchronized.
* Struts2:Struts 2 Action objects are instantiated for each request, so there are no thread-safety issues. (In practice, servlet containers generate many throw-away objects per request, and one more object does not impose a performance penalty or impact garbage collection.)



3.Servlet Dependency :

* Struts1:Struts 1 Actions have dependencies on the servlet API since the HttpServletRequest and HttpServletResponse is passed to the execute method when an Action is invoked.
* Struts2:Struts 2 Actions are not coupled to a container. Most often the servlet contexts are represented as simple Maps, allowing Actions to be tested in isolation. Struts 2 Actions can still access the original request and response, if required. However, other architectural elements reduce or eliminate the need to access the HttpServetRequest or HttpServletResponse directly.



4.Testability :

* Struts1:A major hurdle to testing Struts 1 Actions is that the execute method exposes the Servlet API. A third-party extension, Struts TestCase, offers a set of mock object for Struts 1.
* Struts2:Struts 2 Actions can be tested by instantiating the Action, setting properties, and invoking methods. Dependency Injection support also makes testing simpler.



5.Harvesting Input :

* Struts1:Struts 1 uses an ActionForm object to capture input. Like Actions, all ActionForms must extend a base class. Since other JavaBeans cannot be used as ActionForms, developers often create redundant classes to capture input. DynaBeans can used as an alternative to creating conventional ActionForm classes, but, here too, developers may be redescribing existing JavaBeans.
* Struts2:Struts 2 uses Action properties as input properties, eliminating the need for a second input object. Input properties may be rich object types which may have their own properties. The Action properties can be accessed from the web page via the taglibs. Struts 2 also supports the ActionForm pattern, as well as POJO form objects and POJO Actions. Rich object types, including business or domain objects, can be used as input/output objects. The ModelDriven feature simplifies taglb references to POJO input objects.



6.Expression Language :

* Struts1:Struts 1 integrates with JSTL, so it uses the JSTL EL. The EL has basic object graph traversal, but relatively weak collection and indexed property support.
* Struts2:Struts 2 can use JSTL, but the framework also supports a more powerful and flexible expression language called "Object Graph Notation Language" (OGNL).



7.Binding values into views :

* Struts1:Struts 1 uses the standard JSP mechanism for binding objects into the page context for access.
* Struts2:Struts 2 uses a "ValueStack" technology so that the taglibs can access values without coupling your view to the object type it is rendering. The ValueStack strategy allows reuse of views across a range of types which may have the same property name but different property types.



8.Type Conversion :

* Struts1:Struts 1 ActionForm properties are usually all Strings. Struts 1 uses Commons-Beanutils for type conversion. Converters are per-class, and not configurable per instance.
* Struts2:Struts 2 uses OGNL for type conversion. The framework includes converters for basic and common object types and primitives.



9.Validation :

* Struts1:Struts 1 supports manual validation via a validate method on the ActionForm, or through an extension to the Commons Validator. Classes can have different validation contexts for the same class, but cannot chain to validations on sub-objects.
* Struts2:Struts 2 supports manual validation via the validate method and the XWork Validation framework. The Xwork Validation Framework supports chaining validation into sub-properties using the validations defined for the properties class type and the validation context.



10.Control Of Action Execution :

* Struts1:Struts 1 supports separate Request Processors (lifecycles) for each module, but all the Actions in the module must share the same lifecycle.
* Struts2:Struts 2 supports creating different lifecycles on a per Action basis via Interceptor Stacks. Custom stacks can be created and used with different Actions, as needed.




Action 类:
• Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口。
• Struts 2 Action 类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现常用的接口。Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的Action对象。
线程模式:
• Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
• Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)
Servlet 依赖:
• Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
• Struts 2 Action 不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。
可测性:
• 测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。
• Struts 2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。
捕获输入:
• Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的类捕获输入。动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是在重新描述(创建)已经存在的JavaBean(仍然会导致有冗余的javabean)。
• Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。Struts2也支持 ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种ModelDriven 特性简化了taglib对POJO输入对象的引用。
表达式语言:
• Struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。
• Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL).
绑定值到页面(view):
• Struts 1使用标准JSP机制把对象绑定到页面中来访问。
• Struts 2 使用 "ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。
 
类型转换:
• Struts 1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。
• Struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。
校验:
• Struts 1支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
• Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性
Action执行的控制:
• Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。
• Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。

Spring, struts, Hibernate

更多精彩请到 http://www.139ya.com


1.strust的。
Action是不是线程安全的?如果不是
有什么方式可以保证Action的线程安全?如果是,说明原因

2.MVC,分析一下struts是如何实现MVC的

3.struts中的几个关键对象的作用(说说几个关键对象的作用)

4.spring
说说AOP和IOC的概念以及在spring中是如何应用的

5.Hibernate有哪几种查询数据的方式

6.load()和get()的区别

1.不是线程安全的。只要不申明类变量就可以保证线程安全。因为只存在一个Action类实例,所有线程会共享类变量。
2.好笼统,ActionServlet实现控制层,丰富的标签库提供视图层的良好支持
3.ActionServlet,requestProcess,ActionForm,Action等等
4.由spring完成AOP(面向切面),IOC(注入)
5.3种,HQL,QBC,SQL
6.如果查询不到记录,load方法会抛出异常,get方法返回null



1.谈谈hibernate的延迟加载和openSessionInView

3.spring的事务有几种方式?谈谈spring事务的隔离级别和传播行为。

9.Hibernate的主键生成机制increment,native,identity,assigned,sequence


1、 简述你对IoC(Inversion of Control)的理解,描述一下Spring中实现DI(Dependency Injection)的几种方式。


2、 Spring的Bean有多种作用域,包括:

singleton、prototype、request、session、global session、application、自定义


3、 简单描述Spring framework与Struts的不同之处,整合Spring与Struts有哪些方法,哪种最好,为什么?


4、 Hibernate中的update()和saveOrUpdate()的区别


5、 Spring对多种ORM框架提供了很好的支持,简单描述在Spring中使用Hibernate的方法,并结合事务管理。



答案:

1、 好莱坞原则不要打电话找我,我会打给你的。IoC将创建的职责从应用程序代码搬到了框架中。Spring对Setter注入和构造方法注入提供支持。(详见 http://martinfowler.com/articles/injection.html,以及http://www.redsaga.com /spring_ref/2.0/html/beans.html#beans-factory-collaborators)


2、 除application(详见Spring framework 2.0 Reference的3.4节bean的作用域)


3、 Spring是完整的一站式框架,而Struts仅是MVC框架,且着重于MVC中的C。Spring有三种方式整合Struts:使用 Spring 的 ActionSupport 类整合 Struts;使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor;将 Struts Action 管理委托给 Spring 框架,动作委托最好。(详见使用Spring 更好地处理Struts 动作)

Spring 2.0新增一种方式:AutowiringRequestProcessor。(详见http://www.javaeye.com/topic/24239)


4、 saveOrUpdate()方法可以实现update()的功能,但会多些步骤,具体如下:

如果对象在该session中已经被持久化,不进行操作;

对象的标识符属性(identifier property)在数据库中不存在或者是个暂时的值,调用save()方法保存它;

如果session中的另一个对象有相同的标识符抛出一个异常;

以上皆不符合则调用update()更新之。


5、 在context中定义DataSource,创建SessionFactoy,设置参数;DAO类继承HibernateDaoSupport,实现具体接口,从中获得HibernateTemplate进行具体操作。

在使用中如果遇到OpenSessionInView的问题,可以添加OpenSessionInViewFilter或 OpenSessionInViewInterceptor。(详见Spring framework 2.0 Reference的12.2节Hibernate)

声明式事务需声明事务管理器,在context中设置指定属性,用确定和。

1.简述一下spring,hibernate,struts
2.说一说spring,hibernate,struts的优缺点

Friday, January 9, 2009

Struts基本工作流程

更多精彩请到 http://www.139ya.com

Struts是一个“Web应用框架”用来在开发以浏览器为客户端的应用程序时,帮助你进行更深入和更快速的开发;Struts框架是一个基于Model-View-Controller的架构。Model提供了一个内部数据的表示。View显示数据,而不去与大量的业务逻辑打交道。Controller决定执行的过程以及下一步做什么。Web应用如果采用Struts框架,基本执行交互步骤如下:

  1. 在Web应用程序启动时就会加载并初始化ActionServlet,浏览器所有请求都被提交给ActionServlet处理。
  2. 此时,当用户把表单提交时,一个配置好的ActionForm对象将被创建,并被填入表单中相应的数据。
  3. ActionServlet根据struts-config.xml 文件中预先配置好的设置,决定是否需要表单验证,如果需要验证;就调用ActionForm的validate()方法,验证成功后选择应该将请求转发给 哪个Action,如果Action对象不存在,ActionServlet会先创建这个对象。然后调用Action的execute()方法。
  4. Action的execute()方法中:从ActionForm对象中获取数据,完成业务功能,返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指向的JSP组件
  5. ActionForward对象指向的JSP组件生成动态网页,返回给客户。