如果每个请求都对应一个action,这样就会造成action过多,使得程序显得比较臃肿。这样就可以通过使用DispatchAction,其原理是将一类请求写到一个action中。
PS:其实这种思想和以前学Servlet时,处理一类事物的控制器差不多。原文链接:用户管理系统
PS:在uri中,跳转到分派action,如果execute方法没被删除,每次都是调用它来处理。所以一定要将它删除。
<struts-config> <global-forwards > <forward name="goerror" path="/WEB-INF/Error.jsp" /> </global-forwards> </struts-config>
<struts-config> <action-mappings > <action> <!-- 局部跳转 --> <forward name="logout" path="/WEB-INF/login.jsp" /> <forward name="ok" path="/WEB-INF/welcome.jsp" /> </action> </action-mappings> </struts-config>
PS:全局跳转指得是所有的action都可以跳转到该页面,局部跳转指得是只有本action可以跳转到该页面。需要在struts-config.xml中配置。
动态表单(dynimic form),当表单个数和类型不确定的情况下,就可以使用动动态表单来解决。
1、普通表单actionForm是首先需要定义这样的一个类,然后配置到struts-config.xml中。
2、动态表单完全依赖于反射机制创建,不需要定义表单类,直接在struts-config.xml配置即可。
<form action="/DynamicForm/action名.do?type=login" method="post"> 用户名:<input type="text" name="username" /><br /> 密 码:<input type="password" name="password" /><br /> Email :<input type="text" name="email" /><br /> <input type="submit" value="注册用户" /> </form>
<struts-config> <form-beans> <form-bean name="userForm" type="org.apache.struts.action.DynaActionForm"> <!-- 动态表单的属性是配置出来的 --> <form-property name="username" type="java.lang.String" /> <form-property name="passowrd" type="java.lang.String" /> <form-property name="email" type="java.lang.String" /> </form-bean> </form-beans> </struts-config>
PS:动态表单不需要写ActionForm类,只需要在struts-config.xml中配置成如上形式。动态表单比静态表单要方便很多,而且也将硬编码做成了配置形式,扩展性更强了,所以建议使用动态表单。
/* * Generated by MyEclipse Struts * Template path: templates/java/JavaClass.vtl */ package com.pc.web.struts.action; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.upload.FormFile; import com.pc.domain.User; import com.pc.service.UserService; import com.pc.utils.MyTools; import com.pc.web.struts.form.UserForm; /** * MyEclipse Struts Creation date: 01-27-2016 * * XDoclet definition: * * @struts.action */ public class RegisterAction extends Action { /* * Generated Methods */ /** * Method execute * * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { UserForm userForm = (UserForm) form; // 取出用户名字 String name = userForm.getName(); FormFile formFile = userForm.getMyphoto(); // 通过formFile可以获取关于用户上传文件的各种信息 String filename = formFile.getFileName(); String newFileName = MyTools.getNewFileName(filename); // 获取文件大小 int filesize = formFile.getFileSize(); // 上传文件不能大于10M if(filesize > 10 * 1024 * 1024) { return mapping.findForward("error"); } // 测试 // System.out.println(filename + " " + filesize); InputStream inputStream = null; OutputStream outputStream = null; try { // 取出输入流 inputStream = formFile.getInputStream(); // 得到一个输出流->文件 // 1.得到file文件夹上传到tomcat服务器后的绝对路径 String keepFilePath = this.getServlet().getServletContext() .getRealPath("/file"); // 测试 // System.out.println(keepFilePath); // 创建输出流 outputStream = new FileOutputStream(keepFilePath + "\\" + newFileName); // 测试 // System.out.println(keepFilePath + "\\" + filename); // 读取文件并写出到服务器file路径下 int len = 0; // buffer byte[] bytes = new byte[1024]; // 循环处理 while ((len = inputStream.read(bytes)) > 0) { outputStream.write(bytes, 0, len); } // 如果用户上传文件成功,则把该用户信息保存到数据库中 UserService userService = new UserService(); User user = new User(); user.setUsername(userForm.getName()); user.setPreFileName(filename); user.setNewFileName(newFileName); // 测试 // System.out.println(user.getUsername() + " " + user.getPreFileName() + " " + user.getNewFileName()); if (userService.addUser(user)) { return mapping.findForward("register"); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { inputStream.close(); outputStream.close(); } catch (Exception e2) { // TODO: handle exception e2.printStackTrace(); } inputStream = null; outputStream = null; } return mapping.findForward("error"); } }
思路:使用过滤器解决
package com.pc.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; /** * * @author Switch * @function 过滤中文乱码 * @description * */ public class EncodingFilter extends HttpServlet implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("charset=utf-8"); chain.doFilter(request, response); } @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } }
思路一:在文件名称里加入毫秒级时间信息。
思路二:扫描该文件夹里的所有文件,如果有相同文件,就在文件名里加诸如“第几个”之类的前缀或者后缀。
思路三:利用UUID类生成伪随机数,然后拼接文件名。
package com.pc.utils; import java.util.UUID; /** * * @author Switch * @function 工具类 * @description 上传下载的各种工具方法 * */ public class MyTools { public static String getNewFileName(String fileName) { // 获取伪随机数 String uuid = UUID.randomUUID().toString(); // 例:e08ac7c9-1adc-4bd6-8674-eabbb302d92e // System.out.println(uuid); // 上传文件名考虑扩展名问题 // String fileName = "switch.jpg"; // // 截取字符串 String str = "abcdef"; // String subStr = str.substring(2, 4); // // 输出cd System.out.println(subStr); // // // 找到最后一个指定String的的位置 // int index = fileName.lastIndexOf("."); // // 输出6 // System.out.println(index); // 找到上传文件的扩展名 fileName = fileName.substring(fileName.indexOf("."), fileName.length()); // 输出.jpg // System.out.println(fileName); // 拼接 return uuid + fileName; // 例:d1ebe185-fd40-48db-9d25-0e9f25f606af.jpg // System.out.println(fileName); } }
可以从Tomcat主目录\conf目录下的 web.xml中可以查看文件的类型
// 获取文件大小 int filesize = formFile.getFileSize(); // 上传文件不能大于10M if(filesize > 10 * 1024 * 1024) { return mapping.findForward("error"); }
PS:文件已经上传到服务器了,但是文件名为了保证不重复,却是一个随机的文件名。下载的时候肯定是需要改成上传时的文件名的,这就需要保存之前的文件名,随机的文件名,以及上传的用户名。这里使用MySQL数据库进行保存。
CREATE TABLE users -- 创建用户表 ( username VARCHAR(50) PRIMARY KEY, -- 用户名 preFileName VARCHAR(200) NOT NULL,-- 之前的名字 newFileName VARCHAR(200) NOT NULL -- 之后的名字 );
/* * Generated by MyEclipse Struts * Template path: templates/java/JavaClass.vtl */ package com.pc.web.struts.action; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import com.pc.domain.User; import com.pc.service.UserService; /** * MyEclipse Struts * Creation date: 01-28-2016 * * XDoclet definition: * @struts.action */ public class DownloadFileAction extends Action { /* * Generated Methods */ /** * Method execute * @param mapping * @param form * @param request * @param response * @return ActionForward */ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { // 获取用户名 String username = request.getParameter("user"); // 创建UserService对象 UserService userService = new UserService(); // 获取User对象 User user = userService.getUserByUsername(username); response.setContentType("text/html;charset=utf-8"); // 设置文件头,告诉浏览器下载文件 response.setHeader("Content-Disposition", "attachment; filename=" + user.getPreFileName()); // 下载文件 // 1.获取要下载文件的绝对路径 String filePath = this.getServlet().getServletContext().getRealPath("/file"); String filterFilename = null; // 如果有中文名,要对其进行URL编码 try { filterFilename = URLEncoder.encode(user.getPreFileName(), "utf-8"); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } String fileAllPath = filePath + "\\" + filterFilename; // 2.创建输入输出流 InputStream inputStream = null; OutputStream outputStream = null; // 3.创建Buffer byte[] buffer = new byte[1024]; int len = 0; try { // 4.获取文件流 inputStream = new FileInputStream(fileAllPath); outputStream = response.getOutputStream(); // 5.循环写出 while((len = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, len); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { try { inputStream.close(); outputStream.close(); } catch (Exception e2) { // TODO: handle exception e2.printStackTrace(); } // 垃圾回收机制回收 inputStream = null; outputStream = null; } return mapping.findForward("goback"); } }
PS:中文存入MySQL中一直显示是“???”,花了一两个小时,找了好多办法都没解决,以后有时间,遇到这个问题再想办法解决这个问题。
String filterFilename = null; // 如果有中文名,要对其进行URL编码 try { filterFilename = URLEncoder.encode(user.getPreFileName(), "utf-8"); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } String fileAllPath = filePath + "\\" + filterFilename;
源代码:Struts框架文件上传下载案例