Struts2的MVC思想以及面向AOP切面编程

1 MVC简单概述: M Model(业务逻辑模型,service层,dao层) V View(视图,html,css,js页面) C Controller(前端控制器,servlet,jsp,action) 2 Struts2MVC的流程: 客户端发送请求,struts2核心过滤器filter进行拦截处理后传递到Action --Controller Action中调用service,dao层的业务方法 ---Model Action返回结果,进行页面跳转 --View 3 Aop切面编程 精简含义:纵向重复代码,横向抽取。 典型应用: * Servlet时代,使用过滤器filter统一处理多个Servlet类的乱码问题 * Action时代,使用Interceptor拦截器将相同的参数传递给多个不同的action中

Struts2与OGNL语言(Struts的默认表达式语言)

1 概述:OGNL(Object Graph Navigation Language )对象图导航语言是一种开源表达式语言。 它可通过表达式语法,存取java对象的属性和调用java对象的方法,同时可自动实现类型转换。 2 功能:

	(1)支持对象方法调用的方式。如 objectName.method()
	(2)支持类静态方法调用和值访问,格式为:@全类名@方法名|值名,
			 如:java.lang.Math@min(xx)
	(3)支持赋值操作和表达式串联。
	(4)可访问OGNL上下文对象OGNL Context和Action上下文对象ActionContext
	(5)可操作集合对象

3 OGNL详解 (1)概述:OGNL表达式语言结构由三要素组成:表达式(Expression),根对象(Root Object),上下文环境(Context)。 <1>OGNL的表达式(规定OGNL做什么) & 它是OGNL的核心,所有OGNL操作都是针对表达式进行的。 & 它是一个带语法含义的字符串,该字符串规定了操作类型和操作内容。 & 它不仅支持链式对象访问路径,还支持在表达式中进行简单的计算。 <2>OGNL的根对象(规定对谁操作) & 它是OGNL的操作对象,它能以任意对象为根,通过OGNL可以访问该对象关联的其他对象。 & 设置了Root对象,OGNL可以对Root对象进行任何取写操作。
<3>Context对象(规定了在哪里操作) & Root对象所在的环境就是OGNL的上下文对象Context。 & 上下文对象Context是一个Map类型对象,使用表达式访问Context中的对象时, 需使用“#”号加上对象名称。 (2)OGNL的API <1>OgnlContext和Root对象的创建 //创建一个User对象作为Root对象的数据 User rootUser=new User("tom", 18); //创建一个Map集合作为OgnlContext对象的数据 Map<String,User>map=new HashMap<String,User>(); map.put("user1",new User("jack",18)); map.put("user2",new User("rose",19));

		  //创建OgnlContext对象
		  OgnlContext oc=new OgnlContext();
		  //把map数据封装到OGNLContext中
		  oc.setValues(map);
		  //将rootUser数据封装到Root
		  oc.setRoot(rootUser);
	<2>获取OgnlContext的root对象和其他对象数据。
			//获取OgnlContext中整个Root对象
			User root = (User) Ognl.getRoot(oc);
			//获取OgnlContext中Root对象的name和age的属性值
			String name = (String) Ognl.getValue("name",oc,oc.getRoot());
			int age= (int) Ognl.getValue("age",oc,oc.getRoot());
			System.out.println("root:"+root+",rootName:"+name+",rootAge:"+age); 
			
			//获取OgnlContext其他对象数据
			//获取OgnlContext内整个user1对象
			User user1 = (User) Ognl.getValue("#user1",oc,oc.getRoot());
			//获取OgnlContext内user1对象的name和age属性
			String user1_name = (String) Ognl.getValue("#user1.name",oc,oc.getRoot());
			Integer user1_age = (Integer) Ognl.getValue("#user1.age",oc,oc.getRoot());
			System.out.println("user1:"+user1+",user1Name:"+user1_name+",user1Age:"+user1_age);
	<3>修改OgnlContext的root对象和其他对象数据。
			  //修改OgnlContext中Root对象的name和age属性数据
			  Ognl.getValue("name='flower'",oc,oc.getRoot());
			  Ognl.getValue("age=100",oc,oc.getRoot());
			  //获取修改后的Root对象
			  User root = (User) Ognl.getRoot(oc);
			  System.out.println("root:"+root);
			  
			  //修改OgnlContext中其他对象user1的name和age属性
			  String user1_name = (String) Ognl.getValue("#user1.name='panda'",oc,oc.getRoot());
			  Integer user1_age = (Integer) Ognl.getValue("#user1.age=200",oc,oc.getRoot());
			  //获取修改后Context内的user1对象
			  User user1 = (User) Ognl.getValue("#user1",oc,oc.getRoot());
			  System.out.println("user1:"+user1);
	<4>OGNL的操作之调用对象方法
			  //调用 OgnlContext中root对象和user1对象的setName方法
			  Ognl.getValue("setName('root1111')",oc,oc.getRoot()); 
			  Ognl.getValue("#user1.setName('u11111')",oc,oc.getRoot());
			 
			  //取掉用方法后的root对象和user1对象
			  User root = (User) Ognl.getRoot(oc);
			  User user1 = (User) Ognl.getValue("#user1",oc,oc.getRoot());
			  System.out.println("root:"+root);
			  System.out.println("user1:"+user1);
	<4>OGNL的操作之调用工具类的静态方法
			//自定工具类MyUtils如下
			public class MyUtils {
				//回音方法
				public static Object echo(Object o) {
					return o;
				}
			}
			 //调用 自定义工具类静态方法格式:@+完整类名+@静态方法
			  String value = (String) Ognl.getValue("@cn.xx.MyUtils@echo('hello flower')",oc,oc.getRoot());
			  System.out.println(value);
			  //调用 jdk内置工具类 Math的静态属性 PI
			  Double pi=  (Double) Ognl.getValue("@java.lang.Math@PI",oc,oc.getRoot());
			  Double pi2=  (Double) Ognl.getValue("@@PI",oc,oc.getRoot());//简写 
			  System.out.println(pi2);
	<5>GONL的操作之 存储List单列集合对象数据到OgnlContext内,注意这里没有  用到 #  号
			  //在OgnlContext内创建List集合对象--注意里面元素字母超过一个才可识别字符串,否则作为字符集合处理
			  Ognl.getValue("{'aa','bb','cc'}",oc,oc.getRoot());
			  //从OgnlContext里重新获取整个list集合对象以及集合的其他数据
			  List<String> list = (List<String>) Ognl.getValue("{'aa','bb','cc'}",oc,oc.getRoot());
			  Integer size = (Integer) Ognl.getValue("{'aa','bb','cc'}.size()",oc,oc.getRoot());
			  String name1 = (String) Ognl.getValue("{'aa','bc','cc'}[0]",oc,oc.getRoot());
			  String name2 = (String) Ognl.getValue("{'aa','bc','cc'}.get(0)",oc,oc.getRoot());
			  System.out.println("list:"+list+";\n"+"listSize:"+size+
								";listName1:"+name1+";listName2:"+name2);
	<6>GONL的操作之 存储Map双列集合对象数据到OgnlContext内,注意这里用到了 # 号
		  //创建Map双列集合--用#识别
		  Ognl.getValue("#{'name':'zs','age':18}",oc,oc.getRoot());
		  //获取整个Map集合以及Map集合的数据
		  HashMap<String,Object> map =
			(HashMap<String, Object>) Ognl.getValue("#{'name':'zs','age':18}",oc,oc.getRoot());
		  Integer size2 = (Integer) Ognl.getValue("#{'name':'zs','age':18}.size()",oc,oc.getRoot());
		  String name3 = (String) Ognl.getValue("#{'name':'zs','age':18}['name']",oc,oc.getRoot());
		  String name4 = (String) Ognl.getValue("#{'name':'zs','age':18}.get('name')",oc,oc.getRoot());
		  System.out.println(map+"\n"+size2+";"+name3+";"+name4);
(3)Ognl总结
	Ognl表达式语言,其运行在一个上下文对象环境OgnlContext里,
	该环境由Root对象和一个Map集合类型的Context组成。

Struts2的值栈(ValueStack)

1 概述 (1)值栈ValueStack的产生: Ognl表达式要想运行必须有Ognl环境OgnlContext。 struts2为结合Ognl技术,产生了一个OgnlContext,名为ValueStack。 ValueStack由两个部分组成,一部分为Root,是一个栈, 另一部分为ActionContext数据中心,是一个map集合。 (2)值栈特点: & 值栈ValueStack是Struts2的一个接口,OgnlValueStack是ValueStack的实现类。 & 客户端发送请求,struts2创建一个Action实例的同时创建一个OgnlValueStack值栈实例。 & struts2通过OGNL在值栈中存取,读写Action参数数据。 2 OgnlValueStack的内部结构 (1) 概述:OgnlValue包括两部分,值栈(CompoundRoot)和 Map<String,Object>Context(ognl的上下文对象 OgnlContext). (2) CompoundRoot细述 <1>它作为OgnlContext的Root对象,存储action实例数据。 <2>它继承了ArrayList实现压栈和出栈功能,拥有先进后出的特点,我们称其为对象栈。 CompoundRoot中的Action实例位于栈顶,struts2会先从栈顶的Action实例查找相应的属性, 若找不到则从栈顶往下找其他对象。 <3>CompoundRoot(自定义栈)是struts2对Ognl的Root使用的改进, 调用OgnlValueStack的findValue()方法即可查找CompoundRoot栈中的对象及其属性。 (3)OgnlContext细述 <1>它是一个Map<String,Object>结构,存储一些引用,parameters,request,session,application,attr等. <2>Ognl的一些引用 & parameters:该Map为当前请求的请求参数。 & request:该Map为request域中的数据 & session:该Map为session域中的数据 & appliaction:该Map为application域中的数据。 & attr:该Map按如下顺序检索以上对象,request,session,application 3 ValueStack细述 (1) ActionContext和ValueStack的关系 * Struts2创建ActionContext的同时也创建ValueStack值栈对象。 * ActionContext内有一个ValueStack的引用,ValueStack内也有一个ActionContext的引用。 * ActionContext获取ServletApI依赖ValueStack值栈。 (2)ValueStack相应ApI操作 <1>获取值栈对象 * 方式一(通过ActionContext): ValueStack valueStack = ActionContext.getContext().getValueStack(); * 方式二(通过ServletActionContext): String vs=ServletActionContext.STRUTS_VALUESTACK_KEY; ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(vs); <2>操作值栈对象 * 方式一:在Action中 提供get方法的方式 因为Action本身在值栈中,所以可通过属性的get()方法从值栈中获取Action的属性值。 * 方式二:手动操作值栈 调用值栈的push和set方法手动操作值栈中数据。 <3>struts2的El表达式 * #号的使用 & 获取值栈中的 上下文对象OgnlContext内的数据,如request的数据 示例:<s:property value="#request.name"/> &遍历集合的值 <s:iterator value="#{'aaa':'111','bbb':'222' }" var="entry"> <!--第一种形式--> <s:property value="#entry.key"/> <s:property value="#entry.value"/> ------------------------------ <!--第二种形式--> <s:property value="key"/> <s:property value="value"/> </s:iterator> * %号的使用 & 强制解析Ognl的表达式 <s:textfield name="name" value="%{#request.name}"></s:textfield> & 强制不解析Ognl的表达式 <s:property value="%{'#request.name'}"/> * $号的使用 在struts2配置文件中书写ognl表达式时使用。

Struts2结合ognl技术封装数据的过程

1 属性驱动 (1)客户端发送请求参数,struts2的param拦截器进行拦截,ognl对参数进行处理。 (2)ognl先从ValueStack值栈的Root栈里获取 Action实例里的 相关属性,为该属性赋值。 2 对象驱动 (1)客户端发送请求参数,struts2的param拦截器进行拦截,ognl对参数进行处理。 (2)ognl先从ValueStack值栈的Root栈里获取 Action实例里的 相关对象,为该对象属性赋值。 3 模型驱动 (1)客户端发送请求参数,struts2的param拦截器进行拦截,ognl对参数进行处理。 ()ognl先从ValueStack值栈的Root栈里获取 Action实例里的 相关对象,为该对象属性赋值。