为了账号安全,请及时绑定邮箱和手机立即绑定

Java框架中的拦截器简介

拦截器
一:

1.Struts 2架构分析

  1. 下面我们开始介绍结构图中所涉及的对象:
    (1.)ActionMapper:提供了在请求和Action调用的映射信息,ActionMapper根据请求的URL来查找是否存在对应的Action调用请求,如果有,则返回一个描述,Action映射的ActionMapping对象,如果没有找到匹配的Action调用请求,则返回null。
    (2.)ActionMapping:ActionMapping保存了调用Action的映射信息,其中必须保存Action的命名空间信息和name属性信息。
    (3.)ActionProxy:ActionProxy在XWork和正真的Action之间充当代理,在执行Action的过程中,因为使用代理而非直接操作对象,所以可以在Action执行前后执行额外的操作。
    (4.)ActionInvocation:标示Action的执行状态,它保存拦截器(按配置顺序),Action实例。Actionlnvocation由ActionProxy创建,通过调用invoke()方法开始Action的执行,执行顺序为按配置顺序执行拦截器,拦截器执行完毕后执行Action,Action执行结束后返回结果字符串,匹配对应的Result后,再一次执行拦截器。
    (5.)Interceptor(拦截器):拦截器是一种可以再请求处理之前或者之后执行的Struts 2组件。拦截器是Struts 2重要特性,Struts 2框架的绝大多数功能是通过拦截器完成的。
    二:Struts 2的拦截器
  2. 为什么使用拦截器:
    便于请求数据的封装,类型转换,数据效验,解析上传文件,防止表单多次提交等。
    拦截器的方法在Action执行之前或者执行之后自动地执行,从而将通用的操作动态插入到Action执行的前后,这样有利于系统的解耦。
    2.拦截器栈:
    从结构上看,拦截器相当于多个拦截器的组合,拦截器栈也是拦截器同样可以和其他拦截器(或拦截器栈)一起组成更强大的拦截器栈。
    3.拦截器的工作原理:
    拦截器围绕着Action 和Result的执行而执行。从上图可以看出,struts 2拦截器的实现原理和Servlte Filter的实现原理差不多,以链试执行,对正真要执行的方法(execute())进行拦截。首先执行Action配置的拦截器,在Action和Result执行之后拦截器在一次执行(与先前调用相反的顺序)在此链式的执行过程中,任何一个拦截器都可以直接返回,从而终止余下的拦截器,Action及Result的执行。
    当ActionInvocation的invoke()方法被调用时,开始配置Action配置的第一个拦截器,拦截器做出相应处理后再次调用ActionInvocation的invoke()方法,ActionInvocation对象负责跟踪执行过程的状态,并且把控制权交给合适的拦截器。ActionInvocation通过调用拦截器的intercept()方法将控制转交给拦截器,因此拦截器的执行可以看做一个递归的过程,后续拦截器继续执行,直到最后一个拦截器。

4.拦截器有一个三阶段的,有条件的执行周期:
(1.)做一下Action执行前的预处理。拦截器可以准备,过滤,改变或者操作任何可以访问的数据,包括Action。
(2.)调用ActionInvocation的invoke()方法将控制权转交给后续的拦截器或者返回字符串终止执行,如果拦截器决定请求的处理不应该继续,可以不调用invoke()方法,而不是直接返回一个控制字符串。通过这种方式,可以停在后续的执行,并且决定将那个结果呈现给客户端。
(3.)做一下Action执行后的处理。此时拦截器依然可以改变可以发访问的对象和数据,只是此时框架已经选择了一个结果呈现给客户端了。
示例如下:
public class MytimerInterceptor extends AbstractInterceptor{

@Override
public String intercept(ActionInvocation invocation) throws Exception {
    // TODO Auto-generated method stub
    //执行Action之后的工作,获取开始执行时间
    long startTime=System.currentTimeMillis();
    System.out.println("开始时间:"+startTime);
    //2.执行后续拦截器
    String result=invocation.invoke();
    //3.执行action之后的工作,计算并输出时间
    long endTime=System.currentTimeMillis();
    long execTime=endTime-startTime;
    System.err.println("结束时间:"+endTime);
    System.err.println("总共用时:"+execTime);
    return result;
}

}

三:拦截器的配置
  1. 配置拦截器需要经过以下两个步骤:
  2. 通过<interceptor……./>元素定义拦截器。
  3. 通过<interceptor-ref…../>元素来使用拦截器。
    示例代码如下 struts.xml文件中:
    <package name="default" namespace="/" extends="struts-default">
    <interceptors>
    <interceptor name="myTimer"
    class="cn.bdqn.interceptor.MytimerInterceptor">
    </interceptor>
    </interceptors>

    <action name="invocation" class="cn.bdqn.action.Invocation"
        method="time">
        <result name="success">/index.jsp</result>
    
        <interceptor-ref name="myTimer"></interceptor-ref>
        <!-- 引用默认拦截器栈 -->
        <interceptor-ref name="defaultStack"></interceptor-ref>
    </action>

    </package>

四:Struts 2内置拦截器
  1. params 拦截器:
    将请求中的数据设置到Action的属性上。
  2. staticParams拦截器:
    在配置文件中通过<action >元素的子元素<param>设置的参数设置到对应的Action的属性中。
  3. servletConfig拦截器:
    提供了将一种源于Servlet API的各种对象注入,Action当中的简洁方法,Action必须实现相应对应的接口,servletConfig拦截器才能将对应的Servlet对象注入Action中。
    ServletAPI对象的接口如下:
    接口 作用
    ServletContextAware 设置ServletContext
    ServletRequestAware 设置HttpServletRequest
    ServletResponseAware 设置HttpServletResponse
    ParameterAware 设置Map类型的请求参数
    RequestAware 设置Map类型的请求(HttpServletRequest)属性
    SessionAware 设置Map类型的会话(HttpSession)属性
    ApplicationAware 设置Map类型的应用程序作用域对象(ServletContext)

  4. fileUpload拦截器:
    拦截器将文件和元数据从多重要求(multipart/form-data)转换为常规的请求数据,以便将他们设置在对应的Action属性上,实现文件上传。
  5. validation拦截器:
    该拦截器用于执行数据效验。
  6. work flow拦截器:
    该拦截器提供当数据效验错误时终止执行流程的功能。
  7. exception拦截器:
    该拦截器用于捕获异常,并且能够根据异常类型捕获的异常映射到用户自定义的错误页面。
    五:自定义拦截器
  8. 改接口提供了三个方法:
    Com.opensymphony.xwork2.interceptor.Interceptor
    (1.)Void init();该拦截初始化后再改拦截器执行拦截之前,系统回调该方法。执行一次
    (2.)void destroy();该方法跟init()方法对应。在拦截器销毁之前系统回调。
    (3.)String intercept(ActionInvocation invocation)throws Exception:该方法是用户需要实现的拦截动作。该方法会返回一个字符串作为逻辑视图。
    2.处此之外继承com.opensymphony.xwork2.interceptor.AbstractInterceptor类是更简单的一种实现拦截器的方式,AbstractInterceptor类提供了init()和destroy()方法的实现,这样我们只需要实现intercept()方法,就可以创建自己的拦截器了。
    六:文件上传及下载:

    首先导入JAR架包:

package cn.bdqn.action;包中文件:
UploadAction 类:
package cn.bdqn.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class UploadAction extends ActionSupport {
//封装文件标题属性
private String title;
//封装上传文件属性
private File upload; //upload 与jsp页面中 组件<<s:file >name属性值保持一致
//获取提交的文件类型
private String uploadContentType;// 命名规则 <s:file name=upload >name属性值开头
//封装上传文件名称
private String uploadFileName;//命名规则 <s:file name=upload>name属性值开头
//获取文件上传的路径
private String savePath; //上传路径

public String getUploadContentType() {
    return uploadContentType;
}

public void setUploadContentType(String uploadContentType) {
    this.uploadContentType = uploadContentType;
}

public String getUploadFileName() {
    return uploadFileName;
}

public void setUploadFileName(String uploadFileName) {
    this.uploadFileName = uploadFileName;
}

@Override
public String execute() throws Exception {
    byte[] buffer=new byte[1024];
    //读取配置文件
    FileInputStream fis=new FileInputStream(this.getUpload());
    //保存文件,并设置保存目录路径
    FileOutputStream fos=new FileOutputStream(getSavePath()+"\\"+this.getUploadFileName());
    int length=fis.read(buffer);

    while (length>0) {
        //每次写入length长度的内容
        fos.write(buffer,0, length);
        length=fis.read(buffer);
    }   
    fis.close();
    fos.flush();
    fos.close();
    return SUCCESS;
}
//获取上传文件的路径 通过读取保存目录获得保存路径
public String getSavePath() {
    return ServletActionContext.getServletContext().getRealPath(savePath);
}

public void setSavePath(String savePath) {
    this.savePath = savePath;
}

public File getUpload() {
    return upload;
}

public void setUpload(File upload) {
    this.upload = upload;
}

public String getTitle() {
    return title;
}
public void setTitle(String title) {
    this.title = title;
}

}

ManyUploadAction 类:
package cn.bdqn.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class ManyUploadAction extends ActionSupport {
//封装文件标题属性
private String title;
//封装上传文件属性
private File[] upload; //upload 与jsp页面中 组件<<s:file >name属性值保持一致

//获取提交的文件类型
private String[] uploadContentType;// 命名规则 <s:file name=upload >name属性值开头  
//封装上传文件名称
private String[] uploadFileName;//命名规则 <s:file name=upload>name属性值开头 

//获取文件上传的路径
private String savePath;  //上传路径

@Override
public String execute() throws Exception {
    byte[] buffer=new byte[4096];

    for(int i=0;i<upload.length;i++){
        //读取配置文件
        FileInputStream fis=new FileInputStream(this.getUpload()[i]);
        //保存文件,并设置保存目录路径
        FileOutputStream fos=new FileOutputStream(getSavePath()+"\\"+this.getUploadFileName()[i]);
        int length=fis.read(buffer);

        while (length>0) {
            //每次写入length长度的内容
            fos.write(buffer,0, length);
            length=fis.read(buffer);
        }   
        fis.close();
        fos.flush();
        fos.close();

    }
    return SUCCESS;
}
//获取上传文件的路径 通过读取保存目录获得保存路径
public String getSavePath() {
    return ServletActionContext.getServletContext().getRealPath(savePath);
}

public void setSavePath(String savePath) {
    this.savePath = savePath;
}

public String[] getUploadContentType() {
    return uploadContentType;
}
public void setUploadContentType(String[] uploadContentType) {
    this.uploadContentType = uploadContentType;
}
public String[] getUploadFileName() {
    return uploadFileName;
}
public void setUploadFileName(String[] uploadFileName) {
    this.uploadFileName = uploadFileName;
}
public void setUpload(File[] upload) {
    this.upload = upload;
}
public File[] getUpload() {
    return upload;
}

public String getTitle() {
    return title;
}
public void setTitle(String title) {
    this.title = title;
}

}

FileDownAction类:
package cn.bdqn.action;

import java.io.BufferedInputStream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

import java.io.InputStream;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class FileDownAction extends ActionSupport {
private String inputPath; //下载文件的目录
public String getInputPath() {
return inputPath;
}

public void setInputPath(String inputPath) {
    this.inputPath = inputPath;
}

//下载文件的文件名
private String fileName;
//读取下载文件的输入流

// private InputStream inputStream;
//下载文件的类型
private String conetntType;

public  InputStream getInputStream() throws FileNotFoundException{
    /*return ServletActionContext
            .getServletContext()
            .getResourceAsStream(inputPath + "\\" + fileName);*/
    String path=ServletActionContext.getServletContext().getRealPath(inputPath);
return new BufferedInputStream(new FileInputStream(path+"\\"+fileName));

}

@Override
public String execute() throws Exception {

/ //创建一个File对象
File file=new File(fileName);
//通过读取File对象创建输入流
inoutStream=new FileInputStream(file) ;
//得到实际的文件名称
fileName=file.getName();
//
conetntType=this.getConetntType();
/

    return SUCCESS;
}

public String getFileName() {
    return fileName;
}
public void setFileName(String fileName) {
    this.fileName = fileName;
}

/ public InputStream getInputStream() {
return inputStream;
}
/
public String getConetntType() {
return conetntType;
}
// public void setInputStream(InputStream inputStream) {
// this.inputStream = inputStream;
// }

public void setConetntType(String conetntType) {
    this.conetntType = conetntType;
}

}

Jsp页面示例代码如下
Filedown.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>My JSP 'filedown.jsp' starting page</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>
<a href="download.action?fileName=1.jpg">点击此处下载文档</a>
</body>
</html>

fileinput.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>文件上传</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>
<s:form action="upload.action" enctype="multipart/form-data" method="post">

    文件一:<s:file name="upload" label="选择文件"></s:file><br/>

<%-- 文件二:<s:file name="upload" label="选择文件"/><br/>
--%>
<s:submit name="submit" value="上传文件"/>
</s:form>
</body>
</html>

manyfileinput.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>文件上传</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">    
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>
<s:form action="mangUpload.action" enctype="multipart/form-data" method="post">

    文件一:<s:file name="upload" label="选择文件"></s:file><br/>
         文件二:<s:file name="upload" label="选择文件"/><br/>

<s:submit name="submit" value="上传文件"/>
</s:form>
</body>
</html>

manyupload_success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>文件上传</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>

您所上传的文件是:
<s:property value="uploadFileName" />
<br /> 文件类型:
<s:property value="uploadContentType" />
<br />
<s:iterator value="uploadFileName" status="i">
 图片:<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="<%=basePath%>upload/<s:property />" />
</s:iterator>

</body>
</html>

upload_success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>文件上传</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>
您所上传的文件是:
<s:property value="uploadFileName" />
<br /> 文件类型:
<s:property value="uploadContentType" />
<br /> 图片:
<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="<%=basePath%>upload/<s:property value='uploadFileName'/>" />
</body>
</html>
示例代码如下: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>
<constant name="struts.multipart.maxSize" value="10485760" />
<constant name="struts.i18n.encoding" value="UTF-8" />
<constant name="struts.ui.theme" value="simple" />
<package name="default" namespace="/" extends="struts-default">

    <action name="upload" class="cn.bdqn.action.UploadAction">
        <!-- param 标签的name值为action中定义的属性 -->
        <param name="savePath">/upload</param>
        <result name="success">/upload_success.jsp</result>
    </action>

    <!-- 多文件上传 -->
    <action name="mangUpload" class="cn.bdqn.action.ManyUploadAction">
        <!-- 通过设置参数方式保存路径 -->
        <param name="savePath">/upload</param>
        <result name="success">/manyupload_success.jsp</result>
    </action>
    <!-- 下载 注意事项,下载的文件必须提前存在upload文件中 -->
    <action name="download" class="cn.bdqn.action.FileDownAction">
        <!-- inputPath 为action 中 定义的下载文件目录  WebRoot下文件名upload -->
        <param name="inputPath">/upload</param>
        <result name="success" type="stream">
            <!-- contentType 下载文件类型 此处配置通用的 -->
            <param name="contentType">application/octet-stream</param>
            <!-- inputName 固定命名,为action中定义的inputStream类型的属性名称 -->
            <param name="inputName">inputStream</param>
            <!--
                attachment表示下载弹出对话框,filename下载文件名称 ${fileName}为读取action中下载文件名称
            -->
            <param name="contentDisposition">attachment;filename="${fileName}"</param>
            <!-- 上传或下载的缓冲区 4k -->
            <param name="bufferSize">4096</param>
        </result>

    </action>
</package>

</struts>

点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
40
获赞与收藏
344

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消