struts框架几个模块:从源码分析struts框架转换器
struts框架几个模块:从源码分析struts框架转换器<form action="typeconvert.do" method="post">• jsp 页面中提交请求:• 为什么很少使用 sql 类型的日期:– sql 日期格式是固定的,必须是 [ 年-月-日 ],util 日期格式不是固定的转换实例
类型转换器
• 所有从表单中提交到后台的数据都是 String 类型
• struts 提供了相应的转换器,将表单中收集来的 String 类型自动转换为其他类型
• struts 不提供 util 日期类型的转换器
• 为什么很少使用 sql 类型的日期:
– sql 日期格式是固定的,必须是 [ 年-月-日 ],util 日期格式不是固定的
转换实例
• jsp 页面中提交请求:
<form action="typeconvert.do" method="post">
<input type="text" name="intValue"><br>
<input type="text" name="doubleValue"><br>
<input type="text" name="BooleanValue"><br>
<input type="text" name="sqlDate"><br>
<input type="text" name="utilDate"><br>
<input type="submit" value="提交">
</form>
• Tomcat 创建 request 内置对象存放请求后提交给 struts:
请求字符串:/typeconvert.do?intValue="3"&doubleValue="3.3"&booleanValue="true"&sqlDate="2018 -8-23"&utilDate="2018-8-23"
<form-bean name="typeconvertForm" type="com.bjsxt.struts.TypeConvertActionForm"/> <action path="/typeconvert" type="com.bjsxt.struts.TypeConvertTestAction" name="typeconvertForm" scope="request" > <forward name="success" path="/typeconvert_success.jsp"/> </action>
• 创建表单Bean 对象:
private int intValue;
private double doubleValue; private boolean booleanValue; private java.sql.Date sqlDate; private java.util.Date utilDate;
• 收集数据:收集数据到 ActionForm
– 最终调用:setProperty( bean name value); // 调用 setProperty 方法,相当于 bean.setName(value); 将数据封装到 ActionForm 里
§ 先看表单Bean 中与参数名同名的属性的属性类型是否为 String 类型,如果表单Bean 中属性的类型不是 String 类型,struts 会调用一个相应类型的转换器进行类型转换后再将数据封装进表单Bean 中
– 整型:name = "intValue",value = "3"
§ 通过参数名 intValue 找到表单Bean 中的属性名,发现表单Bean 中的类型为整型
§ struts 到 ConvertUtils 类中找一个静态的 Map 集合 converters
§ 在 converters 集合中找整型转换器进行类型转换
§ 过程源码分析:
□ Tomcat 一启动会创建 Actionservlet 中央控制器对象,创建该对象时会调用 init() 初始化方法
□ init() 方法初始化时调用 initOther() 初始化方法 -- 在 initOther() 初始化方法中将多种默认类型转换器注册进了 ConvertUtils 中
---------------------------------- initOther()
ConvertUtils.deregister(); ConvertUtils.register(new BigDecimalConverter(null) BigDecimal.class); ConvertUtils.register(new BigIntegerConverter(null) BigInteger.class); ConvertUtils.register(new BooleanConverter(null) Boolean.class); ConvertUtils.register(new ByteConverter(null) Byte.class); ConvertUtils.register(new CharacterConverter(null) Character.class); ConvertUtils.register(new DoubleConverter(null) Double.class); ConvertUtils.register(new FloatConverter(null) Float.class); ConvertUtils.register(new IntegerConverter(null) Integer.class); ConvertUtils.register(new LongConverter(null) Long.class); ConvertUtils.register(new ShortConverter(null) Short.class);
® ConvertUtils 类中创建了一个静态的 Map 集合 converters 用来存放这些类型转换器
---------------------------------- ConvertUtils.java
private static FastHashMap converters = new FastHashMap(); // 静态的,通过类调用,只要有了ConvertUtils 类就能调用public static void register(Converter converter Class clazz) { converters.put(clazz converter); }
整型类型转换器:转换器类一定要实现 Converter 接口 -- 实现 convert() 方法
---------------------------------- IntegerConverter.java public class IntegerConverter implements Converter {
public Object convert( Class type Object value) { // 用 Object 来接收表单中的 String 类型
return (new Integer( value.toString())); // 将 Object 类型的参数转换为字符串类型的3,再将其转换为整型返回
}
– 布尔类型:name = "booleanValue",value = "true"
§ 通过参数名 booleanValue 找到表单Bean 中的属性名,发现表单Bean 中的类型为布尔型
§ struts 到 ConvertUtils 类中找一个静态的 Map 集合 converters
§ 在 converters 集合中找布尔型转换器进行类型转换
---------------------------------- BooleanConverter.java String stringValue = value.toString();
if (stringValue.equalsIgnoreCase("yes") || stringValue.equalsIgnoreCase("y") || stringValue.equalsIgnoreCase("true") || stringValue.equalsIgnoreCase("on") || stringValue.equalsIgnoreCase("1")) { return (Boolean.TRUE); } else if (stringValue.equalsIgnoreCase("no") || stringValue.equalsIgnoreCase("n") || stringValue.equalsIgnoreCase("false") || stringValue.equalsIgnoreCase("off") || stringValue.equalsIgnoreCase("0")) { return (Boolean.FALSE); }
创建 util.date 转换器
• 类名:UtilDateConverter
• 实现 Converter 接口 -- 实现 convert 方法:
public class UtilDateConverter implements Converter { public Object convert(Class type Object value) { if (value == null) { return value; } if (value instanceof Date) { return value; } Date d = null; if (value instanceof String) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 将此种格式的字符串转换为 Date 类型try { d = sdf.parse((String)value); } catch (ParseException e) { e.printStackTrace(); } } return d; } }
• 将 转 换 器 注 册 进 静 态 的 集 合 中 的 注 册 代 码 : ConvertUtils.register(new UtilDateConverter(null) Date.class);
• 类型转换器需要在 Tomcat 一启动就被注册到 ConvertUtils 类中,有以下七种方案:
– servlet 中的 init() 方法 -- 不需要 servlet-mapping,不处理用户请求,只是执行一段代码
public class UtilDateConverterInitWithServlet extends HttpServlet { public void init() throws ServletException {
ConvertUtils.register(new UtilDateConverter() Date.class); }
}
§ 配置 servlet:
<servlet> <servlet-name>UtilDateConverterInitWithServlet</servlet-name> <servlet-class>com.bjsxt.struts.UtilDateConverterInitWithServlet</servlet-class> <load-on-startup>3</load-on-startup> // 一定要有此标签,让 Tomcat 一启动就创建 </servlet>
– 插件 -- 写一个插件类,配置在 struts-config.xml 的 <plug-in> 标签中public class UtilDateConverterInitWithPlugin implements PlugIn {
public void destroy() { } public void init(ActionServlet servlet ModuleConfig config) throws ServletException { ConvertUtils.register(new UtilDateConverter() Date.class); } }
§ 配置插件类:
<plug-in className="com.bjsxt.struts.UtilDateConverterInitWithPlugin"/>
–
ActionServlet -- 巧用继承,使用自己的中央控制器,即复写 ActionServlet -- 复写 init() 初始化方法
public class MyActionServlet extends ActionServlet { public void init() throws ServletException { super.initOther(); ConvertUtils.register(new UtilDateConverter() Date.class); } }
§ Tomcat 一启动,创建自己复写的中央控制器对象,执行复写的 init() 方法
§ 父类的 init() 方法中有三个具体的初始化方法:
□ initInternal();
□ initOther();
□ initServlet();
§ 如果自己没有 initInternal() / initServlet() 方法,就会执行父类的,自己写了 initOther() 方法,就执行自己的
§ 先调用父类的 initOther() 方法注册完默认的转换器,再将自己写的转换器注册进集合中
§ 继续调用父类的其他方法
§ 配置 web.xml:
<servlet-name>action</servlet-name>
<servlet-class>com.struts.MyActionServlet</servlet-class>
–
–
– 在表单Bean 中将 utilDate 定义为 String 类型,使数据可以正常被自动收集进表单Bean 中
– 在表单Bean 的 getUtilDate() 方法中创建 SimpleDateFormat() 将字符串转换为 utilDate 类型
– 在表单Bean 中将 utilDate 定义为 String 类型,使数据可以正常被自动收集进表单Bean 中
– 在转向到 jsp 页面后,将字符串转换为 utilDate 类型
§ 写一个自定义函数,拿到参数转换之后返回给 jsp 页面输出