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 {
@Autowired
private 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.
*/
@Override
public 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().
*/
@Override
public 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 {
@Override
public 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 {
@Autowired
private CustomPropertyEditorRegistrar customPropertyEditorRegistrar;
@Override
public 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> {
@Override
public 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 {
@Autowired
private ConversionService conversionService;
@Override
public 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;
@Autowired
public ReservationFormController(ReservationService reservationService, ReservationValidator validator){
this.reservationService = reservationService;
this.validator = validator;
}
@Autowired
private ConversionService conversionService;
@InitBinder
protected void initBinder(ServletRequestDataBinder binder) {
binder.setConversionService(conversionService);
}
/*@InitBinder
protected void initBinder(ServletRequestDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("dd-MM-yyyy"), true));
binder.registerCustomEditor(SportType.class, new SportTypeEditorSupport(reservationService));
}*/
/*@Autowired
private PropertyEditorRegistrar propertyEditorRegistrar;
@InitBinder
protected 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èä¸æ¯è½¬æ¢å¨çå°æ¹ï¼æ³¨éç代ç ã å æ¤ï¼å¨ä¸¤ç§å®ç°æ¹å¼ä¸é½å¯ä»¥ä½¿ç¨åºäºæ§å¶å¨å¯ç¨ç±»å转æ¢å¨çåè½ã
åèï¼prasanthnathå客ä¸çJCGåä½ä¼ä¼´ Prasanth Gullapalli å¨Springä¸è¿è¡äºç±»åè½¬æ¢ ã
ç¿»è¯èª: https://www.javacodegeeks.com/2013/11/type-conversion-in-spring-2.html
spring ç±»å转æ¢å¨