類型轉換器引入
為什么頁面上輸入”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