类型转换器引入

为什么页面上输入”12”,可以赋值给Handler方法对应的参数?
这是因为框架内部帮我们做了类型转换的工作。将String转换成int
 但默认类型转换器并不是可以将用户提交的String,转换为用户需要的所有类型。此时 ,就需要自定义类型转换器了

案例:自定义日期类型转换器

要求日期格式为:yyyy/MM/dd

spring 工具类有没有现成的方法将String 转为map 或者Properties_类型转换

---单日期(在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

spring 工具类有没有现成的方法将String 转为map 或者Properties_异常处理_02

spring 工具类有没有现成的方法将String 转为map 或者Properties_java_03

如果换成yyyy-MM-dd格式的

spring 工具类有没有现成的方法将String 转为map 或者Properties_类型转换_04

在applicationContext.xml中

spring 工具类有没有现成的方法将String 转为map 或者Properties_测试_05

 

spring 工具类有没有现成的方法将String 转为map 或者Properties_测试_06

 多种日期格式
上述页面和applicationContext.xml配置的都一样

spring 工具类有没有现成的方法将String 转为map 或者Properties_类型转换_07

 

spring 工具类有没有现成的方法将String 转为map 或者Properties_类型转换_08

 

 

 MyController.java中也是一样

spring 工具类有没有现成的方法将String 转为map 或者Properties_测试_09

只需在在类型转换器中改一下

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;
    }
    
}

效果:

spring 工具类有没有现成的方法将String 转为map 或者Properties_异常处理_10

表单数据填错后返回表单页面

当数据类型转换发生异常后,需要返回到表单页面,让用户重写填写,但实际情况是发生类型转化异常,系统会自动跳转到400页面。所以,若要在发生类型转换异常后,跳转到指定页面,在需要将异常捕获,然后通过异常处理器跳转到指定页面。
   需要注意的是:SimpleMappingExceptionResolver捕获的是处理器方法在执行过程中发生的异常,而类型转换异常发生在处理器方法执行之前。所以使用SimpleMappingExceptionResolver将无法捕获到类型转换异常。但注解式异常处理是可以获取到类型转换异常的。所以这里需要使用注解式异常处理。
    当请求参数的值与接收该参数的处理器方法形参类型不匹配时,会抛出类型匹配有误异常:TypeMismatchException.

当我们在前台输入如下信息 ,年龄为string不能装配成后台的int类型转向400错误页面,

面对这种情况我们更想看到的是回到初始页面

我们就采用异常处理机制,其实再出现类型转换异常时,请求就不会再进入处理器方法,而是被我们自定的的异常处理方法所捕获

在处理器类中加入异常处理方法,完成重定向的功能

在MyController.java中

spring 工具类有没有现成的方法将String 转为map 或者Properties_类型转换_11

关于表单内容填写错误转向表单本身原理

spring 工具类有没有现成的方法将String 转为map 或者Properties_类型转换_12

 

数据回显

在异常处理器中,通过request.getParameter()将用户输入的表单原始数据获取到,直接放入到ModelAndView中的Model中,然后从要转向的页面中就可以直接通过EL表达式读取出来,也就实现了数据回显

其它代码都与上述一样我们会发现一个规律,利于我们进行特定数据异常的定位 所以下面我们使用ex.getMessage().contains(birthday)

只需在MyController.java

我们会发现一个规律,利于我们进行特定数据异常的定位 所以下面我们使用ex.getMessage().contains(birthday)

 

spring 工具类有没有现成的方法将String 转为map 或者Properties_类型转换_13

index.jsp

spring 工具类有没有现成的方法将String 转为map 或者Properties_测试_14

spring 工具类有没有现成的方法将String 转为map 或者Properties_java_15