之前在培训学习中只是学到了关于request的设置session检查来实现登录验证,但是在ssh框架上,在每个页面都要写上那么几句条件语句和显示语句,实在不方便,而且会多了很多不明因素影响,以后关于系统的完善与改善工作,因此验证登录的功能应该放手给拦截器去做,而struts本身就是实现拦截器功能来美化简化开发过程。
事实上,拦截器的学习之路有点坎坷,主要是因为学习的时候,一味的在网上书上找资料,找例子,但是经过一两天的效率低下搜索之后,放弃了。后来又因为在看jsp项目实际开发的书,最后一章看到了希望,我又开始按照书本的例子来编写拦截器,可是,悲催的是,遇到问题有:1.未能拦截成功,2.拦截可以,但是不能实现部分方法避免拦截,3.在添加错误输入页面提示中用了addActionError而破坏了系统的正常操作流程。
anyway,还是说下拦截器的实现吧:
一、首先是建立一个拦截器类实现拦截后的主要功能例如实现“已经登录”的验证,这个在方法体中定义
/* 引入包*/
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
/*继承MethodFilterInterceptor 类,实现action中的方法拦截,因为本身项目内只含有两个action,而方法集成在action中*/
public class LoginInterceptor extends MethodFilterInterceptor {
@Override
public String doIntercept(ActionInvocation arg0) throws Exception {
// System.out.println("interceptor");
/*获取request并拿去session保存的信息,查询信息是否存在,存在则invoke即通过拦截,不存在表明未登录此时拦截器将页面送回登录处,当然在此前是已经是确定session要么存储了登录成功之后的用户名,要么就是妙手空空*/
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
String name = (String)session.getAttribute("userName");
if(name == null){
return "login";
}else{
return arg0.invoke();
}
}
}
二、接下来则是在struts.xml文件中添加标签信息,在package标签内首先添加下列标签:
<interceptors>
<interceptor name="logininterceptor" class="com.changeman.action.LoginInterceptor" />
<interceptor-stack name="logininterceptorStack" >
<interceptor-ref name="defaultStack" />
<interceptor-ref name="logininterceptor" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStack" />
<global-results>
<!-- 下面定义的结果对所有的Action都有效 -->
<result name="login">/index.jsp</result>
<result name="error">/error.jsp</result>
</global-results>
其中interceptor标签是定义拦截器类与名称,interceptor-stack 标签是拦截器栈,可以保存的是多个拦截器,<global-results>定义的是全局~这个不大清楚,注意,这里的defaultStack是必不可少的,因为struts原先已经定义好一些类成员申明,没有defaultStack将会发生一些棘手错误,而且这些错误指示在网页跳转时报错说nullpoint之类的,而在ide上并没有报错。
三、接下来就是很重要的一步了,就是实现拦截器的作用域与作用目标方法:
同样在struts.xml中,在action标签内,添加拦截器属性,来表明此action需要拦截,
<action name="UserAction" class="UserAction" >
<result name="checkUser">/main.jsp</result>
<result name="input">/error.jsp</result>
<interceptor-ref name="defaultStack" />......................................................................(1)
<interceptor-ref name="logininterceptor">
<param name="excludeMethods">checkUser,registerUser</param>.............(2)
</interceptor-ref>
</action>
这里用了两个拦截器,也许有疑问,为什么我上面设置了拦截器栈已经包括了上面两个拦截器,怎么这里还有分出来呢?
“研究”发现,原来是(2)中需要用的param标签是用来定义声明避免拦截的方法,如checkUSer等,是action里面定义的方法,也就是函数,当调用到它时,拦截器就不会去拦截它,因为它是用来验证登录的,没有它,要实现的拦截器功能就没有用了。
(1)则是对应于我上面说的“注意”;这里用stack的话,貌似param就没有用了,也就是exclude不到方法。
搞了半天,最后在科兄的帮助下,弄懂了这个问题!!!特此记录!