《深入浅出struts2》--第三章,动作与结果

一,动作类

1,规范:
(1),每个属性必须要有get和set方法,并且struts里面非字符串的属性会自动进行数据转换。
(2),  必须要有一个不带参数的构造器。
(3),每个动作类至少要有一个方法供struts在执行动作时进行调用。因为struts会根据这个动作结果选择控制权转移到哪里
(4),同一个动作类可以包含多个动作方法。动作类为不同的动作提供不同的方法
(5),不必考虑线程安全问题,因为struts2会为每个http请求创建一个新动作实例。
(6),struts2不创建httpsession对象,但jsp中默认会。
2,说明:
(1),编写的大多动作类扩展自ActionSupport类,并因此实现了Action接口,从接口中会继承5个静态字段:
《深入浅出struts2》--第三章,动作与结果_第1张图片
2),在原始的MVC Model2中为了在试图中可以访问到从控制层得到的数据,必须在控制层把数据存放在某个作用域,但是在struts2中不用这样做啦,我们不必考虑试图如何访问它,因为在struts2中动作类对象和其他对象压入ValueStack栈中,而这个栈中的值,则可以被视图访问。

二,动作类如何访问strut2中资源

资源:ServletContext,HttpSession,HttpServletRequest,HttpServletResponse等等
1,两种方法:
(1),通过ServletActionContext类的对象访问
其中ServletActionContext的父类ActionContext也可以访问这些资源。只是这个子类更方便使用。
ServletActionContext提供的静态方法:
public static javax.servlet.http.HttpServletRequest    getRequest()也可以在该对象上获得HttpSession对象
public static javax.servlet.http.HttpServletResponse    getResponse()
public static javax.servlet.ServletContext   getServletContext()
(2),通过实现Aware接口来实现访问资源
  • 动作类实现Aware接口:
调用一个动作时,struts会先检查相关的动作类是否实现了ServletContextAware接口,如果实现了,strut2将先调用动作的setServletContext()方法并且传递相应的参数对象,再然后才是填充属性,最后执行动作方法。并且在那个方法里,需要把servletcontext对象赋值给一个对象。(其它两个接口ServletRequestAware和ServletResponseAware的过程类似)
  • 特别注意SessionAware接口:
实现这个接口,得到的不是HttpSession实例,而是java.util.Map的实例。
其接口的方法为:
void setSession(java.util.Map map)
在填充属性之前,struts2调用上面方法,并传递一个SessionMap对象参数。注意:SessionMap类,扩展于AbstractMap,这个抽象类实现了java.util.Map接口。
SessionMap内部有一个指向HttpSession的受保护的指针,所以不能直接通过SessionMap获得HttpSession对象,但是SessionMap提供了一系列方法可以间接对HttpSession对象进行访问。但是不能通过这个map对象访问HttpSession的标示符。
通过接口访问资源的例子:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- struts2过滤器 -->
  <filter>
     <filter-name>struts2</filter-name>
     	<filter-class>
     	    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
     	</filter-class>	
  </filter>
  <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping> 
</web-app>
struts.xml

<?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="app03a" extends="struts-default" namespace="/">
		<action name="User_input">
			<result>
				<param name="location">/jsp/Login.jsp</param>
			</result>
		</action>
		<action name="User_login" class="demo.User" method="login">
			<result name="success">/jsp/Menu.jsp</result>
			<result name="input">/jsp/Login.jsp</result>
		</action>
		<action name="User_logout" class="demo.User" method="logout">
			<result name="success">/jsp/Login.jsp</result>
		</action>
	</package>
</struts>

动作类:

package demo;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.dispatcher.SessionMap;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.util.ServletContextAware;

import com.opensymphony.xwork2.ActionSupport;


public class User extends ActionSupport implements SessionAware,
		ServletRequestAware, ServletResponseAware, ServletContextAware {

	private String userName;
	private String password;
	private ServletContext servletContext;
	private HttpServletRequest servletRequest;
	private HttpServletResponse servletResponse;
	private Map sessionMap;
	
	@Override
	public void setServletContext(ServletContext servletContext) {
		this.servletContext=servletContext;
	}

	@Override
	public void setServletResponse(HttpServletResponse servletResponse) {
		this.servletResponse=servletResponse;
	}

	@Override
	public void setServletRequest(HttpServletRequest servletRequest) {
		this.servletRequest=servletRequest;
	}

	@Override
	public void setSession(Map<String, Object> map) {
		this.sessionMap=map;
	}

	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 User() {}
	
	public String login(){
		String referer=servletRequest.getHeader("referer");
		if(referer!=null && userName.length()>0 && password.length()>0){
			int onlineUserCount=0;
			synchronized (servletContext) {
				try{
					onlineUserCount=(Integer)servletContext.getAttribute("onlineUserCount");
				}catch(Exception e){}
				servletContext.setAttribute("onlineUserCount", onlineUserCount+1);
			}
			
			return SUCCESS;
		}else{
			return INPUT;
		}
	}
	
	public String logout(){
		if(sessionMap instanceof SessionMap){
			((SessionMap)sessionMap).invalidate();
		}
		int onlineUserCount=0;
		synchronized (servletContext) {
			try{
				onlineUserCount=(Integer)servletContext.getAttribute("onlineUserCount");
			}catch(Exception e){}
			servletContext.setAttribute("onlineUserCount", onlineUserCount-1);
		}
		
		return SUCCESS;
	}
	
}
视图页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'Login.jsp' starting page</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  
  <body>
    <form action="User_login.action">
    	<input type="text" name="userName"><br>
    	<input type="password" name="password"><br>
    	<input type="submit">
    </form>
  </body>
</html>

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'Menu.jsp' starting page</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  
  <body>
    人数${onlineUserCount}<br>
    <a href="User_logout.action">退出</a>
  </body>
</html>

三,struts给动作属性赋值的方法:

1,方法一:请求参数对应着动作属性,struts用这些值进行进行填充动作属性
2,方法二:struts.xml文件的动作声明里传递值
(1),通过ServletActionContext类的对象访问
<param name="userName">user1</param>
<param name="password">123</param>
</action>
就像上面例子:每个param元素对应一个动作属性,static parameters拦截器负责把这些静态参数映射到动作属性。

四,默认的动作类ActionSupport:

1,实现了Action接口,通常我们写动作类会扩展于ActionSupport类。
(1),ActionSupport类实现了Action的execute()方法,这个方法的实现仅仅是返回Acion.SUCCESS.,除此外这个类还有很多别的方法,很方便我们使用。当然根据需要,我们有时候会去覆盖这些方法的实现。

五,结果result:

1,结果类型






(1),Chain
构成动作链:前一个动作的控制权转交给后一个动作,前一个动作在后一个动作里仍然保持着。
动作链由Chaining拦截器负责处理。这个拦截器是defaultStack拦截器栈一份子,因此可以随时使用动作链。
《深入浅出struts2》--第三章,动作与结果_第2张图片

(2),Dispatcher
默认的结果类型,把控制权转交给同一个应用程序中的某个资源,这个资源不能是外部资源,不能转交到一个绝对地址。
(3),HttpHeader
把一个http状态发送给浏览器。

(3),Redirect
把用户重定向到另一个资源,通常用于重定向到外部资源。
这种结果类型有连个参数:
location重定向的目的地
parse表明是否把location参数的值视为一个OGNL表达式解释。默认为true。
定向到外部资源,通常用Redirect。定向内部资源, 通常dispatcher,这样更高效,不用向redirect那样需要向浏览器发送定位信息,然后浏览器再向服务器请求别的内
Redirect结果类型由HttpServletResponse.sendRedirect的类负责处理。

(4),Redirect Action
重定向到另一个动作。

四,异常处理exception-mapping元素:

1,Struts提供了一种机制能把在动作类里未捕获的异常捕获,并且做相应的处理。
(1),

(2)
《深入浅出struts2》--第三章,动作与结果_第3张图片

所有被捕获的异常有exception拦截器负责处理。这个拦截器是defaultStack默认拦截器栈的一份子,每当某个exception-mapping元素捕获一个异常,这个拦截器就会向valueStack栈添加两个对象:
exception,表示被捕获的异常对象
exceptionStack,被捕获异常的栈线索。
那么,视图就可以访问这些异常信息,一般用OGNL表达式访问。

五,通配符映射:

  1. 多个相似的映射关系简化为一个映射关系
  2. 如果某个动作存在,则会调用相应的动作。如果某个动作不存在,则会去查找含有通配符的那个动作,如果符合这个带通配符的名字,那么就会执行这个动作。如果符合的带通配符的动作不止一个,则最后一个胜出。如果找到了多个匹配,那么不带通配符的那个胜出。
  3. 被通配符匹配的URI字符串的字串可以用{1}来引用。下面例子:《深入浅出struts2》--第三章,动作与结果_第4张图片
  4. 允许使用多个通配符:看例子:《深入浅出struts2》--第三章,动作与结果_第5张图片

你可能感兴趣的:(《深入浅出struts2》--第三章,动作与结果)