Struts2中的OGNL表达式

CANoe软件之离线报文回放与分析实战 本文详细介绍了如何使用CANoe软件进行离线报文回放与分析,帮助工程师将现场故障数据转化为可反复研究的实验室资源。通过实战步骤,指导如何搭建分析工程、加载DBC文件解码信号,并利用Trace和Graphics窗口进行深度数据筛选与图形化分析,从而高效定位汽车电子故障,是提升诊断效率的关键技能。 阅读详情

浅析值栈

ValueStack对象相当于一个栈,它贯穿整个Action的生命周期,每个Action类的对象实例都会拥有一个ValueStack对象。当Struts2接收到一个*.action请求后,并不是直接调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点,值栈也位于内存中,它也是和parameters、request、session、application、attr对象放在一起的,值栈属于ONGL Context里面的根对象。也就是说它位于整个内存中最最重要的地方,所以叫根对象。根对象和另外五个对象是有区别的,根对象可以省写#号,比如<s:property value="user.username"/>,值栈的生命周期与request请求相关,每次请求产生一个值栈。默认所有的Action会被自动放到值栈里。

服务器跳转时共用值栈

假设从一个Action11通过服务器跳转到Action22的话,就意味着这两个Action是共享一个值栈的,因为一次请求只使用一个值栈。这时内存中情况是这样的:
首先接收到Action11请求后,会产生一个值栈,在栈顶存放Action11对象以及它所有的属性,然后经过服务器跳转到Action22,这时就会把Action22对象压入值栈的栈顶位置,此时Action11对象以及它的所有属性就位于栈底了。

取值过程

栈的特征是后进先出。于是首先到栈顶的对象里查找是否存在这个属性,如果栈顶的Action22对象中不存在这个属性的话它就会继续向下寻找直至栈底对象,一直查找是否存在这个属性。如果最后找到该属性的话,那么就会在JSP页面中通过<s:property value="username"/>输出属性值,如果在Action22和Action11都有一个同名的同类型的username属性的话,那么将输出Action22中的属性值。因为它是先从栈顶开始寻找属性的,值栈的特征就是后进先出,但有个前提:请求过程是通过服务器跳转的

三个语法

假设此时想要获取Action11中的username属性的话,就可以使用值栈的Top语法或者N语法,使用Top语法获取值栈中的第二个对象的属性:<s:property value="[1].top.username"/>,使用 N 语法获取值栈中的第二个对象的属性:<s:property value="[1].username"/>,另外值栈还有一个@语法,例如使用@语法调用Action中的静态方法:<s:property value="@vs@getVOMethod()"/>@vs@get()等价于@vs1@getVOMethod(),指的是栈顶对象的静态getVOMethod()方法,同理@vs2@getVOMethod()就是取值栈中第二个对象的静态getVOMethod()方法

客户端跳转时使用各自的值栈

假如中间某一个步骤中出现了客户端跳转的话,那么两个Action所使用的就是两个不同的值栈了,所以在Action22中就不能再使用Action11中的属性了,在最后跳转到的JSP页面中也就无法获取Action11的属性了,也即从Action22跳转到JSP页面时使用的是redirect的话,那么最后值栈中是没有任何的Action对象的,这个时候我们可以通过链接传参,比如<result type="redirect">test.jsp?netname=${username}</result>,意思就是取出Action22中的username属性作为参数,通过浏览器地址栏传递到JSP页面中,然后使用OGNL中的#号获取Paraments对象的属性,即<s:property value="#parameters.netname"/>就可以取到值了
辅助参考:http://blog.youkuaiyun.com/jadyer/archive/2010/09/16/5887509.aspx

手工向值栈中压入对象

正常情况下值栈保存的是Action对象,而我们也可以直接往值栈中添加其它对象,这时可以在Action中添加如下代码,向值栈中添加对象:ActionContext.getContext.getValueStack().push(new Student("沈浪",22));,而且我们手工往值栈中添加的Student对象会位于栈顶。这是因为Struts2会首先初始化Action,然后才能调用它的方法,初始化Action的时候,便把Action放到值栈中了,然后在执行它的execute()方法时,就又往值栈中添加了Student对象

浅析OGNL

OGNL是Object-Graph Navigation Language的缩写,是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能,OGNL用得最多的地方就是和Struts2的标签绑定,也可以在配置文件中通过${}使用OGNL表达式

OGNL中$号的使用

1..在国际化资源文件中,引用OGNL表达式
2..在struts.xml文件中,引用OGNL表达式

OGNL中%号的使用

1..使用%{}可以取出保存在值堆栈中的Action对象,直接调用它的方法
2..如果Action继承了ActionSupport,那么在页面标签中可以使用%{getText('key')}获取国际化信息
辅助参考:http://blog.youkuaiyun.com/jadyer/archive/2010/09/16/5887545.aspx

OGNL中#号的使用

OGNL中的#号可以取出堆栈上下文中存放的对象

获取Action中的属性值或者Action中的对象的某某属性值

利用<s:property/>标签可以直接获取Action中的引用类型user里面的username属性,同样可以通过user.address.addr获取user中引用类型address中的addr属性的值,像这种一层一层往下传递的访问方式,即所谓的导航,也就是一步步的往下调用

调用Action的对象里面的普通方法

默认的会把Action放到值栈里面,而值栈在访问的时候,并不需要值栈的名字,当我们调用<s:property value="user.getVOMethod()"/>的时候,它会自动到值栈里面查找Action对象里面有没有user对象,然后它就发现有user,然后它就再找user里面有没有getVOMethod()方法,然后它发现有,于是调用getVOMethod(),实际上调用User中的getVOMethod()方法的过程与获取表单中的姓名密码的方式都是相同的,都是到值栈里面查找,找是否存在user对象,如果存在,接着查找user中是否存在某某属性或方法。

调用Action中的静态方法

同样我们也可以在JSP页面中写一个OGNL表达式调用Action中的静态方法,调用Action中的静态方法时,与调用user对象的getVOMethod()方法的过程,是截然不同的,此时value的写法是固定的,以@开头,后面跟上具体的包名,然后@加上静态方法
比如<s:property value="@com.jadyer.action.LoginAction@getStatic()"/>,另外user对象是LoginAction中的一个属性,这个属性会自动的放到值栈里面,而值栈调用的时候,不用加上@或者包名等等,所以直接user.getVOMethod()就可以了

调用JDK类中的静态方法

可以使用<s:property value="@@floor(46.58)"/>输出floor()的执行结果,这就意味着如果不在@@中指定类的话,默认的就表示java.lang.Math类,当前大多数情况下,我们都不会省略这个类,都会写全了的,然后在后面加上静态方法

集合的伪属性

OGNL能够引用集合的一些特殊的属性,这些属性并不是JavaBean模式,例如size()、length(),当表达式引用这些属性时,OGNL会调用相应的方法,这就是伪属性,比如获取List的大小:<s:property value="testList.size"/>

List的伪属性:size、isEmpty、iterator
Set的伪属性:size、isEmpty、iterator 
Map的伪属性:size、isEmpty、keys、values
Iterator的伪属性:next、hasNext
Enumeration伪属性:next、hasNext、nextElement、hasMoreElements

获取集合中元素的实质就是调用它的toString()方法

它还可以直接获取集合中的元素,事实上是在调用集合的toString()方法,所以我们可以根据实际情况通过重写集合的toString()方法来实现个性化输出,甚至它还可以像访问数组那样,直接testList[2]获取集合中的元素,但这种方法只适用于List,不适用于Map。因为Map的索引是key,不是数值。另外,由于HashSet中的元素是没有顺序的,所以也不能用下标获取单个元素

Lambda表达式

补充一下:使用Lambda表达式可以在OGNL中书写递归式子,在帮助中对它有很详细的说明,打开帮助中的//struts-2.0.14-all//struts-2.0.14//docs//index.html页面,在左侧的Documentation下面点击Guides链接,然后在这个页面中点击OGNL,最后跳转到//struts-2.0.14-all//struts-2.0.14//docs//docs//ognl.html,将这个页面右侧的下拉条拖放到最下面,就会看到它的说明了,它举的例子如下所示<s:property value="#fib =:[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" />,Lambda表达式的语法是:[...] ,中括号前面有一个冒号,所有东西都在中括号里面写,也就是说我们只要看到一个冒号跟着一个中括号,就表示这里使用的是Lambda表达式,#this指的是表达式的参数,所以这个例子可以这样理解:先判断这个参数是否等于零,如果等于零,那么它的值最后就是零,如果参数不等于零,就再判断它是否等于壹。如果参数等于壹,那么它的值最后就是壹,如果参数不等于壹,就继续调用#fib。注意这里已经用中括号将整体的值赋给了fib,实际上很少能够用得到Lambda表达式
 

利用投影获取属性

利用投影获取List中对象的username属性时,其中{}表示的是一个集合,stus.{username}就表示将suts中所有的username属性取出组成一个新的列表。

利用选择获取属性

OGNL表达式是很灵活的,可以同时使用选择技术与投影技术获取属性,使用选择技术时,#this代表当前元素,问号?是把所有满足条件的元素都取出来,上箭头^是开始的意思,所以stus.{^#this.grade>=60}.{username}输出的是[张三],注意,此时输出文本中包含中括号,这表示它是一个列表,而stus.{?#this.grade>=60}.{username}[0]输出的是张三,是字符串,二者是不同的
美元符号$是结束的意思,所以stus.{$#this.grade>=60}.{username}输出的是[王五],这三个符合:问号、上箭头、美元符所返回的都是List

补充

1..当OGNL取不到值的时候,它不会报错,而是什么都不显示
2..<s:property value="[0]"/>返回的是ValueStack中从上至下的所有的Object
    <s:property value="[1]"/>返回的是ValueStack中从上至下的第二个Object
3..<s:property value="[0].username"/>返回的是成员变量username的值
    假设ValueStack中存在两个Action的话,如果第一个Action如果没有username变量
    那么它会继续找第二个Action。那么在什么情况下ValueStack中会存在两个Action呢
    答案是在struts.xml中配置的是从一个Action通过<result type="chain">跳转到另一个Action
4..<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
    在Struts2.1.6中必须设置struts.ognl.allowStaticMethodAccess为true之后
    才允许使用OGNL访问静态方法。而在Struts2.0.11则无需设置,即可直接访问
 

OGNL测试代码

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  	<filter>
	  	<filter-name>struts2</filter-name>
  		<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  	</filter>
  	<filter-mapping>
  		<filter-name>struts2</filter-name>
  		<url-pattern>/*</url-pattern>
  	</filter-mapping>
	<welcome-file-list>
    	<welcome-file>login.jsp</welcome-file>
  	</welcome-file-list>  
</web-app>

用于输入用户名和密码等信息的测试页面login.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<h1>这是测试OGNL使用的登录页面</h1>
<h3><font color="red">提示:</font>程序设定的用户名和密码各为<font color="blue"><strong>admin</strong></font>和<font color="blue"><strong>jadyer</strong></font></h3>
<h3><font color="red">注意:</font>用户名和密码不正确时将停留在页面不动</h3>
<form action="<%=request.getContextPath()%>/login.action" method="POST">
	<%--这里user.username匹配的是LoginAction中的引用类型user里面的username属性--%>
	<%--查看标签库说明的话,就知道name中指定的是对象。这里它不是字符串,而是OGNL表达式--%>
	姓名:<input type="text" name="user.username"><br>
	密码:<input type="text" name="user.password"><br>
	地址:<input type="text" name="user.address.addr"><br>
	<input type="submit" value="测试OGNL的输出">
</form>

用于显示OGNL处理结果的loginSuc.jsp页面

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<h1>这是使用OGNL输出的结果页面</h1>
<table border="9">
	<tr>
		<td align="right">获取姓名属性:</td>
		<td align="left"><s:property value="user.username"/></td>
		<%-- 另外还有两种写法也是可以正常输出值栈中对象的普通属性的 --%>
		<%-- <s:property value="user['username']"/> --%>
		<%-- <s:property value="user[/"username/"]"/> --%>
		<%-- 但是如果写成下面这种形式的话,就什么都不会输出了 --%>
		<%-- <s:property value="user[username]"/> --%>
	</tr>
	<tr>
		<td align="right">获取地址属性:</td>
		<td align="left"><s:property value="user.address.addr"/></td>
	</tr>
	<tr>
		<td align="right">调用值栈中的对象的普通方法:</td>
		<td align="left"><s:property value="user.getVOMethod()"/></td>
	</tr>
	<tr>
		<td align="right">调用值栈中Action的普通方法:</td>
		<td align="left"><s:property value="getCommon()"/></td>
	</tr>
</table>
<hr/>
<table border="9">
	<tr>
		<td align="right">获取普通类的静态属性:</td>
		<td align="left"><s:property value="@com.jadyer.vo.Address@TIPS"/></td>
	</tr>
	<tr>
		<td align="right">访问普通类的构造方法:</td>
		<td align="left"><s:property value="new com.jadyer.vo.Student('张小三',22).username"/></td>
	</tr>
	<tr>
		<td align="right">调用Action中的静态方法:</td>
		<td align="left"><s:property value="@com.jadyer.action.LoginAction@getStatic()"/></td>
	</tr>
	<tr>
		<td align="right">调用JDK中的类的静态方法:</td>
		<td align="left"><s:property value="@java.util.Calendar@getInstance().time"/></td>
	</tr>
	<tr>
		<td align="right">调用JDK中的类的静态方法:</td>
		<td align="left"><s:property value="@java.lang.Math@floor(46.58)"/></td>
	</tr>
	<tr>
		<td align="right">调用JDK中的类的静态方法:</td>
		<td align="left"><s:property value="@@floor(46.58)"/></td>
	</tr>
</table>
<hr/>
<table border="9">
	<tr>
		<td align="right">获取List中的所有元素:</td>
		<td align="left"><s:property value="testList"/></td>
	</tr>
	<tr>
		<td align="right">获取Set中的所有元素:</td>
		<td align="left"><s:property value="testSet"/></td>
	</tr>
	<tr>
		<td align="right">获取Map中的所有元素:</td>
		<td align="left"><s:property value="testMap"/></td>
	</tr>
	<tr>
		<td align="right">获取Map中的某个元素:</td>
		<td align="left"><s:property value="testMap['m22']"/></td>
		<%-- 另外还有两种写法也是可以正常获取Map中的某个具体元素的 --%>
		<%-- <s:property value="testMap.m22"/> --%>
		<%-- <s:property value="testMap[/"m22/"]"/> --%>
	</tr>
	<tr>
		<td align="right">获取Set中的某个元素:</td>
		<%-- 由于Set中的元素是无顺序的,所以不能使用下标获取数据,所以这里什么也得不到 --%>
		<td align="left"><s:property value="testSet[2]"/></td>
	</tr>
	<tr>
		<td align="right">获取List中的某个元素:</td>
		<td align="left"><s:property value="testList[2]"/></td>
	</tr>
</table>
<hr/>
<table border="9">
	<tr>
		<td align="right">获取List的大小:</td>
		<td align="left"><s:property value="testList.size"/></td>
	</tr>
	<tr>
		<td align="right">获取Set的大小:</td>
		<td align="left"><s:property value="testSet.size"/></td>
	</tr>
	<tr>
		<td align="right">获取Map的大小:</td>
		<td align="left"><s:property value="testMap.size"/></td>
	</tr>
	<tr>
		<td align="right">获取Map中所有的键:</td>
		<td align="left"><s:property value="testMap.keys"/></td>
	</tr>
	<tr>
		<td align="right">获取Map中所有的值:</td>
		<td align="left"><s:property value="testMap.values"/></td>
	</tr>
	<tr>
		<td align="right">Lambda计算4的阶乘:</td>
		<td align="left"><s:property value="#f= :[#this==1?1 : #this*#f(#this-1)],#f(4)"/></td>
	</tr>
</table>
<hr/>
<table border="9">
	<tr>
		<td align="right">获取List中的所有对象:</td>
		<td align="left"><s:property value="stus"/></td>
	</tr>
	<tr>
		<td align="right">利用投影获取List中对象的名字:</td>
		<td align="left"><s:property value="stus.{username}"/></td>
	</tr>
	<tr>
		<td align="right">利用投影获取List中第二个对象的名字:</td>
		<%-- 使用<s:property value="stus[1].{username}"/>获取到的值为:[李四] --%>
		<%-- 二者的区别在于:后者比前者多了一个中括号 --%>
		<td align="left">
			<s:property value="stus.{username}[1]"/>      
			<s:property value="stus[1].{username}"/>
		</td>
	</tr>
	<tr>
		<td align="right">利用选择获取List中成绩及格的所有对象:</td>
		<td align="left"><s:property value="stus.{?#this.grade>=60}"/></td>
	</tr>
	<tr>
		<td align="right">利用选择获取List中成绩及格的第一个对象:</td>
		<td align="left"><s:property value="stus.{^#this.grade>=60}"/></td>
	</tr>
	<tr>
		<td align="right">利用选择获取List中成绩及格的最后一个对象:</td>
		<td align="left"><s:property value="stus.{$#this.grade>=60}"/></td>
	</tr>
</table>
<hr/>
<table border="9">
	<tr>
		<td align="right">利用选择获取List中成绩及格的所有对象的名字:</td>
		<td align="left"><s:property value="stus.{?#this.grade>=60}.{username}"/></td>
	</tr>
	<tr>
		<td align="right">利用选择获取List中成绩及格的第二个对象的名字:</td>
		<td align="left"><s:property value="stus.{?#this.grade>=60}.{username}[1]"/></td>
	</tr>
	<tr>
		<td align="right">利用选择获取List中成绩及格的第一个对象的名字:</td>
		<td align="left"><s:property value="stus.{^#this.grade>=60}.{username}"/></td>
	</tr>
	<tr>
		<td align="right">利用选择获取List中成绩及格的最后一个对象的名字:</td>
		<td align="left"><s:property value="stus.{$#this.grade>=60}.{username}"/></td>
	</tr>
	<tr>
		<td align="right">利用选择获取List中成绩及格的第一个对象然后求大小:</td>
		<td align="left"><s:property value="stus.{^#this.grade>=60}.{username}.size"/></td>
	</tr>
</table>
<hr/>
<table border="9">
	<tr>
		<td align="right">利用OGNL中的#号获取attr中的属性:</td>
		<td align="left"><s:property value="#attr.BB"/></td>
	</tr>
	<tr>
		<td align="right">利用OGNL中的#号获取request范围中的属性:</td>
		<td align="left"><s:property value="#request.req"/></td>
	</tr>
	<tr>
		<td align="right">利用OGNL中的#号获取session范围中的属性:</td>
		<td align="left"><s:property value="#session.ses"/></td>
	</tr>
	<tr>
		<td align="right">利用OGNL中的#号获取Paraments对象的属性:</td>
		<td align="left"><s:property value="#parameters.netname"/></td>
	</tr>
	<tr>
		<td align="right">使用&#60;&#37;=request.getParameter&#40;""&#41;&#37;&#62;或者&#36;&#123;param.name&#125;获取链接参数值:</td>
		<td align="left">
			${param.netname}      
			<%=request.getParameter("netname")%>
		</td>
	</tr>
	<tr>
		<td align="right">查看值栈中的信息:</td>
		<td align="left"><s:debug/></td>
	</tr>
</table>

struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	<package name="ognl" extends="struts-default">
		<action name="login" class="com.jadyer.action.LoginAction">
			<result name="input">/login.jsp</result>
			<result name="success">/loginSuc.jsp?netname=hongyu</result>
			<!--
			<result name="success" type="redirect">/loginSuc.jsp?netname=hongyu</result>
			<result name="success" type="redirect">/loginSuc.jsp?netname=${user.username}</result> 
			 -->
		</action>
	</package>
</struts>

用到的三个VO类

package com.jadyer.vo;
public class User {
	private String username;
	private String password;
	private Address address;
	/* 三个属性的setter和getter略 */
	public String getVOMethod(){
		return "这是User类中的一个普通方法";
	}
}


package com.jadyer.vo;
public class Address {
	//如果将TIPS设为private的话,loginSuc.jsp中就无法获取它的属性值了
	//事实上将一个静态的final属性设为private是毫无意义的
	//因为既然设置成了静态,那么就是供他人调用的,如果再设成private的话,别的地方根本就无法调用了
	//即使OGNL再怎么强大,它也不可能违反Java的规则,所以不要将静态的属性设为私有
	public static final String TIPS = "玄玉加油!!";
	//addr属性的setter和getter略
	private String addr;
}


package com.jadyer.vo;
public class Student {
	private String username;
	private int grade;
	/* 两个属性的setter和getter略 */
	
	//只要是重写一个类的构造方法,就必须要为这个类保留空的构造方法
	//因为框架默认的都会去调用无参的空的构造方法
	public Student(){};
	public Student(String username,int grade){
		this.username = username;
		this.grade = grade;
	}
	@Override
	public String toString() {
		//如果不重写它的toString()方法的话,默认调用toString()将输出【类型+@+内存地址的哈希值】
		return "{学生姓名:" + username + ",成绩:" + grade + "}";
	}
}

用来提供OGNL测试的数据的LoginAction.java

package com.jadyer.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;

import com.jadyer.vo.Student;
import com.jadyer.vo.User;
import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings({"serial", "unchecked"})
public class LoginAction extends ActionSupport implements RequestAware,SessionAware {
	private User user;
	private List testList = new ArrayList();
	private Set testSet = new HashSet();
	private Map testMap = new HashMap();
	private List stus = new ArrayList();
	
	/* 以上五个属性的setter和getter略 */
	
	private Map request;
	private Map session;
	public void setRequest(Map request) {
		this.request = request;
	}
	public void setSession(Map session) {
		this.session = session;
	}
	
	public static String getStatic(){
		return "这是LoginAction中的一个静态方法";
	}
	public String getCommon(){
		return "这是LoginAction中的一个普通方法";
	}
	
	@Override
	public String execute() throws Exception {
		if(user.getUsername().trim().equalsIgnoreCase("admin") && user.getPassword().equals("jadyer")){
			testList.add("list11");
			testList.add("list22");
			testList.add("list33");
			testList.add("list44");
			testList.add("list55");
			
			testSet.add("set11");
			testSet.add("set22");
			testSet.add("set33");
			testSet.add("set22");
			testSet.add("set11");
			
			testMap.put("m11", "map11");
			testMap.put("m22", "map22");
			testMap.put("m33", "map33");
			testMap.put("m44", "map44");
			testMap.put("m55", "map55");
			
			stus.add(new Student("张三",88));
			stus.add(new Student("李四",77));
			stus.add(new Student("王五",66));
			stus.add(new Student("马六",55));
			
			request.put("req", "这是通过OGNL中的#号获取的request属性范围的值");
			session.put("ses", "这是通过OGNL中的#号获取的session属性范围的值");
			request.put("BB", "这是通过OGNL中的#号获取的request属性范围的BB");
			session.put("BB", "这是通过OGNL中的#号获取的session属性范围的BB");
			return SUCCESS;
		}else{
			return INPUT;
		}
	}
}

Refer:
https://www.cnblogs.com/tilney/p/3242661.html
 

论文分栏前后内容不连续?教你word如何删除分节符 问题 当我们在写论文的时候,很多期刊的模板都是两栏的格式,但有的时候我们插入的图像尺寸可能太大,两栏格式放不下,因此需要将其以一栏的格式出入,如下: 但当我们把图片删除后,再将其转换成两栏格式,前后内容就出现不连续的情况: 正常情况下应该是如下: 正确处理方式 里面有个分页符,把分页符去掉,或者把你的文字全部复制到记事本里,然后重新复制回word就可以取消原有的格式了。 删除分节符的方法(以word 2019为例) -点击菜单栏上的“视图”,点击“大纲视图”。 可以看到word文档以整列的形式展开: 阅读详情

相关推荐

卫星测试科普(三):卫星载荷的核心测试设备探秘

总的说来,卫星芯片与元器件,部组件与单机,整机与子系统,系统与整星的设计、定型、制造、验证、总装、发射、在轨等环节都离不开各种测试场景,对于这些卫星测试场景而言,“射频三大件”与高速数字示波器是构成强大测试系统的基础。卫星通信信号生成:覆盖Ka、Q等波段,具备扫频、脉冲、数字调制、噪声信号、雷达信号、数据链信号、OFDM 等多种信号库,用于测试和验证卫星电子设备的电气性能、频率响应、抗干扰能力等。卫星的通信需要高效、快速地传输大量数据,高速信号的质量至关重要,如果卫星信号不佳,卫星就会出现故障或者隐患。

spwbjss的博客 2318

Struts2的OGNL表达式语言(转)

1.OGNL表达式语言OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts 2框架使用OGNL作为默认的表达式语言。 相对EL表达式,它提供了平时我们需要的一些功能,如:支持对象方法调用,如xxx.sayHello(); 支持类静态方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],

388

手把手教你用OPA运放和MOS管搭建恒流源电路(附完整电路图)

本文详细介绍了如何使用OPA运放和MOS管搭建高精度恒流源电路,涵盖核心元器件选型、电路设计、工作原理及实际搭建步骤。通过负反馈控制机制和MOS管工作区设置技巧,实现稳定的电流输出,适用于LED驱动、电池充电等场景。附完整电路图和调试技巧,助您快速掌握恒流源设计。

weixin_29239279的博客 535

struts2 中 OGNL表达式的使用

beidou321的专栏 1246

IDEA 2023最新破解教程:从安装到永久激活(附常见问题解决方案)

本文为Java开发者提供了一份详尽的IntelliJ IDEA 2023高效使用指南。内容涵盖从版本选择、安装配置到核心快捷键、项目依赖管理、高级调试测试以及插件生态的深度优化。旨在帮助用户在合法合规的前提下,充分发挥这款顶级IDE的潜力,显著提升Java开发效率与工作体验。

time3的博客 3360

DroidGuard虚拟机逆向解析:指令集、密钥派生与反调试机制

DroidGuard是Google在Android生态中部署的轻量级定制虚拟机,用于设备完整性校验。其核心原理是通过自解释字节码、多层混淆指令集与动态密钥派生机制,在ART运行时构建静默安全沙箱。技术价值在于规避传统API检测盲区,实现高鲁棒性环境感知;典型应用场景包括金融SDK风控、Play Services可信启动及合规性审计。本文深入拆解其4字节指令编码规则、基于设备指纹的三阶段密钥派生(SHA256→Feistel→AES)、以及五层反调试体系(ptrace快照、时间差分、内存页探测、指令流校验、服

weixin_32736961的博客 587

Struts2之OGNL表达式

Struts2之OGNL表达式

qq_42640067的博客 1097

从生成到检测:全面解析Deepfake技术的演进与对抗策略

本文全面解析了Deepfake技术的演进与对抗策略,从GAN生成技术到先进的检测手段,探讨了其在娱乐与安全领域的双重影响。文章详细介绍了Deepfake的核心原理、技术迭代关键节点以及最新的检测方法,揭示了AI生成与识别的激烈博弈。同时,展望了量子计算和生物特征认证在未来攻防战中的潜在应用。

jenkins8butler的博客 255

struts学习——OGNL表达式

1、OGNL表达式 OGNL,全称为Object-Graph Navigation Language,它是一个功能强大的表达式语言,用来获取和设置Java对象的属性,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。XWork对OGNL的实现: OGNL表达式的基本单位是"导航链",一般导航链...

weixin_34185364的博客 315

【纯干货分享】常用高速接口眼图模板合集

文章汇集了常见的高速接口的信号眼图测试模板技术要求,比如,LPDDR5/4、PCIe 5.0/4.0、USB、MIPI等等,方便工程师快速进行查询和使用。

一只豌豆象的博客 3116

Hermes接入IMA知识库全攻略:将知识库装进你的Hermes智能体

本文详细介绍了如何将IMA知识库功能接入Hermes Agent平台,实现一站式笔记管理和知识库操作。主要内容包括:获取IMA访问凭证、下载技能包、配置凭据(支持文件和环境变量两种方式)、验证配置有效性,以及实际应用演示(查询知识库列表、创建笔记并添加到知识库)。文章还提供了常见问题解决方案,如认证失败处理、版本更新等。通过该集成,用户可在Hermes中直接调用IMA的笔记创建、知识库管理等强大功能,提升工作效率。

小石头的专栏 641

Struts2——OGNL表达式

一、简介 OGNL(对象图导航语言:Object Graphic Navigation Language),是Struts2框架默认的表达式语言。 作用:取值,获取javaBean中的属性,获取List或者数组元素,获得Map的键值对,还可以执行逻辑运算。 二、OGNL三要素 1.表达式 2.根对象root 3.上下文context 三、例子 三个类,User为根对象,User类中包含group作为成员变量,Group类中包含branch作为成员变量,分别提供对应变量的get,set方法 pac

是草莓味的啊 529

用 SAP-ABAP-1 把 ABAP 代码读懂:从 Generative AI Hub Orchestration 到 Joule 落地的实战指南

SAP-ABAP-1 是 SAP 推出的 ABAP 专用基础模型,专注于代码解释与理解。它能显著降低企业遗留系统的维护成本,帮助开发人员快速掌握复杂业务逻辑。该模型通过 SAP Generative AI hub 托管,支持 128,000 tokens 的上下文长度,适合分析大型 ABAP 类和 CDS 视图。典型应用场景包括代码解释、迁移辅助和云合规检查。调用需通过 Orchestration service 进行,确保企业级安全治理。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1212

深入解析Struts2中的OGNL表达式及其强大功能

值栈(ValueStack)是什么值栈(ValueStack),是 Struts2 的数据中转站,栈中自动保存了当前Action 对象和其他相关对象(包括常用的 Web 对象的引用,如 request、session、application 等),也可以手动保存自己的数据对象,同时也可以随时随地将对象从值栈取出或操作(通过 OGNL 表达式)值栈(ValueStack),

蓝鲸鱼计算机软件开发工作室 1308

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Struts2学习笔记三:OGNL表达式学习、Struts2与Ognl表达式的结合原理

文章目录1. Struts2学习笔记三:OGNL表达式学习、Struts2与Ognl表达式的结合原理1.1. 什么是OGNL表达式1.2. 使用OGNL表达式1.3. Struts2和ONGL表达式的结合原理 1. Struts2学习笔记三:OGNL表达式学习、Struts2与Ognl表达式的结合原理 1.1. 什么是OGNL表达式 OGNL:对象视图导航语言,是比EL表达式有更加丰富的功能,E...

公子&小白的博客 725

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Struts2之Ognl表达式

这里写目录标题前言Mock.js简介Mock.js使用步骤2.1 安装mockjs依赖2.2 引入2.3 目录和文件创建 前言 前后端分离开发开发过程当中,经常会遇到以下几个尴尬的场景: 老大,接口文档还没输出,我的好多活干不下去啊! 后端小哥,接口写好了没,我要测试啊! 前后端分离之后,前端迫切需要一种机制, 不再需要依赖后端接口开发, 而今天的主角mockjs就可以做到这一点 ! Mock.js简介 Mock.js是一个模拟数据的生成器,用来帮助前端调试开发、进行前后端的原型分离以及用来提高自动化

月亮投递员的博客 549

struts2之ognl表达式

struts2之ognl基础前言ognlValueStack(值栈) 前言 之前讲了基于maven的struts2框架项目的简单流程,这次主要讲关于struts2的ognl。 ognl 什么是ognl? OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言。 说起表达式语言我们就会想起来el表达式,ognl表达式与el表达式最大的区别就是他可以存值也可以取值,而el表达式只能取值。 什么是ognl上下文? OgnlContext(OGN

JiangHu_Java的博客 355

Struts2—Ognl 表达式

补充一下Ognl表达式的相关的知识点。尽量调有用的知识点来进行记录。Ognl:Object-Graph Navigation Language,表达式语言,Java能做的,都可以使用OGNL来完成,实际上相当于动态的Java代码执行。

王嘟嘟的博客 977

Struts2中OGNL表达式的用法

今天分享的是Struts2框架中的一种ognl表达式语言,主要分两个目标去学习     1.理解struts2传值的优先级     2.ognl与el的区别 一:ognl表达式语言简介   OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,让你通过简单一致的表达式语法来读取和设置Java对象的属性...

a846075506的博客 315

Struts2(15)_Struts2 的 ognl 表达式

本系列博客汇总在这里:Struts2 汇总 ognl 表达式一、什么是 ognl 表达式二、ognl 对普通方法的调用三、ognl 对静态变量和静态方法的调用四、ActionContext1、在 context map 中存取数据2、在值栈中存取数据 源码工程文件为:struts2_17 一、什么是 ognl 表达式 OGNL 是 Object Graphic Navigation Lan...

魏宇轩 652

struts2中的ognl表达式

1、object graph navigation language 对象导航图语言 2、ognl和struts2没有必然的关系,它不是真正的编程语言,它只是一种数据访问语言。 3、在struts2中ognl完成数据设置,类型转换两个功能,Apache推荐使用。 4、需要的jar包  ognl-3.1.15.jar  javassist-3.20.0-GA.jar 5、ognl的思想 把数...

底层码农 1万+

Struts2中OGNL表达式

前提:在struts2中要使用OGNL表达式,必须放到Struts2的标签中。 与jsp,servlet对比

Newstar优快云的博客 9128

Struts2--用OGNL表达式从域中取值

在实际开发过程中,OGNL 表达式要结合 struts2 的标签使用,主要就是%、#和$三个符号的使用。 # 符号 在 Struts2 框架中,#符号有三种用途,分别如下: 1.访问非跟对象的属性 如访问 OGNL 上下文和 Action 上下文。由于 Struts2 中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀。 #相当于 ActionContext.getContext()。例如‘...

吴声子夜歌的博客 749

Struts2:OGNL表达式

OGNL表达式 OGNL(Object-Graph Navigation Language)的全称是对象图导航语言,是一个用来获取和设置java对象属性的表达式语言的开源表达式语言,通过使用表达式语法导航对象图,而不是直接调用对象的获取和设置方法。同时它可以提供许多应用,比如在XML文件或者脚本文件中嵌入OGNL表达式语法,在JSP页面使用OGNL表达式语法。 OGNL的三要素 一、表达式:...

离开屏幕的光,哪盏灯照亮你的孤独? 417

Struts2 OGNL表达式

访问值栈中普通属性 Ognl类中创建一个简单的属性username(设置set get方法),传入参数username=u。 获取值栈中普通属性OGNL表达式 <li >访问值栈中的action的普通属性: username = <s:property value="username"/> </li> 访问值栈中对象 创建user对象,在action中创建us...

OVO_LQ_Start的博客 286
上一篇: WEBshell提权的20种思路
下一篇: 协议篇————1、OSI七层模型与TCP/IP四层模型
FLy_鹏程万里
FLy_鹏程万里 优质创作者: 后端开发技术领域 优质创作者: 后端开发技术领域 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄9年 1万+粉丝 1364原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FLy_鹏程万里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值