【Struts2】Ognl表达式

5).OGNL表达式-操作数据空间

O(Object) G(Graphic) N(Navigation) L(Language) 对象 图 导航语言
作用:通过表达式方式(非Java代码)的方式操作指定数据。
特点:(对比EL)
①可以调用方法
②可以存入数据(绑定数据)
OGNL可以操作数据空间(对象):
导入jar: ognl.jar
① ognl向root区的对象中存入数据
Ognl.setValue("root区的对象的属性名",root区对象,值);
②ognl从root区的对象中获取数据
Object ognl表达式获取的结果 = Ognl.getValue("root区对象的属性名",root区对象);
③调用方法
语法: Ognl: "对象.方法名(参数)"
注意: 表示字符串 "zxxx"   '1000'(如果ognl外部使用双引号,内部字符串使用单引号)
④数学运算和逻辑运算
+ - * / % == != ! && || 
注意: (1==“1”)忽略数据类型;(10/3结果为3) 数字除运算, 按照java运算规则计算
⑤Ognl访问List集合类型数据
语法: ognl: "list集合[i]"
⑥Ognl访问Map集合元素
语法: ognl:  
			"map对象.key"  		key不能是纯数字内容。
    		"map对象['key']" 		key可以数字或者字符串。
⑦Ognl从context区域获取数据
重点: context区域是一个map结构
	key是字符串、value对象类型
语法: Ognl表达式: "#key"   context中map的value
测试方法: Ognl.getValue("ognl表达式",放入context区的map,root对象);

6).OGNL表达式-值栈(ValueStack)、Struts2值栈的使用+Struts2标签库[重点]

(1)值栈 ValueStack(类名)
作用:
封装ognl的root和context
使用Ognl表达式访问值栈内部root区中的对象,context中map的key对应的value
值栈相关api:
①获得值栈对象
ValueStack vs = ActionContext.getContext().getValueStack();
②获得root(栈)
CompoundRoot root = vs.getRoot();
③向root中存入对象
root.push(作为root对象);
④获得context
Map<String,Object> context = vs.getContext();
⑤如果想context中存入数据
context.put("key",值);
⑥值栈对象提供方法  vs.findValue("ognl表达式"), 使用ognl获得值栈中的数据。
			获取root区属性值:			vs.findValue(“对象属性”);
			获取ContextMap区value:		vs.findValue(“#key”);
(2)Struts2值栈的使用+Struts2标签库[重点]
Struts2对值栈的管理
①值栈:
Context区(数据结构  Map)[重点]
    "request"    	RequestMap(相当于HttpServletRequest作用域)
    "session"    	SessionMap(相当于HttpSession作用域)
    "application" 	ApplicationMap(相当于ServletContext作用域)
Root区(数据结构  栈 Stack)
	将当前的Action对象放在root区栈顶。
②struts2标签库:
使用:
a.引入标签库:<%@taglib uri="/struts-tags" prefix="s" %>
b.使用property标签:<s:property value="ognl表达式"></s:property>
作用: 
a.执行ognl获得数据
b.将结果展示给浏览器
③总结:
a. 向RequestMap中存入值
	Map<String,Object> requestMap =  (...)vs.getContext().get("request");
	requestMap.put("名字key",值);
    通过Ognl表达式访问RequestMap(相当于request作用域)
    OGNL: "#request.requestmap中的key"
b. 向SessionMap存入值
    Map<String,Object>  sessionMap = (..)vs.getContext().get("session");
    sessionMap.put("key",value)
    通过Ognl表达式访问SessionMap(相当于session作用域)
    OGNL: "#session.sessionMap中的key"
c. 通过Ognl表达式访问当前的Action的属性值:
    注意: Action生命周期是一次请求过程。(请求转发)
OGNL: "Action的属性名"

7).OGNL表达式-常用的Struts2标签、及在struts.xml中使用

(1)常用Struts2标签(在JSP中使用OGNL)
①property
   语法: <s:property value="OGNL表达式,值栈的root获取值,context获得值"/>
   作用:
   	a.执行ognl表达式,获得数据
b.讲结果显示给浏览器。
   常用:
   <s:property value="Action的属性名"/>   [获得action的属性值]
   <s:property value="#request.requestMap的key"/>  [获得相当于request作用域的requestMap的值]
   <s:property value="#session.sessionmap的key"/>  [获得相当于session作用域的sessionMap的值]
   补充:
   	<s:property/>   [获得的值栈的root区栈顶的对象]
②格式化日期
   <s:date name="ognl获得要格式化显示的日期" format="设置日期格式"/>
   日期格式:
   年yyyy     月MM     日dd
③判断
   语法: 	<s:if test="OGNL获得数据并逻辑判断1">条件1成立</s:if>
   		<s:elseif test="ognl条件2">条件2成立</s:elseif>
   		<s:else>都不成立</s:else>
④遍历ListJ集合
  <s:iterator value="OGNL被遍历的集合">
<s:property/>当前被遍历的对象:被遍历的当前对象被放在了root区的栈顶位置
      <s:property value="当前对象的属性名"/>当前被遍历的对象的属性
  </s:iterator>
  作用: a. value属性遍历集合;b. 遍历过程中,每个被遍历的当前对象,暂时放在值栈的root区的栈顶。
  属性介绍:
 	 	value: 			OGNL获得被遍历集合
begin: 			起始下标
  		end: 			截止下标
  		step: 			步长      	[配合  begin="0"]
 		status="vs"		(vs.index(下标序号);   vs.count(排序序号))
  注意: 将vs存入值栈的context中。key="vs"
⑤遍历Map
  <s:interator value="ognl获得map">
  		将遍历的每个当前对象(Map.Entry key+value),放入root栈顶。
      	展示key:  <s:property value="key"/>
      	获得value: <s:property value="value"/>
  </s:interator>
⑥url重写
<s:url value="请求资源的路径"></s:url>
    作用:
 	a. 自动补全 "/项目名"
      b. cookie被禁用的请情况下对url进行重写。(url;jsessionid=1234asdd1234asd);
⑦action请求标签
   语法:  s:action name="" namespace="" executeResult="true"></s:action>
   作用:向action发起请求,接收服务器响应的结果。
   属性:
   name: 		请求的action的name
   namespace: 	请求的action的命名空间namespace
   executeResult: 	是否包含action的执行结果页面。
(2)Struts2标签在struts.xml中使用
struts.xml书写OGNL表达式
ognl在struts.xml获得root中当前Action的属性名,作用域对应的map中的值。 
语法: ${ognl表达式}
在跳转路径中使用超链接传值:

8).OGNL表达式-值栈的生命周期、及其原理(如何替代作用域)

(1)值栈的生命周期
生命周期: 一次请求过程.
 
(2)#值栈如何替代作用域的(原理)
原理:值栈的生命周期一次请求过程,但是值栈的context中的sessionMap中的数据可以跨请求存在,是因为其
	  最终保存在HttpSession作用域中,HttpSession可跨多次请求。
SessionMap底层源码实现:
存入: 讲put方法接受的key和value,session.setAttribute(key,value);保存在session作用域中,。
取出: 讲get方法接受key,session.getAttribute(key);,从session作用域中获的值

9).拦截器(Interceptor)、拦截器栈(组)

(1)拦截器
概念: 拦截浏览器请求struts2的Action.
作用(应用): 提取多个Action中的共同代码(通用功能),到拦截器中完成。
运行机制:
   ①请求访问Action,会先经过拦截器中代码。
   ②请求经过拦截调用方法: intercept(ActionInvocation ai)
       ai.invoke();//放行action的请求。
拦截器核心工作机制:(类比Filter)
 编码实现拦截器:
①自定义一个类,实现Interceptor接口
public class MyInterceptor implements Interceptor{
	//请求到达拦截器的执行方法。(类似filter中doFilter)
	intercept(ai){
	    Action之前运行的代码
		ai.invoke();//放行请求。
		Action运行之后的代码
	}
}
②注册配置拦截器(拦截器被struts2管理)
<interceptors>
   <intercept name="名字" class=""></intercept>
</interceptors>
③在需要拦截的action中引用拦截器(名字)
 
④拦截器修改跳转路径:
 
⑤拦截器和Action+跳转的完整流程。
 
(2)拦截器栈(组)
 
拦截器注意事项:
如果aciton引用自定义拦截器的话,默认拦截器就失效了。
struts-default[笔试]
struts.xml中, `extends="struts-default"`
默认拦截器中配置大量struts核心拦截器,(请求参数自动接收,文件上传,值栈,编码设置),如果action要使用这些拦截器,必须继承struts-default配置文件的额信息。而且还要引入Struts默认的拦截器,放到自己定义的拦截器栈的首个位置:

10).Struts应用-文件的上传、下载

(1)文件上传
步骤:
①浏览器页面(文件选择输入框
   a. 文件输入框
   b. 表单提交方式 post
   c. 设置表单以二进制流提交: form enctyp="multipart/form-data"
②Action接受文件
   public class FileAction{
      	private File 文件输入框的name;
       	//set get;
   }
③在action讲接受file对象拷贝保存在tomcat项目所在的目录下
    //动态获得服务器中项目下的文件夹路径
   	ServletContext ctx = ServletActionContext.getServletContext();
   	String realPath = ctx.getRealPath("/upload");//upload文件夹的真实路径
   	String fileName = "hehe.jpg";
   	String filePath = realPath+"/"+fileName;
   	
   	//headPic文件----->filePath路径
   	OutputStream os = new FileOutputStream(filePath);
   	BufferedOutputStream bos = new BufferedOutputStream(os);
   	BufferedInputStream bis = new BufferedInputStream(new FileInputStream(headPic));
   	byte[] bs = new byte[1024];
   	while(true){
   		int i = bis.read(bs);//读入bs数组多少长度
   		if(i<0)break;
   		bos.write(bs, 0, i);
   	}
   	bos.flush();
   	bos.close();
   	bis.close();
④获得上传文件名:
 
文件上传优化
①文件大小
    默认struts接受上传文件大小上限: 2M;
	<!-- 常量配置设置文件上传的大小 -->
	<!-- struts.multipart.maxSize=2097152   100M  1字节*100000000 -->
	<constant name="struts.multipart.maxSize" value="100000000"></constant>
②文件名
    问题: 文件名在服务器端冲突。
    解决: 使用UUID生成唯一的名字作为文件名。
    代码: UUID.randomUUID().toString();"1234-1234-asdfg-2345-435"
    文件名设计: UUID+".后缀";
③保存路径
    问题: 保存文件的目录写死在代码中,耦合,不便于维护。
解决办法: 保存目录名转移到配置文件。
 
④ io工具类:commons-io的jar包
文件拷贝代码简化:FileUtils.copyFile();
(2)文件下载
使浏览器保存该文件,而不是解析展示该文件?
给浏览器设置头信息: "content-disposition" "attachment;filename=文件.后缀"
①设置下载;
    response.setHeader("content-disposition", "attachment;filename="+fileName);
②读入服务器端文件输入流
③指向浏览器的输入流
④边读边写
补充:
	对下载的文件名编码:
    URLEncoder.encode(字符串,"UTF-8");

11).Struts应用-验证码、令牌、日期转化(String/util.Date/sql.Date)

(1)验证码
作用:
①防止机器人登陆,对系统添加无效信息
②防止机器人,恶意注册无效用户信息
使用java生成验证码图片:
①产生一个随机验证码字符串
②如何将字符串生成图片中
public static BufferedImage getSafeCodeImage(String code) throws IOException {
    BufferedImage bi = new BufferedImage(80, 30, BufferedImage.TYPE_INT_BGR);
    Graphics g = bi.getGraphics();
    g.fillRect(0, 0, 80, 30);
    g.setColor(Color.BLUE);
    g.drawString(code, 20, 12);
    /*ImageIO.write(bi, "jpg", new FileOutputStream("D:\a.jpg"));*/
    return bi;
}

public static String getGenerateCode(int n) {
    String str = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
    Random rd = new Random();
    StringBuilder sb = new StringBuilder("");
    for (int i = 0; i < n; i++) {
        sb.append(str.charAt(rd.nextInt(62)));
    }
    return sb.toString();
}

在jsp中产生一个验证码:
验证码工具类:
Hutool(工具包)
导入hutool的jar包。
 CaptchaUtil   	功能: 生成随机验证码(字符串)、 生成验证码图片,直接通过流写出
代码步骤:
①生成验证码对象: 
			Captcha captcha = CaptchaUtil.createLineCaptcha(宽度,高度,字符个数,干扰线个数);
			Captcha captcha = CaptchaUtil.createLineCaptcha(宽度,高度);
②生成验证码:
			captcha.getCode();//code字符串
			captcha.write(outputStream);//将验证码图片通过输出流,写出到对应位置

jsp使用验证码核心思路:依靠image的src,请求生成验证码图片的action,响应写回去
 
使用:
 
(2)Struts2令牌机制
防止表单重复提交
①分发令牌
Struts中给用户分发令牌方式:	<s:token></s:token>
作用: 
a. 给用户的浏览器的表单放入一个随机字符串。
b. 将字符串(令牌),向session中存入一份。
核心机制:
 

②验证令牌
验证令牌核心机制
 

编码步骤:
a. 书写一个验证令牌的拦截器(struts已经提供了) 
b. 配置令牌拦截器拦截防止重复提交的action
c. Action必须继承ActionSupport.
 

(3)日期格式
	①java.util.Date和java.sql.Date之间的转换:
中间值:Date.getTime();
例:
long l = (new java.util.Date()).getTime();
java.sql.Date d = new java.sql.Date(l);
	②String格式转换为日期格式
	日期格式化工具: SimpleDateFormat
	String s = "1999-9-9";
	//1. 创建日期格式化工具,(匹配日期格式)
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
	//2. 调用转发方法
	Date parse = format.parse(s);
原文地址:https://www.cnblogs.com/jwnming/p/13634991.html