root和context 都有 name 先从root找name;
<body>
<%
request.setAttribute("num", 22);
List<String> names= Arrays.asList("周","吴","郑");
session.setAttribute("names",names );
%>
<s:property value="#num"/> <br>
<h1>你好啊。。。这是welcome to here</h1>
<s:iterator value="#session.names" var="name" status="obj">
<s:property value="#obj.index"/> <s:property value="name" /> <br>
</s:iterator>
<s:if test="#request.age<30">中年中产</s:if>
<s:property value="h" /> <br>
<s:property value="num" /> <br>
<s:property value="#o" /> <br>
<s:property value="person.name" /> <br>
<s:if test="person.age<12">儿童</s:if> <br>
<s:elseif test="person.age<18">少年</s:elseif> <br>
<s:else>成年</s:else> <br>
<s:iterator value="list" var="name">
<s:property value="name" /> <br>
</s:iterator>
<!--迭代 对象或集合时不用var接收,用属性取值,在root里 -->
<s:iterator value="person" var="p">
<s:property value="name" /> <br>
<s:property value="age" /> <br>
</s:iterator>
<!--迭代 对象或集合时用var接收,用#var.属性取值,在context里 -->
<s:iterator value="person" var="p">
<s:property value="#p.name" /> <br>
<s:property value="#p.age" /> <br>
</s:iterator>
<s:a namespace="/" action="hello"><!--会自动添加应用上下文路径和后缀,效果同<url> -->
<s:param name="param" value="%{'dfdfds'}"></s:param>
dfdfds
</s:a>
<s:form namespace="/" action="hello" method="post" theme="simple" >
<s:textfield name="username" />
<s:password name="password"/>
<s:radio list="{'男','女'}" name="gender"></s:radio><!-- 用{构建List} -->
<s:radio list="#{'1':'男','2':'女'}" value="2" name="gender"></s:radio><%-- value 默认值 name属性可回显 用#{构建Map} --%>
<s:checkboxlist list="#{'1':'java','2':'c','3':'VB'}" value="2" name="fav"></s:checkboxlist>
<s:select list="#{'1':'南京','2':'北京','3':'上海'}" name="city" headerKey="-1" headerValue="--请选择--"></s:select>
</s:form>
</body>
拦截器:Interceptor
------------------------------
拦截器:Struts2拦截器是在访问某个Action或Action的某个方法之前或之后实施拦截,并且Struts2拦截器是可插拔的(谁用谁引用),拦截器是AOP的一种实现.
WebWork中文文档解释:拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者自己定义在一个Action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也提供了一种可以提取Action中可重用的代码的方式。
拦截器栈(Interceptor Stack):Struts2拦截器栈就是将拦截器按一定的顺序连接成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
--------------------------------------------------------------------
拦截器在设计和程序结构上的优点:
拦截器能把很多功能从Action中独立出来,分散到不同的拦截器里面,减少了Action的代码。如此,拦截器和Action本身的功能都更单一了。当通用的功能代码被封装在拦截器里面(代码模块化),就可以对不同的Action,根据功能需要,来配置相应功能的拦截器了。提高了拦截器所实现的功能的重用性,也变相实现了装配式和可插拔式的体系结构,使得整个系统结构变得更灵活。
Struts2中Action的执行流程
----------------------------------------------------------
①.客户端发送请求;
②.该请求经过一系列的过滤器(Filter): ActionContextCleanUp,帮助Struts2和其他框架集成。例如:SiteMesh Plugin。
③.接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper,来决定该请求是否需要调用某个Action。
④.若ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。
⑤.ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类。
⑥.ActionProxy创建一个ActionInvocation的实例。
⑦.ActionInvocation实例调用Action的前后,涉及到相关拦截器(Intercepter)的调用。
⑧.一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果是一个JSP或其他页面(也可以是其他的Action链)。 JSP页面展现可使用Struts2框架中的标签(该过程会涉及ActionMapper)。
-------------------------------------------------------------------
在上述整个过程中,Struts2框架中会产生很多对象,都是由Struts2中的xwork容器负责创建的. ObjectFactoty.
Struts2之所有强大,是因为它内置了很多拦截器,Struts2框架中自定义的,可以直接拿来使用的拦截器.
不同的拦截器栈(interceptor-stack)是不同拦截器的组合,用户根据不同的需求选择不同的拦截器栈.
找到:struts-default.xml文件:
Struts2中内置的拦截器:
在struts-core-2.3.x.jar--->struts-default.xml中
------------------------------------------
常见的拦截器:
1:params拦截器
这个拦截器偷偷的把请求参数设置到相应的Action的属性去的,并自动进行类型转换。
2.modelDriven拦截器
如果Action实现ModelDriven接口,它将getModel()取得的模型对象存入OgnlValueStack中。
3.execption拦截器
顾名思义,在抛出异常的时候,这个拦截器起作用。最好把它放在第一位,让它能捕获所有的异常。
4.validation拦截器
调用验证框架读取 *-validation.xml文件,并且应用在这些文件中声明的校验。
5.token拦截器
核对当前Action请求(request)的有效标识,防止重复提交Action请求。
6.fileUpload拦截器
用来处理文件上传
7.workflow拦截器
调用Action的validate方法,一旦有错误返回,重新定位到INPUT结果视图
8.servletConfig
通过感知接口,获取感应对象
自定义拦截器:CheckLoginInterceptor:
步骤1.定义拦截器类
方式2:继承com.opensymphony.xwork2.interceptor.AbstractInterceptor类.
步骤2.在struts.xml中注册拦截器,告诉Struts2框架来帮我管理CheckLoginInterceptor.
第一步:先在<package>中声明拦截器CheckLoginInterceptor.
第二步:在<action>中来引用CheckLoginInterceptor拦截器.
package icbc.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class LoginInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
Object person = invocation.getInvocationContext().getSession().get("PERSON_IN_SESSION");
if (person==null) {
return "loginJSP";
}
return invocation.invoke();
}
}
<package name="interceptorPkg" extends="struts-default" namespace="/interceptor">
<interceptors>
<interceptor name="loginInterceptor" class="icbc.interceptor.LoginInterceptor"></interceptor>
</interceptors>
<global-results>
<result name="loginJSP">/login.jsp</result>
</global-results>
<action name="login" class="icbc.helloStruts.LoginAction"
method="execute">
<result name="success" type="chain">
<param name="namespace">/interceptor</param>
<param name="actionName">main</param>
</result>
<result name="login" type="dispatcher">login.jsp</result>
</action>
<action name="main" class="icbc.interceptor.MainAction"
method="execute">
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<result name="success" type="dispatcher">/WEB-INF/main.jsp</result>
</action>
</package>
自定义拦截器栈
<package name="interceptorPkg" extends="struts-default" namespace="/interceptor">
<interceptors>
<interceptor name="loginInterceptor" class="icbc.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="loginInterceptor"/>
</interceptor-stack>
</interceptors>
<!-- 用来设置包的默认拦截器引用 -->
<default-interceptor-ref name="myStack" />
<global-results>
<result name="loginJSP">/login.jsp</result>
</global-results>
<action name="login" class="icbc.helloStruts.LoginAction"
method="execute">
<result name="success" type="chain">
<param name="namespace">/interceptor</param>
<param name="actionName">main</param>
</result>
<result name="login" type="dispatcher">login.jsp</result>
<!-- 自己有用自己引用的拦截器 -->
<interceptor-ref name="defaultStack"/>
</action>
<action name="main" class="icbc.interceptor.MainAction"
method="execute">
<result name="success" type="dispatcher">/WEB-INF/main.jsp</result>
<!-- <interceptor-ref name="loginInterceptor"></interceptor-ref> -->
</action>
</package>
-
<package name="interceptorPkg" extends="struts-default" namespace="/interceptor"> <interceptors> <interceptor name="loginInterceptor" class="icbc.interceptor.LoginInterceptor"> <param name="unCheckLoginAction">login,logon</param> </interceptor> <interceptor-stack name="myStack"> <interceptor-ref name="defaultStack"/> <interceptor-ref name="loginInterceptor"/> </interceptor-stack> </interceptors> <!-- 用来设置包的默认拦截器引用 --> <default-interceptor-ref name="myStack" /> <global-results> <result name="loginJSP">/login.jsp</result> </global-results> <action name="login" class="icbc.helloStruts.LoginAction" method="execute"> <result name="success" type="chain"> <param name="namespace">/interceptor</param> <param name="actionName">main</param> </result> <result name="login" type="dispatcher">/login.jsp</result> <!-- 自己有用自己引用的拦截器 --> <!-- <interceptor-ref name="defaultStack"/> --> </action> <action name="main" class="icbc.interceptor.MainAction" method="execute"> <result name="success" type="dispatcher">/WEB-INF/main.jsp</result> <!-- <interceptor-ref name="loginInterceptor"></interceptor-ref> --> </action> </package>
需求:国际化的登陆界面:
准备国际化资源文件:基本名词_语言_国家.properties
中文:app_zh_CN.properties
英文:app_en_US.properties
---------------------------------
告诉Struts2框架:国际化资源文件叫什么名字.
<constant name="struts.custom.i18n.resources" value="app"/>
---------------------------------
在jsp中引入Struts2标签:<%@ taglib uri="/struts-tags" prefix="s" %>
准备国际化的login.jsp
在JSP中,获取指定的国际化信息:(先引入Struts2的标签库)
<s:text name="资源文件中的key"/>
-----------------------------------
若要让Action支持国际化,那么Action必须继承ActionSupport或者ActionSupport的子类.
在Action中获取资源信息:
通过ActionSupport类中的:
String getText(String name,String[] args);
参数: name:表示资源文件中的key
args:资源文件中指定key占位符的真实值.
返回:拼接好的一个国际化信息. -
---------------------------------------------------------------------------------------------------------------
1:访问ServletApi方式1:让Action类实现感知接口.ServletRequestAware:感知HttpServletRequest对象; 提供setterServletRequest
ServletResponseAware:感知HttpServletResponse对象; 提供setterServletResponse
ServletSessionAware:感知HttpSession对象; 提供setterServletSession
问题,和ServletAPI藕合严重;
问题:Action中感知接口的方法是谁在调用?----->servletConfig拦截器(优先于Action执行)2:访问ServletApi方式2:通过ServletActionContext工具类.
-
访问ServletApi方式3:通过ActionContext工具类,
理解ActionContext:从字面上分析,表示Action的上下文对象.ActionContext封装每一次请求的相关信息.
获取ActionContext对象:
ActionContext ctx = ActionContext.getContext();
在ActionContext中把request,session,application三大作用域都作为Map对象.
---------------------------------------------------------------------------------------------------------------------
1):获取请求参数.
原始:Map<String,String[]> params = request.getParameterMap();
现在:Map<String,String[]> params = ctx.getParameters();
2):操作request作用域:
原始:request.setAttribute(String name, Object value); Object val = request.getAttribtue(String name);
现在:ctx.put(String key,Object value); Object val = ctx.get(String name);
3):操作session作用域:
原始:HttpSession session =request.getSession();
现在:Map<String,Object> session = ctx.getSession(); 接下来就是操作Map对象
4):操作servletContext(application)作用域:
原始:ServletContext servletContext = request.getServletContext();
现在:Map<String,Object> app = ctx.getApplication();