Struts2 自定义拦截器

本文详细介绍了 Struts2 框架中拦截器的实现原理及应用实践,包括自定义拦截器的编写、配置方法以及如何利用拦截器进行权限验证等高级功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果要编写自定义拦截器,那么可以只用实现com.opensymphony.xwork2.interceptor.Interceptor这个接口即可。

在这个类中,需要实现3个方法:destroy(),init(),intercept(),核心方法是intercept(),该方法完成了主要逻辑。

在该方法中有个参数invocation,类型为ActionInvocation接口,这个接口中最重要的是invoke方法。

intercept 方法可以如此实现:

view plaincopy to clipboardprint?

Stringresult=invocation.invoke();

returnresult;



例如,可以这样来实现自定义拦截器

view plaincopy to clipboardprint?

packagecn.tshining.interceptor;

importcom.opensymphony.xwork2.ActionInvocation;

importcom.opensymphony.xwork2.interceptor.Interceptor;

publicclassMyInterceptorimplementsInterceptor{

publicvoiddestroy(){

System.out.println("destory");

}

publicvoidinit(){

System.out.println("init");

}

publicStringintercept(ActionInvocationinvocation)throwsException{

Stringresult=invocation.invoke();

returnresult;

}

}



配置拦截器

定义好拦截器后,需要在struts.xml中配置使用拦截器,配置使用拦截器有2步:

1.声明拦截器。

在 struts.xml中package元素下增加元素

view plaincopy to clipboardprint?

<interceptors>

<interceptorname="myinterceptor"class="cn.tshining.interceptor.MyInterceptor"></interceptor>

</interceptors>



2.使用拦截器

首先需要了解的是,struts2已经定义了一个默认的拦截器栈,拦截器栈就是若干个拦截器或拦截器栈组成的一系列拦截器的集合。

在 struts2-core-2.1.8.jar下struts-default.xml中定义了这个默认的拦截器栈。

在 struts中所有的action都使用了默认的拦截器栈,若想使用自定义的拦截器栈,只用在action中配置即可,但是此时必须显式的写出使用默认拦截器栈的配置信息。

view plaincopy to clipboardprint?

<actionname="register2"class="cn.tshining.action.RegisterAction">

<resultname="success">/success.jsp</result>

<resultname="input">/register2.jsp</result>

<interceptor-refname="myinterceptor"></interceptor-ref>

<interceptor-refname="defaultStack"></interceptor-ref>

</action>



同时可以在控制台上看到输出的"init",这是由于拦截器在服务器启动时会自动加载,完成初始化。拦截器中定义的intercept方法就是在提交请求时执行的。

用户输入的数据会自动赋值到action中,实际上是底层拦截器起的作用。

在 struts-default.xml中可以看到名为params的拦截器,这个拦截器的作用就是将用户输入的数据注入到Action中的字段中。

使用拦截器参数

在定义拦截器,或者在使用拦截器时可以给拦截器传递参数。

首先在 MyInterceptor类中声明一下字段

public int myparam;

修改 intercept方法:

view plaincopy to clipboardprint?

publicStringintercept(ActionInvocationinvocation)throwsException{

Stringresult=invocation.invoke();

System.out.println(myparam);

returnresult;

}



修改struts.xml中拦截器的定义:

view plaincopy to clipboardprint?

<interceptors>

<interceptorname="myinterceptor"class="cn.tshining.interceptor.MyInterceptor">

<paramname="myparam">1</param>

</interceptor>

</interceptors>



然后运行该程序,在register2.jsp中输入正确数据提交后就会在控制台中输出1.

也可以在拦截器调用时再传入参数:

view plaincopy to clipboardprint?

<actionname="register2"class="cn.tshining.action.RegisterAction">

<resultname="success">/success.jsp</result>

<resultname="input">/register2.jsp</result>

<interceptor-refname="myinterceptor">

<paramname="myparam">2</param>

</interceptor-ref>

<interceptor-refname="defaultStack"></interceptor-ref>

</action>



此时重启服务器,在register2.jsp中输入正确的数据之后,可以看到控制台中输出2.

注意此时并没有删除之前拦截器定义时的参数,由此可见,在拦截器调用时的参数比拦截器定义时优先级高。

上面的拦截器调用中使用到了默认拦截器栈,当然自己也可以自定义默认拦截器栈。

view plaincopy to clipboardprint?

<interceptors>

<interceptorname="myinterceptor"class="cn.tshining.interceptor.MyInterceptor">

<paramname="myparam">1</param>

</interceptor>

<interceptor-stackname="myDefaultStack">

<interceptor-refname="myinterceptor"></interceptor-ref>

<interceptor-refname="defaultStack"></interceptor-ref>

</interceptor-stack>

</interceptors>

<default-interceptor-refname="myDefaultStack"></default-interceptor-ref>



这样,这个自定义的默认拦截器栈中包含了自定义的拦截器和struts2定义的默认拦截器栈。

在拦截器栈的定义中,既可以引用拦截器,也可以引用拦截器栈。

在 action中没定义拦截器时,会使用默认拦截器。

当然 struts2提供了一个简便的创建自定义拦截器的方法。

只需要继承AbstractInterceptor类,该类空实现了Interceptor接口的init和destroy方法,因此只用实现 intercept方法即可。

在这里我们override AbstractInterceptor的init方法。

view plaincopy to clipboardprint?

packagecn.tshining.interceptor;

importcom.opensymphony.xwork2.ActionInvocation;

importcom.opensymphony.xwork2.interceptor.AbstractInterceptor;

publicclassMyInterceptor2extendsAbstractInterceptor{

@Override

publicStringintercept(ActionInvocationinvocation)throwsException{

Stringresult=invocation.invoke();

returnresult;

}

@Override

publicvoidinit(){

System.out.println("init2");

}

}



在<interceptor-ref name="myinterceptor"></interceptor-ref>下面增加以下内容:

view plaincopy to clipboardprint?

<interceptor-refname="myinterceptor2"></interceptor-ref>



这样就将myinterceptor2增加到了默认拦截器栈中,查看控制台输出会看到:

init

init2

销毁时会看到:

destory2

destory

这是由于先配置的拦截器先执行,结束时后配置的拦截器先执行

在这里拦截器的执行顺序为:

myintercept——myintercept2——action——myintercept2——myintercept

需要说明的是一定要在action中引用拦截器才会使用拦截器,拦截器拦截的是Action中的execute或自定义的逻辑处理方法。

当然也可以让拦截器拦截指定的方法,那么我们需要继承MethodFilterinterceptor类

view plaincopy to clipboardprint?

packagecn.tshining.interceptor;

importcom.opensymphony.xwork2.ActionInvocation;

importcom.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

publicclassMyInterceptor3extendsMethodFilterInterceptor{

@Override

protectedStringdoIntercept(ActionInvocationinvocation)throwsException{

Stringresult=invocation.invoke();

System.out.println("doing");

returnresult;

}

}



在struts.xml中声明拦截器

view plaincopy to clipboardprint?

<interceptorname="myinterceptor3"class="cn.tshining.interceptor.MyInterceptor3"></interceptor>



然后在 Action中引用此拦截器。

首先查看MethodFilterinterceptor,它接受两个参数,

excludeMethods:排除的方法,多个方法间用逗号隔开

includeMethods:包含的方法,多个方法间用逗号隔开

在 struts.xml中如下配置

view plaincopy to clipboardprint?

<interceptor-refname="myinterceptor3">

<paramname="excludeMethods">test,execute</param>

<paramname="includeMethods">test</param>

</interceptor-ref>



那么该拦截其将会拦截test方法,因为include比exclude优先级高

在 com.opensymphony.xwork2.interceptor包里面还有一个重要的接口PreResultListener,查看文档。

* PreResultListeners may be registered with an ActionInvocation to get a callback after the Action has been executed but before the Result is executed.

注释:

PreResultListeners 可以注册到ActionInvocation,当Action执行完毕但是在返回结果之前调用。

也就是在action的execute执行结束之后,在渲染页面前调用。

首先实现自己的PreResultListeners类

view plaincopy to clipboardprint?

packagecn.tshining.interceptor;

importcom.opensymphony.xwork2.ActionInvocation;

importcom.opensymphony.xwork2.interceptor.PreResultListener;

publicclassMyListenerimplementsPreResultListener{

publicvoidbeforeResult(ActionInvocationinvocation,StringresultCode){

System.out.println(resultCode);

}

}



修改自己的拦截器MyInterceptor3中的 doIntercept方法。

view plaincopy to clipboardprint?

protectedStringdoIntercept(ActionInvocationinvocation)throwsException{

invocation.addPreResultListener(newMyListener());

Stringresult=invocation.invoke();

System.out.println("doing");

returnresult;

}



注意PreResultListeners必须向 ActionInvocation实例去注册,而且注册要在调用ActionInvocation实例的invoke方法之前。

当在 register2.jsp中输入正确的数据时,在控制台上可以看到输出的success信息。

该执行过程为:

拦截器 ——validate——execute——beforeResult——结束

拦截器的应用

用拦截器进行权限校验

首先分析一下这个示例的工作流程:

首先用户从login2.jsp登陆,只有username输入hello,password输入world,然后跳转到register2.jsp进行注册操作。

如果用户直接访问register2.jsp,提交后将直接跳转回login2.jsp。

1.首先我们修改struts2.xml,让用户在login2.jsp中输入正确页面之后,将页面转到register2.jsp。

view plaincopy to clipboardprint?

<actionname="login"class="cn.tshining.action.LoginAction">

<resultname="success">/register2.jsp</result>

<resultname="input">/login2.jsp</result>

<resultname="failer">/login2.jsp</result>

</action>



2.修改LoginAction类中execute方法

view plaincopy to clipboardprint?

publicStringexecute()throwsException{

if("hello".equals(this.getUsername())

&&"world".equals(this.getPassword())){

Map<String,Object>map=ActionContext.getContext().getSession();

map.put("user","login");

return"success";

}else{

this.addFieldError("username","usernameorpassworderror");

return"failer";

}

}



在该方法中,若用户输入正确信息后,会获得session对象,并把 user和login存到session中。

struts2 的Action中获得session对象的方法是

Map map = ActionContext.getContext().getSession();

struts 将session从servlet容器中抽离出来了,形成了一个map,更利于单元测试

3.新建一个拦截器。

view plaincopy to clipboardprint?

packagecn.tshining.interceptor;

importjava.util.Map;

importcom.opensymphony.xwork2.Action;

importcom.opensymphony.xwork2.ActionInvocation;

importcom.opensymphony.xwork2.interceptor.AbstractInterceptor;

publicclassAuthInterceptorextendsAbstractInterceptor{

@Override

publicStringintercept(ActionInvocationinvocation)throwsException{

Map<String,Object>map=invocation.getInvocationContext().getSession();

if(map.get("user")==null){

returnAction.LOGIN;

}else{

returninvocation.invoke();

}

}

}



在这个拦截器中,获得session对象的方法是

view plaincopy to clipboardprint?

Map<String,Object>map=invocation.getInvocationContext().getSession();



因此,当session中不存在user的值为login时,拦截器将返回Action.LOGIN,在struts.xml中返回结果为login将跳转到 login2.jsp。

这样便可以实现一个简单的用户校验了。

4.配置action

view plaincopy to clipboardprint?

<actionname="register2"class="cn.tshining.action.RegisterAction">

<resultname="success">/success.jsp</result>

<resultname="input">/register2.jsp</result>

<resultname="login">/login2.jsp</result>

<interceptor-refname="logininterceptor"></interceptor-ref>

<interceptor-refname="defaultStack"></interceptor-ref>

</action>



这样就可以正常工作了。

当然也可以不在Action中定义login的结果跳转,而直接在全局结果中配置。将下面代码放到Action配置前即可正常工作。

view plaincopy to clipboardprint?

<global-results>

<resultname="login">/login2.jsp</result>

</global-results>



这样就定义了一个全局结果页面。

直接进入到register2.jsp,点提交后,会发现地址栏跳到了http://localhost:8888/struts2 /register.action

结果重定向

前面在结果转发时都是用到了请求转发,实际上struts2定义了很多结果类型,我们可以使用重定向试试。

打开 struts2-core-2.1.8.jar,查看里面的struts-default.xml,其中定义了很多结果类型。

其中的 redirect代表的就是重定向。

然后将上面Action配置中作如下修改:

view plaincopy to clipboardprint?

<resultname="login"type="redirect">/login2.jsp</result>



然后重启服务器,直接进入到register2.jsp,点提交后,会发现地址栏跳到了http://localhost:8888/struts2 /login2.jsp

这就是重定向。在struts2中默认是dispatcher。

下次将学习struts2的文件上传与下载。
内容概要:本文围绕直流微电网中带有恒功率负载(CPL)的DC/DC升压转换器的稳定控制问题展开研究,提出了一种复合预设性能控制策略。首先,通过精确反馈线性化技术将非线性不确定的DC转换器系统转化为Brunovsky标准型,然后利用非线性扰动观测器评估负载功率的动态变化和输出电压的调节精度。基于反步设计方法,设计了具有预设性能的复合非线性控制器,确保输出电压跟踪误差始终在预定义误差范围内。文章还对比了多种DC/DC转换器控制技术如脉冲调整技术、反馈线性化、滑模控制(SMC)、主动阻尼法和基于无源性的控制,并分析了它们的优缺点。最后,通过数值仿真验证了所提控制器的有效性和优越性。 适合人群:从事电力电子、自动控制领域研究的学者和工程师,以及对先进控制算法感兴趣的研究生及以上学历人员。 使用场景及目标:①适用于需要精确控制输出电压并处理恒功率负载的应用场景;②旨在实现快速稳定的电压跟踪,同时保证系统的鲁棒性和抗干扰能力;③为DC微电网中的功率转换系统提供兼顾瞬态性能和稳态精度的解决方案。 其他说明:文中不仅提供了详细的理论推导和算法实现,还通过Python代码演示了控制策略的具体实现过程,便于读者理解和实践。此外,文章还讨论了不同控制方法的特点和适用范围,为实际工程项目提供了有价值的参考。
内容概要:该论文介绍了一种名为偏振敏感强度衍射断层扫描(PS-IDT)的新型无参考三维偏振敏感计算成像技术。PS-IDT通过多角度圆偏振光照射样品,利用矢量多层光束传播模型(MSBP)和梯度下降算法迭代重建样品的三维各向异性分布。该技术无需干涉参考光或机械扫描,能够处理多重散射样品,并通过强度测量实现3D成像。文中展示了对马铃薯淀粉颗粒和缓步类动物等样品的成功成像实验,并提供了Python代码实现,包括系统初始化、前向传播、多层传播、重建算法以及数字体模验证等模块。 适用人群:具备一定光学成像和编程基础的研究人员,尤其是从事生物医学成像、材料科学成像领域的科研工作者。 使用场景及目标:①研究复杂散射样品(如生物组织、复合材料)的三维各向异性结构;②开发新型偏振敏感成像系统,提高成像分辨率和对比度;③验证和优化计算成像算法,应用于实际样品的高精度成像。 其他说明:PS-IDT技术相比传统偏振成像方法具有明显优势,如无需干涉装置、无需机械扫描、可处理多重散射等。然而,该技术也面临计算复杂度高、需要多角度数据采集等挑战。文中还提出了改进方向,如采用更高数值孔径(NA)物镜、引入深度学习超分辨率技术等,以进一步提升成像质量和效率。此外,文中提供的Python代码框架为研究人员提供了实用的工具,便于理解和应用该技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值