这个功能是这样的,用户在访问网站时,先要进行登录,即要访问处理登录的Action,若没有登录,即访问除了登录的Action之外的Action,则会被拦截器拦截,跳转到错误页面,提示用户还没有进行登录。
所以这个拦截器的作用是如果是登录,即请求的是LoginAction,那么就不拦截这个请求,让其通过拦截器,进行登录如果请求的是别的Action,若在没有进行登录的情况下,那么拦截器就会起作用,跳转到登录页面,进行登录,若是在登录的情况下,则可以通过拦截器,继续下面操作。
实现这个功能的难点主要在如何让拦截器拦截除了LoginAction之外的其他所有Action。解决这个问题的方法有很多种,可以把这个拦截器引用到所有的除了LoginAction之外的Action,但是有点烦。为了简单一点,所以我们可以为所有的Action定义一个默认的拦截器栈。我们知道在struts.xml中定义的所有Action,都有一个默认的拦截器栈,这个默认的拦截器在struts-default.xml中定义。我们可以先自定义一个拦截器栈,把上面那个拦截登录的拦截器放到这个拦截器栈里面,再把原先的默认的拦截器栈放到自定义的这个拦截器栈。然后把这个拦截器栈设置为默认的拦截器栈,这样自定义的拦截器栈就覆盖了以前的默认拦截器栈,相当于在默认的拦截器栈中多了一个拦截登录的拦截器,即实现了对所有的Action进行拦截的目的,但是这样的话,用来处理登录的LoginAction就会被拦截了,而我们不想让这个Action被拦截,所以还必须在拦截器中做一下判断,若当前是LoginAction,则不进行拦截,让其通过,除此之外,若没有登录的,全部进行拦截,若登录了的,就不拦截。
有点乱吧?看一下示例:
LoginAction.java:
package com.suo.actions;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
import com.suo.beans.User;
import com.suo.services.LoginService;
import com.suo.services.LoginServiceImpl;
public class LoginAction extends ActionSupport implements Preparable{
/**
* 实现Preparable接口是为了进行Action类的初始化工作,其中的prepare()方法在execute()之前执行
*/
private String username;
private String password;
private LoginService loginService=new LoginServiceImpl();
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 String execute()
{
if(loginService.isLogin(username, password))
{//判断用户名和密码是否正确
User user=new User();
user.setUsername(username);
user.setPassword(password);
ActionContext.getContext().getSession().put("userInfo", user);//将这个用户的信息,放在session中,表示进行了登录
return SUCCESS;
}
return INPUT;
}
@Override
public void prepare() throws Exception {
System.out.println("prepare invoke !");
}
}
拦截器:
package com.suo.interceptor;
import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.suo.actions.LoginAction2;
public class LoginInterceptor extends AbstractInterceptor {
/**
* 这个拦截器的作用是如果是登录,即请求的是LoginAction2,那么就不拦截这个请求,让其通过拦截器,进行登录
* 如果请求的是别的Action,若在没有进行登录的情况下,那么拦截器就会起作用,跳转到登录页面,进行登录,
* 若是在登录的情况下,则可以通过拦截器,继续下面操作。
*/
@Override
public String intercept(ActionInvocation invocation) throws Exception {
/**
* invocation.getAction()是得到当前访问的Action
*/
if(LoginAction2.class==invocation.getAction().getClass())
{
return invocation.invoke();
}
Map map=invocation.getInvocationContext().getSession();//获得session
if(null==map.get("userInfo"))
{
return Action.LOGIN;
}
return invocation.invoke();
}
}
struts.xml:
<interceptors>
<interceptor name="loginInterceptor" class="com.suo.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="myDefaultStack">
<interceptor-ref name="loginInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myDefaultStack"/><!--覆盖掉原来的默认拦截器,注意,这个要放在interceptors的外面-->
注意,拦截器中,若没有登录,就返回Action.LOGIN,这个返回的结果页面应该是全局的,因为请求被拦截了,还没有进入到Action中,所以不能返回到struts.xml中action中定义的结果页面。