非本人总结的笔记,抄点笔记复习复习。感谢传智博客和黑马程序猿
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"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
My JSP 'helloOgnl.jsp' starting page
<%--调用静态方法 格式:@[类全名(包括包路径)]@[方法名] --%>
第二步 配置struts.xml调用静态方法,必须开启常量值
值栈
什么是值栈
值栈是数据的中转战,类似于域对象,之前操作,可以向域对象里面设置值,可以从域对象里面获取值。向域对象设置值,从域对象获取值。获取值栈的数据,可以通过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
/index.jsp
值栈的内部结构
值栈包含两部分内容
- 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
/stack/demo2.jsp
第三步 创建页面 demo.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
My JSP 'demo2.jsp' starting page
<%--
--%>
<%--
--
--%>
${itcast }<%--EL表达式直接获取数据-->
第四步 创建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的对象的值
获取值栈的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 list = new ArrayList();
//生成list集合的get和set方法
public List getList() {
return list;
}
public void setList(List 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
/stack/demo3.jsp
第三步 创建jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
My JSP 'demo2.jsp' starting page
--
--
第二种 获取值栈的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
/stack/demo4.jsp
第三步 创建jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
My JSP 'demo2.jsp' starting page
--
获取值栈的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 list = new ArrayList();
list.add(u1);
list.add(u2);
//放到域对象
ServletActionContext.getRequest().setAttribute("userlist", list);
return SUCCESS;
}
}
第二步 配置struts.xml
/stack/demo5.jsp
第三步 创建jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
My JSP 'demo2.jsp' starting page
--
--
EL表达式为什么可以获取值栈数据
实现原理:首先增强request里面的getAttribute方法,而getAttribute方法获取域对象里面的值
增强逻辑:首先调用getAttribute获取域对象里面的值,如果获取了值,直接返回;如果获取不到域对象的值,获取到值栈对象,从值栈中把值取出来,赋值给域对象中的参数数据。所以,通过EL表达式就可以获取值栈数据。
Ognl中#的使用
用来获取值栈里面context里面的数据
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
/ognl/ognl2.jsp
第三步 创建jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
My JSP 'ognl1.jsp' starting page
用户名:
Ognl表达式的$的使用
在国际化资源文件中使用
在properties文件中msg=欢迎您 ${#request.username}
在页面
Struts2座文件下载用
attachment;file=${filename}
${inputstream}
总结值栈和ognl表达式
1、ognl
ognl不是Struts2表达式的一部分,是独立的项目,经常和Struts2的标签一起使用,获取值栈
2、值栈
类似域对象,数据的中转站,存值和取值
每个Action对象里面都只有一个值栈对象,在值栈request域里面
3、获取值栈对象有两种
- 从request域对象里面获取
- ActionContext类方法获取
4、放数据到值栈有三种
- set方法
- push方法
- 创建对象,生成get和set方法
5、从值栈去数据
获取context里面数据,ognl之前写#
6、El表达式获取值栈数据
7、 %和$的使用
8、值栈内部结构
Root是list集合;Context是Map集合;Struts2里面默认操作数据都在Root里面,把数据放到域对象里面存到context里面
Struts2的标签库
通用标签库
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"%>
My JSP 'struts2tag.jsp' starting page
Struts2的表单标签数据回显
现象: 只是校验其中的一个输入项是否为空,但是把其他的输入项也清空了
演示一:使用普通的html标签,提交表单数据到action,进行数据的校验
创建页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
My JSP 'tagCommon.jsp' starting page
<%--真正的错误--%>
创建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
/index.jsp
/tag/tagstruts2.jsp
通过xml做配置校验 Tag1Action-validation.xml放到action的包下
用户名不能为空xml
演示二:使用struts2的表单标签,提交数据到action,进行数据的校验
创建页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
My JSP 'tagCommon.jsp' starting page
<%--action直接写action的名字就行 不要写绝对路径--%>
<%--写上showPassword="true"密码才会回显--%>
创建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
/index.jsp
/tag/tagstruts2.jsp
通过xml做配置校验 Tag1Action-validation.xml放到action的包下
用户名不能为空xml
防止表单重复提交
防止表单重复提交原理:
使用令牌机制 javaweb原理
第一步 在表单里面做几件事情
(1)在表单页面中生成随机的唯一的值 uuid
<%
Stirng uuid =UUID.randomUUID().toString()
%>
(2)把生成的唯一的值首先放到页面的隐藏项里面 hidden
(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"%>
My JSP 'form1.jsp' starting page
创建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中
<%--因为token不是默认的所以要声明默认的否则默认的会失效--%>
--------------------配置位置在struts.xml中
/index.jsp
<%--使用token拦截器之后返回的视图不是input而是invalid.token--%>
/form/form1.jsp