struts.xml由struts2的中央控制器在初始化时完成装载
在服务器启动时,会去初始化struts2的中央控制器(StrutsPrepareAndExecuteFilter),在初始化过程中会调用中央控制器的init方法,在init方法中会去读取
src下的struts.xml文件完成初始化操作,并装载进内存中,以后struts对每一次用户的请求将使用内存中的数据,而不是每次对读取struts.xml文件,提高了效率
struts2有两个重要的控制器:
1.中央控制器StrutsPrepareAndExecuteFilter,负责接收所有请求
2.Action业务逻辑控制器,负责接收单个请求
struts.xml配置文件
<struts>
<package name="" namspace="" extends="struts-default">
<action name="" class="" method="">
<result name="" type="dispatcher/chain/redirect/redirectAction">
</result>
</action>
</package>
</struts>
当用户请求时,struts会先解析url,将解析后的结构同struts.xml文件中进行匹配,当匹配当后(调用转换器,校验器,拦截器进行相关处理)
执行匹配的的Action的class类对应的方法,进行相应的处理,并返回一个字符串的结果(在次调用一次校验器)又同struts配置文件中对应的Action中的result
标签进行匹配,并返回结果
注:拦截器的实现原理是AOP,即面向切面编程
ognl的两个基本概念:表达式和上下文
ognl上下文(application,session,OgnlValueStack,request,parameter,attr)
struts2是线程安全的,每次请求都会产生一个新的Action实例,新的Action实例通过域模型将提交的参数赋值给新的Action实例的属性
Action实例每次调用结束时都会将Action实例压人值栈中,Action中的每个属性都会放入到HttpServletRequest的作用域中
Ognl的优势:
1.支持实例属性和方法的调用
<s:property value="user.name"/>
<s:property value=“user.getUserName()”/>
2.支持所有的类的静态属性和静态方法的调用
<s:property value="@com.scxh.web.vo.User@getPI()"/><br>
<s:property value="@com.scxh.web.vo.User@SCXH_NAME"/><br>
<s:property value="@java.lang.Integer@parseInt('123')"/><br>
注:
1、调用类的静态成员时其成员必须是public修饰的成员(属性或方法)
2、@符号一种调用静态成员的约定,它用在全类名(即便是java.lang包)、属性名、方法名之前
3、如果是Struts2.2.1版本之后则在调用静态方法时必须在struts.xml中添加一个常量,如下所示:
<struts>
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
<package name="scxh" extends="struts-default" namespace="/user">
<action name="dispatchAction" class="com.scxh.web.action.DispatchAction">
<result name="success" type="dispatcher">
<param name="location">/helloWorld.jsp</param>
<param name="parse">true</param>
</result>
</action>
</package>
</struts>
3.支持赋值操作和表达式串联
<s:property value="user.setUname('zhanghongmei'),user.uname"/>
注:多个表达式之间使用英文逗号分割,这里的第一个表达式是调用实例方法setUname为user对象的uname属性设置,第二个表达式是取出user对象的uname属性值
4.值栈操作
注:
1、在同一次请求与响应中,任何时候通过ActionContext获取到的值栈对象都是同
一个值栈对象,这意味着我们可以在Action中将数据推入值栈,然后在JSP中取
出值栈中的对象
2、值栈的push方法有两个作用,一是将对象推入值栈,二是将对象的属性存储到
request作用域
5.栈的上下文操作
ActionContext context=ActionContext.getContext(); //获取栈上下文
context.put(“xhname”, “sichuanxinhua”); //将对象推入栈中
String xhname=(String)context.get(“xhname”); //从栈中取出对象
注:
1、在同一次请求的任何一个位置通过ActionContext获得的上下文对象都是同一个
上下文对象,这意味着我们可以在Action中将一个键值对压入栈中,在JSP中使用
标签将其取出来显示:
<s:property value=“#xhname”/>
这里的符号#相当于ActionContext.getContext(),Struts2.2.1中,非预定义的的键
值对象访问可以省略#,但是我们还是强烈推荐都加上#,这样便于与值栈的访问模式
进行区分
2、对值栈中对象属性的访问不要加符号#,#仅仅用在栈上下文中通过键访问值,栈上
下文中还内置了一些预定义的对象,如:request、session、application、
parameters、attr等,访问时也是类同的:
<s:property value=“#request.userName”/>
对内置预定义的对象访问必须带上符号#
6、操作集合对象(过滤与投影)
假设Action类中定义如下属性并提供了相应的getter/setter方法:
private Set<Group> groups;
则JSP中可以使用标签从值栈中取出并进行过滤:
<s:property value="groups.{? #this.gid>100}[1].gname"/><br>
注:语法是:集合属性.{expression},其中?表示取后面满足条件的所有元素,#this代表集合中的每个元素,整个表达式groups.{? #this.gid>100}执行过滤之后将得到一个新的子集合,[1]表示取子集合中下标为1的元素项,最后的gname表示取出对象的gname属性
<s:property value="groups.{^ #this.gid>100}[0].gname"/><br>
注:^表示取满足条件的第一项,而$表示取满足条件的最后一项,?、^及$都是返回一个子集合,前两者返回的子集合元素数量为1,这意味着后面的下标只能取到0
<s:property value="groups.{$ #this.gid>100}[0].gname"/><br>
%{#name}:表示从值栈的map中取值
%{name}:表示从值栈的对象栈中取值
%{#request.name}:表示从request域中取值
国际化资源:
命名规范:资源键名_语言代号_国家代号.properties
messageResource_zh_CN.properties
messageResource_en_US.properties
应放位置:在classpath根目录下(开发时放置在src目录下即可)
在struts.xml文件中根标签struts下添加:
<constant name="struts.custom.il8n.resource" value="messageResource" />
国家化资源内容:键=值
zh_CN中文资源定义:
user.userName=username
user.passWord=password
loginText=login
resetText=reset
en_US英文资源定义:
user.userName=username
user.passWord=password
loginText=login
resetText=reset
国际化使用:
1、在JSP中获取国际化资源需要首先导入Struts2标签库:
<%@taglib uri="/struts-tags" prefix="s"%>
2、在JSP中使用如下标签完成国际化资源使用:
<s:text name="user.userName"/>
注:text标签的name属性值为国际化资源文件中的键名Key
3、国际化语言的自动切换显示:
浏览器在发送请求时将它当前所支持的语言一并通过请求头提交给服务器,Struts2根据请求头中的语言代号选择对应的语言并通过它内置的标签完成国际化资源显示
4、在JSP中某些Struts2标签可以直接完成国际化显示,这主要是
依赖于这些标签中的一个称为key的属性,如:
单行文本框:
<s:textfield name=“user.userName” key="user.userName"/>
多行文本框:
<s:textarea name="user.userName" key="user.userName" value="xinhua"/>
提交按钮:
<s:submit key="loginText" theme="simple"/>
重置按钮:
<s:reset key="resetText" theme="simple"/>
在key属性中指定国际化资源的键名Key即可
在Struts2的逻辑控制Action中也可以获取到国际化资源信息,这
主要依赖于ActionSupport提供的getText(String key)方法。如
@SuppressWarnings("serial")
public class UserAction extends ActionSupport{
private User user;
public String execute(){
String loginTitle=this.getText(“loginTitle”); //loginTitle是键名Key
System.out.println(loginTitle);
return ActionSupport.SUCCESS;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
注:
1、除非你安装系统时选择了英文,否则这里获取的国际化信息都是中文信息
2、除非继承ActionSupport类,否则不能享受到getText方法的使用
struts的类型转换器:
strutsTypeConverter---》defaultTypeConverter---》TypeConverter
通常我们自定义的转换器只需重写StrutsTypeConverter的convertFormString方法即可
转换器配置:
全局:
文件名为xwork-conversion.properties放在classpath路径下
局部:
针对特定的Action的属性类型转换,命名ActionName-conversion.properties放在Action类所在包中
#对于全局配置而言:Action实例属性所在类全名(含包名)=转换类全名(含包名)
com.scxh.web.vo.Point=com.scxh.type.converter.GlobalPointConverter
#对于局部配置而言:Action实例属性名=转换类全名(含包名)
point=com.scxh.type.converter.LocalPointConverter
注:
A、全局(或局部)配置文件中可以配置多个属性类(或属性名)的转换器
B、如果针对同一个Action类中的同一个属性同时配置了局部转换器和全局转换器则局部
转换器将覆盖全局转换器
C、Struts2首先选择使用域模型完成类型转换,当域模型不能完成类型转换时才考虑程序
员定义的转换器
D、如果类型转换失败则自动返回ActionSupport.INPUT视图,该视图用于说明输入的数据
不合法
struts的校验器:
在业务控制器类Action中重写ActionSupport类的validate方法即可
哪些情况称为数据校验失败,或者说校验失败的标准是什么?
struts的流程是:类型转换器--》(通过反射获取属性指向的属性实例,通过getting和setting方法进行赋值)--》校验器--》业务逻辑控制器
在此过程如果类型转换器转换失败则跳转到逻辑视图input中,同理,如果校验失败也会跳转的逻辑视图input中
在Struts2的校验器中,如果validate方法回调完成之后在以下数据结构(它们
都是线程安全的)中存在错误消息(由程序员自己定义),则认为校验出现错误:
A、ActionError:数据结构是ArrayList<String>
B、FieldError:数据结构是LinkedHashMap<String,List<String>>
拦截器:
拦截器是struts的核心,我们只需要继承struts的默认拦截器包(struts-default),在默认的拦截器包中提供了struts的许多核心功能
struts中实现了Interceptor接口的称为拦截器,该接口有一个默认的抽象实现AbstractInterceptor类(该类实现了init和destory方法),
初始之外,还有一个称为MethodFilterInterceptor的拦截器,它是AbstractInterceptor的抽象子类,它主要是提供了两个属性excludeMethods
和includeMethods,便于说明哪些方法需要被拦截,哪些方法不需要被拦截;一般我们自定义的拦截器只需要继承AbstractInterceptor抽象类就可以了
本包中定义的默认拦截器将覆盖继承的默认拦截器,Action中
为拦截器传入的参数将覆盖定义拦截器时传入的参数,Action
中不使用任何拦截器时将使用默认配置的拦截器,如果显式
使用了拦截器默认拦截器不生效
在服务器启动时,会去初始化struts2的中央控制器(StrutsPrepareAndExecuteFilter),在初始化过程中会调用中央控制器的init方法,在init方法中会去读取
src下的struts.xml文件完成初始化操作,并装载进内存中,以后struts对每一次用户的请求将使用内存中的数据,而不是每次对读取struts.xml文件,提高了效率
struts2有两个重要的控制器:
1.中央控制器StrutsPrepareAndExecuteFilter,负责接收所有请求
2.Action业务逻辑控制器,负责接收单个请求
struts.xml配置文件
<struts>
<package name="" namspace="" extends="struts-default">
<action name="" class="" method="">
<result name="" type="dispatcher/chain/redirect/redirectAction">
</result>
</action>
</package>
</struts>
当用户请求时,struts会先解析url,将解析后的结构同struts.xml文件中进行匹配,当匹配当后(调用转换器,校验器,拦截器进行相关处理)
执行匹配的的Action的class类对应的方法,进行相应的处理,并返回一个字符串的结果(在次调用一次校验器)又同struts配置文件中对应的Action中的result
标签进行匹配,并返回结果
注:拦截器的实现原理是AOP,即面向切面编程
ognl的两个基本概念:表达式和上下文
ognl上下文(application,session,OgnlValueStack,request,parameter,attr)
struts2是线程安全的,每次请求都会产生一个新的Action实例,新的Action实例通过域模型将提交的参数赋值给新的Action实例的属性
Action实例每次调用结束时都会将Action实例压人值栈中,Action中的每个属性都会放入到HttpServletRequest的作用域中
Ognl的优势:
1.支持实例属性和方法的调用
<s:property value="user.name"/>
<s:property value=“user.getUserName()”/>
2.支持所有的类的静态属性和静态方法的调用
<s:property value="@com.scxh.web.vo.User@getPI()"/><br>
<s:property value="@com.scxh.web.vo.User@SCXH_NAME"/><br>
<s:property value="@java.lang.Integer@parseInt('123')"/><br>
注:
1、调用类的静态成员时其成员必须是public修饰的成员(属性或方法)
2、@符号一种调用静态成员的约定,它用在全类名(即便是java.lang包)、属性名、方法名之前
3、如果是Struts2.2.1版本之后则在调用静态方法时必须在struts.xml中添加一个常量,如下所示:
<struts>
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
<package name="scxh" extends="struts-default" namespace="/user">
<action name="dispatchAction" class="com.scxh.web.action.DispatchAction">
<result name="success" type="dispatcher">
<param name="location">/helloWorld.jsp</param>
<param name="parse">true</param>
</result>
</action>
</package>
</struts>
3.支持赋值操作和表达式串联
<s:property value="user.setUname('zhanghongmei'),user.uname"/>
注:多个表达式之间使用英文逗号分割,这里的第一个表达式是调用实例方法setUname为user对象的uname属性设置,第二个表达式是取出user对象的uname属性值
4.值栈操作
注:
1、在同一次请求与响应中,任何时候通过ActionContext获取到的值栈对象都是同
一个值栈对象,这意味着我们可以在Action中将数据推入值栈,然后在JSP中取
出值栈中的对象
2、值栈的push方法有两个作用,一是将对象推入值栈,二是将对象的属性存储到
request作用域
5.栈的上下文操作
ActionContext context=ActionContext.getContext(); //获取栈上下文
context.put(“xhname”, “sichuanxinhua”); //将对象推入栈中
String xhname=(String)context.get(“xhname”); //从栈中取出对象
注:
1、在同一次请求的任何一个位置通过ActionContext获得的上下文对象都是同一个
上下文对象,这意味着我们可以在Action中将一个键值对压入栈中,在JSP中使用
标签将其取出来显示:
<s:property value=“#xhname”/>
这里的符号#相当于ActionContext.getContext(),Struts2.2.1中,非预定义的的键
值对象访问可以省略#,但是我们还是强烈推荐都加上#,这样便于与值栈的访问模式
进行区分
2、对值栈中对象属性的访问不要加符号#,#仅仅用在栈上下文中通过键访问值,栈上
下文中还内置了一些预定义的对象,如:request、session、application、
parameters、attr等,访问时也是类同的:
<s:property value=“#request.userName”/>
对内置预定义的对象访问必须带上符号#
6、操作集合对象(过滤与投影)
假设Action类中定义如下属性并提供了相应的getter/setter方法:
private Set<Group> groups;
则JSP中可以使用标签从值栈中取出并进行过滤:
<s:property value="groups.{? #this.gid>100}[1].gname"/><br>
注:语法是:集合属性.{expression},其中?表示取后面满足条件的所有元素,#this代表集合中的每个元素,整个表达式groups.{? #this.gid>100}执行过滤之后将得到一个新的子集合,[1]表示取子集合中下标为1的元素项,最后的gname表示取出对象的gname属性
<s:property value="groups.{^ #this.gid>100}[0].gname"/><br>
注:^表示取满足条件的第一项,而$表示取满足条件的最后一项,?、^及$都是返回一个子集合,前两者返回的子集合元素数量为1,这意味着后面的下标只能取到0
<s:property value="groups.{$ #this.gid>100}[0].gname"/><br>
%{#name}:表示从值栈的map中取值
%{name}:表示从值栈的对象栈中取值
%{#request.name}:表示从request域中取值
国际化资源:
命名规范:资源键名_语言代号_国家代号.properties
messageResource_zh_CN.properties
messageResource_en_US.properties
应放位置:在classpath根目录下(开发时放置在src目录下即可)
在struts.xml文件中根标签struts下添加:
<constant name="struts.custom.il8n.resource" value="messageResource" />
国家化资源内容:键=值
zh_CN中文资源定义:
user.userName=username
user.passWord=password
loginText=login
resetText=reset
en_US英文资源定义:
user.userName=username
user.passWord=password
loginText=login
resetText=reset
国际化使用:
1、在JSP中获取国际化资源需要首先导入Struts2标签库:
<%@taglib uri="/struts-tags" prefix="s"%>
2、在JSP中使用如下标签完成国际化资源使用:
<s:text name="user.userName"/>
注:text标签的name属性值为国际化资源文件中的键名Key
3、国际化语言的自动切换显示:
浏览器在发送请求时将它当前所支持的语言一并通过请求头提交给服务器,Struts2根据请求头中的语言代号选择对应的语言并通过它内置的标签完成国际化资源显示
4、在JSP中某些Struts2标签可以直接完成国际化显示,这主要是
依赖于这些标签中的一个称为key的属性,如:
单行文本框:
<s:textfield name=“user.userName” key="user.userName"/>
多行文本框:
<s:textarea name="user.userName" key="user.userName" value="xinhua"/>
提交按钮:
<s:submit key="loginText" theme="simple"/>
重置按钮:
<s:reset key="resetText" theme="simple"/>
在key属性中指定国际化资源的键名Key即可
在Struts2的逻辑控制Action中也可以获取到国际化资源信息,这
主要依赖于ActionSupport提供的getText(String key)方法。如
@SuppressWarnings("serial")
public class UserAction extends ActionSupport{
private User user;
public String execute(){
String loginTitle=this.getText(“loginTitle”); //loginTitle是键名Key
System.out.println(loginTitle);
return ActionSupport.SUCCESS;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
注:
1、除非你安装系统时选择了英文,否则这里获取的国际化信息都是中文信息
2、除非继承ActionSupport类,否则不能享受到getText方法的使用
struts的类型转换器:
strutsTypeConverter---》defaultTypeConverter---》TypeConverter
通常我们自定义的转换器只需重写StrutsTypeConverter的convertFormString方法即可
转换器配置:
全局:
文件名为xwork-conversion.properties放在classpath路径下
局部:
针对特定的Action的属性类型转换,命名ActionName-conversion.properties放在Action类所在包中
#对于全局配置而言:Action实例属性所在类全名(含包名)=转换类全名(含包名)
com.scxh.web.vo.Point=com.scxh.type.converter.GlobalPointConverter
#对于局部配置而言:Action实例属性名=转换类全名(含包名)
point=com.scxh.type.converter.LocalPointConverter
注:
A、全局(或局部)配置文件中可以配置多个属性类(或属性名)的转换器
B、如果针对同一个Action类中的同一个属性同时配置了局部转换器和全局转换器则局部
转换器将覆盖全局转换器
C、Struts2首先选择使用域模型完成类型转换,当域模型不能完成类型转换时才考虑程序
员定义的转换器
D、如果类型转换失败则自动返回ActionSupport.INPUT视图,该视图用于说明输入的数据
不合法
struts的校验器:
在业务控制器类Action中重写ActionSupport类的validate方法即可
哪些情况称为数据校验失败,或者说校验失败的标准是什么?
struts的流程是:类型转换器--》(通过反射获取属性指向的属性实例,通过getting和setting方法进行赋值)--》校验器--》业务逻辑控制器
在此过程如果类型转换器转换失败则跳转到逻辑视图input中,同理,如果校验失败也会跳转的逻辑视图input中
在Struts2的校验器中,如果validate方法回调完成之后在以下数据结构(它们
都是线程安全的)中存在错误消息(由程序员自己定义),则认为校验出现错误:
A、ActionError:数据结构是ArrayList<String>
B、FieldError:数据结构是LinkedHashMap<String,List<String>>
拦截器:
拦截器是struts的核心,我们只需要继承struts的默认拦截器包(struts-default),在默认的拦截器包中提供了struts的许多核心功能
struts中实现了Interceptor接口的称为拦截器,该接口有一个默认的抽象实现AbstractInterceptor类(该类实现了init和destory方法),
初始之外,还有一个称为MethodFilterInterceptor的拦截器,它是AbstractInterceptor的抽象子类,它主要是提供了两个属性excludeMethods
和includeMethods,便于说明哪些方法需要被拦截,哪些方法不需要被拦截;一般我们自定义的拦截器只需要继承AbstractInterceptor抽象类就可以了
本包中定义的默认拦截器将覆盖继承的默认拦截器,Action中
为拦截器传入的参数将覆盖定义拦截器时传入的参数,Action
中不使用任何拦截器时将使用默认配置的拦截器,如果显式
使用了拦截器默认拦截器不生效