Struts 学习笔记3(拦截器、文件上传、下载、xml、json)

项目文件结构

 

Struts2应用的分层体系架构

要点:

1.将处理逻辑放到service里,如Action层不准许出现在sql语句,session、request不允许传到service层去。

 

示例:

LoginAction.java

package com.struts2.struts2;

……该导入的包……

public class LoginAction extends ActionSupport

{

    private String username;

    private String password;

    private int age;

    private Date date;

    private LoginService loginService = new LoginServiceImpl();

    

……Setget方法……

    

    public String execute() throws Exception

    {    //业务逻辑不写到Action

//        if(!"hello".equals(username))

//        {

//            throw new UsernameException("username invalid");

//        }

//        if(!"world".equals(password))

//        {

//            throw new PasswordException("password invalid");

//        }

//        return SUCCESS;

        

//利用ServletActionContext,获得HttpServletRequest请求

        HttpServletRequest request = ServletActionContext.getRequest();

        HttpSession session = request.getSession();

        

        session.setAttribute("hello", "helloworld");

        

        ActionContext actionContext = ActionContext.getContext();

        Map<String, Object> map = actionContext.getSession();    //获取session

        

        Object object = map.get("hello");    //打印出session的信息

        System.out.println(object);    

        if(this.loginService.isLogin(username, password))

        {

            return SUCCESS;

        }

        

        return INPUT;

    }

………………

}

 

LoginService.java

package com.struts2.service;

public interface LoginService

{

    public boolean isLogin(String username, String password);

}

 

LoginServiceImpl.java

package com.struts2.service.impl;

import com.struts2.service.LoginService;

public class LoginServiceImpl implements LoginService

{

    public boolean isLogin(String username, String password)

    {

        if("hello".equals(username) && "world".equals(password))

        {

            return true;

        }

        return false;

    }

}

 

编辑struts2.xml文件

    …………

<action name="login" class="com.struts2.struts2.LoginAction">

        <result name="success" type="dispatcher">/result.jsp</result>

        <result name="input">/login.jsp</result>

    </action>

    …………

 

Struts2的模型驱动(model driven)

要点:

  1. 属性驱动(propertity driven)与模型驱动的区别:之前的都是属性驱动,属性驱动与模型驱动的处理方式差不多,但它们导致的结果却不同,属性驱动是在接收的请求后,将对象里的值一个一个的 set 好,此时并没有new 出一个整的对象。而模型驱动是在接收到用户提交表单请求后,就将对象创建好了,并把对象的值也设定好了,可以直接拿对象来用了。
  2. 实现了ModelDriven接口的Action的执行过程

1).首先调用getModel()方法,返回一个person对象

2).模型查找提交过来的表单中有没有username、password等属性名是否匹配,如果匹配,则将对应的值自动设置到对象中,放到模型当中。

3).当在结果页面,以request.getAttribute()或requestScope取值时,同样通过Action从模型当中取值。

  1. 属性驱动与模型驱动的比较

1)属性驱动灵活,准确;模型驱动不灵活,因为很多时候,页面所提交过来的参数并不属于模型中的属性,也就是说页面所提交过来的参数与模型中的属性并不一致,这是很常见的情况。

2)模型驱动更加符合面向对象的编程风格,使得我们获得的是对象而不是一个个离散的值。

小结:推荐使用属性驱动编写 Action

  1. Preparable接口的作用是让 Action完成一些初始化工作,这些初始化工作是放在 Preparable接口的prepare方法中完成的,该方法会在execute方法执行之前得到调用。

 

示例:

Person.java

package com.struts2.bean;

import java.util.Date;

public class Person

{

    private String username;

    private String password;

    private int age;

    private Date date;

    ……getset方法……

}

LoginAction2.java

package com.struts2.struts2;

import com.opensymphony.xwork2.ActionSupport;

import com.opensymphony.xwork2.ModelDriven;

import com.opensymphony.xwork2.Preparable;

import com.struts2.bean.Person;

public class LoginAction2 extends ActionSupport implements ModelDriven<Person>, Preparable

{    //模型驱动

    private Person person = new Person();

    

    //1.首先调用getModel()方法,返回一个person对象

    //2.模型查找提交过来的表单中有没有usernamepassword等属性值,如果有,则模型自动设置到对象中

    public Person getModel()

    {

        System.out.println("getModel invoked!");

        return person;    //返回生成的person

    }

 

//调用这个方法让action准备自身

    public void prepare() throws Exception

    {

        System.out.println("prepare invoked!!");

    }

public String execute() throws Exception

    {

        System.out.println("execute invoked!");

        //System.out.println(person.getUsername());

        return SUCCESS;

    }

}

 

struts.xml

向struts.xml文件中,添加一个action,如下:

    <action name="login2" class="com.struts2.struts2.LoginAction2">

        <result name="success">/result.jsp</result>

    </action>

 

login.jsp

…………

<form action="login2.action">

username: <input type="text" name="username"><br>

password: <input type="password" name="password"><br>

age: <input type="text" name="age"><br>

date: <input type="text" name="date"><br>

<input type="submit" value="submit">

</form>

…………

result.jsp

…………

<body>

username: ${requestScope.username }<br><!-- requestScope相当于request.getAttribute() -->

password: ${requestScope.password }<br>

age: ${requestScope.age }<br>

date: ${requestScope.date }<br>

session: ${sessionScope.hello }<!-- 取得通过ServletActionContext方式获取的session -->

</body>

…………

 

服务器端代码的单元测试

要点:

1) 容器内测试(Jetty)

2) Mock 测试 ( 继承 HttpServletRequest 、 HttpSession 、HttpServletResponse等Servlet API) 。

 

防止表单重复提交

要点:

1) 通过重定向

2) 通过Session Token(Session令牌):当客户端请求页面时,服务器会通过token标签生成一个随机数,并且将该随机数放置到 session当中,然后将该随机数发向户端;如果客户第一次提交,那么会将该随机数发往服务器端,服务器会接收到该随机数并且与 session 中所保存的随机数进行比较,这时两者的值是相同的,服务器认为是第一次提交,并且将更新服务器端的这个随机数值;如果此时再次重复提交,那么客户端发向服务器端的随机数还是之前的那个,而服务器端的随机数则已经发生了变化,两者不同,服务器就认为这是重复提交,进而转向invalid.token所指向的结果页面。

 

Struts-default.xml中定义的结果类型

打开struts2-core-2.2.1.1.jar下的struts-default.xml文件,其中定义了的结果类型,如下:

<package name="struts-default" abstract="true">

<result-types>

<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>

<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>

<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>

<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>

<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>

<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>

<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>

<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>

<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>

<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />

</result-types>

    ………………

 

页面重定向与请求转发的设定

在struts.xml文件中,设置Action中的result元素的type属性即可,如下:

    <action name="login" class="com.struts2.struts2.LoginAction">

        <!--

        <result name="success" type="dispatcher">/result.jsp</result>

-->

<result name="success" type="redirect">/result.jsp</result>

        <result name="input">/login.jsp</result>

    </action>

 

重定向到Action (redirectAction)

action1.jsp

…………

<body>

<form action="action1.action">

username: <input type="text" name="username"><br>

password: <input type="password" name="password"><br>

<input type="submit" value="submit">

</form>

</body>

…………

action2.jsp

…………

<body>

username: <s:property value="username"/><br>

password: <s:property value="password"/><br>

usernameAndPassword: <s:property value="usernameAndPassword"/>

</body>

…………

Action1.java

package com.struts2.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class Action1 extends ActionSupport

{

    private String username;

    private String password;

    private String usernameAndPassword;

    ……setget方法……

    @Override

    public String execute() throws Exception

    {

        this.usernameAndPassword = this.username + this.password;

        

        return SUCCESS;

    }

}

 

Action2.java

package com.struts2.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class Action2 extends ActionSupport

{

    private String username;

    private String password;

    private String usernameAndPassword;

    ………getset方法………

    @Override

    public String execute() throws Exception

    {

        return SUCCESS;

    }

}

 

struts.xml

    …………

<action name="action1" class="com.struts2.struts2.Action1">

            <result name="success" type="redirectAction">

                <!--如果不传参数,可把action2直接写到resulttext域中 -->

<param name="actionName">action2</param>

                <param name="username">${username}</param><!-- 获取Action1的成员变量 -->

                <param name="password">${password}</param>

                <param name="usernameAndPassword">${usernameAndPassword}</param>

            </result>

        </action>

        

        <action name="action2" class="com.struts2.struts2.Action2">

            <result name="success">/action2.jsp</result>

        </action>

    …………

 

chain结果类型(Action之间的请求转发)

要点:直接修改struts.xml文件中的action的result的type属性的值为 chain ,如下:

    …………

<action name="action1" class="com.vvvv.struts2.Action1">

            <result name="success" type=chain">

                <!--如果不传参数,可把action2直接写到resulttext域中 -->

<param name="actionName">action2</param>

                <param name="username">${username}</param><!-- 获取Action1的成员变量 -->

                <param name="password">${password}</param>

                <param name="usernameAndPassword">${usernameAndPassword}</param>

            </result>

    …………

运行可以发现,这种方式不是以重定向的形式转发,且action2.jsp页面拿不到usernameAndPassword的信息。因为由Action1转发到到Action2,是在服务器内部进行了,是在一个客户端页面(action1.jsp)请求范围内,而请求中只包含usernamepassword两个参数。所以拿不到usernameAndPassword的值。

 

Struts2 Session Token机制

token.jsp

…………

<body>

<s:form action="token.action" theme="simple">

username: <s:textfield name="username"></s:textfield><br>

password: <s:password name="password"></s:password><br>

<s:token></s:token>

<s:submit value="submit"></s:submit>

</s:form>

</body>

…………

TokenAction.java

package com.struts2.struts2;

 

import com.opensymphony.xwork2.ActionSupport;

 

public class TokenAction extends ActionSupport

{

    private String username;

    private String password;

    ……getset方法……

    @Override

    public String execute() throws Exception

    {

        return SUCCESS;

    }

}    

 

tokenSuccess.jsp

…………

<body>

username: <s:property value="username"/><br>

password: <s:property value="password"/>

</body>

…………

 

tokenFail.jsp

…………

<body>

不要重复提交表单

</body>

…………

 

struts.xml

…………

        <action name="token" class="com.struts2.struts2.TokenAction">

            <result name="success">/tokenSuccess.jsp</result>

            <result name="invalid.token">/tokenFail.jsp</result>

            

            <interceptor-ref name="token"></interceptor-ref>

            <interceptor-ref name="defaultStack"></interceptor-ref>

        </action>

…………

 

struts2拦截器

要点:

拦截器的配置

1)编写实现Interceptor 接口的类。

2)在struts.xml 文件中定义拦截器。

3)在action中使用拦截器

首先编写拦截器类(TheInterceptor1)

package com.struts2.interceptor;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.Interceptor;

public class TheInterceptor1 implements Interceptor

{

    private String test;

    public String getTest()

    {

        return test;

    }

    public void setTest(String test)

    {

        System.out.println("setTest invoked!");    //set方法先于init方法执行

        this.test = test;

    }

    public void destroy()

    {

    }

    public void init()

    {

        System.out.println("init invoked!");

        System.out.println("test: " + this.test);

    }

    //服务器永远不会去执行挂截器,只不过是在执行拦截器之前,执行一个invoke方法

    public String intercept(ActionInvocation invocation) throws Exception

    {

        System.out.println("before");

        String result = invocation.invoke();

        System.out.println("after");

        return result;

    }

}

struts.xml

<struts>

    <package name="struts2" extends="struts-default">

        <interceptors>

            <interceptor name="theInterceptor1" class="com.vvvv.interceptor.TheInterceptor1">

                <param name="test">vvvv</param>

            </interceptor>

        </interceptors>

    ………………

        <action name="token" class="com.struts2.struts2.TokenAction">

            <result name="success">/tokenSuccess.jsp</result>

            <result name="invalid.token">/tokenFail.jsp</result>

            <interceptor-ref name="token"></interceptor-ref>

            <interceptor-ref name="defaultStack"></interceptor-ref>

        </action>

    </package>

</struts>

 

一旦定义了自己的拦截器,将其配置到 action上后,我们需要在action的最后加上默认的拦截器栈:defaultStack。

 

示例2

项目源包 : struts2sd

要点:

 

TheInterceptor2.java

package com.vvvv.interceptor;

 

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

 

public class TheInterceptor2 extends AbstractInterceptor

{

    @Override

    public String intercept(ActionInvocation invocation) throws Exception

    {

        System.out.println("interceptor before...");

        System.out.println("interceptor2: " + invocation.getAction().getClass());

        String result = invocation.invoke();

        System.out.println("interceptor after...");

        return result;

    }

}

 

struts.xml

…………

<interceptors>

    <interceptor name="theInterceptor1" class="com.vvvv.interceptor.TheInterceptor1">

        <param name="test">vvvv</param>

    </interceptor>

    

    <interceptor name="theInterceptor2" class="com.vvvv.interceptor.TheInterceptor2">

    </interceptor>

    

    <interceptor name="theInterceptor3" class="com.vvvv.interceptor.TheInterceptor3">

    </interceptor>

    

    <interceptor name="loginInterceptor" class="com.vvvv.interceptor.LoginInterceptor">

    </interceptor>

</interceptors>

…………

<action name="action1" class="com.vvvv.struts2.Action1" method="myExecute">

    <result name="success" type="chain">

        <param name="actionName">action2</param>

        <param name="username">${username}</param>

        <param name="password">${password}</param>

        <param name="usernameAndPassword">${usernameAndPassword}</param>

    </result>

    

    <interceptor-ref name="theInterceptor1"></interceptor-ref>

    <interceptor-ref name="theInterceptor2"></interceptor-ref>

    <!-- 方法过滤拦截器 -->

    <interceptor-ref name="theInterceptor3">

        <param name="includeMethods">execute, myExecute</param>

        <!-- 不包含以下拦截器,使其不执行 --><!--

        <param name="excludeMethods">myExecute</param>

         -->

    </interceptor-ref>

    <interceptor-ref name="defaultStack"></interceptor-ref>

</action>

…………

TheInterceptor3

package com.vvvv.interceptor;

 

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

import com.vvvv.listener.TheListener;

 

public class TheInterceptor3 extends MethodFilterInterceptor

{

    @Override

    protected String doIntercept(ActionInvocation invocation) throws Exception

    {

        invocation.addPreResultListener(new TheListener());

        System.out.println("before interceptor3");

        String result = invocation.invoke();

        System.out.println("after interceptor3");

        return result;

    }

}

 

示例3

struts.xml

<interceptors>

            <interceptor name="theInterceptor1" class="com.vvvv.interceptor.TheInterceptor1">

                <param name="test">vvvv</param>

            </interceptor>

            

            <interceptor name="theInterceptor2" class="com.vvvv.interceptor.TheInterceptor2">

            </interceptor>

            

            <interceptor name="theInterceptor3" class="com.vvvv.interceptor.TheInterceptor3">

            </interceptor>

            

            <!-- 配置login拦截器 -->

            <interceptor name="loginInterceptor" class="com.vvvv.interceptor.LoginInterceptor">

            </interceptor>

            

            <interceptor-stack name="myDefaultInterceptorStack">

                <interceptor-ref name="loginInterceptor"></interceptor-ref>

                <interceptor-ref name="defaultStack"></interceptor-ref>

            </interceptor-stack>

            

        </interceptors>

        

        <default-interceptor-ref name="myDefaultInterceptorStack"></default-interceptor-ref>

      

        <global-results>

            <result name="usernameInvalid">/usernameInvalid.jsp</result>

            <result name="passwordInvalid">/passwordInvalid.jsp</result>

            <result name="login">/error.jsp</result>

        </global-results>

        

        <global-exception-mappings>

            <exception-mapping result="usernameInvalid" exception="com.vvvv.exception.UsernameException"></exception-mapping>

            <exception-mapping result="passwordInvalid" exception="com.vvvv.exception.PasswordException"></exception-mapping>

        </global-exception-mappings>

      

        <action name="login" class="com.vvvv.struts2.LoginAction">

            <result name="success" type="dispatcher">/result.jsp</result>

            <result name="input">/login.jsp</result>

        </action>

        

        <action name="login2" class="com.vvvv.struts2.LoginAction2">

            <result name="success">/result.jsp</result>

        </action>

        

        <action name="userAction" class="com.vvvv.struts2.UserAction">

            <result name="success">/output.jsp</result>

        </action>

        

        <action name="userAction2" class="com.vvvv.struts2.UserAction2">

            <result name="success">/output.jsp</result>

        </action>

        

        <action name="register" class="com.vvvv.struts2.RegisterAction" method="myExecute">

            <result name="success">/registerResult.jsp</result>

            <result name="input">/register.jsp</result>

        </action>

        

        <action name="action1" class="com.vvvv.struts2.Action1" method="myExecute">

            <result name="success" type="chain">

                <param name="actionName">action2</param>

                <param name="username">${username}</param>

                <param name="password">${password}</param>

                <param name="usernameAndPassword">${usernameAndPassword}</param>

            </result>

        …………

LoginInterceptor.java

package com.vvvv.interceptor;

import java.util.Map;

import com.opensymphony.xwork2.Action;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

import com.vvvv.struts2.LoginAction;

 

public class LoginInterceptor extends AbstractInterceptor

{

    @Override

    @SuppressWarnings("unchecked")

    public String intercept(ActionInvocation invocation) throws Exception

    {

        if(LoginAction.class == invocation.getAction().getClass())

        {

            return invocation.invoke();

        }

        Map map = invocation.getInvocationContext().getSession();

        if(null == map.get("userInfo"))

        {

            return Action.LOGIN;

        }

        return invocation.invoke();

    }

}

 

同时,也可以在一个Struts.xml中有多个package ,例如,可以将前台的Action放到一个package里,将后台的一个package放到另一个包里面。

 

也可以将配置文件拆分开来,写到多个配置文件中,例如:

<struts>

    <include file="xxx.xml"></include>

    …………

 

struts-2.3.1-all.zip\struts-2.3.1\apps\struts2-mailreader.war\WEB-INF\src\java\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.action.extension" value="do" />

<constant name="struts.devMode" value="false" />

<constant name="struts.enable.DynamicMethodInvocation" value="false" />

<include file="mailreader-default.xml"/>

<include file="mailreader-support.xml"/>

</struts>

 

struts命名空间

配置struts.xml

…………

<package name="hello" extends="struts-default" namespace="/theNamespace">

      

        <action name="namespaceAction" class="com.vvvv.struts2.NamespaceAction">

            <result name="success">output.jsp</result>

        </action>

    

</package>

…………

NamespaceAction(命名空间)

package com.vvvv.struts2;

 

import com.opensymphony.xwork2.ActionSupport;

public class NamespaceAction extends ActionSupport

{

    @Override

    public String execute() throws Exception

    {

        return SUCCESS;

    }

}

 

实现文件上传

要点:

1)首先将客户端上传的文件保存到struts.multipart.saveDir键所指定的目录中,如果该键所对应的目录不存在,那么就保存到javax.servlet.context.tempdir 环境变量所指定的目录中。

2)Action中所定义的File类型的成员变量file实际上指向的是临时目录中的临时文件,然后在服务器端通过 IO的方式将临时文件写入到指定的服务器端目录中。

 

示例1

fileUpload.jsp

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

 

fileUploadResult.jsp

<body>

username: <s:property value="username"/><br>

name:<s:property value="fileFileName"/>

<br>

type:<s:property value="fileContentType"/>

</body>

 

通过servlet实现对文件的上传

 

UploadServlet.java

package com.vvvv.servlet;

 

import java.io.File;

import java.io.IOException;

import java.util.List;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet extends HttpServlet

{

    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)

            throws ServletException, IOException

    {

        //DiskFileItemFactory创建在内存中保存内容的FileItem实例

        DiskFileItemFactory factory = new DiskFileItemFactory();

        //得到真实绝对路径

        String path = req.getRealPath("/upload");

        

        //把工厂的仓库设置为真实路径

        factory.setRepository(new File(path));

        //设置阀值

        factory.setSizeThreshold(1024 * 1024);

        //创建ServletFileUpload实例

        ServletFileUpload upload = new ServletFileUpload(factory);

        try

        {

            //解析HttpServletRequestList到中

            List<FileItem> list = (List<FileItem>)upload.parseRequest(req);

            for(FileItem item : list)

            {

                //获得表单字段的名字

                String name = item.getFieldName();

                //判断是否是表单字段

                //如果是普通文本域返回true; 如果不是普通文本域返回false.

                if(item.isFormField())

                {

                    //获得表单字段的值

                    String value = item.getString();

                    System.out.println(name + "=" + value);

                    req.setAttribute(name, value);

                }

                else

                {

                    String value = item.getName();

                    int start = value.lastIndexOf("\\");

                    String fileName = value.substring(start + 1);

                    req.setAttribute(name, fileName);

                    item.write(new File(path, fileName));

//                    OutputStream os = new FileOutputStream(new File(path, fileName));

//                    InputStream is = item.getInputStream();

//                    byte[] buffer = new byte[400];

//                    int length = 0;

//                    while((length = is.read(buffer)) != -1)

//                    {

//                        os.write(buffer, 0, length);

//                    }

//                    is.close();

//                    os.close();

                }

            }

        }

        catch(Exception ex)

        {

            ex.printStackTrace();

        }

        req.getRequestDispatcher("fileUploadResult.jsp").forward(req, resp);

    }

}

 

Struts2的配置文件

 

WEB-INF/lib/struts2-core-2.2.1.1.jar/org.apache.struts2/default.properties

…………

### This can be used to set your default locale and encoding scheme

# struts.locale=en_US

struts.i18n.encoding=UTF-8        //指定了国际化的默认编码格式

 

### if specified, the default object factory can be overridden here

### Note: short-hand notation is supported in some cases, such as "spring"

### Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here

# struts.objectFactory = spring

 

### specifies the autoWiring logic when using the SpringObjectFactory.

### valid values are: name, type, auto, and constructor (name is the default)

struts.objectFactory.spring.autoWire = name

…………

### Used by the DefaultActionMapper

### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do

### The blank extension allows you to match directory listings as well as pure action names

### without interfering with static resources.

struts.action.extension=action,,    //指定了表单提交的文件的后缀名

…………

 

单个文件上传

fileUpload.jsp

…………

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

    …………

 

fileUploadResult.jsp

…………

<body>

username: <s:property value="username"/><br>

 

name:<s:property value="fileFileName"/>

<br>

type:<s:property value="fileContentType"/>

</body>

…………

 

UploadAction.java

package com.vvvv.struts2;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.OutputStream;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class UploadAction extends ActionSupport

{

    private String username;

    private File file;

    private String fileFileName;

    private String fileContentType;

    …………setget方法…………

    @Override

    public String execute() throws Exception

    {

        //文件上传的步骤是:先将上传的文件缓存在struts.multipart.saveDir=xxx指定的目录下,

        //然后从xxx目录下,通过输出流将文件上传到服务器指定的目录("/upload")

        String root = ServletActionContext.getRequest().getRealPath("/upload");

        InputStream is = new FileInputStream(file);

        System.out.println("path: " + file.getAbsolutePath());

        

        System.out.println("file: " + file.getName());

        System.out.println("fileFileName: " + fileFileName);

        File destFile = new File(root, fileFileName);

        OutputStream os = new FileOutputStream(destFile);

        byte[] buffer = new byte[400];

        int length = 0;

        while(-1 != (length = is.read(buffer)))

        {

            os.write(buffer, 0, length);

            Thread.sleep(1000);

        }

        is.close();

        os.close();

        return SUCCESS;

    }

}

 

struts.properties

#定义文件的拓展名

struts.action.extension=action

#指定上传文件的缓存目录

struts.multipart.saveDir=c:/vvvv

#限定上传文件的最大大小

struts.multipart.maxSize=1048576000

 

注:限定上传文件的大小等也可以在struts.xml文件中配置,如下:

<struts><!-- 限定2M -->

    <constant name="struts.multipart.maxSize" value="5242880"></constant>

    …………

</struts>

 

多个文件上传

fileUpload2.jsp

<form action="fileUpload2.action" method="post" enctype="multipart/form-data">

username: <input type="text" name="username"><br>

file: <input type="file" name="file"><br>

file2: <input type="file" name="file"><br>

file3: <input type="file" name="file"><br>

<input type="submit" value="submit">

</form>

fileUploadResult2.jsp

<body>

username: <s:property value="username"/><br>

<s:iterator value="fileFileName" id="f">

file: <s:property value="#f.toUpperCase()"/><br><!-- ognl表达示 -->

</s:iterator>

</body>

UploadAction2.java

package com.vvvv.struts2;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.List;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class UploadAction2 extends ActionSupport

{

    private String username;

    private List<File> file;

    private List<String> fileFileName;

    private List<String> fileContentType;

    …………setget方法…………

    @Override

    public String execute() throws Exception

    {

        for(int i = 0; i < file.size(); i++)

        {

            InputStream is = new FileInputStream(file.get(i));

            String root = ServletActionContext.getRequest().getRealPath("/upload");

            File destFile = new File(root, fileFileName.get(i));

            OutputStream os = new FileOutputStream(destFile);

            byte[] buffer = new byte[400];

            int length = 0;

            while(-1 != (length = is.read(buffer)))

            {

                os.write(buffer, 0, length);

            }

            is.close();

            os.close();

        }

        return SUCCESS;

    }

}

 

struts2文件下载

 

struts.xml

    </package>

…………

        <action name="fileUpload2" class="com.vvvv.struts2.UploadAction2">

            <result name="success">/fileUploadResult2.jsp</result>

        </action>

        <action name="downloadFile2" class="com.vvvv.struts2.DownloadAction2">

            <result type="stream"><!-- 动态的获得文件的名字 -->

                <param name="contentDisposition">attachment;filename=${filename}</param>

                <param name="inputName">downloadFile</param>

            </result>

        </action>

    </package>

 

downloadFile.jsp

<body>

<a href="downloadFile2.action?number=1">下载文件</a>

</body>

 

downloadAction2.java

package com.vvvv.struts2;

import java.io.InputStream;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class DownloadAction2 extends ActionSupport

{

    private int number;

    private String filename;

    …………getset方法…………

    public InputStream getDownloadFile()

    {

        try

        {

            if (1 == number)

            {    

                //动态的修改文件的名字

                this.filename = "中文.txt";

                //转码

                this.filename = new String(this.filename.getBytes("gbk"),

                        "8859_1");

                return ServletActionContext.getServletContext()

                        .getResourceAsStream("/upload/中文.txt");

            }

            else

            {

                this.filename = "CaptureSprite.exe";

                return ServletActionContext.getServletContext()

                        .getResourceAsStream("/upload/CaptureSprite.exe");

            }

        }

        catch (Exception ex)

        {

        }

        return null;

    }

 

    @Override

    public String execute() throws Exception

    {

        return SUCCESS;

    }

}

 

基于注解的配置

 

要点

 

编辑LoginAction.java,

package com.vvvv.struts2;

 

@ParentPackage("struts-default")

@Action(value = "login", results = {

        @Result(name = "success", location = "/login.jsp"),

        @Result(name = "input", location = "/login.jsp") })

//@InterceptorRef("defaultStack")

//@InterceptorRefs({@InterceptorRef(""), @InterceptorRef("")})

//@ExceptionMappings({@ExceptionMapping(),@E.....})

public class LoginAction extends ActionSupport

{

    private String username;

    private String password;

    private int age;

    private Date date;

    private LoginService loginService = new LoginServi

    …………

}

 

Struts2异步处理xml

项目文件结构

要点:

 

GetXMLAction.java

package com.vvvv.action.xml;

…………getset方法…………

public class GetXMLAction extends ActionSupport

{

    private String name;

    public String getName()

    {

        return name;

    }

    public void setName(String name)

    {

        this.name = name;

    }

    @Override

    public String execute() throws Exception

    {

        //zhang san

        People people1 = new People();

        people1.setId(1);

        people1.setName("zhangsan");

        people1.setAge(30);

        people1.setAddress("beijing");

        People people2 = new People();

        people2.setId(2);

        people2.setName("lisi");

        people2.setAge(50);

        people2.setAddress("tianjin");

        //创建文档对象

        Document document = DocumentHelper.createDocument();

        //创建根元素

        Element rootElement = document.addElement("persons");

        rootElement.addComment("This is comment!!");

        Element e = rootElement.addElement("person");

        Element idElement = e.addElement("id");

        Element nameElement = e.addElement("name");

        Element ageElement = e.addElement("age");

        Element addressElement = e.addElement("address");

        if("zhangsan".equals(name))

        {

            idElement.setText(people1.getId() + "");

            nameElement.setText(people1.getName());

            ageElement.setText(people1.getAge() + "");

            addressElement.setText(people1.getAddress());

        }

        else{

            idElement.setText(people2.getId() + "");

            nameElement.setText(people2.getName());

            ageElement.setText(people2.getAge() + "");

            addressElement.setText(people2.getAddress());

        }

        //创建ajax响应

        HttpServletResponse response = ServletActionContext.getResponse();

        response.setContentType("text/xml; charset=utf-8");

        response.setHeader("cache-control", "no-cache");

        PrintWriter out = response.getWriter();

        OutputFormat format = OutputFormat.createPrettyPrint();

        format.setEncoding("utf-8");

        XMLWriter writer = new XMLWriter(out, format);

        writer.write(document);

        out.flush();

        out.close();

        return null;

    }

}

 

People.java

package com.vvvv.action.xml;

public class People

{

    private int id;

    private String name;

    private int age;

    private String address;

    …………get、set方法…………

}

 

Struts2异步处理Json

 

要点

getJson.jsp

<script type="text/javascript" src="scripts/jquery-1.4.4.js"></script>

    <script type="text/javascript">

    $(function()

    {

        $("#button1").click(function()

        {

            $.post("getJsonAction2.action",{name: $("#name").val()},

                function(returnedData, status)

            {

                var people = returnedData;

                var id = people.id;

                var name = people.name;

                var age = people.myAge;

                var address = people.address;

                var html = "<table width='60%' border='1' align='center'><tr><th>id</th><th>name</th><th>age</th><th>address</th><tr align='center'><td>" + id + "</td><td>" + name + "</td><td>" + age + "</td><td>" + address + "</td></tr></table>";

                $("#theBody table:eq(0)").remove();

                $("#theBody").append(html);

            });            

        });

    });

    </script>

</head>

<body id="theBody">

<select id="name">

    <option value="zhangsan">zhangsan</option>

    <option value="lisi">lisi</option>

</select>

<input type="button" value="get json content from server" id="button1">

</body>

 

GetJsonAction.java

package com.vvvv.action.json;

…………getset方法…………

public class GetJsonAction extends ActionSupport

{

    private String name;

    public String getName()

    {

        return name;

    }

    public void setName(String name)

    {

        this.name = name;

    }

 

    @Override

    public String execute() throws Exception

    {

        People people = new People();

        people.setId(1);

        people.setName(name);

        people.setAge(30);

        people.setAddress("beijing");

        Gson gson = new Gson();

        String result = gson.toJson(people);

        HttpServletResponse response = ServletActionContext.getResponse();

        response.setContentType("application/json; charset=utf-8");

        response.setHeader("cache-control", "no-cache");

        PrintWriter out = response.getWriter();

        out.print(result);

        out.flush();

        out.close();

        return null;

    }

}

 

GetJsonAction2.java(利用struts2的插件)

package com.vvvv.action.json;

 

public class GetJsonAction2 extends ActionSupport

{

    private String name;

    private int id;

    private int age;

    private String address;

    …………getset方法…………

    @Override

    public String execute() throws Exception

    {

        this.id = 1;

        this.age = 30;

        this.address = "beijing";

        return SUCCESS;

    }

}

注:本文档参考张龙老师的struts2教程

原文地址:https://www.cnblogs.com/luowei010101/p/2358701.html