数组转换器
-
在Struts2.x里面有一个比较换方便的功能,可以将输入的参数自动转换为制定的类型,这种操作就属于转换器的定义.
-
如果现在前台给的是复选框,那么提交之后,必须使用数组接收.
-
定义复选框
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":"
+ request.getServerPort()+path+"/";
String addUrl = basePath +"ConvertAction!add.action";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="<%= addUrl%>" method="post" >
请选择管理部门:<input type="checkbox" name="depts" id="dev-1" value="1"/>开发
<input type="checkbox" name="depts" id="dev-2" value="2"/>管理
<input type="checkbox" name="depts" id="dev-3" value="3"/>财务
</form>
</body>
</html>
-
复选框在进行信息提交的时候往往是以数组的形式传递的,所以这个时候最简单的处理方式就是在Action中编写一个整形数组.
-
定义接收数组Action
package mao.shu.action;
import java.util.Arrays;
import com.opensymphony.xwork2.ActionSupport;
public class Convert extends ActionSupport {
private int[] depts;
public int[] getDepts() {
return depts;
}
public void setDepts(int[] depts) {
this.depts = depts;
}
public void add(){
System.out.println(Arrays.toString(this.depts));
}
}
- struts.xml文件的配置
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="root" namespace="/" extends="struts-default">
<action name="ConvertAction" class="mao.shu.action.ConvertAction">
</action>
</package>
</struts>
- 访问http://localhost:8080/ConvertProject/input.jsp
- 后台提交数据
-
在Struts2中提供的默认内置转换器,除了可以将复选框中数据转换为数组之外,还可以将复选框转换为集合.
-
使用Set集合接收
-
修改ConvertAction程序类,将depts字段类型改为Set集合,并提供setter和getter方法
private Set<Integer> depts;
public Set<Integer> getDepts() {
return depts;
}
public void setDepts(Set<Integer> depts) {
this.depts = depts;
}
public void add(){
System.out.println(this.depts);
}
- 后台输出
-
如果手工进行处理,则需要接收全部参数,而后进行循环转型处理
-
使用List集合接收
private List<Integer> depts;
public List<Integer> getDepts() {
return depts;
}
public void setDepts(List<Integer> depts) {
this.depts = depts;
}
public void add(){
System.out.println(this.depts);
}
- 以上的类型转换的操作都是Struts2自动帮我们完成了.
对象集合转换器
- 定义一个雇员的vo类
package mao.shu.vo;
import java.io.Serializable;
import java.util.Date;
public class Emp implements Serializable{
private Integer empno;
private String ename;
private Integer age;
private Date hiredate;
private Double sal;
//getter和setter方法
}
- 如果此时只是一个对象数组,只需要在Action中保存一个数组即可
package mao.shu.action;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
import mao.shu.vo.Emp;
public class EmpAction extends ActionSupport {
private List<Emp> allEmps;
public List<Emp> getAllEmps() {
return allEmps;
}
public void setAllEmps(List<Emp> allEmps) {
this.allEmps = allEmps;
}
public void show(){
System.out.println(this.allEmps);
}
}
- struts.xml文件中的配置
<action name="EmpAction" class="mao.shu.action.EmpAction">
</action>
- 表单定义
- 此时name值直接使用数组下标的形式来定义
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":"
+ request.getServerPort()+path+"/";
String addUrl = basePath +"EmpAction!show.action";
%>
<form action="<%= addUrl%>" method="post" >
雇员0id:<input type="text" name="allEmps[0].empno" id="allEmps[0].empno" value="1001"><br/>
雇员0Name:<input type="text" name="allEmps[0].ename" id="allEmps[0].ename" value="雇员1"><br/>
雇员0Age:<input type="text" name="allEmps[0].age" id="allEmps[0].age" value="22"><br/>
雇员0Hiredate:<input type="text" name="allEmps[0].hiredate" id="allEmps[0].hiredate" value="1997-10-16"><br/>
雇员0Sal:<input type="text" name="allEmps[0].sal" id="allEmps[0].sal" value="2500.5"><br/>
雇员1id:<input type="text" name="allEmps[1].empno" id="allEmps[1].empno" value="1002"><br/>
雇员1Name:<input type="text" name="allEmps[1].ename" id="allEmps[1].ename" value="雇员2"><br/>
雇员1Age:<input type="text" name="allEmps[1].age" id="allEmps[1].age" value="23"><br/>
雇员1Hiredate:<input type="text" name="allEmps[1].hiredate" id="allEmps[1].hiredate" value="2001-10-16"><br/>
雇员1Sal:<input type="text" name="allEmps[1].sal" id="allEmps[1].sal" value="50050.1"><br/>
雇员2id:<input type="text" name="allEmps[2].empno" id="allEmps[2].empno" value="1003"><br/>
雇员2Name:<input type="text" name="allEmps[2].ename" id="allEmps[2].ename" value="雇员3"><br/>
雇员2Age:<input type="text" name="allEmps[2].age" id="allEmps[2].age" value="24"><br/>
雇员2Hiredate:<input type="text" name="allEmps[2].hiredate" id="allEmps[2].hiredate" value="2020-10-16"><br/>
雇员2Sal:<input type="text" name="allEmps[2].sal" id="allEmps[2].sal" value="5000.5"><br/>
<input type="submit" value="提交"/>
</form>
- 测试http://localhost:8080/ConvertProject/emp_add.jsp
- 提交之后后台输出
- 需要注意的是集合类型不能够使用Set类型,否则将会出现无法赋值等问题
自定义转换器
-
虽然很多时候系统中提供有转换器的处理,但是有些功能是不足的,例如:现在Action中有一个Locale类型的参数,这个时候用户提交的数据就不可能自动进行处理.
-
在Action类之中接收Locale对象
package mao.shu.action;
import java.util.Locale;
import com.opensymphony.xwork2.ActionSupport;
public class LocaleAction extends ActionSupport {
private Locale loc;
public Locale getLoc() {
return loc;
}
public void setLoc(Locale loc) {
this.loc = loc;
}
public void show(){
System.out.println(this.loc);
}
}
- 随后定义一个页面,使用下拉列表实现
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":"
+ request.getServerPort()+path+"/";
String addUrl = basePath +"LocalAction!show.action";
%>
<form action="<%= addUrl%>" method="post" >
<select name="loc" id="loc">
<option value="zh_CN">中文</option>
<option value="en_US">英语</option>
</select>
<input type="submit" value="提交"/>
</form>
- struts.xml文件配置
<action name="LocaleAction" class="mao.shu.action.LocaleAction">
</action>
-
测试提交表单
-
现在发现如果直接进行接收处理,那么就根本不可能将String变为Lovale,也就是说Struts2中提供的转换器不够使用.
-
所以此时就必须自己来实现转换器,那么就需要有一个单独的类来进行转换处理,如果要实现转换器,必须要求继承一个类
-
com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter
-
该类继承自TypeConverter接口,该类帮助我们实现了许多功能,所以只需要实现一下的方法即可
-
需要复写以下的方法
方法 | 作用 |
---|---|
public Object convertValue(Map<String,Object> context, Object value, Class toType) | 子类复写该方法实现指定类型转换 |
- convertValue()方法的参数说明
参数 | 说明 |
---|---|
context | 正在进行转换的上下文 |
value | 要转换的值 |
toType | 要转换的类型 |
- 实现String向locale类的转换.
- 思路:
- 判断要转换的类型是否为Lovale类型
- 取出value中的内容,将其使用"_"拆分出内容
- 使用Locale类中的构造器进行类型转换
package mao.shu.convert;
import java.util.Locale;
import java.util.Map;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
public class ConvertStringToLovale extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
if(toType == Locale.class){
//取出要转换的数据,struts中参数都是以数据的形式保存的,参数的内容为"zh_CN"
String var = ((String[])value)[0];
String[] temp = var.split("_");
return new Locale(temp[0],temp[1]);
}
return null;
}
}
- 这个时候实现了转换器的定义,但是Struts2此时还不认识该转换器,要想是他起作用,那么需要建立一个配置文件
- 配置形式一:配置全局配置,根据目标类型判断,在src下建立一个"xwork-conversion.properties"文件.
- 并且在配置文件之中以"待转换的类型=类型转换器的全类名"的格式配置转换的类型
java.util.Locale=mao.shu.convert.ConvertStringToLovale
- 配置类型二:可能只有某一个Action需要这种转换,可以在Action类所在的包之中建立一个Action类名称-conversion.properties文件
- 以"Action类参数名称=转换器完整类名称"的格式定义
loc=mao.shu.convert.ConvertStringToLovale
- 启动tomcat,访问http://localhost:8080/ConvertProject/locale.jsp
- 后台输出结果
Struts2国际化处理
-
如果现在项目有国际化处理,在JSP之中提供有一个Struts2国际化文字显示标签,但是如果是Action之中要想进行国际化信息的读取,那么可以依靠一个类完成.
-
com.opensymphony.xwork2.util.LocalizedTextUtil类(该类在Struts2的api之中无法找到,不知道为什么,但是可以直接在编译器之中打出来,有知道的朋友帮我解惑一下感谢!)
-
findDefaultText()方法
public void show(){
String info = LocalizedTextUtil.findDefaultText("info",this.loc);
System.out.println(info);
System.out.println(this.loc);
}
- 配置struts.properties文件
struts.custom.i18n.resources=Message
-
而后分别针对于不同的语言定义不同的资源文件,资源文件的名称由在struts.properties文件中定义的"Message"_语言_国家.properties"所组成
-
定义Message_zh_CN.properties文件
info=你好,世界
- 定义Message_en_US.properties文件
info=Hello,World
-
提交之后后台运行
转换器实例
- 在代码之中如果要进行如果要进行数据批量删除处理,可以采用"id|id|id|"的形式进行数据的传输(Tomcat8.5版本左右请求路径中不能够包含"|"竖线的特殊符号,如果要使用这种形式,那么表单提交方式最后是post),那么也可以定义一个转换器自动将字符串转换为Set<集合>.
- 定义一个转换器,将字符串变为Set集合
package mao.shu.convert;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
public class ConvertStringToSet extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
if(toType == Set.class){
String var = ((String[])value)[0];
String[] temp = var.split("-");
Set<Integer> set = new HashSet<Integer>();
for(int x = 0; x < temp.length; x++){
set.add(Integer.parseInt(temp[x]));
}
return set;
}
return null;
}
}
-
这样的转换器只适合于做局部配置
-
定义配置文件
ids=mao.shu.convert.ConvertStringToSet
- Action程序类,如果执行了remove()方法能够能够成功将ids转换为Set集合的形式,表示转换器成功.
public class LocaleAction extends ActionSupport {
private Set<Integer>ids;
public Set<Integer> getIds() {
return ids;
}
public void setIds(Set<Integer> ids) {
this.ids = ids;
}
public void remove(){
System.out.println(this.ids);
}
}
- 测试访问数据
http://localhost:8080/ConvertProject/LocaleAction!remove.action?ids=1-2-3-4-5-6
- 后台输出结果
- 思考:到底需不需要使用转换器?
- 转换器的操作如果手工实现,可可以实现,之所以会提供转换器的概念,主要是受到了AOP思想影响,AOP观点指的是程序只完成核心功能,所有的辅助功能应该交由处理类完成.