struts2框架自带项目struts2-mailreader学习笔记
struts2框架自带项目struts2-mailreader学习笔记
我们依照使用该项目的步骤来说。
第一、一个网页请求转到welcome.do的网页,我们去查看web.xml中的配置,发现要调用StrutsPrepareAndExecuteFilte这个过滤器。而这个过滤器是干什么用的呢?
查看源代码我们发现:
1.StrutsPrepareAndExecuteFilte 实现了Filter接口。
服务器启动调用StrutsPrepareAndExecuteFilter .init()初始化来初始化几个重要的类,比如Dispatcher,FilterHostConfig。
2.当前台有请求发来,StrutsPrepareAndExecuteFilter 的doFilter()被调用,这个doFilter实现了封装request,查找 ActionMapper,以确定这个请求是否需要调用某个 Action。
那么,为什么使用StrutsPrepareAndExecuteFilter而不是用FilterDispatcher呢?可参见http://wellfrog.iteye.com/blog/773482
在这里,还要注意,项目源码为:
execute.executeAction(request, response, mapping);
public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException { dispatcher.serviceAction(request, response, servletContext, mapping); }:Configuration config = configurationManager.getConfiguration(); ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( namespace, name, method, extraContext, true, false); request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack()); // if the ActionMapping says to go straight to a result, do it! if (mapping.getResult() != null) { Result result = mapping.getResult(); result.execute(proxy.getInvocation()); } else { proxy.execute(); }<action name="Welcome" name="code"><include file="mailreader-default.xml"/><include file="mailreader-support.xml"/>
<action name="Welcome" name="code"><interceptor-stack name="guest" > <interceptor-ref name="defaultStack"/> </interceptor-stack>代表这个guest拦截器是一个拦截器栈,使用的是defaultStack这个拦截器栈,在struts2-core-xxx.jar包下找到struts-default.xml,再在其中找到如下代码:
<interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="i18n"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="debugging"/> </interceptor-stack> <!-- The completeStack is here for backwards compatibility for applications that still refer to the defaultStack by the old name --> <interceptor-stack name="completeStack"> <interceptor-ref name="defaultStack"/> </interceptor-stack>
<s:url id="en" action="Welcome"> <s:param name="request_locale">en</s:param> </s:url><s:a href="%{en}">English</s:a><s:url id="en" action="Welcome">的id,现在应该使用var属性取代,它的作用是:<s:text name="index.title"/>
<li><a href="<s:url action="Registration_input"/>"><s:text name="index.registration"/></a></li>
<s:actionerror/><s:form action="Registration_save" validate="false"> <s:token /> <s:hidden name="task"/> <s:if test="task == 'Create'"> <s:textfield key="username"/> </s:if> <s:else> <s:label key="username"/> <s:hidden name="username"/> </s:else> <s:password key="password" showPassword="true"/> <s:password key="password2"/> <s:textfield key="user.fullName"/> <s:textfield key="user.fromAddress"/> <s:textfield key="user.replyToAddress"/> <s:if test="task == 'Create'"> <s:submit key="button.save" action="Registration_save"/> <s:reset key="button.reset"/> <s:submit action="Welcome" key="button.cancel" onclick="form.onsubmit=null"/> </s:if> <s:else> <s:submit key="button.save" action="Registration"/> <s:reset key="button.reset"/> <s:submit action="MainMenu" key="button.cancel" onclick="form.onsubmit=null"/> </s:else></s:form>
<s:text name ="资源文件中中定义的key">输出国际化b.使用struts2标签的key属性,此时一定要注意theme不能设置为simple,否则不能成功引用国家化文件,如<s:textfield name =“name”key ="资源化文件中的key">。c.使用<s:i18n></s:i18n>在对应资源文件中查找如
<s:i18n name = "globalMessages"> <s:text name ="username"></s:text> </s:i18n>
<s:textfield label ="%{getText("username")}" name = "username">其中%{}是取出值栈中的Action对象 然后我们直接调用它的相应方法取出这个username属性。或者说我们对这个值栈中的action对象我们调用它相应的方法。this.addFieldError(username,this.getText("username.invalid"));this.addActionError(this.getText("username.invalid"));<result type="redirectAction">MainMenu</result>默认的name为SUCCESS。得到这个主页面,然后也有两个链接,
<s:if test ="task=='Edit'">这里就显示相应的编辑信息。
<validators> <field name="username"> <field-validator type="requiredstring"> <message key="error.username.required"/> </field-validator> </field> <field name="user.fullName"> <field-validator type="requiredstring"> <message key="error.fullName.required"/> </field-validator> </field> <field name="user.fromAddress"> <field-validator type="requiredstring"> <message key="error.fromAddress.required"/> </field-validator> <field-validator type="email"> <message key="errors.email"/> </field-validator> </field> <field name="user.replyToAddress"> <field-validator type="email"> <message key="errors.email"/> </field-validator> </field></validators>如果我们要使用上述客户端校验框架,我们必须在所检验的字段的这个页面的form标签中将<s:form validate="true">的validate属性设置为TRUE,并且不能将<s:form theme="">的theme属性设置为simple,我的理解是,我们使用simple主题,排版中就不会有错误信息显示的地方了。设置<s:form validate = "true">属性之后,表单的onsubmit="return validateForm_register();"即在源码中多出了一段函数名为validateForm_register()的JavaScript代码,调用完成后再提交到相关页面。