Struts2学习总结(3)

本文包括以下五个部分:

  1. 值栈。
  2. Ognl表达式。
  3. struts2标签库。
  4. 国际化。
  5. 表单数据校验
  6. 拦截器。
  7. struts2的执行过程。

一、值栈

采用servlet和JSP开发时,servlet通过域对象保存数据,在JSP页面通过jstl标签+el表达式获取数据。

采用struts2和JSP框架进行开发时,Action通过值栈对象保存数据,在JSP页面通过struts标签+ognl表达式获取数据。

1.1 值栈(ValueStack)的概念

值栈就是存放action的堆栈,用来存储请求响应数据,是Struts2存取数据的核心。值栈将数据统一管理起来,方便Action、Result、Interceptor的使用。值栈有一个标准接口ValueStack,而在实际的项目开发中,是通过一个实现类OgnlValueStack来存储数据的。

1.2 值栈的结构

值栈分为值栈分为两个逻辑结构(数据结构):

  • Object Stack(对象栈):ArrayList (CompoundRoot),底层数据结构为ArrayList集合+栈的结构(先进后出)。

对象栈主要存储Action对象和Provider代理对象。

  • Context Map(映射栈): HashMap (OgnlContext),底层的数据结构为Map集合的结构。

a. 映射栈主要存放各个域存放的数据和用户的参数信息。

b. 对象栈主要有五个对象:

Key Value
request RequestMap
session SessionMap
application ApplicationMap
parameters ParaemterMap
attr AttributeMap (封装了三个Map(request,session,application))

1.3 操作值栈对象

1.3.1 操作Object Stack

                //得到ActionContext对象
		ActionContext ac = ActionContext.getContext();
		//得到值栈对象
		ValueStack vs = ac.getValueStack();

push(Object o):压入栈顶

Object pop():推出栈顶元素

1.3.2 操作Context Map

Map<String,Object> getContext(): 得到Context Map对象

ActionContxt.get("request").put("name",Object): 操作Context Map中的reqest元素

ActionContxt.getSession().put("name",Object): 操作Context Map中的session元素

ActionContxt.getApplication().put("name",Object): 操作Context Map中的application元素

package edu.scut.d_valuestack;

import java.util.Date;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
//演示值栈
public class BookAction extends ActionSupport {
	public String list(){
		//值栈是由struts2框架在每次访问Action的方法时创建的,然后将其存入ActionContext

		//1 得到ActionContext对象
		ActionContext ac = ActionContext.getContext();
		//2 得到值栈对象
		ValueStack vs = ac.getValueStack();
		System.out.println(vs);

		//3 操作值栈
		//Object Stack(对象栈)
		Book book = new Book();
		book.setName("java编程思想");
		book.setPrice(58);
		book.setPublishtime(new Date());

		//3.1 压入元素(栈定)
		vs.push(book);
		System.out.println(vs);

		//3.2 推出元素
		vs.pop();
		System.out.println(vs);

		//4 映射栈(Context Map)
		//4.1 操作request属性
		Map requestMap = (Map) ac.get("request");
		requestMap.put("r_book", book);

		//4.2 操作session属性
		ac.getSession().put("s_book", book);

		//4.3 操作application属性
		ac.getApplication().put("c_book", book);		

		System.out.println(vs);
		return SUCCESS;
	}
}

二、Ognl表达式

2.1 Ognl表达式简介

OGNL是Object GraphicNavigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。在struts2项目中导入ognl.jar  包来实现支持ognl表达式。

2.2 Ognl表达式和EL表达式的比较

Ognl表达式 EL表达式

获取域对象的数据。可以存放数据,可以调用方法。


获取域对象的数据。不能存放数据,不能调用方法

2.3 Ognl表达式的优势

  • 支持对象方法调用,如xxx.doSomeSpecial();
  • 支持类静态的方法调用和值访问,表达式的格式:

    @[类全名(包括包路径)]@[方法名 |  值名],例如:

    @[email protected](‘foo %s‘, ‘bar‘)或者

    @[email protected]_NAME。

  • 支持赋值操作和表达式串联,如(price=10,discount=0.6,calculatePrice()),这个表达式会返回6.0;
  • 可以访问OGNL上下文(OGNL context)和ActionContext;
  • 可以操作集合对象。

2.4 Ognl表达式的核心对象(OgnlContext)

2.4.1 Ognl表达式的核心对象OgnlContext对象的使用

package edu.scut.a_ognl;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.junit.Test;

//演示Ognl
public class OgnlDemo {
	//1 学习了解Ognl表达式的核心对象OgnlContext对象的使用
	@Test
	public void test1(){
		User user = new User();
		user.setId(1);
		user.setUserName("乔峰");
		user.setUserPsw("666666");

		//1 创建一个OgnlContext对象
		OgnlContext context = new OgnlContext();

		//2 把user对象存入OgnlContext对象
		context.put("user", user);
		//3 从OgnlContext对象取出数据
		User user2 = (User) context.get("user");
		System.out.println(user2.getId()+"\t"+user2.getUserName()+"\t"+user2.getUserPsw());
	}
}

2.4.2 使用Ognl表达式取出OgnlContext的数据,根对象不需要有key,取值不需要#

package edu.scut.a_ognl;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.junit.Test;

//演示Ognl
public class OgnlDemo {

	//2 使用Ognl表达式取出OgnlContext的数据,根对象不需要有key,取值不需要#
	@Test
	public void test2() throws Exception{
		User user = new User();
		user.setId(3);
		user.setUserName("段誉");
		user.setUserPsw("88888888");

		//1 创建一个OgnlContext对象
		OgnlContext context = new OgnlContext();

		//2 把user对象存入OgnlContext对象
		//根对象要存储数据需要key
		context.setRoot(user);
		//3 从OgnlContext对象取出数据,使用Ognl表达式取数据
		Object ognlObj = Ognl.parseExpression("userName");
		Object result = Ognl.getValue(ognlObj, context, context.getRoot());

		System.out.println(result);
	}

}

2.4.3 使用Ognl表达式取出OgnlContext的数据,非根对象需要有key,取值需要#

package edu.scut.a_ognl;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.junit.Test;

//演示Ognl
public class OgnlDemo {

<pre name="code" class="java">        //3 使用Ognl表达式取出OgnlContext的数据,非根对象需要有key,取值需要#
	@Test
	public void test3() throws Exception{
		User user = new User();
		user.setId(2);
		user.setUserName("虚竹");
		user.setUserPsw("7777777");

		//1 创建一个OgnlContext对象
		OgnlContext context = new OgnlContext();

		//2 把user对象存入OgnlContext对象
		//非根对象要存储数据需要key
		context.put("user", user);
		//3 从OgnlContext对象取出数据,使用Ognl表达式取数据
		Object ognlObj = Ognl.parseExpression("#user.userName");
		Object result = Ognl.getValue(ognlObj, context, context.getRoot());

		System.out.println(result);
	}

}


2.4.4 Ognl表达式调用静态方法

package edu.scut.a_ognl;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.junit.Test;

//演示Ognl
public class OgnlDemo {

	//4 Ognl表达式调用静态方法
	@Test
	public void test4() throws Exception{
		System.out.println(Math.round(12.55));
		//1 创建一个OgnlContext对象
		OgnlContext context = new OgnlContext();
		//使用Ognl表达式取数据
		Object ognlObject = Ognl.parseExpression("@[email protected](10.5)");
		Object result = Ognl.getValue(ognlObject, context, context.getRoot());
		System.out.println(result);
	}
}

结论:

a. 从OgnlContext对象的根对象取出数据,不需要#号。

b. 从OgnlContext对象的非根对象取出数据,需要#号。

2.5 值栈如何共享和获取数据

2.5.1 值栈如何传递到jsp页面

struts2框架在Action中最后把值栈对象传递到jsp页面,是通过request域对象的struts.valueStack名称的属性传递到jsp页面的。

 class Action{
		1.创建OgnlValueStack对象			

	public String list(){
		2.得到OgnlValueStack对象,然后操作OgnlValueStack对象
	}

        3.把OgnlValueStack对象放入request域对象
                request.setAttribute("struts.valueStack",OgnlValueStack对象);
}

2.5.2 查看值栈对象所有内容

<s:debug/>

2.5.3 获取值栈数据

2.5.3.1 获取值栈数据的条件

a. 必须使用ognl表达式获取,需要学习ognl表达式语法。

b. ognl表达式必须依赖struts2的标签。

struts2获取数据的标签:
            <s:property value="ognl表达式"/> 

2.5.3.1 获取值栈数据的规则

a. 获取Object Stack: 不带#号直接获取

(a)  获取对象(对象栈):  [下标]    下标从0开始 。

规则:从对象栈的指定下标的元素开始查找,直到最后一个元素为止!

[0]  从第一个元素开始查找

[1]  从第二个元素开始查找

 <s:property value="[1]"/>

(b)  获取对象属性: [下标].属性    注意:下标可以不写,默认从第一个元素开始查找。

规则:从对象栈的指定下标的元素开始查找指定的属性,如果找到了就直接返回了,如果没有继续查找,直到最后一个元素为止!

 <s:property value="[1].name"/>

b. 获取Context Map(映射栈):带#号获取

<s:property value="#name"/>
<s:property value="#request.r_book.price"/><br/>
<s:property value='#session.s_book.price'/>
<s:property value='#application.c_book.price'/>
<s:property value="#parameters.email"/>
<s:property value="#attr.request.r_book.price"/>

三、struts2标签库

3.1 逻辑类标签: 类似于jstl里面的的条件判断,循环等,用于处理jsp页面的逻辑

<s:set/>  保存数据

<s:property/> 获取数据

<s:if/>+<s:elseif/>+<s:else>  条件判断

<s:iterator/>  循环

 <body>
   <%-- <s:set> 设置数据, <s:property> 获取数据--%>
    <s:set var="message" value="'itcast'" scope="request"/>
    <s:set var="message" value="'itcast'" scope="session"/>
    <s:set var="message" value="'itcast'" scope="application"/>
    <s:property value="#request.message"/>
    <hr>

   <%--条件判断 <s:if>  <s:elseif>  <s:else> --%>
   <%--默认登录数据放在ContextMapd的session中 --%>
   	<s:set var="loginInfo" value="'rose'" scope="session" ></s:set>
   	<s:if test="#session.loginInfo==null">
   		请先登录
   	</s:if>
   	<s:else>
              欢迎你,用户名:<s:property value="#session.loginInfo"/>
   	</s:else>
   	<hr>

   <%--<S:iterator>循环迭代  --%>
   <s:iterator value="#request.books" status="vs" id="book">
   		序号:<s:property value="#vs.count"/>
   		书名:<s:property value="#book.name"/>
   		价格:<s:property value="#book.price"/><br>
   </s:iterator>
</body>

3.2 UI标签:用于简化html标签(表单)使用

<s:form>

<s:textfield>

<s:password>

<s:submit>

<s:reset>

<s:checkbox>

*<s:checkboxlist>

*<s:radio>

*<s:select>

<body>
   	<s:form action="book_list" namespace="/ognl">
   	<%--Struts2的UI部分不是代表ognl表达式,如果要让他们成为OGNL表达式,要加上%{}
   		%{ognl表达式}
   	 --%>
   		<s:textfield label="用户名" name="curUser.userName" cssClass="style2"></s:textfield>
   		<s:password label="密码" name="curUser.userPsw" ></s:password>
   		<s:textarea label="简介" name="info"></s:textarea>
   		<s:submit value="注册" align="left"></s:submit>
   		<s:checkbox name="hobby" label="篮球" value="打篮球"></s:checkbox>
   		<s:checkbox name="hobby" label="足球" value="足球"></s:checkbox>
   		<s:checkbox name="hobby" label="网球" value="网球"></s:checkbox>

   	<%-- 可以用ognllist进行数据的展示
   		ognl表达式创建List集合
   		ognl表达式创建Map集合
   	 --%>
   	<%--label和value一致的情况 --%>
   		<s:checkboxlist name="hobby" list="{'篮球','足球','网球'}"></s:checkboxlist>
   		<s:checkboxlist name="types" list="#request.types"></s:checkboxlist>

   	<%--lable和value不一致的情况 --%>
		<s:checkboxlist name="hobby" list="#{'eat':'吃','drink':'喝','play':'玩'}"></s:checkboxlist>

	<%--list:所以checkbox的值
	    value:默认选中的checkbox的值 --%>
   	<s:checkboxlist name="types" list="#request.typesMap" value="curTypes" ></s:checkboxlist>
   	<s:select name="types" list="#request.typesMap" value="curTypes"></s:select>
   	<s:radio list="#request.typesMap" value="%{curTypes}"></s:radio>
 	<s:reset value="重置" align="left" theme="simple"></s:reset>
   	</s:form>
</body>

四、国际化

国际化步骤:

1. 在src目录下创建resource包,在resource包下创建国际化的properties文件:

message_en_US.properties:

user=USERNAME
password=PASSWORD
login=LOGIN

message_zh_CN.properties:

user=\u7528\u6237\u540D
password=\u5BC6\u7801
login=\u767B\u5F55

2. 统一绑定资源包。

在struts.xml配置文件中添加国际化的常量配置。

<!-- 修改国际化资源包的路径 -->
<constant name="struts.custom.i18n.resources" value="resource.message"></constant>

3. 使用国际化

a. Action:注意action类要继承ActionSupport类,用getText()方法获取需要国际化的属性。

package edu.scut.a_ognl;

import com.opensymphony.xwork2.ActionSupport;

public class BookAction extends ActionSupport{
	public String i18n(){
		//获取国际化内容
		String user = getText("user");
		String password = getText("password");
		String login = getText("login");
		System.out.println(user);
		System.out.println(password);
		System.out.println(login);

		return "i18n";
	}
}

b. JSP页面:注意用key接收需要国际化的属性。

<body>
  <%--在标签中使用国际化内容 --%>
  <s:form>
   	<s:textfield key="user"/>
   	<s:password key="password"/>
   	<s:submit key="login"/>
  </s:form>
</body>

五、表单数据校验

采用javascript页面前端进行验证安全性不够,容易被绕过去,为了提高安全性,一般要进行后台验证。

5.1 使用代码验证

使用代码进行验证的方式灵活太差,一般比较少用。

5.1.1 全局验证(所有的方法都验证)

a. 编写一个Action类,继承ActionSupport(为了实现Valiateable接口)。b. 覆盖validate()方法。

b. 覆盖validate()方法。

下面的代码中对reg()和list()两个方均进行了验证。

package edu.scut.b_validate;

import org.hibernate.validator.constraints.Email;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
//采用方式进行验证,必须继承actionSupport
public class UserAction extends ActionSupport implements ModelDriven<User> {
	//接受页面数据
	private User user = new User();
	@Override
	public User getModel() {
		// TODO Auto-generated method stub
		return user;
	}

	/**
	 * 1)用户名不能为空,必须为数字或字母,长度4-16位
	 * 2)密码不能为空,必须为数字,长度为6-16位
	 */
 	@Override
	public void validate() {
  		System.out.println("执行数据校验!");
 		System.out.println(user);
 		if(user!=null){
			//进行数据校验
 			 //用户名
			if(user.getName()==null || user.getName().equals("")){
 				//用户名不能为空
  				//将错误信息带入注册页面
				addFieldError("username", "用户名不能为空!");
  			}else{
 				//必须是字母或者数字。并且长度为4-16位
 				if(!user.getName().matches("[0-9a-zA-Z]{4,16}")){
  					addFieldError("username", "用户名格式错误!");
 				};
  			}

			 //密码
 			if(user.getPassword()==null || user.getPassword().equals("")){
 				//密码不能为空
 				addFieldError("password", "密码不能为空!");
 	 		 }else{
 				//必须为数字,4-16位
 				if(!user.getPassword().matches("[0-9]{6,16}")){
 					addFieldError("password", "密码格式有误!");
				}
  			}
 	}

	 public String reg(){
  		System.out.println(user);
 		return SUCCESS;
  	}
<span style="color:#FF0000;"><span style="color:#000000;"></span></span><pre name="code" class="java">        public String list(){
		System.out.println(user);
		return "list";
	}

}


c. 在struts.xml文件中对应的action配置加上input视图,然后struts2就会自动把错误信息转发到input视图的页面上去。

<result name="input">/reg.jsp</result>

d.
在input视图页面上,打印出错误信息。

<s:fielderror></s:fielderror>

5.1.2 局部验证(对一个方法验证)

局部校验时,只需要把需要验证的方法名改成固定格式(validate+需要验证的方法名称)即可。

例如,要对只对reg()方法验证,而不对其他方法验证,只需将reg()方法名称改成validateReg()即可。

        //代码方式局部验证,编写validate+需要验证的方法名称!!!
	public void validateReg(){
		//有错误信息,struts2会自动跳转到input页面
		if(user!=null){
			//用户名验证
			if(user.getName()==null || user.getName().equals("")){
				addFieldError("name", "用户名不能为空!");
			}else{
				if(!user.getName().matches("[0-9a-zA-Z]{4,16}")){
					addFieldError("name", "用户名格式错误!");
				}
			}

		}
	}

5.2 使用配置文件验证

为了提高数据校验的灵活性,可以使用配置文件的方式完成校验。

5.2.1 全局验证(所有的方法都验证)

这种配置方式对action的所有方法都生效。

a. 编写一个xml文件,名称:  Action文件名-validation.xml。

b. 该xml文件必须放在Action文件的同一目录。

例如:UserAction-validation.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//Apache Struts//XWork Validator 1.0.2//EN"
        "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
	<!-- 验证一个属性 name是属性名 -->
	<field name="name">
		<!-- 属性验证器 -->
		<field-validator type="requiredstring">
			<!-- 错误信息 -->
			<message key="name.requried"></message>
		</field-validator>
		<field-validator type="regex">
			<!-- 给验证器注入一个参数 -->
			<param name="expression">[0-9a-zA-Z]{4,16}</param>
			<!-- 错误信息 -->
			<message key="name.formaterror"></message>
		</field-validator>
	</field>

	<field name="email">
		<field-validator type="requiredstring">
			<message key="email.requried"></message>
		</field-validator>
		<field-validator type="email">
			<message key="email.formaterror"></message>
		</field-validator>
	</field>
</validators>

5.2.2 局部验证(对一个方法验证)

这种配置方式对action的指定方法都生效。

a. 编写一个xml文件,名称: Action文件名-访问方法路径-validation.xml。

b. 该xml文件必须放在Action文件的同一目录。

例如:UserAction-user_reg-validation.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//Apache Struts//XWork Validator 1.0.2//EN"
        "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
	<!-- 验证一个属性 name是属性名 -->
	<field name="name">
		<!-- 属性验证器 -->
		<field-validator type="requiredstring">
			<!-- 错误信息 -->
			<message key="name.requried"></message>
		</field-validator>
		<field-validator type="regex">
			<!-- 给验证器注入一个参数 -->
			<param name="expression">[0-9a-zA-Z]{4,16}</param>
			<!-- 错误信息 -->
			<message key="name.formaterror"></message>
		</field-validator>
	</field>

	<field name="email">
		<field-validator type="requiredstring">
			<message key="email.requried"></message>
		</field-validator>
		<field-validator type="email">
			<message key="email.formaterror"></message>
		</field-validator>
	</field>
</validators>

六、拦截器

6.1 拦截器简介

拦截器的功能类似于过滤器,但是过滤器可以过滤项目的任何请求(servlet/jsp/html/img),拦截器只能拦截Action资源。拦截器是struts2框架的核心,因为struts2的核心功能都是通过拦截器来实现的。

例如:

参数的接收拦截器:com.opensymphony.xwork2.interceptor.ParametersInterceptor

文件上传拦截器:org.apache.struts2.interceptor.FileUploadInterceptor

国际化拦截器:com.opensymphony.xwork2.interceptor.I18nInterceptor

6.2 拦截器和过滤器的比较

拦截器 过滤器
可以拦截代码 可以拦截代码
struts2的组件之一,主要是拦截的action(方法) servlet的三大组件之一,主要是拦截请求(静态内容和动态内容)和响应

6.3 自定义拦截器的开发步骤

struts2框架有很多拦截器,来支持其核心功能。但是,有时候不能满足实际开发的需求,用户需要自定义具有特殊功能的拦截器。struts2支持自定义拦截器。 自定义拦 截器的开发步骤如下:

a. 编写java类,实现Intercepor接口。

Example

编写两个拦截器:

MyInterceptor1

package edu.scut.d_Interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class MyInterceptor1 implements Interceptor {

	@Override
	public void destroy() {
	}

	@Override
	public void init() {
	}

 	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
 		System.out.println("1 执行interceptor1的action前面的代码!");
		String result = invocation.invoke();
 		System.out.println("5 执行interceptor1的action后面的代码!");
		return result;
 	}
}

MyInterceptor2

package edu.scut.d_Interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class MyInterceptor2 implements Interceptor {

	@Override
	public void destroy() {
	}

	@Override
	public void init() {
	}

	@Override
 	public String intercept(ActionInvocation invocation) throws Exception {
		System.out.println("2 执行interceptor2的action前面的代码!");
 		String result = invocation.invoke();
		System.out.println("4 执行interceptor2的action后面的代码!");
 		return result;
 	}
}

action类

package edu.scut.d_Interceptor;

import com.opensymphony.xwork2.ActionSupport;
//图书操作类
public class BookAction extends ActionSupport {
	//接收页面参数
	private String name;
	public void setName(String name) {
		this.name = name;
	}

	private String password;
	public void setPassword(String password) {
		this.password = password;
	}

       public String list(){
		System.out.println("3 执行了图书的list方法!");
		System.out.println(name);
 		System.out.println(password);
		return SUCCESS;
 	}
}

b. 在struts.xml文件中配置拦截器,并定义拦截器栈。。

注意:在配置action时,引用了自定义的拦截器栈后,默认的拦截器栈(defaultStack)也要引用,并且放在配置的第一位置。否则,struts2的很多核心功能将实效。例如不能接收页面传过来的参数。

<?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="interceptor" extends="struts-default" namespace="/interceptor">
		<!-- 配置自定义拦截器 -->
		<interceptors>
			<!-- 定义拦截器 -->
			<interceptor name="interceptor1" class="edu.scut.d_Interceptor.MyInterceptor1"/>
			<interceptor name="interceptor2" class="edu.scut.d_Interceptor.MyInterceptor2"/>
			<!-- 定义拦截器栈 -->
			<interceptor-stack name="myStack">
				<!-- 一个拦截器栈包含多个拦截器 -->
				<!-- 注意:struts2的默认拦截器一定要配置在第一位!否则会被覆盖! -->
				<interceptor-ref name="defaultStack"></interceptor-ref>
				<interceptor-ref name="interceptor1"></interceptor-ref>
				<interceptor-ref name="interceptor2"></interceptor-ref>
			</interceptor-stack>
		</interceptors>

		<action name="book_*" class="edu.scut.d_Interceptor.BookAction" method="{1}" >
			<!-- 引入拦截器 -->
			<interceptor-ref name="myStack"></interceptor-ref>
			<result >/succ.jsp</result>
		</action>
	</package>
</struts>

以上Example的运行结果:

1 执行interceptor1的action前面的代码!
2 执行interceptor2的action前面的代码!
3 执行了图书的list方法!
4 执行interceptor2的action后面的代码!
5 执行interceptor1的action后面的代码!

可以看出,页面发送的请求,必须经过拦截器才能访问action类,而且通过拦截器的顺序是根据struts2里面的配置顺序进行的。执行了第一个拦截器的(String result = invocation.invoke();)才能放行,依次执行后面的拦截器或者方法。

七、struts2的执行过程

下面这个图不是我自己画的,但是为了说明问题,我引用一下。跟着步骤仔细看一遍,会加深理解。

时间: 2024-10-15 03:46:34

Struts2学习总结(3)的相关文章

struts2 学习记录 之 国际化

struts2 接下来是国际化,如果一个系统想要被多个国家的人所用就不得不考虑国际化的问题,如果为每一个国家都开发一套系统维护起来会很麻烦,所以就有了个思想,那就是把动态的,用不同语言展示的部分,放到配置文件中,动态的从文件里读取想要展示的内容,不同国家的人就得到了不同的展示,这是一个很好的思想,所以我把它记录一下了,嘻嘻... 首先 struts2 要把它的配置文件写好,以中文和美式英语为例,配置文件如下: 配置文件是以键值对的形式存在的,且以properties结尾,命名也有一定的格式,如t

struts2 学习记录 过滤器 国际化

struts2接触不是一天两天了,但是一直没有用它做什么项目,但老师确一直说它有很大的学习价值,所以还是把我学习到的东西给记录一下,记录的东西没有规律,只是给自己留个备份, struts2中最关键的是action,action可以用来传值,用起来很方便,它可以用el表达式在jsp页面上展示出来,也可以用ognl,el只能表达作用域里面的值,而struts2里面还有个放数据的地方叫做ActionContext,这个类里面可以放不在作用域里的键值对,但是el表达式还是可以获取到,但是效率很低,所以尽

struts2学习笔记(二)—— 获取登录信息及计算在线人数

实现目的: 1.点击"Login"的超链接,进入登录页面 2.填写登录信息,提交表单,将用户信息保存进Session 3.显示用户名,并计算在线人数 4.点击"Logout"的超链接,在线人数减一,并使Session失效 Struts2实现: 1.配置web.xml文件 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http:/

struts2学习笔记(8)-------struts2的ajax支持

struts2支持一种stream类型的Result,这种类型的Result可以直接向客户端浏览器响应二进制,文本等, 我们可以再action里面生成文本响应,然后在客户端页面动态加载该响应即可. 直接看例子: public class LoginAction { private String user; private String pass; private InputStream inputStream; public InputStream getInput(){ return inpu

Struts2学习

Struts2流程 Web端发起一个request到Struts2action的过程为:首先对提交的表单或者数据进行类型转换,如果转换失败,则action跳转至input所对应的页面,如果没有设置input对应的页面则页面报错.如果转换成功,则已经自动给action的属性赋值了,接下来会调用action中的validate()校验方法,如果校验失败,则同转换失败一样跳转至input所对应的页面,只有校验通过了,才会去执行execute()方法,然后根据返回值跳转到对应的页面. JSP EL表达式

Struts2学习笔记(OGNL表达式)

Struts2学习笔记(OGNL表达式) Struts 2支持以下几种表达式语言: OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言: JSTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言: Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python.Ruby和Smarttalk等)的一些起特性: Velocity,严格来说不是表达式语言,它是一种基于Ja

Struts2 学习笔记(概述)

Struts2 学习笔记 2015年3月7日11:02:55 MVC思想 Strust2的MVC对应关系如下: 在MVC三个模块当中,struts2对应关系如下: Model: 负责封装应用的状态,并实现应用的功能.通常分为数据模型和业务逻辑模型,数据模型用来存放业务数据,比如订单信息.用户信息等:而业务逻辑模型包含应用的业务操作,比如订单的添加或者修改等. 封装应用状态:某些应用数据封装起来,使得视图只能通过接口获取对应的数据 响应状态查询:对应用的状态改变进行处理 暴露应用功能:暴露接口 通

struts2学习笔记(一)

一.struts2和struts1的区别 1.Action类 a) Struts1要求Action类继承于一个抽象类,Struts1普遍使用抽象类编程而不是接口 b) Struts2的Action类可以实现一个Action接口,也可以实现其他接口,使可选和定制的服务成为可能.Struts2提供一个ActionSupport基类去实现常用的接口.Action接口不是必须的,任何有execute标识的POJO对象都可以作为Struts2的Action对象. 2.线程模式 a) Struts1的Act

struts2学习笔记(7)------------ognl表达式

OGNL表达式(Object-Graph Navigation Language),大概可以理解为:对象图形化导航语言.是一种可以方便地操作对象属性的开源表达式语言. Struts2自行维护一个特定范围的"银行",Action将数据放入其中,而JSP页面可从中取数据,表面上似乎看起来像是jsp可以直接访问Action数据.. 当Action属性不再是简单的值,而是某个对象,数组,集合时,就需要使用ognl表达式来访问这些对象,数组,集合内的数据了. 1)ognl的stack Conte

Struts2学习笔记1

一.下载struts2.0.1 http://struts.apache.org/downloads.html,下载struts-2.0.1-all.zip,这个压缩包中包括了开发struts2所需的struts2-core.jar核心包以及其他struts2所依赖的JAR文件,另外另一些struts2的演示样例程序以及一些HTML的API文档. 二.试用struts2.0.1 1. 新建一个WEBproject,将struts-2.0.1-all.zip压缩包中的lib文件夹下的全部jar文件