Struts2---拦截器

  • 所谓的拦截器指的就是AOP(面向切片编程)的一种实现,就是代理设计模式的实现.

认识拦截器

  • 在整个Struts2.x开发框架中,所有的用户请求都交给了Filter,这个FIlter要将请求交个指定的Action进行处理,而且一定要在Filter实现数据的转换处理.
  • 所以在现在的框架设计过程之中,往往会在请求真正的达到摸一个Action之前做一些处理操作,而这就属于拦截器的功能.

在这里插入图片描述

  • 在拦截器存在的前提下,才可以进行数据的验证操作.由于Struts2x使用的是过滤器接受的所有请求,这样也会造成一个问题,session登录检测不可能只在过滤器里处理.

  • 定义一个简单的拦截器

    • 拦截器的存在一定要附加在Action上
    • 编写一个Action程序类
package mao.shu.action;

import com.opensymphony.xwork2.ActionSupport;

public class DemoAction extends ActionSupport{
	public void add(){
		System.out.println("**************执行add方法*****************");
	}
}

  • 配置struts.xml文件
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
	 <package name="root" namespace="/" extends="struts-default">
     <action name="DemoAction" class="mao.shu.action.DemoAction">
     	<interceptor-ref name="timer"></interceptor-ref><!--  使用struts2内置的时间拦截器-->
     </action>  
 </package>
</struts>
  • 在第五行之中,使用了一个Struts2内置的时间拦截器,用于计算Action类方法执行的时间.

  • 启动tomcat发布项目,执行http://localhost:8080/InterceptorProject/DemoAction!add.action

  • 后台输出,可以发现输出的信息为,执行DempAction的add方法共使用了7毫秒

在这里插入图片描述

开发自定义的拦截器

  • 如果要实现自定义的拦截器需要有一个专门的拦截器处理类.这个类要求必须有一个父类------AbstractInterceptor
  • 该类定义如下

[img]

  • 而在AbstractInterceprot类中定义有如下的三个方法.
方法名称作用
public void init()初始化拦截器操作
public void destroy()销毁拦截器
public abstract String intercept(ActionInvocation invocation) throws Exception子类复写该方法实现拦截处理
  • 在这个类中定义的intercept()方法是一个抽象方法,这个方法必须有子类所复写,抽象方法中接受有一个ActionInvocation参数.在这个接口中提供一个请求向下处理的方法
方法名称作用
String invoke()throws Exception调用下一个拦截器,如果没有下一个拦截器,则执行当前的invoke()操作
  • 定义一个简单的拦截器
package mao.shu.Interceptor;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInteceptor extends AbstractInterceptor {

	@Override
	public void init() {
		System.out.println("**********************"+this+"拦截器初始化开始********");
	}
	@Override
	public String intercept(ActionInvocation arg0) throws Exception {
		System.out.println("*****************invoke()方法执行前*************");
		ServletActionContext.getRequest().setCharacterEncoding("UTF-8");
		String result = arg0.invoke();
		System.out.println("*****************invoke()方法执行后返回"+result+"*************");
		ServletActionContext.getResponse().setCharacterEncoding("UFT-8");
		return result;
	}
	@Override
	public void destroy() {
		System.out.println("**********************"+this+"拦截器销毁********");
	}
}

  • 拦截器定义完成之后如果要想使用,必须通过struts.xml文件进行处理

  • 修改strtus.xml文件

<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
	 <package name="root" namespace="/" extends="struts-default">
	 
	 <interceptors><!--  声明自定义的拦截器-->
	 	<interceptor name="MyInterceptor" class="mao.shu.Interceptor.MyInteceptor"></interceptor>
	 </interceptors>
	 
     <action name="DemoAction" class="mao.shu.action.DemoAction">
     	<interceptor-ref name="timer"></interceptor-ref><!--  使用struts2内置的时间拦截器-->
     	<interceptor-ref name="MyInterceptor"/><!--  引用拦截器-->
     	
     </action>  
 </package>
</struts>
  • 拦截器将按照既定的顺序执行.

  • 执行

  • 启动tomcat
    在这里插入图片描述

  • 执行之后发现,默认情况下 容器一档启动之后拦截器会自动进行启动.

  • 执行http://localhost:8080/InterceptorProject/DemoAction!add.action
    在这里插入图片描述

  • 此时的返回结果为null,因为此时的add()方法没有返回值,如果此时修改add()方法,使其有返回值

package mao.shu.action;

import com.opensymphony.xwork2.ActionSupport;

public class DemoAction extends ActionSupport{
	public String add(){
		System.out.println("**************执行add方法*****************");
		return "forward.page";
	}
}

  • 再次请求执行add()方法后,返回结果变为了forward.page,

在这里插入图片描述

  • 每个Action中的返回值,最终实际上就是拦截器中执行invoke()方法的返回结果.

自定义拦截器深入

  • 拦截器是在过滤器和Action之间的产物,也就是说拦截器可以控制进入到Action中的数据是否正确,于是此时如果配置不当,就有可能出现偏差.

  • 定义一个Message类

package mao.shu.vo;

public class Message {
	private Integer mid;
	private String info;
	public Integer getMid() {
		return mid;
	}
	public void setMid(Integer mid) {
		this.mid = mid;
	}
	public String getInfo() {
		return info;
	}
	public void setInfo(String info) {
		this.info = info;
	}
	
		@Override
	public String toString() {
		return "Message [mid=" + mid + ", info=" + info + "]";
	}
}

  • 随后在MessageAction里面希望可以进行内容的自动设置
  • 定义MessageAction程序类
package mao.shu.action;

import com.opensymphony.xwork2.ActionSupport;
import mao.shu.vo.*;

public class MessageAction extends ActionSupport{
	private Message msg = new Message();
	public void setMsg(Message msg) {
		this.msg = msg;
	}
	public Message getMsg() {
		return msg;
	}
	
	public String add(){
		System.out.println("新对象实例化成功********");
		System.out.println(this.msg);
		return null;
	}
}

  • struts.xml稳健的配置
<action name="MessageAction" class="mao.shu.action.MessageAction">
	<interceptor-ref name="timer"></interceptor-ref><!--  使用struts2内置的时间拦截器-->
</action>  
  • 直接诶利用地址重写的方式实现内容传递
http://localhost:8080/InterceptorProject/MessageAction!add.action?msg.mid=1,msg.info=你好
  • 后台输出的结果

在这里插入图片描述

  • 此时发现使用了拦截器并没有成功为属性设置该有的内容,因为没有使用设置内容的拦截器.
  • 当使用了自定义的拦截器,系统中自定义的拦截器就会失效了.
  • 因此要在struts.xml文件中添加系统自定义的拦截器
<action name="MessageAction" class="mao.shu.action.MessageAction">
	<interceptor-ref name="defaultStack"></interceptor-ref><!--  使用struts2默认的拦截器-->
	<interceptor-ref name="timer"></interceptor-ref><!--  使用struts2内置的时间拦截器-->
</action>  
  • 修改之后执行结果
    在这里插入图片描述
  1. 属性设置
    • 拦截器本身也属于一个java程序类,那么就有可能会有类属性.
    • 如果拦截器之中需要接收一些属性的话,那么可以通过配置的参数完成.
  • 在拦截器中定义属性
  • 修改MyIinterceptor程序类,添加两个类属性,以及setter()方法
	private String paramA ;
	private String paramB;
	
	public void setParamA(String paramA) {
		this.paramA = paramA;
	}
	public void setParamB(String paramB) {
		this.paramB = paramB;
	}
  • 所有的属性都可以通过配置文件处理,修改struts.xml文件
<action name="MessageAction" class="mao.shu.action.MessageAction">
      	<interceptor-ref name="MyInterceptor"><!--  引用自定义拦截器-->
      		<param name="paramA">Hello</param><!--  配置拦截器中的参数-->
      		<param name="paramB">World</param>
      	</interceptor-ref>
      <interceptor-ref name="defaultStack"></interceptor-ref><!--  使用struts2默认的拦截器-->
 	<interceptor-ref name="timer"></interceptor-ref><!--  使用struts2内置的时间拦截器-->
 </action>  
  • 在MyInterceptor拦截器程序中的intercept()方法中输出拦截器的参数
	System.out.println(this.paramA+":"+this.paramB);
  • 执行MessageAction类中的add()方法的请求

在这里插入图片描述

  • 改变返回模式
    • 默认情况下拦截器会将invoke(0的内容返回,实际上这个内容可以自己定义
  • 修改MyInterceptor拦截器中的intercept()方法的返回值
return "error.page";
  • 实际上在开发之中拦截器一定是被所有的Action所使用,如果只是用某一个具体Action定义的"result"是非常不合理的,所以最好的做法是将其统一跳转到全局路径上

  • 在struts.xml文件中配置全局跳转路径

  • 该声明必须生命在拦截器之后

 <global-results><!--  拦截器统一的跳转路径-->
 	<result name="error.page">/error.page</result>
 </global-results>

利用拦截器检测登录

  • 在任何的项目之中都一定需要有登录验证,可是对于Struts2.x而言,所有的Action如果要想进行登录检测,就必须使用拦截器完成,过滤器只能够过滤*.jsp,*.html,登录文件路径等信息.

  • 如果要想在拦截器中取的session属性,那么可以使用两种方案

    1. ServletActionContext.getReqeust().getSession().get()
    2. 通过ActionContext类取得session属性
  • 编写一个LoginInterceptor拦截器

package mao.shu.Interceptor;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class LoginInterceptor extends AbstractInterceptor {
	private String key;//保存登录信息的key
	public void setKey(String key) {
		this.key = key;
	}
	@Override
	public String intercept(ActionInvocation arg0) throws Exception {
		ActionContext actionContext = arg0.getInvocationContext();
		String result = (String) actionContext.get(this.key);//根据key取得属性
		if(result == null){
			ServletActionContext.getRequest().setAttribute("msg", "你还未登录");
			return "login";
		}else{
			return arg0.invoke();//如果查询到登录信息,则执行请求Action的方法
		}
	}

}

  • 在struts.xml文件中设置新的拦截器
<interceptors><!--  声明自定义的拦截器-->
	<interceptor name="MyInterceptor" class="mao.shu.Interceptor.MyInteceptor"></interceptor>
	
	<interceptor name="LoginInterceptor" class="mao.shu.Interceptor.LoginInterceptor"></interceptor>
</interceptors>
  • 配置拦截器统一跳转到"login.page"路径
	 <global-results><!--  拦截器统一的跳转路径-->
	 	<result name="login">/login.jsp</result>
	 </global-results>
  • 在MessageAction的配置中,使用该拦截器,并设置属性"key"的参数内容,假设登录信息使用"uid"为名称保存
 <action name="MessageAction" class="mao.shu.action.MessageAction">
	    <interceptor-ref name="defaultStack"></interceptor-ref><!--  使用struts2默认的拦截器-->
		<interceptor-ref name="LoginInterceptor">
		<param name="key">uid</param><!--  设置拦截器属性内容-->
		</interceptor-ref>
</action>  
  • 定义/login.jsp页面,登录的本质就是在用户输入正确的信息之后,将用户的登录信息保存在session属性之中,所以只为了模拟一个登录检测这个login.jsp页面只需要在页面之中设置一个session属性即可
  • 表示只有访问过这个页面才算是登录过.
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
	session.setAttribute("uid", "xiemaoshu");
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>${msg} </h1>
</body>
</html>

在这里插入图片描述

拦截器栈

  • 所谓的拦截器栈指的是配置一族拦截器为统一的名字,而在要使用的位置直接使用拦截器栈的名字即可操作.它的定义同样要在struts.xml文件中完成.
<interceptors><!--  声明自定义的拦截器-->
	<interceptor name="MyInterceptor" class="mao.shu.Interceptor.MyInteceptor"></interceptor>
	<interceptor name="LoginInterceptor" class="mao.shu.Interceptor.LoginInterceptor"></interceptor>
	
	<!--  声明拦截器栈-->
	<interceptor-stack name="maoshuStack">
		<interceptor-ref name="MyInterceptor"/>
		<interceptor-ref name="LoginInterceptor"/>
		<interceptor-ref name="defaultStack"/>
	</interceptor-stack>
</interceptors>
  • 在action配置的时候,只需要使用拦截器栈即可
<action name="MessageAction" class="mao.shu.action.MessageAction">
	<interceptor-ref name="maoshuStack">
		<param name="key">uid</param><!--  设置拦截器属性内容-->
	</interceptor-ref>
	
	<result name="success">/welcome.jsp</result>
</action>  
  • 以后开发中,往往会将许多的拦截器定义在拦截器栈之中.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值