类型转换器
在前面的程序中,表单提交的无论是 int 还是 double 类型的请求参数,用于处理该请求 的处理器方法的形参,
均可直接接收到相应类型的相应数据,而非接收到 String 再手工转换。 那是因为在 SpringMVC 框架中,有默认的类型转换器。
这些默认的类型转换器,可以将 String 类型的数据,自动转换为相应类型的数据
但默认类型转换器并不是可以将用户提交的 String,转换为所有用户需要的类型。此时,就需要自定义类型转换器了。
例如,在 SpringMVC 的默认类型转换器中,没有日期类型的转换器,因为日期的格式太 多。
若要使表单中提交的日期字符串,被处理器方法形参直接接收为 java.util.Date,则需要 自定义类型转换器了。
自定义类型转换器
a)若要定义类型转换器,则需要实现Controller接口。该Controller接口有两个泛型:
第一个为待转换的类型,第二个为目标类型。而该接口的方法convert(),用于完成类型转换
1 // 创建一个 类型转换器,(String 转成 Date)(需要注册) 2 public class MyConverter implements Converter<String, Date> { 3 @Override 4 public Date convert(String dateStr) { 5 //这样只能 使一种 日期格式生效(所以需要判断一下 前台传来的 日期 是哪种格式的,然后创建相对应的 SimpleDateFormat) 6 SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd""); 7 //sdf = getDateFormat(dateStr); 8 try { 9 return sdf.parse(dateStr); 10 } catch (ParseException e) { 11 // TODO Auto-generated catch block 12 e.printStackTrace(); 13 } 14 return null; 15 }
b) 注册类型转换器
1 <!-- 1.注册类型转换器 --> 2 <bean id="dataConverter" class="com.springmvc.converters.MyConverter"/> 3 4 <!-- 2.对于类型转换器,并不是直接使用,而是通过 转换服务Bean 来调用类型转化器 --> 5 <!-- 注册转换服务Bean --> 6 <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 7 <property name="converters" ref="dataConverter"></property> 8 </bean> 9 10 <!-- 3.转换服务Bean 是由处理器适配器直接调用的。采用mvc的注解驱动 注册方式,可以将转换服务直接注入给处理器适配器 --> 11 <mvc:annotation-driven conversion-service="conversionService" />
接收多种日期格式的类型转换器
1 public class MyConverter implements Converter<String, Date> { 2 @Override 3 public Date convert(String dateStr) { 4 //这样只能 使一种 日期格式生效(所以需要判断一下 前台传来的 日期 是哪种格式的,然后创建相对应的 SimpleDateFormat) 5 SimpleDateFormat sdf = new SimpleDateFormat(); 6 sdf = getDateFormat(dateStr); 7 try { 8 return sdf.parse(dateStr); 9 } catch (ParseException e) { 10 // TODO Auto-generated catch block 11 e.printStackTrace(); 12 } 13 return null; 14 } 15 16 //这里使用 判断 日期字符 是否符合格式,是哪种格式 17 private SimpleDateFormat getDateFormat(String dateStr) { 18 SimpleDateFormat sdf = new SimpleDateFormat(); 19 if(Pattern.matches("^\d{4}-\d{2}-\d{2}$", dateStr)) { 20 sdf = new SimpleDateFormat("yyyy-MM-dd"); 21 } else if(Pattern.matches("^\d{4}/\d{2}/\d{2}$", dateStr)) { 22 sdf = new SimpleDateFormat("yyyy/MM/dd"); 23 } else if(Pattern.matches("^\d{4}\d{2}\d{2}$", dateStr)) { 24 sdf = new SimpleDateFormat("yyyyMMdd"); 25 } 26 return sdf; 27 } 28 29 }
类型转换失败后给出提示信息
1
1 else { 2 //如果不满足所有的正则表达式选项 ,则 抛出TypeMismatchException , 3 //为什么要在这里抛出,因为 上面的 sdf.parse(dateStr);已经被try catch 4 throw new TypeMismatchException("",Date.class); 5 }
//因为出现 类型不匹配异常时,是在Controller 的 方法执行之前就出现了,所以 只能用注解的方式来捕获异常 2 @ExceptionHandler(TypeMismatchException.class) 3 public ModelAndView exceptionResolver(HttpServletRequest request,Exception ex) { 4 ModelAndView mv = new ModelAndView(); 5 //根据异常中的 messsage 存储更加友好错误提示信息 6 String errorMessageAge = ""; 7 String errorMessageDate = ""; 8 9 String age = request.getParameter("age"); 10 String birthday = request.getParameter("birthday"); 11 12 //这样写还是有点问题,当年龄和 生日填写一致时,如都填写1,此时ex.message 包含 1,那么会执行errorMessageAge = "年龄填写错误" 13 if(ex.getMessage().contains(age)) { 14 errorMessageAge = "年龄填写错误" ; 15 } else if(ex.getMessage().contains(birthday)) { 16 errorMessageDate = "生日填写错误" ; 17 } 18 19 //回显 表单数据 20 mv.addObject("age", age); 21 mv.addObject("birthday", birthday); 22 23 mv.addObject("errorMessageAge", errorMessageAge); 24 mv.addObject("errorMessageDate", errorMessageDate); 25 //发生异常后,重新返回填写界面 26 mv.setViewName("/index.jsp"); 27 28 return mv; 29 30 31 }