八、Struts2 的拦截器

一、拦截器基本概念

		Intercetor, 即为拦截器。
		
		1. Struts2的每一个功能都是由拦截器实现。
		   用户想使用哪一个功能,可以自由组装。
	
		2. 为了方便对拦截器的引用,struts提供了拦截器栈的定义,
		   里面可以引用多个拦截器。
	
		   文件夹(文件, 文件2)  拦截器栈(拦截器,拦截器2)
		   
		3. struts指定了默认执行的拦截器栈(该栈中定义了18个拦截器)
		   如果用户没有指定拦截器,那么会自动执行该拦截器栈。
		   如果指定了拦截器,则执行指定的拦截器。而默认的拦截器栈就不会执行。

二、自定义一个拦截器 – 开发步骤

2.1 自定义一个拦截器
方式一 实现Interceptor接口
		
		1.自定义拦截器类,必须实现Interceptor接口
		
				public class MyIncepteror implements  Interceptor{			
					@Override
					public void destroy() {
					}			
					@Override
					public void init() {
						System.out.println("1.初始化拦截器");
					}			
					@Override
					public String intercept(ActionInvocation in) throws Exception {
						
						System.out.println("2.拦截器 -- 前置逻辑");					
						//执行方法,返回结果标记
						String  input=in.invoke();
						
						System.out.println("2.拦截器 -- 后置逻辑");
				
						return null;
					}			
				}


方式一 继承AbstractInterceptor
	public class UserInterceptor  extends AbstractInterceptor{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	public String intercept(ActionInvocation ac) throws Exception {
		
		String method = ac.getProxy().getMethod();
		
		//放行
		if(method.equals("login")) {
			return ac.invoke();
		}
		
		//验证
		Object admin = ActionContext.getContext().getSession().get("userInfo");
		
		//验证-失败
		if(admin==null) {
			return "loginFail";
		}
		//验证-放行
		return ac.invoke();
		
	}

}

2.2 在Struts.xml 配置拦截器
	    
	    1.在struts.xml中配置拦截器
	    						 
					 	//1. 定义拦截器以及拦截器栈
						<interceptors>
							    1.1 拦截器定义
							    <interceptor name="mm" class="" /> 
							    
							    1.2 拦截器栈的定义
							    <interceptor-stack name="myStack">
							    	    <interceptor-ref name="mm"></interceptor-ref>	    		
							    	    <interceptor-ref name="defaultStack"></interceptor-ref>	    		
							    </interceptor-stack>						    
						</interceptors>
		
	
		2.引用拦截器
				   	+++package节点下引入拦截器
							   		
							   		<!-- 自定义拦截器 -->
							 		<interceptors>
							 		
							 				<interceptor name="myInterceptor" class="org.jsoft.interceptor.MyIncepteror"></interceptor>
							 				<interceptor-stack name="myStack">
							 					<interceptor-ref name="myInterceptor"></interceptor-ref>
							 					<interceptor-ref name="defaultStack"></interceptor-ref>
							 				</interceptor-stack>
							  	
							 		</interceptors>
							    	
							    	<!--package节点下引入默认执行的拦截器栈 -->
							    	<default-interceptor-ref name="myStack"></default-interceptor-ref>					


					+++ 在action节点下引入拦截器					
								<package name="xxxx1"  extends="struts-default" namespace="/" > 	
								    	
								    	<!-- 自定义拦截器 -->
								 		<interceptors>
								 		
								 				<interceptor name="myInterceptor" class="org.jsoft.interceptor.MyIncepteror"></interceptor>
								 				<interceptor-stack name="myStack">
								 					<interceptor-ref name="myInterceptor"></interceptor-ref>
								 					<interceptor-ref name="defaultStack"></interceptor-ref>
								 				</interceptor-stack>
								  	
								 		</interceptors>
								    	
								      	
								    	<action name="emp_*" class="org.jsoft.action.EmpAction"  method="{1}">									     		
											 	 <!-- 加入默认拦截器、token拦截器 -->
											  	  <interceptor-ref name="defaultStack"></interceptor-ref>
											      <interceptor-ref name="token">
										  					<!-- 哪些方法被令牌拦截器拦截 -->
										                  <param name="includeMethods">addEmp</param>
											     </interceptor-ref>
									    
									   </action>  
								</package>


2.2.1 在package节点下引入拦截器 – 拦截当前包下的所有action
	将拦截器的引用在package节点下配置。
	当前package下所有定义的action都会被拦截。

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
          "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	
    <package name="xxxx" extends="struts-default">
    	
    	<!-- 1.自定义拦截器配置 -->
    	<interceptors> 		       		  
    		  <!-- 自定义拦截器 -->
    		  <interceptor name="testInterceptor" class="org.jsoft.interceptor.HelloInterceptor"></interceptor>
    		
    		  <!-- 自定义拦截器栈 -->
    		  <interceptor-stack name="myStack">
	    			<interceptor-ref name="defaultStack"/>
	    			<interceptor-ref name="testInterceptor"/>
    		</interceptor-stack> 	
    	</interceptors>
    	
      
    	<!-- 2.指定执行的拦截器 -->
        <default-interceptor-ref name="myStack"/>
        
    	<action name="loginOut" class="org.jsoft.action.LoginAction" method="loginOut">
    		<result name="loginOut" type="redirect">/login.jsp</result>
    	</action>
    	
    </package> 
</struts>

2.2.2 在action节点下引入拦截器 – 拦截器拦截当前action
	将拦截器的引用配置在action节点下配置。
	只有当前action被拦截。

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
          "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	
    <package name="xxxx" extends="struts-default">
    	
    	<!-- 1.自定义拦截器配置 -->
    	<interceptors> 		       		  
    		  <!-- 自定义拦截器 -->
    		  <interceptor name="testInterceptor" class="org.jsoft.interceptor.HelloInterceptor"></interceptor>
    		
    		  <!-- 自定义拦截器栈 -->
    		  <interceptor-stack name="myStack">
	    			<interceptor-ref name="defaultStack"/>
	    			<interceptor-ref name="testInterceptor"/>
    		</interceptor-stack> 	
    	</interceptors>
    	
    	<action name="loginOut" class="org.jsoft.action.LoginAction" method="loginOut">    		
    		
    		<!---2.自定义拦截器,只拦截当前action -->
    		<interceptor-ref name="myStack"></interceptor-ref>	
    		<interceptor-ref name="testInterceptor"></interceptor-ref>	    
    				
    		<result name="loginOut" type="redirect">/login.jsp</result>
    	
    	</action>
    	
    </package> 
</struts>

2.3 引入拦截器注意事项
		
		1.在struts的package节点下使用该标签来引入拦截器。 (只能用一个标签)		        
		        	<default-interceptor-ref name="myStack"/>
		
		2.在struts的action节点下使用该标签来引入拦截器。(可以使用多个标签来引入多个拦截器)
			  	
			  		<interceptor-ref name="testStak" />
	  		    	<interceptor-ref name="defaultStack" />
		
		3.在struts中指定了执行的拦截器,
		  那么默认的拦截器栈(18个拦截器)就不会执行了。
		  所以我们仍需要手动指定执行默认的拦截器栈。
		
			 +++ 方式一:	 	
								//1. 定义拦截器以及拦截器栈
								<interceptors>
								    1.1 拦截器定义
								    <interceptor name="" class="" /> 
								    
								    1.2 拦截器栈的定义
								    <interceptor-stack name="defaultStack">
									引用了上面拦截器(1.1)
								    </interceptor-stack>								    
								</interceptors>
								
								//2.执行拦截器
		        				<default-interceptor-ref name="myStack"/>
			 
			  +++ 方式二:
			  		    		<interceptor-ref name="testStak"></interceptor-ref>	    	  		
			  		    		<interceptor-ref name="defaultStack"></interceptor-ref>	    
	  		    		

三、自定义一个拦截器案例

HelloInterceptor.java

public class HelloInterceptor  implements Interceptor{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void init() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public String intercept(ActionInvocation chain) throws Exception {
		System.out.println("拦截器前置逻辑");
		String falg = chain.invoke();
		System.out.println("拦截器后置逻辑");
		return falg;
	}

}

struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
          "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

	

    <package name="xxxx" extends="struts-default">
    	
    	<interceptors> 		  
    		  <!-- 自定义拦截器 -->
    		  <interceptor name="testInterceptor" class="org.jsoft.interceptor.HelloInterceptor"></interceptor>
    		
    		  <!-- 自定义拦截器栈 -->
    		  <interceptor-stack name="myStack">
	    			<interceptor-ref name="defaultStack"/>
	    			<interceptor-ref name="memberInterceptor"/>
	    			<interceptor-ref name="testInterceptor"/>
    		</interceptor-stack> 	
    	</interceptors>
      
    	<!-- 指定执行的拦截器 -->
        <default-interceptor-ref name="myStack"/>
    	
    	<global-results>
    			<result name="login" type="redirect">/login.jsp</result>
    	</global-results>
    	
    	<action name="login" class="org.jsoft.action.LoginAction" method="login">
    		<result name="success" type="redirect">/list</result>
    		<result name="error" type="redirect">/login.jsp</result>
    	</action>
    
    </package> 
</struts>

四、拦截器生命周期

public class MyIncepteror implements  Interceptor{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void init() {
		System.out.println("1.初始化拦截器");
	}

	@Override
	public String intercept(ActionInvocation in) throws Exception {
		
		System.out.println("2.拦截器 -- 前置逻辑");
		
		//执行方法,返回结果标记
		String  input=in.invoke();
		
		System.out.println("2.拦截器 -- 后置逻辑");

		return null;
	}

}

4.1 拦截器的生命周期
	Interceptor接口:
				构造方法
				init()
				intercept(ActionInvocation chain)
				destory()
	   +++ tomcat服务器启动
				1.tomcat 服务器启动时,会自动加载web.xml配置文件
				2.自动创建StrusPrepareAndExcuteFilter过滤器实例。
				3.调用init(FilterConfig  config)方法。传入过滤器参数。
				4.该方法会自动初始化struts。
							a.创建所有拦截器实例。
							b.调用拦截器的init()方法,初始化拦截器。
			
		+++ 用户请求action
				1.用户发送请求首先会被过滤器进行拦截。
				
				2.用户请求进入struts执行链。
								-->	a.创建action实例。		
								--> b.执行拦截器栈(拦截器的interceptor方法)
												-->	执行拦截器前置逻辑(拦截器1前置-->拦截器2前置 ...-->	执行action方法。
												-->	执行拦截器后置逻辑(拦截器1后置-->拦截器2后置 ...)	
				
				用户的每一次请求都会执行用户请求1- 2流程。	
														
4.2 拦截器注意细节
		1、如果用户请求aciton,会被拦截器进行拦截。
		   如果用户请求jsp和静态文件,则不会被拦截器进行拦截。
		   
		2、服务器内部action跳转action,则会被拦截器进行拦截。
		   服务器内部action跳转jsp和静态文件,则不会被拦截器进行拦截。		

		3、用户发送请求,首先创建action实例,然后才会被拦截器进行拦截。
		   			--> 创建action实例
		   			--> 执行拦截器前置逻辑 
		   			--> action业务方法
		   			--> 执行拦截器后置逻辑
		   			--> 跳转

五、过滤器与拦截器的区别?

		都是对于用户的请求起到拦截的作用,
		只不过Filter是Java EE规范的概念,
		而拦截器Interceptors是Struts2中提出的概念!  

		Struts2中过滤器负责调用拦截器!
		
		过滤器会过滤所有资源。即使用户访问jsp,也会被过滤。
		拦截器只会过滤action资源。

六、Stuts2常用的内置拦截器的作用

6.1 Parameters 拦截器

	Parameters拦截器的作用:
			1.获取值栈的栈顶对象。
			2.封装请求数据到栈顶对象中(自动类型转换)。
	
	Parameters拦截器详细过程:
			1.用户访问Action,Struts会自动创建Action,ValueStack,ActionContext对象。
			  同时将Action放在ValueStack对象的list栈的栈顶。
			
			2.			
			  Parameters拦截器会自动获取值栈对象,
			  并将请求数据封装到值栈对象中。类似于BeanUtils组件。
			  由于此时Action即值栈对象,所以会把数据封装到Action对象的属性中。
			(属性必须带有getset方法。属性名和请求参数名必须同名。)
			
		
6.1.1 封装注意事项

	1.Parameters拦截器会将请求数据封装到值栈对象中,并非栈顶对象。
	
	2.Parameters拦截器会将请求数据封装到值栈对象中,从上到下依次封装。
	
    3.Parameters拦截器会将请求数据封装到值栈对象中,从上到下依次封装。
      如果请求属性已经匹配过了,就不会再次匹配其他值栈对象的属性。
      
      即如果name属性在第一个值栈对象中已经匹配了。如果第二个值栈对象也有name属性,
      就不会再次匹配。
      
    
    3.Parameters拦截器只会将请求数据封装到值栈对象中,但是对象中的对象不会封装。	
			   
6.1.2 案例
>>>>>> struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
          "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
  	
  	
    <!-- 0.请求数据的编码 。作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出-->
   <constant name="struts.i18n.encoding" value="UTF-8"></constant>	
	
  
    <package name="xxxx" extends="struts-default">	
    	
    	<!-- 全局视图 -->
    	<global-results>
    		<result name="success">/index.jsp</result>
    		<result name="err1">/error/err1.jsp</result>
    	</global-results>
    	
    	<!-- 全局异常:会到全局视图中查过标记对应的页面 -->
    	<global-exception-mappings>
    		<exception-mapping result="null" exception="java.lang.NullPointerException"></exception-mapping>
    		<exception-mapping result="err1" exception="java.lang.Exception"></exception-mapping>
    	</global-exception-mappings>
   	
    	
    	<!-- action实例交给spring创建 -->
    	<action name="emp_*" class="empAction" method="{1}">
	    	<result name="index">/index.jsp</result>
    	</action>
    	    	
    </package> 
</struts>

>>>>>> EmpEntity.java
	public class EmpEntity {
	
	private String empId;
	private String name;
	private int age;
	
	private DeptEntity dept;
	
	}
>>>>>> EmpAction.java

public class EmpAction extends ActionSupport implements ModelDriven<EmpEntity> {
	
	private EmpEntity emp=new EmpEntity();
	private String deptId;

	public String getDeptId() {
		return deptId;
	}

	public void setDeptId(String deptId) {
		this.deptId = deptId;
	}

	@Override
	public EmpEntity getModel() {
		return emp;
	}
	
	
	
	/**
	 * 	跳转到新增员工界面
	 * @return
	 */
	public String add() {
		
		System.out.println(deptId);
		System.out.println(emp);
		
		return "index";
	}

	
	
}

>>>>>> index.java
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib  uri="http://java.sun.com/jsp/jstl/core"  prefix="c"%>  
  
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<div style="margin:30px auto;width:300px;border:1px solid black;">
	<form action="${pageContext.request.contextPath}/emp_add"  method="get">
			<table   cellspacing="0" cellpadding="0"  style="margin:0 auto;">
					<caption><h1>新增员工</h1></caption>
					<tr>
						<td style="padding-top:8px;">姓名</td>
						<td>&nbsp;&nbsp;<input type="text" name="name"></td>
					</tr>
					<tr >
						<td style="padding-top:8px;">年龄</td>
						<td>&nbsp;&nbsp;<input type="text" name="age"></td>
					</tr>
					<tr >
						<td style="padding-top:8px;">部门</td>
						<td>&nbsp;&nbsp;
							<select name="deptId">
										<option value="1">科技部</option>
										<option value="2">科技部2</option>
							</select>			
						</td>
					</tr>
					<tr  align="center">
						<td colspan="2" style="padding-top:8px;">&nbsp;&nbsp;<input type="submit" value="新增">&nbsp;&nbsp;&nbsp;<input type="submit" value="重置"> </td>
					</tr>
			</table>
	</form>
	</div>
</body>
</html>
>>>>>> 测试

在这里插入图片描述
在这里插入图片描述

>>>>>> 分析
			由上图可以看见,deptId赋值了,emp实体的属性也赋值。
			
			1.用户请求,服务器就会创建AcionContext、ValueStack、Aciton对象。
			  同时将Action对象放在栈顶中。
			2.由于EmpAction使用了模型驱动,所以EmpEtityb又被压入栈顶。
			3.此时值栈对象为(从上到下):
						EmpEntity
										id
										name
										age
						EmpActon
										deptId
			
			6.Parameters拦截器会将请求数据从上到下自动封装到值栈对象中。	
			  所以EmpEntity的属性有值。deptId也有值。
			  						
6.2 ModelDriven 拦截器
	
	+++ ModelDriven拦截器的作用:
					实现数据驱动。
	
	+++ ModelDriven拦截器的具体细节:
					1.用户访问Action,
					  首先会把Action、值栈对象以及ActionContext对象创建出来。
					
					2.然后把action对象放在值栈对象的list集合的栈顶。
					
					3.ModelDriven拦截器调用action的getModel()方法,获取实例对象,
					  然后将该对象放在值栈对象的list集合的栈顶。
					
					4.然后Parameters拦截器会把请求数据自动
					  封装到值栈对象的list集合的栈顶对象。  
					  
									
6.3 FileUpload 拦截器
	fileUpload拦截器主要用于文件上传。
	
	struts封装了fileUpload组件,实现了文件上传功能。
6.4 Token 拦截器
	 
	 1.在defaultStack默认拦截器栈中没有该拦截器,所以如果需要使用该拦截器,
	   必须要手动引入。
	 
	 2.Token拦截器的作用:
	 					解决表单数据重复提交。
	 
	
	 3.Token拦截器执行流程:
	 				+++ 使用:
		 					在请求表单中加入<s:token />
		 					在struts.xml中引入token拦截器
		 			
		 			+++ 执行流程:	
	 						1.用户访问jsp,首先<s:token />会生成一个token值存储在客户端与Token拦截器中。
	 						2.表单提交,token拦截器拦截用户执行的方法
	 								==》用户访问的方法没有被拦截,则放行。
	 								==》用户访问的方法被拦截,则会比较客户端与服务器端的token值,
	 											如果token值一致,则删除服务器端token值,然后进入方法。
	 											如果token值不一致,则视为重复提交,返回 invalide.token 结果视图
	 						

		  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值