1.在struts.xml文件中定义bean时,通常有如下两个作用
(1)创建该bean的实例,将该实例作为struts2框架的核心组件使用
(2)bean包含的静态方法需要一个值注入
注:对于绝大部分struts2应用而言,我们无需重新定义struts2框架的核心组件,也就无需再struts.xml
文件中定义bean
推荐在struts.xml文件中配置struts2常量
2.配置包时,必须指定name属性,这个属性是引用该包的keY,除此外,还可以指定一个可选的extends属
性,extends属性值必须是另外一个包的name属性,指定extends属性表示让该包继承其他包,子包可以继
承一个或多个父包中的拦截器,拦截器栈,action等配置
注意:因为struts2的配置文件是从上到下处理的,所以父包应该在子包前定义
3.默认命名空间里的action可以处理任何模板下的action请求,意思是说:如果存在URL
为/barspace/bar.action的请求,并且/barspace的命名空间下没有名为bar的Action,则默认命名空间下
名为bar的action也会处理用户请求。
4.如果请求为/login.action,系统会在根命名空间(”/“)中查找名为login的action,如果在根命名
空间中查找到了明为login的action,则由该action处理用户请求。否则,系统将转入默认空间中查找名为
login的action,如果默认的命名空间里有名为login的action,则由该action处理用户请求,如果两个命
名空间中都未找到名为login的action,则系统出现错误。
注:命名空间只有一个级别,如果请求的URL是/bookservice/seach/get.action,系统将先
在/bookservice/search的命名空间下查找名为get的action,如果在该命名空间中找到了名为get的
action,则由该action处理用户请求;如果命名空间内没有找到名为get的action,则系统将直接进入默
认的命名空间中查找名为get的action,而不会在/bookservice的命名空间下查找名为get的action
5.包含配置
<include file="struts-zlb.xml"/>
被包含的struts-zlb.xml配置文件是标准的struts2配置文件,一样包含DTD信息,struts2配置文件的根
元素等信息,通常将struts2的所有配置文件都放在web引用的WEB-INF/classes路径下,struts.xml文件
包含了其他的配置文件,struts2框架爱自动加载struts.xml文件时,从而完成加载所有配置信息
6.拦截器可以完成如下操作:
(1)进行权限控制(检查浏览者是否是登陆用户,并且是否有足够的访问权限)
(2)跟踪日志(记录每个浏览者所有请求的每个action)
(3)跟踪系统的性能瓶颈(我们可以通过记录每个action开始处理时间和结束时间,从而取得耗时较长
的action)
7.业务控制器:包含了对用户请求的处理逻辑的action类
对系统而言,封装请求参数的属性和封装处理结果的属性是完全平等的,让action类继承actionsupport
类,会大大简化action的开发,当用户配置action类没有指定class属性时,系统自动使用actionsupport
类作为默认的action处理类。
8.action访问servlet API
web引用中通常需要访问的servlet API就是HttpServletRequest,HttpSession,ServletContext,这三个类
分别代表jsp内置对象中的request,session,appliaction.struts2使用actioncontext类来访问servlet
API.
在struts2中有一个ServletActionContext的类,这个类包含几个静态方法:
(1)static PageContext getPageContext():取得web应用中的PageContext对象
(2)static HttpServletRequest getRequest():取得web应用的HttpServletRequest对象
(3)static HttpServletResponse getResponse():取得web应用的HttpServletResponse对象
(4)static ServletContext getServletContext():取得web应用中的ServletContext对象
借助servletactioncontext类的帮助,开发者可以在action中直接访问servlet API,可以避免action需
要实现XxxAware接口,虽然如此,该action依然与servlet API直接耦合,一样不利于程序的解耦,可以
通过servletactioncontext类的帮助,从而以更简单的方式来直接访问servlet API.
实例:
public HttpServletRequest getRequest(){
return ServletActionContext.getRequest();
}
public HttpServletResponse getResponse(){
return ServletActionContext.getResponse();
}
public Map<?, ?> getApplication(){
return ServletActionContext.getContext().getApplication();
}
直接调用:
HttpServletRequest request = getRequest();
HttpServletResponse response = getResponse();
SessionUser sUser = (SessionUser) request.getSession().getAttribute
(Constants.SESSION_OPERATOR_OBJECT);
疑问:
虽然可以在action类中获取httpservletresponse,但是如果希望通过httpservletresponse来生成服务器
响应是不可能的,因为action只是控制器,即如果在action中书写如下代码:
response.getWriter().println("hello world");
上面代码在标准的servlet中会生成对客户端的输出,但是在struts2的action中,没有任何的实际意义。
注:即使我们在struts2的action类中获取得了httpservletresponse对象,也不要尝试直接在action中生
成对客户端的输出。
9.action只是一个控制器,它并没有直接对浏览者生成任何响应,因此action 处理完用户请求后,
action需要将指定的视图资源呈现给用户,因此配置action时,应该配置逻辑视图和物理视图资源之间的
映射。
10.动态方法调用:使用action的不同方法来处理请求。
使用动态方法调用前必须设置struts2允许动态方法调用,开启系统的动态方法调用是通过设置
struts.enable.DynamicMethodInvocation常量完成的,设置该常量的值为true,将开启动态方法调用;否
则将关闭动态方法调用。
使用通配符:在配置<action.../>元素时,需要指定name,class和method,这三个属性都可以支持通配
符,这种使用通配符的方式是另一种形式的动态方法调用,当我们使用通配符定义action的name属性时,
相当于一个元素action定义了多个逻辑action.
11.对于使用struts2框架的应用而言,尽量不要让超级链接直接链接到某个视图资源,因为这种方式增加
了额外的风险,推荐将所有的请求否发送给struts2框架,让该框架来处理用户请求,即使只是简单的 超
级链接。
12.action仅仅负责处理用户请求,它只是一个控制器,它不能也不该直接提供对浏览者的响应,当
action处理完用户请求后,处理结果应该通过视图资源来实现,但控制器应该控制将哪个视图资源呈现给
浏览者。
struts2的action处理用户请求结束后,返回一个普通字符串---逻辑视图名,必须在struts.xml文件中完
成逻辑视图和物理视图资源的映射,才可让系统转到实际的视图资源。
如果配置<result.../>元素时没有指定location参数,系统将会把<result...>...</result>中间的字符
串当成实际的视图资源,如果没有指定name属性,则name属性采用默认值:success;如果没有指定type属
性,则采用struts2的默认结果类型。
13.结果类型决定了action处理后,下一步将执行哪种类型的动作。
dispather结果类型是将请求forward(转发)到指定的jsp资源,而redirect结果类型,则意味着将请求
redirect(重定向)到指定的视图资源。这种重定向的效果就是重新产生一个请求,因此所有的请求参数,
请求属性,action实例和action中封装的属性全部丢失。
redirect-action与redirect类型非常相似,一样是重新生成一个全新的请求,但与redirect结果类型区
别在于:redirect-action使用actionmapperfactory提供的actionmapper来重定向请求。当需要让一个
action处理完以后,直接将请求重定向(是重定向而不是转发)到另一个action时,使用这种结果类型。
<result type="redirect-action">
<param name="actionName">dashboard</param>
<param name="namespace">/secure</param>
</result>
即需要配置两个参数。actionName指定重定向的action名,namespace指定需要重定向的action所在的命
名空间。
前一个action处理结果和请求参数和请求属性都会丢失。
14.因为全局结果的影响范围是对所有的action都有效,因此如果不是需要对所有的action都有效的结果
,就不应该放在<global-result.../>元素里定义,而是应该放在<action.../>元素里定义。
15.action负责处理用户请求,而actionform专门用于封装请求参数,在struts2中,可以通过专门的
javabean来封装请求参数。实现模型驱动。对于struts1的actionform对象而言,它的唯一作用就是封装
用户的请求参数,当struts1拦截到用户请求后,struts1框架负责将请求参数封装成actionform对象。而
struts2的模型对象则封装了更多的信息,它不仅可以封装用户的请求参数,还可以封装action的处理结
果。
相比于struts1的action类,struts2的action承担了太多的责任:即用于封装来回请求的参数,也保护了
控制逻辑,处于这种考虑,这种模式确实不太清晰,处于结构清晰的考虑,应该采用单独的model实例来
封装请求参数和处理结果,这就是所谓的模型驱动。
所谓模型驱动,就是使用单独的javabean实例来贯穿整个MVC流程;与之对应的属性驱动模式,则使用属
性(Property)作为贯穿MVC流程的信息携带者,当然,属性无法独立存在,它必须依附于一个对象,这
个对象就是action实例,简单的说,模型驱动使用单独的VO(值对象)来封装请求参数和处理结果,属性
驱动则使用action实例来封装请求参数和处理结果。
模型驱动Action包含两个类:
//专门封装请求参数和处理结果的VO
public class XxxMode implements Action{
private Type1 attName1;
private Type2 attName2;
public void setAttName1(Type1 attName1){
……
}
}
除了这个用于封装请求参数和处理结果的javabean之外,必须还提供一个包含处理逻辑的action类
public class XxxAction implements Action ,ModelDriven{
public String execute(){
……
}
public Object getModel(){
……
}
}
上面的action相对于使用属性驱动的action而言,需要多实现一个modeldriver的接口,实现该接口并要
求实现Object getModel()方法----该方法用于关联action和Model之间的关系。
注:模型驱动的含义:使用模型封装了所有的数据,贯穿整个MVC流程,而模型的作用是封装用户的请求
参数和处理结果。建议使用属性驱动。
16.动态方法调用中的通配符使用。
形式一:调用相同Action中的不同方法
Xml代码
<action name="*Action" class="Jcuckoo.LoginRegistAction" method="{1}">
<result name="input">/login.jsp</result>
<result name="error">/error.jsp</result>
<result name="success">/welcome.jsp</result>
</action>
其中表达式{1}的值name属性值中第一个*的值。
如果用户请求的URL为loginAction.action,则调用Jcuckoo.LoginRegistAction中的login方法;
如果用户请求的URL为registerAction.action,则调用Jcuckoo.LoginRegistAction中的register方法;
形式二:通过匹配,调用不同的Action的execute方法
Xml代码
<action name="*Action" class="Jcuckoo.{1}Action">
<result name="input">/login.jsp</result>
<result name="error">/error.jsp</result>
<result name="success">/welcome.jsp</result>
</action>
</action> 上面没有出现method属性,故默认调用对应的execute方法
如果用户请求的URL为LoginAction.action,则调用Jcuckoo.LoginAction中的execute方法;
如果用户请求的URL为RegisterAction.action,则调用Jcuckoo.RegisterAction中的execute方法;
形式三:相同Action动态结果
Xml代码
<action name="crud_*" class="Jcuckoo.CrudAction" method="{1}">
<result name="input">/input.jsp</result>
<result name="success">/{1}.jsp</result>
</action>
当处理结果是input时,会转到/input.jsp页面
当处理结果是success时,
如果crud_create.action,则会执行Jcuckoo.CrudAction中的create方法,并且跳转到/create.jsp;
如果crud_delete.action,则会执行Jcuckoo.CrudAction中的delete方法,并且跳转到/delete.jsp;