zoukankan      html  css  js  c++  java
  • Struts2学习(七)

    Servlet实现下载

    1、Servlet 3.1之前实现文件上传

    package ecut.request;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class FirstUploadServlet extends HttpServlet {
    
        private static final long serialVersionUID = -7777691027208490971L;
    
        @Override
        protected void doGet( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException {
            throw new RuntimeException( "不支持GET方式上传" );
        }
    
        @Override
        protected void doPost( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException {
            
            request.setCharacterEncoding( "UTF-8" );
            
            // 上传文件时,只考虑文本文件,不考虑其它文件
            BufferedReader reader = request.getReader();
            //InputStream in = request.getInputStream();
    
            String s ; 
            while( ( s = reader.readLine() ) != null ){
                System.out.println( s );
            }
            
        }
        
        
    
    }

    2、Servlet 3.1 开始实现文件上传

    package ecut.request;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.Part;
    
    public class SecondUploadServlet extends HttpServlet {
    
        private static final long serialVersionUID = 4485463572490572537L;
    
        @Override
        protected void doGet( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException {
            throw new RuntimeException( "不支持GET方式上传" );
        }
    
        @Override
        protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException {
            
            // String username = request.getParameter( "username" ) ; // <input type="text" name="username" >
            
            Part part = request.getPart( "upfile" ) ; // <input type="file" name="upfile" >
            System.out.println( part );
            
            /* Servlet 3.0 中获得文件名的做法
            String cd = part.getHeader( "Content-Disposition" );
            System.out.println( cd );
            String s = "filename=""; 
            int index = cd.indexOf( s );//找到filename的位置
            String name = cd.substring( index + s.length() , cd.length() - 1 );//获取文件名
            System.out.println( name );
            */
            
            // part.getName() ; // name="upfile"
            String filename = part.getSubmittedFileName(); // Servlet 3.1 开始出现的方法
            
            part.write( filename );
            
        }
        
        
    
    }

    Struts2实现下载

    1、首先在配置文件中指定存储位置storePath,在配置文件中action标签中通过 param 为 当前的 Action 实例 指定一个参数 ,实际上是 Action 类中的一个 属性 。

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    
    <struts>
    <package name="upload" namespace="/upload" extends="struts-default" >
        
           <action name="action/single" class="ecut.upload.SingleFileUploadAction" >
               <!-- 通过 param 为 当前的 Action 实例 指定一个参数 ( 实际上是 Action 类中的一个 属性 ) -->
               <param name="storePath">D:/</param>
               
               <result name="success" type="redirectAction">
                   <param name="actionName">success/single</param>
               </result>
                <result name="fail" type="redirectAction">
                   <param name="actionName">fail/single</param>
               </result>
    </action> </struts>

    2、struts.xml中的包继承了struts-default包,struts-default包中指定了默认的拦截器栈,里面有一个fileUpload interceptor,Struts 2实现文件上传就是由这个拦截器来实现的。所以在struts.xml中最好先引用一下默认拦截器。

    3、参照fileUpload interceptor api 的完成Action类的编写,由图中可知需要添加以下参数

    • [File Name] : File - 实际文件名,和页面的文件名相对应,表单中是xxx,则Action类中也要有xxx属性,且名称保持一致
    • [File Name]ContentType : String - 文件的内容类型,命名前缀得和文件名称保持一致,xxxContentType
    • [File Name]FileName : String -上传文件的实际名称,命名前缀得和文件名称保持一致,xxxFileName 

    Jsp代码:

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%>
    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Struts Upload</title> </head> <body> <h5>文件上传</h5> <!-- method 必须是 POST ,enctype 必须是 multipart/form-data --> <form action="${ pageContext.request.contextPath }/upload/action/single" method="post" enctype="multipart/form-data"> <input type="file" name="upload" > <input type="submit" value="上传" > </form> </body> </html>

     Action类代码:

    package ecut.upload;
    
    import java.io.File;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.StandardCopyOption;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    
    import com.opensymphony.xwork2.Action;
    
    public class SingleFileUploadAction implements Action {
        
        private static Logger logger = LogManager.getLogger();
        //保存文件的位置,上传文件到那个目录
        private String storePath ;
        // [File Name] : File - the actual File,与表单中的name保持一致
        private File upload ; 
        // [File Name]ContentType : String - the content type of the file,文件内容类型
        private String uploadContentType ; 
        // [File Name]FileName : String - the actual name of the file uploaded (not the HTML name),实际的文件名
        private String uploadFileName ;
    
        @Override
        public String execute() throws Exception {
            //临时文件
            logger.info( "upload : " + upload );
            logger.info( "content type : " + uploadContentType );
            logger.info( "file name : " + uploadFileName );
            
            //getCanonicalPath获取规范化路径
            Path source = Paths.get( upload.getCanonicalPath() );
            
            Path target = Paths.get( this.storePath , uploadFileName );
            
            //Replace an existing file if it exists.
            Files.copy( source , target , StandardCopyOption.REPLACE_EXISTING );
            
            return SUCCESS;
        }
    
        public String getStorePath() {
            return storePath;
        }
    
        public void setStorePath(String storePath) {
            this.storePath = storePath;
        }
    
        public File getUpload() {
            return upload;
        }
    
        public void setUpload(File upload) {
            this.upload = upload;
        }
    
        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;
        }
        
    }

    Struts2  上传文件是先生成一个临时文件保存在临时目录下,上传成功后临时文件消失。

    4、上传默认的最大尺寸是,在 default.properties 中默认定义的大小是 2MB ,修改默认上传最大尺寸可以在xml中配置,可以指定全局的常量,也可以在action标签中设置某个action最大上传尺寸(struts.multipart.maxSize >= fileUpload.maximumSize )。

    struts.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    
    <struts>
    
        <!-- 允许在 action 的 名称 中使用 / 字符  -->
         <constant name="struts.enable.SlashesInActionNames" value="true" />
        <!-- 启用动态方法调用  <constant name="struts.enable.DynamicMethodInvocation" value="true" /> -->
        
        <!-- 修改 action 请求路径的后缀 -->
        <constant name="struts.action.extension" value="do,," />
        <!-- 解析器的作用是对request.getInputStream()返回的字节流进行解析获取文件内容、类型、名称(和resultType="stream" 实现下载原理一致) -->
        <!-- 指定 对上传的 字节流进行解析的解析器 : jakarta 、cos 、pell -->
        <constant name="struts.multipart.parser" value="jakarta" />
        <!-- 指定上传文件的尺寸 ( 在 default.properties 中默认定义的大小是 2MB )-->
        <constant name="struts.multipart.maxSize" value="2097152000" />
        
        <package name="upload" namespace="/upload" extends="struts-default" >
        
           <action name="action/single" class="ecut.upload.SingleFileUploadAction" >
               <!-- 通过 param 为 当前的 Action 实例 指定一个参数 ( 实际上是 Action 类中的一个 属性 ) -->
               <param name="storePath">D:/</param>
               
               <result name="success" type="redirectAction">
                   <param name="actionName">success/single</param>
               </result>
                <result name="fail" type="redirectAction">
                   <param name="actionName">fail/single</param>
               </result>
               
                <exception-mapping result="fail" exception="java.lang.Exception" />
                
               <interceptor-ref name="defaultStack">
                   <!-- 必须满足 struts.multipart.maxSize >=  fileUpload.maximumSize -->
                   <param name="fileUpload.maximumSize">20971520</param>
               </interceptor-ref>
               
           </action>
           
           <action name="success/single">
               <result>/WEB-INF/pages/upload/success_single.jsp</result>
           </action>
           
           <action name="fail/single">
               <result>/WEB-INF/pages/upload/fail_single.jsp</result>
           </action>
           
        </package>
    
    </struts>

    在配置文件中还可以指定解析器,struts 2的上传的与FirstUploadServlet 中的方法一致(servlet3.0之前上传的方式),需要去解析inputstream,strust 2 默认是jakarta解析器,去对inputStream 进行解析。如果超出最大尺寸会抛出异常,可以在action标签中指定局部的异常映射。

    5、多文件上传测试案例

    index.jsp

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%>
    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Struts Upload</title> </head> <body> <h5>文件上传</h5> <!-- method 必须是 POST ,enctype 必须是 multipart/form-data --> <form action="${ pageContext.request.contextPath }/upload/action/single" method="post" enctype="multipart/form-data"> <input type="file" name="upload" > <input type="submit" value="上传" > </form> <h5>文件上传</h5> <!-- method 必须是 POST ,enctype 必须是 multipart/form-data --> <form action="${ pageContext.request.contextPath }/upload/action/multiple" method="post" enctype="multipart/form-data"> <input type="file" name="upload" > <br> <input type="file" name="upload" > <br> <input type="file" name="upload" > <br> <input type="file" name="upload" > <br> <input type="submit" value="上传" > </form> </body> </html>

    success_single.jsp

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%>
    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>上传成功</title> </head> <body> <h1>上传成功</h1> </body> </html>

    fail_single.jsp

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%>
    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>上传失败</title> </head> <body> <h1>上传失败</h1> </body> </html>

    struts.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    
    <struts>
    
        <!-- 允许在 action 的 名称 中使用 / 字符  -->
         <constant name="struts.enable.SlashesInActionNames" value="true" />
        <!-- 启用动态方法调用  <constant name="struts.enable.DynamicMethodInvocation" value="true" /> -->
        
        <!-- 修改 action 请求路径的后缀 -->
        <constant name="struts.action.extension" value="do,," />
        <!-- 解析器的作用是对request.getInputStream()返回的字节流进行解析获取文件内容、类型、名称(和resultType="stream" 实现下载原理一致) -->
        <!-- 指定 对上传的 字节流进行解析的解析器 : jakarta 、cos 、pell -->
        <constant name="struts.multipart.parser" value="jakarta" />
        <!-- 指定上传文件的尺寸 ( 在 default.properties 中默认定义的大小是 2MB )-->
        <constant name="struts.multipart.maxSize" value="2097152000" />
        
        <package name="upload" namespace="/upload" extends="struts-default" >
        
           <action name="action/single" class="ecut.upload.SingleFileUploadAction" >
               <!-- 通过 param 为 当前的 Action 实例 指定一个参数 ( 实际上是 Action 类中的一个 属性 ) -->
               <param name="storePath">D:/</param>
               
               <result name="success" type="redirectAction">
                   <param name="actionName">success/single</param>
               </result>
                <result name="fail" type="redirectAction">
                   <param name="actionName">fail/single</param>
               </result>
               
                <exception-mapping result="fail" exception="java.lang.Exception" />
                
               <interceptor-ref name="defaultStack">
                   <!-- 必须满足 struts.multipart.maxSize >=  fileUpload.maximumSize -->
                   <param name="fileUpload.maximumSize">20971520</param>
               </interceptor-ref>
               
           </action>
           
           <action name="action/multiple" class="ecut.upload.MultipleFileUploadAction" >
               <!-- 通过 param 为 当前的 Action 实例 指定一个参数 ( 实际上是 Action 类中的一个 属性 ) -->
               <param name="storePath">D:/</param>
               
               <result name="success" type="redirectAction">
                   <param name="actionName">success/single</param>
               </result>
                <result name="fail" type="redirectAction">
                   <param name="actionName">fail/single</param>
               </result>
               
               <exception-mapping result="fail" exception="java.lang.Exception" />
               
               <interceptor-ref name="defaultStack">
                   <!-- 必须满足全局上传的文件尺寸最大值 struts.multipart.maxSize >=  单前action上传文件尺寸最大值fileUpload.maximumSize -->
                   <param name="fileUpload.maximumSize">20971520</param>
               </interceptor-ref>
               
           </action>
           
           <action name="success/single">
               <result>/WEB-INF/pages/upload/success_single.jsp</result>
           </action>
           
           <action name="fail/single">
               <result>/WEB-INF/pages/upload/fail_single.jsp</result>
           </action>
           
        </package>
    
    </struts>

    Action类

    package ecut.upload;
    
    import java.io.File;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.StandardCopyOption;
    import java.util.List;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    
    import com.opensymphony.xwork2.Action;
    
    public class MultipleFileUploadAction implements Action {
        
        private static Logger logger = LogManager.getLogger();
        
        private String storePath ;
        
        private List<File> upload ; 
        private  List<String> uploadContentType ; 
        private  List<String> uploadFileName ;
    
        @Override
        public String execute() throws Exception {
            logger.info("upload.get(0)对应的类型是uploadContentType.get(0),对应的文件名是uploadFileName.get(0)");
            
            for(int i =0 ; i < upload.size(); i++){
                //getCanonicalPath获取规范化路径
                Path source = Paths.get( upload.get(i).getCanonicalPath() );
                
                Path target = Paths.get( this.storePath , uploadFileName.get(i) );
                
                //Replace an existing file if it exists.
                Files.copy( source , target , StandardCopyOption.REPLACE_EXISTING );
            }
            return SUCCESS;
        }
    
        public String getStorePath() {
            return storePath;
        }
    
        public void setStorePath(String storePath) {
            this.storePath = storePath;
        }
    
        public List<File> getUpload() {
            return upload;
        }
    
        public void setUpload(List<File> upload) {
            this.upload = upload;
        }
    
        public List<String> getUploadContentType() {
            return uploadContentType;
        }
    
        public void setUploadContentType(List<String> uploadContentType) {
            this.uploadContentType = uploadContentType;
        }
    
        public List<String> getUploadFileName() {
            return uploadFileName;
        }
    
        public void setUploadFileName(List<String> uploadFileName) {
            this.uploadFileName = uploadFileName;
        }
        
    }

    Struts2实现国际化

    1、简介

    •  国际化简称i18n,其来源是英文单词 internationalization的首末字符i 和n。18为中间的字符数。
    •  国际化即是对于Web应用来说,页面在不同的语言环境下需要显示不同的效果。
    • Struts2中使用到国际化的地方有: jsp页面的国际化、Action信息国际化、转换错误信息的国际化、校验错误信息的国际化;
    • Struts2国际化文件分类: 全局范围国际化文件 、包范围国际化文件 、Action类范围国际化文件 。

    2、普通实现表单方式和Struts 2 标签去完成表单比较

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%>
    <%@ taglib prefix = "s" uri = "/struts-tags"%>
    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>国际化</title> <style type="text/css"> .login-form { width: 80% ; margin: 20px auto ; box-shadow: 0px 0px 5px 4px #d3d3d3; padding: 10px 10px ;} .login-form .form-row { height: auto ; overflow: hidden; border-bottom: 1px dotted #d3d3d3 ; padding-bottom: 5px ; } .login-form .form-row:last-child { border: none ; } .login-form .form-row i , .login-form .form-row b { height: 30px ; line-height: 30px ; } .login-form .form-row i { float: left ; width: 30% ; text-align: right ; font-style: normal ; font-size: 18px ; } .login-form .form-row b { float: right ; width: 70% ; text-align: left ; } .login-form .form-row b input { margin-left: 1% ; padding-left : 4px ; height: 20px ; line-height: 20px ; width: 96% ; border: 1px solid #dedede ; outline: none ; } .login-form .buttons { width: 70% ; margin-left: 30% ; } .login-form .buttons span { float : left ; width: 50% ; height: 30px ; line-height: 30px ; } .login-form .buttons span:first-child { text-align: center ; } .login-form .buttons span:last-child { text-align: center ; } .login-form .buttons span input { width: 80% ; } </style> </head> <body> <h3>原生HTML表单</h3> <div class="login-form"> <form action="${ pageContext.request.contextPath }/user/login" method="post" > <div class="form-row"> <i>用户名:</i> <b> <input type="text" name="username" ></b> </div> <div class="form-row"> <i>密码:</i> <b> <input type="password" name="password" > </b> </div> <div class=" form-row"> <div class="buttons"> <span > <input type="reset" value="重置"> </span> <span> <input type="submit" value="登录"> </span> </div> </div> </form> </div> <hr> <h3>Struts 2 表单(不支持国际化)</h3> <s:form namespace="/user" action="login" method="post" > <s:textfield label="用户名" name="username" /> <s:password label="密码" name="password" /> <s:reset value="重置" /> <s:submit value="登录" /> </s:form> </body> </html>

    Struts 2实现表单需要先导入标签库,查看Struts 2源码可以得知Struts的表单是用表格实现的,因此两个按钮不在同一行,不太美观,不介意使用Struts实现表单。但是Struts 2实现表单得依赖于Struts 2的标签,因此我们需要先了解Struts 2编写表单。

     3、配置文件编写

    • 国际化文件的命名规则

        基本名.properties 如:user_login.properties

        基本名_语言编码_国家编码.properties 如:user_login_en_US.properties, user_login_zh_CN.properties

        其中语言编码和国家编码是固定的,可以在JDK中Locale类的常量中找到。

    • 为了实现程序的国际化,必须先提供程序所需要的资源文件。资源文件的内容基本是key-value对,其中key是程序使用的部分(页面需要和配置文件中一致),而value是程序的显示部分。

    user_login_zh_CN.properties

    user.login.username.label= User Name
    user.login.password.label= Password
    user.login.reset.button= Reset
    user.login.submit.button= Login

    user_login_en_US.properties

    user.login.username.label=用户名
    user.login.password.label=密码
    user.login.reset.button=重置
    user.login.submit.button=登录

    index.jsp

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%>
    <%@ taglib prefix = "s" uri = "/struts-tags"%>
    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>国际化</title> <style type="text/css"> .login-form { width: 80% ; margin: 20px auto ; box-shadow: 0px 0px 5px 4px #d3d3d3; padding: 10px 10px ;} .login-form .form-row { height: auto ; overflow: hidden; border-bottom: 1px dotted #d3d3d3 ; padding-bottom: 5px ; } .login-form .form-row:last-child { border: none ; } .login-form .form-row i , .login-form .form-row b { height: 30px ; line-height: 30px ; } .login-form .form-row i { float: left ; width: 30% ; text-align: right ; font-style: normal ; font-size: 18px ; } .login-form .form-row b { float: right ; width: 70% ; text-align: left ; } .login-form .form-row b input { margin-left: 1% ; padding-left : 4px ; height: 20px ; line-height: 20px ; width: 96% ; border: 1px solid #dedede ; outline: none ; } .login-form .buttons { width: 70% ; margin-left: 30% ; } .login-form .buttons span { float : left ; width: 50% ; height: 30px ; line-height: 30px ; } .login-form .buttons span:first-child { text-align: center ; } .login-form .buttons span:last-child { text-align: center ; } .login-form .buttons span input { width: 80% ; } </style> </head> <body> <h3>原生HTML表单</h3> <div class="login-form"> <form action="${ pageContext.request.contextPath }/user/login" method="post" > <div class="form-row"> <i>用户名:</i> <b> <input type="text" name="username" ></b> </div> <div class="form-row"> <i>密码:</i> <b> <input type="password" name="password" > </b> </div> <div class=" form-row"> <div class="buttons"> <span > <input type="reset" value="重置"> </span> <span> <input type="submit" value="登录"> </span> </div> </div> </form> </div> <hr> <h3>Struts 2 表单(不支持国际化)</h3> <s:form namespace="/user" action="login" method="post" > <s:textfield label="用户名" name="username" /> <s:password label="密码" name="password" /> <s:reset value="重置" /> <s:submit value="登录" /> </s:form> <h3>Struts 2 表单(支持国际化,只有使用Struts标签才可以支持)</h3> <s:form namespace="/user" action="login" method="post" > <s:textfield key="user.login.username.label" name="username" /> <s:password key="user.login.password.label" name="password" /> <s:reset key="user.login.reset.button" /> <s:submit key="user.login.submit.button" /> </s:form> <hr> <!-- 语言代码小写,国家大写 --> <a href="${ pageContext.request.contextPath }/user/index?request_locale=zh_CN">中文</a> <a href="${ pageContext.request.contextPath }/user/index?request_locale=en_US">English</a> </body> </html>

    4、struts.xml文件配置

    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    
    <struts>
    
        <!-- 指定属性文件的 baseName 就是 除了 "_语言代码_国家或地区代码.properties" 之外的那部分 -->
        <constant name="struts.custom.i18n.resources" value="user_login" />
        
        <package name="user" namespace="/user" extends="struts-default" >
            
           <action name="index" >
               <result>/i18n/index.jsp</result>
           </action>
        
           <action name="login" ></action>
           
        </package>
    </struts>

    需要参照default.properites ( org/apache/struts2/default.properties,当需要找常量名称时候打开他)增加常量struts.custom.i18n.resources,指定属性文件的 baseName 就是 除了 "_语言代码_国家或地区代码.properties" 之外的那部分

    参考博客链接

    https://www.cnblogs.com/hellokitty1/p/5083663.html

    https://blog.csdn.net/weixin_36380516/article/details/72510292

    转载请于明显处标明出处

    https://www.cnblogs.com/AmyZheng/p/9230708.html

  • 相关阅读:
    用python将博客园的文章爬取到本地
    2016.7.9
    2016.7.8
    2016.7.7
    2016.7.5
    2016.7.4
    2016.7.3
    2016.7.2
    2016.6.28
    2016.6.27
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9230708.html
Copyright © 2011-2022 走看看