`

#对struts框架的理解

阅读更多

struts框架和传统的web应用框架的不同之处?

答:struts2框架的知识点,设计思路就行

Struts的优点:
Struts的优点主要集中体现在两个方面:Taglib和页面导航。
a
、利用Struts提供的taglib可以大大节约开发时间。
b
、维护扩展比较方便。通过一个配置文件,即可把握整个系统各部分之间的联系,这对于后期的维护有着莫大的好处。
c
、表现与逻辑分离
d
、表单验证解决了请求数据的验证问题,增强了系统健壮性。
e
、便于团队开发

Struts
的缺点:
a
、大量的使用标签,对于初学者难度较大。
b
ActionForms使用不便、无法进行单元测试(StrutsTestCase只能用于集成测试)

 

 

 

--------------------------------------------------------------------------------------------------------------------------

 

struts是如何实现MVC框架的?

struts是MVC设计模式的体现 M-model V-view C-control


Struts体系结构:
视图:一组jsp文件。这组jsp文件中既没有业务逻辑,也没有模型信息,只有标签。
模型:表示应用程序的状态和业务逻辑,struts没有提供特定的模型组件,在大型分布式应用程序开发中,业务逻辑通常由JavaBean或ejb组件实现。
控制器:Struts的中枢,由ActionServlet类和Action类实现。ActionServlet在MVc模型中扮演中央控 制器的角色,接收所有客户端得请求,并把请求委派到指定的Action类。Action类负责调用模型的方法,更新模型的状态,并帮助控制应用程序的流程。 

 

 

--------------------------------------------------------------------------------------------------------------------------

                                                      Struts2 拦截器
--------------

Struts2拦截器的配置 参考:http://xinghaifeng2006.iteye.com/blog/652493

 

Struts2框架的大部分功能都是通过拦截器来完成的。默认情况下所以的package都会继承默认的struts-default包,这样就可以使用Struts的大量默认拦截器。


1、自定义全局拦截器

在Struts.xml里增加 <interceptor name="拦截器别名" class="拦截器实现类" >

为其他包引用的方便可以把多个拦截器放在一起,组成拦截器栈:

<interceptor-stack name="拦截器栈别名">

    <interceptor name="拦截器别名1" class="拦截器实现类" > 

    <interceptor name="拦截器别名2" class="拦截器实现类" >

</interceptor-stack>



2、在action中使用拦截器

<action name="" class="" extends="struts-default">

    <interceptor-ref="拦截器栈别名">

</action>



3、配置默认的拦截器(每个包只能定义一个默认拦截器)

当配置一个包后,可以为其指定特定的拦截器。这样如果该包中的ACTION没有配置拦截器,那么默认的拦截器将起作用

<default-interceptor-ref name="拦截器栈别名">



4、实现拦截器需继承AbstractInterceptor类



5、在默认情况下,如何某个Action定义了拦截器,这个拦截器会拦截Action的所以方法,如果不想拦截所以方法,可以使用Struts2的方法过滤特性。

<action name="" class="" extends="struts-default">

   <interceptor-ref="拦截器栈别名">

   <param name="excludeMethods">拦截器别名1,拦截器别名2</param> < ————屏蔽的拦截

   <param name="includeMethods">拦截器别名2</param> <————开启拦截

</action>

6、Struts2拦截器的执行顺序

并不是先配置的先拦截,在execute方法执行前的动作按顺序拦截,在execute方法执行之后的动作逆序执行,也就是说配置在后面的先执行。

 

------------------------------------------

Struts2的拦截器总结:参考:http://www.iteye.com/topic/211161

Struts2 中的拦截器和 servelt 中的过滤器是非常的相似的。如果学过过滤器的话,肯定能够感觉的到,尽管有些微的不同。可是struts2的拦截器到底如何使用呢,为什么会有这些配置呢? 接下来一一来看。
过滤器和拦截器是非常相似的,过滤器 public interface Filter 接口里面有三个方法:

  • init(FilterConfig filterConfig),
  • destroy(),
  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain),

这里面的 doFilter() 方法是最重要的,在 struts2 中  String intercept(ActionInvocation invocation)就相当于此方法。

如何完成一个拦截器呢?在 struts2 中要实现一个接口 这个接口是什么呢?在哪呢?,是否在哪听说过?是 webwork 是我们以前听的最多的关于拦截器的框架, struts2 用了其中一个核心的东西,这个东西在是什么呢?是 xwork 。恩,有了它才可以拦截,好了我们在哪找呢?在 com.opensymphony.xwork2.interceptor 中找,里面有个 Interceptor 这是个接口,里面也有三个方法,有 init, destroy 和 intercept 三个方法,而在 struts2 里面的所有的拦截器都继承这个接口!

 

实现如下:

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

public class MyInterceptor implements Interceptor{
    private String hello;//一定要写,后面会用上
   //  get和set方法
    
    public void init() {
       System.out.println("init");
    }
    
    public String intercept(ActionInvocation invoker) throws Exception {
       System.out.println("intercept");

       String result=invoker.invoke();  //执行下一个拦截器

       return result;
    }
    
    public void destroy() {
       System.out.println("destory");
    }
}

 

为了看这些是怎么实现的,加入了一些打印!

intercept 方法返回一个字符串,这个里面最重要的是 ActionInvocation 也是个抽象的接口,里面有个 invoke() 方法 
作用:Invokes the next step in processing this ActionInvocation. 即调用下一个拦截器,如果有的话!

拦截器进行了实现,但是如何让struts2知道我们写了个拦截器呢,此时必须在struts.xml中配置一下。如下所示:

<struts>
   <package name="struts2" extends="struts-default">
      <interceptors>
         <interceptor name="myinterceptor" class="com.interceptor.MyInterceptor">
              <param name="hello">world</param>
         </interceptor>
      </interceptors>
   </package>
<struts>

 

这里为了测试,用了一个注册页面register.jsp 和 RegisterAction

 

<action name="register" class="com.test.action.RegisterAction" >
      <result name="input">/register.jsp</result>
      <result name="success">/success.jsp</result>
</action>

 

好了到了这里 拦截器也配置好了,但是拦截器是拦截 action 的,怎么才能让 action 被拦截呢?
一般的情况下,放在 result 后面,具体如下:

<interceptor-ref name="myinterceptor"></interceptor-ref>

 

将上面的配置整合起来就是:

<struts>
   <package name="struts2" extends="struts-default">
      <interceptors>
         <interceptor name="myinterceptor" class="com.interceptor.MyInterceptor">
              <param name="hello">world</param>
         </interceptor>
      </interceptors>

      <action name="register" class="com.test.action.RegisterAction" >
         <result name="input">/register.jsp</result>
         <result name="success">/success.jsp</result>
         <interceptor-ref name="myinterceptor"></interceptor-ref>
      </action>
   </package>
<struts>

 

这样就可以让 Aciton 被拦截了,到此,好了,可以运行程序了:
输出结果是:启动服务器 init 被打出
运行后提交 action 输出 intercept

这个就是初步的一个拦截器。

 

 

==============

 

在此可能出现一个问题,是什么呢?如果就我们做的注册程序而言,可以想一下,有数据转换,有数据校验,以前当转换和校验不符合的时候,点击提交,会提示相关错误信息,然而,此时当转换和校验依然不符合要求时,点击提交,却不会提示错误信息,为什么呢?
====
当然你答对了,这些功能都包含在struts2的默认拦截器中,这里没执行是被添加的拦截器myinterceptor取代了。

为了查明原因可以查看一下struts2-core-2.xx.jar中的struts-default.xml 这个文件
这里定义的很多的东西,和我们的程序相关的非常紧密
首先这里有个
<package name="struts-default" abstract="true">...</package> 和 struts.xml 里面的
<package name="struts2" extends="struts-default">...</package>有什么关系呢?很明显可以猜到 struts.xml 继承的就是 struts-default.xml中的包 struts-default。

 


这个里面还看到<interceptors></interceptors>标签,这个是定义拦截器栈的,仔细看可以发现里面有个validation 如此可以猜想,validation 也是定义的一个拦截器,猜想当注册信息出错后没有提示信息呢?肯定是相关的验证功能没有执行,以前的执行了,现在没执行,这样说明了,是现有的拦截器取代了原有的拦截器,这个是我仅能想到的!那么我们手工把原来的默认拦截器加入,这样可以吗?
答案是可以的!添加如下!

 

接着上面result后面添加一个吧!

<interceptor-ref name="defaultStack"></interceptor-ref>

 

这也说明一个问题:如果我们没有添加拦截器的话,struts2会给我们添加默认拦截器为什么加这句话呢?是因为在package 中定义了<default-interceptor-ref name="defaultStack"/> 这句话的意思是将defaultStack定义为默认的拦截器

最后配置如下:

<action name="register" class="com.test.action.RegisterAction" >
     <result name="input">/register.jsp</result>
     <result name="success">/success.jsp</result>
     <interceptor-ref name="myinterceptor"></interceptor-ref>
     <interceptor-ref name="defaultStack"></interceptor-ref>
</action>

 

为拦截器添加参数
好了,到了这里,让我们来处理上面为myinterceptor拦截器添加的参数问题吧

<param name="hello">world</param>

 
这里我们可以通过配置文件,给拦截器添加一个参数,那这个在拦截器中怎么取得的呢?
了解过滤器的朋友都知道,里面有个init(FilterConfig filterConfig)方法在这里可以取值,而在struts2中没有这么麻烦,做法吗,上面其实已经给出来了!
private String hello;    get和set方法
写个变量,然后加上get和set方法,当然变量的名字必须和设定的参数是相同的,这个是赋值成功的前提条件

此时,运行,在整个拦截器中任何方法中运行 System.out.println(hello);成功输出: world  
这里的参数使用是在定义拦截器的时候,还有一种是在使用拦截器的时候添加参数。如下:
1. 定义拦截器的时候添加参数:

<interceptor name="myinterceptor" class="com.interceptor.MyInterceptor">
    <param name="hello">world</param>
</interceptor>

 

2. 使用拦截器的时候添加参数:

<interceptor-ref name="myinterceptor">
     <param name="hello">zhuxinyu</param>
</interceptor-ref>

 

这下知道了吗,可是还有个问题,在定义的时候添加了参数hello,使用时同样添加了参数param,当运行MyInterceptor类时会输出哪个呢? world 还是 zhuxinyu。
结果是:zhuxinyu  很明显,覆盖了第一个,这是什么原则:就近原则。形如 OO 中的覆盖,重写。


好了,把这些零散的东西搞完了,真的开始解决更多的知识!

拦截器栈,在struts2里面,其实是把拦截器和拦截器栈一样的对待。可以把拦截器栈当作一个拦截器看待,同样的引用。
现在定义一个拦截器栈把!

同样在<interceptors> </interceptors>里面定义:

<interceptor-stack name="mystack">
     <interceptor-ref name="myinterceptor"></interceptor-ref>
     <interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>

 
看见了没,一个引用第一次定义的myinterceptor拦截器,一个引用默认的拦截器,怎么引用呢,和开始的一个样,呵呵!

 

 

当然我们也可以自己定义一个默认的拦截器,这样在程序中怎么做呢?呵呵,定义如下:

<default-interceptor-ref name="mystack"></default-interceptor-ref>

这里引用的就是上面的mystack拦截器,这样在程序中如果不在action中加入拦截器,它同样可以执行相应的工作,
前面已经说过了,如果不加入任何拦截器的引用,它将把默认的拦截器加入。

 

 

拦截器栈
过滤器可以组成过滤器链,就是可以有多个过滤器来去过滤一个组件,拦截器也是,只不过是叫拦截器栈(相当于拦截器链)。
拦截器栈先把拦截器逐个执行,接着执行action方法,之后又按照相反的顺序回到最后的一个拦截器,再回到视图。

拦截器栈是怎么构成的呢?继续看struts-default.xml这个文件!里面有这些东西:

<interceptor-stack name="defaultStack">
       <interceptor-ref name="static-params"/>
       <interceptor-ref name="params"/>
       <interceptor-ref name="conversionError"/>
</interceptor-stack>

<interceptor-stack name="validationWorkflowStack">
        <interceptor-ref name="defaultStack"/>
        <interceptor-ref name="validation"/>
        <interceptor-ref name="workflow"/>
</interceptor-stack>

 

这里面看见了 栈是什么样的结构,是由很多个预先定义好的拦截器构成,而且也可以再加上拦截器栈组成,就如此就组成了!

AbstractInterceptor 拦截器
我们在做拦截器的时候,刚才实现了Interceptor接口,里面有三个方法,但是一般的情况下init() 和 destroy() 方法我们用不上,最关心的就是intercept(ActionInvocation invoker){}方法,所以怎么办呢?其实,struts2给我们提供了一个简化的拦截器类:AbstractInterceptor

AbstractInterceptor 这是一个抽象的类,里面实现了 init() 和 destroy() 方法,所以只要我们继承这个类,就不用再多写这两个方法!

具体实现如下:

public class MyInterceptor2 extends AbstractInterceptor{ 
  protected String doIntercept(ActionInvocation invocation) throws Exception {

       System.out.println("my interceptor2");

       String result=invocation.invoke();

       return result;
    }
}

 

如此一来写的更加少了,其它的配置方法不变。

当然在这里还需要指出一点,你安放的拦截器的顺序,其实也就是拦截器执行的顺序!但是拦截器,不只是在执行execute()方法之前要执行,而且在execute()方法之后也要执行。给出如下两个拦截器说明:

1.

public String intercept(ActionInvocation invoker) throws Exception {
       System.out.println("intercept1");
       String result = invoker.invoke();
       System.out.println("finish1");
       return result;
}

 2.

public String intercept(ActionInvocation invoker) throws Exception {
       System.out.println("intercept2");
       String result = invoker.invoke();
       System.out.println("finish2");
       return result;
}

 

在配置顺序也是一二,结果会输出什么呢?

intercept1  intercept2 finish2  finish1  这里执行拦截器的过程是正着来的,回来的时候是反着的。就像你要进一个很多门的房间一样。进去一个,开一个门,为了让自己能回来的方便一些,这个打开的门就不要关着了,当你把所有的门进去了后,然后回来,再逐个关门。这样的过程就像是这个拦截器执行的过程。

最后讲一个方法过滤拦截器,顾名思义,过滤的是方法。其实在struts2中可以在一个action类中写很多个与aciton的execute方法类似的方法。
只要在struts.xml中的action添加一个属性就可以了这个属性是method比如: 

<action name="register"class="com.test.action.RegisterAction" method="test">

 

当然在action类中也有个 test() 方法

这个拦截器可以细化到拦截到具体的哪一个方法。如果不是方法过滤拦截器 哪么它可能将与execute()方法类似的方法都执行。
比如说上面的test()方法。如此这样照成很多的不必要。于是这种拦截器就显的格外的重要。在这个类继承后实现的不是inteceptor()方法而是doIntercept(),可是做好这个类后如何配置继承MethodFilterInterceptor这个类呢?
如下(为了实现过滤方法加入了几个参数,其他的都相同): 

<interceptor-ref name="myinterceptor2">
              <param name="includeMethods">execute,test</param>
</interceptor-ref>

 

includeMethods  包含execute,test这两个方法,结果执行了这个拦截器,如果改成excludeMethods ,就不会执行了,也可以再加下面的一个参数
<param name="excludeMethods">execute,test</param>
不排除execute,test这两个方法 可是又加入又排除到底执行吗?答案是执行的,必定结果是最能说明问题的!呵呵! 

 

 

-----------------------------------

 

参考:http://www.iteye.com/topic/149260

在jsp servlet中我们通常使用Servlet Filter控制用户是否登入, 是否有权限转到某个页面。在struts2中我们应该会想到他的拦截器(Interceptor), Interceptor在struts2中起着非常重要的作用。 很多struts2中的功能都是使用Interceptor实现的。

需求:简单的登入界面,让用户输入用户名、密码、记住密码(remember me)。 如果用户选中remember me的话, 下次就不需要再登入了(使用cookie实现, 用需要点击logout取消remeber me功能)。 如果用户起始输入的地址不是登入页面的话,在用户登入之后需要转到用户输入的起始地址。

我们先看看LoginInterceptor.java

package com.javaeye.dengyin2000.wallet.interceptor;

import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.StrutsStatics;

import com.javaeye.dengyin2000.wallet.dao.UserDAO;
import com.javaeye.dengyin2000.wallet.dao.UserNotFoundException;
import com.javaeye.dengyin2000.wallet.domains.User;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class LoginInterceptor extends AbstractInterceptor {
	public static final String USER_SESSION_KEY="wallet.session.user";
	public static final String COOKIE_REMEMBERME_KEY="wallet.cookie.rememberme";
	public static final String GOING_TO_URL_KEY="GOING_TO";
	
	private UserDAO userDao;

	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		
		ActionContext actionContext = invocation.getInvocationContext();
		HttpServletRequest request= (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
		
		Map session = actionContext.getSession();
		if (session != null && session.get(USER_SESSION_KEY) != null){
			return invocation.invoke();
		}
		
		Cookie[] cookies = request.getCookies();
		if (cookies!=null) {
			for (Cookie cookie : cookies) {
				if (COOKIE_REMEMBERME_KEY.equals(cookie.getName())) {
					String value = cookie.getValue();
					if (StringUtils.isNotBlank(value)) {
						String[] split = value.split("==");
						String userName = split[0];
						String password = split[1];
						try {
							User user = userDao
									.attemptLogin(userName, password);
							session.put(USER_SESSION_KEY, user);
						} catch (UserNotFoundException e) {
							setGoingToURL(session, invocation);
							return "login";
						}
					} else {
						setGoingToURL(session, invocation);
						return "login";
					}
					return invocation.invoke();
				}
			}
		}
		setGoingToURL(session, invocation);
		return "login";
	}

	private void setGoingToURL(Map session, ActionInvocation invocation){
		String url = "";
		String namespace = invocation.getProxy().getNamespace();
		if (StringUtils.isNotBlank(namespace) && !namespace.equals("/")){
			url = url + namespace;
		}
		String actionName = invocation.getProxy().getActionName();
		if (StringUtils.isNotBlank(actionName)){
			url = url + "/" + actionName + ".action";
		}
		session.put(GOING_TO_URL_KEY, url);
	}
	
	public UserDAO getUserDao() {
		return userDao;
	}

	public void setUserDao(UserDAO userDao) {
		this.userDao = userDao;
	}

}



首先判断session中有没有用户信息, 如果有的话继续, 如果没有的话,检查cookie中有没有rememberme的值,如果有的话,用==分割, 取得用户名密码进行登入。如果没有这个用户的话,记录下request的action地址然后转到登入页面。如果验证有这个用户,则继续下面的interceptor。 如果cookie中没有信息的话,则记录request的action地址然后转到登入页面。  以上就是LoginInterceptor的全部代码。

下面我们看看struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC 
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
	<package name="default" extends="struts-default">
		<interceptors>
			<interceptor name="loginInterceptor" class="loginInterceptor"></interceptor>
			<interceptor-stack name="loginDefaultStack">
				<interceptor-ref name="loginInterceptor"></interceptor-ref>
				<interceptor-ref name="defaultStack"></interceptor-ref>
			</interceptor-stack>
		</interceptors>
		<default-interceptor-ref name="loginDefaultStack"></default-interceptor-ref>
		<global-results>
			<result name="login" type="redirect">/login.jsp</result>
		</global-results>		
		<action name="index" class="indexAction">
			<result>/index.jsp</result>
		</action>
		<action name="logout" class="logoutAction"></action>
		
		<action name="login" class="loginAction" method="login">
			<result type="redirect">${goingToURL}</result>
			<result name="input">/login.jsp</result>
			<interceptor-ref name="defaultStack"></interceptor-ref>
		</action>
		
		<action name="register" class="registerAction">
			<result type="redirect">/login.jsp</result>
			<result name="input">/register.jsp</result>
			<interceptor-ref name="defaultStack"></interceptor-ref>
		</action>
	</package>
</struts>



我们是使用的默认的interceptor stack是loginInterceptor, 如果你需要让不登入的用户也能访问的话,你需要配置你的action使用defaultStack。 我们这里的login, register使用的就是defaultStack。 这里要注意的是success的result是我们用LoginInterceptor设过来的值。 这样我们就能够转到用户输入的起始页面。 下面我们再来看看login.jsp 和 loginAction

<%@taglib prefix="s" uri="/struts-tags" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Wallet-Login</title>
</head>
<body>
<h2>Login</h2> 
<s:actionmessage/>
<s:actionerror/>
<s:form action="login" method="post" validate="false" theme="xhtml">
<s:textfield name="loginName" label="Username"></s:textfield><br/>
<s:password name="password" label="Password"></s:password><br/>
<s:checkbox label="Remember Me" name="rememberMe"></s:checkbox>
<s:submit value="%{'Login'}"></s:submit> 
</s:form>
<a href="register.jsp">Register</a>
</body>
</html>



 

package com.javaeye.dengyin2000.wallet.actions;

import java.util.Map;

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

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.interceptor.CookiesAware;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;

import com.javaeye.dengyin2000.wallet.dao.UserDAO;
import com.javaeye.dengyin2000.wallet.dao.UserNotFoundException;
import com.javaeye.dengyin2000.wallet.domains.User;
import com.javaeye.dengyin2000.wallet.interceptor.LoginInterceptor;
import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport implements ServletResponseAware, ServletRequestAware, SessionAware, CookiesAware{

	private UserDAO userDao;
	private String loginName;
	private String password;
	private boolean rememberMe;
	private HttpServletResponse response;
	private HttpServletRequest request;
	private Map session;
	private Map cookies;
	private String goingToURL;
	public String getGoingToURL() {
		return goingToURL;
	}
	public void setGoingToURL(String goingToURL) {
		this.goingToURL = goingToURL;
	}
	public boolean isRememberMe() {
		return rememberMe;
	}
	public void setRememberMe(boolean rememberMe) {
		this.rememberMe = rememberMe;
	}
	public String getLoginName() {
		return loginName;
	}
	public void setLoginName(String loginName) {
		this.loginName = loginName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	
	
	public String login()throws Exception{
		try {
			User user = userDao.attemptLogin(loginName, password);
			if (rememberMe){
				Cookie cookie = new Cookie(LoginInterceptor.COOKIE_REMEMBERME_KEY, user.getLoginName() + "==" + user.getPassword());
				cookie.setMaxAge(60 * 60 * 24 * 14);
				response.addCookie(cookie);
			}
			session.put(LoginInterceptor.USER_SESSION_KEY, user);
			String goingToURL = (String) session.get(LoginInterceptor.GOING_TO_URL_KEY);
			if (StringUtils.isNotBlank(goingToURL)){
				setGoingToURL(goingToURL);
				session.remove(LoginInterceptor.GOING_TO_URL_KEY);
			}else{
				setGoingToURL("index.action");
			}
			return SUCCESS;
		} catch (UserNotFoundException e) {
			addActionMessage("user name or password is not corrected.");
			return INPUT;
		}
	}
	public UserDAO getUserDao() {
		return userDao;
	}
	public void setUserDao(UserDAO userDao) {
		this.userDao = userDao;
	}
	public void setServletResponse(HttpServletResponse response) {
		this.response = response;
	}
	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
	}
	public void setSession(Map session) {
		this.session = session;
	}
	public void setCookiesMap(Map cookies) {
		this.cookies = cookies;
	}
}



差不多就是这么多代码了。 最后看看logoutAction

package com.javaeye.dengyin2000.wallet.actions;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;

import com.javaeye.dengyin2000.wallet.interceptor.LoginInterceptor;
import com.opensymphony.xwork2.ActionSupport;

public class LogoutAction extends ActionSupport implements ServletRequestAware , ServletResponseAware{

	private HttpServletRequest request;
	private HttpServletResponse response;

	public String execute() throws Exception{
		HttpSession session = request.getSession(false);
		if (session!=null)
			session.removeAttribute(LoginInterceptor.USER_SESSION_KEY);
		
		Cookie[] cookies = request.getCookies();
		if (cookies!=null) {
			for (Cookie cookie : cookies) {
				if (LoginInterceptor.COOKIE_REMEMBERME_KEY.equals(cookie
						.getName())) {
					cookie.setValue("");
					cookie.setMaxAge(0);
					response.addCookie(cookie);
					return "login";
				}
			}
		}
		return "login";
	}

	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
	}

	public void setServletResponse(HttpServletResponse response) {
		this.response = response;
	}

}



这里需要注意的是需要把cookie也清理下。

applicationContext-struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC 
	"-//SPRING//DTD BEAN//EN" 
	"http://www.springframework.org/dtd/spring-beans.dtd">
	
<beans>
	<!-- Example of SAF2 action instantiated by Spring -->
    <!-- bean id="helloWorldAction" class="tutorial.HelloWorldAction" singleton="false" />
     -->
     <bean id="indexAction" class="com.javaeye.dengyin2000.wallet.actions.IndexAction" singleton="false"></bean>
     <bean id="loginAction" class="com.javaeye.dengyin2000.wallet.actions.LoginAction" singleton="false">
     	<property name="userDao" ref="userDao" />
     </bean>
     
     <bean id="logoutAction" class="com.javaeye.dengyin2000.wallet.actions.LogoutAction" singleton="false"></bean>
     
     <bean id="registerAction" class="com.javaeye.dengyin2000.wallet.actions.RegisterAction" singleton="false"></bean>
     
     <!-- the following is struts2 interceptors -->
     <bean id="loginInterceptor" class="com.javaeye.dengyin2000.wallet.interceptor.LoginInterceptor">
     	<property name="userDao" ref="userDao" />
     </bean>
     
     <bean id="userDao" class="com.javaeye.dengyin2000.wallet.dao.UserDAOImpl">
     </bean>
</beans>




参考:http://www.vitarara.org/cms/struts_2_cookbook/creating_a_login_interceptor


------------------------------------------------------------------------------------------------------


Struts2是如何实现表单验证的?
参考:
http://molisa.iteye.com/blog/358162
http://wenku.baidu.com/view/eb298b6648d7c1c708a14548.html

struts2 校验框架

validate方法实现校验的原理:
程序执行到Action的时候,先判断有没有validate方法,如果实现了先执行validate,再执行execute.如果没有就直接执行execute


struts框架的校验原理:
程序执行到Action时,但是还没有执行到里面的方法时将其拦截,转而执行校验器,校验器执行完毕后返回继续执行Action 。
所以要先做两件事:
1.配置拦截器(让Action暂停,执行校验部分)
2.配置校验器(通过配置文件找到对应的校验器以实现校验器功能)

校验器分为:字段校验器(field-specific FieldValidator),普通校验器(PlainValidator)
非字段校验器(Non-Field Validator)可以配置字段校验器和普通校验器
字段校验方式只能配置字段校验器

给Action的字段配置校验器,比如LogginAction.java里有属性username和password,配置文件LogginAction-validation.xml里对两个字段

进行配置:
<validators>
#字段方式
<field name="username">
<field-validator type="requiredstring">
<message>no null</message>
</field-validator>
</field>

#非字段方式
Java代码
<validator>
<validator type="requiredstring">
#param在申明变通校验器的时候不是必须的,因为普通校验器只返回actionerror(Action级错误)
<param name="fieldName">passeword</param>
<message>password empty.</message>
<validator/>
</validator>
t;/vaildators>

<validator>
<validator type="requiredstring">
#param在申明变通校验器的时候不是必须的,因为普通校验器只返回actionerror(Action级错误)
<param name="fieldName">passeword</param>
<message>password empty.</message>
<validator/>
</validator>
</vaildators>


struts提供的校验器有:
required
requirestring
int
date

expression #普通校验器,只能在字段校验方式下使用
fieldexpression
email
url
visitor
conversion
stringlength
reqex


visistor ,short-circuiting validator可在字段和非字段方式下使用

断路校验器的使用:

非字段校验方式:

<validator type="requiredstring" short-circuit="true">
<param name="fieldName">age</param>
<message>not null</messgae>
</vlidator>

<validator type="requiredstring" short-circuit="true">
<param name="fieldName">age</param>
<message>not null</messgae>
</vlidator>

字段校验方式:

<field name="confirm">
<field-validator type="requiredstring" short-circuit="true">
<param name="expression">(password==confirm)</param>
<message><![CDATA[confirm must be the same as the the password....]]></message>
</field-validator>
</field>

<field name="confirm">
<field-validator type="requiredstring" short-circuit="true">
<param name="expression">(password==confirm)</param>
<message><![CDATA[confirm must be the same as the the password....]]></message>
</field-validator>
</field>

 

struts2校验框架的使用,并不需要在struts配置文件中配置,有点ror中约定替代配置的味道。还是使用上节的例子,TestAction在struts中的配置文件如下:

<package name="struts_crud" extends="struts-default" namespace="/test"> 
  <action name="List" class="com.yangqiang.strutsdemo.web.TestAction" method="list"> 
        <result>list.jsp</result> 
  </action> 
  <action name="Edit" class="com.yangqiang.strutsdemo.web.TestAction" method="load"> 
        <result>edit.jsp</result> 
  </action> 
  <action name="Store" class="com.yangqiang.strutsdemo.web.TestAction" method="store"> 
     <result name="input" type="dispatcher">edit.jsp</result> 
     <result type="redirect">List.action</result> 
  </action> 
  <action name="Remove" class="com.yangqiang.strutsdemo.web.TestAction" method="remove"> 
     <result type="redirect">List.action</result> 
  </action> 
</package> 


首先需要注意的是,数据校验的文件也必须和该Action的存放位置一致,即放在”com.yangqiang.strutsdemo.web“下,xml 的命名规则如下 Action类名-validation.xml(例如:TestAction-validation.xml),如果只是对某个action的数据校验,那么命名规则即为:Action类名-别名-validation.xml (例如:TestAction-Store-validation.xml)即调用Store方法时进行数据检验[注意,这里使用action别名命名数据校验配置文件非常有用,我在系统中就只是使用了TestAction-Store-validation.xml,在这种情况下我只给Store action配置了”input“ result。如果使用TestAction-validation.xml,使用上面的struts.xml,打开调用List,Edit,Remove这三个action的页面时,就会报“没有定义input result”的错误]
其次,看看TestAction-Store-validation.xml文件内容: 

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE validators PUBLIC 
"-//OpenSymphony Group//XWork Validator 1.0//EN" 
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> 
<validators> 
   <field name ="test.name" > 
      <field-validator type ="requiredstring"> 
         <message key = "test.name"/> 
      </field-validator> 
   </field > 
   <field name="test.name"> 
      <field-validator type="stringlength"> 
         <param name="maxLength">100</param> 
         <param name="minLength">5</param> 
         <param name="trim">true</param> 
         <message>必须5-100之内的字符长度</message> 
      </field-validator> 
   </field> 
   <field name ="test.author" > 
      <field-validator type ="requiredstring"> 
         <message> 作者不能为空! </message> 
      </field-validator> 
   </field > 
</validators > 
  

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              

 

 

参考:http://wenku.baidu.com/view/64ad2131b90d6c85ec3ac6b8.html 

------------------------------------------------------------------------------------------------------

Struts2 的重定向:
参考: http://fengzgxing.iteye.com/blog/376296

 

在struts2中,重定向要在struts.xml中配置:

<action name="login" class="LoginAction"> 

    <result name="success" type="velocity">/pages/logok.vm</result> 
    <result name="redirect_1" type="redirect">showInfo.do</result> 
    <result name="redirect_2" type="redirect">showInfo.do?name=yangzi</result> 
    <result name="redirect_3" type="redirect">showInfo.do?name=${name}</result> 
    <result name="redirect_4" type= "redirect"> 
         <param name="actionName">showInfo</param> 
         <param name="name">${name}</param> 
    </result> 

</action> 
 

对应的LoginAction:
public class LoginAction extends ActionSupport{ 
	String name; 
	public String getName() { 
		return name; 
	} 
	public void setName(String name) { 
		this.name = name; 
	} 


	public String execute() throws Exception { 

		//一些处理…… 

		name=xiaowang ; //给要传递的参数赋值 

		return SUCCESS; //默认页面 

		//return "redirect_1" ; //重定向(不带参数) showInfo.do 

		//return "redirect_2" ; //重定向(带固定参数yangzi) showInfo.do?name=yangzi 

		//重定向(带动态参数,根据struts.xml的配置将${name}赋值为xiaowang)最后为 showInfo.do?name=xiaowang 
		// return "redirect_3" ; 

		//return "redirect_4" ; //这个是重定向到 一个action 

	} 

} 
 


说明

struts2 重定向分重定向到url和重定向到一个action。
实现重定向,需在struts.xml中定义返回结果类型。
type="redirect" 是重定向到一个URL。type="redirect-action" 是重定向到一个action。
参数也是在这里指定,action中所做的就是给参数赋值,并return 这个结果。
个人认为:由于大家极度抱怨“action臃肿”,所以struts2中尽量减少了action中的代码

 
------------------------------------------------------------------------------------------------------

                                                                  Struts2 标签





















































































 

 

 

 

 

struts框架是如果实现对servlet的封装的?即struts的中心控制器的机制是什么?

 

参考:1.2的自己查资料+总结:

Struts1.2 控制流程

关键还是要自己了解透彻。现总结如下。供参考:

Struts1.2依然是应用很广的框架,熟悉其基本的控制流程是必要的:


一、ActionServlet的初始化

ActionServlet作为Struts组件的前端控制器,由于web.xml的相应配置:

<load-on-startup>0 </load-on-startup>

在应用一加载时即会被实例化并调用其init方法,init方法所做的主要工作有二:

1. 加载struts配置文件,并创建用于封装配置信息的ModuleConfig对象
2. 加载资源文件,并创建用于封装资源文件的MessageResources对象
需要注意两点:如果web.xml有多模块配置,将创建多个ModuleConfig对象和MessageResources对象分别用于封装各个模块的struts配置文件和资源文件。
针对各个模块所创建的ModuleConfig对象和MessageResources对象将存储在ServletContext中,对应的属性名中有该模块名称的相应标识。
另外,如果有相应配置的话,init方法还将初始化数据源和PlugIn


二、ActionServlet的process

所有形如*.do的请求(根据web.xml中的相关配置)将提交给ActionServlet,最终将调用其process方法。process方法的主要工作有三:

1. 根据请求信息获知所请求的模块名称,从ServletContext中获得与请求模块对应的的ModuleConfig对象,并存储到request中。
2. 根据模块信息获得相应的RequestProcessor对象,一个模块对应一个RequestProcessor对象,RequestProcessor对象将关联与所属模块对应的ModuleConfig对象。
3. 调用RequestProcessor对象的process方法,将request和response作为参数传递给它。


三、RequestProcessor的process

RequestProcessor对象的process方法的主要工作有五步:

1. 调用自己的 processPreprocess(request, response)方法,该方法不进行任何操作,用于子类重写扩展其功能。
2. 获得与请求地址所匹配的ActionMapping对象,AcionMapping对象用于封装一个特定acion的配置信息。
3. 根据ActionMapping中的配置信息获得ActionForm对象(该对象将缓存到request或session中),并将表单数据填充到ActionForm中,然后根据ActionMapping的配置决定是否验证ActionForm,如果验证,将调用ActionForm的validate方法,若其返回的ActionErros对象中包含ActionMessage对象则表示验证失败,将转向action配置信息input属性所指示的地址。
4. 如果ActionForm无需验证或验证通过将创建并缓存与请求地址匹配的Action对象,将ActionMapping对象、ActionForm对象、request和response作为参数调用其execute方法。
5. 根据Action对象的execute方法返回的ActionForward对象,将请求转发或重定向到该ActionForward所封装的地址。

 

 

 

分享到:
评论

相关推荐

    学生管理的Struts框架开发实例

    一个有关学生管理的Struts框架开发的实例,想学习struts框架的可以参考一下,实例比较简单易懂,很容易理解struts框架的精髓。

    深入理解struts2原理之自己实现struts2框架源码

    作为struts2的初学者,有时候理解struts框架的原理,网上看图会一头雾水,所以要是能自己体会实现struts框架的整个过程,对理解struts思路会更加清晰一些,这个源码就是自己实现的过程,代码有详细注释

    重构mvc实现struts框架

    以一个简单mvc模型开始,一步步重构,封装,最终实现struts的雏形,更加深入的理解struts的基本思想

    Struts 2 自定义MVC 框架

    为更好的了解struts2的框架的原理 自定义框架 去更好的理解和认识struts

    谈谈你对Struts的理解。

    1. struts是一个按MVC模式设计的Web层框架,其实它就是一个大大的servlet,这个Servlet名为ActionServlet,或是ActionServlet的子类。我们可以在web.xml文件中将符合某种特征的所有请求交给这个Servlet处理,这个...

    JSPssh投票管理系统MVC设计模式,采用STRUTS框架、HIBERNATE框架

    本系统运用MVC设计模式,采用STRUTS框架、HIBERNATE框架相结合的面向对象的开发方法,采用JSP作为显示页面综合运用标签语言,以MYSQL做为后台数据库 应用技术:java|jsp+ mysql 开发工具:Myeclipse或Eclipse、jdk、...

    struts框架详细介绍

    struts框架的精辟简介,重点突出,理解到位,是一份不可多得的教程。

    struts框架个人留言本系统

    采用JSP+JDBC+Struts实现的简易留言本功能系统 该系统简单的实现了登陆、注册、留言功能 没有什么技术含量,不过通过该系统,能够很好的理解Struts框架。 希望对大家有用!

    JSPssh物流便利店管理系统采用STRUTS框架、HIBERNATE框架ssh框架 MVC模式

    本系统运用MVC设计模式,采用STRUTS框架、HIBERNATE框架相结合的面向对象的开发方法,采用JSP作为显示页面综合运用标签语言,以MYSQL做为后台数据库 应用技术:java|jsp+ mysql 开发工具:Myeclipse或Eclipse、jdk、...

    struts+hibernate+spring框架理解

    struts+hibernate+spring框架理解,总结资料,从各处整理来,希望对大家有帮助。

    struts2框架搭建

    功能:1、第一种方式是原始的struts2框架,struts.xml在src下 2、第二、三种方式主要增加的是动态调用(第三种方式推荐使用),struts.xml放在src下 3、第四种方式struts.xml放在src下某一目录的子目录下面,方便...

    struts框架做的登录 注册 用户列表

    struts框架做的登录 注册 用户列表模块很好理解的 数据库用的是Oracle 用于练习参考相当不错

    struts-2.3.16.1.zip

    Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。struts-2.3.16.1.zip就是struts2.3的一个版本...

    spring_hibernate_struts2的理解

    这是对spring_hibernate_struts2的理解,可以在面试中简要的抓住重点进行陈述。

    Struts2框架实例

    代码,Structs相关实例,用于理解Structs。

    Struts2视频教程

    Struts2是一套非常优秀的Java WEB应用框架,实现优雅、功能强大、使用简洁。目前已有大量的企业项目采用Struts2来...学习完本视频,你会真正理解Struts2相对于Struts1的优雅和简洁,并使你具备开发Struts2项目的能力。

    J2EE基础:MVC模式和Struts模式的理解

    详细介绍了java web开发的model2模式即mvc模式的理论,以及mvc框架struts框架的理解

    strus2特种设备信息管理系统struts2框架 MVC模式应用技术:java|jsp+ mysql

    JSP strus2特种设备信息管理系统 是一套完善的WEB设计系统,对理解JSP java 编程开发语言有帮助,系统采用struts2框架 MVC模式进行开发,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 应用技术:java|...

    struts2校园信息系统采用struts2框架 MVC模式 mysql

    JSP strus2校园信息系统 是一套完善的WEB设计系统,对理解JSP java 编程开发语言有帮助,系统采用struts2框架 MVC模式进行开发,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。#资源达人分享计划# 应用...

    开发自己一套struts框架

    此项目是为了更深入的理解MVC模式以及Struts的工作流程而开发的,运用了第三方commons组件, commons-digester来解析xml文件,把配置信息全部封装成类,然后运用MVC的思想去做相应的操作.

Global site tag (gtag.js) - Google Analytics