掌握SpringMVC中@InitBinder的實(shí)際應(yīng)用
1: 注冊(cè)屬性編輯器
我們?cè)诮邮諈?shù)的時(shí)候,對(duì)于基礎(chǔ)的數(shù)據(jù)類型,比如接收string,int等類型,springmvc是可以直接處理的,但是對(duì)于其他復(fù)雜的對(duì)象類型,有時(shí)候是無法處理的,這時(shí)候就需要屬性編輯器來進(jìn)行處理(源數(shù)據(jù)為string),過程一般就是 String->屬性編輯器->目標(biāo)類型 。spring為我們提供了一些默認(rèn)的屬性編輯器,如 org.springframework.beans.propertyeditors.CustomDateEditor 就是其中一個(gè),我們也可以通過繼承 java.beans.PropertyEditorSuppotr 來根據(jù)具體的業(yè)務(wù)來定義自己的屬性編輯器。
1.1: 使用系統(tǒng)默認(rèn)提供的屬性編輯器
- 定義controller并使用@InitBinder注冊(cè)屬性編輯器
這里注冊(cè)的屬性編輯器為 org.springframework.beans.propertybeans.CustomDateEditor ,作用是根據(jù)提供的 java.text.SimpleDateFormat 將輸入的字符串?dāng)?shù)據(jù)轉(zhuǎn)換為 java.util.Date 類型的數(shù)據(jù),核心源碼如下:
org.springframework.beans.propertyeditors.CustomDateEditor#setAsText public void setAsText(@Nullable String text) throws IllegalArgumentException { ... else { try { // 使用用戶提供的java.text.SimpeDateFormat來將目標(biāo)字符串格式化為java.util.Date類型,并通過SetValue方法設(shè)置最終值 setValue(this.dateFormat.parse(text)); } ... } }
接下來定義類:
@RequestMapping("/myInitBinder0954") @Controller public class MyInitBinderController { /* 注冊(cè)將字符串轉(zhuǎn)換為Date的屬性編輯器,該編輯器僅僅對(duì)當(dāng)前controller有效 */ @InitBinder public void initBinderXXX(WebDataBinder binder) { DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); CustomDateEditor dateEditor = new CustomDateEditor(df, true); binder.registerCustomEditor(Date.class, dateEditor); } // http://localhost:8080/myInitBinder0954/test?date=2020-09-03%2010:17:17會(huì)使用在 // dongshi.controller.initbinder.MyInitBinderController.initBinderXXX注冊(cè)的屬性編輯器轉(zhuǎn)換為, // Date類型的 @RequestMapping(value = "/test", method = RequestMethod.GET) @ResponseBody public String testFormatData(Date date) { Map<String, Object> map = new HashMap<>(); map.put("date", date); return map.toString(); } }
訪問測(cè)試
看到返回了Date的toString的結(jié)果,就是說明成功了。
1.2: 使用自定義的屬性編輯器
假設(shè)我們的需求是這樣的,調(diào)用方傳過來的值是一個(gè) _ 豎線分割的字符串,但是處理的過程使用的是通過 _ 號(hào)分割得到的一個(gè) String[] ,我們當(dāng)然可以在接口內(nèi)部去處理,但是我們作為 專業(yè)的屌絲程序員,哈哈哈 ,還是要用專業(yè)一些的手段,這里就可以定義一個(gè) 將豎線分割的多個(gè)字符串轉(zhuǎn)換為String[] 的自定義屬性編輯器來實(shí)現(xiàn)。
- 自定義屬性編輯器
通過繼承 java.beans.PropertyEditorSupport 類并重寫其 setAdText(String text) 方法完成,最后調(diào)用 setValue(Object Value) 方法完成轉(zhuǎn)換后的值的設(shè)置。
public class StringToListPropertyEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { String[] resultArr = null; if (!StringUtils.isEmpty(text)) { resultArr = text.split("_"); } setValue(resultArr); } }
使用
@RequestMapping("/myStringToList") @Controller public class StringToListController { @InitBinder public void myStringToListBinder(WebDataBinder dataBinder) { dataBinder.registerCustomEditor(String[].class, new StringToListPropertyEditor()); } @RequestMapping(value = "/test", method = RequestMethod.GET) @ResponseBody public String myStringToListTest(String[] strToListArr, HttpServletResponse response) { response.setCharacterEncoding("UTF-8"); String result = "_分割字符串轉(zhuǎn)String[]不成功!"; if (strToListArr != null && strToListArr.length > 0) { result = Arrays.asList(strToListArr).toString(); } return result; } }
訪問測(cè)試
2: 處理帶有前綴的form字段
比如這樣的場(chǎng)景,在People,Address兩個(gè)類中都有name字段,但是我們需要在一個(gè)表單中錄入People和Address的信息,然后在接口中直接通過People,Address兩個(gè)對(duì)象來接收頁面的表單數(shù)據(jù),但是 兩個(gè)name 是無法區(qū)分的,一般的做法就是指定一個(gè)前綴,然后通過@InitBinder通過調(diào)用 org.springframework.web.bind.WebDataBinder 的 setFieldDefaultPrefix(@Nullable String fieldDefaultPrefix) 方法,然后在接口中使用注解 public @interface ModelAttribute 設(shè)置要接收的參數(shù)的前綴,就可以區(qū)分并接收對(duì)應(yīng)的參數(shù)了。
2.1: 定義用到的實(shí)體
Person
public class People { private String name; private String age; // getter setter toString }
Address
public class Address { private String name; private String city; // getter setter toString }
2.2: 定義測(cè)試使用的表單
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <form action="${pageContext.request.contextPath}/myInitBinder0954/test0942" method="post" enctype="multipart/form-data"> <input type="text" name="people.name" placeholder="人名"><br><br> <input type="text" name="people.age" placeholder="人年齡"><br><br> <input type="text" name="address.name" placeholder="地址名稱"><br><br> <input type="text" name="address.city" placeholder="地址所在城市"><br><br> <input type="submit" value="提交"/> </form> </body> </html>
2.3: 定義接口
@RequestMapping("/myInitBinder0954") @Controller public class MyInitBinderController { @InitBinder(value = "people") public void initBinderSetDefaultPreifixPeople(WebDataBinder dataBinder) { dataBinder.setFieldDefaultPrefix("people."); } @InitBinder(value = "address") public void initBinderSetDefaultPreifixAddress(WebDataBinder dataBinder) { dataBinder.setFieldDefaultPrefix("address."); } @RequestMapping(value = "/test0942", method = RequestMethod.POST) @ResponseBody public String test0942(@ModelAttribute("people") People people, @ModelAttribute("address") Address address) { StringBuffer sb = new StringBuffer(); sb.append(people.toString()); sb.append("---"); sb.append(address.toString()); return sb.toString(); } }
2.4: 訪問測(cè)試 錄入表帶數(shù)據(jù)
訪問返回結(jié)果
3:注冊(cè)校驗(yàn)器
3.1:定義測(cè)試實(shí)體
package dongshi.controller.initbinder; public class User { private String userName; // getter setter toString }
3.2:自定義校驗(yàn)器
直接實(shí)現(xiàn) org.springframework.validation.Validator ,該接口只有兩個(gè)方法,一個(gè)是校驗(yàn)是否支持校驗(yàn)的 support(Class<?> clazz) 方法,一個(gè)是進(jìn)行具體校驗(yàn)的 validate(Object target, Errors errors) 方法,源碼如下:
public interface Validator { boolean supports(Class<?> clazz); void validate(Object target, Errors errors); }
定義一個(gè)校驗(yàn)器:
@Component public class UserValidator implements Validator { @Override public boolean supports(Class<?> clazz) { // 只支持User類型對(duì)象的校驗(yàn) return User.class.equals(clazz); } @Override public void validate(Object target, Errors errors) { User user = (User) target; String userName = user.getUserName(); if (StringUtils.isEmpty(userName) || userName.length() < 8) { errors.rejectValue("userName", "valid.userNameLen", new Object[] { "minLength", 8 }, "用戶名不能少于{1}位"); } } }
該校驗(yàn)器校驗(yàn)用戶錄入的userName長(zhǎng)度是否大于8,并給出響應(yīng)的錯(cuò)誤信息,錯(cuò)誤信息直接設(shè)置到errors中,最終會(huì)設(shè)置到 org.springframework.validation.BindingReuslt ,在接口中直接定義該對(duì)象則會(huì)自動(dòng)注入對(duì)象值,從而可以獲取到對(duì)應(yīng)的錯(cuò)誤信息。
3.3:定義控制器
@Controller @RequestMapping("/valid") public class ValidatorController { @Autowired private UserValidator userValidator; @InitBinder private void initBinder(WebDataBinder binder) { binder.addValidators(userValidator); } @RequestMapping(value = { "/index", "" }, method = { RequestMethod.GET }) public String index(ModelMap m) throws Exception { m.addAttribute("user", new User()); return "initbinder/user.jsp"; } @RequestMapping(value = { "/signup" }, method = { RequestMethod.POST }) public String signup(@Validated User user, BindingResult br, RedirectAttributes ra) throws Exception { // 攜帶用戶錄入的信息方便回顯 ra.addFlashAttribute("user", user); return "initbinder/user.jsp"; } }
3.4:定義user.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <html> <head> <title>validate user</title> </head> <body> <form:form modelAttribute="user" action="/valid/signup" method="post"> <!-- 顯示所有的錯(cuò)誤信息 --> <form:errors path="*"></form:errors> 用戶名:<form:input path="userName"/><form:errors path="userName"/> </form:form> </body> </html>
3.5:訪問user.jsp
錄入一個(gè)不合法的字符,并回車:
到此這篇關(guān)于掌握SpringMVC中@InitBinder的實(shí)際應(yīng)用的文章就介紹到這了,更多相關(guān)SpringMVC中@InitBinder內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
maven多個(gè)倉庫查詢的優(yōu)先級(jí)順序案例講解
這篇文章主要介紹了maven多個(gè)倉庫查詢的優(yōu)先級(jí)順序,考慮到我們常用的配置文件是conf/settings.xml和工程里面的pom.xml文件,我們針對(duì)這兩個(gè)文件的結(jié)合來分析倉庫的使用順序,需要的朋友可以參考下2023-04-04Java8 新特性之日期時(shí)間對(duì)象及一些其他特性
這篇文章主要介紹了Java8 新特性之日期時(shí)間對(duì)象及一些其他特性,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01Java代理的幾種實(shí)現(xiàn)方式總結(jié)
本文將通過例子說明java代理的幾種實(shí)現(xiàn)方式,并比較它們之間的差異,文中通過代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的參考價(jià)值,需要的朋友可以參考下2023-12-12springcloud gateway聚合swagger2的方法示例
這篇文章主要介紹了springcloud gateway聚合swagger2的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04Java 中實(shí)現(xiàn)隨機(jī)無重復(fù)數(shù)字的方法
為了更好地理解這個(gè)題意,我們先來看下具體內(nèi)容:生成一個(gè)1-100 的隨機(jī)數(shù)組,但數(shù)組中的數(shù)字不能重復(fù),即位置是隨機(jī)的,但數(shù)組元素不能重復(fù)2013-03-03java ArrayList.remove()的三種錯(cuò)誤用法以及六種正確用法詳解
這篇文章主要介紹了java ArrayList.remove()的三種錯(cuò)誤用法以及六種正確用法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01Java實(shí)現(xiàn)平鋪列表(List)互轉(zhuǎn)樹形(Tree)結(jié)構(gòu)
本文主要介紹了Java實(shí)現(xiàn)平鋪列表(List)互轉(zhuǎn)樹形(Tree)結(jié)構(gòu),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08