提交 87f4f6dc authored 作者: 陈世营's avatar 陈世营

【修改】 leaf config

上级 2bc980b1
...@@ -3,6 +3,14 @@ ...@@ -3,6 +3,14 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.timeloit.project</groupId> <groupId>com.timeloit.project</groupId>
...@@ -21,9 +29,13 @@ ...@@ -21,9 +29,13 @@
<commons-beanutils-version>1.9.1</commons-beanutils-version> <commons-beanutils-version>1.9.1</commons-beanutils-version>
<commons-lang3.version>3.4</commons-lang3.version> <commons-lang3.version>3.4</commons-lang3.version>
<javax.inject.version>1</javax.inject.version> <javax.inject.version>1</javax.inject.version>
<reflections.version>0.9.10</reflections.version>
<mybatis-spring-boot-starter.version>2.1.1</mybatis-spring-boot-starter.version>
<guava.version>20.0</guava.version> <guava.version>20.0</guava.version>
<fastjson.version>1.2.41</fastjson.version> <fastjson.version>1.2.41</fastjson.version>
<jackson.version>2.9.10</jackson.version>
<springfox-swagger2.version>2.9.2</springfox-swagger2.version> <springfox-swagger2.version>2.9.2</springfox-swagger2.version>
<commons-io-version>2.2</commons-io-version> <commons-io-version>2.2</commons-io-version>
...@@ -56,13 +68,19 @@ ...@@ -56,13 +68,19 @@
<dependency> <dependency>
<groupId>com.timeloit.project</groupId> <groupId>com.timeloit.project</groupId>
<artifactId>sharding-keygen-leaf</artifactId> <artifactId>sharding-keygen-leaf</artifactId>
<version>1.0-SNAPSHOT</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.timeloit.project</groupId> <groupId>com.timeloit.project</groupId>
<artifactId>loit-keygen-leaf-zk</artifactId> <artifactId>loit-keygen-leaf-zk</artifactId>
<version>1.0-SNAPSHOT</version> <version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.timeloit.project</groupId>
<artifactId>loit-keygen-leaf-config</artifactId>
<version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
...@@ -80,6 +98,13 @@ ...@@ -80,6 +98,13 @@
<version>${mysql-connector-java.version}</version> <version>${mysql-connector-java.version}</version>
</dependency> </dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot-starter.version}</version>
</dependency>
<!--common begin--> <!--common begin-->
<dependency> <dependency>
...@@ -119,6 +144,29 @@ ...@@ -119,6 +144,29 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>${reflections.version}</version>
</dependency>
<!--api--> <!--api-->
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
...@@ -299,6 +347,18 @@ ...@@ -299,6 +347,18 @@
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerVersion>${java.version}</compilerVersion>
</configuration>
</plugin>
</plugins> </plugins>
</pluginManagement> </pluginManagement>
...@@ -307,13 +367,6 @@ ...@@ -307,13 +367,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerVersion>${java.version}</compilerVersion>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>loit-build-component</artifactId>
<groupId>com.timeloit.project</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>loit-keygen-leaf-config</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--分布式ID-->
<dependency>
<groupId>com.timeloit.project</groupId>
<artifactId>loit-keygen-leaf-zk</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
</dependency>
</dependencies>
<build>
<finalName>loit-keygen-leaf-config</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.loit.component.keygen.config;
import com.loit.component.keygen.leaf.LeafSegmentKeyGeneratorFactory;
import com.loit.component.keygen.plugin.AuotIdInterceptor;
import com.sankuai.inf.leaf.IDGen;
import com.sankuai.inf.leaf.common.PropertyFactory;
import com.sankuai.inf.leaf.snowflake.SnowflakeIDGenImpl;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
@Configuration
public class MybatisKeygenConfig {
/**
* leaf-segment-loit-test
*/
@Value("${leaf.namespace}")
private String leafNamespace;
/**
* 127.0.0.1:2181
*/
@Value("${leaf.zkserver.list}")
private String serverList;
@Value("${leaf.segment.id.initial.value}")
private String leafInitialValue;
/**
* 默认2000
*/
@Value("${leaf.segment.step}")
private String leafSegmentStep;
@Value("${server.port}")
private Integer serverPort;
@Value("${spring.application.name}")
private String applicationName;
@Bean
public LeafSegmentKeyGeneratorFactory leafSegmentKeyGeneratorFactory() {
LeafSegmentKeyGeneratorFactory leafSegmentKeyGeneratorFactory = new LeafSegmentKeyGeneratorFactory();
Properties properties = new Properties();
properties.setProperty("leaf.namespace", leafNamespace);
properties.setProperty("server.list", serverList);
properties.setProperty("leaf.segment.id.initial.value", leafInitialValue);
properties.setProperty("leaf.segment.step", leafSegmentStep);
leafSegmentKeyGeneratorFactory.setGlobleProperties(properties);
return leafSegmentKeyGeneratorFactory;
}
@Bean
public IDGen snowflakeIDGen() {
Properties properties = PropertyFactory.getProperties();
properties.setProperty("leaf.zk.list", serverList);
properties.setProperty("leaf.name", "leaf_snowflake_" + applicationName);
IDGen idGen = new SnowflakeIDGenImpl(properties.getProperty("leaf.zk.list"), serverPort);
return idGen;
}
/**
* 插件mybatis id生成 拦截器
*/
@Bean
AuotIdInterceptor autoIdInterceptor() {
return new AuotIdInterceptor();
}
@Bean
ConfigurationCustomizer mybatisConfigurationCustomizer() {
return configuration -> configuration.addInterceptor(autoIdInterceptor());
}
}
package com.loit.component.keygen.plugin;
import com.google.common.base.Predicate;
import com.loit.component.keygen.leaf.LeafSegmentKeyGeneratorFactory;
import com.loit.component.keygen.utils.IdleafApplicationContextHolder;
import com.sankuai.inf.leaf.IDGen;
import com.sankuai.inf.leaf.common.Result;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.reflections.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Description: mybatis ID自增拦截器
*/
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {
MappedStatement.class, Object.class
}),
})
public class AuotIdInterceptor implements Interceptor {
/**
* key值为class对象 value可以理解成是该类带有AutoId注解的属性,只不过对属性封装了一层。
* 它是非常能够提高性能的处理器 它的作用就是不用每一次一个对象经来都要看下它的哪些属性带有AutoId注解
* 毕竟类的反射在性能上并不友好。只要key包含该对象那就不需要检查它哪些属性带AutoId注解。
*/
private Map<Class, List<Handler>> handlerMap = new ConcurrentHashMap<>();
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
//args数组对应对象就是上面@Signature注解中args对应的对应类型
MappedStatement mappedStatement = (MappedStatement) args[0];
//实体对象
Object entity = args[1];
if ("INSERT".equalsIgnoreCase(mappedStatement.getSqlCommandType().name())) {
// 获取实体集合
Set<Object> entitySet = getEntitySet(entity);
// 批量设置id
for (Object object : entitySet) {
process(object);
}
}
return invocation.proceed();
}
/**
* object是需要插入的实体数据,它可能是对象,也可能是批量插入的对象。
* 如果是单个对象,那么object就是当前对象
* 如果是批量插入对象,那么object就是一个map集合,key值为"list",value为ArrayList集合对象
*/
private Set<Object> getEntitySet(Object object) {
//
Set<Object> set = new HashSet<>();
if (object instanceof Map) {
//批量插入对象
Collection values = (Collection) ((Map) object).get("list");
System.out.println("values = " + values);
for (Object value : values) {
if (value instanceof Collection) {
set.addAll((Collection) value);
} else {
set.add(value);
}
}
} else {
//单个插入对象
set.add(object);
}
return set;
}
private void process(Object object) throws Throwable {
Class handlerKey = object.getClass();
String tableName = handlerKey.getName();
List<Handler> handlerList = handlerMap.get(handlerKey);
//TODO 性能优化点,如果有两个都是user对象同时,那么只需有个进行反射处理属性就好了,另一个只需执行下面的for循环
SYNC:
if (handlerList == null) {
synchronized (this) {
handlerList = handlerMap.get(handlerKey);
//如果到这里map集合已经存在,则跳出到指定SYNC标签
if (handlerList != null) {
break SYNC;
}
handlerMap.put(handlerKey, handlerList = new ArrayList<>());
// 反射工具类 获取带有AutoId注解的所有属性字段
Set<Field> allFields = ReflectionUtils.getAllFields(
object.getClass(),
(Predicate<Field>) input -> input != null && input.getAnnotation(AutoId.class) != null
);
for (Field field : allFields) {
AutoId annotation = field.getAnnotation(AutoId.class);
if (annotation.value().equals(AutoId.IdType.LEAF_SEGMENT)) {
handlerList.add(new LeafSegmentHandler(field, tableName));
} else if (annotation.value().equals(AutoId.IdType.LEAF_SNOWFLAKE)) {
handlerList.add(new LeafSnowflakeHandler(field, tableName));
}
}
}
}
for (Handler handler : handlerList) {
handler.accept(object);
}
}
private static abstract class Handler {
Field field;
String tableName;
Handler(Field field, String tableName) {
this.field = field;
this.tableName = tableName;
}
abstract void handle(Field field, Object object) throws Throwable;
private boolean checkField(Object object, Field field) throws IllegalAccessException {
if (!field.isAccessible()) {
field.setAccessible(true);
}
//如果该注解对应的属性已经被赋值,那么就不用通过雪花生成的ID
return field.get(object) == null;
}
public void accept(Object o) throws Throwable {
if (checkField(o, field)) {
handle(field, o);
}
}
}
/**
* Leaf Segment ID
*/
private static class LeafSegmentHandler extends Handler {
LeafSegmentHandler(Field field, String tableName) {
super(field, tableName);
}
@Override
void handle(Field field, Object object) throws Throwable {
LeafSegmentKeyGeneratorFactory leafSegmentKeyGeneratorFactory = IdleafApplicationContextHolder.getBean(LeafSegmentKeyGeneratorFactory.class);
Comparable<?> id = leafSegmentKeyGeneratorFactory.getKeyGenerator(this.tableName).generateKey();
if (field.getType().isAssignableFrom(String.class)) {
field.set(object, String.valueOf(id));
} else if (field.getType().isAssignableFrom(Long.class)) {
field.set(object, id);
}
}
}
/**
* Leaf 雪花ID
*/
private static class LeafSnowflakeHandler extends Handler {
LeafSnowflakeHandler(Field field, String tableName) {
super(field, tableName);
}
@Override
void handle(Field field, Object object) throws Throwable {
IDGen idGen = IdleafApplicationContextHolder.getBean(IDGen.class);
Result result = idGen.get("");
if (field.getType().isAssignableFrom(String.class)) {
field.set(object, String.valueOf(result.getId()));
} else if (field.getType().isAssignableFrom(Long.class)) {
field.set(object, result.getId());
}
}
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
package com.loit.component.keygen.plugin;
import java.lang.annotation.*;
/**
* @Description: 主键注解
* 支持两种主键:leafSegment 和 leafSnowflake
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface AutoId {
/**
* @return id类型(默认为雪花id)
*/
IdType value() default IdType.LEAF_SNOWFLAKE;
/**
* id类型
*/
enum IdType {
/**
* 雪花id
*/
LEAF_SNOWFLAKE,
LEAF_SEGMENT
}
}
package com.loit.component.keygen.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class IdleafApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
synchronized (this) {
if (IdleafApplicationContextHolder.applicationContext == null) {
IdleafApplicationContextHolder.applicationContext = applicationContext;
}
}
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
public static <T> T getBean(String qualifier, Class<T> clazz) {
return applicationContext.getBean(qualifier, clazz);
}
}
\ No newline at end of file
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>${lombok.version}</version> <version>1.18.8</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- zookeeper snowflake-->
<dependency> <dependency>
<groupId>org.apache.curator</groupId> <groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId> <artifactId>curator-framework</artifactId>
...@@ -52,5 +54,28 @@ ...@@ -52,5 +54,28 @@
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
</dependency> </dependency>
<!-- leaf snowflake-->
<dependency>
<groupId>com.sankuai.inf.leaf</groupId>
<artifactId>leaf-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
<build>
<finalName>loit-keygen-leaf-zk</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project> </project>
\ No newline at end of file
package com.loit.component.keygen.leaf;
import com.sankuai.inf.leaf.IDGen;
import com.sankuai.inf.leaf.common.PropertyFactory;
import com.sankuai.inf.leaf.common.Result;
import com.sankuai.inf.leaf.snowflake.SnowflakeIDGenImpl;
import org.junit.Test;
import java.util.Properties;
public class SnowflakeIDGenImplTest {
@Test
public void testGetId() {
Properties properties = PropertyFactory.getProperties();
properties.setProperty("leaf.zk.list", "localhost:2181");
properties.setProperty("leaf.name", "leaf_test");
IDGen idGen = new SnowflakeIDGenImpl(properties.getProperty("leaf.zk.list"), 8080);
for (int i = 1; i < 1000; ++i) {
Result r = idGen.get("a");
System.out.println(r);
}
}
}
...@@ -36,4 +36,15 @@ ...@@ -36,4 +36,15 @@
</dependency> </dependency>
</dependencies> </dependencies>
<build>
<finalName>loit-seata-mybatis-mysql-suport</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project> </project>
\ No newline at end of file
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
<module>loit-component-jetcache-client</module> <module>loit-component-jetcache-client</module>
<module>sharding-keygen-leaf</module> <module>sharding-keygen-leaf</module>
<module>loit-keygen-leaf-zk</module> <module>loit-keygen-leaf-zk</module>
<module>loit-keygen-leaf-config</module>
</modules> </modules>
</project> </project>
\ No newline at end of file
...@@ -23,9 +23,6 @@ ...@@ -23,9 +23,6 @@
<project.build.locale>zh_CN</project.build.locale> <project.build.locale>zh_CN</project.build.locale>
<slf4j.version>1.7.26</slf4j.version> <slf4j.version>1.7.26</slf4j.version>
<jackson.version>2.9.10</jackson.version>
<meituan.leaf.version>1.0.1</meituan.leaf.version> <meituan.leaf.version>1.0.1</meituan.leaf.version>
<mybatis.version>3.3.0</mybatis.version> <mybatis.version>3.3.0</mybatis.version>
...@@ -182,21 +179,6 @@ ...@@ -182,21 +179,6 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
......
...@@ -27,9 +27,20 @@ ...@@ -27,9 +27,20 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>${lombok.version}</version> <version>1.18.8</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build>
<finalName>loit-build-spi-common</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project> </project>
\ No newline at end of file
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>${lombok.version}</version> <version>1.18.8</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
......
...@@ -10,18 +10,15 @@ ...@@ -10,18 +10,15 @@
<module>loit-build-web-common</module> <module>loit-build-web-common</module>
</modules> </modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.timeloit.project</groupId> <groupId>com.timeloit.project</groupId>
<artifactId>loit-build-common</artifactId> <artifactId>loit-build-common</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
...@@ -34,6 +31,25 @@ ...@@ -34,6 +31,25 @@
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<distributionManagement> <distributionManagement>
<repository> <repository>
<id>nexus-releases</id> <id>nexus-releases</id>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论