1、package元素,除了有name和extends属性,还有abstract属性:这个属性说明这个包是个抽象包,类似抽象类,不能直接使用,只能定义一个子包,然后extends这个abstract包。struts-default这个package就是abstract的,因此需要我们继承这个包来使用。
namespace属性:起到命名空间分割的作用。通常将namespace的属性值定义成页面所在的目录名。
2、使用input file进行文件上传:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'fileUpload.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="fileUploadResult.jsp" 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> </body> </html>
一个显示页面:
<%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'fileUploadResult.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <% InputStream is = request.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String buffer = null; while(null != (buffer = br.readLine())) { out.print(buffer + "<br>"); } %> </body> </html>
注意的是,在输入页面,要进行文件上传,form必须使用post方法,而且要使用enctype=multipart/form-data,显示页面要使用io的形式读取传递过来的数据,如果使用request.getParameter(),结果会显示null。
进行文件上传时,必须将表单的method属性设置为post,将enctype属性设置为multipart/form-data
3、使用apache提供的组件进行文件上传:
下载commons-fileupload-1.3-bin.zip和其要依赖的组件包:commons-io-2.2-bin.zip,将其放入WebRoot/WEB-INF/lib目录下,上传文件页面fileUpload.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'fileUpload.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="UploadServlet" method="post" enctype="multipart/form-data"> username:<input type="text" name="username"><br> file1:<input type="file" name="file"><br> file2:<input type="file" name="file2"><br> <input type="submit" value="submit"> </form> </body> </html>
使用servlet进行文件上传处理:UploadServlet:
package com.cdtax.servlet; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; 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 factory = new DiskFileItemFactory(); String path = req.getRealPath("/upload"); factory.setRepository(new File(path)); factory.setSizeThreshold(1024 * 1024); ServletFileUpload upload = new ServletFileUpload(factory); try { List<FileItem> list = (List<FileItem>)upload.parseRequest(req); for(FileItem item : list) { String name = item.getFieldName(); 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 e) { e.printStackTrace(); } req.getRequestDispatcher("fileUploadResult.jsp").forward(req, resp); } }
在这个servlet中用到了apache的文件上传组件,组要是DiskFileItemFactory、ServletFileUpload、FileItem、
最后的显示页面:
<%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'fileUploadResult.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <% /* InputStream is = request.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String buffer = null; while(null != (buffer = br.readLine())) { out.print(buffer + "<br>"); } */ %> username:${requestScope.username }<br> file:${requestScope.file }<br> file2:${requestScope.file2 }<br/> </body> </html>
4、使用struts框架实现文件上传
struts框架也是借助于apache的文件上传组件。
struts2有一个默认的属性文件,在struts2-core-2.3.14.jar包下的org.apache.struts2下,名字叫做default.properties,里面配置了一些struts框架的属性,如:
struts.action.extension=action,,等等,如果需要修改struts2的默认属性配置,需要在src目录下建立一个属性文件:struts.properties,然后写上要自定义的配置项,如:
struts.action.extension=do 等等,就是覆盖default.properties的属性设置(default.properties是只读的)
使用struts2框架实现文件上传:一个输入页面:fileUpload.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'fileUpload.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="uploadAction.action" method="post" enctype="multipart/form-data"> username:<input type="text" name="username"><br> file1:<input type="file" name="file"><br> <input type="submit" value="submit"> </form> </body> </html>
一个Action:UploadAction
package com.cdtax.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; //输入页面表单<input type="file" name="file">,name的值 private String fileFileName;//变量命名是规范的,就是输入页面file的name值+FileName(这个是固定的) private String fileContentType;//变量命名是规范的,就是输入页面file的name值+ContentType(这个是固定的) public String getFileFileName() { return fileFileName; } public void setFileFileName(String fileFileName) { this.fileFileName = fileFileName; } public String getFileContentType() { return fileContentType; } public void setFileContentType(String fileContentType) { this.fileContentType = fileContentType; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public File getFile() { return file; } public void setFile(File file) { this.file = file; } @Override public String execute() throws Exception { System.out.println(fileFileName); System.out.println(file.getName()); String root = ServletActionContext.getRequest().getRealPath("/upload"); InputStream is = new FileInputStream(file); 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); } is.close(); os.close(); return SUCCESS; } }
要注意这里的file,是已经保存到临时目录中的临时文件。
配置struts.xml,添加action
<action name="uploadAction" class="com.cdtax.struts2.UploadAction"> <result name="success">/fileUploadResult.jsp</result> </action>
最后一个输出结果页面,fileUploadResult.jsp:
<%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'fileUploadResult.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> username:<s:property value="username"/> fllename:<s:property value="fileFileName"/> filecontexttype:<s:property value="fileContentType" /> </body> </html>
这里使用了struts的标签库。
struts2在进行文件上传操作时,实际上是通过两个步骤实现的:
1)首先将客户端上传的文件保存到struts.multipart.saveDir键所指定的目录中,如果该键所对应的目录不存在,那么就保存到javax.servlet.context.tempDir环境变量所指定的目录中。
2)Action中所定义的File类型的成员变量file实际上指向的是临时目录中的临时文件,然后在服务器端通过IO的方式将临时文件写入到指定的服务器端目录中。
在完成上述代码运行时,总是提示org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException:the request was rejected because its size (64594527) exceeds the configured maximum (2097152),无法完成上传,问题的原因是struts2框架规定了默认的上传文件大小为2097152,即2M,是在struts2默认的属性文件,struts2-core-2.3.14.jar包下的org.apache.struts2下,名字叫做default.properties中的struts.multipart.maxSize=2097152规定的,解决的方法有两个:一个是在struts.xml中添加<constant
name="struts.multipart.maxSize" value="10485760"/>,value规定文件大小,二是在struts.properties中定义:struts.multipart.maxSize=2097152000
struts.properties的优先级高。
如果没有定义struts.multipart.saveDir,会出现:信息: Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir
因为在default.properties中struts.multipart.saveDir值为空,没定义,我们可以在struts.properties中定义,这是临时文件保存的地方,没定义,默认在javax.servlet.context.tempdir指定的目录下,就是D:\apache-tomcat-6.0.36\work\Catalina\localhost\struts2,项目的根目录下。
5、OGNL(Object Graph Navigation Language)对象图导航语言。struts标签库就是借助OGNL实现的。
6、多文件上传
一个上传输入页面fileUpload2.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'fileUpload2.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="uploadAction2.action" method="post" enctype="multipart/form-data"> username:<input type="text" name="username"><br> file1:<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> </body> </html>
一个action:UploadAction2
package com.cdtax.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; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public List<File> getFile() { return file; } public void setFile(List<File> file) { this.file = file; } public List<String> getFileFileName() { return fileFileName; } public void setFileFileName(List<String> fileFileName) { this.fileFileName = fileFileName; } public List<String> getFileContentType() { return fileContentType; } public void setFileContentType(List<String> fileContentType) { this.fileContentType = fileContentType; } @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; } }
配置struts.xml,添加action
<action name="uploadAction2" class="com.cdtax.struts2.UploadAction2"> <result name="success">/fileUploadResult2.jsp</result> </action>
一个最后的输出结果页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'fileUploadResult2.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> username:<s:property value="username"/> <s:iterator value="fileFileName" id="f"> file:<s:property value="#f" /><br/> </s:iterator> <s:iterator value="fileContentType" id="n"> contenttype:<s:property value="#n"/><br/> </s:iterator> </body> </html>
要注意,输入页面的多个file,其name值要相同,在action中,定义成员变量要定义为集合。
7、<iterator>标签:很重要。
OGNL有一个根元素,如果不是根元素,就使用#表示,如file:<s:property value="#f" />
8、struts的文件上传也是使用拦截器来处理的,在struts-default.xml中有interceptor为fileUpload的拦截器,具体为FileUploadInterceptor
9、文件的下载:
一个下载页面download.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'download.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <a href="downloadFile.action">xiazai</a> </body> </html>
一个处理下载的action
package com.cdtax.struts2; import java.io.InputStream; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; public class DownloadAction extends ActionSupport { public InputStream getDownloadFile() { return ServletActionContext.getServletContext().getResourceAsStream("/upload/commons.zip"); } @Override public String execute() throws Exception { return SUCCESS; } }
struts.xml中进行配置:
<action name="downloadFile" class="com.cdtax.struts2.DownloadAction"> <result type="stream"> <param name="ContentDisposition">attachment;filename="commons.zip"</param> <param name="inputName">downloadFile</param> </result> </action>
需要注意的地方:action中提供了一个方法获得输入流,这个方法的命名要与配置文件中<param name="inputName">downloadFile</param>对应起来,这里是downloadFile,方法就是getDownloadFile;action的方法返回的流是实际文件,如("/upload/commons.zip对应磁盘上的文件,配置文件中也有一个filename,这个文件名是展现给用户下载对话框中的文件名,对于<param name="ContentDisposition">attachment;filename="commons.zip"</param>如果没有指定attachment,默认为inline的,对于像exe等文件,弹出下载对话框,而对于txt等文件,直接在页面显示内容,加上attachment,无论什么文件,都弹出下载对话框。
对于下载文件,action配置的result类型type为stream
改进:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'download.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <a href="downloadFile2.action?num=2">xiazai</a> </body> </html>
package com.cdtax.struts2; import java.io.InputStream; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; public class DownloadAction2 extends ActionSupport { private int num; private String filename; public String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public InputStream getDownloadFile() { if(1 == num) { this.filename = "comments.zip"; return ServletActionContext.getServletContext().getResourceAsStream("/upload/commons.zip"); } else { this.filename = "struts2.3.14.zip"; return ServletActionContext.getServletContext().getResourceAsStream("/upload/struts-2.3.14-all.zip"); } } }
<action name="downloadFile2" class="com.cdtax.struts2.DownloadAction2"> <result type="stream"> <param name="ContentDisposition">attachment;filename=${filename}</param> <param name="inputName">downloadFile</param> </result> </action>
根据客户端传递的参数不同下载不同的文件
10、中文乱码问题:
对action进行改进
package com.cdtax.struts2; import java.io.InputStream; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; public class DownloadAction2 extends ActionSupport { private int num; private String filename; public String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public InputStream getDownloadFile() { try { if(1 == num) { this.filename = "中文comments.zip"; this.filename = new String(this.filename.getBytes("gbk"),"iso8859_1"); return ServletActionContext.getServletContext().getResourceAsStream("/upload/commons.zip"); } else { this.filename = "中文struts2.3.14.zip"; this.filename = new String(this.filename.getBytes("gbk"),"iso8859_1"); return ServletActionContext.getServletContext().getResourceAsStream("/upload/struts-2.3.14-all.zip"); } } catch(Exception e) { e.printStackTrace(); } return null; } }
使用new String(this.filename.getBytes("gbk"),"iso8859_1");进行转码
11、struts2可以使用struts2-convention-plugin-2.3.14.jar插件实现基于注解的配置
package com.cdtax.struts2; import java.util.Date; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.ExceptionMapping; import org.apache.struts2.convention.annotation.ExceptionMappings; import org.apache.struts2.convention.annotation.InterceptorRef; import org.apache.struts2.convention.annotation.InterceptorRefs; import org.apache.struts2.convention.annotation.ParentPackage; import org.apache.struts2.convention.annotation.Result; import com.cdtax.bean.User; import com.cdtax.service.LoginService; import com.cdtax.service.impl.LoginServiceImpl; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; @ParentPackage("struts-default") @Action(value="login",results={ @Result(name="success",location="/result.jsp"), @Result(name="input",location="/login.jsp")}) @InterceptorRef("defaultStack") @InterceptorRefs({@InterceptorRef(""),@InterceptorRef("")}) @ExceptionMapping(exception = "", result = "") @ExceptionMappings({}) public class LoginAction extends ActionSupport { private String username; private String password; private int age; private Date date; private LoginService loginService = new LoginServiceImpl(); public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String execute() throws Exception { // if(!"hello".equals(username)) // { // throw new UsernameException("username invalid"); // } // if(!"world".equals(password)) // { // throw new PasswordException("password invalid!"); // } // HttpServletRequest request = ServletActionContext.getRequest(); // HttpSession session = request.getSession(); // session.setAttribute("hello", "heloworld"); // // ActionContext actionContext = ActionContext.getContext(); // Map<String,Object> map = actionContext.getSession(); // //使用Map是为了进行单元测试 // Object object = map.get("hello"); // System.out.println(object); if(this.loginService.isLogin(username, password)) { User user = new User(); user.setUsername(username); user.setPassword(password); ActionContext.getContext().getSession().put("userInfo", user); return SUCCESS; } return INPUT; } public String myExecute() { System.out.println("myExecute invoke!"); return SUCCESS; } }
如果既有struts.xml又有注解,冲突时,以注解为准。