Struts2 [OGNL, valueStack] такой простой

Java Java EE

Что такое выражения OGNL?

OGNL — это язык графической навигации по объектам — это выражение с открытым исходным кодом для управления свойствами объектов. Платформа Struts2 использует OGNL в качестве языка выражений по умолчанию.

Почему мы изучаем ОГНЛ

Изучая JSP, мы уже узнали о выражениях EL. Выражения EL также очень просты в использовании... Мы также можем использовать выражения EL в среде Struts2... Так что же хорошего в выражениях OGNL? ?

  • Поддержка вызовов методов объекта, таких как xxx.doSomeSpecial()
  • Поддержка вызова статического метода класса и доступа к значению, формат выражения [например: «@@floor(10.9)» — это метод вызова Math.floor()]
  • Поддержка операций присваивания и конкатенации выражений [на самом деле это можно сделать с помощью выражений EL]
  • Доступ к контексту OGNL (контекст OGNL) и ActionContext
  • Управление объектами коллекций [EL может только просматривать коллекции, OGNL может создавать коллекции]

OGNL — это язык выражений Struts2 по умолчанию, OGNL используется с тегами Strut2.Изучив выражения OGNL, вы сможете лучше понять работу тегов Struts2 и структуру хранения внутри Struts2.

объект valueStack

Прежде чем объяснять выражения OGNL, давайте взглянем на объект valueStack...valueStack — это ядро ​​хранилища данных Struts2....НАСПрежде всего, вы должны знать, как и где хранятся данные, а затем объяснить, как выражение OGNL извлекает данные..

valueStack также известен как объект стека значений.

  • Когда пользователь получает доступ к действию,Создайте объект Action, объект ActionContext, объект valueStack..
  • Struts2 помещает объект Action в объект valueStack..
  • Поместите valueStack в поле запроса и перейдите на страницу JSP.(key: struts.valueStack)
  • Страница JSP может использовать выражение OGNL для получения данных в стеке значений.!

这里写图片描述

Получить объект valueStack

  • В Action мы можем вручную получить объект стека значений,Есть два способа получить:
	//获取值栈对象的2种方式
	private void getVs() {
		// 获取值栈对象,方式1:
		HttpServletRequest request = ServletActionContext.getRequest();
		ValueStack vs1 = (ValueStack) request.getAttribute("struts.valueStack");
		
		// 获取值栈对象,方式2: 
		ActionContext ac = ActionContext.getContext();
		ValueStack vs2 = ac.getValueStack();
		
		System.out.println(vs1 == vs2);//true
	}
	

структура внутренней памяти valueStack

Как упоминалось выше, когда пользователь обращается к действию, будут созданы объект действия и объект стека значений.Struts2 будет хранить объект Action в объекте valueStack внутри.... тогда какова структура хранения valueStack? ? ? Давайте посмотрим

这里写图片描述

CompoundRoot

Значения объекта Action и свойства-члены Action хранятся в CompoundRoot..ComoundRoot наследует ArrayList, поэтому это структура списка.

	public class CompoundRoot extends ArrayList {}


OgnlContext

Объект OgnlContext хранит связанные объекты предметной области: запрос, ответ, сеанс и другие данные, а также реализует коллекцию Map, которая представляет собой структуру Map...

Чтобы позволить объектам домена, таким как запрос и ответ, хранить несколько значений, значения также используют структуру Map....

public class OgnlContext implements Map {}


краткое содержание

这里写图片描述

CompoundRoot содержит такие данные:

  • Объект действия и данные атрибутов члена объекта действия
  • Используйте объект ValueStack .push() для ввода данных
  • Используйте объект ValueStack .set() для ввода данных
  • Данные для других прокси-объектов

OgnlContext содержит такие данные:

  • Сохраняет все данные в CompoundRoot
  • Все данные объектов домена, такие как запрос и ответ

Значение выражения OGNL

  • Struts2 инкапсулирует объект valueStack в домен объекта запроса и передает его на страницу JSP.
  • valueStack хранит объект OgnlContext.
  • Объект OgnlContext поддерживает данные объекта CompoundRoot.
  • CompoundRoot хранит Action и другие данные

то естьБольшую часть необходимых нам данных можно получить через объект OgnlContext.

Так как же выражение OGNL получает данные в объекте OgnlContext? ? Ниже мы проходимЖестко закодированный способ объяснить:

	/**
	 * 1. Ognl表达式语言语言取值,取非根元素的值,必须用#号
	 * @throws Exception
	 */
	@Test
	public void testOgnl() throws Exception {
		// 创建一个Ognl上下文对象
		OgnlContext context = new OgnlContext();
		// 放入数据
		User user = new User();
		user.setId(100);
		user.setName("Jack");
		// 【往非根元素放入数据, 取值的时候表达式要用"#"】
		context.put("user", user);
		
		// 获取数据(map)
		// 先构建一个Ognl表达式, 再解析表达式
		Object ognl = Ognl.parseExpression("#user.name");
		Object value = Ognl.getValue(ognl, context, context.getRoot());
		
		System.out.println(value);
	}
	
	/**
	 * 2. Ognl表达式语言语言取值,取根元素的值,不用带#号
	 * @throws Exception
	 */
	@Test
	public void testOgn2() throws Exception {
		// 创建一个Ognl上下文对象
		OgnlContext context = new OgnlContext();
		// 放入数据
		User user = new User();
		user.setId(100);
		user.setName("Jack");
		// 【往根元素放入数据】
		context.setRoot(user);
		
		// 获取数据(map)
		// 先构建一个Ognl表达式, 再解析表达式
		Object ognl = Ognl.parseExpression("address.province");
		Object value = Ognl.getValue(ognl, context, context.getRoot());
		
		System.out.println(value);
	}
	

То есть, когда данные извлекаются со страницы JSP, ониСначала создайте выражение OGNL, а затем проанализируйте выражение.

  • Если это данные класса CompoundRoot, выражение не нужно помечать #
  • Если это не данные класса CompoundRoot, выражение нужно пометить #

这里写图片描述

пример:



  	<!-- 页面: 必须要拿到ValueStack -->
     <br/>1. 取根元素的值<br/>
     <s:property value="user.id"/> 
     <s:property value="user.name"/> 
     <s:property value="user.address"/> 
     <s:property value="user.address.city"/> 
     <s:property value="user.address.province"/> 
     
      <br/>2. 取非根元素的值<br/>
      <s:property value="#request.cn"/>
      <s:property value="#session.Session_data"/>
      <s:property value="#application.Application_data"/>    <br/>
     
      <!-- 自动找request/session/application,找到后立刻返回 -->
      <s:property value="#request_data"/>
      <s:property value="#attr.Session_data"/>
      <s:property value="#attr.Application_data"/>  <br/>
      
      <!-- 获取请求的参数数据 -->
      <s:property value="#parameters.userName"/>
     
     <!-- struts的调试标签:可以观测值栈数据 -->
     <s:debug></s:debug>


OGNL вызывает статические методы


	/**
	 * 3.Ognl对 静态方法调用的支持
	 * @throws Exception
	 */
	@Test
	public void testOgn3() throws Exception {
		// 创建一个Ognl上下文对象
		OgnlContext context = new OgnlContext();
		
		// Ognl表单式语言,调用类的静态方法
		//Object ognl = Ognl.parseExpression("@Math@floor(10.9)");
		// 由于Math类在开发中比较常用,所以也可以这样写
		Object ognl = Ognl.parseExpression("@@floor(10.9)");
		Object value = Ognl.getValue(ognl, context, context.getRoot());
		System.out.println(value);
	}

ОГНЛ создать коллекцию


    <br/>一、.构建 list集合</br>
    <s:iterator var="str" value="{'a','b'}">
    	<s:property value="#str"/>
    </s:iterator>
    
     <br/>一、.构建 map集合</br>
     <s:iterator var="en" value="#{'cn':'China','usa':'America'}">
     	<s:property value="#en.key"/>
     	<s:property value="#en.value"/>  <br/>
     </s:iterator>

При создании коллекции карт необходимо использовать знак #


#OGNL Несколько специальных символов#

#Получить значение некорневых элементов и динамически построить коллекцию карт $ принимает значение в конфигурационном файле % Обеспечьте среду выполнения выражения ognl


<body>
  	 <br/>获取request域数据<br/>
  	 <!-- property 标签是对象类型的标签,默认支持ognl表达式, 会从根元素去China名称对应的值 -->
  	 <s:property value="China"/>		<br/>
  	 <!-- 如果直接赋值,需要用单引号 -->
  	 <s:property value="'China'"/>		<br/>
  	 <s:property value="%{#request.cn}"/>		<br/>
  	 
  	 <!-- 值类型的标签,value值默认就是值类型,不支持ognl表达式 -->
  	 国家:<s:textfield name="txtCountry" value="%{#request.cn}"></s:textfield>
  </body>

Если в статье есть ошибки, пожалуйста, исправьте меня и поделитесь друг с другом.Учащиеся, которые привыкли читать технические статьи в WeChat и хотят получить больше ресурсов по Java, могут подписаться на общедоступную учетную запись WeChat: Java3y.