国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - JAVA教程 - spring boot tomcat jdbc pool的屬性綁定

spring boot tomcat jdbc pool的屬性綁定

2021-03-29 09:58go4it JAVA教程

這篇文章主要介紹了spring boot tomcat jdbc pool的屬性綁定的相關資料,非常不錯,具有參考借鑒價值,需要的朋友參考下

下面看下spring boot tomcat jdbc pool的屬性綁定代碼,具體代碼如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
 datasource:
 type: org.apache.tomcat.jdbc.pool.DataSource
 driver-class-name: org.postgresql.Driver
 url: jdbc:postgresql://192.168.99.100:5432/postgres?connectTimeout=6000&socketTimeout=6000
 username: postgres
 password: postgres
 jmx-enabled: true
 initial-size: 1
 max-active: 5
 ## when pool sweeper is enabled, extra idle connection will be closed
 max-idle: 5
 ## when idle connection > min-idle, poolSweeper will start to close
 min-idle: 1

使用如上配置,最后發現initial-size,max-active,max-idle,min-idle等配置均無效,生成的tomcat jdbc datasource還是使用的默認的配置

正確配置

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spring:
 datasource:
 type: org.apache.tomcat.jdbc.pool.DataSource
 driver-class-name: org.postgresql.Driver
 url: jdbc:postgresql://192.168.99.100:5432/postgres?connectTimeout=6000&socketTimeout=6000
 username: postgres
 password: postgres
 jmx-enabled: true
 tomcat: ## 單個數據庫連接池,而且得寫上tomcat的屬性配置才可以生效
  initial-size: 1
  max-active: 5
  ## when pool sweeper is enabled, extra idle connection will be closed
  max-idle: 5
  ## when idle connection > min-idle, poolSweeper will start to close
  min-idle: 1

注意,這里把具體tomcat數據庫連接池的配置屬性放到了spring.datasource.tomcat屬性下面,這樣才可以生效。

源碼解析

?
1
2
3
4
5
6
7
8
9
10
spring-boot-autoconfigure-1.5.9.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java
@Configuration
 @Conditional(PooledDataSourceCondition.class)
 @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
 @Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class,
 DataSourceConfiguration.Dbcp.class, DataSourceConfiguration.Dbcp2.class,
 DataSourceConfiguration.Generic.class })
 @SuppressWarnings("deprecation")
 protected static class PooledDataSourceConfiguration {
 }

DataSourceConfiguration.Tomcat

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
spring-boot-autoconfigure-1.5.9.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java
/**
 * Tomcat Pool DataSource configuration.
 */
 @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
 @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true)
 static class Tomcat extends DataSourceConfiguration {
 @Bean
 @ConfigurationProperties(prefix = "spring.datasource.tomcat")
 public org.apache.tomcat.jdbc.pool.DataSource dataSource(
 DataSourceProperties properties) {
 org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(
  properties, org.apache.tomcat.jdbc.pool.DataSource.class);
 DatabaseDriver databaseDriver = DatabaseDriver
  .fromJdbcUrl(properties.determineUrl());
 String validationQuery = databaseDriver.getValidationQuery();
 if (validationQuery != null) {
 dataSource.setTestOnBorrow(true);
 dataSource.setValidationQuery(validationQuery);
 }
 return dataSource;
 }
 }

可以看到這里的DataSourceProperties僅僅只有spring.datasource直接屬性的配置,比如url,username,password,driverClassName。tomcat的具體屬性都沒有。

createDataSource

?
1
2
3
4
protected <T> T createDataSource(DataSourceProperties properties,
 Class<? extends DataSource> type) {
 return (T) properties.initializeDataSourceBuilder().type(type).build();
 }

直接createDataSource出來的org.apache.tomcat.jdbc.pool.DataSource的PoolProperties也是默認的配置

ConfigurationProperties

具體的魔力就在于@ConfigurationProperties(prefix = "spring.datasource.tomcat")這段代碼,它在spring容器構造好代理bean返回之前會將spring.datasource.tomcat指定的屬性設置到org.apache.tomcat.jdbc.pool.DataSource

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java
private void postProcessBeforeInitialization(Object bean, String beanName,
 ConfigurationProperties annotation) {
 Object target = bean;
 PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<Object>(
 target);
 factory.setPropertySources(this.propertySources);
 factory.setValidator(determineValidator(bean));
 // If no explicit conversion service is provided we add one so that (at least)
 // comma-separated arrays of convertibles can be bound automatically
 factory.setConversionService(this.conversionService == null
 ? getDefaultConversionService() : this.conversionService);
 if (annotation != null) {
 factory.setIgnoreInvalidFields(annotation.ignoreInvalidFields());
 factory.setIgnoreUnknownFields(annotation.ignoreUnknownFields());
 factory.setExceptionIfInvalid(annotation.exceptionIfInvalid());
 factory.setIgnoreNestedProperties(annotation.ignoreNestedProperties());
 if (StringUtils.hasLength(annotation.prefix())) {
 factory.setTargetName(annotation.prefix());
 }
 }
 try {
 factory.bindPropertiesToTarget();
 }
 catch (Exception ex) {
 String targetClass = ClassUtils.getShortName(target.getClass());
 throw new BeanCreationException(beanName, "Could not bind properties to "
  + targetClass + " (" + getAnnotationDetails(annotation) + ")", ex);
 }
 }

注意,這里的annotation就是@ConfigurationProperties(prefix = "spring.datasource.tomcat"),它的prefix是spring.datasource.tomcat PropertiesConfigurationFactory的targetName就是spring.datasource.tomcat

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
PropertiesConfigurationFactory.bindPropertiesToTarget
spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/bind/PropertiesConfigurationFactory.java
public void bindPropertiesToTarget() throws BindException {
 Assert.state(this.propertySources != null, "PropertySources should not be null");
 try {
 if (logger.isTraceEnabled()) {
 logger.trace("Property Sources: " + this.propertySources);
 }
 this.hasBeenBound = true;
 doBindPropertiesToTarget();
 }
 catch (BindException ex) {
 if (this.exceptionIfInvalid) {
 throw ex;
 }
 PropertiesConfigurationFactory.logger
  .error("Failed to load Properties validation bean. "
  + "Your Properties may be invalid.", ex);
 }
 }

委托給doBindPropertiesToTarget方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
PropertiesConfigurationFactory.doBindPropertiesToTarget
private void doBindPropertiesToTarget() throws BindException {
 RelaxedDataBinder dataBinder = (this.targetName != null
 ? new RelaxedDataBinder(this.target, this.targetName)
 : new RelaxedDataBinder(this.target));
 if (this.validator != null
 && this.validator.supports(dataBinder.getTarget().getClass())) {
 dataBinder.setValidator(this.validator);
 }
 if (this.conversionService != null) {
 dataBinder.setConversionService(this.conversionService);
 }
 dataBinder.setAutoGrowCollectionLimit(Integer.MAX_VALUE);
 dataBinder.setIgnoreNestedProperties(this.ignoreNestedProperties);
 dataBinder.setIgnoreInvalidFields(this.ignoreInvalidFields);
 dataBinder.setIgnoreUnknownFields(this.ignoreUnknownFields);
 customizeBinder(dataBinder);
 Iterable<String> relaxedTargetNames = getRelaxedTargetNames();
 Set<String> names = getNames(relaxedTargetNames);
 PropertyValues propertyValues = getPropertySourcesPropertyValues(names,
 relaxedTargetNames);
 dataBinder.bind(propertyValues);
 if (this.validator != null) {
 dataBinder.validate();
 }
 checkForBindingErrors(dataBinder);
 }

這里借助RelaxedDataBinder.bind方法

?
1
2
3
4
5
getRelaxedTargetNames
private Iterable<String> getRelaxedTargetNames() {
 return (this.target != null && StringUtils.hasLength(this.targetName)
 ? new RelaxedNames(this.targetName) : null);
 }

這里new了一個RelaxedNames,可以識別多個變量的變種

RelaxedNames

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/bind/RelaxedNames.java
private void initialize(String name, Set<String> values) {
 if (values.contains(name)) {
 return;
 }
 for (Variation variation : Variation.values()) {
 for (Manipulation manipulation : Manipulation.values()) {
 String result = name;
 result = manipulation.apply(result);
 result = variation.apply(result);
 values.add(result);
 initialize(result, values);
 }
 }
 }
 /**
 * Name variations.
 */
 enum Variation {
 NONE {
 @Override
 public String apply(String value) {
 return value;
 }
 },
 LOWERCASE {
 @Override
 public String apply(String value) {
 return value.isEmpty() ? value : value.toLowerCase();
 }
 },
 UPPERCASE {
 @Override
 public String apply(String value) {
 return value.isEmpty() ? value : value.toUpperCase();
 }
 };
 public abstract String apply(String value);
 }

即支持org.springframework.boot.bind.RelaxedNames@6ef81f31[name=spring.datasource.tomcat,values=[spring.datasource.tomcat, spring_datasource_tomcat, springDatasourceTomcat, springdatasourcetomcat, SPRING.DATASOURCE.TOMCAT, SPRING_DATASOURCE_TOMCAT, SPRINGDATASOURCETOMCAT]]這7中配置的寫法

?
1
2
3
4
5
6
7
8
getPropertySourcesPropertyValues
private PropertyValues getPropertySourcesPropertyValues(Set<String> names,
 Iterable<String> relaxedTargetNames) {
 PropertyNamePatternsMatcher includes = getPropertyNamePatternsMatcher(names,
 relaxedTargetNames);
 return new PropertySourcesPropertyValues(this.propertySources, names, includes,
 this.resolvePlaceholders);
 }

這個方法會把spring.datasource.tomact底下的屬性配置拉取到PropertyValues對象里頭

RelaxedDataBinder.bind

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/bind/RelaxedDataBinder.java的bind方法調用的是父類的方法 spring-context-4.3.13.RELEASE-sources.jar!/org/springframework/validation/DataBinder.java
/**
 * Bind the given property values to this binder's target.
 * <p>This call can create field errors, representing basic binding
 * errors like a required field (code "required"), or type mismatch
 * between value and bean property (code "typeMismatch").
 * <p>Note that the given PropertyValues should be a throwaway instance:
 * For efficiency, it will be modified to just contain allowed fields if it
 * implements the MutablePropertyValues interface; else, an internal mutable
 * copy will be created for this purpose. Pass in a copy of the PropertyValues
 * if you want your original instance to stay unmodified in any case.
 * @param pvs property values to bind
 * @see #doBind(org.springframework.beans.MutablePropertyValues)
 */
 public void bind(PropertyValues pvs) {
 MutablePropertyValues mpvs = (pvs instanceof MutablePropertyValues) ?
 (MutablePropertyValues) pvs : new MutablePropertyValues(pvs);
 doBind(mpvs);
 }
 /**
 * 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) {
 checkAllowedFields(mpvs);
 checkRequiredFields(mpvs);
 applyPropertyValues(mpvs);
 }
 /**
 * Apply given property values to the target object.
 * <p>Default implementation applies all of the supplied property
 * values as bean property values. By default, unknown fields will
 * be ignored.
 * @param mpvs the property values to be bound (can be modified)
 * @see #getTarget
 * @see #getPropertyAccessor
 * @see #isIgnoreUnknownFields
 * @see #getBindingErrorProcessor
 * @see BindingErrorProcessor#processPropertyAccessException
 */
 protected void applyPropertyValues(MutablePropertyValues mpvs) {
 try {
 // 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());
 }
 }
 }
 /**
 * Return the underlying PropertyAccessor of this binder's BindingResult.
 */
 protected ConfigurablePropertyAccessor getPropertyAccessor() {
 return getInternalBindingResult().getPropertyAccessor();
 }

最后通過getPropertyAccessor()來設置,這個propertyAccessor就是org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanWrapper: wrapping object [org.apache.tomcat.jdbc.pool.DataSource@6a84bc2a],也就包裝的org.apache.tomcat.jdbc.pool.DataSource

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
AbstractPropertyAccessor.setPropertyValues
spring-beans-4.3.13.RELEASE-sources.jar!/org/springframework/beans/AbstractPropertyAccessor.java
@Override
 public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
 throws BeansException {
 List<PropertyAccessException> propertyAccessExceptions = null;
 List<PropertyValue> 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<PropertyAccessException>();
 }
 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);
 }
 }
 @Override
 public void setPropertyValue(PropertyValue pv) throws BeansException {
 PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
 if (tokens == null) {
 String propertyName = pv.getName();
 AbstractNestablePropertyAccessor nestedPa;
 try {
 nestedPa = getPropertyAccessorForPropertyPath(propertyName);
 }
 catch (NotReadablePropertyException ex) {
 throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
  "Nested property in path '" + propertyName + "' does not exist", ex);
 }
 tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
 if (nestedPa == this) {
 pv.getOriginalPropertyValue().resolvedTokens = tokens;
 }
 nestedPa.setPropertyValue(tokens, pv);
 }
 else {
 setPropertyValue(tokens, pv);
 }
 }

這里的nestedPa.setPropertyValue(tokens, pv);真正把spring.datasource.tomcat的屬性值設置進去 這里的nestedPa就是org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanWrapper: wrapping object [org.apache.tomcat.jdbc.pool.DataSource@6a84bc2a] 最后是調用AbstractNestablePropertyAccessor.processLocalProperty

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
AbstractNestablePropertyAccessor.processLocalProperty
spring-beans-4.3.13.RELEASE-sources.jar!/org/springframework/beans/AbstractNestablePropertyAccessor.java
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
 PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
 if (ph == null || !ph.isWritable()) {
 if (pv.isOptional()) {
 if (logger.isDebugEnabled()) {
  logger.debug("Ignoring optional value for property '" + tokens.actualName +
  "' - property not found on bean class [" + getRootClass().getName() + "]");
 }
 return;
 }
 else {
 throw createNotWritablePropertyException(tokens.canonicalName);
 }
 }
 Object oldValue = null;
 try {
 Object originalValue = pv.getValue();
 Object valueToApply = originalValue;
 if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
 if (pv.isConverted()) {
  valueToApply = pv.getConvertedValue();
 }
 else {
  if (isExtractOldValueForEditor() && ph.isReadable()) {
  try {
  oldValue = ph.getValue();
  }
  catch (Exception ex) {
  if (ex instanceof PrivilegedActionException) {
  ex = ((PrivilegedActionException) ex).getException();
  }
  if (logger.isDebugEnabled()) {
  logger.debug("Could not read previous value of property '" +
   this.nestedPath + tokens.canonicalName + "'", ex);
  }
  }
  }
  valueToApply = convertForProperty(
  tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
 }
 pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
 }
 ph.setValue(this.wrappedObject, valueToApply);
 }
 catch (TypeMismatchException ex) {
 throw ex;
 }
 catch (InvocationTargetException ex) {
 PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(
  this.rootObject, this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
 if (ex.getTargetException() instanceof ClassCastException) {
 throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException());
 }
 else {
 Throwable cause = ex.getTargetException();
 if (cause instanceof UndeclaredThrowableException) {
  // May happen e.g. with Groovy-generated methods
  cause = cause.getCause();
 }
 throw new MethodInvocationException(propertyChangeEvent, cause);
 }
 }
 catch (Exception ex) {
 PropertyChangeEvent pce = new PropertyChangeEvent(
  this.rootObject, this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
 throw new MethodInvocationException(pce, ex);
 }
 }

它使其是使用class org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler來設置

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
BeanWrapperImpl$BeanPropertyHandler.setValue
spring-beans-4.3.13.RELEASE-sources.jar!/org/springframework/beans/BeanWrapperImpl.java
@Override
 public void setValue(final Object object, Object valueToApply) throws Exception {
 final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
  ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
  this.pd.getWriteMethod());
 if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
 if (System.getSecurityManager() != null) {
  AccessController.doPrivileged(new PrivilegedAction<Object>() {
  @Override
  public Object run() {
  writeMethod.setAccessible(true);
  return null;
  }
  });
 }
 else {
  writeMethod.setAccessible(true);
 }
 }
 final Object value = valueToApply;
 if (System.getSecurityManager() != null) {
 try {
  AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
  @Override
  public Object run() throws Exception {
  writeMethod.invoke(object, value);
  return null;
  }
  }, acc);
 }
 catch (PrivilegedActionException ex) {
  throw ex.getException();
 }
 }
 else {
 writeMethod.invoke(getWrappedInstance(), value);
 }
 }
 }

這里利用反射找出setXXX方法( 比如setMaxActive ),然后設置進去

多數據源的配置

上面的配置對于單數據源來說是沒有問題的,對于多數據源,則配置如下

?
1
2
3
4
5
6
7
8
9
@Configuration
public class MasterDatasourceConfig {
 
 @Bean("masterDataSource")
 @ConfigurationProperties(prefix = "spring.datasource.master")
 public DataSource masterDataSource() {
  return DataSourceBuilder.create().build();
 }
}

注意,這里要添加ConfigurationProperties注入tomcat jdbc pool的額外設置

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
spring:
 datasource:
 master:
  type: org.apache.tomcat.jdbc.pool.DataSource
  driver-class-name: org.postgresql.Driver
  url: jdbc:postgresql://192.168.99.100:5432/postgres?connectTimeout=6000&socketTimeout=6000
  username: postgres
  password: postgres
  jmx-enabled: true
# tomcat: ## 多數據源的話,這里要去掉tomcat,通通放在數據源前綴下面
  initial-size: 1
  max-active: 5
  ## when pool sweeper is enabled, extra idle connection will be closed
  max-idle: 5
  ## when idle connection > min-idle, poolSweeper will start to close
  min-idle: 1

原先tomcat的配置都要放在數據源前綴的底下,放在spring.datasource.tomcat或者spring.datasource.master.tomcat底下均無法生效。

原文鏈接:https://juejin.im/post/5a6eb0f5518825733c144ff4

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 99看| 欧美福利在线 | 欧美成在线观看 | 99精品欧美一区二区三区综合在线 | 亚洲视频一区二区 | 国产午夜精品久久久久久久 | 亚洲视频在线观看 | 欧美自拍一区 | 久久精品国产一区二区三区 | 国产中文字幕在线 | 欧美成年黄网站色视频 | 国产欧美日韩一级大片 | 国产在线观看一区二区三区 | 亚洲乱码一区二区三区在线观看 | 欧美三区 | 精品久久久久久国产 | 国产视频一区二区 | 亚洲高清视频在线观看 | 精品国产一二三区 | 精久久| 在线免费观看色视频 | 中文色视频 | 亚洲精品一区二区三区在线 | 国产精品久久久久国产a级 国产免费久久 | 国产精品色哟哟哟 | 91免费观看视频 | 春色导航 | av网站网址 | 天堂av在线免费观看 | 丁香婷婷综合激情五月色 | 亚洲精品一区二区在线 | 久久久国产一区二区三区 | 国产一区二区免费 | 男女全黄一级一级高潮免费看 | 韩国毛片在线 | 在线精品国产一区二区三区 | 免费观看av网站 | 日韩欧美在线免费观看 | 欧美 日韩 国产 成人 在线 | www.91福利 | 日本免费一区二区三区四区 |