新浪微博 Github

三、Action及异常处理

一、Action介绍

在Struts2中,Action是最重要的,因为struts2是由多个Action组成的;比如要对业务进行分发都需要使用Action;

Struts2相比Struts1,采用低侵入式设计,即一个普通的Java类也可以作为一个Action,不一定要继承或实现Action接口;

而定义Action通常需要遵循几个规范:

1.可以选择继承ActionSupport;

2.重写public String execute()throws Exception 方法,此方法是访问Action默认调用的方法(当然可以自己设定调用任意方法,此配置需要在struts.xml进行);

3.Action类中的属性是用于封装HTTP请求、页面结果数据的在访问Action时,如果带有请求参数,则会通过params拦截器对Action同名的属性进行赋值


 Action和ActionSupport:用于规范action类的处理;


二、配置Action

我们在struts.xml中配置Action;

模板:

<struts>
<constant name="struts.devMode" value="true"></constant>
<package name="" extends="struts-default" namespace="" >
	<action name="" class="">
                 <param name="name">xiazdong</param>
   		 <result>1.jsp</result>
	</action>
</package>
</struts>

配置Action规范:<action>元素必须在<package>中;

下面开始介绍配置action时的常用元素;

1.<package>

package能够用几个属性:

(1)name:表示包名称,通过随意指定即可;

(2)extends:继承哪个父包,如果继承了某个父包,则会继承父包的action;通常我们需要继承 struts-default ,此package定义了内建拦截器

(3)namespace:定义命名空间,如果不指定,则为默认的命名空间;如果为"/",则表示根命名空间;

(4)abstract:不常用,如果为true,则不能定义action;

举例:

<package name="myPackage" namespace="/" extends="struts-default">

</package>

默认命名空间和根命名空间:

默认命名空间是一个很特殊的命名空间,如果要访问一个action,最后都会在默认命名空间中寻找;

比如/aaa/bbb.action,首先先去命名空间为"/aaa"中去找,如果找不到,则去默认命名空间中寻找bbb.action;

而根命名空间只是一个普通的命名空间;

访问某个action时的URL 通常为:  http://localhost:8080/ApplicationName/Namespace/ActionName.action;


命名空间的查找规则:

比如 http://localhost:8080/StrutsProject/a/b/c/d/aa.action;

1.查找是否存在/a/b/c/d 命名空间

    如果不存在,则跳到步骤2

    如果存在则查找是否存在aa.action

        如果不存在该action,则到默认命名空间中查找是否存在aa.action;

        如果存在即可;

2.查找是否存在/a/b/c 命名空间

    如果不存在,则跳到步骤3

    如果存在则查找是否存在aa.action

        如果不存在该action,则到默认命名空间中查找是否存在aa.action;

        如果存在即可;

3.查找是否存在/a/b 命名空间

    如果不存在,则跳到步骤4

    如果存在则查找是否存在aa.action

        如果不存在该action,则到默认命名空间中查找是否存在aa.action;

        如果存在即可;

4.查找是否存在/a 命名空间

    如果不存在,则跳到步骤5

    如果存在则查找是否存在aa.action

        如果不存在该action,则到默认命名空间中查找是否存在aa.action;

        如果存在即可;

5.查找是否存在/ 命名空间

    如果不存在,则跳到步骤6

    如果存在则查找是否存在aa.action

        如果不存在该action,则到默认命名空间中查找是否存在aa.action;

        如果存在即可;

6.在默认命名空间中查找;


2.<action>

<action>的属性有:

(1)name:指定了Action的名字,也是对外的URL;

(2)class:访问此Action的处理类,不指定则默认为ActionSupport,ActionSupport的返回值为SUCCESS,注意:必须要写出类的全名;

(3)method:如果不指定,则默认调用execute方法,如果指定,则调用此方法;

3.<result>

定义了Action的返回结果所对应的JSP(当然可以是任意的视图页面);

<result>的常用属性为

(1)name:Action方法返回的字符串,默认为success;

(2)type:结果类型,默认为dispatcher,此问题在下面会详细讲解;

代码示例:

<package name="MyPackage" extends="struts-default" namespace="/" >
		<action name="loginAction" class="org.login.action.LoginAction" >
			<result name="success" type="redirect">
				<param name="location">/result.jsp</param>
			</result>
			<result name="error" type="redirect">/result.jsp</result>
		</action>
		
	</package>


 

逻辑Action和物理Action的区别:

逻辑Action是在struts.xml中配置的action元素,物理Action是实际的Action类;

如果某个Action类存在fun1() 和fun2()方法,则可以定义两个逻辑Action,虽然处理类都是一样的;



局部结果和全局结果:

全局结果是在<global-results>元素中配置,此结果映射关系对于所有action都起作用;

局部结果是在<action>元素中配置,是指此结果映射关系只对特定的Action起作用;

当局部结果和全局结果同时满足要求,则局部结果优先;

全局结果放在<package>元素中,对于该package的所有Action都有效;

全局结果的语法:

<global-results>

    <result> 

    </result>

</global-results>

  


4.<param>


如果是<action>的子元素,用于为action注入值;

比如

当HelloAction中有name属性,struts.xml中包含如下代码:

<action name="hello" class="org.xiazdong.HelloAction">
	<param name="name">xiazdong</param>
	<result>/1</result>
</action>


 

则执行此action时会自动为name属性赋值;


 

三、DMI

Dynamic Method Invocation,即动态决定调用Action的哪个方法,即不是提前配置决定,比如一个页面有登陆按钮和注册按钮,只有一个Action类,里面有login()方法和regist()方法,如果点击注册按钮,则调用regist方法,如果点击登录按钮,则调用login()方法,此时可以使用动态方法调用;

注意:在struts2.3 中动态方法调用默认开启,因此不需要配置,否则

<constant name="struts.enable.dynamicMethodInvocation" value="true"></constant>

默认配置文件:struts2-core-2.3.1.1.jar\org\apache\struts2\default.properties;

动态方法调用语法:ActionName!methodName

比如loginAction!login则调用loginAction类中的login方法;

示例代码:

LoginAction.java

package org.login.action;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport{
	private String user;
	private String password;
	private String result;
	public String login()throws Exception{
		if(user.equals("xiazdong")&&password.equals("12345")){
			setResult("登陆成功");
			return SUCCESS;
		}
		else{
			setResult("登陆失败");
			return ERROR;
		}
	}
	public String regist()throws Exception{
		setResult("注册成功");
		return SUCCESS;
	}
	public String getUser() {
		return user;
	}
	public void setUser(String user) {
		this.user = user;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public void setResult(String result) {
		this.result = result;
	}
	public String getResult() {
		return result;
	}
	
}


login.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>登录界面</title>
<script type="text/javascript">
	function regist(){
		document.forms[0].action = "loginAction!regist";
	}
</script>

</head>
<body>
	<form action="loginAction!login">
		用户名:<input type="text" name="user"/><br />
		密码:<input type="password" name="password"/><br />
		<input type="submit" value="登录"/> 
		<input type="submit" value="注册" onClick="regist();"/>
	</form>
</body>
</html>


struts.xml

<?xml version="1.0" encoding="GBK" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
	<constant name="struts.devMode" value="true"></constant>
	
	<package name="MyPackage" extends="struts-default" namespace="/" >
		<action name="loginAction" class="org.login.action.LoginAction" >
			<result name="success" type="redirect">
				<param name="location">/result.jsp</param>
			</result>
			<result name="error" type="redirect">/result.jsp</result>
		</action>
		
	</package>
</struts>


 

四、通配符使用

我们可能会遇到这种情况:需要配置很多个逻辑Action,但是名称上有许多相似的地方,比如:

<action name="loginAction" class="org.login.action.LoginAction" >
	<result name="success" type="dispatcher">/result.jsp</result>
	<result name="error" type="dispatcher">/result.jsp</result>
</action>
<action name="registAction" class="org.login.action.registAction" >
	<result name="success" type="dispatcher">/result.jsp</result>
	<result name="error" type="dispatcher">/result.jsp</result>
</action>

则如果使用通配符则可以表示成:

<action name="*Action" class="org.login.action.{1}Action" >
	<result name="success" type="dispatcher">/result.jsp</result>
	<result name="error" type="dispatcher">/result.jsp</result>
</action>

 

在name属性中使用“*”,而在class、method、result元素中都可以使用{1}、{2}表示第一个*的值、第二个*的值;

<action name="*">时可以匹配任意的action请求,因为他是位于默认命名空间;

注意:如果同时匹配多个action,则除非完全相同,否则按先后顺序决定;


{N}表达式可以用于class属性、method属性、result属性;

在result中还可以使用${attributeName} 通过OGNL表达式引用Action类的属性的值;

比如 <result>/${name}.jsp


五、默认Action和默认处理类

都配置在<package>元素下;

默认Action是指当全部的action不匹配时,执行此action;

默认处理类是指如果不指定class属性时的处理类,如果不指定,则是ActionSupport;

语法分别如下:

<default-action-ref name="actionName">

<default-class-ref class="Action"/>

六、<result>的type属性

逻辑视图和物理视图的定义:

逻辑视图是Action处理完后的返回值即String,而物理视图是JSP页面;

1.dispatcher

默认值,与JSP相关联;

2.redirect

重定向到JSP页面,与dispatcher的区别是:

dispatcher是服务器跳转;redirect是客户端跳转;

3.redirectAction

重定向到另一个Action类;

<result>子元素<param>可以填写如下两个属性指定Action:

<result type="redirectAction">

<param name="actionName">actionname</param>

<param name="namespace">namespace</param>

</result> 

4. stream

一般用于文件下载,此处不细讲;

5.plainText

用于显示视图资源的源代码;

配置plainText的模板:

<result type="plainText">

<param name="location">/index.jsp</param>

<param name="charSet">UTF-8</param>

</result>

 七、访问Servlet

ServletActionContext能够很方便的获得Servlet的常用对象;在execute()方法中通过:

		HttpServletRequest request = ServletActionContext.getRequest();
		HttpServletResponse response = ServletActionContext.getResponse();
		PageContext page = ServletActionContext.getPageContext();
		ServletContext application = ServletActionContext.getServletContext();
		HttpSession session = request.getSession();


获得;


补充:

PreResultListener的使用

PreResultListener触发于执行完Action代码之后、进入物理视图之前;

模板代码如下:

ActionInvocation invocation = ActionContext.getContext().getActionInvocation();
invocation.addPreResultListener(new PreResultListener(){
	public void beforeResult(ActionInvocation invocation,String resultCode){
		.....
	}
});


八、异常处理

根据Action的execute方法定义public String execute()throws Exception可知,此方法可以抛出任何异常;因此我们遇到任何异常,只需要抛出,交给struts2的框架即可,框架会通过拦截器exception进行捕捉;

我们在struts.xml中配置异常处理的方案,当execute抛出异常后,就会在struts.xml 中寻找解决方案;

异常分为全局异常和局部异常;

全局异常的语法:

 

<global-exception-mappings> 

    <exception-mapping exception="" result=""/>  

</global-exception-mapping> 


 

exception 指定异常所属类;

result是指逻辑视图名;

比如:

<exception-mapping exception="java.sql.SQLException" result="error"/>


 

局部异常语法:

 

<action> 

 <exception-mapping exception="" result=""/> 

</action>  

 

输出异常信息:通过<s:property value="exception.messaeg"/>输出;

代码:

ExceptionAction.java

package org.login.action;

import com.opensymphony.xwork2.ActionSupport;

public class ExceptionAction extends ActionSupport{
	private String str;
	public String execute()throws Exception{
		if("".equals(str) || str==null){
			throw new NullPointerException();
		}
		else{
			throw new ArithmeticException();
		}
	}
}


struts.xml

<action name="exceptionAction" class="org.login.action.ExceptionAction">
			<exception-mapping result="xxxx" exception="java.lang.NullPointerException"></exception-mapping>
			<exception-mapping result="yyyy" exception="java.lang.ArithmeticException"></exception-mapping>
			<result name="xxxx">/xxxx.jsp</result>
			<result name="yyyy">/yyyy.jsp</result>
		</action>


 

posted @ 2012-01-28 18:40  xiazdong  阅读(250)  评论(0编辑  收藏  举报