邪恶小代码

导航

Struts2学习第四天——拦截器及文件上传

1、概述

Struts2的很多核心功能都是由拦截器完成的。

拦截器很好的实现了AOP的编程思想,在动作的执行之前和结果的返回之后,做拦截处理。

 

2、struts2的默认拦截器栈

 

 

 

3、自定义拦截器

 

Struts2提供的拦截器有很多,有些并不是默认的,如果需要只能手动打开。当然,也可以自定义拦截器。

 

1、定义

 

创建一个类,继承AbstractInterceptor或者实现Interceptor

 

 1 public class TimerInterceptor extends AbstractInterceptor {
 2     
 3     public void init(){
 4         System.out.println("TimerInterceptor初始化");
 5     }
 6     
 7     /**
 8      * struts会在请求Action之前和Action之后调用
 9      */
10     @Override
11     public String intercept(ActionInvocation invocation) throws Exception {
12         //请求Action之前的代码
13         long start=System.currentTimeMillis();//返回毫秒数
14         
15         String ret=invocation.invoke();//invoke()执行Action组件
16         
17         long end=System.currentTimeMillis();
18         System.out.println("用时"+(end-start)+"毫秒"+ret);
19         //返回结果字符串
20         return ret;
21     }

2、声明

struts.xml配置文件中声明该拦截器。

1     <interceptors>
2             <interceptor name="CurrentTime" class="com.house.interceptor.TimerInterceptor"/>
3             </interceptor>
4     </interceptors>

3、使用

在动作中使用。

注意:使用了自定义的拦截器,默认的拦截器将不再起作用。如果需要使用它们,必须手动声明。

 1 <action name="*HouserUserAction" class="com.house.action.HouserUserAction" method="{1}">
 2      <interceptor-ref name="CurrentTime"></interceptor-ref>       
 3     <result name="register_success">/page/login.jsp</result>
 4 </action>

 

4、拦截器栈

默认的拦截器是以拦截器栈的形式存在的。如果使用了非默认的拦截器(包括自定义的拦截器和框架提供的其它拦截器),需要将默认的拦截器栈手动声明才可以继续使用。拦截器的拦截顺序,遵守其在拦截器栈中的声明顺序。

拦截器的继承体系

 

自定义拦截器栈及引入

<!-- 自定义拦截器 -->
        <interceptors>
            <interceptor name="CurrentTime" class="com.house.interceptor.TimerInterceptor"/>
            <interceptor name="Permission"  class="com.house.interceptor.PermissionInterceptor">
                <param name="excludeMethods">login,reg</param><!--拦截时过滤这两个页面 -->
            </interceptor>
        
        <!-- 拦截器栈 -->
            <interceptor-stack name="myStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="CurrentTime"></interceptor-ref>
                <!-- <interceptor-ref name="Permission"/> -->
            </interceptor-stack>
        </interceptors>
   <!-- 引入拦截器栈 -->
        <default-interceptor-ref name="myStack"></default-interceptor-ref>

文件上传

 struts2为文件上传下载提供了更好的实现机制,在这里我分别就单文件上传和多文件上传的源代码进行一下讲解,这里需要导入文件下载上传的两个jar文件,一个是commons-fileupload-1.2.2.jar,另一个是commons-io-2.0.1.jar

struts2单文件上传:

<!--在进行文件上传时,表单提交方式一定要是post的方式,因为文件上传时二进制文件可能会很大,还有就是enctype属性,这个属性一定要写成multipart/form-data,
  不然就会以二进制文本上传到服务器端--> 
  <form action="fileUpload.action" method="post" enctype="multipart/form-data">
      
        username: <input type="text" name="username"><br>
        file: <input type="file" name="file"><br>
        
        <input type="submit" value="submit">
    </form>

 FileUploadAction

 

public class FileUploadAction extends ActionSupport
{
    private String username;
    
   //注意,file并不是指前端jsp上传过来的文件本身,而是文件上传过来存放在临时文件夹下面的文件
    private File file;
    
    //提交过来的file的名字
    private String fileFileName;
    
    //提交过来的file的MIME类型
    private String fileContentType;

    public String getUsername()
    {
        return username;
    }

    public void setUsername(String username)
    {
        this.username = username;
    }

    public File getFile()
    {
        return file;
    }

    public void setFile(File file)
    {
        this.file = file;
    }

    public String getFileFileName()
    {
        return fileFileName;
    }

    public void setFileFileName(String fileFileName)
    {
        this.fileFileName = fileFileName;
    }

    public String getFileContentType()
    {
        return fileContentType;
    }

    public void setFileContentType(String fileContentType)
    {
        this.fileContentType = fileContentType;
    }
    
    @Override
    public String execute() throws Exception
    {
        String root = ServletActionContext.getServletContext().getRealPath("/upload");
        
        InputStream is = new FileInputStream(file);
        
        OutputStream os = new FileOutputStream(new File(root, fileFileName));
        
        System.out.println("fileFileName: " + fileFileName);

    // 因为file是存放在临时文件夹的文件,我们可以将其文件名和文件路径打印出来,看和之前的fileFileName是否相同
        System.out.println("file: " + file.getName());
        System.out.println("file: " + file.getPath());
        
        byte[] buffer = new byte[500];
        int length = 0;
        
        while(-1 != (length = is.read(buffer, 0, buffer.length)))
        {
            os.write(buffer);
        }
        
        os.close();
        is.close();
        
        return SUCCESS;
    }
}

这里的file并不是真正指代jsp上传过来的文件,当文件上传过来时,struts2首先会寻找struts.multipart.saveDir(这个是在default.properties里面有)这个name所指定的存放位置,我们可以新建一个struts.properties属性文件来指定这个临时文件存放位置,如果没有指定,那么文件会存放在tomcat的apache-tomcat-7.0.29\work\Catalina\localhost\目录下,然后我们可以指定文件上传后的存放位置,通过输出流将其写到流里面就行了,这时我们就可以在文件夹里看到我们上传的文件了。

在实际开发中,经常需要限制上传文件的大小和类型。这是因为如果客户端上传的文件过大会影响服务器性能,消耗服务器存储空间。

要实现限制上传文件的大小有两种常用方法。第一种是在<strutr>节点下添加struts.multiparty.maxSize常量,代码如下

<constant name="struts.multiparty.maxSize" value="50000000"/>

 它是一个全局配置,可以实现对所有<action>文件上传大小的限制,value的单位是字节。默认值是2MB,如果大于2M一定要修改该值。

第二种方法是在<action>中配置拦截器,它可以限制单个<action>的文件上传大小。

<interceptor-refname="fileUpload">
<paramname="allowedTypes">
image/png,image/gif,image/jpeg
</param>
</interceptor-ref>
上面配置的是上传文件类型的限制,其实共有两个参数

maximumSize(可选)-这个拦截器允许的上传到action中的文件最大长度(以byte为单位).注意这个参数和在webwork.properties中定义的属性没有关系。
allowedTypes(可选)-以逗号分割的contentType类型列表(例如text/html),这些列表是这个拦截器允许的可以传到action中的contentType.如果没有指定就是允许任何上传类型.

多文件上传

public class UploadAction extends ActionSupport {
    /**
    private String title;
    private File upload;//和上传输入的域名称必须一致,类型必须是file
    //注意,file并不是指前端jsp上传过来的文件本身,而是文件上传过来存放在临时文件夹下面的文件
    private String uploadFilename;//用于接收输入域上传的文件名
    //注意:文件名称和文件类型的名称前缀必须相同
    private String uploadContentType;//上传文件的MIME类型
    
    
    
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public File getUpload() {
        return upload;
    }
    public void setUpload(File upload) {
        this.upload = upload;
    }
    public String getUploadFilename() {
        return uploadFilename;
    }
    public void setUploadFilename(String uploadFilename) {
        this.uploadFilename = uploadFilename;
    }
    public String getUploadContentType() {
        return uploadContentType;
    }
    public void setUploadContentType(String uploadContentType) {
        this.uploadContentType = uploadContentType;
    }
*/
    private File[] upload;//多文件上传对应数组
    private String[] uploadFilename;//多文件对应的名字
    private String[] uploadContentType;
    
    public File[] getUpload() {
        return upload;
    }

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

    public String[] getUploadFilename() {
        return uploadFilename;
    }

    public void setUploadFilename(String[] uploadFilename) {
        this.uploadFilename = uploadFilename;
    }

    public String[] getUploadContentType() {
        return uploadContentType;
    }

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

    @Override
    public String execute() throws Exception{
        FileInputStream fis=null;
        FileOutputStream fos=null;
         //获取需要上传文件的文件路径
        String basePath= ServletActionContext.getServletContext().getRealPath("/upload");//服务器upload下
        //判断文件是否上传,如果上传的话将会创建该目录  
        if(upload!=null&&upload.length>0){
            for(int i=0;i<upload.length;i++){
                File file=upload[i];
                fis=new FileInputStream(file);
                String fileName=basePath+"/upload"+uploadFilename[i];
                fos=new FileOutputStream(fileName);
                int c=0;
                while((c=fis.read())!=-1){
                    fos.write(c);
                }
                fis.close();
                fos.close();
            }
        }    
        return "upload";
    }
          
          
        //第二种文件上传的方法  
        //FileUtils.copyFile(upload,new File(uploadFile+"\\"+uploadFileName));  
        //FileUtils.copyFile(upload,new File(uploadFile,uploadFileName));  
          
        //第三种方法  
//      BufferedReader bReader=new BufferedReader(new InputStreamReader(new FileInputStream(upload)));  
//      BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(uploadFile+"\\"+uploadFileName)));  
          
//      try{  
//          char[] str=new char[1024];  
//          int i=0;  
//          while((i=bReader.read(str))>0){  
//              bWriter.write(str,0,i);   
//          }  
//      }catch(Exception e){  
//          e.printStackTrace();  
//      }finally{  
//          bReader.close();  
//          bWriter.close();  
//          uploadFile.delete();  
//      }    
View Code

文件下载

定义一个Action类,FileDownload.java

package com.struts2.filedownload;

import java.io.InputStream;


import org.apache.struts2.ServletActionContext;


import com.opensymphony.xwork2.ActionSupport;

//文件下载
public class FileDownload extends ActionSupport{
    
    private int number ;

    private String fileName;

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
    
    public String getFileName() {
        return fileName;
    }

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

    //返回一个输入流,作为一个客户端来说是一个输入流,但对于服务器端是一个 输出流
    public InputStream getDownloadFile() throws Exception
    {
        if(1 == number)
        {
           this.fileName = "Dream.jpg" ;
           //获取资源路径
           return ServletActionContext.getServletContext().getResourceAsStream("upload/Dream.jpg") ;
        }
        
        else if(2 == number)
        {
            this.fileName = "jd2chm源码生成chm格式文档.rar" ;
            //解解乱码
            this.fileName = new String(this.fileName.getBytes("GBK"),"ISO-8859-1");
            return ServletActionContext.getServletContext().getResourceAsStream("upload/jd2chm源码生成chm格式文档.rar") ;
        }
        else
           return null ;
    }
    
    @Override
    public String execute() throws Exception {
        
        return SUCCESS;
    }

}

在struts.xml文件中配置相关信息

<struts>      
   <package name="struts2" extends="struts-default">      
       <action name="FileDownload" class="com.struts2.filedownload.FileDownload">
           <result name="success" type="stream">
               <param name="contentType">text/plain</param>
               <param name="contentDisposition">attachment;fileName="${fileName}"</param>
               <param name="inputName">downloadFile</param>
               <param name="bufferSize">1024</param>
           </result>
       </action>
   
   </package>
   
</struts>

1.结果类型必须要写成 type="stream"  ,与之对应的处理类是 org.apache.struts2.dispatcher.StreamResult

2.涉及到的参数:


3.

1)  <param name="contentDisposition">attachment;fileName="${fileName}"</param>

     contentDisposition默认是 inline(内联的), 比如说下载的文件是文本类型的,就直接在网页上打开,不能直接打开的才会打开下载框自己选择

2)  attachment :下载时会打开下载框

3)  fileName="${fileName}" :在这定义的名字是一个动态的,该名字是显示在下载框上的文件名字

4.<param name="inputName">downloadFile</param>,这个downloadFile名字要和FileDownload.java类中的getDownloadFile()方法名去掉get 一致

三)用于显示下载的链接界面 filedownload.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
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 'filedownload.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>
  
    <h2>文件下载内容:</h2><br/>
    Dream.jpg:<a href="FileDownload.action?number=1">点击下载</a><br/>
    jd2chm源码生成chm格式文档.rar:<a href="FileDownload.action?number=2">点击下载2</a>
    
    
  </body>
</html>

 

posted on 2017-03-20 21:22  邪恶小代码  阅读(1133)  评论(0编辑  收藏  举报