4.盤點springmvc的經常使用接口之PropertyEditor

4.盤點springmvc的經常使用接口之PropertyEditor###

java.beans.PropertyEditor嚴格上來講,其實並不能算spring框架的接口,很明顯看包名就明白此類是JDK自帶的。是Sun所制定的一套JavaBean規範,是爲IDE圖形化界面準備設置屬性值的接口。看接口源碼上的說明:java

A PropertyEditor class provides support for GUIs that want to allow users to edit a property value of a giventype.

這接口本來是使用在GUI圖形程序中,容許用戶給giventype設定屬性值的。(不熟悉圖形化界面API,不知道giventype是什麼,怎麼翻譯)web

接口說明

public interface PropertyEditor {

    void setValue(Object value);

    Object getValue();

    boolean isPaintable();

    void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box);

    String getJavaInitializationString();

    String getAsText();

    void setAsText(String text) throws java.lang.IllegalArgumentException;
  
    String[] getTags();

    java.awt.Component getCustomEditor();

    boolean supportsCustomEditor();

    void addPropertyChangeListener(PropertyChangeListener listener);

    void removePropertyChangeListener(PropertyChangeListener listener);
}

不要被這麼多的方法給嚇到,對於咱們使用者來講其實重點只有下面4個方法:spring

  • void setValue(Object value);設置屬性值
  • Object getValue();獲取屬性值
  • String getAsText(); 把屬性值轉換成string
  • void setAsText(String text);把string轉換成屬性值

因此Java很機智地提供了一個適配器java.beans.PropertyEditorSupport來幫助咱們實現屬性值的轉換,它幫助咱們實現了GUI部分的接口,咱們只須要重寫getAsTextsetAsText的邏輯。mvc

那麼這個接口跟spring有什麼鳥關係呢,這個接口有什麼用呢?請看示例1。app

示例1

一個由區號和號碼組成的座機號碼實體類:框架

package com.demo.domain;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Telephone {

	/* 區號 */
	private String areaCode;
	/* 號碼 */
	private String phone;

	@Override
	public String toString() {
		return areaCode + "-" + phone;
	}
}

一我的的實體(屏蔽了無關屬性,只有座機-_-):dom

package com.demo.domain;

import org.springframework.beans.factory.annotation.Value;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class PersonEntity {

	@Value("010-12345")
	private Telephone telephone;
}

@Value是spring的註解,至關於xml配置<property name="" value=""/>裏面的value,給屬性賦值的。可是請注意,這裏賦的是字符串。ide

那麼問題來了,這個010-12345的字符串是怎麼賦到Telephone這個類對象上的呢?類型根本轉不過來。spring-boot

答案就是實現轉換器PropertyEditorpost

package com.demo.mvc.component;

import java.beans.PropertyEditorSupport;

import com.demo.domain.Telephone;

public class TelephonePropertyEditor extends PropertyEditorSupport {

	@Override
	public void setAsText(String text) throws IllegalArgumentException {
		if (text.matches("^\\d+\\-\\d+$")) {
			String[] strs = text.split("\\-");
			setValue(new Telephone(strs[0], strs[1]));
		} else {
			throw new IllegalArgumentException();
		}
	}

	@Override
	public String getAsText() {
		return ((Telephone) getValue()).toString();
	}
}

實現完了接口還得註冊到spring容器讓spring管理:

<bean class="com.demo.domain.PersonEntity" />

<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="customEditors">
    <map>
      <entry key="com.demo.domain.Telephone" value="com.demo.mvc.component.TelephonePropertyEditor" />
    </map>
  </property>
</bean>

這個CustomEditorConfigurer類顧名思義就是配置自定義的屬性轉換器的。把自定義的轉換器通通放進這個名叫customEditors的Map結構裏。用key指定Telephone,value指定TelephonePropertyEditor。

就是告訴spring,當遇到Telephone這個類型時,使用TelephonePropertyEditor把字符串轉化成Telephone。

單元測試:

package com.junit;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.demo.domain.PersonEntity;
import com.demo.domain.Telephone;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:spring/spring-context.xml")
public class PropertyEditorlJunitTest {

	@Resource
	private PersonEntity personEntity;

	@Test
	public void test() {
		Telephone telephone = personEntity.getTelephone();
		System.out.printf("區號:%s,號碼:%s\n", telephone.getAreaCode(), telephone.getPhone());
	}
}

最後控制檯輸出結果:

區號:010,號碼:12345

示例2

示例1是普通spring狀況下使用PropertyEditor的例子,那麼怎麼用在springmvc上呢?

package com.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.demo.domain.Telephone;
import com.demo.mvc.component.TelephonePropertyEditor;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("demo4")
public class PropertyEditorDemoController {

	@InitBinder
	public void initBinder(WebDataBinder binder) {
		binder.registerCustomEditor(Telephone.class, new TelephonePropertyEditor());
	}

	@ResponseBody
	@RequestMapping(method = RequestMethod.POST)
	public String postTelephone(@RequestParam Telephone telephone) {
		log.info(telephone.toString());
		return telephone.toString();
	}
}

使用@InitBinder註解,在WebDataBinder對象上註冊轉換器。

這樣在訪問POST http://localhost:8080/demo4 傳表單數據 telephone = 010-12345

010-12345的字符串會自動轉換爲Telephone對象。

固然這種方式有一個缺點,該轉換器只在當前的controller下有效。

想要實現全局轉換,那就得實現WebBindingInitializer接口

package com.demo.mvc.component;

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.context.request.WebRequest;

import com.demo.domain.Telephone;

public class MyWebBindingInitializer implements WebBindingInitializer {

	@Override
	public void initBinder(WebDataBinder binder, WebRequest request) {
		binder.registerCustomEditor(Telephone.class, new TelephonePropertyEditor());
	}

}

在這裏能夠批量註冊轉換器。

spring-boot註冊:

package com.demo;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import com.demo.mvc.component.MyWebBindingInitializer;

@SpringBootApplication
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

	@Override
	public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
		RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
		adapter.setWebBindingInitializer(new MyWebBindingInitializer());
		return adapter;
	}
}

xml註冊:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">  
  <property name="webBindingInitializer">  
    <bean class="com.demo.mvc.component.MyWebBindingInitializer"/>  
  </property>  
</bean>

p.s.:這一章介紹了這麼大篇幅的PropertyEditor的使用,最後再說一句(不要打我哦)上述介紹的方法其實都已過期-_-。

在spring3.x後,新出了一個更強大的轉換器機制,Converter!

那麼下一章再來說解強大的Converter吧。

友情連接:

盤點springmvc的經常使用接口目錄

相關文章
相關標籤/搜索