我是靠谱客的博主 英俊短靴,最近开发中收集的这篇文章主要介绍JAVAWEB开发之Struts2详解(四)——ognl与valueStack(重点)、Struts常用标签、防止表单重复提交、Struts2中内置json插件...,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
ognl
ognl中有一个OgnlContext,它可以设置root与非root,root中获取数据时,不需要加#,而非root数据获取时需要加#号。
简单示例如下:
OgnlDemo1
package cn.itcast.ognl;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OgnlDemo1 {
public static void main(String[] args) throws OgnlException {
// ognl可以通过对象调用方法
// System.out.println("aaa".length());
// 使用ognl来完成上面操作
// 1.创建一个ognl上下文
OgnlContext context = new OgnlContext();
Object obj1 = Ognl.getValue("'aaa'.length()", context.getRoot());
System.out.println(obj1);
}
}
OgnlDemo2
package cn.itcast.ognl;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OgnlDemo2 {
public static void main(String[] args) throws OgnlException {
// ognl可以通过类调用静态方法
System.out.println(Math.max(10, 20));
System.out.println(Math.PI);
// 使用ognl来完成上面操作
// 1.创建一个ognl上下文
OgnlContext context = new OgnlContext();
Object obj1 = Ognl.getValue("@java.lang.Math@max(10,20)",
context.getRoot());
System.out.println(obj1);
Object obj2 = Ognl.getValue("@java.lang.Math@PI", context.getRoot());
System.out.println(obj2);
}
}
关于存取根与非根数据如下所示:
Person
package cn.itcast.ognl;
public class Person {
private String name;
private Dog dog;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
Dog
package cn.itcast.ognl;
public class Dog {
private String name;
private Person p;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
}
OgnlDemo3
package cn.itcast.ognl;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OgnlDemo3 {
public static void main(String[] args) throws OgnlException {
// 创建一个ognl上下文
OgnlContext context = new OgnlContext();// 本质上是一个Map集合
Person p = new Person();
p.setName("张三");
Dog dog = new Dog();
dog.setName("lucy");
p.setDog(dog); // 张三有条狗叫lucy
context.setRoot(p);
Dog dog1 = new Dog();
dog1.setName("豆豆");
Person pp = new Person();
pp.setName("jams");
dog1.setP(pp);
context.put("dog", dog1);
context.put("name", "tom");
// 使用ognl来获取根中数据,不需要加#
Object name1 = Ognl.getValue("name", context, context.getRoot());
System.out.println(name1);
// 使用ognl来获取非根中的数据,获取非根中的数据 需要使用#
Object name2 = Ognl.getValue("#name", context, context.getRoot());
System.out.println(name2);
// 获取张三的狗的名称
Object name3 = Ognl.getValue("dog.name", context, context.getRoot());
System.out.println(name3);
// 获取豆豆的主人名称
Object name4 = Ognl.getValue("#dog.p.name", context, context.getRoot());
System.out.println(name4);
}
}
ognl介绍
ognl是Object Graphic Navigation Language(对象导航图语言)的缩写,它是一个开源项目。Struts2框架使用ognl作为默认的表达式语言。
ognl是一种比EL强大很多倍的语言。
ognl相对其它表达式语言具有下面五大优势:
1、支持对象方法调用,如xxx.doSomeSpecial();
2、支持类静态方法的调用和值访问,表达式的格式:@[类全名(包括包路径)]@[方法名| 值名],例如:@java.lang.String@format("foo %s","bar");或@tutorial.MyConstant@APP_NAME;
设置:struts.ognl.allowStaticMethodAccess=true;
3、访问ognl上下文(OGNL context)和ActionContext;(重点:操作valueStack值栈)
4、支持赋值操作和表达式串联,如price=100,discount=0.8,caculatePrice(),这个表达式会返回80;
5、操作集合对象。
示例:
<h1>实例方法调用</h1>
<s:property value="'abcdef'.length()"/>
<h2>静态方法调用</h2>
<s:property value="@java.lang.String@format('你好, %s','小明')"/>
<s:property value="'abcdef'.length()"/>
<h2>静态方法调用</h2>
<s:property value="@java.lang.String@format('你好, %s','小明')"/>
演示:在struts2中使用ognl表达式
需要结合struts2的标签使用<s:property value="ognl表达式">
<s:property value="'abc'.length()"/> 演示对象调用方法
<s:property value="@java.lang.Math@max(10,20)"/> 演示静态成员访问.
注意:在struts2中使用静态成员访问,必须设置一个常量:
struts.ognl.allowStaticMethodAccess=false
<s:property value="'abc'.length()"/> 演示对象调用方法
<s:property value="@java.lang.Math@max(10,20)"/> 演示静态成员访问.
注意:在struts2中使用静态成员访问,必须设置一个常量:
struts.ognl.allowStaticMethodAccess=false
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:使用ognl来通过对象调用方法</title>
</head>
<body>
<s:property value="'abc'.length()" />
<hr>
<s:property value="@java.lang.Math@max(10,20)" />
</body>
</html>
Struts2中的valueStack
valueStack概述:
ValueStack实际上是一个接口com.opensymphony.xwork2.util.ValueStack,在Struts2中利用ognl时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础
- ValueStack(值栈):贯穿Action的生命周期(每个Action类的对象实例都拥有一个ValueStack对象)相当于一个数据中的中转站.在其中保存当前Action对象和其他相关对象。
- Struts框架把ValueStack对象保存在名为"struts.valueStack"的请求属性中,request中。
在ValueStack对象内部有两个逻辑部分:
- 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
理解Struts2中的ValueStack
断点执行如下代码:
Object ctx=ServletActionContext.getRequest().getAttribute("struts.valueStack");
______________________________________________________________________________
理解OGNL Context
OGNL Context是Struts2的数据中心,结构示意图如下:
当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action,然后将action存放进ValueStack,所以action的实例变量可以被OGNL访问
注意:Struts2中,OGNL表达式需要配合Struts标签才可以使用,如:<s:property value="name" />
问题1:什么是ValueStack?
valueStack主要是将action数据携带到页面上,通过ognl获取数据
1、ValueStack有一个实现类叫OgnlValueStack。
2、每一个action都有一个ValueStack(一个请求,一个request,一个action,一个ValueStack)valueStack生命周期就是request生命周期。
3、valueStack中存储了当前action对象以及其它常用web对象(request,session,application,parameters)
4、Struts2框架将valueStack以"struts.valueStack"为名存储到request域中
ValueStack内部结构图如下:
问题2:valueStack结构?
ValueStack中存在root属性(CompoundRoot)、context属性(OgnlContext)
* CompoundRoot 就是ArrayList
* OgnlContext 就是Map
list 集合中存储的是action相关信息
map集合中存储的是相关映射信息,包含 parameters、request、session,application,attr等
想要从list中获取数据,可以不使用#号(它就是ognl的root)
如果从map中获取数据,需要使用#(其实在Struts2中的map—context其实就是OgnlContext)
结论:
ValueStack有两部分List Map
在Struts2中List就是root,Map就是OgnlContext
默认情况下,在Struts2中从ValueStack中获取数据从root中获取
问题3:值栈对象的创建,ValueStack和ActionContext是什么关系?
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
stack = ctx.getValueStack();
}
if (ctx != null) {
stack = ctx.getValueStack();
}
ValueStack是每一次请求时,都会创建
在ActionContext中持有了ValueStack的引用
ValueStack对象的创建过程
StrutsPrepareAndExecuteFilter
doFilter方法
prepare.createActionContext(request, response);
创建ActionContext和ValueStack
ctx = new ActionContext(stack.getContext());
ActionContext引用ValueStack对象
Dispatcher——serviceAction方法
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
将ValueStack对象 保存到request 范围
doFilter方法
prepare.createActionContext(request, response);
创建ActionContext和ValueStack
ctx = new ActionContext(stack.getContext());
ActionContext引用ValueStack对象
Dispatcher——serviceAction方法
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
将ValueStack对象 保存到request 范围
问题4:如何获得值栈对象?
对于ValueStack获取有两种方式:
1、通过request获取
ValueStack vs=(ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STATUS_VALUESTACK_KEY);
2、通过ActionContext获取
ValueStack vs=ActionContext.getContext().getValueStack();
问题5:向值栈中保存数据(主要针对root)
主要有两个方法
push(Object obj)----->底层就是root.add(0,obj) 将数据存储到栈顶。
set(String name,Object obj)------->底层是将数据封装到HashMap中,在将这个HashMap通过push存储。
在JSP通过<s:debug />查看值栈内容
ActionContext提供了对ognl上下文对象中数据操作的方法
ServletActionContext.getRequest().setAttribute("username", "username_request");
ServletActionContext.getServletContext().setAttribute("username", "username_application");
ServletActionContext.getContext().getSession().put("username", "username_session");
// 获取值栈对象
ValueStack valueStack=ServletActionContext.getContext().getValueStack();
System.out.println("valueStack "+valueStack);
// 向值栈保存数据
valueStack.set("username", "username_valueStack");
valueStach.push("www.baidu.com");
ServletActionContext.getServletContext().setAttribute("username", "username_application");
ServletActionContext.getContext().getSession().put("username", "username_session");
// 获取值栈对象
ValueStack valueStack=ServletActionContext.getContext().getValueStack();
System.out.println("valueStack "+valueStack);
// 向值栈保存数据
valueStack.set("username", "username_valueStack");
valueStach.push("www.baidu.com");
问题6:如何在JSP中获取值栈的数据?
获取root中数据不需要#,而context中数据需要#
1、如果栈顶是一个Map集合,获取时,可以直接通过Map集合的key来获取value
<s:property value="username" />
2、如果栈顶数据不是一个Map,没有key值,可以通过序号来获取
<s:property value="[0]"> 从0的位置向下查找所有
<s:property value="[0].top"> 只查找0位置上数据(栈顶数据)
3、获取OgnlContext中的数据
request:<s:property value="#request.username"/>
session:<s:property value="#session.username"/>
application:<s:property value="#application.username"/>
attr:<s:property value="#attr.username"/>
parameters:<s:property value="#parameters.cid[0]"/>
session:<s:property value="#session.username"/>
application:<s:property value="#application.username"/>
attr:<s:property value="#attr.username"/>
parameters:<s:property value="#parameters.cid[0]"/>
ValueStack主流应用:就是解决将action数据携带到jsp页面
问题:action向jsp携带数据,都是什么样的数据?
1、文本(字符串)
fieldError 校验数据错误信息提示
actionError 关于逻辑操作时错误信息(例如登录失败)
message 就是一个信息提示
this.addFieldError("msg", "字段错误信息");
this.addActionError("Action全局错误信息");
this.addActionMessage("Action的消息信息");
this.addActionMessage("Action的消息信息");
fieldError 针对某一个字段错误信息(常用于表单校验)、actionError(普通错误信息,不针对某个字段 如登录失败)、actionMessage 通用消息
在jsp中使用 struts2提供标签 显示消息信息
<s:fielderror fieldName="msg"/>
<s:actionerror/>
<s:actionmessage/>
<s:fielderror fieldName="msg"/>
<s:actionerror/>
<s:actionmessage/>
2、复杂数据
可以使用valueStack存储
在action中存储数据
List<User> users = new ArrayList<User>();
users.add(new User("tom", "123", 20, "男"));
users.add(new User("james", "456", 21, "男"));
users.add(new User("fox", "789", 26, "男"));
vs.push(users);
在页面上获取数据:
使用了<s:iterator>标签来迭代集合。
<s:iterator value="[0].top" var="user"> 这是将集合中迭代出来每一个元素起个名称叫user,而user是存储在context中,不在root中.l
<s:iterator value="[0].top" var="user">
username:<s:property value="#user.username"/><br>
password:<s:property value="#user.password"/>
<hr>
</s:iterator>
注意:如果我们在使用<s:iterator>进行迭代时,没有给迭代出的元素起名.
<s:iterator value="[0].top">
username:<s:property value="username"/><br>
password:<s:property value="password"/>
<hr>
</s:iterator>
users.add(new User("tom", "123", 20, "男"));
users.add(new User("james", "456", 21, "男"));
users.add(new User("fox", "789", 26, "男"));
vs.push(users);
在页面上获取数据:
使用了<s:iterator>标签来迭代集合。
<s:iterator value="[0].top" var="user"> 这是将集合中迭代出来每一个元素起个名称叫user,而user是存储在context中,不在root中.l
<s:iterator value="[0].top" var="user">
username:<s:property value="#user.username"/><br>
password:<s:property value="#user.password"/>
<hr>
</s:iterator>
注意:如果我们在使用<s:iterator>进行迭代时,没有给迭代出的元素起名.
<s:iterator value="[0].top">
username:<s:property value="username"/><br>
password:<s:property value="password"/>
<hr>
</s:iterator>
关于默认压入到valueStack中的数据
1、访问的action对象会被压入到valueStack中。
DefaultActionInvocation 的init方法 stack.push(action);
Action如果想传递数据给JSP,只有将数据保存成成员变量,并且提供get方法就可以了。
2.ModelDriveInterceptor会执行下面操作
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
Object model = modelDriven.getModel();
if (model != null) {
stack.push(model);
}
将实现了ModelDrive接口的action中getModel方法的返回值,也就是我们所说的model对象压入到了valueStack.
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
Object model = modelDriven.getModel();
if (model != null) {
stack.push(model);
}
将实现了ModelDrive接口的action中getModel方法的返回值,也就是我们所说的model对象压入到了valueStack.
问题7:为什么EL表达式可以访问valueStack中的数据?
Struts2框架中所使用的request对象,是增强后的request对象。
${ username }--------->request.getAttribute("username");
增强后的request,会首先在request范围查找,如果查找不到,会在valueStack中查找。
StrutsPreparedAndExecuteFilter的doFilter代码中 request = prepare.wrapRequest(request);
* 对Request对象进行了包装 ,StrutsRequestWrapper
* 重写request的 getAttribute
Object attribute = super.getAttribute(s);
if (attribute == null) {
attribute = stack.findValue(s);
}
* 对Request对象进行了包装 ,StrutsRequestWrapper
* 重写request的 getAttribute
Object attribute = super.getAttribute(s);
if (attribute == null) {
attribute = stack.findValue(s);
}
访问request范围的数据时,如果数据找不到,去值栈中找
request对象 具备访问值栈数据的能力(查找root的数据)
OGNL表达式常见用法($ % #)
#号的用法
用法一: 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext()
如果访问OgnlContext中的除了被抽取后的root外的其他对象,由于它们不是根对象,所以在访问时,需要添加#前缀
也可以写为#request['username'] 或#session['username']或#application['username']
Action中代码:
ServletActionContext.getRequest().setAttribute("username", "username_request");
ServletActionContext.getServletContext().setAttribute("username", "username_application");
ServletActionContext.getContext().getSession().put("username", "username_session");
ValueStack valueStack=ServletActionContext.getContext().getValueStack();
valueStack.set("username", "username_valueStack");
ServletActionContext.getRequest().setAttribute("username", "username_request");
ServletActionContext.getServletContext().setAttribute("username", "username_application");
ServletActionContext.getContext().getSession().put("username", "username_session");
ValueStack valueStack=ServletActionContext.getContext().getValueStack();
valueStack.set("username", "username_valueStack");
Jsp页面:
使用ognl表达式取值*****************************<br>
request:<s:property value="#request.username"/><br>
session:<s:property value="#session.username"/><br>
application:<s:property value="#application.username"/><br>
attr:<s:property value="#attr.username"/><br>
valueStack:<s:property value="username"/><br>
parameters:<s:property value="#parameters.cid[0]"/><br>
用法二:不写#号 默认在值栈root中进行查找
request:<s:property value="#request.username"/><br>
session:<s:property value="#session.username"/><br>
application:<s:property value="#application.username"/><br>
attr:<s:property value="#attr.username"/><br>
valueStack:<s:property value="username"/><br>
parameters:<s:property value="#parameters.cid[0]"/><br>
用法二:不写#号 默认在值栈root中进行查找
在OgnlValueStack类中有一个List类型的root变量,它存放了一组对象。
处于第一位的对象叫栈顶对象。
通常我们在ognl表达式里直接写上属性的名称即可访问root变量里对象的属性,搜索顺序是从栈顶元素开始寻找,如果栈顶对象不存在该属性,就会从第二个对象开始寻找,如果没有找到就会从第三个对象开始寻找,依次向下访问直到找到为止。代码示例剖析如下图所示:
<s:property value="name" /> 在root中查找name属性
* 查询元素时,从root的栈顶元素 开始查找, 如果访问指定栈中元素
<s:property value="[1].name" /> 访问栈中第二个元素name属性
* 访问第二个元素对象 <s:property value="[1].top" />
用法三:进行投影映射(过滤)
* 查询元素时,从root的栈顶元素 开始查找, 如果访问指定栈中元素
<s:property value="[1].name" /> 访问栈中第二个元素name属性
* 访问第二个元素对象 <s:property value="[1].top" />
用法三:进行投影映射(过滤)
1、集合的投影(只输出部分属性)
collocationName.{ expression }
<h1>遍历集合只要name属性</h1>
<s:iterator value="products.{name}" var="pname">
<s:property value="#pname"/>
</s:iterator>
2、遍历时对数据设置条件
例如过滤年龄大于19 的用户
集合的过滤有以下三种方式:
方式一:"?#":过滤所有符合条件的集合,如:users.{?#this.age>19};
方式二:"^#":过滤第一个符合条件的元素,如:users.{^#this.age>19};
方式三:"$#":过滤最后一个符合条件的元素,如:users.{$#this.age>19};
this:表示集合中的每个元素。
<h1>遍历集合只要price大于1500商品</h1>
<s:iterator value="products.{?#this.price>1500}" var="product">
<s:property value="#product.name"/> --- <s:property value="#product.price"/>
</s:iterator>
<s:iterator value="products.{?#this.price>1500}" var="product">
<s:property value="#product.name"/> --- <s:property value="#product.price"/>
</s:iterator>
3、投影综合使用
投影(过滤)操作返回的是一个集合,可以使用索引取得集合中指定的元素,如:users.{?#this.age>19}[0]
<s:iterator value="allList.{?#this.age>25}.{name}" var="person">
<s:property/><br>
</s:iterator>
<s:iterator value="allList.{?#this.age>25}[0]" var="person">
<s:property/><br>
</s:iterator>
<s:property/><br>
</s:iterator>
<s:iterator value="allList.{?#this.age>25}[0]" var="person">
<s:property/><br>
</s:iterator>
<h1>只显示价格大于1500 商品名称</h1>
<s:iterator value="products.{?#this.price>1500}.{name}" var="pname">
<s:property value="#pname"/>
</s:iterator>
<s:iterator value="products.{?#this.price>1500}.{name}" var="pname">
<s:property value="#pname"/>
</s:iterator>
用法四:使用#号构造Map,如#{‘foo1’:‘bar1’, ‘foo2’:‘bar2’}
经常结合Struts2标签用来生成select、checkbox、radio
<h1>使用#构造map集合 遍历</h1>
<s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry">
key : <s:property value="#entry.key"/> , value: <s:property value="#entry.value"/> <br/>
</s:iterator>
<s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry">
key : <s:property value="#entry.key"/> , value: <s:property value="#entry.value"/> <br/>
</s:iterator>
%号的使用
%号的用途是在标签的属性值被理解为字符串类型时,告诉执行环境%{}里的OGNL表达式。
%{表达式} 当前表达式会被作为ognl解析。
%{'表达式'} 当前表达式不会被作为ognl解析。
<s:property value="表达式"> 对于s:property标签,他的value属性会被默认作为ognl。以后,所有表达式如果想要让其是ognl %{表达式}
$号用法
$作用:就是在配置文件中使用ognl表达式来获取valueStack中的数据
有两个主要用途:
- 用于在国际化资源文件中,引用ognl表达式。
- 在struts2配置文件中,引用ognl表达式
1.struts.xml
<result type="stream">
<param name="contentType">${contentType}</param>
</result>
2.在校验文件中使用
${min} ${max}
${minLength} ${maxLength}
3.在国际化文件中使用
在properties文件中
username=${#request.username}
在jsp页面
<s:text name="username">
<result type="stream">
<param name="contentType">${contentType}</param>
</result>
2.在校验文件中使用
${min} ${max}
${minLength} ${maxLength}
3.在国际化文件中使用
在properties文件中
username=${#request.username}
在jsp页面
<s:text name="username">
总结:#就是用于获取数据 %就是用于设置是否是ognl表达式 $就是在配置文件中使用ognl
Struts常用逻辑标签(property、set、iterator、if/elseif/else、url)
property标签
property标签用于输出指定值:
<s:property value="#name" default="a default value" />
* default:可选属性,如果需要输出的属性值为null,则显示该属性的指定值。
* escape:可选属性,指定是否格式化HTML代码。
* value:可选属性,指定需要输出的属性值,如果没有指定该属性值,则默认输出ValueStack栈顶的值。
set标签
set标签用于将某个值放入指定范围。
var:变量的名字,name,id和var表达的含义是一样的,name,id被var替代。
scope:指定变量被放置的范围,该属性可以接收application、session、request、page或action。如果没有设置该属性,则默认放置在值栈的context中。
value:赋给变量的值,如果没有设置该属性,则将ValueStack栈顶的值赋给变量。
iterator标签
Iterator:标签用于对集合进行迭代,这里的集合包含List、set和数组。
value:可选属性,指定被迭代的集合,如果没有设置该属性,则使用ValueStack栈顶的集合。
var:可选属性,引用变量的名称。
status:可选属性,该属性指定迭代时IteratorStatus实例。该实例包含如下几个方法:
int getCount(),返回当前迭代了几个元素
int getIndex(),返回当前迭代元素的索引
boolean isEvent(),返回当前被迭代元素的索引是否是偶数
boolean isOdd(),返回当前被迭代元素的索引是否是奇数
boolean isFirst(),返回当前被迭代元素是否是第一个元素
boolean isLast(),返回当前被迭代元素是否是最后一个元素
st下的属性在:org.apache.struts2.views.jsp.IteratorStatus类下
if/elseif/else标签
if/elseif/else 基本的流程控制:if 标签可单独使用也可以和elseif标签以及else标签一起使用
url标签
url: 该标签用于创建url,可以通过"param"标签提供request参数
value:如果不提供就使用当前的action,使用value后缀必须加.action
action:用来生成url的action,如果没有则使用value
namespace:命名空间
var:引用变量的名称
ognl操作集合
使用ognl操作list和数组
ognl也可以直接创建集合对象,利用下拉列表框
使用ognl操作Map
ognl用多种方式使用#号,每种是不同的.动态map对于动态单选按扭组很有用.
创建map与创建list语法很相似,不同的是map前需要加"#"号.
创建map与创建list语法很相似,不同的是map前需要加"#"号.
操作示例:
代码示例演示ognl如下:
Product
package cn.test.domain;
public class Product {
private String name;
private double price;
private int count;
public String getName() {
return name;
}
public Product() {
super();
}
public Product(String name, double price, int count) {
super();
this.name = name;
this.price = price;
this.count = count;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
User
package cn.test.domain;
public class User {
public User() {
super();
}
public User(String username, String password, int age, String sex) {
super();
this.username = username;
this.password = password;
this.age = age;
this.sex = sex;
}
private String username;
private String password;
private int age;
private String sex;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
<package name="default" namespace="/" extends="struts-default">
<action name="ognlDemo1" class="cn.test.action.OgnlDemo1Action"></action>
<action name="ognlDemo2" class="cn.test.action.OgnlDemo2Action">
<result>/ognl2.jsp</result>
</action>
<action name="ognlDemo3" class="cn.test.action.OgnlDemo3Action">
<result>/ognl3.jsp</result>
</action>
<action name="ognlDemo4" class="cn.test.action.OgnlDemo4Action">
<result>/ognl4.jsp</result>
</action>
<action name="ognlDemo5" class="cn.test.action.OgnlDemo5Action">
<result>/ognl5.jsp</result>
</action>
<action name="ognlDemo6" class="cn.test.action.OgnlDemo6Action">
<result>/ognl6.jsp</result>
</action>
</package>
</struts>
my.properties
OgnlDemo1Action
package cn.test.action;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class OgnlDemo1Action extends ActionSupport {
@Override
public String execute() throws Exception {
// 获取ValueStack
// 1.通过request获取
ValueStack vs = (ValueStack) ServletActionContext.getRequest()
.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
System.out.println(vs);
// 2.通过ActionContext获取
ValueStack vs2 = ActionContext.getContext().getValueStack();
System.out.println(vs2);
return null;
}
}
OgnlDemo2Action
package cn.test.action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class OgnlDemo2Action extends ActionSupport {
@Override
public String execute() throws Exception {
// 向valueStack中存入数据
ValueStack vs=ActionContext.getContext().getValueStack();
vs.set("username", "tom");
vs.push("hello world");
return SUCCESS;
}
}
ognl2.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:使用ognl来获取valueStack数据</title>
</head>
<body>
1.获取栈顶的map
<br>
<s:property value="username" />
<hr>
2.获得栈顶非Map集合数据
<br>
<s:property value="[1].top" />
<hr>
3.获得OgnlContext中数据
<br>
<%
request.setAttribute("rname", "rvalue");
session.setAttribute("sname", "svalue");
application.setAttribute("aname", "avalue");
%>
<s:property value="#request.rname" />
<br>
<s:property value="#session.sname" />
<br>
<s:property value="#application.aname" />
<br>
<s:property value="#attr.sname" /><br>
<s:property value="#parameters.username[0]" />
<s:debug />
</body>
</html>
OgnlDemo3Action
package cn.test.action;
import java.util.ArrayList;
import java.util.List;
import cn.test.domain.User;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class OgnlDemo3Action extends ActionSupport {
@Override
public String execute() throws Exception {
// 向valueStack中存入数据(root)
ValueStack vs = ActionContext.getContext().getValueStack();
List<User> users = new ArrayList<User>();
users.add(new User("tom", "123", 20, "男"));
users.add(new User("jams", "456", 21, "男"));
users.add(new User("fox", "789", 26, "男"));
//
vs.push(users);
vs.set("users", users);
return SUCCESS;
}
}
ognl3.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:使用ognl来获取valueStack中复杂数据</title>
</head>
<body>
1.使用push存储数据存取
<br>
<s:property value="[0].top.users" />
<br>
<s:iterator value="[0].top.users" var="user">
username:<s:property value="#user.username" />
<br>
password:<s:property value="#user.password" />
<hr>
</s:iterator>
<hr>
<s:iterator value="[0].top.users">
username:<s:property value="username" />
<br>
password:<s:property value="password" />
<hr>
</s:iterator>
<hr>
2.使用set存储数据
<hr>
<s:property value="users" />
<br>
<s:iterator value="users" var="user">
username:<s:property value="#user.username" />
<br>
password:<s:property value="#user.password" />
<hr>
</s:iterator>
<hr>
<s:iterator value="users">
username:<s:property value="username" />
<br>
password:<s:property value="password" />
<hr>
</s:iterator>
<s:debug />
</body>
</html>
OgnlDemo4Action
package cn.test.action;
import java.util.ArrayList;
import java.util.List;
import cn.test.domain.User;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.util.ValueStack;
public class OgnlDemo4Action extends ActionSupport implements ModelDriven<User> {
private List<User> users;
private User user = new User("tom", "123", 20, "男");
public User getModel() {
return user;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public String getHello() {
return "hello world";
}
@Override
public String execute() throws Exception {
ValueStack vs = ActionContext.getContext().getValueStack();
users = new ArrayList<User>();
users.add(new User("tom", "123", 20, "男"));
users.add(new User("jams", "456", 21, "男"));
users.add(new User("fox", "789", 26, "男"));
user = new User("fox", "789", 26, "男");
return SUCCESS;
}
}
ognl4.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:使用ognl来获取valueStack中复杂数据</title>
</head>
<body>
<s:property value="hello" />
<hr>
<s:property value="username" />
<s:property value="age" />
<hr>
<s:property value="model.username"/>
<s:property value="model.age"/>
<hr>
<s:iterator value="users" var="u">
<s:property value="#u.username" />
<br>
</s:iterator>
<s:debug />
</body>
</html>
OgnlDemo5Action
package cn.test.action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class OgnlDemo5Action extends ActionSupport {
@Override
public String execute() throws Exception {
ValueStack vs = ActionContext.getContext().getValueStack();
vs.set("username", "张三"); // 向ValueStack压入数据
return SUCCESS;
}
}
ognl5.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:使用el获取ValueStack中数据</title>
</head>
<body>
Ognl获取:<s:property value="username"/><br>
el获取:${username }
<s:debug />
</body>
</html>
OgnlDemo6Action
package cn.test.action;
import java.util.ArrayList;
import java.util.List;
import cn.test.domain.Product;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class OgnlDemo6Action extends ActionSupport {
private List<Product> ps;
public List<Product> getPs() {
return ps;
}
public void setPs(List<Product> ps) {
this.ps = ps;
}
@Override
public String execute() throws Exception {
// 对ps进行赋值
ps = new ArrayList<Product>();
ps.add(new Product("电视机", 1800, 100));
ps.add(new Product("洗衣机", 800, 10));
ps.add(new Product("空调", 3800, 100));
return SUCCESS;
}
}
ognl6.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:进行投影操作</title>
</head>
<body>
<s:property value="ps" />
<br>1.使用iterator进行遍历
<br>
<s:iterator value="ps" var="p">
名称:<s:property value="#p.name" />
<br>
价格:<s:property value="#p.price" />
<br>
数量:<s:property value="#p.count" />
<br>
<hr>
</s:iterator>
<hr>
2.对集合进行投影,只得到指定的属性
<br>
<s:iterator value="ps.{name}" var="pname">
<s:property value="#pname" />
</s:iterator>
<hr>
3.将ps中价格大于1000的商品得到
<br>
<s:iterator value="ps.{?#this.price>1000}" var="p">
名称:<s:property value="#p.name" />
<br>
价格:<s:property value="#p.price" />
<br>
数量:<s:property value="#p.count" />
<br>
</s:iterator>
<hr>
4.将ps中价格大于1000的商品名称得到
<br>
<s:iterator value="ps.{?#this.price>1000}.{name}" var="pname">
<s:property value="#pname" />
<br>
<hr>
</s:iterator>
<s:debug />
</body>
</html>
ognl7.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:进行投影操作</title>
</head>
<body>
1.可以使用#来构建一个Map集合
<br>
<s:iterator value="#{'name':'tom','age':20}" var="entry">
<s:property value="#entry.key" />----<s:property value="#entry.value" />
<br>
</s:iterator>
<hr>
2.可以构建List集合
<br>
<s:iterator value="{'aa','bb','cc'}" var="v">
<s:property value="#v" />
</s:iterator>
<hr>
3.手动创建一个集合,在Struts2中是结合表单标签使用的
<br>
<s:form>
<s:radio list="{'男','女'}" name="sex"></s:radio>
<s:radio list="#{'男':'male','女':'female'}" name="sex"></s:radio>
<s:select list="{'a','b','c'}" name="aa"></s:select>
<s:select list="#{'a':'aaa','b':'bbb','c':'ccc' }" name="aa"></s:select>
</s:form>
<s:debug />
</body>
</html>
ognl8.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:%号的使用</title>
</head>
<body>
<%
request.setAttribute("username", "tom");
%>
<s:property value="#request.username" default="hello" />
<br>
<s:property value="%{#request.username}" />
<br>
<s:property value="%{'#request.username'}" />
<br>
<hr>
<s:textfield name="abc" value="%{#request.username}" />
<s:debug />
</body>
</html>
ognl9.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:$用法</title>
</head>
<body>
<%
request.setAttribute("username", "张三");
%>
在国际化文件中使用:
<br>
<s:i18n name="cn.test.resource.my">
<s:text name="username" />
</s:i18n>
<s:debug />
</body>
</html>
Struts2中的表单标签
概述:
表单标签将在HTML文档里被呈现为一个表单元素
使用表单标签的优点:
- 表单回显
- 对页面进行布局和排版
标签的属性可以被赋值为一个静态的值或一个OGNL表达式,如果在赋值时使用了一个OGNL表达式并把它用%{}括起来,这个表达式将会被求值。
表单标签的共同属性
* 表示该属性只在没有使用theme=simple 主题时才可以使用
form标签
form标签用来呈现HTML语言中的表单元素
默认情况下,form标签将被呈现为一个表格形式的HTML表单。嵌套在form标签里的输入字段将被呈现为一个表格行。每个表格行由两个字段组成,一个对应着行标,一个对应着输入元素。提交按钮将被呈现为一个横跨两列单元格的行。<s:form action="" method="post" namespace="/ui">
textfield, password, hidden 标签
extfield 标签将被呈现为一个输入文本字段, password 标签将被呈现为一个口令字段, hidden 标签将被呈现为一个不可见字段.
password标签扩展自textfield标签,多了一个showPassword属性 该属性是布尔类型,默认值是false,它决定着在表单回显时是否显示输入的密码,true显示密码
submit标签
submit 标签将呈现为一个提交按钮. 根据其 type 属性的值. 这个标签可以提供 3 种呈现效果:
- input: <input type=“submit” value=“提交”…/>
- button: <input type=“button” value=“确定” …/>
- image: <input type=“image” value=“图片” src=“XX.jpg” …/>
reset标签
reset 标签将呈现为一个重置按钮. 根据其 type 属性的值.
这个标签可以提供 2 种呈现效果:
input: <input type=“reset” value=“重置”…/>
button: <input type=“button” value=“重置按键” …/>
这个标签可以提供 2 种呈现效果:
input: <input type=“reset” value=“重置”…/>
button: <input type=“button” value=“重置按键” …/>
label标签
label 标签将呈现一个 HTML 行标元素:
textarea标签
textarea 标签将呈现为一个 HTML 文本域元素
checkboxlist标签
checkboxlist 标签将呈现一组多选框.
checkboxlist标签被映射到一个字符串数组或是一个基本类型的数组。若它提供的多选框一个也没有被选中,相应的属性将被赋值为一个空数组而不是空值。
示例1:
示例2:
radio标签
radio标签将呈现为一组单选按钮,单选按钮的个数与程序员通过该标签的list属性提供的选项的个数相同。
一般的,使用后radio标签实现多选一,对于真假 则该使用checkbox标签
示例如下:
select标签
select标签将呈现一个select元素
示例代码:
示例代码2:
主题
主题:为了让所有的UI标签能够产生同样的视觉效果而归集到一起的一组模板,即风格相近的模板被打包成为一个主题
1、simple:把UI标签翻译成最简单的HTML对应元素,而且会忽视行标属性
2、xhtml:xhtml是默认的主题,这个主题的模板通过使用一个布局表格提供了一种自动化排版机制(默认值)
3、css_xhtml:这个主题里的模板与xhtml主题里的模板很相似,但他们将使用css来进行布局和排版
4、ajax:这个主题类的模板以xhtml主题里的模板为基础,但增加了一些ajax的功能
修改主题:
A、通过UI标签的theme属性(只试用于当前的标签)
<s:textfield name="username" label="用户名" theme="simple"></s:textfield>
B、在一个表单里,若没有给出某个UI标签的theme属性,它将使用这个表单的主题(适用于整个form标签)
<s:form action="" method="post" namespace="/ui" theme="simple">
C、修改struts.properties文件中的struts.ui.theme属性.(适用于整个环境)
<!--设置ui标签的主题 -->
<constant name="struts.ui.theme" value="simple"></constant>
优先级:A>B>C
struts2标签自动回显
<s:textfield name="username"/> <input type="text" name="username" value="zhang">
*当Struts2解析该标签时,获取name属性的值username
*以username为条件,到对象栈中查找PropertyName="username"的属性
*如果找到了,获取该属性的值,该属性的值就是<s:textfield name="username"/> 的值
* 如果找到了,获取该属性的值,该属性的值(是“”)就是<s:textfield name="username"/>的值
* 如果没有找到了,<s:textfield name="username"/>的值=" "
* 如果没有找到了,<s:textfield name="username"/>的值=" "
防止表单重复提交
问题:什么是表单重复提交?
regist.jsp----->RegistServlet
表单重复提交 危害: 刷票、 重复注册、带来服务器访问压力(拒绝服务)
解决方案:
在页面上生成一个令牌(就是一个随机字符串),将其存储到session中,并在表单中携带.
在服务器端,获取数据时,也将令牌获取,将它与session中存储的token对比,没问题,
将session中令牌删除。
struts2中怎样解决表单重复提交:
在struts2中解决表单重复提交,可以使用它定义的一个interceptor。
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
1、定义一个JSP页面,在表单中增加一个隐藏域
regist.jsp----->RegistServlet
表单重复提交 危害: 刷票、 重复注册、带来服务器访问压力(拒绝服务)
解决方案:
在页面上生成一个令牌(就是一个随机字符串),将其存储到session中,并在表单中携带.
在服务器端,获取数据时,也将令牌获取,将它与session中存储的token对比,没问题,
将session中令牌删除。
struts2中怎样解决表单重复提交:
在struts2中解决表单重复提交,可以使用它定义的一个interceptor。
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
1、定义一个JSP页面,在表单中增加一个隐藏域
2、定义struts_token.xml配置文件
问题:token拦截器只拦截save方法
<!-- 在默认栈中增加token拦截器 -->
<interceptors>
<interceptor-stack name="tokenStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="token">
<!-- 配置token拦截器拦截哪些方法 -->
<param name="includeMethods">save</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
error.jsp页面打印错误信息
error.jsp页面如下:使用<s:actionerror/>打印错误信息
<%@ page language="java" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<s:actionerror/>
</body>
</html>
<%@ page language="java" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<s:actionerror/>
</body>
</html>
修改error.jsp页面打印错误信息为中文
1、在与action同级目录新建token.properties资源文件
2、在该文件中增加如下内容
struts.messages.invalid.token=您已经重复提交表单,请刷新后重试
该信息所在位置struts2-core-2.3.3.jar包下orgapachestruts2struts-messages.properties文件
3、在struts.xml文件中加载该资源文件
<constant name="struts.custom.i18n.resources" value="cn.itcast.model.token">
</constant>
2、在该文件中增加如下内容
struts.messages.invalid.token=您已经重复提交表单,请刷新后重试
该信息所在位置struts2-core-2.3.3.jar包下orgapachestruts2struts-messages.properties文件
3、在struts.xml文件中加载该资源文件
<constant name="struts.custom.i18n.resources" value="cn.itcast.model.token">
</constant>
<s: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'
严重: 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'
代码示例如下:
RegisterServlet
package cn.itcast.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RegistServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String token = request.getParameter("token");
String _token = (String) request.getSession().getAttribute("token");
request.getSession().removeAttribute("token");
if (token.equals(_token)) {
System.out.println("将" + username + " 与" + password
+ "存储到数据库中,完成注册");
} else {
response.getWriter().write("不允许表单重复提交");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
register.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<%
//生成一个令牌
String token=UUID.randomUUID().toString();
session.setAttribute("token", token);
%>
<form action="${pageContext.request.contextPath}/regist" method="get">
<input type="hidden" name="token" value="<%=token%>">
username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
Struts2中的防止表单重复刷新如下:
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default">
<action name="regist" class="cn.itcast.action.RegistAction">
<result name="invalid.token">/token.jsp</result>
<interceptor-ref name="token" />
<interceptor-ref name="defaultStack" />
</action>
</package>
</struts>
RegistAction
package cn.itcast.action;
import com.opensymphony.xwork2.ActionSupport;
public class RegistAction extends ActionSupport {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String execute() throws Exception {
System.out.println("将" + username + " 与" + password + "存储到数据库中,完成注册");
return null;
}
}
struts_regist.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/regist.action"
method="get">
<s:token/>
username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br> <input
type="submit" value="注册">
</form>
</body>
</html>
token.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<s:actionerror/>
</body>
</html>
Struts2中json插件的使用
Struts2中怎样处理异步提交(ajax)
原始:
HttpServletResponse response=ServletActionContext.getRequest();
response.getWriter().write("hello "+msg);
respoonse.getWriter().close();
还可以使用Struts2中提供的json插件(步骤如下):
1、导入json插件包
在Struts2的lib包下 struts2-json-plugin-2.3.15.1.jar
2、在struts.xml文件中配置
<package extends="json-default">
设置视图<result type="json">
这样设置后,会将ValueStack栈顶数据变为json。
对于Struts中,也就是会将action对象转为json。
<param name="root">p</param>如果没有设置,可以理解成将整个action都转换为json数据。也就是说在action中提供的getXxx方法,就是json中国的一个属性。
如果设置了root,那么只将指定数据转换成json
怎样设置转换成json的对象中不包含特定的属性?
1、@json(serialize=false) 在getXxx方法上进行设置
2、还可以通过json插件的interceptor完成
<param name="includeProperties">ps[d+].name,ps[d+].price,ps[d+].count</param>
代码示例如下:
Product
package cn.test.domain;
import org.apache.struts2.json.annotations.JSON;
public class Product {
private int id;
private String name;
private double price;
private int count;
public Product() {
super();
}
public Product(int id, String name, double price, int count) {
super();
this.id = id;
this.name = name;
this.price = price;
this.count = count;
}
// @JSON(serialize=false)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
Ajax1Action
package cn.test.action;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Ajax1Action extends ActionSupport {
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String execute() throws Exception {
HttpServletResponse response = ServletActionContext.getResponse();
response.getWriter().write("hello " + msg);
response.getWriter().close();
return null;
}
}
Ajax2Action
package cn.test.action;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import cn.test.domain.Product;
import com.opensymphony.xwork2.ActionSupport;
public class Ajax2Action extends ActionSupport {
private List<Product> ps;
private Product p;
public Product getP() {
return p;
}
public void setP(Product p) {
this.p = p;
}
public List<Product> getPs() {
return ps;
}
public void setPs(List<Product> ps) {
this.ps = ps;
}
@Override
public String execute() throws Exception {
ps = new ArrayList<Product>();
ps.add(new Product(1, "洗衣机", 1800, 10));
ps.add(new Product(2, "电视机", 2800, 20));
ps.add(new Product(3, "缝纫机", 800, 50));
p = new Product(3, "缝纫机", 800, 50);
return SUCCESS;
}
}
my.js
function getXmlHttpRequest() {
var xmlhttp=null;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest(); //针对于现在的浏览器包括IE7以上的版本
} else if(window.ActiveXObject){
// 针对于IE5,IE6版本
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
return xmlhttp;
}
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="default" namespace="/" extends="json-default">
<action name="ajax1" class="cn.test.action.Ajax1Action"></action>
<action name="ajax2" class="cn.test.action.Ajax2Action">
<result type="json">
<param name="includeProperties">ps[d+].name,ps[d+].price,ps[d+].count</param>
</result>
</action>
</package>
</struts>
ajax1.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>第一种Struts2处理异步请求</title>
<script type="text/javascript"
src="${pageContext.request.contextPath}/my.js"></script>
<script type="text/javascript">
function hello() {
//1.得到XMLHttpRequest对象
var xmlhttp = getXmlHttpRequest();
//2.设置回调函数
xmlhttp.onreadystatechange = function() {
if (xmlhttp.status == 200 && xmlhttp.readyState == 4) {
alert(xmlhttp.responseText);
}
};
//3.open
xmlhttp.open("GET", "${pageContext.request.contextPath}/ajax1?msg="
+ document.getElementById("t").value);
//4.send
xmlhttp.send(null);
}
</script>
</head>
<body>
<input type="text" id="t">
<input type="button" value="提交" οnclick="hello();">
</body>
</html>
ajax2.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>第一种Struts2处理异步请求</title>
<script type="text/javascript"
src="${pageContext.request.contextPath}/my.js"></script>
<script type="text/javascript">
function showProduct() {
//1.得到XMLHttpRequest对象
var xmlhttp = getXmlHttpRequest();
//2.设置回调函数
xmlhttp.onreadystatechange = function() {
if (xmlhttp.status == 200 && xmlhttp.readyState == 4) {
alert(xmlhttp.responseText);
// var jsonObj = eval("(" + xmlhttp.responseText + ")");
}
};
//3.open
xmlhttp.open("GET", "${pageContext.request.contextPath}/ajax2?msg="
+ document.getElementById("t").value);
//4.send
xmlhttp.send(null);
}
</script>
</head>
<body>
<input type="text" id="t">
<input type="button" value="提交" οnclick="showProduct();">
</body>
</html>
运行结果如下:
最后
以上就是英俊短靴为你收集整理的JAVAWEB开发之Struts2详解(四)——ognl与valueStack(重点)、Struts常用标签、防止表单重复提交、Struts2中内置json插件...的全部内容,希望文章能够帮你解决JAVAWEB开发之Struts2详解(四)——ognl与valueStack(重点)、Struts常用标签、防止表单重复提交、Struts2中内置json插件...所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复