Struts2核心技术(三)

struts2的国际化

国际化的概念

国际化是指web程序在运行时,根据客户端请求的国家、语言的不同而显示不同的界面。 
例如,如果请求来自中文客户端,则页面的显示,提示信息等都是中文,如果是英文客户端,则显示英文信息。 
国际化的英文单词是Internationalization,但因为单词太长,简称I18N,I是第一个字母,18表示中间的字母个数,N是最后一个字母。

java中国际化的思路

1.必须先提供程序需要的资源文件,资源文件是很多键值对组成,键是程序使用的部分,值是页面显示的部分。  资源文件的命名规则:Name_language_country.properties  name是资源文件的基本名,可以自由定义。language和country都必须使用java给我们提供的名称。  

2.通过类加载资源文件,然后显示在页面上,java程序国际化的关键类是ResourceBundle 
            它有一个静态方法:
                    -getBundle(String baseName,Locale locale):baseName是资源文件的基本名,我们自己定义的那个,locale代表国家/语言 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

java国际化案例

第一步:创建两个国际化资源文件

              第一个文件:message_zh_CN.properties 
              内容:
                hello=您好

              第二个文件:message_en_US.properties 
              内容:
                hello=hello,world 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
第二步:在类中实现国际化 

        public class I18NDemo {

            public static void main(String[] args) { 
                //根据locale加载国际化资源文件
                ResourceBundle bundle=ResourceBundle.getBundle("com.cad.struts2.resource.message",Locale.CHINA);//加载中文资源文件,输出您好
                //ResourceBundle bundle=ResourceBundle.getBundle("com.cad.struts2.resource.message",Locale.US);//加载英文资源文件,输出hello,world
                String mess=bundle.getString("hello");
                System.out.println(mess);
            }
        } 

            完成java国际化主要是提供不同语言的资源文件,然后使用ResourceBundle来根据不同的Locale加载语言资源文件,再根据指定Key来获取对应的字符串即可。

            至于在jsp页面中显示国际化信息,可以使用jstl标签来完成。具体的可以百度。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

struts2的国际化支持

struts2的国际化建立在java国际化之上。一样也是通过提供不同国家的资源文件,然后通过ResourceBundle加载指定Locale对应的资源文件,再通过指定key获取对应的信息。 

整个过程完成相同,只是struts2进行了进一步封装,简化了操作。 
  • 1
  • 2
  • 3
  • 4

struts2的国际化步骤

1.让系统加载国际化资源文件,有两种方式
                -自动加载:Action范围、包范围的国际化资源文件由系统自动加载
                -手动加载:JSP范围、全局范围的国际化资源文件,分别使用标签,配置常量的方式来手动加载。

2.输出国际化,有两种方式
                -在视图页面输出国际化信息,需要使用struts2标签库
                -在Action类中输出国际化信息,需要使用ActionSupport的getText()方法 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

struts2中Action的国际化

(一)配置全局的国际化资源  

                    1.创建国际化资源,和上面的一样
                    2.在struts.xml中配置
                    struts.xml中配置方法:<constant name="struts.custom.i18n.resources" value="com.cad.struts2.resource.message"></constant>

                    3.在action中通过getText方法获取值
                    public class I18NDemo2 extends ActionSupport {
                        public String execute(){ 
                            String value=getText("hello");  
                            System.out.println(value);
                            return SUCCESS;
                        }
                    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
(二)配置包范围的国际化资源  

                    包范围的国际化资源可以被该包下的所有Action使用。
                    包范围的国际化资源文件的名称为:package_language_country.properties 例如 package_zh_CN.properties 
                    文件放在包的根路径下。 

                    包范围的国际化资源不用在配置文件中配置。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
(三)配置Action范围的国际化资源 

                    Action范围的国际化资源只能被该Action使用
                    在Action类所在的路径创建文件:ActionName_language_country.properties 例如:ActionDemo_zh_CN.properties 
  • 1
  • 2
  • 3
  • 4
  • 5

Action类中国际化资源的加载顺序

    1.优先加载Action范围,当前Action类路径下的并且名字为ActionName的国际化资源文件 

    2.如果上一步未找到,并且Action有父类,则加载名字为Action父类的国际化资源文件 

    3.如果上一步未找到,并且Action有实现的接口,则加载名字为Action接口的国际化资源文件 

    4.如果上一步未找到,并且该Action实现接口ModelDriven,则对于getModel()方法返回的Model对象,重新执行第一步。 
    5.如果上一步未找到,则查找当前包范围的国际化资源文件 

    6.如果上一步未找到,则沿着当前包上溯,直到最顶层包中查找包范围的国际化资源文件 

    7.如果上一步未找到,则找全局的国际化资源文件。 

    8.如果上述所有步骤都没找到,则直接输出Key。 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

struts2视图资源的国际化

        需要用到<s:text>标签,这个标签如果不经过action,直接访问页面,则显示全局的国际化资源
        如果经过action,通过结果视图返回到页面,则按照国际化资源的加载顺序显示,从Action类路径下开始
                <body> 

                    <s:text name="hello"></s:text>
                </body> 

        如果经过action,还想显示全局的国际化资源 ,可以用以下方式 

                显示指定名称的国际化资源     
                //指定全局国际化资源名称
                <s:i18n name="com.cad.struts2.resource.message">
                    <s:text name="hello"></s:text>
                </s:i18n>  

        如果<s:i18n> 标签当成表单标签的父标签,则表单标签的key属性会从国际化资源文件中加载信息
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Struts2的拦截器

简介

    拦截器体系是struts2重要的组成部分。正是大量的内建拦截器完成了该框架的大部分操作。 

    比如params拦截器将请求参数解析出来,设置Action的属性。servletConfig拦截器负责将request和response对象传给Action的等等

    拦截器可以动态的拦截发送到指定Action的请求,通过拦截器机制,我们可以在Action执行的前后插入某些代码。
    通过这种方式,就可以把多个Action中重复的代码提取出来,放在拦截器中,从而提高更好的代码复用性。

    理解DRY规则
            DRY:Don‘t Repeat Yourself 意思是不要书写重复的代码。

    对于软件开发的新手来说,开发软件时可能很多地方需要重复性的功能和代码,新手会直接选择复制粘贴即可。
    一旦需要更改维护这段代码,就要修改很多地方,后期的维护简直是噩梦。
    所以有经验的开发人员会将重复代码定义成一个方法,哪里需要哪里调用即可,更改的时候只用修改方法即可。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

拦截器的意义

    上面的例子中当有一天代码中需要调用另一个方法,或者是代码中的方法需要经常切换。 

    这时候我们又得打开源码,修改所有调用方法的地方。造成这个问题的关键在于 以硬编码的方式调用方法。

    为了解决这个问题,我们需要一种机制,所有代码中无需硬编码调用某个方法,但实际上又可以调用方法的功能。 

    struts2的拦截器就是实现了这种需求。拦截器会在目标方法调用之前之后调用一些方法。  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

拦截器的实现原理

通过动态代理实现。我们以前有讲过。

    拦截器基于AOP(面向切面编程)思想。
    AOP编程方式中,有三个重要的概念 

            -目标对象:被拦截方法的对象 

            -被插入的处理方法:定义在拦截器中,会在被拦截方法之前、之后自动调用的方法。方法不能独立存在,必须有载体,载体就是拦截器,拦截器就是包含处理方法的实例。  

            -代理对象:根据目标对象创建的代理对象。代理对象也称为AOP代理,系统动态生成一个对象,该对象将代替目标对象来使用。AOP代理包含了目标对象的所有方法,AOP代理中的方法会在特定位置插入拦截器方法,然后回调目标对象的处理方法,从而实现了执行目标方法之前或者之后调用拦截器方法。 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

struts2中的拦截器

    struts2内建了大量的拦截器。这些拦截器配置在struts-default.xml中。  

    struts2拦截器非常灵活,struts2允许使用各种拦截器,如果有一批拦截器需要经常使用,可以将这批拦截器组成拦截器栈。 

    struts2有一些通用功能是所有Action必需的,所以struts2将这些拦截器组成拦截器栈,并配置成默认的拦截器应用。 

    大部分时候,我们直接使用defaultStack默认的拦截器栈即可。 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

拦截器的使用

配置拦截器

            在struts.xml中定义拦截器 

            <interceptor name="拦截器名" class="拦截器类" />

            如果配置拦截器时需要传入拦截器参数,则需要使用param元素。

            <interceptor name="拦截器名" class="拦截器类" > 
                <param name="参数名">参数值</param>
                ....
            </interceptor> 


            还可以把多个拦截器组成拦截器栈 
            <interceptor-stack name="拦截器栈名">
                <interceptor-ref name="拦截器一"/>
                <interceptor-ref name="拦截器二"/>
                ....
            </interceptor-stack>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

使用拦截器或拦截器栈

            通过<intercept-ref name="拦截器名字" />使用拦截器
  • 1
  • 2

自定义拦截器

实现自定义拦截器需要实现Interceptor接口
            该接口有三个方法
            -void init():拦截器实例化之后调用,只会执行一次,用于初始化资源 

            -void destory():拦截器销毁之前调用 

            -String intercept(ActionInvocation invoction)throws Exception:该方法是用户需要实现的拦截动作。 该方法的ActionInvocation包含了被拦截的action引用等所有数据,可以调用该参数的invoke方法放行,如果有下一个拦截器转到下一个拦截器,如果没有就转给Action类的方法。

            struts2提供了AbstractInterceptor类实现了Interceptor接口,我们只需要继承这个类即可。  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

简单案例

    第一步:实现拦截器 
            public class MyInterceptor extends AbstractInterceptor {
                public String intercept(ActionInvocation invocation) throws Exception {
                    System.out.println("拦截器执行:动作方法之前"); 
                    //放行
                    String result=invocation.invoke();
                    System.out.println("拦截器执行:动作方法之后");
                    return result;
                }
            } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

    第二步:创建action类 
                    public class Demo extends ActionSupport {
                        public String execute(){
                            System.out.println("执行动作类的execute方法");
                            return SUCCESS;
                        }
                    } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
    第三步:配置struts.xml文件 

                    <package name="demo1" extends="struts-default"> 
                        //定义拦截器
                        <interceptors>
                            <interceptor name="myinterceptor" class="com.cad.struts2.interceptor.MyInterceptor"></interceptor>
                        </interceptors> 

                        <action name="demo1" class="com.cad.struts2.action.Demo"> 
                            //action中使用拦截器,如果action使用了拦截器,则默认的拦截器栈就失效
                            <interceptor-ref name="myinterceptor"></interceptor-ref>
                            <result>/Demo.jsp</result>
                        </action>
                    </package>   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
    第四步:返回成功的jsp页面 

                    <body>
                        demo1.jsp
                        <%System.out.println("demo1.jsp执行了"); %>
                    </body>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
输出结果:

                        拦截器之前
                        执行动作类的execute方法
                        demo1.jsp执行了
                        拦截器之后 

和我们以前学习的struts2运行流程一样。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

拦截器和struts2插件的关系

我们需要为struts2扩展新功能时,这时需要开发自己的拦截器,通常我们不可能去修改struts-default.xml文件

而通用功能的拦截器也不应该在某个指定的action中配置。这就需要在struts2插件的struts-plugin.xml文件中配置拦截器。

配置默认使用的拦截器

<default-interceptor-ref name="拦截器或者拦截器栈名"></default-interceptor-ref> 
对于多个action都要使用的拦截器,避免了在多个action中重复指定拦截器。  
  • 1
  • 2
  • 3

使用拦截器时配置参数

    <interceptor-ref name="myinterceptor">
                    <param name="参数名"></param>
    </interceptor-ref> 

    用拦截器时配置的参数如果和定义拦截器时配置的参数相同,那么会覆盖定义时的参数。 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

覆盖拦截器栈里特定拦截器的参数

    有时候,action需要使用拦截器栈,当使用这个拦截器栈,又需要覆盖指定拦截器的参数。
    可以通过param来指定,name为 拦截器名字.参数名 

                    <interceptor-ref name="mystack">
                        <param name="myintercept.name">参数值</param>
                    </interceptor-ref>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

拦截指定方法的拦截器

默认情况下,我们为某个action定义了拦截器,则这个拦截器会拦截该Action的所有方法,如果我们只需要拦截指定方法,此时需要使用struts2拦截器的方法过滤特性。

struts2提供了一个和MethodFilterInterceptor类,该类是AbstractInterceptor的子类。 

该类重写了intercept方法,提供了一个doIntercept(ActionInvocation invocation)抽象方法。 

该类重写的intercept方法已经实现了对Action的拦截行为,通过回调doIntercept来完成具体的拦截逻辑。 

我们需要重写doIntercept方法来实现拦截逻辑。 

实现方法过滤的拦截器和普通的拦截器并没有太大区别,但是这个类中增加了两个方法。
        -public void setExcludeMethods(String excludeMethods):指定的方法都不会被拦截
        -public void setIncludeMethods(String includeMethods):指定的方法会被拦截

如果一个方法同时被这两个方法指定,则这个方法会被拦截。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
 第一步:我们编写一个自定义拦截器
                public class DemoIntercept extends MethodFilterInterceptor {


                    protected String doIntercept(ActionInvocation invocation) throws Exception {

                        System.out.println("拦截器执行:动作方法之前");
                        String result=invocation.invoke();
                        System.out.println("拦截器执行:动作方法之后");
                        return result;
                    }

                } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
    第二步:在struts.xml中配置 
                    <action name="demo1" class="com.cad.struts2.action.Demo">
                        <interceptor-ref name="myinterceptor"> 
                            //设置不会被拦截的方法
                            <param name="excludeMethods">execute</param>
                            //设置被拦截的方法
                            <param name="includeMethods">login,regist</param>
                        </interceptor-ref>
                        <result>/Demo.jsp</result>
                    </action> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

拦截器的执行顺序

    invoke方法之前的动作谁排在前面谁执行。
    invoke方法之后的动作谁排在后面先执行。

    其实这是递归实现。
    第一个拦截器执行完,调用invoke方法,如果有下一个拦截器,执行第二个拦截器,然后没有拦截器的话,就执行Action类中的方法,然后返回到第二个拦截器,第二个拦截器执行完毕,然后返回到第一个拦截器。 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

案例:实现登录权限控制

第一步:先创建一个自定义拦截器 

        public class LoginInterceptor extends MethodFilterInterceptor {


            protected String doIntercept(ActionInvocation invocation) throws Exception { 
                //获取session,判断session中是否有用户
                HttpSession session=ServletActionContext.getRequest().getSession(); 

                //没用户返回到input页面
                Object obj=session.getAttribute("user");
                if(obj==null){
                    return "input";
                } 
                //有的话放行
                String result=invocation.invoke();
                return result;
            }

        } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
    第二步:创建一个action类  

            public class DemoAction extends ActionSupport { 

                //登陆方法,向session中设置
                public String login(){
                    HttpSession session=ServletActionContext.getRequest().getSession();
                    session.setAttribute("user", "user");
                    return SUCCESS;
                }
                public String execute() throws Exception {

                    return SUCCESS;
                }
            } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
    第三步:配置我们的struts.xml文件  

                <package name="demo8" extends="struts-default"> 
                    <!--定义拦截器-->
                    <interceptors>
                        <interceptor name="logininterceptor" class="com.cad.struts2.interceptor.LoginInterceptor"></interceptor>
                    </interceptors> 

                    <action name="login" class="com.cad.struts2.action.DemoAction" method="login">
                        <!--登陆成功,直接跳转到main页面-->
                        <result type="redirectAction">main</result>
                    </action>  

                    <!--执行main动作时,需要拦截器拦截-->
                    <action name="main" class="com.cad.struts2.action.DemoAction">
                        <result>/main.jsp</result>
                        <result name="input">/login.jsp</result> 
                        <!--使用默认拦截器和我们的拦截器-->
                        <interceptor-ref name="defaultStack"></interceptor-ref>
                        <interceptor-ref name="logininterceptor"></interceptor-ref>
                    </action>
                </package>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

当我们访问main.jsp时,触发拦截器,如果没有登录,返回到登陆页面

struts2的文件上传和下载

文件上传的原理

我们以前学习上传的时候知道需要将表单的enctype属性设置为multipart/form-data. 

表单的enctype属性指定的是表单数据的编码方式,有三个值:

            -application/x-www-form-urlencoded:这是默认的编码方式。只处理表单的value属性值。采用这种会将表单域的值处理为url编码方式。 

            -multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,会将文件域里指定文件内容也封装到请求参数里。 

            -text/plain:这种方式主要用于直接通过表单发送邮件的情况。 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

我们用一个简单的案例来说明一下application/x-www-form-urlencoded 和multipart/form-data的区别。

    上传表单 
        <body>
            <form action="${pageContext.request.contextPath }/DemoServlet" enctype="application/x-www-form-urlencoded" method="post">
                上传文件:<input type="file" name="file"><br>
                请求参数:<input type="text" name="username"><br>
                <input type="submit" value="提交" name="dd">  
            </form>
        </body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
处理Servlet,这里的处理直接通过二进制流来处理http请求。这是底层的方式,当通过request的getParameter方法获取请求参数时,实际上是web服务器替我们处理了这种底层的二进制流,并转换成对应的请求参数值。 

            public class DemoServlet extends HttpServlet {

                protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                    InputStream is=request.getInputStream();
                    BufferedReader br=new BufferedReader(new InputStreamReader(is));
                    String buffer=null;
                    while((buffer=br.readLine())!=null)
                    {
                        System.out.println(buffer);
                    }
                }

            } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
    然后我们访问页面,选中file.txt文件 输入框中输入张三 ,点击提交 
                输出 
                file=file.txt&username=%E5%BC%A0%E4%B8%89&dd=%E6%8F%90%E4%BA%A4 

                这个字符串包含了三个属性,file,username 和 dd 
                浏览器会将表单里所有具有name属性的表单项转换成请求参数,因为提交按钮也有name属性,因此也被转换成请求参数。 

                这里的编码都是使用url编码。可以通过java提供的URLDecoder解码。
                大部分时候,程序中通过getParameter方法即可获得参数,底层的二进制流处理,以及使用URLDecoder处理请求参数,都由web服务器帮我们完成了,。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
显然,通过上面这种方式,只能获取到文件名,不能获取到文件的内容,所以为了实现文件上传,只能将enctype属性设置为multipart/form-data.
                一旦设置了表单的 enctype属性设置为multipart/form-data  getParameter方法就无法使用。 


                当我们设置完以后,再次点击提交,则输出

                        ------WebKitFormBoundary2lDSbdeEx3KW1Tup
                        Content-Disposition: form-data; name="file"; filename="file.txt"
                        Content-Type: text/plain

                        我是上传文件
                        ------WebKitFormBoundary2lDSbdeEx3KW1Tup
                        Content-Disposition: form-data; name="username"

                        zhangsan
                        ------WebKitFormBoundary2lDSbdeEx3KW1Tup-- 

                这时我们发现文件的内容也获取到,我们只需要通过io流的知识将其分割然后获取指定的参数即可。
                对于一个成熟的文件上传框架,需要完成的逻辑很简单,分析request请求的二进制流,解析出数据,然后允许开发者以简单的方式获取数据内容即可。

                Servlet3.0给我们所提供了提供了更加简单的文件上传方法,我们可以查阅API进行使用,这里不再细说。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

Struts2的文件上传

struts2并未提供自己的上传组件。在struts.properties配置文件中,可以看到底层配置的是Common-fileupload组件。 

但struts在原有的组件上进行了封装,因此底层的上传组件可以随意切换,代码不用变化。 
  • 1
  • 2
  • 3
  • 4
第一步:编写我们的Action动作类 
            public class UploadAction extends ActionSupport {
                private String username;
                private File upload; //封装了文件内容,无法获得文件名和文件类型
                private String uploadContentType;//封装了文件类型,xxxContentType
                private String uploadFileName; //用xxxFileName封装文件名字

                public String getUsername() {
                    return username;
                }

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

                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;
                }

                public String upload(){  
                    //获取真实路径
                    String savepath=ServletActionContext.getRequest().getRealPath("/WEB-INF/files");
                    File file=new File(savepath); 
                    //判断文件是否存在,不存在就创建相应的目录等
                    if(!file.exists()){
                        file.mkdirs();
                    } 
                    //将上传的临时文件重命名并且另存到指定地址
                    upload.renameTo(new File(file,uploadFileName));
                    return null;
                }

            } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
第二步:配置Action 
            <package name="p1" extends="struts-default">
                <action name="upload" class="com.cad.struts2.action.UploadAction" method="upload">
                </action>
            </package>
  • 1
  • 2
  • 3
  • 4
  • 5

文件过滤

            我们可以自己手动判断文件大小,文件类型来进行文件过滤,但是比较繁琐。
            struts2为我们提供了一个fileUpload拦截器,来帮我们实现文件过滤。
            fileUpload拦截器也被配置在了默认的拦截器栈中

            fileUpload拦截器有两个参数
            -allowedTypes:该参数指定允许上传的文件类型,多个文件类型之间用逗号分割,
            -maximumSize:该属性指定允许上传的文件大小,单位是字节
            struts2默认的允许上传文件大小为2MB。

            设置最大允许上传文件大小为30M ,经过测试,这种方法行不通,不知道具体原因是什么。
            <action name="upload" class="com.cad.struts2.action.UploadAction" method="upload">
                <interceptor-ref name="defaultStack">
                    <param name="fileUpload.allowedTypes">image/jpg</param>
                    <param name="fileUpload.maximumSize">31457280</param>
                </interceptor-ref>
            </action> 

            所以我们只能通过配置常量来修改允许上传文件的大小 
            <constant name="struts.multipart.maxSize" value="31457280"></constant> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

同时上传多个文件

        需要将文件表单项的name设置成相同的。

            表单页面
                <body>
                        <form action="${pageContext.request.contextPath }/upload.action" enctype="multipart/form-data" method="post">
                        上传文件1:<input type="file" name="upload"><br>
                        上传文件2:<input type="file" name="upload"><br>
                        上传文件3:<input type="file" name="upload"><br>
                        用户名:<input type="text" name="username"><br>
                        <input type="submit" value="提交">    
                    </form>
                </body> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
            然后写Action类,需要将file,fileName,ContentType等用数组封装起来 
            然后遍历得到
            public class UploadAction extends ActionSupport {
                private String username;
                private File upload[]; 
                private String uploadContentType[];
                private String uploadFileName[]; 

                public String getUsername() {
                    return username;
                }

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


                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;
                }

                public String upload(){ 
                    String savepath=ServletActionContext.getRequest().getRealPath("/WEB-INF/files");
                    File file=new File(savepath);
                    if(!file.exists()){
                        file.mkdirs();
                    }
                    for(int i=0;i<upload.length;i++){
                        upload[i].renameTo(new File(file,uploadFileName[i]));
                    }
                    return null;
                }

            } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

Struts2的文件下载

    创建下载的action类 

                public class DownloadAction extends ActionSupport {
                    private InputStream input;

                    public InputStream getInput() {
                        return input;
                    }

                    public void setInput(InputStream input) {
                        this.input = input;
                    }

                    public String download() throws Exception{
                        //获取文件路径
                        String path=ServletActionContext.getRequest().getRealPath("/WEB-INF/files/photo.jpg");
                        //读取文件
                        input=new FileInputStream(path);
                        return SUCCESS;
                    }
                } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
    配置Action
                struts2指定了stream结果类型,专门用来处理下载。

                contentType:被下载文件的文件类型。
                contentDisposition:下载文件弹窗,文件名等 
                inputName:action类中流的名字 

                <action name="download" class="com.cad.struts2.action.DownloadAction" method="download">
                    <result name="success" type="stream">
                        <param name="contentType">application/octet-stream</param>
                        <param name="contentDisposition">attachment;filename=phpto.jpg</param>
                        <param name="inputName">input</param>
                    </result>
                </action>

猜你喜欢

转载自my.oschina.net/architectliuyuanyuan/blog/1800366
今日推荐