对象呢?原因是struts2对HttpServletRequet进行了一次封装,封装的代码主要是重写了getAttribute方法,简述重写此方法的核心代码:首先在原始的HttpServletRequest对象中查找el表达式中的属性,如果找不到再通过ActionContext获取值栈对象,进而再从值栈对象中查找el表达式中要访问的属性。 2.OGNL入门
下面我们在com.asm.vo.User类中增加一个字段private Address addres;,并提供此字段的get/set方法,随后再在login.jsp中增加如下代码:
城 市:
然后再在loginSuc.jsp中增加如下代码:
获取城市属性:
然后测试,会得到登录时输入的城市信息(中文会有乱码)。下面借助此例谈ognl的定义:在这个例子中,我们的LoginAction中有一个User对象,而在User对象中又有一个Address对象,这些对象之间依靠这种类的字段进行关联,或者说是依靠字段属性进行导航,这也就是OGNL的定义:Object Graph Navigation Language:对象图导航图语言,它是建立在值栈技术之上的一种全新语言。
补充:用%{}可以取出存在值堆栈中的Action对象,直接调用它的方法.我们在loginSuc.jsp中增加如下内容调用LoginAction中的get方法:
调用值栈对象中的方法:
LoginACtion中增加的get方法如下:
public String get(){ }
return \这是User中的get方法\;
3.普通方法访问
首先在User中增加一个成员方法,代码如下:
public String get(){ }
return \这是User中的get方法\;
在LoginAction中也有类似的get方法,随后再在loginSuc.jsp中增加如下代码:
调用值栈对象中的普通方法(2):
调用值栈对象中的普通方法(1):
调用LoginAction中的普通方法:
最后测试,发现这些方法都可以访问到。 4.静态方法访问
在LoginAction中增加如下方法:
public static String getSta() { }
return \这是LoginAction中的静态方法\;
然后在loginSuc.jsp中增加如下代码:
调用Action中的静态方法:
调用LoginAction中的静态方_方式(2):
说明:我们在方式二中用到@vs,只有那些值栈中的对象才可以这样写。 然后访问,发现访问不到,因为在struts2.1.6的版本中,struts.ognl.allowStaticMethodAccess的默认值为false,我们只需在struts.xml中增加如下内容:
在loginSuc.jsp中增加如下代码:
调用Math类中的静态方法:
21
调用Math类中的静态方法_方式(2):
调用Math类中的字段:
说明:因为是默认的类,所以可以省略类名 6.调用普通类的构造方法
建立一个新的类:Student,在此省略代码。 然后在loginSuc.jsp中增加如下代码:
调用普通类中的构造方法 :
调用普通类中的构造方法并访问其字段 :
说明:第一种是只new出对象,显示的时候其实是调用对象的toString方法。 7.集合对象初步
首先在LoginAction中增加如下字段并提供相应的get/set方法:
private List myList = new ArrayList(); private Set mySet = new HashSet(); private Map myMap = new HashMap();
然后再在execute方法中初始化这些集合对象,代码如下:
myList.add(\); myList.add(\); myList.add(\); myList.add(\);
mySet.add(\); mySet.add(\); mySet.add(\); mySet.add(\);
myMap.put(\, \); myMap.put(\, \); myMap.put(\, \);
最后在loginSuc.jsp中增加如下代码:
获取List:
获取List中的第一个元素:
获取Set:
获取Set中的第一个元素(set无序,不能取到):
获取Map:
获取Map中的key=m1的元素的值:
方式一:
方式二:
获取List的大小:
获取Map中所有键:
获取Map中所有值:
最后测试,这些东西不多作解释。 8.集合对象进阶
首先在LoginAction中增加如下字段并提供相应的get/set方法: private List studentList = new ArrayList();
22
然后再在execute中为其初始化赋值,代码如下:
studentList.add(new Student(\, 20, 86.0f)); studentList.add(new Student(\, 22, 96.5f)); studentList.add(new Student(\, 23, 56.5f));
最后在loginSuc.jsp中增加如下代码:
获取List中的Student对象:
利用投影获取List中的name属性:
利用投影获取List中的age属性:
利用投影获取List中的第一个对象的name属性:
或者
利用选择获取List中grade>60的student信息:
利用选择获取List中grade>60的student名字信息:
利用选择获取List中grade>60的第一个student名字信息:
利用选择获取List中grade>60的第一个student名字信息(链表):
利用选择获取List中grade>60的最后一个student名字信息(链表):
说明:这里重点是说明?#的使用,结合此例来看,studentList中有许多Stutdent对象,我们可以用条件来限制取哪些对象,这些条件必须以?#开始,并且条件要用{}括起。而this是指在判断studentList中的对象是否符合条件的当前对象。?#是指取出符合条件的所有Student对象,而^#是指取出符合条件的第一个对象,$#是指取出符合条件的最后一个对象。 9.N语法top语法
我们在loginSuc.jsp中增加如下下代码:
N语法[0]:
N语法[1]:
N语法[0].top:
N语法[1].top:
N语法top:
N语法取值:
N语法取值:
说明:规定栈顶的对象为[0],而我们只使用[0]的意思是从值栈中第一个对象取,一直取至栈底。N的意思是从值栈中的第N个对象开始,取到栈底为止。如果要想访问某个对象,需要使用[N].top,它的意思是取出符合N语法的栈顶对象,比如在这里,[0]会取出两个对象,而[0].top是取出这两个对象的栈顶对象。纯top可以简洁地取出值栈中的栈顶对象。
为什么要提出N语法,当我们通过chain链访问时,值栈中可能有两个以上的Action对象,如果这些对象中存在相同的属性,N便能正确区分他们。通常,这些Action对象的入栈顺序是:先访问先入栈。 从上面的N语法取值实例中,我们知道[N]top语法的一个重要作用就是能通过它们引用值栈对象中的属性。结合前面的五种[N]top语法实例,不难理解这里的取值实例。
补充:在此实例中,我们用
我们知道,除了可以从值栈中获取信息,还可以从Stack Context中获取信息,只是要加上#,下面我们通过scope对象来演示。首先是在LoginAction中增加如下字段:
23
Map myRequest; Map mySession;
随后再用前面提到的“在Action中获取Scope对象”的方式二来完成这些对象的初始化。即实现RequestAware和SessionAware接口。然后再在execute方法中增加如下内容:
myRequest.put(\, \属性\); mySession.put(\, \属性\);
最后在loginSuc.jsp中增加如下代码:
获取Request属性:
获取Session属性:
获取parameters属性:
说明:我们获取这些对象都用了#,因为这些对象都是存在一般的Context Map中,而不是存在值栈中。别最后一个信息的获取是因为我们在login.jsp中增加了如下代码:
关于这些scope的更多信息可以参看下表: 名称 parameters 作用 例子 #parameters.id[0]作用相当于包含当前HTTP请求参数的Map request.getParameter(\包含当前HttpServletRequest#request.userName相当于request.getAttribute(\的属性(attribute)的Map 包含当前HttpSession的属性(attribute)的Map #session.userName相当于session.getAttribute(\request session application Attr 包含当前应用的ServletContext#application.userName相当于的属性(attribute)的Map application.getAttribute(\用于按request > session > #application.userName相当于application顺序访问其属性 application.getAttribute(\11.总结$ # %的区别 $用于i18n和struts配置文件 #取得ActionContext的值
%将原来的文本串解析为ognl,对于本来就是ognl的文本不起作用。形式:%{要解析的文本串} 12.总结OGNL[重点]
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。Struts2使用OGNL作为默认的表达式语言。
相对于EL表达式,它提供了平时我们需要的一些功能,如:支持对象方法调用,支持各类静态方法调用和值访问,支持操作集合对象。OGNL有一个上下文的概念,这个上下文件实质就是一个Map结构,它实现了java.utils.Map接口,在struts2中上下文的实现为ActionContext,下面是上下文的结构示意图:
24
ValueStack(值栈,它是根对象) OgnlValueStack对象的[List] root变量 Parameters OGNL Context request session application attr 当struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action。然后把action存放进ValueStack,所以action的实例变量可以接受OGNL访问。
访问上下文中的对象需要使用#号标注命名空间,如#application、#session。另外OGNL会设定一个根对象,在struts2中根对象就是ValueStack值栈对象,如果要访问根对象中对象的属性,则可以省略#命名空间,直接访问该对象的属性即可。在struts2中,根对象的实现类为OgnlValueStack,该对象不是我们想象的只存放单个值,而是存放一组对象,在OgnlValueStack类里有一个List类型的变量,就是使用这个List变量来存放一组对象。在root变量(List类型)中处于第一位的对象叫栈顶对象,通常我们在Ognl表达式里直接写上属性的名称即可访问root变量里对象的属性,搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下寻找。 注意:struts2中 ,OGNL表达式需要配合struts的标签才可以使用。
五、拦截器
在前面我们已经初步使用过拦截器,下面继续细细探讨。 1.概述strust2中的拦截器
拦截器是Struts2框架的核心,它主要完成解析请求参数、将请求参数赋值给Action属性、执行数据校验、文件上传等工作。Struts2设计的灵巧性,拦截器起了关键性的作用,当需要扩展Struts2功能时,只需要提供对应拦截器,并将它配置在Struts2容器中即可;如果不需要该功能时,也只需要取消该拦截器的配置即可。
Struts2内建了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default. xml文件中,其中name是拦截器的名字,就是以后我们使用该拦截器的唯一标识;class则指定了该拦截器的实现类,如果我们定义的package继承了Struts2的默认struts-default包,则可以自由使用它下面定义的拦截器,否则必须自己定义这些拦截器。 2.自定义拦截器
自定义拦截器需要特别注意的是不要忘记引入struts2默认的拦截器。为了实现某些操作,我们可以自定义拦截器,自定义拦截器有三种方式定义。分别为实现Interceptor接口,继承抽象类AbstractInterceptor,继承MethodFilterInteceptor类。 方式一,实现Interceptor接口。
准备工作,新建struts2interceptor项目。构建一个登录环境:当我们点登录链接时,便成功登录(为了方便,这里不进行验证)。即在link.jsp页面中写如下链接:
href=\<%=request.getContextPath()%>/login.action\>登录 然后,我们点击此链接便可以登录。login.action在strutst.xml中的的配置如下:
25