大家好,又见面了,我是你们的朋友全栈君。
拦截器
拦截器Filter是Struts2的核心。
Struts2的拦截器与Servlet中的过滤器相似。 在执行Action的execute()方法之前,Struts2先执行struts.xml中引用的拦截器,在执行完所有引用的拦载器的doIntercept()方法后,会执行Action的execute()方法。在Struts2的拦截器体系中,Struts2的内建拦截器完成了该框架的大部分操作,所以在实际的开发过程中通常是使用系统的拦截器。
拦截器的实现原理
Struts2拦截器的实现原理相对简单,当请求Action时,Struts2会查找配置文件(struts.xml),并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。 比如:应用要求用户登陆,且必须为指定用户名才可以查看系统中某个视图资源;否则,系统直接转入登陆页面。对于上面的需求,可以在每个Action的执行实际处理逻辑之前,先执行权限检查逻辑,但这种做法不利于代码复用。因为大部分Action里的权限检查代码都大同小异,故将这些权限检查的逻辑放在拦截器中进行将会更加优雅。
拦截器什么时候执行?
在Action类对象创建之后,execute()方法调用之前之后执行(响应到客户端之前)。
拦截器的分类 系统拦截器(默认拦截器) 自定义拦截器 当系统拦截器满足不了需求,就要自定义拦截器.
系统拦截器 系统拦截器有很多,这里重点讲解:Timer和Token struts-default.xml中intercept有很多系统拦截器
Timer 时间拦截器 作用:测试方法执行所耗的时间。
代码语言:javascript复制<action name="person" class="com.zking.action.PersonAction">
<result>/success.jsp</result>
<!--系统时间拦截器-->
<interceptor-ref name="timer"></interceptor>
<!--系统拦截器栈,使用拦载器一定要带这个栈才生效,这是个好习惯-->
<interceptor-ref name="defaultStack"/>
</action>
说明: 当访问PersonAction类里所有方法之前,都会触发Timer拦截器,该拦截器显示方法执行消耗时间秒。 运行后发现并没有显示什么时间,原因是2.3缺少了commons-logging-1.1.jar日志包或log4j2日志包,项目中加入该包后再测试。
Token令牌拦截器
作用:解决表单重复提交问题。 办法一:重定向,不让地址栏出现action地址。(这里不再描述) 办法二:令牌,进Action要令牌(当天的火车票,进站时、出站时用,再想进站就要有新的票了)
令牌具体实现步骤: (1)在表单中使用<s:token>会随机产生的一个字符串,隐藏的文本域。
代码语言:javascript复制<form action="" method="post">
<s:token></s:token>
……
</form>
运行JSP页面后,会随机产生一个字符串的token:
第二步:在struts.xml中配置令牌的拦截器
代码语言:javascript复制<action name="person*" class="com.action.PersonAction">
<result>/success.jsp</result>
<!--令牌拦截器-->
<interceptor-ref name="token">
<!--这里可以配置token拦截器的排队方法-->
<!-- param name="excludeMethods">...</param -->
</interceptor>
<!-- 当出现重复提交时,自动跳转到error.jsp -->
<result name="invalid.token">/error.jsp</result>
<interceptor-ref name="defaultStack" />
</action>
可在error.jsp页面中添加<s:actionerror>显示重复提交信息。
自定义拦截器 (1)创建拦截器类 继承MethodFilterInterceptor类,并重写doIntercept方法,在方法中写业务逻辑。
代码语言:javascript复制public class MyInterceptor extends MethodFilterInterceptor {
//ActionInvocation为当前Action的运行状态
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
ActionContext ac = invocation.getInvocationContext();
//获得session
Map session = ac.getSession();
User user = (User)session.get("user");
if(null==user){
return “login”;
}
//通过放行
invocation.invoke();
return "usreMain";
}
}
先在拦截器doIntercept()方法中获取parameters对象:
代码语言:javascript复制Map paramMap = invocation.getInvocationContext().getParameters();
然后用parameters对象获取参数(是一个字符串数组):
代码语言:javascript复制String[] names = (String[])paramMap.get("user.userName");
String username = names[0];
配置拦截器
代码语言:javascript复制<struts>
<package name="mypack" extends="struts-default" namespace=”/admin”>
<!--1. 声明自定义拦截器-->
<interceptors>
<interceptor name="loginInterceptor" class="com.zking.interceptor.MyInterceptor">
</interceptor>
</interceptors>
<action name="login" class="com.zking.LoginAction">
<result name="success">success.jsp</result>
<!--2. Action中引用自定义拦截器-->
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack" />
</action>
</package>
</struts>
配置Action中某些方法执行时,不进行拦截:
代码语言:javascript复制<interceptor-ref name="loginInterceptor">
<!-- 忽略login、add方法 -->
<param name="excludeMethods">login,add</param>
</interceptor-ref>
案例: 我们尝试编写一个Session过滤用的拦截器,该拦截器查看用户Session中是否存在特定的属性(LOGIN属性)如果不存在,中止后续操作定位到LOGIN,否则执行原定操作,代码为:
代码语言:javascript复制public class CheckLoginInterceptor extends AbstractInterceptor {
public static final String LOGIN_KEY = "LOGIN";
public static final String LOGIN_PAGE = "global.login";
public String intercept(ActionInvocation actionInvocation) throws Exception {
//获得Action对象
Object action = actionInvocation.getAction();
//对LoginAction不做该项拦截
if (action instanceof LoginAction) {
return actionInvocation.invoke();
}
// 确认Session中是否存在LOGIN
Map session = actionInvocation.getInvocationContext().getSession();
String login = (String) session.get(LOGIN_KEY);
if (login != null && login.length() > 0) {
// 存在的情况下进行后续操作
return actionInvocation.invoke();
} else {
// 否则终止后续操作,返回LOGIN
System.out.println("请登录");
return LOGIN_PAGE;
}
}
}
注册拦截器:
代码语言:javascript复制<interceptors>
<interceptor name="login" class="com.zking.util.CheckLoginInterceptor"/>
<interceptor-stack name="teamwareStack">
<interceptor-ref name="login"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
将上述拦截器设定为默认拦截器:
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/189004.html原文链接:https://javaforall.cn