本文目录导读:

我将为您设计一个完整的Java评论系统案例,包含前端展示、后端服务、数据库设计和核心功能实现。
系统架构设计
评论系统架构
├── Controller层 - 接收HTTP请求
├── Service层 - 业务逻辑处理
├── DAO层 - 数据访问
├── Entity层 - 实体对象
└── 数据库 - MySQL
完整代码实现
1 实体类
// Comment.java - 评论实体
package com.example.commentsystem.entity;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class Comment {
private Integer id;
private Integer articleId; // 文章ID
private Integer userId; // 评论用户ID
private String username; // 评论用户名
private String content; // 评论内容
private Integer parentId; // 父评论ID,0表示顶级评论
private Integer replyUserId; // 被回复的用户ID
private String replyUsername; // 被回复的用户名
private Integer likeCount; // 点赞数量
private LocalDateTime createTime; // 创建时间
private Integer status; // 状态:1-正常,0-删除
private List<Comment> children; // 子评论列表
}
// User.java - 用户实体
package com.example.commentsystem.entity;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class User {
private Integer id;
private String username;
private String avatar;
private String email;
private LocalDateTime createTime;
}
2 DTO类
// CommentRequest.java - 评论请求DTO
package com.example.commentsystem.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Data
public class CommentRequest {
@NotNull(message = "文章ID不能为空")
private Integer articleId;
@NotNull(message = "用户ID不能为空")
private Integer userId;
@NotBlank(message = "评论内容不能为空")
@Size(max = 1000, message = "评论内容不能超过1000字")
private String content;
private Integer parentId; // 父评论ID,回复评论时使用
private Integer replyUserId; // 被回复的用户ID
}
3 Controller层
// CommentController.java
package com.example.commentsystem.controller;
import com.example.commentsystem.common.Result;
import com.example.commentsystem.dto.CommentRequest;
import com.example.commentsystem.entity.Comment;
import com.example.commentsystem.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/comment")
public class CommentController {
@Autowired
private CommentService commentService;
/**
* 获取文章的所有评论(按时间倒序)
*/
@GetMapping("/list/{articleId}")
public Result<List<Comment>> getComments(@PathVariable Integer articleId) {
List<Comment> comments = commentService.getCommentsByArticle(articleId);
return Result.success(comments);
}
/**
* 获取文章的评论树(按树形结构)
*/
@GetMapping("/tree/{articleId}")
public Result<List<Comment>> getCommentTree(@PathVariable Integer articleId) {
List<Comment> comments = commentService.getCommentTree(articleId);
return Result.success(comments);
}
/**
* 发表评论
*/
@PostMapping("/add")
public Result<Comment> addComment(@Valid @RequestBody CommentRequest request) {
Comment comment = commentService.addComment(request);
return Result.success("评论成功", comment);
}
/**
* 删除评论(逻辑删除)
*/
@DeleteMapping("/delete/{id}")
public Result<Void> deleteComment(@PathVariable Integer id,
@RequestParam Integer userId) {
boolean success = commentService.deleteComment(id, userId);
return success ? Result.success("删除成功", null) : Result.error("删除失败");
}
/**
* 点赞评论
*/
@PostMapping("/like/{id}")
public Result<Integer> likeComment(@PathVariable Integer id) {
Integer likeCount = commentService.likeComment(id);
return Result.success("点赞成功", likeCount);
}
}
4 Service层
// CommentService.java
package com.example.commentsystem.service;
import com.example.commentsystem.dto.CommentRequest;
import com.example.commentsystem.entity.Comment;
import java.util.List;
public interface CommentService {
// 获取文章评论列表
List<Comment> getCommentsByArticle(Integer articleId);
// 获取评论树
List<Comment> getCommentTree(Integer articleId);
// 添加评论
Comment addComment(CommentRequest request);
// 删除评论
boolean deleteComment(Integer id, Integer userId);
// 点赞评论
Integer likeComment(Integer commentId);
// 获取用户评论历史
List<Comment> getUserComments(Integer userId, int page, int size);
}
// CommentServiceImpl.java
package com.example.commentsystem.service.impl;
import com.example.commentsystem.dao.CommentDao;
import com.example.commentsystem.dto.CommentRequest;
import com.example.commentsystem.entity.Comment;
import com.example.commentsystem.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class CommentServiceImpl implements CommentService {
@Autowired
private CommentDao commentDao;
@Override
public List<Comment> getCommentsByArticle(Integer articleId) {
return commentDao.findByArticleIdOrderByCreateTimeDesc(articleId);
}
@Override
public List<Comment> getCommentTree(Integer articleId) {
// 获取所有评论
List<Comment> allComments = commentDao.findByArticleIdOrderByCreateTimeDesc(articleId);
// 构建评论树
return buildCommentTree(allComments);
}
/**
* 构建评论树
*/
private List<Comment> buildCommentTree(List<Comment> allComments) {
// 将评论按ID分组
java.util.Map<Integer, Comment> commentMap = allComments.stream()
.collect(Collectors.toMap(Comment::getId, comment -> comment));
List<Comment> treeRoots = new ArrayList<>();
for (Comment comment : allComments) {
if (comment.getParentId() == 0) {
// 顶级评论
treeRoots.add(comment);
} else {
// 子评论,找到父评论并添加
Comment parent = commentMap.get(comment.getParentId());
if (parent != null) {
if (parent.getChildren() == null) {
parent.setChildren(new ArrayList<>());
}
parent.getChildren().add(comment);
} else {
// 父评论已被删除,作为顶级评论显示
treeRoots.add(comment);
}
}
}
// 对每个父评论的子评论按时间排序
treeRoots.forEach(root -> {
if (root.getChildren() != null) {
root.getChildren().sort((c1, c2) ->
c2.getCreateTime().compareTo(c1.getCreateTime()));
}
});
return treeRoots;
}
@Override
@Transactional
public Comment addComment(CommentRequest request) {
Comment comment = new Comment();
comment.setArticleId(request.getArticleId());
comment.setUserId(request.getUserId());
comment.setContent(request.getContent());
comment.setParentId(request.getParentId() != null ? request.getParentId() : 0);
comment.setReplyUserId(request.getReplyUserId());
comment.setLikeCount(0);
comment.setCreateTime(LocalDateTime.now());
comment.setStatus(1); // 正常状态
commentDao.insert(comment);
// 获取用户名(假设从用户服务获取)
comment.setUsername(getUsernameById(request.getUserId()));
// 如果被回复的用户存在,设置用户名
if (request.getReplyUserId() != null) {
comment.setReplyUsername(getUsernameById(request.getReplyUserId()));
}
return comment;
}
@Override
@Transactional
public boolean deleteComment(Integer id, Integer userId) {
Comment comment = commentDao.findById(id);
if (comment != null && comment.getUserId().equals(userId)) {
// 逻辑删除
commentDao.updateStatus(id, 0);
// 同时删除子评论(级联删除)
commentDao.deleteByParentId(id);
return true;
}
return false;
}
@Override
@Transactional
public Integer likeComment(Integer commentId) {
Comment comment = commentDao.findById(commentId);
if (comment != null) {
comment.setLikeCount(comment.getLikeCount() + 1);
commentDao.updateLikeCount(commentId, comment.getLikeCount());
return comment.getLikeCount();
}
return 0;
}
@Override
public List<Comment> getUserComments(Integer userId, int page, int size) {
int offset = (page - 1) * size;
return commentDao.findByUserIdOrderByCreateTimeDesc(userId, offset, size);
}
/**
* 获取用户名(模拟,实际应该调用用户服务)
*/
private String getUsernameById(Integer userId) {
// 这里应该调用用户服务获取用户名,这里简化处理
return "用户" + userId;
}
}
5 DAO层
// CommentDao.java
package com.example.commentsystem.dao;
import com.example.commentsystem.entity.Comment;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface CommentDao {
@Select("SELECT * FROM comment WHERE article_id = #{articleId} AND status = 1 ORDER BY create_time DESC")
List<Comment> findByArticleIdOrderByCreateTimeDesc(Integer articleId);
@Select("SELECT * FROM comment WHERE id = #{id} AND status = 1")
Comment findById(Integer id);
@Insert("INSERT INTO comment (article_id, user_id, content, parent_id, reply_user_id, " +
"like_count, create_time, status) " +
"VALUES (#{articleId}, #{userId}, #{content}, #{parentId}, #{replyUserId}, " +
"#{likeCount}, #{createTime}, #{status})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(Comment comment);
@Update("UPDATE comment SET status = 0 WHERE id = #{id}")
int updateStatus(@Param("id") Integer id, @Param("status") Integer status);
@Update("UPDATE comment SET like_count = #{likeCount} WHERE id = #{id}")
int updateLikeCount(@Param("id") Integer id, @Param("likeCount") Integer likeCount);
@Update("UPDATE comment SET status = 0 WHERE parent_id = #{parentId}")
int deleteByParentId(Integer parentId);
@Select("SELECT * FROM comment WHERE user_id = #{userId} AND status = 1 " +
"ORDER BY create_time DESC LIMIT #{size} OFFSET #{offset}")
List<Comment> findByUserIdOrderByCreateTimeDesc(@Param("userId") Integer userId,
@Param("offset") int offset,
@Param("size") int size);
}
6 通用返回结果类
// Result.java
package com.example.commentsystem.common;
import lombok.Data;
@Data
public class Result<T> {
private Integer code; // 编码:200-成功,500-失败
private String message; // 消息
private T data; // 数据
public static <T> Result<T> success(String message, T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMessage(message);
result.setData(data);
return result;
}
public static <T> Result<T> success(T data) {
return success("操作成功", data);
}
public static <T> Result<T> error(String message) {
Result<T> result = new Result<>();
result.setCode(500);
result.setMessage(message);
return result;
}
}
7 全局异常处理器
// GlobalExceptionHandler.java
package com.example.commentsystem.exception;
import com.example.commentsystem.common.Result;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidationException(MethodArgumentNotValidException e) {
FieldError fieldError = e.getBindingResult().getFieldError();
String message = fieldError != null ? fieldError.getDefaultMessage() : "参数错误";
return Result.error(message);
}
@ExceptionHandler(Exception.class)
public Result<Void> handleException(Exception e) {
return Result.error("系统异常:" + e.getMessage());
}
}
8 数据库建表脚本
-- 创建数据库
CREATE DATABASE IF NOT EXISTS comment_system DEFAULT CHARACTER SET utf8mb4;
USE comment_system;
-- 用户表
CREATE TABLE IF NOT EXISTS `user` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`avatar` VARCHAR(255) DEFAULT NULL COMMENT '头像URL',
`email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 评论表
CREATE TABLE IF NOT EXISTS `comment` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`article_id` INT NOT NULL COMMENT '文章ID',
`user_id` INT NOT NULL COMMENT '评论用户ID',
`content` TEXT NOT NULL COMMENT '评论内容',
`parent_id` INT DEFAULT 0 COMMENT '父评论ID',
`reply_user_id` INT DEFAULT NULL COMMENT '被回复的用户ID',
`like_count` INT DEFAULT 0 COMMENT '点赞数',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`status` TINYINT DEFAULT 1 COMMENT '状态:1-正常,0-删除',
KEY `idx_article_id` (`article_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论表';
-- 插入测试数据
INSERT INTO `user` (username, email) VALUES
('张三', 'zhangsan@example.com'),
('李四', 'lisi@example.com'),
('王五', 'wangwu@example.com');
-- 插入评论示例
INSERT INTO `comment` (article_id, user_id, content, parent_id, reply_user_id, like_count) VALUES
(1, 1, '这篇文章写得太好了,收藏了!', 0, NULL, 5),
(1, 2, '学习了,很不错的内容', 1, 1, 3),
(1, 3, '希望能够多出一些这样的教程', 0, NULL, 2);
9 配置文件
# application.yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/comment_system?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: yourpassword
driver-class-name: com.mysql.cj.jdbc.Driver
redis:
host: localhost
port: 6379
# 用于评论点赞计数缓存,减少数据库压力
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
mybatis:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
10 前端代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">评论系统</title>
<style>
.comment-section {
max-width: 800px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
.comment-input {
border: 1px solid #ddd;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.comment-input textarea {
width: 100%;
height: 100px;
margin-bottom: 10px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 3px;
}
.btn-submit {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 3px;
cursor: pointer;
}
.btn-submit:hover {
background-color: #0056b3;
}
.comment-list {
list-style: none;
padding: 0;
}
.comment-item {
border: 1px solid #eee;
margin-bottom: 10px;
padding: 15px;
border-radius: 5px;
background-color: #f9f9f9;
}
.comment-item.child-comments {
margin-left: 40px;
margin-top: 10px;
}
.comment-header {
font-size: 14px;
margin-bottom: 10px;
}
.comment-username {
color: #007bff;
font-weight: bold;
}
.comment-content {
margin-bottom: 10px;
line-height: 1.5;
}
.comment-footer {
font-size: 12px;
color: #999;
}
.like-btn {
background: none;
border: none;
color: #007bff;
cursor: pointer;
margin-right: 10px;
}
.reply-btn {
background: none;
border: none;
color: #007bff;
cursor: pointer;
}
.reply-tag {
color: #999;
font-size: 13px;
}
.comment-content .reply-to {
color: #007bff;
font-weight: bold;
margin-right: 5px;
}
.empty-comments {
color: #999;
text-align: center;
padding: 20px;
}
.reply-area {
margin-top: 10px;
}
.reply-area textarea {
width: 100%;
height: 60px;
margin-bottom: 5px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 3px;
}
.btn-submit-reply {
background-color: #28a745;
color: white;
border: none;
padding: 5px 15px;
border-radius: 3px;
cursor: pointer;
}
footer {
font-size: 12px;
color: #999;
margin-top: 20px;
text-align: center;
}
</style>
</head>
<body>
<div class="comment-section">
<!-- 发表评论区域 -->
<div class="comment-input">
<h3>发表评论</h3>
<textarea id="commentContent" placeholder="请输入评论内容..."></textarea>
<button class="btn-submit" onclick="submitComment()">发表评论</button>
</div>
<!-- 评论列表 -->
<h3>全部评论</h3>
<ul class="comment-list" id="commentList">
<!-- 评论将在这里动态加载 -->
</ul>
</div>
<script>
// 当前文章ID(示例)
const articleId = 1;
// 当前用户ID和用户名(示例,实际应从登录状态获取)
const currentUser = { id: 1, username: '张三' };
// 页面加载时获取评论
window.onload = function() {
loadComments();
};
// 提交评论
function submitComment() {
const content = document.getElementById('commentContent').value.trim();
if (!content) {
alert('请输入评论内容');
return;
}
const data = {
articleId: articleId,
userId: currentUser.id,
content: content,
parentId: 0
};
fetch('/api/comment/add', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => response.json())
.then(res => {
if (res.code === 200) {
alert('评论成功');
document.getElementById('commentContent').value = '';
loadComments();
} else {
alert(res.message);
}
});
}
// 加载评论
function loadComments() {
fetch(`/api/comment/tree/${articleId}`)
.then(response => response.json())
.then(res => {
if (res.code === 200) {
renderComments(res.data, document.getElementById('commentList'));
}
});
}
// 渲染评论树
function renderComments(comments, container) {
if (!comments || comments.length === 0) {
container.innerHTML = '<li class="empty-comments">暂无评论,快来发表第一条评论吧!</li>';
return;
}
container.innerHTML = '';
comments.forEach(comment => {
const li = document.createElement('li');
li.className = 'comment-item';
// 评论头部
const header = document.createElement('div');
header.className = 'comment-header';
header.innerHTML = `
<span class="comment-username">${comment.username}</span>
<span class="comment-time">${formatTime(comment.createTime)}</span>
`;
// 评论内容
const contentDiv = document.createElement('div');
contentDiv.className = 'comment-content';
if (comment.replyUsername) {
contentDiv.innerHTML = `<span class="reply-to">回复 @${comment.replyUsername}:</span>${comment.content}`;
} else {
contentDiv.textContent = comment.content;
}
// 评论底部
const footer = document.createElement('div');
footer.className = 'comment-footer';
footer.innerHTML = `
<button class="like-btn" onclick="likeComment(${comment.id})">👍 ${comment.likeCount}</button>
<button class="reply-btn" onclick="toggleReplyArea(${comment.id})">回复</button>
`;
li.appendChild(header);
li.appendChild(contentDiv);
li.appendChild(footer);
// 回复区域
const replyArea = document.createElement('div');
replyArea.className = 'reply-area';
replyArea.id = `replyArea${comment.id}`;
replyArea.style.display = 'none';
replyArea.innerHTML = `
<textarea id="replyContent${comment.id}" placeholder="回复评论..."></textarea>
<button class="btn-submit-reply" onclick="submitReply(${comment.id})">提交回复</button>
`;
li.appendChild(replyArea);
// 如果有子评论,递归渲染
if (comment.children && comment.children.length > 0) {
const childUl = document.createElement('ul');
childUl.className = 'comment-list child-comments';
renderComments(comment.children, childUl);
li.appendChild(childUl);
}
container.appendChild(li);
});
}
// 点赞评论
function likeComment(commentId) {
fetch(`/api/comment/like/${commentId}`, {
method: 'POST'
})
.then(response => response.json())
.then(res => {
if (res.code === 200) {
loadComments(); // 重新加载以更新点赞数
}
});
}
// 显示/隐藏回复区域
function toggleReplyArea(commentId) {
const replyArea = document.getElementById(`replyArea${commentId}`);
replyArea.style.display = replyArea.style.display === 'none' ? 'block' : 'none';
}
// 提交回复
function submitReply(parentId) {
const content = document.getElementById(`replyContent${parentId}`).value.trim();
if (!content) {
alert('请输入回复内容');
return;
}
const data = {
articleId: articleId,
userId: currentUser.id,
content: content,
parentId: parentId,
replyUserId: getCommentById(parentId).userId // 获取被回复者的ID
};
fetch('/api/comment/add', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => response.json())
.then(res => {
if (res.code === 200) {
alert('回复成功');
loadComments();
} else {
alert(res.message);
}
});
}
// 格式化时间
function formatTime(timeStr) {
if (!timeStr) return '';
const time = new Date(timeStr);
const now = new Date();
const diff = now - time;
if (diff < 60000) return '刚刚';
if (diff < 3600000) return `${Math.floor(diff/60000)}分钟前`;
if (diff < 86400000) return `${Math.floor(diff/3600000)}小时前`;
if (diff < 2592000000) return `${Math.floor(diff/86400000)}天前`;
return time.toLocaleDateString('zh-CN');
}
</script>
</body>
</html>
11 Maven依赖
<!-- pom.xml -->
<?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>comment-system</artifactId>
<version>1.0.0</version>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
</project>
12 启动类
// CommentApplication.java
package com.example.commentsystem;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.commentsystem.dao")
public class CommentApplication {
public static void main(String[] args) {
SpringApplication.run(CommentApplication.class, args);
System.out.println("评论系统启动成功!");
}
}
系统功能特性
1 核心功能
- ✅ 发表评论
- ✅ 回复评论(支持多级嵌套)
- ✅ 删除评论(逻辑删除)
- ✅ 点赞评论
- ✅ 按时间排序
- ✅ 分页加载
2 增强功能建议
- 敏感词过滤:添加敏感词库进行内容过滤
- 评论审核:管理员审核机制
- @用户提醒:支持@功能并通知
- 表情支持:集成emoji表情
- 图片上传:支持评论图片上传
- 实时通知:WebSocket实现实时通知
3 性能优化建议
- 缓存优化:使用Redis缓存热数据
- 数据库优化:合适的索引设计
- 异步处理:异步发送通知邮件
- 限流控制:防止刷评论攻击
这个评论系统案例包含了完整的后端实现和前端展示,可以根据实际需求进行扩展和优化。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播