Struts2(六)
以下内容是基于导入struts2-2.3.32.jar包来讲的
1.OGNL
OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者调用对象的方法,能够遍历整个对象的结构图,实现对象属性类型的转换等功能。它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
OGNL 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了 java.utils.Map 的接口。
作用:
1、支持对象方法调用,如xxx.doSomeSpecial();
2、支持类静态的方法调用和值访问,表达式的格式:
@[类全名(包括包路径)]@[方法名 | 值名],例如:
@java.lang.String@format('foo %s', 'bar')
或@tutorial.MyConstant@APP_NAME;
3、支持赋值操作和表达式串联,如price=100, discount=0.8,
calculatePrice(),这个表达式会返回80;
4、访问OGNL上下文(OGNL context)和ActionContext;
5、操作集合对象。
ognl表达式取值,如果是根元素取值不用带#符号, 非根元素取值要带#号!
知识点:
OGNL中重要的3个符号:#、%、$:
#符号的用途一般有三种。
— 访问非根对象属性,例如#session.msg表达式,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀。实际上,#相当于ActionContext. getContext();#session.msg表达式相当于ActionContext.getContext().getSession(). getAttribute("msg") 。
— 用于过滤和投影(projecting)集合,如persons.{?#this.age>25},persons.{?#this.name=='pla1'}.{age}[0]。
— 用来构造Map,例如示例中的#{'foo1':'bar1', 'foo2':'bar2'}。
2.%符号
%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值,这个类似js中的eval,很暴力。
3.$符号
$符号主要有两个方面的用途。
— 在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在${min}同${max}之间。
— 在Struts 2框架的配置文件中引用OGNL表达式。
2.基本使用
A.往根元素设置并获取值:
package com.rong.web.test; import com.rong.web.entity.User; import ognl.Ognl;
import ognl.OgnlContext; public class OGNLTest { public static void main(String[] args) throws Exception{
//Ognl上下文OgnlContext实现了 java.util.Map 的接口,具有Map的功能
OgnlContext ognlContext = new OgnlContext();
ognlContext.put("username", "huge");
System.out.println(ognlContext.get("username")); User user=new User();
user.setId(57);
user.setName("rjl");
user.setAge(18);
//设置上下文根对象
ognlContext.setRoot(user);
//表达式
Object expression1 = Ognl.parseExpression("name");
Object expression2 = Ognl.parseExpression("id");
Object expression3 = Ognl.parseExpression("age");
Object value1 = Ognl.getValue(expression1, ognlContext, ognlContext.getRoot());
Object value2 = Ognl.getValue(expression2, ognlContext, ognlContext.getRoot());
Object value3 = Ognl.getValue(expression3, ognlContext, ognlContext.getRoot()); System.out.println(value1.toString()+value2.toString()+value3.toString());
}
}
B.往非根元素设置并获取值:
package com.rong.web.test; import com.rong.web.entity.Student; import ognl.Ognl;
import ognl.OgnlContext; public class OGNLTest { public static void main(String[] args) throws Exception{
//Ognl上下文OgnlContext实现了 java.utils.Map 的接口,具有Map的功能
OgnlContext ognlContext = new OgnlContext();
//往非根元素设置值;非根元素取值要带#号
Student student = new Student(24,"kobe",38);
ognlContext.put("stu", student);
Object expression = Ognl.parseExpression("#stu.sid");
Object value = Ognl.getValue(expression, ognlContext, ognlContext.getRoot());
System.out.println(value);
}
}
3.值栈(ValueStack)
ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础。
ValueStack贯穿整个 Action 的生命周期
(每个 Action 类的对象实例都拥有一个ValueStack 对象).
相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象.
Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 的request请求属性中。
Action中获取值栈对象的两种方式:
package com.rong.web.action; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L; @Override
public String execute() throws Exception {
ActionContext actionContext = ActionContext.getContext();
//ValueStack是执行Ognl表达式的基础。也是从OgnlContext中去获取值、设置值的基础
//ValueStack值栈
ValueStack valueStack = actionContext.getValueStack();
//com.opensymphony.xwork2.ognl.OgnlValueStack@55195240
System.out.println(valueStack); //Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 的request请求属性中。
HttpServletRequest request = ServletActionContext.getRequest();
Object object = request.getAttribute("struts.valueStack");
//com.opensymphony.xwork2.ognl.OgnlValueStack@55195240
System.out.println(object);
return SUCCESS;
}
}
ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中--List
ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中
Struts 会把下面这些映射压入 ContextMap 中
parameters: 该 Map 中包含当前请求的请求参数
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application 对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application
值栈中有根元素 和 非根元素。
非根元素就是OgnlContext
OgnlContext中引用了值栈的根元素数据
Struts每次访问action的时候:
1. 创建一个ActionContext对象
2. 创建值栈对象
把域中存放的数据、以及Action对象,放到值栈中!
这时候,值栈就有了struts运行时期的数据!
3. 把值栈的数据,拷贝一份给ActionContext!
4. 最后,把值栈放到request的请求中!
操作根元素数据:
ActionContext actionContext = ActionContext.getContext();
//ValueStack是执行Ognl表达式的基础。也是从OgnlContext中去获取值、设置值的基础
//ValueStack值栈
ValueStack valueStack = actionContext.getValueStack();
//com.opensymphony.xwork2.ognl.OgnlValueStack@55195240
System.out.println(valueStack);
Student student = new Student(24,"kobe",38);
valueStack.pop();//移出根元素
valueStack.getRoot().push(student);//设置根元素 boolean empty = valueStack.getRoot().isEmpty();
System.out.println("根元素是否为空:"+empty);
Student pop = (Student) valueStack.getRoot().pop();//移出根元素,并返回该元素
System.out.println(pop.getSname());
操作非根元素数据:
package com.rong.web.action; import java.util.Map; import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.rong.web.entity.Student; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L; @Override
public String execute() throws Exception {
ActionContext actionContext = ActionContext.getContext();
Student student = new Student(24,"kobe",38);
Map<String, Object> request = actionContext.getContextMap();
request.put("one", "ONE");
Map<String, Object> session = actionContext.getSession();
session.put("two", student);
Map<String, Object> application = actionContext.getApplication();
application.put("three", "Three");
System.out.println(request.get("one"));
System.out.println(((Student)session.get("two")).getSname());
System.out.println(application.get("three")); return SUCCESS;
}
}
4.struts标签(实际开发很少用,用jstl较多)
标签防止重复提交
<s:token />标签防止重复提交,用法如下:第一步:在表单中加入<s:token />
<s:form action="helloworld_other" method="post" namespace="/test">
<s:textfield name="person.name"/><s:token/><s:submit/>
</s:form>
第二步:
<action name="helloworld_*" class="com.rong.web.action.HelloWorldAction" method="{1}">
<interceptor-ref name="defaultStack"/>
<!-- 增加令牌拦截器 -->
<interceptor-ref name="token">
<!-- 哪些方法被令牌拦截器拦截 -->
<param name=“includeMethods">save</param>
</interceptor-ref>
<!-- 当表单重复提交转向的页面 -->
<result name="invalid.token">/WEB-INF/page/message.jsp</result>
</action>
以上配置加入了“token”拦截器和“invalid.token”结果,因为“token”拦截器在会话的token与请求的token不一致时,将会直接返回“invalid.token”结果。
在debug状态,控制台出现下面信息,是因为Action中并没有struts.token和struts.token.name属性,我们不用关心这个错误:
严重: ParametersInterceptor - [setParameters]: Unexpected Exception caught setting 'struts.token' on 'class xxx: Error setting expression 'struts.token' with value '[Ljava.lang.String;@39f16f'
严重: ParametersInterceptor - [setParameters]: Unexpected Exception caught setting 'struts.token.name'
$符号配置文件取值用:
package com.rong.web.action; import com.opensymphony.xwork2.ActionSupport; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L;
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String execute() throws Exception {
username="rjl";
return SUCCESS;
}
}
<struts>
<package name="default" namespace="/" extends="struts-default" >
<action name="test" class="com.rong.web.action.MyAction">
<result type="redirect">/one.jsp?username=${username}</result>
</action>
</package>
</struts>
#号%号略。
struts标签使用:
导入标签库:<%@ taglib uri="/struts-tags" prefix="s"%>
1、条件标签 if…elseif…else
package com.rong.web.action; import java.util.Map; import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L;
@Override
public String execute() throws Exception {
ActionContext actionContext = ActionContext.getContext();
Map<String, Object> session = actionContext.getSession();
session.put("number", 57);
return SUCCESS;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/struts-tags" prefix="s"%>
<c:set var="basePath" value="${pageContext.request.contextPath }"></c:set>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
one.jsp!
<s:debug></s:debug>
<s:if test="#session.number>57">great!</s:if>
<s:elseif test="#session.number<57">less!</s:elseif>
<s:else>equal!</s:else>
</body>
</html>
2、迭代标签 iterator
用于循环数组,集合和Map
属性:
value:数组,集合或Map
var:当前元素
status:当前元素的状态index,count,even,odd,first,last
其余的标签略。
5.Action中验证(代码验证)
后台向前台返回校验信息,数据校验由后台进行(较少用,一般前台做数据校验)
A.验证所有方法
<struts>
<package name="default" namespace="/" extends="struts-default" >
<action name="check" class="com.rong.web.action.MyAction">
<result>/one.jsp</result>
<!-- 验证信息错误时,框架固定返回input视图 -->
<result name="input">/index.jsp</result>
</action>
</package>
</struts>
index.jsp
<body>
<form action="${pageContext.request.contextPath }/check" method="post">
<input type="text" name="student.sname"/>
<!-- 获取后台返回的校验信息 -->
<s:fielderror key="#student.sname"></s:fielderror>
<input type="submit" value="登录"/>
</form>
</body>
MyAction.java
package com.rong.web.action; import com.opensymphony.xwork2.ActionSupport;
import com.rong.web.entity.Student; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
//重写validate方法校验前台信息,在执行execute方法之前执行。此Action里所有的方法都会走这个验证。
@Override
public void validate() {
if(student.getSname().trim().length()==0){
//向前台返回校验信息
this.addFieldError("student.sname", "学生名字不能为空!");
}
}
@Override
public String execute() throws Exception {
System.out.println("execute!!!");
return SUCCESS;
}
}
B.验证某个方法
public void validate方法名(){
//方法名首字母需要大写!!!
}
package com.rong.web.action; import com.opensymphony.xwork2.ActionSupport;
import com.rong.web.entity.Student; public class MyAction extends ActionSupport {
private static final long serialVersionUID = -351587239525292420L;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
//针对某一个方法做验证:validate方法名,其中方法名首字母要大写
public void validateExecute(){
if(student.getSname().trim().length()==0){
//向前台返回校验信息
this.addFieldError("student.sname", "学生名字不能为空!");
}
}
@Override
public String execute() throws Exception {
System.out.println("execute!!!");
return SUCCESS;
}
}
C.添加/显示错误
添加:
@Override
public void validate() {
if(student.getSname().trim().length()==0){
//向前台返回校验信息
this.addFieldError("student.sname", "学生名字不能为空!");
}
}
显示:
<body>
<form action="${pageContext.request.contextPath }/check" method="post">
<input type="text" name="student.sname"/>
<!-- 获取后台返回的校验信息 -->
<!-- 显示指定错误信息 -->
<s:fielderror key="#student.sname"></s:fielderror>
<!-- 显示指定错误信息 -->
<s:fielderror fieldName="student.sname"></s:fielderror>
<!-- 可以显示所有的错误信息 -->
<s:fielderror></s:fielderror>
<input type="submit" value="登录"/>
</form>
</body>
fielderror标签样式问题:
struts默认添加额外的ul-li样式,去除这种效果便于显示!
解决方式:
1.新建src\\template\\simple包
2.拷贝一个fielderror.ftl
3.修改fielderror.ftl文件,把ul和li去掉即可
Struts2(六)的更多相关文章
- Struts2(六):ResultType
本章节将继续学习struts2的返回类型的使用方法. 学习文档下载struts2 full包解压后会在doc下包含离线html文档. 点击运行后页面: 点击Guides向导终将会有向导列表 再点开后, ...
- Struts2六、为应用指定多个配置文件
为了使用Struts.xml更简洁,更利于维护,我们可以把Struts.xml要配置的Action信息分类别放在其他的XML文件中,使用include在struts.xml中加载这些文件: 将Web. ...
- Struts2(六) 用Struts完成客户列表显示
Struts完成客户列表显示 所用的基础知识 在之前的随笔中已经讲过.这篇是介绍如何使用Struts 完成客户列表显示 . 下面是 完成的代码执行逻辑图: 抽取项目部分代码 相信大家认真看一遍就明 ...
- struts2(六) 文件上传和下载
前面对文件下载提过一点点,这里正好要讲文件上传,就放在一起在说一遍. --WH 一.单文件上传 在没学struts2之前,我们要写文件上传,非常麻烦,需要手动一步步去获取表单中的各种属性,然后在进行相 ...
- Struts2(六)result
一.result简述 result:输出结果:第个Action返回一个字符串,Struts2根据这个值来决定响应结果 name属性:result的逻辑名.和Actin里的返回值匹配,默认"s ...
- Struts2(六.用标签显示用户列表及Value Stack和Stack Context)
一.用Struts2标签显示用户列表 原理: 在struts中可以通过在action中将所有用户的信息存入到某个范围中,然后转向userlist.jsp,进行访问 原则: 在jsp网页上,尽量不要出现 ...
- 二十六:Struts2 和 spring整合
二十六:Struts2 和 spring整合 将项目名称为day29_02_struts2Spring下的scr目录下的Struts.xml文件拷贝到新项目的scr目录下 在新项目的WebRoot-- ...
- Struts2(十六)Json
一.JSON Json就是浏览器和服务器之间交换数据的一种轻量级对象 javaSctipt中类似的对象操作 $(function() { var person = { "name" ...
- 六、Struts2的配置文件
六.Struts2的配置文件 1.default.properties:在struts2-core-**.jar的org.apache.struts包中 关于Struts2一些常量配置(框架内部) s ...
- struts2总结六: Struts2的拦截器
一.Struts2的系统结构图
随机推荐
- Python-条件语句和循环语句
·条件语句 笔记: If 布尔值: print(‘hello,world!’) 当表达式为布尔表达式时,Flase None 0 ”” () [] {} 都视为假! @ ...
- python 数据类型、进制转换
数据类型 存储单位 最小单位是bit,表示二进制的0或1,一般写作b 最小的存储单位是字节,用byte表示,1B = 8b 1024B = 1KB 1024KB = 1MB 1024MB = 1GB ...
- homebrew 使用心得
''' 安装anaconda 安装命令: brew search anaconda brew cask install anaconda 添加环境变量: vi ~/.bash_profile expo ...
- 格式化输出%02hhx
每次看到人家的十六进制输出,对齐的很好,ff就显示了,而我的总是0xffffffff.如果是"%02x",是以0补齐2位数,如果超过2位就显示实际的数:"%hhx&quo ...
- c语言宏
使用 c语言的宏是在预处理时候对字符进行简单替换. 优点:1.如果要改一个变量,只需要改宏就可以了,也就是只改一次;2.宏函数展开和普通函数一样,但是它没有普通函数调用的过程,不需要压栈出栈等操作,所 ...
- js 修改字符串中某些字符的样式
var str = 'abcdefghijklmnobqrstuvwxyz'; function HightLight(e){ var reg = new RegExp(e, 'g') str = s ...
- 20155204 实验3《敏捷开发与XP实践》实验报告
20155204 实验3<敏捷开发与XP实践>实验报告 一.实验内容与步骤 1.研究IDEA的code菜单. 老师给的任务的是把一串代码格式化,这个任务很简单.code菜单主要是关于编辑代 ...
- 学号20155308 2006-2007-2 《Java程序设计》第3周学习总结
学号20155308 2006-2007-2 <Java程序设计>第3周学习总结 教材学习内容总结 对象(Object):存在的具体实体,具有明确的状态和行为 类(Class):具有相同属 ...
- 适配iOS11和iPhoneX
详细见参考链接吧, 其他不多说了. 适配iOS11&iPhoneX的一些坑 http://www.cocoachina.com/ios/20170921/20623.html http://w ...
- CF 833 B. The Bakery
B. The Bakery http://codeforces.com/contest/833/problem/B 题意: 将一个长度为n的序列分成k份,每份的cost为不同的数的个数,求最大cost ...