本文目录导读:

我来提供一个完整的Java代码生成器实现案例,包含数据库表结构解析、模板渲染和代码生成功能。
项目结构
code-generator/
├── pom.xml
├── src/main/java/com/example/generator/
│ ├── GeneratorApplication.java
│ ├── config/
│ │ └── GeneratorConfig.java
│ ├── model/
│ │ ├── TableInfo.java
│ │ ├── ColumnInfo.java
│ │ └── GeneratorConfig.java
│ ├── parser/
│ │ └── DatabaseParser.java
│ ├── generator/
│ │ ├── CodeGenerator.java
│ │ └── TemplateEngine.java
│ └── utils/
│ └── NamingUtils.java
└── src/main/resources/
├── application.yml
└── templates/
├── entity.ftl
├── mapper.ftl
├── service.ftl
└── controller.ftl
Maven依赖配置
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<groupId>com.example</groupId>
<artifactId>code-generator</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!-- Freemarker模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
数据模型类
// TableInfo.java
package com.example.generator.model;
import lombok.Data;
import java.util.List;
@Data
public class TableInfo {
private String tableName; // 表名
private String entityName; // 实体类名
private String entityVariableName; // 实体变量名
private String comment; // 表注释
private List<ColumnInfo> columns; // 列信息集合
}
// ColumnInfo.java
package com.example.generator.model;
import lombok.Data;
@Data
public class ColumnInfo {
private String columnName; // 列名
private String dataType; // JDBC类型
private String columnComment; // 列注释
private boolean primaryKey; // 是否主键
private boolean autoIncrement; // 是否自增
private String javaProperty; // Java属性名
private String javaType; // Java类型
private String javaPackage; // Java类型包名
private boolean nullable; // 是否可空
private Integer columnSize; // 列大小
private Integer decimalDigits; // 小数位数
}
数据库解析器
// DatabaseParser.java
package com.example.generator.parser;
import com.example.generator.model.ColumnInfo;
import com.example.generator.model.TableInfo;
import com.example.generator.utils.NamingUtils;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class DatabaseParser {
private final String url;
private final String username;
private final String password;
public DatabaseParser(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
}
/**
* 获取所有表信息
*/
public List<TableInfo> getTables(String databaseName, String tablePrefix) throws SQLException {
List<TableInfo> tables = new ArrayList<>();
try (Connection conn = DriverManager.getConnection(url, username, password)) {
DatabaseMetaData metaData = conn.getMetaData();
// 获取表信息
ResultSet rs = metaData.getTables(databaseName, null, tablePrefix + "%",
new String[]{"TABLE"});
while (rs.next()) {
String tableName = rs.getString("TABLE_NAME");
String tableComment = rs.getString("REMARKS");
TableInfo table = new TableInfo();
table.setTableName(tableName);
table.setComment(tableComment);
table.setEntityName(NamingUtils.tableNameToClassName(tableName));
table.setEntityVariableName(NamingUtils.tableNameToVariableName(tableName));
// 获取列信息
table.setColumns(getColumns(conn, databaseName, tableName));
tables.add(table);
}
}
return tables;
}
/**
* 获取表的列信息
*/
private List<ColumnInfo> getColumns(Connection conn, String databaseName,
String tableName) throws SQLException {
List<ColumnInfo> columns = new ArrayList<>();
DatabaseMetaData metaData = conn.getMetaData();
// 获取主键信息
ResultSet pkRs = metaData.getPrimaryKeys(databaseName, null, tableName);
List<String> primaryKeys = new ArrayList<>();
while (pkRs.next()) {
primaryKeys.add(pkRs.getString("COLUMN_NAME"));
}
pkRs.close();
// 获取列信息
ResultSet rs = metaData.getColumns(databaseName, null, tableName, null);
while (rs.next()) {
ColumnInfo column = new ColumnInfo();
column.setColumnName(rs.getString("COLUMN_NAME"));
column.setDataType(rs.getString("TYPE_NAME"));
column.setColumnComment(rs.getString("REMARKS"));
column.setNullable(rs.getInt("NULLABLE") == DatabaseMetaData.columnNullable);
column.setColumnSize(rs.getInt("COLUMN_SIZE"));
column.setDecimalDigits(rs.getInt("DECIMAL_DIGITS"));
column.setPrimaryKey(primaryKeys.contains(column.getColumnName()));
column.setAutoIncrement("YES".equals(rs.getString("IS_AUTOINCREMENT")));
// 转换为Java类型
column.setJavaProperty(NamingUtils.columnNameToProperty(column.getColumnName()));
SqlTypeConvertor.convert(column);
columns.add(column);
}
rs.close();
return columns;
}
}
// SqlTypeConvertor.java - 类型转换器
package com.example.generator.parser;
import com.example.generator.model.ColumnInfo;
public class SqlTypeConvertor {
public static void convert(ColumnInfo column) {
String dataType = column.getDataType().toUpperCase();
switch (dataType) {
case "BIGINT":
case "LONG":
column.setJavaType("Long");
column.setJavaPackage("java.lang");
break;
case "INT":
case "INTEGER":
case "MEDIUMINT":
column.setJavaType("Integer");
column.setJavaPackage("java.lang");
break;
case "SMALLINT":
case "TINYINT":
column.setJavaType("Integer");
column.setJavaPackage("java.lang");
break;
case "VARCHAR":
case "CHAR":
case "TEXT":
case "LONGTEXT":
case "MEDIUMTEXT":
case "TINYTEXT":
column.setJavaType("String");
column.setJavaPackage("java.lang");
break;
case "DATE":
case "DATETIME":
case "TIMESTAMP":
case "TIME":
column.setJavaType("Date");
column.setJavaPackage("java.util");
break;
case "DECIMAL":
case "NUMERIC":
column.setJavaType("BigDecimal");
column.setJavaPackage("java.math");
break;
case "DOUBLE":
case "FLOAT":
column.setJavaType("Double");
column.setJavaPackage("java.lang");
break;
case "BOOLEAN":
case "BIT":
column.setJavaType("Boolean");
column.setJavaPackage("java.lang");
break;
default:
column.setJavaType("Object");
column.setJavaPackage("java.lang");
break;
}
}
}
命名工具类
// NamingUtils.java
package com.example.generator.utils;
public class NamingUtils {
/**
* 表名转类名 (user_info -> UserInfo)
*/
public static String tableNameToClassName(String tableName) {
StringBuilder result = new StringBuilder();
boolean upper = true;
for (char c : tableName.toCharArray()) {
if (c == '_' || c == '-') {
upper = true;
} else if (upper) {
result.append(Character.toUpperCase(c));
upper = false;
} else {
result.append(c);
}
}
return result.toString();
}
/**
* 表名转变量名 (user_info -> userInfo)
*/
public static String tableNameToVariableName(String tableName) {
String className = tableNameToClassName(tableName);
if (className.isEmpty()) {
return className;
}
return Character.toLowerCase(className.charAt(0)) + className.substring(1);
}
/**
* 列名转属性名 (user_name -> userName)
*/
public static String columnNameToProperty(String columnName) {
StringBuilder result = new StringBuilder();
boolean upper = false;
for (char c : columnName.toCharArray()) {
if (c == '_' || c == '-') {
upper = true;
} else if (upper) {
result.append(Character.toUpperCase(c));
upper = false;
} else {
result.append(c);
}
}
return result.toString();
}
/**
* 首字母大写
*/
public static String capitalize(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return Character.toUpperCase(str.charAt(0)) + str.substring(1);
}
/**
* 首字母小写
*/
public static String decapitalize(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return Character.toLowerCase(str.charAt(0)) + str.substring(1);
}
/**
* 将属性名转为下划线命名
*/
public static String propertyToUnderscore(String property) {
StringBuilder result = new StringBuilder();
for (char c : property.toCharArray()) {
if (Character.isUpperCase(c)) {
if (result.length() > 0) {
result.append('_');
}
result.append(Character.toLowerCase(c));
} else {
result.append(c);
}
}
return result.toString();
}
}
代码生成器核心
// CodeGenerator.java
package com.example.generator.generator;
import com.example.generator.model.TableInfo;
import com.example.generator.parser.DatabaseParser;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CodeGenerator {
private final DatabaseParser databaseParser;
private final Configuration configuration;
private final GeneratorConfig config;
public CodeGenerator(GeneratorConfig config) {
this.config = config;
this.databaseParser = new DatabaseParser(config.getUrl(),
config.getUsername(),
config.getPassword());
this.configuration = initFreeMarker();
}
/**
* 初始化FreeMarker配置
*/
private Configuration initFreeMarker() {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
cfg.setClassLoaderForTemplateLoading(getClass().getClassLoader(),
"templates");
cfg.setDefaultEncoding("UTF-8");
return cfg;
}
/**
* 生成所有代码
*/
public void generateAll() throws SQLException, IOException, TemplateException {
List<TableInfo> tables = databaseParser.getTables(config.getDatabaseName(),
config.getTablePrefix());
for (TableInfo table : tables) {
generateEntity(table);
generateMapper(table);
generateService(table);
generateController(table);
System.out.println("生成成功: " + table.getEntityName());
}
}
/**
* 生成实体类
*/
private void generateEntity(TableInfo table) throws IOException, TemplateException {
Map<String, Object> data = new HashMap<>();
data.put("table", table);
data.put("packageName", config.getEntityPackage());
data.put("imports", getImports(table));
Template template = configuration.getTemplate("entity.ftl");
renderTemplate(template, data, config.getEntityPath(),
table.getEntityName() + ".java");
}
/**
* 生成Mapper接口
*/
private void generateMapper(TableInfo table) throws IOException, TemplateException {
Map<String, Object> data = new HashMap<>();
data.put("table", table);
data.put("packageName", config.getMapperPackage());
data.put("entityPackage", config.getEntityPackage());
Template template = configuration.getTemplate("mapper.ftl");
renderTemplate(template, data, config.getMapperPath(),
table.getEntityName() + "Mapper.java");
}
/**
* 生成Service
*/
private void generateService(TableInfo table) throws IOException, TemplateException {
Map<String, Object> data = new HashMap<>();
data.put("table", table);
data.put("packageName", config.getServicePackage());
data.put("entityPackage", config.getEntityPackage());
data.put("mapperPackage", config.getMapperPackage());
Template template = configuration.getTemplate("service.ftl");
renderTemplate(template, data, config.getServicePath(),
table.getEntityName() + "Service.java");
}
/**
* 生成Controller
*/
private void generateController(TableInfo table) throws IOException, TemplateException {
Map<String, Object> data = new HashMap<>();
data.put("table", table);
data.put("packageName", config.getControllerPackage());
data.put("entityPackage", config.getEntityPackage());
data.put("servicePackage", config.getServicePackage());
Template template = configuration.getTemplate("controller.ftl");
renderTemplate(template, data, config.getControllerPath(),
table.getEntityName() + "Controller.java");
}
/**
* 渲染模板并输出文件
*/
private void renderTemplate(Template template, Map<String, Object> data,
String outputPath, String fileName)
throws IOException, TemplateException {
File dir = new File(outputPath);
if (!dir.exists()) {
dir.mkdirs();
}
File outputFile = new File(dir, fileName);
try (FileWriter writer = new FileWriter(outputFile)) {
template.process(data, writer);
}
}
/**
* 获取实体类需要的import
*/
private String getImports(TableInfo table) {
StringBuilder imports = new StringBuilder();
for (ColumnInfo column : table.getColumns()) {
if (!"java.lang".equals(column.getJavaPackage())) {
imports.append("import ").append(column.getJavaPackage())
.append(".").append(column.getJavaType()).append(";\n");
}
}
return imports.toString();
}
}
配置类
// GeneratorConfig.java
package com.example.generator.generator;
import lombok.Data;
@Data
public class GeneratorConfig {
// 数据库配置
private String url;
private String username;
private String password;
private String databaseName;
private String tablePrefix;
// 包名配置
private String entityPackage;
private String mapperPackage;
private String servicePackage;
private String controllerPackage;
// 输出路径配置
private String entityPath;
private String mapperPath;
private String servicePath;
private String controllerPath;
}
Freemarker模板
<!-- entity.ftl -->
package ${packageName};
import lombok.Data;
import com.baomidou.mybatisplus.annotation.*;
${imports}
/**
* ${table.comment!''}实体类
*/
@Data
@TableName("${table.tableName}")
public class ${table.entityName} {
<#list table.columns as column>
<#if column.comment?? && column.comment?length gt 0>
/**
* ${column.comment}
*/
</#if>
<#if column.primaryKey>
@TableId(value = "${column.columnName}", type = IdType.AUTO)
<#else>
@TableField("${column.columnName}")
</#if>
private ${column.javaType} ${column.javaProperty};
</#list>
}
<!-- mapper.ftl -->
package ${packageName};
import ${entityPackage}.${table.entityName};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* ${table.comment!''}Mapper接口
*/
@Mapper
public interface ${table.entityName}Mapper extends BaseMapper<${table.entityName}> {
}
<!-- service.ftl -->
package ${packageName};
import ${entityPackage}.${table.entityName};
import ${mapperPackage}.${table.entityName}Mapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* ${table.comment!''}Service实现类
*/
@Service
public class ${table.entityName}Service extends ServiceImpl<${table.entityName}Mapper, ${table.entityName}> {
}
<!-- controller.ftl -->
package ${packageName};
import ${entityPackage}.${table.entityName};
import ${servicePackage}.${table.entityName}Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* ${table.comment!''}控制器
*/
@RestController
@RequestMapping("/api/${table.entityVariableName}")
public class ${table.entityName}Controller {
@Autowired
private ${table.entityName}Service ${table.entityVariableName}Service;
/**
* 获取列表
*/
@GetMapping("/list")
public List<${table.entityName}> list() {
return ${table.entityVariableName}Service.list();
}
/**
* 获取详情
*/
@GetMapping("/{id}")
public ${table.entityName} getById(@PathVariable Long id) {
return ${table.entityVariableName}Service.getById(id);
}
/**
* 新增
*/
@PostMapping
public boolean save(@RequestBody ${table.entityName} entity) {
return ${table.entityVariableName}Service.save(entity);
}
/**
* 更新
*/
@PutMapping
public boolean update(@RequestBody ${table.entityName} entity) {
return ${table.entityVariableName}Service.updateById(entity);
}
/**
* 删除
*/
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Long id) {
return ${table.entityVariableName}Service.removeById(id);
}
}
启动类
// Main.java
package com.example.generator;
import com.example.generator.generator.CodeGenerator;
import com.example.generator.generator.GeneratorConfig;
public class Main {
public static void main(String[] args) {
// 创建配置
GeneratorConfig config = new GeneratorConfig();
// 数据库配置
config.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8");
config.setUsername("root");
config.setPassword("123456");
config.setDatabaseName("test");
config.setTablePrefix("sys_");
// 包名配置
config.setEntityPackage("com.example.demo.entity");
config.setMapperPackage("com.example.demo.mapper");
config.setServicePackage("com.example.demo.service");
config.setControllerPackage("com.example.demo.controller");
// 输出路径配置
String basePath = System.getProperty("user.dir") + "/src/main/java/com/example/demo";
config.setEntityPath(basePath + "/entity");
config.setMapperPath(basePath + "/mapper");
config.setServicePath(basePath + "/service");
config.setControllerPath(basePath + "/controller");
try {
// 执行代码生成
CodeGenerator generator = new CodeGenerator(config);
generator.generateAll();
System.out.println("代码生成完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
高级特性扩展
// 支持自定义模板
public void generateCustomCode(TableInfo table, String templateName,
String outputPath, Map<String, Object> extraData)
throws IOException, TemplateException {
Map<String, Object> data = new HashMap<>();
data.put("table", table);
data.putAll(extraData);
Template template = configuration.getTemplate(templateName);
renderTemplate(template, data, outputPath,
table.getEntityName() + "Custom.java");
}
// 支持批量生成SQL脚本
public List<String> generateCreateTableSQL(TableInfo table) {
List<String> sqls = new ArrayList<>();
StringBuilder sql = new StringBuilder();
sql.append("CREATE TABLE ").append(table.getTableName()).append(" (");
for (ColumnInfo column : table.getColumns()) {
sql.append("\n ").append(column.getColumnName()).append(" ")
.append(column.getDataType());
if (!column.isNullable()) {
sql.append(" NOT NULL");
}
if (column.isAutoIncrement()) {
sql.append(" AUTO_INCREMENT");
}
sql.append(",");
}
// 添加主键
sql.append("\n PRIMARY KEY (");
table.getColumns().stream()
.filter(ColumnInfo::isPrimaryKey)
.forEach(c -> sql.append(c.getColumnName()).append(","));
sql.deleteCharAt(sql.length() - 1);
sql.append(")");
sql.append("\n)");
sqls.add(sql.toString());
return sqls;
}
这个代码生成器案例包含了完整的数据库表结构解析、类型转换、模板渲染和代码生成功能,支持生成实体类、Mapper、Service和Controller等常用代码,使用时只需要修改配置信息即可快速生成项目基础代码,大大提高开发效率。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播