一,动作类
1,规范:
(1),每个属性必须要有get和set方法,并且struts里面非字符串的属性会自动进行数据转换。
(2), 必须要有一个不带参数的构造器。
(3),每个动作类至少要有一个方法供struts在执行动作时进行调用。因为struts会根据这个动作结果选择控制权转移到哪里
(4),同一个动作类可以包含多个动作方法。动作类为不同的动作提供不同的方法
(5),不必考虑线程安全问题,因为struts2会为每个http请求创建一个新动作实例。
(6),struts2不创建httpsession对象,但jsp中默认会。
2,说明:
(1),编写的大多动作类扩展自ActionSupport类,并因此实现了Action接口,从接口中会继承5个静态字段:
(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接口来实现访问资源
调用一个动作时,struts会先检查相关的动作类是否实现了ServletContextAware接口,如果实现了,strut2将先调用动作的setServletContext()方法并且传递相应的参数对象,再然后才是填充属性,最后执行动作方法。并且在那个方法里,需要把servletcontext对象赋值给一个对象。(其它两个接口ServletRequestAware和ServletResponseAware的过程类似)
实现这个接口,得到的不是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拦截器栈一份子,因此可以随时使用动作链。
(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)
所有被捕获的异常有exception拦截器负责处理。这个拦截器是defaultStack默认拦截器栈的一份子,每当某个exception-mapping元素捕获一个异常,这个拦截器就会向valueStack栈添加两个对象:
exception,表示被捕获的异常对象
exceptionStack,被捕获异常的栈线索。
那么,视图就可以访问这些异常信息,一般用OGNL表达式访问。
五,通配符映射:
- 多个相似的映射关系简化为一个映射关系
- 如果某个动作存在,则会调用相应的动作。如果某个动作不存在,则会去查找含有通配符的那个动作,如果符合这个带通配符的名字,那么就会执行这个动作。如果符合的带通配符的动作不止一个,则最后一个胜出。如果找到了多个匹配,那么不带通配符的那个胜出。
- 被通配符匹配的URI字符串的字串可以用{1}来引用。下面例子:
- 允许使用多个通配符:看例子: