一般,我们的web应用都是只有在用户登录之后才允许操作的,也就是说我们不允许非登录认证的用户直接访问某些页面或功能菜单项。我还记得很久以前我的做法:在某个jsp页面中查看session中是否有值(当然,在用户登录逻辑中会将用户名或者用户对象存入session中),如果session中用户信息为空,那么redirect 到登录页面。然后在除了登录页面外的其它所有需要验证用户已登录的页面引入这个jsp 。
比如,我们将检查用户是否登录的代码放入一个jsp页面中,如 checkUser.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
Object username = session.getAttribute("username");
if(null == username){
response.sendRedirect("login.jsp");
}
%>
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登录页面</title>
</head>
<body>
<h1>用户登录</h1>
用户名:<input type="text" name="username" /><br />
密码:<input type="text" name="pwd" />
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<%@ include file="checkUser.jsp" %>
<title>菜单页</title>
</head>
<body>
<h1>菜单1</h1> <br />
<h1>菜单2</h1> <br />
<h1>菜单3</h1> <br />
<h1>菜单4</h1> <br />
</body>
</html>
以上这种方法当然是可行的,可是太过丑陋和麻烦。后来,我学到可以把除了登录页面外的 jsp 或html 页面放到 WEB-INF 目录下, 这样用户就无法直接在浏览器中敲url 来访问页面了。可是,如果有人通过某种方式得知我们的action 名和方法名了呢?难道我们要在action的每个方法中,检查用户是否登录吗?这样子做光是想一想就觉得很蠢。好在我们有struts2 拦截器。
先来看看怎样实现。
我们写一个拦截器类,让它继承 MethodFilterInterceptor。
/**
* @Title: LoginInterceptoe.java
* @Description: 拦截非登录用户请求
* @author ThinkPad
* @version 1.0
* @date 2014年8月2日
*/
package com.exam.interceptor;
import com.exam.utils.Constants;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
/**
* @author ThinkPad
*
*/
public class LoginInterceptor extends MethodFilterInterceptor{
/**
*
*/
private static final long serialVersionUID = -4409507846064552966L;
/* (non-Javadoc)
* @see com.opensymphony.xwork2.interceptor.MethodFilterInterceptor#doIntercept(com.opensymphony.xwork2.ActionInvocation)
*/
@Override
protected String doIntercept(ActionInvocation invoker) throws Exception {
// TODO Auto-generated method stub
Object loginUserName = ActionContext.getContext().getSession().get(Constants.USERNAME);
if(null == loginUserName){
return Constants.VIEW_LOGIN; // 这里返回用户登录页面视图
}
return invoker.invoke();
}
}
<interceptors>
<interceptor name="loginInteceptor" class="com.exam.interceptor.LoginInterceptor" />
<interceptor-stack name="loginStack">
<interceptor-ref name="loginInteceptor">
<param name="excludeMethods">goLogin,login</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="loginStack" />
关于 struts2 拦截器的详细介绍,可以参考这篇文章:http://wenku.baidu.com/link?url=GPQkMm2UkyFeRPMWH7RMTqJD1xVV2DWU90b5FwuNzDQjuAnx300jMePNb1IVgxMkM3dek3Irixm-kuTOmClbSQ8vdyEjRPwmAdXqZOlG_GK
我在这里稍微总结下:
1、在struts2 中,所有的拦截器都会继承 Interceptor 这个接口。
2、拦截器写好之后要在 struts.xml 文件中配置,如果该拦截器是用来拦截某个action的,那么,就在该action 的result 后面放入该拦截器。如(注:来自以上参考文章):
<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>
4、Interceptor 接口有三个方法:init 、 destroy、intercept 。但一般我们不关心 init 和 destroy 方法。所以struts2 为我们提供了一个简化的拦截器类:AbstractInterceptor ,它实现了init 和 destroy 方法,我们只需实现 intercept 方法。
5、关于拦截器栈。可以把拦截器栈看成是一个“大”拦截器,里面由若干个拦截器组成。把它当成一个拦截器一样的引用。
6、方法过滤拦截器,需要继承 MethodFilterInterceptor 类(也就是我们这里示例使用的拦截器类的做法)。你可以指定该拦截器拦截哪些方法(使用<param name="includeMethods">method1,method2</param>
),也可以指定该拦截器不去拦截哪些方法(<param name="excludeMethods">method1,method2</param>)
联系客服