Struts使用细节

Struts使用细节

为什么使用DispatchAction(分派action)

    如果每个请求都对应一个action,这样就会造成action过多,使得程序显得比较臃肿。这样就可以通过使用DispatchAction,其原理是将一类请求写到一个action中。

PS:其实这种思想和以前学Servlet时,处理一类事物的控制器差不多。原文链接:用户管理系统

 

DispatchAction原理图

Struts使用细节_第1张图片

PS:在uri中,跳转到分派action,如果execute方法没被删除,每次都是调用它来处理。所以一定要将它删除。

 

Struts全局跳转

全局跳转页面配置基本语法

<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中配置成如上形式。动态表单比静态表单要方便很多,而且也将硬编码做成了配置形式,扩展性更强了,所以建议使用动态表单。


文件的上传与下载

文件上传

Struts使用细节_第2张图片


/*
 * 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");
	}
}

细节问题

1、上传文件中文乱码问题

思路:使用过滤器解决

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

2、上传同名文件覆盖问题

思路一:在文件名称里加入毫秒级时间信息。

思路二:扫描该文件夹里的所有文件,如果有相同文件,就在文件名里加诸如“第几个”之类的前缀或者后缀。

思路三:利用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数据库进行保存。

 

SQL语句

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框架文件上传下载案例


你可能感兴趣的:(Struts使用细节)