您的位置:首页 > 编程语言 > Java开发

Struts1.3源代码学习总结

2013-08-08 15:47 435 查看


Struts1.3源代码学习总结

Struts相对来说是一个比较简单的MVC框架,实现的Service to Worker模式。研究Struts源代码从ActionServlet开始,因为它是统一的入口处理类,通常配置如下:

1 <servlet>

2 <servlet-name>action</servlet-name>

3 <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

4 <init-param>

5 <param-name>config</param-name>

6 <param-value>/WEB-INF/struts-config.xml</param-value>

7 </init-param>

8 <init-param>

9 <param-name>debug</param-name>

10 <param-value>2</param-value>

11 </init-param>

12 <init-param>

13 <param-name>application</param-name>

14 <param-value>ApplicationResources</param-value>

15 </init-param>

16 <load-on-startup>2</load-on-startup>

17 </servlet>

18 <servlet-mapping>

19 <servlet-name>action</servlet-name>

20 <url-pattern>*.do</url-pattern>

21 </servlet-mapping>

ActionServlet是一个Servlet,继承HttpServlet。先分析一个这个类的init方法,这里做了很多初始化的工作,会被容器调用,初始化代码如下:

1 public void init() throws ServletException {

2 final String configPrefix = "config/";

3 final int configPrefixLength = configPrefix.length() - 1;

4

5 // Wraps the entire initialization in a try/catch to better handle

6 // unexpected exceptions and errors to provide better feedback

7 // to the developer

8 try {

9 initInternal();

10 initOther();

11 initServlet();

12 initChain();

13

14 getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);

15 initModuleConfigFactory();

16

17 // Initialize modules as needed

18 ModuleConfig moduleConfig = initModuleConfig("", config);

19

20 initModuleMessageResources(moduleConfig);

21 initModulePlugIns(moduleConfig);

22 initModuleFormBeans(moduleConfig);

23 initModuleForwards(moduleConfig);

24 initModuleExceptionConfigs(moduleConfig);

25 initModuleActions(moduleConfig);

26 moduleConfig.freeze();

27

28 Enumeration names = getServletConfig().getInitParameterNames();

29

30 while (names.hasMoreElements()) {

31 String name = (String) names.nextElement();

32

33 if (!name.startsWith(configPrefix)) {

34 continue;

35 }

36

37 String prefix = name.substring(configPrefixLength);

38

39 moduleConfig =

40 initModuleConfig(prefix,

41 getServletConfig().getInitParameter(name));

42 initModuleMessageResources(moduleConfig);

43 initModulePlugIns(moduleConfig);

44 initModuleFormBeans(moduleConfig);

45 initModuleForwards(moduleConfig);

46 initModuleExceptionConfigs(moduleConfig);

47 initModuleActions(moduleConfig);

48 moduleConfig.freeze();

49 }

50

51 this.initModulePrefixes(this.getServletContext());

52

53 this.destroyConfigDigester();

54 } catch (UnavailableException ex) {

55 throw ex;

56 } catch (Throwable t) {

57 // The follow error message is not retrieved from internal message

58 // resources as they may not have been able to have been

59 // initialized

60 log.error("Unable to initialize Struts ActionServlet due to an "

61 + "unexpected exception or error thrown, so marking the "

62 + "servlet as unavailable. Most likely, this is due to an "

63 + "incorrect or missing library dependency.", t);

64 throw new UnavailableException(t.getMessage());

65 }

66 }

初始化的工作基本见名知义。当收到请求时,ActionServlet的doGet()或doPost()方法都调用process()方法来处理请求:

1 protected void process(HttpServletRequest request,

2 HttpServletResponse response)

3 throws IOException, ServletException {

4 ModuleUtils.getInstance().selectModule(request, getServletContext());

5

6 ModuleConfig config = getModuleConfig(request);

7

8 RequestProcessor processor = getProcessorForModule(config);

9

10 if (processor == null) {

11 processor = getRequestProcessor(config);

12 }

13

14 processor.process(request, response);

15 }

这个方法中重点是14行,调用RequestProcessor的process方法。RequestProcessor类可以定制,在struts.config中设置:

<controller processorClass="org.springframework.web.struts.DelegatingTilesRequestProcessor" />

process方法具体如下:

1 public void process(HttpServletRequest request, HttpServletResponse response)

2 throws IOException, ServletException {

3 // Wrap multipart requests with a special wrapper

4 request = processMultipart(request);

5

6 // Identify the path component we will use to select a mapping

7 String path = processPath(request, response);

8

9 if (path == null) {

10 return;

11 }

12

13 if (log.isDebugEnabled()) {

14 log.debug("Processing a '" + request.getMethod() + "' for path '"

15 + path + "'");

16 }

17

18 // Select a Locale for the current user if requested

19 processLocale(request, response);

20

21 // Set the content type and no-caching headers if requested

22 processContent(request, response);

23 processNoCache(request, response);

24

25 // General purpose preprocessing hook

26 if (!processPreprocess(request, response)) {

27 return;

28 }

29

30 this.processCachedMessages(request, response);

31

32 // Identify the mapping for this request

33 ActionMapping mapping = processMapping(request, response, path);

34

35 if (mapping == null) {

36 return;

37 }

38

39 // Check for any role required to perform this action

40 if (!processRoles(request, response, mapping)) {

41 return;

42 }

43

44 // Process any ActionForm bean related to this request

45 ActionForm form = processActionForm(request, response, mapping);

46

47 processPopulate(request, response, form, mapping);

48

49 // Validate any fields of the ActionForm bean, if applicable

50 try {

51 if (!processValidate(request, response, form, mapping)) {

52 return;

53 }

54 } catch (InvalidCancelException e) {

55 ActionForward forward = processException(request, response, e, form, mapping);

56 processForwardConfig(request, response, forward);

57 return;

58 } catch (IOException e) {

59 throw e;

60 } catch (ServletException e) {

61 throw e;

62 }

63

64 // Process a forward or include specified by this mapping

65 if (!processForward(request, response, mapping)) {

66 return;

67 }

68

69 if (!processInclude(request, response, mapping)) {

70 return;

71 }

72

73 // Create or acquire the Action instance to process this request

74 Action action = processActionCreate(request, response, mapping);

75

76 if (action == null) {

77 return;

78 }

79

80 // Call the Action instance itself

81 ActionForward forward =

82 processActionPerform(request, response, action, form, mapping);

83

84 // Process the returned ActionForward instance

85 processForwardConfig(request, response, forward);

86 }

每项处理都封装成一个方法,对struts控制器的扩展,可以继承这两个类,然后覆盖以上方法。

具体看一下processActionCreate方法:

protected Action processActionCreate(HttpServletRequest request,

HttpServletResponse response, ActionMapping mapping)

throws IOException {

// Acquire the Action instance we will be using (if there is one)

String className = mapping.getType();

if (log.isDebugEnabled()) {

log.debug(" Looking for Action instance for class " + className);

}

// If there were a mapping property indicating whether

// an Action were a singleton or not ([true]),

// could we just instantiate and return a new instance here?

Action instance;

synchronized (actions) {

// Return any existing Action instance of this class

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

if (instance != null) {

if (log.isTraceEnabled()) {

log.trace(" Returning existing Action instance");

}

return (instance);

}

// Create and return a new Action instance

if (log.isTraceEnabled()) {

log.trace(" Creating new Action instance");

}

try {

instance = (Action) RequestUtils.applicationInstance(className);

// Maybe we should propagate this exception

// instead of returning null.

} catch (Exception e) {

log.error(getInternal().getMessage("actionCreate",

mapping.getPath()), e);

response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,

getInternal().getMessage("actionCreate", mapping.getPath()));

return (null);

}

actions.put(className, instance);

if (instance.getServlet() == null) {

instance.setServlet(this.servlet);

}

}

return (instance);

}

针对所有的请求,只实例化一个Action,因此必须注意线程安全的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: