1, 当Action设置了某个属性后,Struts将这些属性封装一个叫做Struts.valueStack的属性里。获取valueStack对象: ValueStack vs = (ValueStack) request.getAttribute("struts.valueStack");
   调用ValueStack 的vs.findValue("books")方法(books为Action中的属性);

2, struts2的Action类是一个普通的POJO类(通常包含一个无参的execute方法)从而很 好的重用代码。

4,struts2通常直接使用Action来封装HTTP请求参数,所以Action中要定义与请求参数对应的属性,并且为该属性提供相应的 getter和setter方法。

5,即使Action需要处理的请求name和pass两个HTTP请求参数,Action类也可以不包含name和pass属性,因为系统是通过对应的 getter和setter方法来处理请求参数。而不是通过属性来处理请求参数的。所以Action类是否包含name和pass属性不重要, 重要的是需要setter和getter方法。

6,Action类的属性,不仅可以封装请求参数,还可以用于封装处理结果,通过Struts2标签来输出对应的属性值。如 <s:Property value="tip">。

7,ActionContext类。Struts2的Action并未直接与任何Servlet api耦合,从而更加方便测试该Action(可以通过脱离web容器测试Action)。但是对于Web应用的控制器来说,不访问Servlet api 几乎是不能的。例如跟踪HTTP session状态等。访问的Servlet Api 就 是HttpServeltRequest、HttpSession、ServletContext,这三个类分别jsp内置对象中的request、session、application。Web应用中提供了一个ActionContext类,Struts2的Action可以通过该类来访问Servlet api。
该类的ActionContext提供getContext方法得到ActionContext实例,
  该类的方法:
   ①Object get(Object key),该方法类似于HttpServletRequest的getAttribute(String name)方法;
   ②Map getApplication(),返回Map对象,该对象模拟了应用的ServletContext的实例
   ③static ActionContext getContext(),静态方法,获得系统提供的ActionContext实例。
   ④Map getParameters()获取所有的请求参数,类似于调用HttpServletRequest对象的getParammeterMap方法。
   ⑤Map getSession()该Map对象模拟了HttpSession实例。
   ⑥void setApplication(Map application)直接传入一个Map实例,将该Map实例的key-value对转换成application的属性名、属性值。类似的还有setSession(Map session)
   ⑦put(Object key, Object value)直接为HttpServletRequest设置属性。相当于request.setAttribute(key,value).可通过EL表达式输出。

8,ServletActionContext类(是ActionContext类的子类)。 虽然Struts2提供了ActionContext来访问Servlet Api,但是这种访问毕竟不能直接获得Servlet Api实例,为了Action中 直接访问Servlet api,Struts2提供了如下的接口:ServletContextAware、ServletRequestAware、ServletResponseAware 。如果Action实现这些接口,能分别直接访问用户请求的ServletContext、HttpServletRequest、HttpServletResponse实例。
  并且,为了直接访问Servlet api。Struts2提供了一个ServletAction类。通过ServletActionContext类可以更加方便的地直接访问Servlet api。这类的主要方法(全是static):
   ①getActionContext(HttpServletRequest req)得到当前的ActionContext实例。
   ②getActionMapping()得到ActionMapping实例(得到 action mapping为context)。
   ③getRequest()得到HttpServletRequest实例(Gets the HTTP servlet request object)。
   ④getResponse()得到HttpServletResponse实例(Gets the HTTP servlet response object.)
   ⑤getServletContext()得到ServletAction实例(Gets the servlet context.)
   ⑥getValueStack(HttpServletRequest req)得到ValueStack实例。
   ⑦setRequest(HttpServletRequest request)(Sets the HTTP servlet request object)相应的有setResponse(HttpServletResponse response)、setServletContext(ServletContext servletContext)。

9,虽然可以在Action类获取HttpServletResponse,但如果希望通过HttpServletResponse来生成服务器响应是不可能的,因为Action只是控制器(它并不直接对浏览器生成任何相应)。即如果在Action中写如下代码:response.getWriter().println("hello world");
是没有意义的。

10,对于使用Struts2框架的应用而言,尽量不要让超级链接链接到某个视图资源,
因为这种方式增加了额外的风险,推荐将所有请求都发给Struts2框架,让该框架来处理用户的请求,
即使是简单的超级链接。

11,逻辑视图名是指:Action返回的字符串;物理视图是指:页面的实际名称。
Struts2通过配置逻辑视图名和物理视图之间的映射关系,一旦系统收到Action返回的某个逻辑视图,系统就会把相应的物理视图呈现给用户。

12,默认值:如果配置<result../>元素时没有指定location参数,系统将会把<result..>...<result../>中间的字符串当成实际视图资源。如果没有配置parse参数,则默认值为true(该参数指定实际视图名是否可以使用OGNL表达式);如果没有指定name属性则默认值为Struts2的默认处理结果类型(dispacher).

13,归纳起来,Struts2内建支持结果类型如下(14):
   ①chain结果类型:Action链式处理结果类型。
   ②chart结果类型:用于整合JFreeChart的结果类型。
   ③dispatch结果类型:用于jsp整合的结果类型。
   ④freemarker结果类型:FreeaMarker整合的结果类型。
   ⑤httpheader结果类型:用于控制Http行为的结果类型。   
   ⑥jasper结果类型:用于JasperReports整合的结果类型。
   ⑦jsf结果类型:用于整合JSF整合的结果类型。
   ⑧redirect结果类型:用于直接跳转到其他的URI的结果类型。
   ⑨redirectAction结果类型:用于直接跳转到其他的Action的结果类型。
   ⑩stream结果类型:用于向浏览器返回一个InputStream(一般用于文件下载)。
   ⑾tiles结果类型:用于与Tiles整合的结果类型。
   ⑿velocity结果类型:用于与Velocity整合的结果类型。
   ⒀xslt结果类型:用于与XML/XSLT整合的结果类型。
   ⒁plainText结果类型:用于显示某个页面的原始代码的结果类型。

14,【redirect】结果类型。
   这种结果类型与dispatch结果类型相对,dispatch结果类型是将请求Forward(转发)
到指定的jsp资源。而redirect结果类型,则意味着将请求Redirect(重定向)
到指定的视图资源。
   dispatch结果类型与redirect结果类型的差别就是转发和重定向的差别:
重定向会丢失所有的请求参数和请求属性---当然也会丢失Action的处理结果。
   使用redirect结果类型的效果是:系统将调用HttpServletResponse的sendRedirect(String)方法来重定向指定的视图资源,这种重定向的效果就是重新产生一个请求。所以所有的请求参数、请求属性、Action实例和Action中封装的属性全部丢失。

15,【redirectAction】结果类型.
   使用redirectAction结果类型时,系统将重新生成一个新的请求,
只是该请求的URI不是一个具体的试图资源,而是一个Action。因此前一个Action处理结果
,请求参数,请求参数都会丢失。

16,除了可以通过通配符来配置Action(result),还可以使用OGNL表达式,这种
用法允许让请求参数来决定结果。如:
<action name="save" class="......." method="save">
<result name="input">/..jsp</result>
<result type="redirect" >edit.action?skillName=${currentSkill.name}</result>
</action>
对于上面的表达式语法,要求对应的Action实例里应该包含currentSkill属性,且currentSkill属性必须包含name属性--否则,${currentSkill.name}表达式为null。

17,模型驱动:
对于Struts1的ActionForm对象而言。它的唯一作用就是封装请求参数,当Struts1拦截到用户的请求后,Struts1负责将请求参数封装成ActionForm对象。
如果Struts2的开发者怀念这种开发方式,则可以使用Struts2提供的模型驱动模式,
这种模式也通过专门的JavaBean来封装请求参数。
    相比于Struts1的Action类,Struts2的Action承担了太多的责任,既用于封装来回请求的参数,也保护了控制逻辑---这种模式实在不太清晰。出于清晰的考虑,应该采用单独的Model实例来封装请求参数和处理结果,这就是所谓的模型驱动。
   作用:Struts2的模型对象可以封装更多的信息,它不仅可以封装用户的请求参数,而且还可以封装Action的处理结果。用单独的JavaBean实例来贯穿MVC流程。
   使用模型驱动时,Action必须实现ModelDriven接口,且必须实现getModel方法,
该方法用于把Action和与之相对应的Model实例关联起来。
    简单的说,模型驱动使用单独的VO(值对象)来封装请求参数和处理结果。

18,【属性驱动】:
使用属性(Property)作为贯穿MVC流程的信息携带者,当然属性无法独立存在,他必须依附于一个对象,这个对象就是Action实例,
    简单的说,属性驱动使用Action实例来封装请求参数和处理结果。

19,Struts2的【处理异常机制】:
   在execute方法中手动捕捉异常,当捕捉到特定的异常时,返回特定的视图--但是
这种方式很是繁琐,需要在execute中书写大量的catch块,最大的缺点
还在于异常与代码耦合,一旦需要改变异常处理方式,必须修改代码!
   Struts2提供了一种声明式的异常处理方式。
在输出错误信息的jsp页面,有两种输出方式:
   ①通过struts2标签输出异常对象的message属性。<s:property value="exception.message"/>。
   ②通过struts2标签输出堆栈信息。<s:property value="exceptionStack"/>。
注意:全局异常映射的result属性通常不要使用局部结果,局部异常映射的result属性可以使用全局结果,也可以不使用。

20,对于WEB应用而言,所有的请求参数都是字符串类型的。

21,【类型转换器】:
struts2的类型转换器实际上是基于OGNL实现的,在OGNL项目中有一个TypeConverter接口,因其实现的方法过于麻烦,所以OGNL项目还提供了一个该接口的实现类:DefaultTypeConverter,通过继承该类来实现自己的转换器。
  实现自定义的类型转换需要重写DefaultTypeConverter类的convertValue方法。

22,上面的类型转换器都是基于OGNL的DefaultTypeConverter类实现的,基于
该类实现类型转换器的时候时,将字符串转化成符合类型要通过convertValue方法实现
因此我们必须先通过toType参数来判断转换的方向,然后分别实现不同的转换逻辑。
  为了简化类型转换的实现,struts2提供了一个StrutsTypeConverter抽象类(基于struts2的类转换器)
这个抽象类是DefaultTypeConverter类的子类.

23,对于以上的类型转换,我们一直只处理字符串数组的第一个元素---我们都假设请求参数是单个值。实际上,必须考虑请求参数是字符数组的情形, 假设用户信息的请求参数,名称都是user。那么这两个请求参数必须通过getParameterValues方法来获取参数。此时user请求参数必须是数组类型,或者List类型(实际上,List和数组是完全相通的)。

24,因为struts2内建的OGNL表达式的支持,那么可以用另一种方式将请求参数转换成复合类型,如(JSP页面中):
<input type=text name="user.name"/>,<input type=text name="user.pass"/>这样就不需要转换器了。
  通过这种方式也可以把字符串转换成复合类型。但需要注意以下几点:
    ①因为struts2是需要直接创建一个复合类(User类)的实例,因此系统必须为该复合类构建一个无参的构造方法。
    ②如果希望使用user.name请求参数的形式为Action实例的user属性和pass属性赋值,则必须为user属性对应的复合类型提供setName方法,因为struts2是通过该方法类为属性赋值的。当然Action类还应该包含setUser方法。

25,表单元素enctype属性指定的是表单数据的编码方式。属性有如下3个值:
    ①application/x-www-form-urlencoded:这是默认的编码方式。它只处理表单中的value属性值,采用这种编码方式会将表单域的值处理成URL编码方式。
    ②multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定的文件内容也封装到请求参数里。
    ③text/plain:这种编码方式当表单的action的属性为mailto:URL的形式时比较方便,这种方式主要适用于直接通过表单发送邮件的方式。

26,通过Action在jsp页面输出提示信息,我们可以
   ①在Action中添加一个属性(通过setXx方法设置属性值),然后通过struts2的标签(<s:properties value="xx"/>)在jsp页面输出。
   ②通过ActionContext类来处理,如:ActionContext.getContext.put(key,value);然后通过EL表达式进行输出。

27,在Form表单中action属性的值要得到【上下文路径】:
   ①<%=request.getContextPath()%>
   ②还可以通过EL表达式得到 :${pageContext.request.contextPath}

28,得到【ValueStack】的对象有哪几种方法:
   ①ServletActionContext类中的方法:static getValueStack(HttpServletRequest req)【Gets the current value stack for this request】;
   ②ActionContext类中的方法:getValueStack()【Gets the OGNL value stack.】;
   ③ValueStack vs = (ValueStack) request.getAttribute("struts.valueStack");
(request.getAttribute()返回一Object类型)

29,【拦截器】。在默认的情况下,如果我们为某个Action定义了拦截器,则这个拦截器会拦截Action的所有方法。可能在有些情况下,我们无需拦截器所有的方法,只需要拦截某些方法,此时就需要struts2拦截器的方法过滤特性。

30,struts2的【校验】,可以继承ActionSupport类重写validate方法,利用ActionSupport的addFieldError方法把错误信息通过key保存起来,在jsp页面通过struts2标签的fielderror属性输出错误信息。注意:struts2的校验在配置action的时候需要提供输入页面(就是<result name="input">)。这是对action中的所有方法进行校验。
    如果要对action中指定的方法进行校验,把validate方法名改为:validateXxx,其中Xxx是需要校验的指定方法名。

31,输入校验的流程:
   ①类型转换器把请求参数进行类型转换,并把转换后的值赋给action中的属性。
   ②如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext中,conversionError拦截器将异常信息 添加到fieldErrors中。不管类型转换是否失败都会转入第三步。
   ③系统通过反射技术调用action中的validateXxx方法。
   ④再调用validate方法。
   ⑤如果fieldErrors中存在错误信息,系统自动将请求转发至input视图。如果没有错误信息将执行action中的方法。
注意:如果validate方法里没有问题,却返回input页面,可能是类型转换有问题。所以返回input视图有两种原因(类型转换有问题或校验出错).

32,基于xml配置方式对action内所有的方法进行校验,xml文件的命名规则是:ActionClassName-validation.xml
   如果只需要对action内指定的方法进行校验,则xml文件的命名规则为:ActionClassName-ActionName-validation.xml。其 中ActionName(action的逻辑名称)。它的配置一般用通配符(有助于实验)。
   ①基于xml配置方式的校验,如果ActionClassName-validation.xml、ActionClassName-ActionName-validation.xml同时存在则把两个文件汇总,在进行校验。如果两个xml文件的校验规则起了冲突则执行后面的xml文件。
   ②如果action继承了另一个action则先找到父action校验文件,在找到子action校验文件,再把4(每个action都有指定方法名或非指定方法名)个文件汇总。

33,【国际化】。国际化按范围分为:全局、action、package的范围的资源文件。Properties文件命名的规则为:xxx_language_country.properties(xxx为用户定义的名字,第二部分为语言类别。)
  Ⅰ定义好了国际化文件后,需要在struts.xml文件配置<constants name="struts.custom.i18n.resources" value="国际化文件的名称(xxx)">[这是定义全局的国际化资源文件],可以在jsp页面显示国际化信息<s:text name="key"/>。
  Ⅱ也可以通过action类继承ActionSupport类,再调用个getText方法的资源文件的key(getText("key")).然后可以通过EL表达式在jsp页面输出。
  Ⅲ也可以通过struts2的表单标签的key属性。如<s:textfield key="key"/>或<s:textarea key="key"/>
输出带有占位符的国际化信息:
①<s:text name="key"><s:param>....</s:param>..</s:text>
②通过ActionSupport类的getText(String key,String[] str)或者getText(String key,List list)

34,包范围的国际化资源文件,
在大型的应用程序中,整个应用有大量的内容需要国际化,如果我们把国际化的内容放置在全局资源属性文件中,显然会导致资源文件变得过于庞大、臃肿,不便于维护,这个时候我们需要针对不同的模块,使用包范围来组织国际化文件。
   在java的包下创建名为:package_language_country.properties的资源文件,package为固定写法,language_country是对应的语言类别。处于该包及子包都可以访问该资源文件。当在包范围找不到对应的资源文件,然后会在全局范围内查找。

35,Action范围的资源文件。在Action所在的路径创建名为:ActionClassName_language_country.properties
如果同时存在全局、package、Action范围的国际化资源文件,系统搜索的顺序是:Action-->package-->全局范围。

36,以上三种配置有的是基于配置的国际化资源文件。我们也可以通过无配置的方式进行直接访问某个资源文件。
通过struts2标签,如:
    <s:i18n name="xxx">
       <s:text name="key">
    </s:i18n> 其中xxx是全局范围文件的名称的前缀。
如果直接想访问包范围的国际化资源文件
    <s:i18n name="com.johnny.action.package">
       <s:text name="key">
    </s:i18n> 其中package是固定写法。

37,OGNL表达式(Object Graphic Navigation Language对象图导航语言),当struts2接受一个请求时,会迅速创建ActionContext、ValueStack、action,然后把action存放在ValueStack,所以OGNL表达式可以迅速访问action实例的属性。
    OGNL表达式一般要配合Struts2标签使用。
    在struts2中,EL表达式只能访问OgnlValueStack的root里的属性。即action的属性(因为action的属性放在OgnlValueStack的root属性里)。利用OGNL表达式创建List/Map对象,<s:set var="" value="" scope=""/>scope指定变量的被放置的范围,可以为application、session、request、page和action。如果没有设置属性,则默认为OGNLContext(OGNL上下文)中,如果在OGNLContext访问时不用#,如果scope为request....中,则需要用#。value:赋给变量的值,如果没有该属性,则将ValueStack的栈顶的值赋给变量。

38,防止表单重复提交,首先要有struts的token标签。再使用系统的拦截器。

最新文章

  1. 用 namspace 隔离 DHCP 服务 - 每天5分钟玩转 OpenStack(90)
  2. mac安装 Vitual box 虚拟机(window8.1)
  3. 函数指针_typedef
  4. 转:C++中的单例模式
  5. android mvvm初探
  6. 5 个 Composer 小技巧
  7. 转:Linux 安装 Mysql
  8. Objective-C----MRC内存管理 、 自动释放池 、 面向对象三大特性及封装 、 继承 、 组合与聚合
  9. 如何在不同编程语言中获取现在的Unix时间戳(Unix timestamp)?
  10. 通过css代码使边框变圆角(ie9以下浏览器不支持)
  11. Configure Database Mirroring
  12. route命令详解与使用实例
  13. 【狼】unity3d point light 个数限制更改
  14. oracle 常用博客网址
  15. 《图解CSS3》——笔记(一)
  16. keil c51的内部RAM(idata)动态内存管理程序
  17. python 字符串探讨
  18. 利用vanitygen生成比特币个性地址的教程
  19. MySQL sum聚合函数
  20. Extjs小总结

热门文章

  1. ELK 中的elasticsearch 集群的部署
  2. php7+apache2.4 (Windows7下)安装
  3. php分享二十六:支付系统设计
  4. idea自动编译
  5. 全局获取 (Activity)Context,实现全局弹出 Dialog
  6. [Leet Code]Path Sum
  7. 星云 Android 开发工具箱
  8. [svc][op]磁盘(结构)容量计算
  9. 【Unity】7.6 自定义输入
  10. android 学习视频汇总