Struts2之OGNL表达式

1、什么是OGNL表达式

全称Object Graph Navigation Language,对象导航语言。属于开源项目,其目的是为了取代页面中的Java脚本,简化数据的访问。和EL表达式同属于表达式语言,其功能强大。

2、OGNL表达式的作用

主要用作表达式语言和进行类型转换。如下:

  • 表达式语言:将表单或Struts2标签与特定的Java数据绑定起来,用来将数据移入、移出框架。
  • 类型转换:数据进入和流出框架,在页面数据的字符串类型和Java数据类型之间进行转换。

以下用图示说明:

在这里插入图片描述

3、值栈与OGNL

3.1、值栈

值栈,英文为ValueStack,是由Struts2框架创建的存储区域,具有栈的特点,并且所有的Action实例都会被存放在值栈中。

3.2、OGNL访问值栈

需要注意以下两点:

  • 按照从上到下的顺序访问。
  • 靠近栈顶的同名属性会被读取。

图示如下:

在这里插入图片描述

4、类型转换

4.1、类型转换的意义

在基于HTTP协议的Web应用中,客户端请求的所有内容都是以文本编码方式传输到服务端。服务器端的编程语言却有着丰富的数据类型。比如在Servlet中,接收到的参数类型都是String类型,需要开发者根据需要的类型进行自行转换,如下:

String ageStr = request.getParameter("age");
Integer age = Integer.parseInt(ageStr);

如果每个接收到的参数都需要手动转换,就会很不方便,而类型转换则很好的解决了这一问题。

4.2、内置的类型转换器

Struts2提供了多种内置类型转换器,自动对客户端传来的数据进行类型转换。如下图示:

在这里插入图片描述

4.3、自定义类型转换器

有时Struts2自带的内置转换器不能很好的满足需求,需要自定义类型转换器。自定义的转换器需要继承org.apache.struts2.util.StrutsTypeConverter类,该类的源码如下:

public abstract class StrutsTypeConverter extends DefaultTypeConverter {
    public Object convertValue(Map context, Object o, Class toClass) {
        if (toClass.equals(String.class)) {
            return convertToString(context, o);
        } else if (o instanceof String[]) {
            return convertFromString(context, (String[]) o, toClass);
        } else if (o instanceof String) {
            return convertFromString(context, new String[]{(String) o}, toClass);
        } else {
            return performFallbackConversion(context, o, toClass);
        }
    }

    /**
     * Hook to perform a fallback conversion if every default options failed. By default
     * this will ask Ognl's DefaultTypeConverter (of which this class extends) to
     * perform the conversion.
     *
     * @param context the action context
     * @param o object to be converted
     * @param toClass the class to convert to
     * @return The fallback conversion
     */
    protected Object performFallbackConversion(Map context, Object o, Class toClass) {
        return super.convertValue(context, o, toClass);
    }


    /**
     * Converts one or more String values to the specified class.
     *
     * @param context the action context
     * @param values  the String values to be converted, such as those submitted from an HTML form
     * @param toClass the class to convert to
     * @return the converted object
     */
    public abstract Object convertFromString(Map context, String[] values, Class toClass);

    /**
     * Converts the specified object to a String.
     *
     * @param context the action context
     * @param o       the object to be converted
     * @return the converted String
     */
    public abstract String convertToString(Map context, Object o);
}

一般需要重写convertFromString(Map context, String[] values, Class toClass)方法或convertToString(Map context, Object o)方法,在对象和字符串之间进行转换。

以下将自定义一个日期类型转换器,对日期格式进行自动转换。

4.3.1、创建日期转换器

/**   
 * @ClassName:  DateConverter   
 * @Description:自定义日期类型转换器
 * @author: yanchengzhi
 * @date:   2023年1月9日 下午3:25:01      
 * @Copyright:  
 */
public class DateConverter extends StrutsTypeConverter {
	
	private final DateFormat [] dfs = {
            new SimpleDateFormat("yyyy年MM月dd日"),
            new SimpleDateFormat("yyyy-MM-dd"),
            new SimpleDateFormat("MM/dd/yy"),
            new SimpleDateFormat("yyyy.MM.dd"),
            new SimpleDateFormat("yyMMdd"),
            new SimpleDateFormat("yyyy/MM/dd")
    };

	/**
	 * 字符串转为日期格式
	 */
	@Override
	public Object convertFromString(Map context, String[] values, Class toClass) {
		String dateStr = values[0];
		for(int i=0;i<dfs.length;i++) {
			try {
				return dfs[i].parse(dateStr);
			} catch (Exception e) {
				continue;
			}
		}
		throw new TypeConversionException("转换错误");
	}

	/**
	 * 日期转换为字符串格式
	 */
	@Override
	public String convertToString(Map context, Object o) {
		Date date = (Date)o;
		return dfs[1].format(date);
	}

}

4.3.2、配置转换器

如果是应用于全局范围内的类型转换器,则需要在resources目录下创建一个xwork-conversion.properties属性文件,如下:
在这里插入图片描述
如果是用于特定类的类型转换器,则需要在同级目录下创建一个名为ClassName-conversion.properties的属性文件,配置与上相同。

4.3.3、页面

person.jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
      <form action="person/person.action" method="post">
          <div>
             <label>姓名:</label>
             <input type="text" name="person.name" />
          </div>
          <div>
             <label>年龄:</label>
             <input type="text" name="person.age" />
          </div>
          <div>
             <label>出生日期:</label>
             <input type="text" name="person.birth" />
          </div>
          <div>
             <input type="submit" value="提交" />
          </div>
     </form>
</body>
</html>

personMess.jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
     <h1>姓名:<s:property value="person.name" /> </h1>
     <h1>年龄:<s:property value="person.age" /> </h1>
     <h1>出生日期:<s:property value="person.birth" /> </h1>
     <h1>出生日期:<s:date name="person.birth" /> </h1>
</body>
</html>

4.3.4、实体类和Action控制器

Person类如下:

@Data
public class Person {
	
	private String name;
	
	private Integer age;
	
	private Date birth;

}

PersonAction控制器如下:

public class PersonAction extends ActionSupport {

	private static final long serialVersionUID = 1L;
	
	private Person person;

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}
	
	public String test() {
		System.out.println(person.toString());
		return SUCCESS;
	}

}

4.3.5、struts.xml配置

             <package name="person" extends="default" namespace="/person">
                <action name="person" class="com.ycz.struts01.action.PersonAction" method="test">
                   <result>/personMess.jsp</result>
                </action>
             </package>

4.3.6、测试

启动项目,访问http://localhost:8081/struts01/person.jsp:

在这里插入图片描述
填写表单,这里的出生日期是手动输入的字符串,只要满足自定义类型转换器里的一种格式即可:

在这里插入图片描述
提交表单,页面跳转:

在这里插入图片描述
控制台输出:

在这里插入图片描述
可以看到,控制台输出的是日期格式,而表单中填写的是字符串格式,格式自动由字符串转换成了日期,而该转换由类型转换器自动完成。注意页面中用到了一个特殊标签:

在这里插入图片描述
<s:date>标签用于向页面中输出格式化的日期,该标签有三个属性,name,format和nice。当nice属性为false时(不指定默认为false),可通过format属性自定义日期的格式,如果为true,format设置将不生效。

4.4、处理类型转换错误

在这里插入图片描述
在这里插入图片描述

在resources目录下创建message.properties属性文件,内容如下:

xwork.default.invalid.fieldvalue=字段"{0}"的值无效

然后在sturts.xml中进行配置:

在这里插入图片描述
在这里插入图片描述

页面中添加相应的错误输出标签:

在这里插入图片描述

启动项目,访问页面:

在这里插入图片描述
日期里输入一个错误格式,提交:

在这里插入图片描述
错误提示消息正确回显了。

5、OGNL表达式注意事项

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值