Spring MVC类型转换器
类型转换器引入
为什么页面上输入”12”,可以赋值给Handler方法对应的参数?
这是因为框架内部帮我们做了类型转换的工作。将String转换成int
但默认类型转换器并不是可以将用户提交的String,转换为用户需要的所有类型。此时 ,就需要自定义类型转换器了
案例:自定义日期类型转换器
要求日期格式为:yyyy/MM/dd
---单日期(在Controller定义了一个方法,主要是对参数有要求)
MyCOntroller.java
package cn.controller; import java.util.Date; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * * @author 景佩佩 * */ @Controller public class MyController{ //处理器方法 @RequestMapping(value="/first.do") public String doFirst(Date birthday,int age) { System.out.println(birthday+"==========="); System.out.println(age+"==========="); return "/welcome.jsp"; } }
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <style type="text/css"> form{ background-color:pink; width:500px; } </style> <title></title> </head> <body> <form action="${pageContext.request.contextPath }/first.do" method="post"> <h1>自定义类型转换器</h1> 出生日期:<input name="birthday"/><br/><br/> 年龄:<input name="age"/><br/><br/> <input type="submit" value="注册"/> </form> </body> </html>
welcome.jsp(欢迎页面)
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>欢迎页面</title> </head> <body> <h1>欢迎访问${uname }${param.uage }</h1> </body> </html>
定义自己的类型转换器 继承一个父接口 Converter<S, T>
package cn.converters; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.core.convert.converter.Converter; /** * * @author 景佩佩 * *S:Source 源类型 *T:Target 目标类型 */ public class MyDateConverter implements Converter<String, Date> { public Date convert(String source) { SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); return null; } }
applicationContext.xml
如果换成yyyy-MM-dd格式的
在applicationContext.xml中
多种日期格式
上述页面和applicationContext.xml配置的都一样
MyController.java中也是一样
只需在在类型转换器中改一下
package cn.converters; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.regex.Pattern; import org.springframework.beans.TypeMismatchException; import org.springframework.core.convert.converter.Converter; /** * * @author 景佩佩 * *S:Source 源类型 *T:Target 目标类型 */ public class MyDateConverter implements Converter<String, Date> { public Date convert(String source) { //SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat sdf=getDateFormat(source); try { return sdf.parse(source); } catch (ParseException e) { //e.printStackTrace(); } return null; } private SimpleDateFormat getDateFormat(String source){ //一个字符串和一个特定形式能否匹配,正则 SimpleDateFormat sdf=new SimpleDateFormat(); if (Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", source)) { sdf=new SimpleDateFormat("yyyy-MM-dd"); }else if (Pattern.matches("^\\d{4}/\\d{2}/\\d{2}$", source)) { sdf=new SimpleDateFormat("yyyy/MM/dd"); }else if (Pattern.matches("^\\d{4}\\d{2}\\d{2}$", source)) { sdf=new SimpleDateFormat("yyyyMMdd"); } return sdf; } }
效果:
表单数据填错后返回表单页面
当数据类型转换发生异常后,需要返回到表单页面,让用户重写填写,但实际情况是发生类型转化异常,系统会自动跳转到400页面。所以,若要在发生类型转换异常后,跳转到指定页面,在需要将异常捕获,然后通过异常处理器跳转到指定页面。
需要注意的是:SimpleMappingExceptionResolver捕获的是处理器方法在执行过程中发生的异常,而类型转换异常发生在处理器方法执行之前。所以使用SimpleMappingExceptionResolver将无法捕获到类型转换异常。但注解式异常处理是可以获取到类型转换异常的。所以这里需要使用注解式异常处理。
当请求参数的值与接收该参数的处理器方法形参类型不匹配时,会抛出类型匹配有误异常:TypeMismatchException.
当我们在前台输入如下信息 ,年龄为string不能装配成后台的int类型转向400错误页面,
面对这种情况我们更想看到的是回到初始页面
我们就采用异常处理机制,其实再出现类型转换异常时,请求就不会再进入处理器方法,而是被我们自定的的异常处理方法所捕获
在处理器类中加入异常处理方法,完成重定向的功能
在MyController.java中
关于表单内容填写错误转向表单本身原理
数据回显
在异常处理器中,通过request.getParameter()将用户输入的表单原始数据获取到,直接放入到ModelAndView中的Model中,然后从要转向的页面中就可以直接通过EL表达式读取出来,也就实现了数据回显
其它代码都与上述一样我们会发现一个规律,利于我们进行特定数据异常的定位 所以下面我们使用ex.getMessage().contains(birthday)
只需在MyController.java
我们会发现一个规律,利于我们进行特定数据异常的定位 所以下面我们使用ex.getMessage().contains(birthday)
index.jsp