javascript
spring 类型转换器_Spring中的类型转换
spring 類型轉換器
以下是一些需要類型轉換的簡單情況:
情況1。 為了幫助簡化bean配置,Spring支持屬性值與文本值之間的轉換。 每個屬性編輯器僅設計用于某些類型的屬性。 為了使用它們,我們必須在Spring容器中注冊它們。
案例2。 同樣,在使用Spring MVC時,控制器會將表單字段值綁定到對象的屬性。 假設對象是由另一個對象組成的,則MVC控制器無法自動將值分配給內部自定義類型對象,因為表單中的所有值都作為文本值輸入。 Spring容器將把文本值轉換為原始類型,而不轉換為自定義類型對象。 為此,我們必須在MVC流中初始化自定義編輯器。
本文將討論實現自定義類型對象的轉換器的各種方法。 為了詳細說明這些,讓我們考慮以下用例。 在該示例中,我想模擬游戲場地預訂系統。 所以這是我的領域對象:
public class Reservation {public String playGround;public Date dateToReserve;public int hour;public Player captain;public SportType sportType;public Reservation(String playGround, Date date, int hour, Player captain, SportType sportType) {this.playGround = playGround;this.dateToReserve = date;this.hour = hour;this.captain = captain;this.sportType = sportType;}/*** Getters and Setters*/ }public class Player {private String name;private String phone;/*** Getters and Setters*/}public class SportType {public static final SportType TENNIS = new SportType(1, "Tennis");public static final SportType SOCCER = new SportType(2, "Soccer");private int id;private String name;public SportType(int id, String name) {this.id = id;this.name = name;}public static Iterable<SportType> list(){return Arrays.asList(TENNIS, SOCCER);}public static SportType getSport(int id){for(SportType sportType : list()){if(sportType.getId() == id){return sportType;}}return null;}/*** Getters and Setters*/ }這是案例1的示例:假設我們要定義一個預留bean,這是我們的方法:
<bean id="dummyReservation" class="com.pramati.model.Reservation"><property name="playGround" value="Soccer Court #1"/><property name="dateToReserve" value="11-11-2011"/><property name="hour" value="15"/><property name="captain"><bean class="com.pramati.model.Player"><property name="name" value="Prasanth"/><property name="phone" value="92131233124"/></bean></property><property name="sportType"><property name="id" value="1"/><property name="name" value="TENNIS"/></property> </bean>這個bean的定義很冗長。 如果定義看起來像這樣,它本來可以表現得更好:
<bean id="dummyReservation" class="com.pramati.model.Reservation"><property name="playGround" value="Soccer Court #1"/><property name="dateToReserve" value="11-11-2011"/><property name="hour" value="15"/><property name="captain" value="Prasanth,92131233124"/><property name="sportType" value="1,TENNIS"/> </bean>為此,我們應該告訴Spring在定義bean的過程中使用自定義轉換器。
這是案例2的示例:假設我的應用程序中有一個JSP,它允許用戶在一天的特定時間預訂游樂場。
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Reservation Form</title> <style type="text/css"> .error {color: #ff0000;font-weight: bold; } </style> </head> <body><form:form method="post" modelAttribute="reservation"><table><tr><th>Court Name</th><td><form:input path="courtName" /></td></tr><tr><th>Reservation Date</th><td><form:input path="date" /></td></tr><tr><th>Hour</th><td><form:input path="hour" /></td></tr><tr><th>Player Name</th><td><form:input path="player.name" /></td></tr><tr><th>Player Contact Number</th><td><form:input path="player.phone" /></td></tr><tr><th>Sport Type</th><td><form:select path="sportType" items="${sportTypes}"itemLabel="name" itemValue="id" /></td></tr><tr><td colspan="3"><input type="submit" name="Submit" /></td></tr></table></form:form> </body> </html>這是對應的MVC控制器:
@Controller @RequestMapping @SessionAttributes("reservation") public class ReservationFormController {@Autowiredprivate ReservationService reservationService;@ModelAttribute("sportTypes")public Iterable<SportType> getSportTypes(){return SportType.list();}@RequestMapping(value="/reservationForm/{captainName}", method=RequestMethod.GET)public String initForm(Model model, @PathVariable String captainName){Reservation reservation = new Reservation();reservation.setPlayer(new Player(captainName, null));reservation.setSportType(SportType.TENNIS);model.addAttribute("reservation", reservation);return "reservationForm";}@RequestMapping(value="/reservationForm/{captainName}",method=RequestMethod.POST)public String reserve(@Valid Reservation reservation, BindingResult bindingResult, SessionStatus sessionStatus){validator.validate(reservation, bindingResult);if(bindingResult.hasErrors()){return "/reservationForm";} else{reservationService.make(reservation);sessionStatus.setComplete();return "redirect:../reservationSuccess";}} }現在您可以看到,在JSP中,我們將表單字段綁定到Reservation對象(modelAttribute =“ reservation”)。 該對象由傳遞給視圖的控制器(在initForm()方法中)保留在模型中。 現在,當我們提交表單時,Spring會引發一條驗證消息,指出無法將字段值轉換為類型Player和SportType。 為此,我們必須定義自定義轉換器并將其注入Spring MVC流中。
現在的問題是如何定義自定義轉換器? Spring提供了兩種支持這些自定義轉換器的方式:
- 解決方案1:使用PropertyEditors
- 解決方案2:使用轉換器
使用PropertyEditor:
PropertyEditorSupport,實現PropertyEditor接口,是用于幫助構建PropertyEditor的支持類。
public class SportTypeEditorSupport extends PropertyEditorSupport {/*** Sets the property value by parsing a given String. May raise* java.lang.IllegalArgumentException if either the String is* badly formatted or if this kind of property can't be expressed* as text.** @param text The string to be parsed.*/@Overridepublic void setAsText(String text) throws IllegalArgumentException {try{SportType sportType = SportType.getSport(Integer.parseInt(text));setValue(sportType);// setValue stores the custom type Object into a instance variable in PropertyEditorSupport.}catch(NumberFormatException nfe){throw new RuntimeException(nfe.getMessage());}}/*** Gets the property value as a string suitable for presentation* to a human to edit.** @return The property value as a string suitable for presentation* to a human to edit.* <p> Returns "null" is the value can't be expressed as a string.* <p> If a non-null value is returned, then the PropertyEditor should* be prepared to parse that string back in setAsText().*/@Overridepublic String getAsText() {SportType sportType = (SportType)getValue();return Integer.toString(sportType.getId());} }現在,在PropertyEditorRegistry中注冊自定義編輯器。 PropertyEditorRegistrar在PropertyEditorRegistry中注冊自定義編輯器。 這是您的操作方式:
import java.text.SimpleDateFormat; import java.util.Date;import org.springframework.beans.PropertyEditorRegistrar; import org.springframework.beans.PropertyEditorRegistry; import org.springframework.beans.propertyeditors.CustomDateEditor;import com.pramati.model.SportType;public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {@Overridepublic void registerCustomEditors(PropertyEditorRegistry registry) {registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("dd-MM-yyyy"), true));registry.registerCustomEditor(SportType.class, new SportTypeEditorSupport());} }CustomEditorConfigurer被實現為Bean工廠后處理器,您可以在實例化任何Bean之前注冊自定義屬性編輯器。 為此,我們將PropertyEditorRegistry與CustomEditorConfigurer關聯。
<bean id="customPropertyEditorRegistrar" class="com.pramati.spring.mvc.CustomPropertyEditorRegistrar"/><bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"><property name="propertyEditorRegistrars"><list><ref bean="customPropertyEditorRegistrar"/></list></property> </bean>現在,當Spring容器看到??此信息時:
<property name="captain" value="Prasanth,92131233124"/>Spring自動將指定的值轉換為Player對象。 但是,此配置對于Spring MVC流還不夠。 控制器仍然會抱怨類型不兼容,因為它期望一個Player對象在獲取String的地方。 為了將表單字段值解釋為自定義類型對象,我們必須進行很少的MVC配置更改。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.convert.ConversionService; import org.springframework.validation.Validator; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.support.WebBindingInitializer; import org.springframework.web.context.request.WebRequest;public class CustomWebBindingInitializer implements WebBindingInitializer {@Autowiredprivate CustomPropertyEditorRegistrar customPropertyEditorRegistrar;@Overridepublic void initBinder(WebDataBinder binder, WebRequest request) {customPropertyEditorRegistrar.registerCustomEditors(binder);} }現在,手動刪除并定義必要的bean,因為我們需要將WebBindingInitializer注入RequestMappingHandlerAdapter
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="webBindingInitializer"><bean class="com.pramati.spring.mvc.CustomWebBindingInitializer"/></property> </bean>現在,控制器會自動將String轉換為必要的自定義類型對象。 請注意,我們必須進行單獨的配置更改,以簡化Spring MVC中的bean配置和表單字段的類型轉換。 同樣值得指出的是,在擴展PropertyEditorSupport時,我們將自定義類型對象存儲在實例變量中,因此使用PropertyEditors并不是線程安全的。 為了克服這些問題,Spring 3.0引入了轉換器和格式化程序的概念。
使用轉換器:
轉換器組件用于將一種類型轉換為另一種類型,并通過強制將所有此類與轉換相??關的代碼放在一個位置來提供更清晰的分隔。 Spring已經支持常用類型的內置轉換器,并且該框架可擴展性足以編寫自定義轉換器。 Spring Formatters進入圖片以根據呈現數據的顯示來格式化數據。 在考慮編寫適合特定業務需求的自定義轉換器之前,總是有必要先查看詳盡的預制轉換器列表。 有關查看預建轉換器的列表,請參見org.springframework.core.convert.support軟件包。
回到我們的用例,讓我們實現String到SportType轉換器:
import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; import com.pramati.model.SportType;public class StringToSportTypeConverter implements Converter<String, SportType> {@Overridepublic SportType convert(String sportIdStr) {int sportId = -1;try{sportId = Integer.parseInt(sportIdStr);} catch (NumberFormatException e) {throw new ConversionFailedException(TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(SportType.class), sportIdStr, null);}SportType sportType = SportType.getSport(sportId);return sportType;}}現在,在ConversionService中注冊它,并將其與SpringMVC流鏈接:
<mvc:annotation-driven conversion-service="conversionService"/><bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean" ><property name="converters"><set><bean class="com.pramati.type.converters.StringToSportTypeConverter"/><bean class="com.pramati.type.converters.StringToDateConverter"/><bean class="com.pramati.type.converters.StringToPlayerConverter"/></set></property> </bean>如果您使用的是自定義bean聲明而不是?mvc:annotation-driven /?,則可以使用以下方法:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.convert.ConversionService; import org.springframework.validation.Validator; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.support.WebBindingInitializer; import org.springframework.web.context.request.WebRequest;public class CustomWebBindingInitializer implements WebBindingInitializer {@Autowiredprivate ConversionService conversionService;@Overridepublic void initBinder(WebDataBinder binder, WebRequest request) {binder.setConversionService(conversionService);}}現在將WebBindingInitializer注入RequestMappingHandlerAdapter。
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="webBindingInitializer"><bean class="com.pramati.spring.mvc.CustomWebBindingInitializer"/></property> </bean>單獨注冊ConversionService將有助于簡化bean配置(案例1)。 為了使案例2正常工作,我們必須在Spring MVC流中注冊ConversionService。 請注意,這種類型轉換方式也是線程安全的。
同樣,除了使Converters / PropertEditor對應用程序中的所有控制器都可用之外,我們還可以基于每個控制器啟用它們。 這是您的操作方式。 刪除上面指定的通用配置,并在控制器類中引入@InitBinder,如下所示:
@Controller @RequestMapping @SessionAttributes("reservation") public class ReservationFormController {private ReservationService reservationService;private ReservationValidator validator;@Autowiredpublic ReservationFormController(ReservationService reservationService, ReservationValidator validator){this.reservationService = reservationService;this.validator = validator;}@Autowiredprivate ConversionService conversionService;@InitBinderprotected void initBinder(ServletRequestDataBinder binder) {binder.setConversionService(conversionService);}/*@InitBinderprotected void initBinder(ServletRequestDataBinder binder) {binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("dd-MM-yyyy"), true));binder.registerCustomEditor(SportType.class, new SportTypeEditorSupport(reservationService));}*//*@Autowiredprivate PropertyEditorRegistrar propertyEditorRegistrar;@InitBinderprotected void initBinder(ServletRequestDataBinder binder) {propertyEditorRegistrar.registerCustomEditors(binder);}*/@ModelAttribute("sportTypes")public Iterable<SportType> getSportTypes(){return SportType.list();}@RequestMapping(value="/reservationForm/{userName}", method=RequestMethod.GET)public String initForm(Model model, @PathVariable String userName){Reservation reservation = new Reservation();reservation.setPlayer(new Player(userName, null));reservation.setSportType(SportType.TENNIS);model.addAttribute("reservation", reservation);return "reservationForm";}@RequestMapping(value="/reservationForm/{userName}",method=RequestMethod.POST)public String reserve(@Valid Reservation reservation, BindingResult bindingResult, SessionStatus sessionStatus){validator.validate(reservation, bindingResult);if(bindingResult.hasErrors()){return "/reservationForm";} else{reservationService.make(reservation);sessionStatus.setComplete();return "redirect:../reservationSuccess";}}@RequestMapping("/reservationSuccess")public void success(){} } 因此,如果您看到上面的代碼,您會注意到在使用PropertyEditor而不是轉換器的地方,注釋的代碼。 因此,在兩種實現方式中都可以使用基于控制器啟用類型轉換器的功能。
翻譯自: https://www.javacodegeeks.com/2013/11/type-conversion-in-spring-2.html
spring 類型轉換器
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的spring 类型转换器_Spring中的类型转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Google Cloud Stora
- 下一篇: 认识适配器:JSON绑定概述系列