Java进阶学习第十六天(Struts框架:配置、数据处理、自动封装、日期类型转换、文件上传)

一、Struts2配置

1、Struts2的Action开发的几种方式
① 方式1:继承ActionSupport(一般使用方法)
public class UserAction extends ActionSupport {}
如果用Struts的数据校验功能,必须继承此类!
② 方式2:实现Action接口
public class UserAction implements Action {}
③ 方式3:不继承任何类,也不实现任何接口
public class UserAction{}

2、Struts访问通配符使用
在Struts的配置信息struts.xml中可以用*与{1}优化配置

<!-- 使用通配符优化上面的步骤 -->
<!-- http://localhost:8080/struts02/user_login -->
<action name="user_*" class="cn.itcast.a_config.UserAction" method="{1}">
<result name="{1}">/{1}.jsp</result>			
</action>

3、Struts中路径匹配原则
① 访问路径 = 名称空间+action的name

<package name="config" namespace="/user" extends="struts-default" abstract="false">
	<action name="user_*" class="cn.itcast.a_config.UserAction" method="{1}">
		<result name="{1}">/{1}.jsp</result>			
	</action>
</package>

访问路径:http://localhost:8080/struts02/user/user_login(可以)
访问路径:http://localhost:8080/struts02/a/b/user_login(可以)
访问路径:http://localhost:8080/a/b/struts02/user_login(不可以)
② 过程:Tomcat访问
Localhost:找到访问哪一台机器
8080:找到tomcat
struts02:找到项目名称
/user/a/b:先看看有没有这个名称空间,没找到继续向下,找到就返回
/user/a:先看看有没有这个名称空间,没找到继续向下,找到就返回
/user:默认的名称空间,还没找到就报错,找到就返回

4、Struts常量
① Struts默认访问后缀:
◆ Struts1:.do
◆ Struts2:
.action
② 如何修改默认访问后缀?
Struts2的*.action在哪里定义的
struts2-core-2.3.4.1-sources.jar > org.apache.struts2 > default.properties
其中,修改struts2.action.extension=action

总配置文件(struts.xml):

<struts>
	<!-- 一、全局配置 -->
	<!-- 0. 请求数据编码 -->
	<constant name="struts.i18n.encoding" value="UTF-8"/>
	<!-- 1. 修改Struts默认的访问后缀action或do或不写 -->
	<constant name="struts.action.extension" value="action,do,"></constant>
	<!-- 2. 修改xml自动重新加载 -->
	<constant name="struts.configuration.xml.reload" value="true"/>
	<!-- 3. 开启动态方法调用 (默认不开启)-->
	<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
	<!-- 4. 修改上传文件的最大大小为30M -->
	<constant name="struts.multipart.maxSize" value="31457280"/>

	<!-- 二、总配置文件:引入其他所有配置文件 -->
	<include file="constant.xml"></include>
	<include file="cn/itcast/a_config/struts.xml"></include>
	<include file="cn/itcast/b_config2/config.xml"></include>
	<include file="cn/itcast/c_data/data.xml"></include>
	<include file="cn/itcast/d_type/type.xml"></include>
	<include file="cn/itcast/e_fileupload/upload.xml"></include>	
</struts>

单个配置文件(congig.xml):

<struts>
	<package name="config2" namespace="/" extends="struts-default">
	    <!-- 动态方法调用语法: http://locahost:8080/struts02/user!login 
		<action name="user" class="cn.itcast.b_config2.UserAction">
			<result name="success">/index.jsp</result>			
		</action>
		-->	
		
		<!-- 配置全局跳转视图 -->
		<global-results>
			<result name="success">/index.jsp</result>
		</global-results>	
		
		<!-- 通配符: http://locahost:8080/struts02/user_login -->
		<action name="user_*" class="cn.itcast.b_config2.UserAction" method="{1}">
		</action>
		<!-- 
		
		<action name="test" class="cn.itcast.b_config2.TestAction" method="execute">
			返回结果标记success对应的页面再当前action中没有配置,
			所以会去找全局配置有是否有success标记对应的页面
		</action>
		--> 
		
		<!-- 配置各项默认值 -->
		<!-- 
		 	 name  只配置了访问路径名称
		 	 class 默认执行的action在struts-default有配置
		 	 		<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
		 	 method  默认为execute
		 	 默认的方法execute返回值为success,对应的页面去全局视图找。 
		 -->
		<action name="test"></action>

		<!-- 什么情况不配置class? 即处理的aciton -->
		<!-- 答案: 当只是需要跳转到WEB-INF下资源的时候 -->
		<action name="test2">
		 	<result name="success">/WEB-INF/index.jsp</result>
		</action>	
	</package>	
</struts>

二、Struts数据处理

public class DataAction extends ActionSupport{
	@Override
	public String execute() throws Exception {
		// 1. 请求数据封装; 
		// 2. 调用Service处理业务逻辑,拿到结果数据
		// 3. 数据保存到域中
		
		// Struts中对数据操作,方式1: 直接拿到ServletApi, 执行操作
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpSession session = request.getSession();
		ServletContext application = ServletActionContext.getServletContext();
		// 操作
		request.setAttribute("request_data", "request_data1");
		session.setAttribute("session_data", "session_data1");
		application.setAttribute("application_data", "application_data1");
		
		// Struts中对数据操作,方式2: 通过ActionContext类 
		// 【推荐:解耦的方式实现对数据的操作】
		ActionContext ac = ActionContext.getContext();
		// 得到Struts对HttpServletRequest对象进行了封装,封装为一个map
		// 拿到表示request对象的map
	 	Map<String,Object> request =  ac.getContextMap(); 
	 	// 拿到表示session对象的map
	 	Map<String, Object> session = ac.getSession();
	 	// 拿到表示servletContext对象的map
	 	Map<String, Object> application = ac.getApplication();
	 	
	 	// 数据
	 	request.put("request_data", "request_data1_actionContext");
		session.put("session_data", "session_data1_actionContext");
		application.put("application_data", "application_data1_actionContext");
		
		return SUCCESS;
	}
}
/**
 * Struts中对数据操作,方式3: 实现接口的方法
 */
public class DataAction extends ActionSupport implements RequestAware, SessionAware, ApplicationAware{
	private Map<String, Object> request;
	private Map<String, Object> session;
	private Map<String, Object> application;
	
	// struts运行时候,会把代表request的map对象注入
	@Override
	public void setRequest(Map<String, Object> request) {
		this.request = request;
	}
	
	// 注入session
	@Override
	public void setSession(Map<String, Object> session) {
		this.session = session;
	}
	
	// 注入application
	@Override
	public void setApplication(Map<String, Object> application) {
		this.application = application;
	}

	@Override
	public String execute() throws Exception {
	 	// 数据
	 	request.put("request_data", "request_data1_actionAware");
		session.put("session_data", "session_data1_actionAware");
		application.put("application_data", "application_data1_actionAware");
			
		return SUCCESS;
	}
}

三、Struts自动封装

实现原理:参数拦截器
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.Parameterslnterceptor">

public class UserAction {
	 // 对象类型,一定给get方法
	private User user; 
	public void setUser(User user) {
		this.user = user;
	}
	public User getUser() {
		return user;
	}

	// 处理注册请求
	public String register() {
		System.out.println(user.getName());
		System.out.println(user.getPwd());
		System.out.println(user.getAge());
		System.out.println(user.getBirth());
		return "success";
	}
}

四、Struts日期类型转换

struts中jsp提交的数据,struts会自动转换为action中属性的类型,对于基本数据类型和日期类型会自动转换,但是日期类型支持yyy-MM-dd格式,如果是其他格式需要自定义类型转换器
1、局部类型转换器
① 写类型转换器

public class MyConverter extends StrutsTypeConverter {

	// 新需求: 要求项目中要支持的格式,如: yyyy-MM-dd/yyyyMMdd/yyyy年MM月dd日
	// 先定义项目中支持的转换的格式
	DateFormat[] df = { new SimpleDateFormat("yyyy-MM-dd"),
			new SimpleDateFormat("yyyyMMdd"),
			new SimpleDateFormat("yyyy年MM月dd日") };

	/**
	 * 把String转换为指定的类型 【String To Date】
	 * @param context 当前上下文环境
	 * @param values jsp表单提交的字符串的值
	 * @param toClass 要转换为的目标类型
	 */
	@Override
	public Object convertFromString(Map context, String[] values, Class toClass) {
		// 判断: 内容不能为空
		if (values == null || values.length == 0) {
			return null;
		}
		// 判断类型必须为Date
		if (Date.class != toClass) {
			return null;
		}
		// 迭代:转换失败继续下一个格式的转换; 转换成功就直接返回
		for (int i=0; i<df.length; i++) {
			try {
				return df[i].parse(values[0]);
			} catch (ParseException e) {
				continue;
			}
		}
		return null;
	}
	@Override
	public String convertToString(Map context, Object o) {
		return null;
	}
}

② 配置转换器类(告诉struts应用自己的类型转换器)
在同包的action目录下新建一个properties文件(文件命名规则:ActionClassName-conversion.properties
③ 内容
user.birth = 转换器类全路径(cn.itcast.c.MyConverter)

2、全局类型转换器
配置:src/Xwork-conversion.properties
内容:Java.util.Data = 转换器类全路径(cn.itcast.c.MyConverter)

五、Struts文件上传

文件上传拦截器帮助我们完成文件上传的功能
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadlnterceptor">

<body>
  	<form action="${pageContext.request.contextPath }/fileUploadAction" method="post" enctype="multipart/form-data">
  		用户名:<input type="text" name="userName"><br/>
  		文件:<input type="file" name="file1"><br/>
  		<input type="submit" value="上传">
  	</form>
</body>
public class FileUpload extends ActionSupport {

	// 对应表单:<input type="file" name="file1">
	private File file1; 
	// 文件名
	private String file1FileName;
	// 文件的类型(MIME)
	private String file1ContentType;
	public void setFile1(File file1) {
		this.file1 = file1;
	}
	public void setFile1FileName(String file1FileName) {
		this.file1FileName = file1FileName;
	}
	public void setFile1ContentType(String file1ContentType) {
		this.file1ContentType = file1ContentType;
	}
		
	@Override
	public String execute() throws Exception {
		/******拿到上传的文件,进行处理******/
		// 把文件上传到upload目录
		
		// 获取上传的目录路径
		String path = ServletActionContext.getServletContext().getRealPath("/upload");
		// 创建目标文件对象
		File destFile = new File(path,file1FileName);
		// 把上传的文件,拷贝到目标文件中
		FileUtils.copyFile(file1, destFile);
		
		return SUCCESS;
	}
}

1、文件大小限制
struts默认支持的文件上传最大是2M,通过常量修改

<!-- 4. 修改上传文件的最大大小为30M -->
<constant name="struts.multipart.maxSize" value="31457280"/>

2、限制文件上传的类型
需求:只运行txt/jpg后缀的文件
拦截器:注入参数从而限制文件上传类型

<struts>
	<package name="upload_" extends="struts-default">
		<!-- 注意: action 的名称不能用关键字"fileUpload" -->
		<action name="fileUploadAction" class="cn.itcast.e_fileupload.FileUpload">
			<!-- 限制运行上传的文件的类型 -->
			<interceptor-ref name="defaultStack">
				<!-- 限制运行的文件的扩展名 -->
				<param name="fileUpload.allowedExtensions">txt,jpg,jar</param>
				<!-- 限制运行的类型【与上面同时使用,取交集】
				<param name="fileUpload.allowedTypes">text/plain</param>
				-->
			</interceptor-ref>
		</action>
	</package>	
</struts>

3、错误提示
当文件上传出现错误的时候,struts内部会返回input视图,所以我们就需要在struts.xml中配置input视图对应的错误页面!

<struts>
	<package name="upload_" extends="struts-default">
		<!-- 注意: action 的名称不能用关键字"fileUpload" -->
		<action name="fileUploadAction" class="cn.itcast.e_fileupload.FileUpload">
			<!-- 配置错误视图 -->
			<result name="input">/e/error.jsp</result>
		</action>
	</package>	
</struts>

4、文件下载
文件下载两种方式:
① 通过response对象向浏览器中写入字节流数据,设置相应下载头
② struts方式

<struts>
	<package name="upload_" extends="struts-default">
		<action name="down_*" class="cn.itcast.e_fileupload.DownAction" method="{1}">
			<!-- 列表展示 -->
			<result name="list">/e/list.jsp</result>
			<!-- 下载操作 -->
			<result name="download" type="stream">
			   <!-- 允许下载的文件的类型:指定为所有的二进制文件类型 -->
			   <param name="contentType">application/octet-stream</param>
			   <!-- 对应的是Action中属性:返回流的属性【其实就是getAttrInputStream()】 -->
			   <param name="inputName">attrInputStream</param>
			   <!-- 下载头,包括:浏览器显示的文件名 -->
			   <param name="contentDisposition">attachment;filename=${downFileName}</param>
			   <!-- 缓冲区大小设置 -->
			   <param name="bufferSize">1024</param>
			</result>
		</action>
	</package>	
</struts>

/**
 * 文件下载
 * 1. 显示所有要下载文件的列表
 * 2. 文件下载
 */
public class DownAction extends ActionSupport {
	/*************1. 显示所有要下载文件的列表*********************/
	public String list() throws Exception {	
		//得到upload目录路径
		String path = ServletActionContext.getServletContext().getRealPath("/upload");
		// 目录对象
		File file  = new File(path);
		// 得到所有要下载的文件的文件名
		String[] fileNames =  file.list();
		// 保存
		ActionContext ac = ActionContext.getContext();
		// 得到代表request的map (第二种方式)
		Map<String,Object> request= (Map<String, Object>) ac.get("request");
		request.put("fileNames", fileNames);
		return "list";
	}
	/*************2. 文件下载*********************/
	// 1. 获取要下载的文件的文件名
	private String fileName;
	public void setFileName(String fileName) {
		// 处理传入的参数中问题(get提交)
		try {
			fileName = new String(fileName.getBytes("ISO8859-1"),"UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
		// 把处理好的文件名,赋值
		this.fileName = fileName;
	}
	
	//2. 下载提交的业务方法 (在struts.xml中配置返回stream)
	public String down() throws Exception {
		return "download";
	}
	
	// 3. 返回文件流的方法
	public InputStream getAttrInputStream(){
		return ServletActionContext.getServletContext().getResourceAsStream("/upload/" + fileName);
	}
	
	// 4. 下载显示的文件名(浏览器显示的文件名)
	public String getDownFileName() {
		// 需要进行中文编码
		try {
			fileName = URLEncoder.encode(fileName, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
		return fileName;
	}
}

<html>
  <head>
    <base href="<%=basePath%>">
    <title>下载列表</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
  </head>
  <body>
  	<table border="1" align="center">
  		<tr>
  			<td>编号</td>
  			<td>文件名</td>
  			<td>操作</td>
  		</tr>
  		<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
  		<c:forEach var="fileName" items="${fileNames}" varStatus="vs">
  			<tr>
  				<td>${vs.count }</td>
  				<td>${fileName }</td>
  				<td>
  					<!-- 构建一个url -->
  					<c:url var="url" value="down_down">
  						<c:param name="fileName" value="${fileName}"></c:param>
  					</c:url>
  					<a href="${url }">下载</a>
  				</td>
  			</tr>
  		</c:forEach>
  	</table>
  </body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值