Struts2 (1) 高级操作

236 阅读4分钟

ognl概述

  • 1: 之前web阶段,学习过EL表达式,EL表达式在jsp中获取域对象里面的值
  • 2: OGNL是—种表达式,这个表达式功能更加强大,
    • (1):struts2里面操作值栈数据
    • (2): 一般把ognlstruts2操作:和struts2标签一起使用操作值栈
  • 3: OGNL不是struts2的一部分,单独的项目,经常和struts2一起使用
    • (1): 使用ognl时候首先导入jar包,struts2提供jar

ognl入门案例

  • 1:
    • (1): 支持对象方法调用。例如: objName.methodName()
    • (2):java代码中,调用字符串.length();
  • 2: 使用struts2标签
    • (1): 使用jstl时候,导入jar包之外,在jsp页面中引入标签库
    • 使用struts2标签时候,在jsp中引入标签库
      • <%@ taglib uri="/struts-tags" prefix="s"%>:粘贴在第三行
    • (2): 使用struts2标签实现操作
	<!-- 使用`ognl+struts2`标签实现计算字符串长度·
		value属性值:ognl表达式
		 -->
	<s:property value="'haha'.length()" />

什么是值栈

概念:

  • 之前在web阶段,在servlet里面进行操作,把数据放到域对象里面,在页面中使用el表达式获取到,域对象在一定范围内,存值和取值
  • struts2里面提供本身一种存储机制,类似于域对象,是值栈,可以存值和取值。
    • action里面把数据放到值栈里面,在页面中获取到值栈数据

servlet和action区别

  • Servlet:默认在第一次访间时候创建,创建一次,单实例对象
  • Action:访问的时候创建,每次访问aciton的时候,都会创建action对象,创建对象,多实例对象
public class UserAction extends ActionSupport {

	public UserAction() {
		System.out.println("action创建了、、、、、、、、、、");
	}

	@Override
	public String execute() throws Exception {
		return NONE;
	}
}
	<package name="demo1" extends="struts-default" namespace="/">
		<action name="userAction" class="com.day2.action.UserAction"></action>
	</package>

值栈存储位置

  • 每次访问aciton的时候,都会创建action对象
  • 在每个aciton对象里面都会有一个值栈对象(只有一个)

如何获取值栈对象

  • 1: 获取值栈对象有多种方式
    • 常用方式: 使用ActionContext类里面的方法得到值栈对象
      • ActionContext context = ActionContext.getContext();:获取ActionContext类的对象
      • ValueStack stack1 = context.getValueStack();:调用方法得到值栈对象
  • 2: 每个Action对象中只有一个值栈对象

向值栈放数据

值栈的内部结构

  • 1: 第一部分root,结构是list集合
    • 一般操作都是root里面数据
    • extends ArrayList
  • 2: 第二部分context。结构map集合。
    • extends object implements Map
    • request:request对象引用
    • session:HttpSession对象引用
    • application:ServletContext对象引用
    • parameters:传递相关的参数
    • attr:一个品对象,向三个域对象放值,名称都相同setAttribute(name",value);
      • 使用attr操作,获取域对象

s:debug 标签

概念: 使用这个标签可以查看值栈结构和存储值

  • struts2里面标签<s:debug></s:debug>,使用这个标签可以查看值栈结构和存储值
    • (1): 访间action,执行action的方法有返回值,配置返回值到jsp页面中,在jsp页面中使用这个标签
    • (2):action没有做任何操作,栈顶元素是com.yap.action.ValuestackDemoAction
      • action 对象里面有值栈对象
      • 值栈对象里面有action引用
public class ValuestackDemoAction extends ActionSupport {

	@Override
	public String execute() throws Exception {
		return "success";
	}
}
	<package name="demo1" extends="struts-default" namespace="/">
		<action name="valueStackDemo1" class="com.day2.action.ValuestackDemoAction">
			<result name="success">/valueStack.jsp</result>
		</action>
	</package>
	<!-- 使用struts2标签杳看值栈结构 -->
	<s:debug></s:debug>

向值栈放数据多种方式

  • 1: 获取值栈对象,调用值栈对象里面的set方法
    • ActionContext context = ActionContext.getContext();
    • ValueStack valueStack = context.getValueStack();:获取值栈对象
    • valueStack.set("username", "yap");:调用set方法
  • 2: 获取值栈对象,调用值栈对象里面的push方法。
    • ActionContext context = ActionContext.getContext();
    • ValueStack valueStack = context.getValueStack();:获取值栈对象
    • stack.push("abcd");:调用push方法
  • 3:action定义变量,生成变量的get方法

向值栈放对象

  • 1: 实现步骤
    • 第一步 实现对象变量
    • 第二步 生成变量get方法
    • 第三步 在执行的方法里面向对象中设置值
public class ListDemoAction extends ActionSupport {

	// 1 定义list变量
	private List<User> list = new ArrayList<User>();

	// 2 get方法
	public List<User> getList() {
		return list;
	}

	@Override
	public String execute() throws Exception {
		// 3向list中设置值
		User user1 = new User();
		user1.setUsername("小奥");
		user1.setPassword("123");
		user1.setAddress("美国");
		User user2 = new User();
		user2.setUsername("小王");
		user2.setPassword("250");
		user2.setAddress("越南");
		list.add(user1);
		list.add(user2);

		return "success";
	}
}
		<action name="ListDemo" class="com.day2.action.ListDemoAction">
			<result name="success">/valueStack.jsp</result>
		</action>
	<!-- 使用struts2标签杳看值栈结构 -->
	<s:debug></s:debug>

向值栈放list对象

  • 1: 实现步骤
    • 第一步 定义list集合变量
    • 第二步 生成变量get方法
    • 第三步 在执行的方法里面向list集合设置值
public class ObjectDemoAction extends ActionSupport {

   // 1定义对象变量
   private User user = new User();

   // 2生成get方法
   public User getUser() {
   	return user;
   }

   @Override
   public String execute() throws Exception {
   	// 向值栈的uesr里面放数据
   	user.setUsername("aaa");
   	user.setPassword("123");
   	user.setAddress("adada");
   	return "success";
   }
}

		<action name="ObjectDemo" class="com.day2.action.ObjectDemoAction">
			<result name="success">/valueStack.jsp</result>
		</action>
	<!-- 使用struts2标签杳看值栈结构 -->
	<s:debug></s:debug>

从值核获取数据

从值栈获取字符串。

  • 1: 使用struts2的标签+ognl表达式获取值栈数据
    • (1): <s:property value=”ognl表达式”>
  • 向值栈放字符串
public class ValueStackAction extends ActionSupport {

	private String username;
	public String getUsername() {
		return username;
	}

	@Override
	public String execute() throws Exception {
		username = "itcast";
		return "success";
	}
}
		<action name="valueDemo" class="com.day2.valuestack.ValueStackAction">
			<result name="success">/valueStack.jsp</result>
		</action>
	<!-- 获取字符串值 -->
	<s:property value="username"/>

从值栈获取对象

public class ValueStackAction extends ActionSupport {

	private User user = new User();
	public User getUser() {
		return user;
	}

	@Override
	public String execute() throws Exception {
		// 向值栈的uesr里面放数据
		user.setUsername("aaa");
		user.setPassword("123");
		user.setAddress("adada");
		return "success";
	}
}
		<action name="valueDemo" class="com.day2.valuestack.ValueStackAction">
			<result name="success">/valueStack.jsp</result>
		</action>
	<!-- 2获取值栈对象的值 -->
	<br /> 获取对象的值:
	<br />
	<s:property value="user.username" />
	<s:property value="user.password" />
	<s:property value="user.address" />

从值栈获取list集合

测试代码

public class ValueStackAction extends ActionSupport {

	private List<User> list = new ArrayList<User>();
	public List<User> getList() {
		return list;
	}
	@Override
	public String execute() throws Exception {
		// 3向list中设置值
		User user1 = new User();
		user1.setUsername("小奥");
		user1.setPassword("123");
		user1.setAddress("美国");
		User user2 = new User();
		user2.setUsername("小王");
		user2.setPassword("250");
		user2.setAddress("越南");
		list.add(user1);
		list.add(user2);

		return "success";
	}
}
		<action name="valueDemo" class="com.day2.valuestack.ValueStackAction">
			<result name="success">/valueStack.jsp</result>
		</action>

第一种方式

	<!-- 获取值栈list集合数据-->
	<!--第一种方式实现 -->
	<s:property value="list[0].username" />
	<s:property value="List[0].password" />
	<s:property value="list[0].address" />
	<br />
	<s:property value="list[1].username" />
	<s:property value="List[1].password" />
	<s:property value="list[1].address" />

第二种方式 通过<s:iterator>循环获取数据

	<!-- 使用struts2标签类似jstl的foreach标签
		s:iterator:遍历值栈的list集合
		
		<c:foreach items="" var="user">
			${user.username}
		</foreach>
	-->
	<s:iterator value="list">
		<!--遍历list得到list里面每个user对象-->
		<s:property value="username" />
		<s:property value="password" />
		<s:property value="address" />
	</s:iterator>

第三种方式

	<s:iterator value="list" var="user">
		<!--	
		遍历值栈list集合,得到每个user对象
		机制: 把每次遍历出来的user对象放到context里面
		获取context里面数据,特点:写ognl表达式,
		使用特殊符号 #
	
		-->
		<s:property value="#user.username" />
		<s:property value="#user.password" />
		<s:property value="#user.address" />
		<br />
	</s:iterator>

使用set/push方法向值栈放/取

    // 第一种方式使用值栈对象里面的set方法
    // 1获取值栈对象
    ActionContext context = ActionContext.getContext();
    ValueStack valueStack = context.getValueStack();
    // 调用set方法
    valueStack.set("username", "yap");
    // 调用push方法
    valueStack.push("yap");
	<!-- 获取字符串值 set中的key -->
	<s:property value="username" />
        
        <!-- 使用push方法设置值,没有名称,只有设置的值 -->
        <!-- 向值栈放数据,把向值柱放数据存到数组里面,数组名称 top,根据数组获取值 -->
        <s:property value="[0].top" />

foreach方法获取

  • <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>:如果使用foreach需要在jsp添加这串代码
<!--使用foreach标签+el表达式获取值栈list集合数据-->
	<c:forEach items="${list}" var="user">
	${user.username }
	${user.password }
	${user.address }
		<br />
	</c:forEach>

EL表达式获取值栈数据(为什么)

  • 1: EL表达式获取域对象值。
  • 2: 向域对象里面放值使用setAttribute方法,获取值使用getAttribute方法。
  • 3: 底层增强request对象里面的方法getAttribute方法。
    • (1:) 首先从request域获取值,如果获取到,直接返回
    • (2:) 如果从request域获取不到值,到值栈中把值获取出来,把值放到域对象里面

ognl表达式

#使用

  • 第一种方式
	<s:iterator value="list" var="user">
		<!--	
		遍历值栈list集合,得到每个user对象
		机制: 把每次遍历出来的user对象放到context里面
		获取context里面数据,特点:写ognl表达式,
		使用特殊符号 #
	
		-->
		<s:property value="#user.username" />
		<s:property value="#user.password" />
		<s:property value="#user.address" />
		<br />
	</s:iterator>
  • 第二种方式
    • (1:)request域放值。
    • (2:) 在页面中使用ognl获取
public class ContextAction extends ActionSupport {

	@Override
	public String execute() throws Exception {
		HttpServletRequest request = ServletActionContext.getRequest();
		request.setAttribute("req", "reqValue");
		return "success";
	}
}
		<action name="contextAction" class="com.day2.action.ContextAction">
			<result name="success">/context.jsp</result>
		</action>
	<!-- 获取context里面数据,写ognl时候,首先添加符号
		#context的key名称.域对象名称		
	-->
	<s:property value="#request.req" />

%使用

  • 1:struts2标签中表单标签
    • (1:)struts2标签里面使用ognl表达式,如果直接在struts2表单标签里面使用ognl表达式不识别,只有%之后才会识别。
public class ContextAction extends ActionSupport {

	@Override
	public String execute() throws Exception {
		HttpServletRequest request = ServletActionContext.getRequest();
		request.setAttribute("req", "reqValue");
		return "success";
	}
}
		<action name="contextAction" class="com.day2.action.ContextAction">
			<result name="success">/context.jsp</result>
		</action>
	<!-- <input type="text" name="name" value="123" value="${req }" />-->
	<s:textfield name="username" value="%{#request.req}"></s:textfield>