【电信计费系统项目实战】基础篇---登录检查拦截器
拦截器-struts2016-08-11
上一篇中,我们主要了解了如何用map实现登录界面的验证码,这一次,我们将学习登录检查拦截器,用于对资费等业务模块进行登录校验。
在上一篇的登录验证码中,登录成功后,将登录信息记录到Session(第54行),如下:
package com.tarena.action.login;
import org.omg.CORBA.Request;
import com.tarena.action.BaseAction;
import com.tarena.dao.DAOException;
import com.tarena.dao.DAOFactory;
import com.tarena.dao.login.ILoginDAO;
import com.tarena.entity.Admin;
public class LoginAction extends BaseAction {
//input
private String adminCode;
private String password;
private String imageCode;
//output
private String errorMsg;
public String execute() {
//1.校验验证码
String code = (String) session.get("imageCode");
if(code == null ||
!code.equalsIgnoreCase(imageCode)) {
//验证码不匹配,校验失败
errorMsg = "验证码错误!";
return "fail";
}
//2.根据账号查询管理员
ILoginDAO dao = DAOFactory.getLoginDAO();
Admin admin = null;
try {
admin = dao.findByCode(adminCode);
} catch (DAOException e) {
e.printStackTrace();
errorMsg = "查询管理员报错,请联系系统管理员!";
return "fail"; //异常,返回登录页面
}
if(admin == null) {
//3.如果没有对应的管理员,登录失败,账号不存在
errorMsg = "账号不存在!";
return "fail"; //验证失败,回登录页面
} else {
//4.如果有对应管理员,看密码,若密码错误,登录失败
String pwd = admin.getPassword();
if(!pwd.equals(password)) {
errorMsg = "密码错误!";
return "fail"; //验证失败,回登录页面
}
}
//4.登录成功后,将登录信息记录到Session
session.put("admin", adminCode);
return "success"; //成功,去index.jsp
}
public String getAdminCode() {
return adminCode;
}
public void setAdminCode(String adminCode) {
this.adminCode = adminCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getImageCode() {
return imageCode;
}
public void setImageCode(String imageCode) {
this.imageCode = imageCode;
}
}
我们在公共配置包中注册了登录拦截器,这样每个Action都引用了这个拦截器,如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
<!--
定义公共的包,将公共的配置放于此包下,
如果其他package希望使用此包下的内容,
则继承与此包即可。
-->
<package name="netctoss" extends="json-default">
<!-- 注册拦截器 -->
<interceptors>
<!-- 注册登录检查拦截器 -->
<interceptor name="loginInterceptor"
class="com.tarena.interceptor.LoginInterceptor"></interceptor>
<!--
为了引用方便,将登录检查拦截器和默认
拦截器打包成栈
-->
<interceptor-stack name="loginStack">
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!--
指定当前包下Action默认引用的拦截器,
其作用相当于是在此包下每个Action中
都引用了这个拦截器。
-->
<!-- <default-interceptor-ref name="loginStack"/>-->
<!--
定义全局的Result,全局Result可以被当前包下
所有的Action访问。相当于当前包下每个Action
中都写了这个全局Result。
-->
<global-results>
<!-- 踢回登录页面Result -->
<result name="login" type="redirectAction">
<param name="namespace">/login</param>
<param name="actionName">toLogin</param>
</result>
<!-- 转到错误页面Result -->
<result name="error">
/WEB-INF/main/error.jsp
</result>
</global-results>
</package>
</struts>
登录检查拦截器,用于对资费等业务模块进行登录校验
package com.tarena.interceptor;
import java.util.Map;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
/**
* 登录检查拦截器,用于对资费等业务模块进行登录校验
*/
public class LoginInterceptor implements Interceptor {
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation ai)
throws Exception {
Map<String,Object> session =
ai.getInvocationContext().getSession();
//如果登录过,则从session中可以取到admin,否则取不到
Object admin = session.get("admin");
if(admin == null) {
//session中没取到admin,说明没登录过,踢回登录页
return "login"; //通过login找Result转到登录页
} else {
//session中取到admin,说明登录过,可以访问Action
return ai.invoke();
}
}
}
这里有必要说一下struts2 拦截器和actioninvocation(参考这里):
Interceptor的接口定义没有什么特别的地方,除了init和destory方法以外,intercept方法是实现整个拦截器机制的核心方法。而它所依赖的参数ActionInvocation则是我们之前章节中曾经提到过的著名的Action调度者。
我在这里需要指出的是一个很重要的方法invocation.invoke()。这是ActionInvocation中的方法,而ActionInvocation是Action调度者,所以这个方法具备以下2层含义(详细看DefaultActionInvocation源代码):
1. 如果拦截器堆栈中还有其他的Interceptor,那么invocation.invoke()将调用堆栈中下一个Interceptor的执行。
2. 如果拦截器堆栈中只有Action了,那么invocation.invoke()将调用Action执行。
3.