Struts2框架–学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

Struts2框架–学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

一、OGNL概述:OGNL是一种表达式

(1)在struts2中操作值栈数据。

(2)一般把ognl在struts2中操作,和struts2标签一起使用操作值栈。

(3)ognl不是strut2的一部分,是单独的项目,经常和struts2一起使用。

(4)使用ognl的时候首先要导入jar包。

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!-- 引入struts2标签 -->
<%@ taglib prefix="s"  uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>ognl案例</title>
</head>
<body>
	<!-- ognl+struts2实现计算字符串长度 -->
	<!-- value值:ognl表达式 -->
	<s:property value="'这是一个字符串'.length()"/>
</body>
</html>

 

 

二、值栈:

1、概述:

(1)值栈是struts2提供的一种存储机制,类似于域对象,可以存值和取值。

(2)Servlet和Action的区别:

Servlet:默认在第一次访问时创建,只创建一次,单实例对象。

Action:访问时候创建,每次访问action的时候,都会创建action对象,创建多次,多实例对象。

(3)值栈存储位置:

在每个action对象里面都会有一个值栈对象(只有一个)

 

2、获取值栈对象:

(1)获取值栈对象有多种方式,常用方式是:使用ActionContext类里面的方法得到值栈对象。

(2)每个action对象中只有一个值栈对象。

public class StackDemoAction extends ActionSupport {
	public String execute(){
		//1.获取ActionContext类的对象
		ActionContext context=ActionContext.getContext();
		//调用方法获取值栈对象:
		ValueStack stack1=context.getValueStack();
		ValueStack stack2=context.getValueStack();
		
		System.out.println(stack1==stack2);//输入结果为true
		return NONE;
	}
}

 

3、值栈内部结构:

(1)值栈一般分为两部分:

第一部分是root,结构是list集合,一般操作都是root里面的数据。

第二部分是context,结构是map集合。

(2)struts2里面标签<s:debug>,使用这个标签可以查看值栈结构和存储值:

访问action,执行action的方法有返回值,配置返回到jsp页面中,在jsp页面中使用这个标签:

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

(3)action对象里面有值栈对象,值栈对象里面有action引用。

在action没有做任何操作,栈顶元素默认是action的引用。

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

 

4、向值栈放数据的三种方式:

(1)第一种:Set方法:HashMap类型(重新分配空间)

//向值栈放数据的三种方式:
public class SaveStackDemoAction extends ActionSupport {

	public String execute(){
		//获取ActionContext对象,调用方法获取值栈对象
		ActionContext context=ActionContext.getContext();
		ValueStack stack=context.getValueStack();
	
		//第一种:set方法:
		stack.set("stackobject", "第一个对象");
		
		return "test";			
	}
}

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

(2)第二种:Push方法:String类型(重新分配空间):

//向值栈放数据的三种方式:
public class SaveStackDemoAction extends ActionSupport {

	public String execute(){
		//获取ActionContext对象,调用方法获取值栈对象
		ActionContext context=ActionContext.getContext();
		ValueStack stack=context.getValueStack();
	
		//第二种:push方法:
		stack.push("第二个对象");
		
		return "test";			
	}
}

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

(3)第三种(常用):在action中定义常量,生成变量的get方法。(不用重新分配空间)

//向值栈放数据的三种方式:
public class SaveStackDemoAction2 extends ActionSupport {
	//第三种方式:
	//在action中定义变量,生成变量的get方法
	private String object;
	public String getObject() {
		return object;
	}

	public String execute(){
		object="第三个对象";
		return "test";			
	}
}

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

 

5、向值栈放对象:

实现步骤:

(1)第一步:在action中定义对象变量;

(2)第二步:生成变量的get方法;

(3)第三步:在执行的方法里面,给对象设置值;

//向值栈放对象:
public class SaveStackDemoAction3 extends ActionSupport {

	//在action中定义对象变量,生成对象的get方法
	private User user;
	public User getUser() {
		return user;
	}
	
	public String execute(){	
		//在执行的方法里面,给对象设置值。
		user=new User();
		user.setUid(1);
		user.setUsername("张三");
		user.setPassword("123456");
		user.setAddress("中国");
		
		return "test";			
	}
}

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

 

6、向值栈放List集合:

实现步骤:

(1)第一步:在action中,定义list集合;

(2)第二步:生成list集合的get方法;

(3)第三步:在执行的方法里面,给集合设置值。

//向值栈放list集合:
public class SaveStackDemoAction4 extends ActionSupport {

	//在action中定义list集合,生成对象的get方法
	private List<User> list=new ArrayList<User>();
	public List<User> getList() {
		return list;
	}
	
	public String execute(){	
		//在执行的方法里面,给list集合设置值。
		User user1=new User();
		user1.setUsername("张三");
		user1.setPassword("123456");
		user1.setAddress("中国");
		
		User user2=new User();
		user2.setUsername("李四");
		user2.setPassword("654321");
		user2.setAddress("北京");	
		list.add(user1);
		list.add(user2);
		
		return "test";			
	}
}

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

 

7、从值栈中获取数据:

使用struts2的标签+ognl表达式获取值栈数据:

<s:property value=”ognl表达式”/>

例子:获取字符串;获取对象;获取list集合;取出set方法存取的数据;取出push方法存取的数据;

//在action中存放数据:
public class ReadStackDemoAction extends ActionSupport {

	//设置字符串
	private String username;
	public String getUsername() {
		return username;
	}	
	//设置对象
	private User user=new User();
	public User getUser() {
		return user;
	}	
	//设置list集合
	private List<User> list=new ArrayList<User>();
	public List<User> getList() {
		return list;
	}

	public String execute(){	
		username="这是一个字符串";
		
		user.setUsername("这是一个对象");
		user.setPassword("123456");
		user.setAddress("china");
		
		User user1=new User();
		User user2=new User();
		user1.setUsername("张三");
		user1.setPassword("123456");
		user1.setAddress("china");
		user2.setUsername("李四");
		user2.setPassword("123456");
		user2.setAddress("English");
		list.add(user1);
		list.add(user2);
			
		ActionContext context=ActionContext.getContext();
		ValueStack stack=context.getValueStack();
		
		//使用set方法存数据:
		stack.set("set", "set方法存的数据");
		//使用push方法存数据:
		stack.push("push方法存的数据");
	
		return "test";
	}
}
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="s"  uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>案例</title>
</head>
<body>
	<s:debug></s:debug>
	
	<!-- 在jsp中获取字符串 -->
	获取值栈的字符串:<br/>
	<s:property value="username"/><br/>
	<br/>
	
	获取值栈的对象:<br/>
	<s:property value="user.name"/>
	<s:property value="user.password"/>
	<s:property value="user.address"/><br/><br/>
	
	获取值栈的list集合:<br/>
	第一种方式:<br/>
	<s:property value="list[0].name"/>
	<s:property value="list[0].password"/>
	<s:property value="list[0].address"/><br/>
	<s:property value="list[1].name"/>
	<s:property value="list[1].password"/>
	<s:property value="list[1].address"/><br/><br/>
	第二种方式(常用):<br/>
	<!-- 使用s:iterator:遍历值栈的list集合 -->
	<s:iterator value="list">
		<s:property value="name"/>
		<s:property value="password"/>
		<s:property value="address"/><br/>
	</s:iterator>
	<br/>
	第三种方式(最常用):<br/>
	<s:iterator value="list" var="user">
	<!-- 遍历值栈list集合,得到每个user对象
		 机制:把每次遍历出来的user对象放到context中
		 获取context里面数据的特点:写ognl表达式
		 使用特殊符号# -->
		<s:property value="#user.name"/>
		<s:property value="#user.password"/>
		<s:property value="#user.address"/><br/>
	</s:iterator><br/>
	
	<!-- 取出set方法存取的数据,根据名称获取值 -->
	<s:property value="set"/>
	<br/><br/>
	<!-- 取出push方法存取的数据-->
	<!-- (1)使用push方法设置值,没有名称,只有设置的值
		  (2)向值栈放数据,会把向值栈放的数据存到数组里面,
		  	   数值名称为top,根据数据获取值 -->
	<s:property value="[0].top"/>
	
</body>
</html>

 

8、EL表达式怎么获取值栈数据:

(1)EL表达式获取域对象值;

(2)向域对象里面放值使用setAttribute方法,获取值使用getAttribute方法。

(3)底层增强request对象里面的getAttribute方法:

–如果从request域获取值,如果获取到,则直接返回;

–如果从request域获取不到值,到值域中把值获取出来,把值放到域对象里面。

9、#和%的使用:

(1)#的使用:获取context里面的数据;

(2)%的使用:在struts2标签里面使用ognl表达式,如果直接在struts2表单标签里面使用ognl表达式会发生不识别,只有在%之后才会识别。

 

 

三、拦截器:

1、struts2拦截器的介绍:

(1)struts2是框架,封装了很多的功能,struts2里面封装的功能很多都是在拦截器里面。

(2)struts2有很多拦截器,不是每次这些拦截器都执行,每次执行默认的拦截器

(3)默认拦截器的位置:struts2-core的jar包下面的struts-default.xml文件:

以下是默认的拦截器:

            <interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="scopedModelDriven"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="datetime"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params"/>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="debugging"/>
                <interceptor-ref name="deprecation"/>
            </interceptor-stack>

(4)拦截器在action对象创建之后,action的方法执行之前执行。

(5)拦截器底层使用两个原理:

第一个:aop思想:AOP是面向切面的编程,不改变源代码,就可以增加功能;

第二个:责任链模式;

(6)aop思想和责任链模式如何应用到拦截器里面?

①拦截器在action对象创建之后,action的方法执行之前执行。

②在action方法执行之前执行默认拦截器,执行过程使用aop思想,在action没有直接调用拦截器的方法,使用配置文件方式进行操作。

③ 在执行拦截器的时候,会执行很多的拦截器,这个过程使用到责任链模式:

–假如执行三个拦截器,执行拦截器1,执行拦截器1之后做放行操作,执行拦截器2,执行拦截器2之后做放行操作,执行拦截器3,执行拦截器3之后做放行,执行action方法。

 

2、拦截器的执行过程:

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

3、过滤器和拦截器的区别:

(1)过滤器:理论上可以拦截任意内容,比如html,jsp,servlet,图片路径。

(2)拦截器:拦截器值拦截action。

4、servlet和action的区别:

(1)servlet:第一次访问的时候创建,创建一次,单实例对象。

(2)action:每次访问的时候都会创建,多实例对象。

 

5、自定义拦截器:

(1)首先,我们查看源代码看拦截器的结构:

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

(2)在接口里面有三个方法:

void init();//初始化操作
void destroy();//销毁操作
String intercept(ActionInvocation invocation);//拦截逻辑的操作

(3)在实际开发中,建议使用另外一种方式开发:

①创建类,继承MethodFilterInterceptor类实现;

②重写里面的doIntercept方法,拦截器逻辑写在方法体里面。

 

6、举例:登陆拦截器:

(1)判断是否登陆:判断session里面是否有名称是username的值;

(2)拦截器实现过程:

第一步:创建类,继承MethodFilterInterceptor类;

第二步:重写MethodFilterInceptor类里面的方法,方法里面写拦截器逻辑;

//创建拦截器类:继承MethodFilterInterceptor类
public class myIntercept extends MethodFilterInterceptor {

	//重写里面的doIntercept方法,拦截器逻辑写在方法体里面
	@Override
	protected String doIntercept(ActionInvocation arg0) throws Exception {
		//取得username的值
		HttpServletRequest request=ServletActionContext.getRequest();
		Object obj=request.getSession().getAttribute("username");
		System.out.println(obj);
		
		if(obj!=null){
			//已经登陆,拦截器做类似于放行的操作
			return arg0.invoke();
		}
		else{
			//没有登陆,不执行action里面的方法,返回登陆界面
			//回到result标签里面寻找到fail的值,到相应的配置路径中去
			return "fail";
		}
	}
}

第三步:注册拦截器,配置action和拦截器的关系:

<!-- 登陆拦截器配置: -->
<!-- 1.首先在package标签中声明要使用的拦截器 -->
<interceptors>
	<interceptor name="logininterceptor" class="com.zwp.intercept.myIntercept"></interceptor>
</interceptors>
		
<action name="customer_*" class="com.zwp.action.login.loginAction" method="{1}">
	<!-- 2.在action里使用自定义拦截器-->
	<interceptor-ref name="logininterceptor">
		<!-- 配置action里面的某些方法不进行拦截 :name:excludeMethods;值:action不拦截方法的名称 -->
		<param name="excludeMethods">login</param>	
	</interceptor-ref>
	<!-- 3.当使用了自定义拦截器的时候,系统将不加载默认拦截器,需要手动配置一次 -->
	<interceptor-ref name="defaultStack"></interceptor-ref>
	
	<result name="success">/main.jsp</result>
	<result name="fail">/login.jsp</result>
</action>

 

 

四、Struts2标签:

1、Struts2标签使用在jsp页面中:

<s:property>:和ognl表达式在jsp页面中获取值栈数据

<s:iterator> :获取值栈list集合数据,表示list集合

<s:debug>:查看值栈结构和数据。

2、常用的Html表单标签:

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

3、在struts2里面对应的html表单标签大部分都有:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="s"  uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>struts常用表单标签</title>
</head>
<body>
	<!-- 1.普通输入域 -->
	<s:textfield name="username" label="username"></s:textfield><br/>
	
	<!-- 2.密码输入域 -->
	<s:password name="password" label="password"></s:password><br/>
	
	<!-- 3.单选框 -->
	<!-- value和显示值一样 -->
	<s:radio list="{'男','女'}" name="sex" label="性别"></s:radio><br/>
	<!-- value和显示值不一样 -->
	<s:radio list="#{'nan':'男','nv':'女'}" name="sex1" label="性别"></s:radio>
	
	<!-- 4. 复选框-->
	<s:checkboxlist list="{'java','android','jsp','lunix'}" name="hobit" lable="爱好"></s:checkboxlist><br/>
	
	<!-- 5.下拉框 -->
	<s:select list="{'初中','高中','大学','博士'}" name="college" label="学历"></s:select><br/>
	
	<!-- 6.文件上传项 -->
	<s:file name="file" label="上传文件"></s:file><br/>
	
	<!-- 7.隐藏项 -->
	<s:hidden name="hide" value="abcd"></s:hidden><br/>
	
	<!-- 8.文本域 -->
	<s:textarea rows="10" cols="10" name="resume" label="简历"></s:textarea><br/>
	
	<!-- 9.提交按钮 -->
	<s:submit value="提交"></s:submit><br/>
	
	<!-- 10.重置按钮 -->
	<s:submit value="重置"></s:submit><br/>
	
</body>
</html>

 

 

五、Struts2实现文件上传:

之前web阶段实现上传,使用组件FileUpload,使用struts2实现文件上传,struts2对之前的FileUpload进行封装。

1、如何对上传进行封装:

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

2、使用struts2框架方便实现文件上传:

步骤:

(1)导入所需的jar包:

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

(2)页面中的配置:

第一个要求:表单提交方式 post;

第二个要求:form标签里面有属性 enctype属性值,修改为 multipart/form-data

第三个要求:在表单里面有文件上传项,有name属性 <input type= “file” name=“”/>

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

(3)action中的配置:

①在action直接得到上传文件名称和上传文件;

②在action定义成员变量,生成变量set和get方法;

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

(4)文件上传的逻辑实现:

①在具体的action的方法里面写上传逻辑;

②在服务器里面创建文件;

③把本地文件复制服务器文件里面;

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

(5)出现的问题:

①如果上传的文件超过2M,出现异常:

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

②页面中出现提示:没有input结果定义:

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

(6)解决方法:在struts2.xml文件中配置:

①使用struts2做文件上传大小默认有限制的,默认2M;

②可以设置允许上传文件的大小:

–struts2里面有常量:

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

③页面中Input处理:

input是struts2里面错误处理机制,如果上传文件超过设置的大小之后,自动返回结果,结果名称是input。

解决:配置input结果,到错误页面。

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

④当struts2自动返回input结果,出现错误,在配置input的页面中可以查看错误信息。

–在配置的错误页面中,使用struts2标签可以查看到错误的信息。

Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114719.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号