springソースコード学習シリーズ3.2.1-commandオブジェクトのバインディング
11904 ワード
もっと読む
MultiAction Controller〓〓invoke NamedMethod法では、requestパラメータ値をcommandオブジェクトに設定する-別の形式のモデルドライバ
springmvc設計の重要な原則は開閉の原則です.
変更または処理の流れをオフにして、拡張に開放します.
しかし、カスタムコントローラに対してMultiAction Controllerを継承し、いくつかの方法をカバーし、springmvcの一部機能を変更しました.
Bind(HttpServletRequest request、Object command)をカバーするように、バインディングプロセスは完全にユーザーのプログラミング能力によって決定されます.
springバージョン3.2.2
バインディングエントリインターフェース:
Servlet Request Data Binder
日付フォーマットの変換はどこですか?
binderは属性エディタを登録できます.文字列フォーマットをData形式に変更します.
MultiAction Controller〓〓createBinder
ServletRequest Data Binder extends WebData Binder extends Data Binder
ServletRequest Data Binderのオブジェクトを作成する場合は、設定値のcommandオブジェクトでbinderを初期化します.もうすぐcommandをData Binderにパッケージングします.
======================================================================職責分割線
実際にcommandオブジェクトを結びつける作業はData Binderインターフェースで行い、ユーザー(開発者)は設定値requestと設定値commandをData Binderに送るだけでいいです.
1.request->MutalbPropertyValues(data Binder)
2.MutalbPropertyValues->command(beanWrapper)
Servlet Request Data Binder胫bind
Data Binder萉doBind
テストのエラーまたは他の情報の処理に対して、springmvcは、DataBinderの属性bindingResoultに配置され、BenPropertyBindingResoultのようなオブジェクトです.
2.2.1と2.2.1を結合する前にチェックアウトした場合、なぜ彼女たちのチェックを一緒にしないですか?独立して見るべきです.それぞれの種類の関心や役割が違っています.彼女たちはそれぞれの方法の丈夫さを維持しなければなりません.
Data Binder萼appyPropertyValues
request->mpvs
======================================================================職責分割線
DataBinderは最後にやはりバトンをBenWrapperに渡しました.
mpvs->command
AbstractPropertyAccess or啝set PropertyValues
以下はbeanWrapperまたはConfigrable PropertyAccess orを得るための経路です.無視できます.
Data Binder萢get PropertyAccess or
commandバインディングをしないなら、正常なrequest.get Parameeter()、効率はきっとspringmvcのパラメータバインディング効率より高くて、空間的にも比較的少ないメモリを占有します.
時間と空間にはどのような違いがありますか?
Servlet Request Data Binderオブジェクトを作成しました.
MutablePropertyValuesオブジェクトを作成しました.
BenPropertyBindingResoultを作成しました.
Default BindingErrocessorを作成しました.
BenWrapperImplを作成しました.command属性を設定します.
参考:
Validation,Data Binding,and Type Coversion
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html
MultiAction Controller〓〓invoke NamedMethod法では、requestパラメータ値をcommandオブジェクトに設定する-別の形式のモデルドライバ
springmvc設計の重要な原則は開閉の原則です.
変更または処理の流れをオフにして、拡張に開放します.
しかし、カスタムコントローラに対してMultiAction Controllerを継承し、いくつかの方法をカバーし、springmvcの一部機能を変更しました.
Bind(HttpServletRequest request、Object command)をカバーするように、バインディングプロセスは完全にユーザーのプログラミング能力によって決定されます.
springバージョン3.2.2
バインディングエントリインターフェース:
Servlet Request Data Binder
日付フォーマットの変換はどこですか?
binderは属性エディタを登録できます.文字列フォーマットをData形式に変更します.
@InitBinder
public void initBinder(WebDataBinder binder) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
CustomDateEditor dateEditor = new CustomDateEditor(df, true);
binder.registerCustomEditor(Date.class, dateEditor);
}
パラメータチェックはいつですか?// If last parameter isn't of HttpSession type, it's a command.
if (paramTypes.length >= 3 &&
!paramTypes[paramTypes.length - 1].equals(HttpSession.class)) {
Object command = newCommandObject(paramTypes[paramTypes.length - 1]);
params.add(command);
bind(request, command);
}
MultiAction Controller〓〓〓bindprotected void bind(HttpServletRequest request, Object command) throws Exception {
logger.debug("Binding request parameters onto MultiActionController command");
// 1 ServletRequestDataBinder
ServletRequestDataBinder binder = createBinder(request, command);
// 2 request command
binder.bind(request);
if (this.validators != null) {
for (Validator validator : this.validators) {
if (validator.supports(command.getClass())) {
ValidationUtils.invokeValidator(validator, command, binder.getBindingResult());
}
}
}
binder.closeNoCatch();
}
カスタムvalidators、検証パラメータ、必ず検証などMultiAction Controller〓〓createBinder
protected ServletRequestDataBinder createBinder(HttpServletRequest request, Object command) throws Exception {
// 1.1 ServletRequestDataBinder
ServletRequestDataBinder binder = new ServletRequestDataBinder(command, getCommandName(command));
// 1.2 binder- -webBindingInitializer-springmvc
initBinder(request, binder);
return binder;
}
MultiAction Controllerにおける方法については、bindやinitBinderなど、カスタマイズされたcontrollerのサブクラスによってカバーされ、自分のバインディングロジックを定義することができます.しかし、一般的にはそうしません.このようにプロジェクトはspringmvcと結合性が強化されました.@Override
protected void bind(HttpServletRequest request, Object command) throws Exception {
System.out.println(" bind");
}
@Override
protected ServletRequestDataBinder createBinder(HttpServletRequest request, Object command) throws Exception {
return null;
}
@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
binder.setAutoGrowNestedPaths(true);
binder.setAutoGrowCollectionLimit(1024);
System.out.println("hi, i am initBinder");
}
Servlet Request Data Binder継承システムは、ServletRequest Data Binder extends WebData Binder extends Data Binder
ServletRequest Data Binderのオブジェクトを作成する場合は、設定値のcommandオブジェクトでbinderを初期化します.もうすぐcommandをData Binderにパッケージングします.
======================================================================職責分割線
実際にcommandオブジェクトを結びつける作業はData Binderインターフェースで行い、ユーザー(開発者)は設定値requestと設定値commandをData Binderに送るだけでいいです.
1.request->MutalbPropertyValues(data Binder)
2.MutalbPropertyValues->command(beanWrapper)
Servlet Request Data Binder胫bind
public void bind(ServletRequest request) {
// 2.1 MutablePropertyValues: request ProperValues
// request.getParameterNames() map, MutablePropertyValues
MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request);
MultipartRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartRequest.class);
if (multipartRequest != null) {
bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
}
addBindValues(mpvs, request);
// 2.2 , mpvs command - ServletRequestDataBinder
doBind(mpvs);
}
WebData Binder芫doBind@Override
protected void doBind(MutablePropertyValues mpvs) {
// 2.2.1 ( ! _ ) , -WebDataBinder
// ( ) controller , createBinder ,
checkFieldDefaults(mpvs);
checkFieldMarkers(mpvs);
// 2.2.2 , command
super.doBind(mpvs);
}
2.2.1特殊属性名を処理し、プレフィックスを削除する.このロジックが必要でないなら、createBinderをカバーして、自分のdata Binder extexds ServletRequest Data Binderをカスタマイズします.Data Binder萉doBind
/**
* Actual implementation of the binding process, working with the
* passed-in MutablePropertyValues instance.
* @param mpvs the property values to bind,
* as MutablePropertyValues instance
* @see #checkAllowedFields
* @see #checkRequiredFields
* @see #applyPropertyValues
*/
protected void doBind(MutablePropertyValues mpvs) {
// 2.2.2.1 -DataBinder
checkAllowedFields(mpvs);
checkRequiredFields(mpvs);
// 2.2.2.2
applyPropertyValues(mpvs);
}
Data Binder胪doBindはmpvsをcommandオブジェクトに結びつけるところであり、これはrequestパラメータをMutble PropertyValuesにパッケージする意味かもしれない.Servlet Request Data Binderはrequestをmpvsにパッケージ化するだけでなく、他の形式の要求パラメータもあります.Data Binderを継承してから対応するパッケージを作ります.テストのエラーまたは他の情報の処理に対して、springmvcは、DataBinderの属性bindingResoultに配置され、BenPropertyBindingResoultのようなオブジェクトです.
2.2.1と2.2.1を結合する前にチェックアウトした場合、なぜ彼女たちのチェックを一緒にしないですか?独立して見るべきです.それぞれの種類の関心や役割が違っています.彼女たちはそれぞれの方法の丈夫さを維持しなければなりません.
Data Binder萼appyPropertyValues
protected void applyPropertyValues(MutablePropertyValues mpvs) {
try {
// 2.2.2.2.1
// Bind request parameters onto target object.
getPropertyAccessor().setPropertyValues(mpvs, isIgnoreUnknownFields(), isIgnoreInvalidFields());
}
catch (PropertyBatchUpdateException ex) {
// Use bind error processor to create FieldErrors.
for (PropertyAccessException pae : ex.getPropertyAccessExceptions()) {
getBindingErrorProcessor().processPropertyAccessException(pae, getInternalBindingResult());
}
}
}
get BindingErrocessor().processPropertyAccess Exception(pae,get Internal BindingResoult();異常処理メカニズムのために、異常をbindingReltに設定し、バインディング終了時にServletRequest Data Binderを呼び出します.request->mpvs
======================================================================職責分割線
DataBinderは最後にやはりバトンをBenWrapperに渡しました.
mpvs->command
AbstractPropertyAccess or啝set PropertyValues
public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
throws BeansException {
List propertyAccessExceptions = null;
List propertyValues = (pvs instanceof MutablePropertyValues ?
((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
for (PropertyValue pv : propertyValues) {
try {
// This method may throw any BeansException, which won't be caught
// here, if there is a critical failure such as no matching field.
// We can attempt to deal only with less serious exceptions.
setPropertyValue(pv);
}
catch (NotWritablePropertyException ex) {
if (!ignoreUnknown) {
throw ex;
}
// Otherwise, just ignore it and continue...
}
catch (NullValueInNestedPathException ex) {
if (!ignoreInvalid) {
throw ex;
}
// Otherwise, just ignore it and continue...
}
catch (PropertyAccessException ex) {
if (propertyAccessExceptions == null) {
propertyAccessExceptions = new LinkedList();
}
propertyAccessExceptions.add(ex);
}
}
// If we encountered individual exceptions, throw the composite exception.
if (propertyAccessExceptions != null) {
PropertyAccessException[] paeArray =
propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
throw new PropertyBatchUpdateException(paeArray);
}
}
下に追跡すると、beanWrapperが属性値をどう設定しますか?最初のテーマのspringmvcの原理から遠くなります.だからもう下に降りません.以下はbeanWrapperまたはConfigrable PropertyAccess orを得るための経路です.無視できます.
Data Binder萢get PropertyAccess or
protected ConfigurablePropertyAccessor getPropertyAccessor() {
return getInternalBindingResult().getPropertyAccessor();
}
Data Binder菵get Internal BindingResoultprotected AbstractPropertyBindingResult getInternalBindingResult() {
if (this.bindingResult == null) {
initBeanPropertyAccess();
}
return this.bindingResult;
}
Data Binder莻initBenPropertyAccesspublic void initBeanPropertyAccess() {
Assert.state(this.bindingResult == null,
"DataBinder is already initialized - call initBeanPropertyAccess before other configuration methods");
this.bindingResult = new BeanPropertyBindingResult(
getTarget(), getObjectName(), isAutoGrowNestedPaths(), getAutoGrowCollectionLimit());
if (this.conversionService != null) {
this.bindingResult.initConversion(this.conversionService);
}
}
BeanPropertyBindingResult啢get PropertyAccess or/**
* Returns the {@link BeanWrapper} that this instance uses.
* Creates a new one if none existed before.
* @see #createBeanWrapper()
*/
@Override
public final ConfigurablePropertyAccessor getPropertyAccessor() {
if (this.beanWrapper == null) {
this.beanWrapper = createBeanWrapper();
this.beanWrapper.setExtractOldValueForEditor(true);
this.beanWrapper.setAutoGrowNestedPaths(this.autoGrowNestedPaths);
this.beanWrapper.setAutoGrowCollectionLimit(this.autoGrowCollectionLimit);
}
return this.beanWrapper;
}
BenPropertyBindingResoult啢createBenWrapperprotected BeanWrapper createBeanWrapper() {
Assert.state(this.target != null, "Cannot access properties on null bean instance '" + getObjectName() + "'!");
return PropertyAccessorFactory.forBeanPropertyAccess(this.target);
}
PropertyAccess orFactory啝forBenPropertyAccesspublic static BeanWrapper forBeanPropertyAccess(Object target) {
return new BeanWrapperImpl(target);
}
感想:commandバインディングをしないなら、正常なrequest.get Parameeter()、効率はきっとspringmvcのパラメータバインディング効率より高くて、空間的にも比較的少ないメモリを占有します.
時間と空間にはどのような違いがありますか?
Servlet Request Data Binderオブジェクトを作成しました.
MutablePropertyValuesオブジェクトを作成しました.
BenPropertyBindingResoultを作成しました.
Default BindingErrocessorを作成しました.
BenWrapperImplを作成しました.command属性を設定します.
参考:
Validation,Data Binding,and Type Coversion
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html