拦截器可谓struts2的核心了,最基本的bean的注入就是通过默认的拦截器实现的,一般在struts2.xml的配置中,package内直接或间接继承了struts-default.xml,这样struts2默认的拦截器就会作用.下面详细的说明一下:

Interceptor拦截器类似于过滤器,是可以在action执行前后执行的代码。是我们做web开发时经常用的技术。比如:权限控制、日志等。我们也可以将多个Interceptor连在一起组成Interceptor栈。

Struts2拦截器,每个拦截器类只有一个对象实例,即采用单例模式,所以引用这个拦截器的Action都共享这一拦截器类的实例,因此,在拦截器中如果使用类变量,要注意同步问题。

实现原理 : Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对应拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。

拦截器和过滤器的区别:

1. 拦截器和过滤器的概念非常类似。

2. 过滤器隶属于web容器,可以过滤一切请求(包括action、servlet、jsp、html等等)。

3. 而拦截器隶属于struts2框架,只能拦截action(无法拦截对jsp的请求)。

4. 过滤器内部采用函数回调来实现。拦截器采用动态代理来实现!

拦截器在struts2中的应用:

对于Struts2框架而言,正是大量的内置拦截器完成了大部分操作。比如:

– 像params拦截器将http请求中参数解析出来赋值给Action中对应的属性。

– Servlet-config拦截器负责把请求中HttpServletRequest实例和HttpServletResponse实例传递给Action

– …

struts-default.xml中有一个默认的引用,在默认情况下(也就是<action>中未引用拦截器时)会自动引用一些拦截器。

常用拦截器:token

作用:防止表单重复提交拦截器

使用方法:配置struts2.xml+重复提交处理+jsp页面表单内插入<s:token></s:token>标签;其中struts.xml的配置是核心

(1)先来看一下最基本的struts.xml的配置:

 <package name="test" namespace="/" extends="struts-default">
<action name="testValidate" class="com.bjsxt.struts.test.TestValidateAction">
<interceptor-ref name="token"></interceptor-ref>
<result name="success">/ok.jsp</result>
<result name="input">/testFormLabel.jsp</result>
<result name="invalid.token">/tokenInvalid.jsp</result>
</action>
</package>

说明:

1.代码第三行代表引入一个struts2自带的拦截器token,此操作会使默认的拦截器失效,即无法使用其他功能,自定义拦截器再详细说明;

2.代码第六行为基本固定的格式,result的name属性值是固定的,后面的/tokenInvalid.jsp可以根据需求自己定义

3.此token拦截器会对该action下的所有请求作用,最关键的一点!即:所有该action的请求都会经过token的拦截处理,自定义拦截器时再说明;

(2)form表单中需加入<s:token></s:token>标签:

 <s:form action="testValidate" >
<s:textfield name="uname" ></s:textfield>
<s:token></s:token>
<s:submit></s:submit>
</s:form>

说明:不一定是s标签的表单,普通表单中插入<s:token></s:token>也可以实现拦截的效果.

(3)处理措施,我的是跳到一个错误页面:testFormLabel.jsp

 <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
<h1>表单不能重复提交!!</h1>

--------------------------------------------------------------------------------------------------------------------------------------------------------

 自定义拦截器:

作为“框架(framework)”,可扩展性是不可或缺的,因为世上没有放之四海而皆准的东西。虽然,Struts 2为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在Struts 2自定义拦截器是相当容易的一件事。

大家在开始着手创建自定义拦截器前,切记以下原则:
  拦截器必须是无状态的,不要使用在API提供的ActionInvocation之外的任何东西。要求拦截器是无状态的原因是Struts 2不能保证为每一个请求或者action创建一个实例,所    以如果拦截器带有状态,会引发并发问题。

条件:

  1. 直接或间接实现接口com.opensymphony.xwork2.interceptor.Interceptor或者继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor

  2.通过<interceptor>元素来定义拦截器

3.通过<interceptor-ref>元素来使用拦截器

  4.自定拦截器的java类并重写public String intercept(ActionInvocation ai) throws Exception

注意:如果为Action指定了一个拦截器,则系统默认的拦截器栈将会失去作用。为了继续使用默认拦截器,所以上面配置文件中手动引入了默认拦截器

步骤:

  1.新建一个class,用于实现自定义拦截器功能,这儿就实现最为普遍的登陆验证,即防止未经登陆的情况下,访问action;先说一下原理:

  首先,用户登陆后,经过action验证用户名和密码是否正确,如果正确则在session作用域内存放user对象,否则跳到登陆页面并提示用户名或密码不正确,而且session作用域中user的值是没有设置的.然后,由于在该action下使用了自定义的拦截器(struts.xml配置),访问该action的所有请求都会被拦截,验证session中user属性的值,如果值不存在,则跳到登陆页面并提示无权操作,否则执行invoke方法,即请求会被action正常响应,并返回相应的结果.

代码体现如下:

自定义拦截器类:

 package com.bjsxt.struts2.exercise.interceptor;

 import java.util.Map;

 import com.bjsxt.struts2.exercise.vo.Users;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; public class LoginInterceptor extends MethodFilterInterceptor{
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
//获取session对象(经过struts2包装过)
Map session = ActionContext.getContext().getSession();
//获取session作用域内是否有值
Users user = (Users) session.get("user");
if(user!=null){//合法访问
return invocation.invoke();
}else{//user为空说明未经过登陆,保存错误提示信息,跳到登陆页面
ActionContext.getContext().put("noright", "请先登陆再进行操作!");
return Action.LOGIN;
}
}
}

user类:

 package com.bjsxt.struts2.exercise.vo;

 public class Users {
private Integer id;
private String name;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

2.配置struts.xml,使自定义拦截器作用:

 <package name="move" namespace="/move" extends="struts-default">
<interceptors>
<interceptor name="loginInteceptor" class="com.bjsxt.struts2.exercise.interceptor.LoginInterceptor"></interceptor>
</interceptors>
<global-results>
<result name="login" >/jsp/movebooking/login.jsp</result>
</global-results>
<action name="moveBookingAction" class="com.bjsxt.struts2.exercise.action.MoveBookingAction" >
<interceptor-ref name="loginInteceptor">
<param name="excludeMethods">addMoveInfo</param>
</interceptor-ref>
<interceptor-ref name="token">
<param name="includeMethods">addMoveInfo</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="queryList" >/jsp/movebooking/movelist.jsp</result>
<result name="queryInfo" >/jsp/movebooking/moveinfo.jsp</result>
<result name="update" >/jsp/movebooking/updateinfo.jsp</result>
<result name="afterupdate" type="redirectAction" >moveBookingAction!queryMoveList</result>
<result name="success">/jsp/movebooking/success.jsp</result>
<result name="invalid.token">/jsp/movebooking/tokenInvalid.jsp</result>
</action> <action name="userAction" class="com.bjsxt.struts2.exercise.action.UserAction">
<result name="success" type="redirectAction" >moveBookingAction!queryMoveList</result>
<result name="failed" type="redirect">/jsp/movebooking/login.jsp
</result>
</action>
</package>

说明:

  (1)使用自定义拦截器会使默认拦截器失效,所以需要手动引入:代码第15行;当然上述代码引入拦截器的方式也可以采用拦截器栈的方式,就不贴了;

  (2)注意拦截器的顺序,一般情况下,默认拦截器都是放在最后面的,权限验证与token相比较,我觉得先验证是否登陆更加必要;

  (3)interceptor-ref内可以定义param元素,即实现对特定方法的拦截;但是注意,使用方法拦截器必须直接或间接实现AbstractInerceptor接口或者继承

MethodFilterInterceptor类,并重写doIntercept方法.param标签内有两个属性:

      excludeMethods:排除的方法

      includeMethods:包含的方法

在本配置文件中,由于token拦截器的作用范围为moveBookingAction下所有请求,而我在测试的时候就发现,该action下的所有请求都会被拦截到重复提交的错误页面,原理尚不明白,有高手敬请指导(只有需要被作用的请求对应的jsp页面的form表单内加入了token标签),所以被逼无奈对token拦截的方法只限定在addMoveInfo方法中!

3.使用的action类和几个jsp页面:

UserAction:

 package com.bjsxt.struts2.exercise.action;

 import com.bjsxt.struts2.exercise.service.UserService;
import com.bjsxt.struts2.exercise.vo.Users;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport; public class UserAction extends ActionSupport{
private UserService userService =new UserService();
private Users user;
public String queryUser() throws Exception{
user = userService.queryUser(user);
// 将user存到session中,实现拦截器拦截未经登陆直接请求的url的功能
ActionContext.getContext().getSession().put("user", user);
if(user!=null){
return Action.SUCCESS;
}else{
ActionContext.getContext().getSession().put("wrong", "用户名或密码错误!");
return "failed";
}
} public Users getUser() {
return user;
} public void setUser(Users user) {
this.user = user;
} }

MoveBookingAction:

 package com.bjsxt.struts2.exercise.action;

 import com.bjsxt.struts2.exercise.service.MoveBookingService;
import com.bjsxt.struts2.exercise.util.MyPageUtil;
import com.bjsxt.struts2.exercise.vo.MoveBookingVo;
import com.opensymphony.xwork2.ActionSupport; public class MoveBookingAction extends ActionSupport{
private MoveBookingService moveBookingService = new MoveBookingService();
private MyPageUtil pu;
private Integer pageNum;
private MoveBookingVo moveBookingVo;
private String[] phone;
/**
* 搬家列表
* @return
* @throws Exception
*/
public String queryMoveList() throws Exception{
pu = moveBookingService.queryMoveList(pageNum);
return "queryList";
} /**
* 搬家信息详情
* @return
* @throws Exception
*/
public String queryMoveInfo() throws Exception{
moveBookingVo = moveBookingService.queryMoveInfo(moveBookingVo);
return "queryInfo";
} /**
* 搬家详情,跳到update页面
* @return
* @throws Exception
*/
public String queryForUpdate() throws Exception{
moveBookingVo = moveBookingService.queryMoveInfo(moveBookingVo);
return "update";
} /**
* 修改搬家信息
* @return
* @throws Exception
*/
public String updateMoveInfo() throws Exception{
moveBookingService.updateMoveInfo(moveBookingVo);
return "afterupdate";
}
/**
* 搬家预约
* @return
* @throws Exception
*/
public String addMoveInfo() throws Exception{
moveBookingVo.setStatus("0");
moveBookingVo.setPhone(phone[0]+phone[1]);
moveBookingService.addMoveInfo(moveBookingVo);
return "success";
} public MyPageUtil getPu() {
return pu;
}
public void setPu(MyPageUtil pu) {
this.pu = pu;
}
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public MoveBookingVo getMoveBookingVo() {
return moveBookingVo;
}
public void setMoveBookingVo(MoveBookingVo moveBookingVo) {
this.moveBookingVo = moveBookingVo;
} public String[] getPhone() {
return phone;
} public void setPhone(String[] phone) {
this.phone = phone;
}
}

login.jsp:

 <body>
<font size="5"><b>管理员登陆</b></font><br>
<form id="f1" action="move/userAction!queryUser">
<input type="hidden" id="flag" name="flag" value="${flag }"/>
用户名:
<input id="uname" name="user.name" onclick="clearMsg()" />
密码:
<input id="pwd" type="password" name="user.password" onclick="clearMsg()" />
<input type="button" style="background-color: lightgray;width: 100px;" value="登陆" onclick="submit_form()"/>
</form>
<div id="div" style="color: red">${wrong }${noright }</div>
</body>

tokenInvalid.jsp:

  <body>
<h1>请勿重新提交</h1>
</body>

从struts2拦截器到自定义拦截器的更多相关文章

  1. CXF添加拦截器和自定义拦截器

    前面讲了如何采用CXF开发webservice,现在来讲如何添加拦截器和自定义拦截器. 服务端代码: HelloWorld implementor=new HelloWorldImpl(); Stri ...

  2. flask之web网关、三件套、配置、路由(参数、转化器及自定义转化器)、cbv、模板语言、session

    目录 1.wsgiref.py 2.werzeug.py 3.三件套 4.配置文件 5.路由本质 6.cbv.py 7.路由转化器 8.自定义转化器 9.模板语言 10.session原理 11.te ...

  3. Elasticsearch修改分词器以及自定义分词器

    Elasticsearch修改分词器以及自定义分词器 参考博客:https://blog.csdn.net/shuimofengyang/article/details/88973597

  4. [原创]java WEB学习笔记74:Struts2 学习之路--自定义拦截器,struts内建的拦截器

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. Struts2学习笔记(十)——自定义拦截器

    Struts2拦截器是基于AOP思想实现的,而AOP的实现是基于动态代理.Struts2拦截器会在访问某个Action之前或者之后进行拦截,并且Struts2拦截器是可插拔的:Struts2拦截器栈就 ...

  6. Struts2第七篇【介绍拦截器、自定义拦截器、执行流程、应用】

    什么是拦截器 拦截器Interceptor-..拦截器是Struts的概念,它与过滤器是类似的-可以近似于看作是过滤器 为什么我们要使用拦截器 前面在介绍Struts的时候已经讲解过了,Struts为 ...

  7. struts2(五)之struts2拦截器与自定义拦截器

    前言 前面介绍了struts2的输入验证,如果让我自己选的话,肯定是选择xml配置校验的方法,因为,能使用struts2中的一些校验规则,就无需自己编写了, 不过到后面应该都有其他更方便的校验方法,而 ...

  8. Struts2重新学习之自定义拦截器(判断用户是否是登录状态)

    拦截器 一:1:概念:Interceptor拦截器类似于我们学习过的过滤器,是可以再action执行前后执行的代码.是web开发时,常用的技术.比如,权限控制,日志记录. 2:多个拦截器Interce ...

  9. struts2内置拦截器和自定义拦截器详解(附源码)

    一.Struts2内置拦截器 Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特 性.这些内置的拦截器在struts-default.xml中配置.只有配置了拦截 ...

随机推荐

  1. Model Validation in Asp.net MVC

    原文:Model Validation in Asp.net MVC 本文用于记录Pro ASP.NET MVC 3 Framework中阐述的数据验证的方式. 先说服务器端的吧.最简单的一种方式自然 ...

  2. 经验总结35--IP地址区域匹配

    想知道客服端訪问的IP地址是多少,并知道区域. 一般能够去http://www.ip138.com/,输入IP查询,但没提供比較好的接口,程序使用不方便. 另外有些企业提供一些离线的IP数据库,能够进 ...

  3. DataTable相关操作,筛选,取前N条数据,获取指定列数据

    DataTable相关操作,筛选,取前N条数据,获取指定列数据2013-03-12 14:50 by Miracle520, 2667 阅读, 0 评论, 收藏, 编辑 1 #region DataT ...

  4. 了解ASP.NET 5

    通过3个Hello World应用来了解ASP.NET 5应用是如何运行的(1) 微软在开发ASP.NET 5(当时被称为ASP.NET vNext)是采用的代号为Project K,所以运行时被称为 ...

  5. Hbuilder常用快捷键功能.html

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. Java开发工具IntelliJ IDEA使用教程:创建新的Andriod项目

    IntelliJ IDEA社区版作为一个轻量级的Java开发IDE,本身是一个开箱即用的Android开发工具. 注意:在本次的教程中我们将以Android平台2.2为例进行IntelliJ IDEA ...

  7. 来自 Repository 的一丝线索,Domain Model 再重新设计

    来自 Repository 的一丝线索,Domain Model 再重新设计 写在前面 阅读目录: 疑惑解读 设计窘境 一幅图的灵感 为嘛还是你-Repository 后记 上一篇<No zuo ...

  8. memcached与.NET的融合使用2

    memcached与.NET的融合使用(二) memcached部署完成之后,对当前缓存中数据的监控就显得比较迫切,这里看到网上开源的memadmin比较小巧好用,决定用它来查看监控memcached ...

  9. ASP.NET MVC路由

    ASP.NET MVC路由(四) 前言 在前面的篇幅中我们讲解路由系统在MVC中的运行过程以及粗略的原理,想必看过前面篇幅的朋友应该对路由有个概念性的了解了,本篇来讲解区域,在读完本篇后不会肯定的让你 ...

  10. Android调用本机应用市场,实现应用评分功能

    原本以为应用评分是个很小的功能,但是一实现才发现真不是个小事.网上搜索资料没有找到答案,在很多开发群里面询问了很多人也没有解决问题,最后分析log,反编译看源码才终于有了些眉目,好吧,上代码: try ...