非本人总结的笔记,抄点笔记复习复习。感谢传智博客和黑马程序猿
记笔记啊记笔记
Ognl的简介
Ognl是独立的项目,不是Struts2的一部分,只是经常和Struts2一起使用,获取值栈的数据。如果想要使用Ognl首先导入包。
El表达式,在jsp页面中获取域对象里面的数据,显示到页面中。
Ognl表达式比El表达式强大
- 支持对象方法调用,如xxx.xxx();
- 支持类静态方法调用和值访问,表达式的格式:@[类全名(包括包路径)]@[方法名|值名]。例如:@java.lang.String@format('foo%s', 'bar')或@tutorial.MyConstant@APP_NAME。设置 struts.ognl.allowStaticMethodAccess=true
- 访问OGNL上下文(OGNL content)和ActionContent;(操作值栈数据)
- 支持赋值操作和表达式串联
- 操作值栈集合对象
Ognl入门案例
使用ognl和Struts2标签一起做下面的操作
第一步 创建Ognl.jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!--引入struts2标签-->
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'helloOgnl.jsp' starting page</title>
</head>
<body>
<!-- 调用对象的方法
计算字符串长度
String str = "aa";
str.length();
-->
<s:property value="'itcast'.length()"/>
<hr/>
<%--调用静态方法 格式:@[类全名(包括包路径)]@[方法名] --%>
<s:property value="@java.lang.Math@random()"/>
</body>
</html>
第二步 配置struts.xml调用静态方法,必须开启常量值
<!--设置OGNL静态方法常量-->
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
值栈
什么是值栈
值栈是数据的中转战,类似于域对象,之前操作,可以向域对象里面设置值,可以从域对象里面获取值。向域对象设置值,从域对象获取值。获取值栈的数据,可以通过struts2标签和ognl表达式获取。
每次访问action的时候,都会创建action实例,每个action实例里面只有一个值栈对象(valueStack对象)
在action实例中,值栈是如何存在的?
Struts2框架将把ValueStack对象保存在名为"struts.valueStack",的请求属性中,request中Request.setAttribute("struts.valueStack")
获取值栈对象方法
第一种
从request域对象里面使用getAttribute获取,名称为struts.valueStack
第二种
得到ActionContext,使用ActionContext里面的方法得到
案例演示
第一步 创建Action
package cn.itcast.valuestack;
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 StackDemo1 extends ActionSupport {
private String name;
@Override
public String execute() throws Exception {
//第一种 从request域对象里面使用getAttribute获取,名称struts.valueStack
//第一种方式 从request域里面获取
HttpServletRequest request = ServletActionContext.getRequest();
ValueStack stack1 = (ValueStack) request.getAttribute("struts.valueStack");
//第二种 得到ActionContext,使用ActionContext里面的方法得到
//第二种方式 使用ActionContext获取
ActionContext context = ActionContext.getContext();
ValueStack stack2 = context.getValueStack();
//每个action实例中只有一个值栈对象
//值是 true,表示是一个对象
System.out.println(stack1 == stack2);
return SUCCESS;
}
}
第二步 配置Action struts.xml
<package name="valuedemo" extends="struts-default" namespace="/">
<action name="stack1" class="cn.itcast.valuestack.StackDemo1">
<result>/index.jsp</result>
</action>
</package>
值栈的内部结构
值栈包含两部分内容
- Root:是list集合,Struts2里面默认操作数据都在root里面
- Context:是map集合
在action里面把数据放到域对象里面,这个数据存到context里面,context里面的Map结构,key名称为request、session、Application、attr、parameters
值栈向值栈中存放数据
第一种 获取值栈对象,调用值栈对象里面的方法的set方法
第二种 获取值栈对象,调用值栈对象的方法push方法
第三种 在action中创建对象,生成set和get方法
案例演示
第一步 创建Action
package cn.itcast.valuestack;
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 StackDemo2 extends ActionSupport {
//第三种
//创建对象
private User user = new User();
//生成对象的get和set方法
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
//第一种 获取值栈对象,调用值栈对象里面的方法set方法
//获取值栈对象
ValueStack stack = ActionContext.getContext().getValueStack();
//设置值
stack.set("itcast", "东方不败");
//第二种 获取值栈对象,调用值栈对象的方法push方法
stack.push("岳不群");
//第三种 在action中创建对象,生成get和set方法
//演示效果: 向值栈中放对象,在页面中获取对象值
//栈特点:后进先出
//向值栈的user对象里面设置值
user.setUsername("lucy");
user.setPassword("250");
return SUCCESS;
}
}
第二步 配置struts.xml
<action name="stack2" class="cn.itcast.valuestack.StackDemo2">
<result>/stack/demo2.jsp</result>
</action>
第三步 创建页面 demo.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'demo2.jsp' starting page</title>
</head>
<body>
<!-- 获取set方法设置到值栈数据 -->
<%--
<s:property value="itcast"/>
<!-- 获取push方法设置到值栈数据 -->
<hr/>
<s:property value="[0].top"/> <!--获取栈顶数据写法-->
--%>
<!-- 获取值栈的user对象中的值 -->
<%--
<s:property value="user.username"/>
--
<s:property value="user.password"/>
--%>
${itcast }<%--EL表达式直接获取数据-->
</body>
</html>
第四步 创建User类
package cn.itcast.valuestack;
public class User {
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;
}
}
从值栈中获取值
第一种 获取值栈的root里面的值:对象和list集合
获取值栈的root的对象的值
<s:property value="user.username"/>
<s:property value="user.password"/>
获取值栈的root里面list集合内容
第一步 创建action
package cn.itcast.valuestack;
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
/**
* 向值栈放数据的方式
* @author asus
*
*/
public class StackDemo3 extends ActionSupport {
// 获取root的list集合的值
//创建list集合
private List<User> list = new ArrayList<User>();
//生成list集合的get和set方法
public List<User> getList() {
return list;
}
public void setList(List<User> list) {
this.list = list;
}
@Override
public String execute() throws Exception {
//向list集合中设置值
//创建多个user对象,放到list集合
User u1 = new User();
u1.setUsername("岳不群");
u1.setPassword("119");
User u2 = new User();
u2.setUsername("林平之");
u2.setPassword("999");
list.add(u1);
list.add(u2);
return SUCCESS;
}
}
第二步 配合struts.xml
<action name="stack3" class="cn.itcast.valuestack.StackDemo3">
<result>/stack/demo3.jsp</result>
</action>
第三步 创建jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'demo2.jsp' starting page</title>
</head>
<body>
<!--在jsp中获取值栈的list集合内容-->
<!-- 获取值栈中的list集合内容 -->
<s:property value="list[0].username"/>
--
<s:property value="list[0].password"/>
<br/>
<s:property value="list[1].username"/>
--
<s:property value="list[1].password"/>
</body>
</html>
第二种 获取值栈的context里面的值:对象和list集合
获取值栈的context里面的对象
第一步 创建action
package cn.itcast.valuestack;
import java.util.ArrayList;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* 向context里面放对象
*/
public class StackDemo4 extends ActionSupport {
@Override
public String execute() throws Exception {
//创建对象
User user = new User();
user.setUsername("mary");
user.setPassword("520");
//把对象放到request域对象里面先得到在放到context中
ServletActionContext.getRequest().setAttribute("userrequest", user);
return SUCCESS;
}
}
第二步 配置struts.xml
<action name="stack4" class="cn.itcast.valuestack.StackDemo4">
<result>/stack/demo4.jsp</result>
</action>
第三步 创建jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'demo2.jsp' starting page</title>
</head>
<body>
<!-- 在jsp中获取值栈的context里面的对象的值
获取context里面值,首先 #
request :是context里面key的名称
#request.userrequest : 获取request域里面名称是userrequest的对象
#request.userrequest.username: 获取域对象里面对象的属性值
-->
<s:property value="#request.userrequest.username"/>
--
<s:property value="#request.userrequest.password"/>
</body>
</html>
获取值栈的context里面的list集合
第一步 创建action
package cn.itcast.valuestack;
import java.util.ArrayList;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* 向值栈放数据的方式
*/
public class StackDemo5 extends ActionSupport {
@Override
public String execute() throws Exception {
//向context里面放list集合
//创建对象
User u1 = new User();
u1.setUsername("岳不群");
u1.setPassword("119");
User u2 = new User();
u2.setUsername("林平之");
u2.setPassword("999");
//创建list集合
List<User> list = new ArrayList<User>();
list.add(u1);
list.add(u2);
//放到域对象
ServletActionContext.getRequest().setAttribute("userlist", list);
return SUCCESS;
}
}
第二步 配置struts.xml
<action name="stack5" class="cn.itcast.valuestack.StackDemo5">
<result>/stack/demo5.jsp</result>
</action>
第三步 创建jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'demo2.jsp' starting page</title>
</head>
<body>
<!-- 获取值栈context中的list集合值 -->
<s:property value="#request.userlist[0].username"/>
--
<s:property value="#request.userlist[0].password"/>
<hr/>
<s:property value="#request.userlist[1].username"/>
--
<s:property value="#request.userlist[1].password"/>
</body>
</html>
EL表达式为什么可以获取值栈数据
实现原理:首先增强request里面的getAttribute方法,而getAttribute方法获取域对象里面的值
增强逻辑:首先调用getAttribute获取域对象里面的值,如果获取了值,直接返回;如果获取不到域对象的值,获取到值栈对象,从值栈中把值取出来,赋值给域对象中的参数数据。所以,通过EL表达式就可以获取值栈数据。
Ognl中#的使用
用来获取值栈里面context里面的数据
<!--获取值栈context里面的数据-->
<s:property value="#request.userrequest.username"/>
<s:property value="#request.userrequest.password"/>
Ognl表达式的%的使用
一般使用在Struts2的表单标签里面
演示效果:
- 编写action,向request里面设置值
- 到jsp中获取request域里面设置的值
- 在jsp中把值显示到Struts2表单中
第一步 创建Action
package cn.itcast.ognl;
import java.util.ArrayList;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import cn.itcast.valuestack.User;
import com.opensymphony.xwork2.ActionSupport;
/**
* 编写action,向request域里面设置值
*/
public class OgnlDemo2 extends ActionSupport {
@Override
public String execute() throws Exception {
//向request域里面设置值
ServletActionContext.getRequest().
setAttribute("username", "requestValueOgnl");
return SUCCESS;
}
}
第二步 配置struts.xml
<action name="ognl2" class="cn.itcast.ognl.OgnlDemo2">
<result>/ognl/ognl2.jsp</result>
</action>
第三步 创建jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'ognl1.jsp' starting page</title>
</head>
<body>
<!--显示到struts2的表单标签里面
在struts2的表单标签里面,使用ognl显示数据,
不能直接写ognl表达式,因为作为普通字符串显示,
要让是一个ognl,使用%{ognl表达式}
<s:textfield> 类似于 <input type="text" value=""/>
-->
用户名: <s:textfield value="%{#request.username}"></s:textfield>
</body>
</html>
Ognl表达式的$的使用
在国际化资源文件中使用
在properties文件中msg=欢迎您 ${#request.username}
在页面
<s:i18n name="massages">
<s:text name="msg"></s:text>
</s:i18n>
<s:text name="namekey"></s:text>
Struts2座文件下载用
<result name="success" type="stream">
<param name="contentDisposition">attachment;file=${filename}</param>
<param name="inputstream">${inputstream}</param>
</result>
总结值栈和ognl表达式
1、ognl
ognl不是Struts2表达式的一部分,是独立的项目,经常和Struts2的标签一起使用,获取值栈
2、值栈
类似域对象,数据的中转站,存值和取值
每个Action对象里面都只有一个值栈对象,在值栈request域里面
3、获取值栈对象有两种
- 从request域对象里面获取
- ActionContext类方法获取
4、放数据到值栈有三种
- set方法
- push方法
- 创建对象,生成get和set方法
5、从值栈去数据
<s:property value="ognl表达式"></s:property>
获取context里面数据,ognl之前写#
6、El表达式获取值栈数据
7、 %和$的使用
8、值栈内部结构
Root是list集合;Context是Map集合;Struts2里面默认操作数据都在Root里面,把数据放到域对象里面存到context里面
Struts2的标签库
通用标签库
<!-- 和ognl表达式使用,获取值栈数据 -->
<s:property value="ognl表达式"></s:property>
<!-- 遍历值栈集合 -->
<s:iterator value="" var=""></s:iterator>
<!-- 获取action里面使用addActionError设置的值 本身不是错误业务上的操作 如文件大小-->
<s:actionerror></s:actionerror>
<!-- 获取action里面使用addFiledError设置的值 真正的错误 -->
<s:fielderror></s:fielderror>
<!-- 获取国际化资源文件内容 -->
<s:text name=""></s:text>
Struts2表单标签UI标签库
介绍
Html中表单标签
Form :属性 action、method、enctype
在form里面有很多的输入项
大部分在input里面 type=””
text : 普通输入项
password :密码输入项
radio :单选输入项
checkbox:复选框
file: 文件上传项
hidden:隐藏项
button:普通按钮
submit: 提交按钮
reset: 重置按钮
select : 下拉输入框
textarea:文本域
struts2的表单标签对应的输入项,没有文件上传输入项
struts2表单标签实现
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'struts2tag.jsp' starting page</title>
</head>
<body>
<!--<input type="radio" name="sex" value="女"/>女
<input type="radio" name="sex" value="nan"/>男 -->
<!-- 显示内容和value值一样
显示内容和value不一样
-->
<!-- <input type="checkbox" value="足球"/>足球 -->
<select>
<option value="足球">足球</option>
</select>
<hr/>
<s:form action="" method="">
<s:textfield name="username" label="用户名"></s:textfield>
<s:password name="password" label="密码"></s:password>
<!-- 性别 -->
<!--显示内容和value值一样 在list属性里面 构造一个list集合
显示内容和value不一样 在list属性里面 构造一个map集合
-->
<!-- <s:radio list="{'女','男'}" name="sex1" label="性别"></s:radio> -->
<s:radio list="#{'nv':'女','nan':'男'}" name="sex2" label="性别"></s:radio>
<s:checkboxlist list="{'足球','篮球','乒乓球'}" name="love" label="爱好">
</s:checkboxlist>
<s:select list="{'博士后','博士前','幼儿园'}" name="college" label="学历"></s:select>
<s:textarea cols="2" rows="2" name="resume" label="简历"></s:textarea>
<s:hidden name="hid" value="hidvalue" label="隐藏"></s:hidden>
<s:submit value="提交"></s:submit>
<s:reset value="重置"></s:reset>
</s:form>
</body>
</html>
Struts2的表单标签数据回显
现象: 只是校验其中的一个输入项是否为空,但是把其他的输入项也清空了
演示一:使用普通的html标签,提交表单数据到action,进行数据的校验
创建页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'tagCommon.jsp' starting page</title>
</head>
<body>
<s:fielderror/> <%--真正的错误--%>
<form action="${pageContext.request.contextPath }/tag1.action" method="post">
username:<input type="text" name="username"/>
<br/>
password:<input type="text" name="password"/>
<br/>
address:<input type="text" name="address"/>
<br/>
<input type="submit"/>
</form>
</body>
</html>
创建Action
package cn.itcast.tag;
import com.opensymphony.xwork2.ActionSupport;
public class Tag1Action extends ActionSupport {
//属性封装方法
private String username;
private String password;
private String address;
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 String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
return SUCCESS;
}
}
配置struts.xml
<action name="tag1" class="cn.itcast.tag.Tag1Action">
<result name="success">/index.jsp</result>
<result name="input">/tag/tagstruts2.jsp</result>
</action>
通过xml做配置校验 Tag1Action-validation.xml放到action的包下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<message>用户名不能为空xml</message>
</field-validator>
</field>
</validators>
演示二:使用struts2的表单标签,提交数据到action,进行数据的校验
创建页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'tagCommon.jsp' starting page</title>
</head>
<body> <%--action直接写action的名字就行 不要写绝对路径--%>
<s:form action="tag1.action" method="post">
<s:textfield name="username" label="username"></s:textfield>
<%--写上showPassword="true"密码才会回显--%>
<s:password name="password" label="password"showPassword="true"></s:password>
<s:textfield name="address" label="address"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
</body>
</html>
创建Action
package cn.itcast.tag;
import com.opensymphony.xwork2.ActionSupport;
public class Tag1Action extends ActionSupport {
//属性封装方法
private String username;
private String password;
private String address;
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 String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
return SUCCESS;
}
}
配置struts.xml
<action name="tag1" class="cn.itcast.tag.Tag1Action">
<result name="success">/index.jsp</result>
<result name="input">/tag/tagstruts2.jsp</result>
</action>
通过xml做配置校验 Tag1Action-validation.xml放到action的包下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<message>用户名不能为空xml</message>
</field-validator>
</field>
</validators>
防止表单重复提交
防止表单重复提交原理:
使用令牌机制 javaweb原理
第一步 在表单里面做几件事情
(1)在表单页面中生成随机的唯一的值 uuid
<%
Stirng uuid =UUID.randomUUID().toString()
%>
(2)把生成的唯一的值首先放到页面的隐藏项里面 hidden
<input type=”hidden” name=”id” value=”uuid”/>
(3)还要把生成的唯一的值再放到session域里面
session.setAttribute("id",uuid);
第二步 提交表单到action,
(1) 获取隐藏项里面的uuid值
(2) 获取session域对象里面的uuid值
(3) 比较这两个值是否相同,如果相同,获取表单其他值进行操作
(4) 操作完成之后,把session域里面的值清空
(5) 如果这两个值,不相同,不进行操作
使用struts2防止表单重复提交
使用struts2里面拦截器实现,token,这个token拦截器不是默认执行的拦截器
创建页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%--引入struts标签--%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'form1.jsp' starting page</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/formSubmit.action" method="post">
<%--使用struts标签token--%>
<s:token/>
<input type="submit"/>
</form>
</body>
</html>
创建Action
package cn.itcast.form;
import com.opensymphony.xwork2.ActionSupport;
public class FormSubmitAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("ACTION执行了.............");
return SUCCESS;
}
}
使用token拦截器 配置action
token拦截器不是默认的所以要声明拦截器 struts.xml
----------------------配置位置在struts.xml中<package的最上面----------------
<%--声明token拦截器--%>
<interceptors>
<interceptor-stack name="mytoken">
<interceptor-ref name="token"></interceptor-ref>
<%--因为token不是默认的所以要声明默认的否则默认的会失效--%>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
--------------------配置位置在struts.xml中<package的任意位置----------------
<%--配置action--%>
<action name="formSubmit" class="cn.itcast.form.FormSubmitAction">
<interceptor-ref name="mytoken"></interceptor-ref>
<result name="success">/index.jsp</result>
<%--使用token拦截器之后返回的视图不是input而是invalid.token--%>
<result name="invalid.token">/form/form1.jsp</result>
</action>
网友评论