一、先来说说在项目中遇到的问题:由于需要对用户权限进行控制,在控制过程中采用的Sturts2的拦截器:为了获得session,我在拦截器类上实现了SessionAware(愚蠢的错误),才开始是想方便,结果怎么也得不到session,相关代码如下:
package edu.cqupt.iactg.helper;
import java.util.Map;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import edu.cqupt.iactg.action.UserAction;
public class UserInterceptor implements Interceptor ,SessionAware{
private Map<String ,Object> session=null;//获得session
private Map<String,Object> session3=null;
public static final String LOGIN="index";//全局返回值
public void destroy() {
System.out.println("拦截器销毁");
}
public void init() {
System.out.println("拦截器加载");
}
public String intercept(ActionInvocation actionInvocation) throws Exception {
System.out.println("进入拦截器");
//如果访问的是登陆acton则不需要对其拦截
if(actionInvocation.getAction() instanceof UserAction){
System.out.println("Useraction=========================");
return actionInvocation.invoke();//执行其他的拦截器
}
session = actionInvocation.getInvocationContext().getSession(); // 从Invocation得到session对象
Map<String,Object> session2=ActionContext.getContext().getSession();
System.out.println(session+"actionInvocation的session");
System.out.println(session2+"ActionCOntext的session");
System.out.println(session3+"注入的session");
String user=(String) session.get("username");//得到session中的值
//如果存在该用户,放行
System.out.println(user);
if(user!=null&&!user.isEmpty()){
System.out.println("存在该用户");
return actionInvocation.invoke();
}else{
//如果不存在该用户
System.out.println("不岑在该用户");
return LOGIN;//跳转到登陆页面
}
}
public void setSession(Map<String, Object> arg0) {
this.session3=arg0;
System.out.println("注入session3");
}
}
然后换成用ActionInvocation和ActionContext都能得到session,一直在思考这个愚蠢的问题,查阅资料发现,Struts2要访问ServletApi是通过
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="profiling"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
<!-- The completeStack is here for backwards compatibility for
applications that still refer to the defaultStack by the
old name -->
<interceptor-stack name="completeStack">
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<!-- Sample execute and wait stack.
Note: execAndWait should always be the *last* interceptor. -->
<interceptor-stack name="executeAndWaitStack">
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStack"/>
大家可以发现,Struts2已经帮我们做好了一个默认的拦截器,里面的功能大多了!大家不难发现里面有诸如modelDriven,fileupload等大家经常用到的东西。public abstract class AbstractInterceptor implements Interceptor {
public void init() {
}
public void destroy() {
}
public abstract String intercept(ActionInvocation invocation) throws Exception;
}
public abstract class AbstractInterceptor implements Interceptor {
public void init() {
}
public void destroy() {
}
public abstract String intercept(ActionInvocation invocation) throws Exception;
}
package edu.cqupt.iactg.helper
import java.util.Map;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import edu.cqupt.iactg.action.UserAction;
public class UserInterceptor implements Interceptor {
private Map<String ,Object> session=null;//获得session
public static final String LOGIN="index";//全局返回值
public void destroy() {
System.out.println("拦截器销毁");
}
public void init() {
System.out.println("拦截器加载");
}
public String intercept(ActionInvocation actionInvocation) throws Exception {
System.out.println("进入拦截器");
//如果访问的是登陆acton则不需要对其拦截
if(actionInvocation.getAction() instanceof UserAction){
return actionInvocation.invoke();//执行其他的拦截器
}
session = actionInvocation.getInvocationContext().getSession(); // 从Invocation得到session对象
String user=(String) session.get("username");//得到session中的值
//如果存在该用户,放行
System.out.println(user);
if(user!=null&&!user.isEmpty()){
System.out.println("存在该用户");
return actionInvocation.invoke();
}else{
//如果不存在该用户
System.out.println("不岑在该用户");
return LOGIN;//跳转到登陆页面
}
}
}
<package name="basic" abstract="true" extends="json-default">
<!-- 定义自己的拦截器 -->
<interceptors>
<!-- z指定改拦截器的位置 -->
<interceptor name="userInterceptor" class="edu.cqupt.iactg.helper.UserInterceptor"></interceptor>
<!-- 指定拦截器栈 -->
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"></interceptor-ref><!-- Struts2自己提供的默认拦截器 -->
<interceptor-ref name="userInterceptor"></interceptor-ref><!-- 我们自己定义的拦截器 -->
</interceptor-stack>
</interceptors>
<!-- <default-interceptor-ref name="myStack"></default-interceptor-ref> --><!--设置为默认拦截器 -->
<global-results>
<result name="ERROR" type="redirectAction">disparter/error</result>
<result name="index" type="redirect">/</result><!-- 登陆界面地址 -->
</global-results>
<!-- 异常处理 -->
<global-exception-mappings>
<exception-mapping result="ERROR" exception="java.lang.Exception"/>
</global-exception-mappings>
</package>
现在我们就定义好了自己的代码了,我的拦截器定义时放在最终的一个父包里面的,如果要让继承该包的xml文件都使用这个拦截器就应该加上一条
<package name="disparter" namespace="/disparter" extends="basic">
<action name="main">
<interceptor-ref name="myStack"></interceptor-ref>
<result>/jsp/index_main.jsp</result>
</action>
<action name="home">
<interceptor-ref name="myStack"></interceptor-ref>
<result>/jsp/home.jsp</result>
</action>
<action name="index">
<result>index.jsp</result>
</action>
<action name="error">
<result>/jsp/error.html</result>
</action>
</package>
在要使用的的action下指定拦截器就行了。
过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符
拦截器,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
拦截器与过滤器的区别 :
- 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
- 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,做一些前期的数据处理,接着把处理后的数据发给对应的Action;Action处理完成返回后,拦截器还可以做其他过程(还没想到要做啥),再向上返回到过滤器的后续操作。
这样看来,AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上来说,AOP基本上是通过代理机制实现的。