原本想先写一下JAVA的反射机制的,整了两天,感受没整出个简单和思路出来,想来,算了,后面再整吧。想一想,今天在支持使用Struts2框架开发的时候,发现基本的使用仍是有些生疏,仍是先小结一下Struts2的基本用法吧。 html
准备工做当是准备使用框架时使用的包,具体以下: 前端
Maven工程pom.xml中添加依赖: java
<dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.3.14</version> </dependency>(如今低版本struts2有比较严重的问题,不过用于Demo学习仍是能够的,应该不会没事把Demo应用挂到公网的,固然,想感觉一下struts2所带来的安全风暴,也能够放上去感觉感觉的,哈哈哈!!!)
struts2-core-2.3.14.jar
xwork-core-2.3.14.jar
commons-lang3-3.1.jar
asm-3.3.jar
asm-commons-3.3.jar
asm-tree-3.3.jar
freemarker-2.3.19.jar
ognl-3.0.6.jar
javassist-3.11.0.GA.jar
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar web
添加依赖后Maven包里多了这几个包,没有建Maven工程的项目应用把这几个包引入应用也没问题的。(固然也有意外,具体就看人品了,没试过,哪天中招了再说,^_^) apache
总的来讲,Struts2使用时候大格局配置比较简单: json
(1)web.xml配置:配置struts2的过滤器,用于请求的拦截,并按struts2自定义的流程去走(好像这个过滤器一般被称为Struts2请求分发器); api
(2)struts.xml:基本功能就是配置请求与处理类、处理类处理结果与响应内容的映射关系; 浏览器
(3)请求处理类:用于处理接收的请求,在struts.xml里把请求action名称与处理类映射上。 安全
Demo源码以下: 服务器
web.xml文件:
<?xml version="1.0" encoding="utf-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Archetype Created Web Application</display-name> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>error.jsp</welcome-file> </welcome-file-list> </web-app>
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> <!-- package的name属性在我看来没什么用处,感受只是为了配置的继承方便而已 --> <!-- struts-default是一个struts框架包中自定的一个package, --> <!-- 在struts2-core包中的struts-default.xml进行定义 --> <!-- namespace如今的理解是URL除去域名和请求文件名后每剩下的那一部分 --> <!-- 处理URL:http://localhost/fristDemo.action --> <package name="demo1" namespace="/" extends="struts-default"> <!-- name是action的名称 --> <!-- class对应请求为firstDemo.action的处理对象类型 --> <!-- 还有一个method属性省略了,默认是execute,即,下面这个配置至关于:: --> <!-- <action name="fristDemo" class="tutorial.demo.DemoAction" method="execute"> --> <action name="firstDemo" class="tutorial.demo.action.DemoAction"> <result name="success">/demo1Success.jsp</result> <result name="error">/demo1Fail.jsp</result> </action> </package> <!-- 处理URL:http://localhost/test/secondDemo.action --> <package name="demo2" namespace="/test" extends="struts-default"> <action name="secondDemo" class="tutorial.demo.action.DemoAction" method="sayHello"> <result name="success">/demo2Success.jsp</result> <result name="error">/demo2Fail.jsp</result> </action> </package> </struts>DemoAction.java请求处理类:
package tutorial.demo.action; import com.opensymphony.xwork2.ActionSupport; public class DemoAction extends ActionSupport { // 在struts。xml配置文件中, 若是不指定action对应的执行方法, // 则默认执行该action对应的方法名为execute的方法 public String execute() { System.out.println("默认调用方法!"); return "success"; } public String sayHello() { System.out.println("配置文件中指定调用方法!"); return "success"; } }
其它jsp文件:略。
在struts2框下,在处理类中获取前端输入的参数有两种方式:
(1)非IOC方式(感观上讲是经过HttpServletRequest对象获取)
既然是经过HttpServletRequest对象获取,首先要作的是获取HttpServletRequest对象,而后再从HttpServletRequest对象中读取相应名称的参数,具体看以下处理类的修改后的代码:
添加jar包:
servlet-api-2.5-6.1.14.jar
Maven依赖:
<dependency> <groupId>org.mortbay.jetty</groupId> <artifactId>servlet-api-2.5</artifactId> <version>6.1.14</version> </dependency>
DemoAction.java请求处理类(1):
package tutorial.demo.action; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class DemoAction extends ActionSupport { // 在struts。xml配置文件中, 若是不指定action对应的执行方法, // 则默认执行该action对应的方法名为execute的方法 public String execute() { System.out.println("默认调用方法!"); return "success"; } public String sayHello() { System.out.println("配置文件中指定调用方法!"); // 取Action上下文 ActionContext context = ActionContext.getContext(); // 从上下文中取出Http请求对象,请求对象中保存了请求的全部内容 HttpServletRequest request = (HttpServletRequest)context.get(ServletActionContext.HTTP_REQUEST); // 请求对象中取出参数username的值 String username = request.getParameter("username"); // 请求对象中取出参数password的值 String password = request.getParameter("password"); // 输出请求参数 System.out.println("前端输入的参数是: " + username + "和 " + password); return "success"; } }
如请求URL:
http://localhost/test/secondDemo.action?username=demo&password=123456
Console打印结果:
配置文件中指定调用方法!
前端输入的参数是: demo和 123456
固然,为了方便,获取HttpServletRequest的方式能够经过继承ServletRequestAware接口,并实现相应的方法便可,具体以下:
DemoAction.java请求处理类(2):
package tutorial.demo.action; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class DemoAction extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; // 在struts。xml配置文件中, 若是不指定action对应的执行方法, // 则默认执行该action对应的方法名为execute的方法 public String execute() { System.out.println("默认调用方法!"); return "success"; } public String sayHello() { System.out.println("配置文件中指定调用方法!"); // 请求对象中取出参数username的值 String username = request.getParameter("username"); // 请求对象中取出参数password的值 String password = request.getParameter("password"); // 输出请求参数 System.out.println("前端输入的参数是: " + username + "和 " + password); return "success"; } // 继承ServletRequestAware实现的方法 public void setServletRequest(HttpServletRequest request) { this.request = request; } }
第三种获HttpServletRequest对象的方式:
HttpServletRequest requst = ServletActionContext.getRequest();
从代码简洁程序方面来说,获取HttpServletRequest的方式,继承ServletRequestAware接口最优(第二种),ServletActionContext获取次之(第三种),ActionContext获取最差(第一种)。
(好了,回到正题,继续咱们从前端获取参数的方式!!!!!)
(2)IOC方式(感观上讲是经过struts2框架的自动赋值方式获取)
IOC方式代码很简单,先看具体代码:
DemoAction.java请求处理类:
package tutorial.demo.action; import com.opensymphony.xwork2.ActionSupport; public class DemoAction extends ActionSupport { private String aa; private int bb; // username对应set方法 public void setUsername(String username) { this.aa = username; } // password对应set方法 public void setPassword(int password) { this.bb = password; } // 在struts。xml配置文件中, 若是不指定action对应的执行方法, // 则默认执行该action对应的方法名为execute的方法 public String execute() { System.out.println("默认调用方法!"); return "success"; } public String sayHello() { System.out.println("配置文件中指定调用方法!"); // 输出请求参数 System.out.println("前端输入的参数是: " + aa + "和 " + bb); return "success"; } }
在效果上与以前是同样的,如请求URL:
http://localhost/test/secondDemo.action?username=demo&password=123456
Console打印结果:
配置文件中指定调用方法!
前端输入的参数是: demo和 123456
说明,IOC方式须要作如下事情:
a. 在处理类(DemoAction)中添加用于接收参数值的变量:
b. 给添加的变量配上相应的setter方法(注意方法名构成:set + 转入参数名第一个字母的大写形式 + 转入参数名第二个字母之后的字符[含第二个])。(如转入参数名为:username,对应setter名为:setUsername)
以下,对应的配置这个以后,就可自动接收前端传过来名为username和password的参数,其中username为字符串,password被解析为整型:
private String aa; private int bb; // username对应set方法 public void setUsername(String username) { this.aa = username; } // password对应set方法 public void setPassword(int password) { this.bb = password; }
(为何这么随意地使用个aa、bb的变量名,太丢广大码农的脸了!!!其实我是无辜的,为了不把setter与变量名想固然地关系起来,只好忍痛弄个aa、bb的变量来接收数据,而没有使用优雅的username和password!!!!!!)
这一节的标题有点太俗了一些,官方的说法应该是:数据输出到视图资源(哎,这就小菜和大鸟的区别啊)。
原理:
首先,咱们要了解一些事实:
a. HttpServlet对象(包括HttpServletRequest、HttpServletResponse)存在于服务器请求响应的整个生命周期中(粗划分);(java web基本知识)
b. 在java中,只要咱们获取一个对象,咱们就能够获取与改变这个对象里开放的信息;(java基本知识)
c. 咱们能够在Action类(处理类)和jsp文件最终转化的servlet都获取HttpServlet对象;(struts2知识、jsp与servlet关系)
d. Action类与jsp文件最终转化的servlet处理于同一个请求响应的生命周期;(java web、struts2基本知识)
e. jsp文件最终转化的servlet处理时间在Action类的后面。(java web、struts2基本知识)
(以上“事实”理解有误之处,望指点,谢谢!!!^_^)
到如今,已经很明了了,也就是:
咱们能够在Action类中获取HttpServlet对象(事实c),把数据放到HttpServlet对象中(事实b),而后在jsp文件中获取HttpServlet对象(事实c),把Action类放入的数据从HttpServlet对象中取出(事实b)。
因而,咱们也就获得了下面的数据转递的例子(数据从DemoAction转到demo2Success.jsp)。
实例:
DemoAction.java请求处理类:
package tutorial.demo.action; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionSupport; public class DemoAction extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; // 继承ServletRequestAware必须实现的request的setter方法 public void setServletRequest(HttpServletRequest request) { this.request = request; } // 在struts。xml配置文件中, 若是不指定action对应的执行方法, // 则默认执行该action对应的方法名为execute的方法 public String execute() { System.out.println("默认调用方法!"); return "success"; } public String sayHello() { // 将要转递的数据 String aa = "Demo"; int bb = 123456; // 把数据放到HttpServletRequest中 request.setAttribute("username", aa); request.setAttribute("password", bb); return "success"; } }demo2Success.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="utf-8"%> <% String username = (String)request.getAttribute("username"); Integer password = (Integer)request.getAttribute("password"); // 设置输出字符串编码,与数据转递主题无关 response.setContentType("text/html;charset=gbk"); out.println("在jsp中输出从Action转递的数据:" + username + "和" + password.toString() ); %>输出结果:
本例中使用的是HttpServletRequest对象进行传递,除此外也可使用其它对象传递,前提是:该对象在Action与jsp文件最终转化的servlet均可以获取而且能够改变其数据(如:session对象、application对象、context对象等)。
在讲述响应返回JSON格式数据方式以前,我以为有必要处理一个问题:“JSON格式数据与咱们通常返回的HTML页面数据有什么区别?”
JSON格式数据是什么样的数据?说到底,JSON格式数据就是一个按JSON规范整出来的字符串,在后台处理时,它就是一个普通的字符串;
HTML页面数据是什么样的数据?同样的,不一样点是,HTML页面数据是按HTML规范整出来的字符串,在前端浏览器,它解析成一个个好看的WEB页面,那是浏览器的功劳,在后台处理时,它也是一个普通的字符串。
在web服务器处理请求过程当中,在响应的过程当中,无论理是JSON格式数据仍是HTML页面数据,web服务器识别的都只是一个字符串,作的都是只是把字符串返回给请求端。
既然这样,那么是否是能够像返回HTML页面数据同样响应返回JSON格式数据呢?答案是确定的!!!^_^
下面是和常见的响应方式同样的返回JSON数据的方法(或把数据放到Response响应对象的方式):
(1)servlet方式(直接获取HttpServletResponse对象获取输出流写入数据):
DemoAction.java请求处理类:
package tutorial.demo.action; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.interceptor.ServletResponseAware; import com.opensymphony.xwork2.ActionSupport; public class DemoAction extends ActionSupport implements ServletResponseAware { private HttpServletResponse response; // 继承ServletResponseAware必须实现的response的setter方法 public void setServletResponse(HttpServletResponse response) { this.response = response; } // 在struts。xml配置文件中, 若是不指定action对应的执行方法, // 则默认执行该action对应的方法名为execute的方法 public String execute() { System.out.println("默认调用方法!"); return "success"; } public void sayHello() { // 向浏览器发送一个响应头,设置浏览器的解码方式为UTF-8 response.setHeader("Content-type", "text/html;charset=UTF-8"); try { // 构造json字符串 String json = "{\"username\": \"Demo\", \"birthdate\": \"2013-08-03\"}"; PrintWriter out = response.getWriter(); out.println(json); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } // 注意,这里是没有返回 } }
<?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> <!-- package的name属性在我看来没什么用处,感受只是为了配置的继承方便而已 --> <!-- struts-default是一个struts框架包中自定的一个package, --> <!-- 在struts2-core包中的struts-default.xml进行定义 --> <!-- namespace如今的理解是URL除去域名和请求文件名后每剩下的那一部分 --> <!-- 处理URL:http://localhost/fristDemo.action --> <package name="demo1" namespace="/" extends="struts-default"> <!-- name是action的名称 --> <!-- class对应请求为firstDemo.action的处理对象类型 --> <!-- 还有一个method属性省略了,默认是execute,即,下面这个配置至关于:: --> <!-- <action name="fristDemo" class="tutorial.demo.DemoAction" method="execute"> --> <action name="firstDemo" class="tutorial.demo.action.DemoAction"> <result name="success">/demo1Success.jsp</result> <result name="error">/demo1Fail.jsp</result> </action> </package> <!-- 处理URL:http://localhost/test/secondDemo.action --> <package name="demo2" namespace="/test" extends="struts-default"> <action name="secondDemo" class="tutorial.demo.action.DemoAction" method="sayHello"> <!-- 注意:这里不用添加result标签 --> </action> </package> </struts>
(2)正常struts2映射jsp(或其它视图文件)返回方式 :
DemoAction.java请求处理类:
package tutorial.demo.action; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import com.opensymphony.xwork2.ActionSupport; public class DemoAction extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; // 继承ServletRequestAware必须实现的request的setter方法 public void setServletRequest(HttpServletRequest request) { this.request = request; } // 在struts。xml配置文件中, 若是不指定action对应的执行方法, // 则默认执行该action对应的方法名为execute的方法 public String execute() { System.out.println("默认调用方法!"); return "success"; } public String sayHello() { // 构造json字符串 String json = "{\"username\": \"Demo\", \"birthdate\": \"2013-08-03\"}"; request.setAttribute("json", json); return "success"; } }strtus.xml(主要是相应的secondDemo对应Action的配置有所修改):
<?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> <!-- package的name属性在我看来没什么用处,感受只是为了配置的继承方便而已 --> <!-- struts-default是一个struts框架包中自定的一个package, --> <!-- 在struts2-core包中的struts-default.xml进行定义 --> <!-- namespace如今的理解是URL除去域名和请求文件名后每剩下的那一部分 --> <!-- 处理URL:http://localhost/fristDemo.action --> <package name="demo1" namespace="/" extends="struts-default"> <!-- name是action的名称 --> <!-- class对应请求为firstDemo.action的处理对象类型 --> <!-- 还有一个method属性省略了,默认是execute,即,下面这个配置至关于:: --> <!-- <action name="fristDemo" class="tutorial.demo.DemoAction" method="execute"> --> <action name="firstDemo" class="tutorial.demo.action.DemoAction"> <result name="success">/demo1Success.jsp</result> <result name="error">/demo1Fail.jsp</result> </action> </package> <!-- 处理URL:http://localhost/test/secondDemo.action --> <package name="demo2" namespace="/test" extends="struts-default"> <action name="secondDemo" class="tutorial.demo.action.DemoAction" method="sayHello"> <result name="success">/json.jsp</result> <result name="error">/error.jsp</result> </action> </package> </struts>json.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> ${request.json}(3)使用struts2提供的json插件功能
在前面的两个方法中,构造json串的话都是咱们本身构造的,在方法(3)中,咱们将使用到struts2的json插件功能,自动地把咱们的对象转化为json字符串返回给前端,具休实例以下:
DemoAction.java请求处理类(添加jsonTest方法):
package tutorial.demo.action; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionSupport; public class DemoAction extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; private Map<String, Object> dataMap = new HashMap<String, Object>(); public Map<String, Object> getDataMap() { return dataMap; } public void setDataMap(Map<String, Object> dataMap) { this.dataMap = dataMap; } // 继承ServletRequestAware必须实现的request的setter方法 public void setServletRequest(HttpServletRequest request) { this.request = request; } // 在struts。xml配置文件中, 若是不指定action对应的执行方法, // 则默认执行该action对应的方法名为execute的方法 public String execute() { System.out.println("默认调用方法!"); return "success"; } public String sayHello() { // 构造json字符串 String json = "{\"username\": \"Demo\", \"birthdate\": \"2013-08-03\"}"; request.setAttribute("json", json); return "success"; } public String jsonTest() { Person person1 = new Person("Jack", 170, 100); Person person2 = new Person("Lucy", 160, 90); Person person3 = new Person("Lili", 165, 95); Person person4 = new Person("Cray", 186, 130); List<Person> personList = new ArrayList<Person>(); personList.add(person1); personList.add(person2); personList.add(person3); personList.add(person4); dataMap.put("status", "success"); dataMap.put("personList", personList); return "success"; } }
struts.xml(添加jsonAction.action的处理配置):
<?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> <!-- package的name属性在我看来没什么用处,感受只是为了配置的继承方便而已 --> <!-- struts-default是一个struts框架包中自定的一个package, --> <!-- 在struts2-core包中的struts-default.xml进行定义 --> <!-- namespace如今的理解是URL除去域名和请求文件名后每剩下的那一部分 --> <!-- 处理URL:http://localhost/fristDemo.action --> <package name="demo1" namespace="/" extends="struts-default"> <!-- name是action的名称 --> <!-- class对应请求为firstDemo.action的处理对象类型 --> <!-- 还有一个method属性省略了,默认是execute,即,下面这个配置至关于:: --> <!-- <action name="fristDemo" class="tutorial.demo.DemoAction" method="execute"> --> <action name="firstDemo" class="tutorial.demo.action.DemoAction"> <result name="success">/demo1Success.jsp</result> <result name="error">/demo1Fail.jsp</result> </action> </package> <!-- 处理URL:http://localhost/test/secondDemo.action --> <package name="demo2" namespace="/test" extends="struts-default"> <action name="secondDemo" class="tutorial.demo.action.DemoAction" method="sayHello"> <result name="success">/json.jsp</result> <result name="error">/error.jsp</result> </action> </package> <!-- 自动把action中的dataMap转化为json字符串的配置 --> <package name="json" namespace="/json" extends="json-default"> <action name="jsonAction" class="tutorial.demo.action.DemoAction" method="jsonTest"> <result type="json"> <param name="root">dataMap</param> </result> </action> </package> </struts>
配置总结:
在配置利用struts2的json插件自动将对象以json字符串返回时须要作如下几件事:
a. 添加struts2的json插件包及相应依赖:
Maven工程的pom.xml文件添加依赖:
<dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-json-plugin</artifactId> <version>2.3.14</version> </dependency>b. 定义一个对象用于构造json对象(即最终将被插件转成json串的字符串,如例中的:dataMap);
c. struts.xml添加一个继承json-default的包(package),并进行相应的输出配置。
(这里讲的是使用struts2进行json字符串返回最基本的配置,还有基本功能的配置具体可查看官方文档。)
注:无论web应用有没有使用struts框架,无论在servlet处理类,仍是在JSP文件中(JSP文件最后也是被转化为一个servlet类的),在响应处理上的本质都是同样的,都是把响应的字符串写入HttpServletResponse对象中,web服务器在向前端响应时,就从HttpServletResponse对象中取出响应数据,返回给发起请求的前端。
文件上传功能的基本功能实现和struts2的基本映射功能是同样的,只是上传功能为实现一些额外功能,存在它一些特有的配置项目而已,基本上传框架以下:
UploadDemoAction.java上传请求处理类:
package tutorial.demo.action; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import com.opensymphony.xwork2.ActionSupport; public class UploadDemoAction extends ActionSupport { private File file; private String fileName; private String fileContentType; public String fileUpload() { // 文件保存路径 File savefile = new File("c:\\test.txt"); try { // 复制临时文件到指定文件中 FileUtils.copyFile(file, savefile); } catch (IOException e) { e.printStackTrace(); } return "success"; } public File getFile() { return file; } public void setFile(File file) { this.file = file; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFileContentType() { return fileContentType; } public void setFileContentType(String fileContentType) { this.fileContentType = fileContentType; } }struts.xml添加配置以下:
<!-- 上传功能添加配置 --> <package name="upload" namespace="/upload" extends="struts-default"> <action name="fileUpload" class="tutorial.demo.action.UploadDemoAction" method="fileUpload"> <result name="success">/upload.jsp</result> <result name="fail">/error.jsp</result> </action> </package>upload.jsp(上传前端页面):
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <form enctype="multipart/form-data" action="upload/fileUpload.action" method="post"> 请选择上传文件: <input type="file" name="file" /> <input type="submit" value="submit" /> </form>