本文目录导读:

我来为您设计一个完整的Java社交系统案例,包含核心功能模块和实现代码。
项目结构
social-system/
├── pom.xml
├── src/main/java/com/social/
│ ├── SocialApplication.java
│ ├── config/
│ │ ├── SecurityConfig.java
│ │ └── RedisConfig.java
│ ├── controller/
│ │ ├── UserController.java
│ │ ├── PostController.java
│ │ ├── FriendController.java
│ │ └── MessageController.java
│ ├── service/
│ │ ├── impl/
│ │ │ ├── UserServiceImpl.java
│ │ │ ├── PostServiceImpl.java
│ │ │ ├── FriendServiceImpl.java
│ │ │ └── MessageServiceImpl.java
│ │ └── ...
│ ├── mapper/
│ ├── entity/
│ ├── dto/
│ └── util/
└── src/main/resources/
├── application.yml
└── mapper/
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.14</version>
</parent>
<groupId>com.social</groupId>
<artifactId>social-system</artifactId>
<version>1.0.0</version>
<properties>
<java.version>11</java.version>
<jjwt.version>0.11.5</jjwt.version>
</properties>
<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- FastJson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
</dependencies>
</project>
实体类设计
User.java
package com.social.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private String password;
private String nickname;
private String avatar;
private String email;
private String phone;
private String bio; // 个人简介
private Integer gender; // 0:未知 1:男 2:女
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
private Integer deleted; // 逻辑删除
private Integer status; // 账号状态
}
Post.java
package com.social.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
@TableName("post")
public class Post {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
private String content;
private String images; // JSON存储多张图片
private String location;
@TableField(exist = false)
private User user; // 发布者信息
@TableField(exist = false)
private Integer likeCount; // 点赞数
@TableField(exist = false)
private Integer commentCount; // 评论数
@TableField(exist = false)
private Boolean isLiked; // 当前用户是否点赞
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
private Integer deleted;
private Integer status;
}
Friend.java
package com.social.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("friend")
public class Friend {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
private Long friendId;
private Integer status; // 0:待确认 1:已通过 2:已拒绝
private String remark; // 好友备注
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
控制器层
UserController.java
package com.social.controller;
import com.social.common.Result;
import com.social.dto.LoginDTO;
import com.social.dto.RegisterDTO;
import com.social.dto.UpdateUserDTO;
import com.social.entity.User;
import com.social.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 用户注册
*/
@PostMapping("/register")
public Result register(@Valid @RequestBody RegisterDTO registerDTO) {
return userService.register(registerDTO);
}
/**
* 用户登录
*/
@PostMapping("/login")
public Result login(@Valid @RequestBody LoginDTO loginDTO) {
return userService.login(loginDTO);
}
/**
* 获取用户信息
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Long id) {
return userService.getUserInfo(id);
}
/**
* 更新用户信息
*/
@PutMapping("/{id}")
public Result updateProfile(@PathVariable Long id,
@RequestBody UpdateUserDTO updateUserDTO) {
return userService.updateUser(id, updateUserDTO);
}
/**
* 搜索用户
*/
@GetMapping("/search")
public Result search(String keyword,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
return userService.searchUsers(keyword, page, size);
}
}
PostController.java
package com.social.controller;
import com.social.common.Result;
import com.social.dto.CreatePostDTO;
import com.social.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/post")
public class PostController {
@Autowired
private PostService postService;
/**
* 创建帖子
*/
@PostMapping
public Result createPost(@RequestBody CreatePostDTO createPostDTO) {
return postService.createPost(createPostDTO);
}
/**
* 删除帖子
*/
@DeleteMapping("/{id}")
public Result deletePost(@PathVariable Long id) {
return postService.deletePost(id);
}
/**
* 获取帖子详情
*/
@GetMapping("/{id}")
public Result getPost(@PathVariable Long id) {
return postService.getPost(id);
}
/**
* 获取时间线(关注用户的帖子)
*/
@GetMapping("/timeline")
public Result getTimeline(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
return postService.getTimeline(page, size);
}
/**
* 获取用户发布的帖子
*/
@GetMapping("/user/{userId}")
public Result getUserPosts(@PathVariable Long userId,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
return postService.getUserPosts(userId, page, size);
}
/**
* 点赞/取消点赞
*/
@PostMapping("/{id}/like")
public Result like(@PathVariable Long id) {
return postService.likePost(id);
}
/**
* 评论
*/
@PostMapping("/{id}/comment")
public Result comment(@PathVariable Long id, @RequestParam String content) {
return postService.commentPost(id, content);
}
}
服务层实现
UserServiceImpl.java
package com.social.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.social.common.Result;
import com.social.dto.LoginDTO;
import com.social.dto.RegisterDTO;
import com.social.dto.UpdateUserDTO;
import com.social.entity.User;
import com.social.exception.BusinessException;
import com.social.mapper.UserMapper;
import com.social.service.UserService;
import com.social.util.JwtUtil;
import com.social.util.RedisUtil;
import com.social.vo.LoginVO;
import com.social.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private JwtUtil jwtUtil;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public Result register(RegisterDTO registerDTO) {
// 检查用户名是否已存在
User existingUser = userMapper.selectOne(
new LambdaQueryWrapper<User>()
.eq(User::getUsername, registerDTO.getUsername())
);
if (existingUser != null) {
throw new BusinessException("用户名已存在");
}
// 创建新用户
User user = new User();
BeanUtils.copyProperties(registerDTO, user);
user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
user.setNickname(registerDTO.getUsername());
user.setAvatar("default_avatar.png");
userMapper.insert(user);
return Result.success("注册成功", user.getId());
}
@Override
public Result login(LoginDTO loginDTO) {
// 查询用户
User user = userMapper.selectOne(
new LambdaQueryWrapper<User>()
.eq(User::getUsername, loginDTO.getUsername())
);
if (user == null || !passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
throw new BusinessException("用户名或密码错误");
}
// 生成JWT Token
String token = jwtUtil.generateToken(user.getId(), user.getUsername());
// 存储到Redis,设置7天有效期
String redisKey = "token:" + user.getId();
redisTemplate.opsForValue().set(redisKey, token, 7, TimeUnit.DAYS);
// 构建返回数据
LoginVO loginVO = new LoginVO();
loginVO.setToken(token);
UserVO userVO = new UserVO();
BeanUtils.copyProperties(user, userVO);
loginVO.setUser(userVO);
return Result.success("登录成功", loginVO);
}
@Override
public Result getUserInfo(Long id) {
User user = userMapper.selectById(id);
if (user == null) {
throw new BusinessException("用户不存在");
}
UserVO userVO = new UserVO();
BeanUtils.copyProperties(user, userVO);
// 获取关注数和粉丝数
Integer followCount = userMapper.getFollowCount(id);
Integer fansCount = userMapper.getFansCount(id);
Map<String, Object> data = new HashMap<>();
data.put("userInfo", userVO);
data.put("followCount", followCount);
data.put("fansCount", fansCount);
return Result.success(data);
}
@Override
public Result updateUser(Long id, UpdateUserDTO updateUserDTO) {
User user = userMapper.selectById(id);
if (user == null) {
throw new BusinessException("用户不存在");
}
// 更新用户信息
if (StringUtils.hasText(updateUserDTO.getNickname())) {
user.setNickname(updateUserDTO.getNickname());
}
if (StringUtils.hasText(updateUserDTO.getAvatar())) {
user.setAvatar(updateUserDTO.getAvatar());
}
if (updateUserDTO.getGender() != null) {
user.setGender(updateUserDTO.getGender());
}
if (StringUtils.hasText(updateUserDTO.getBio())) {
user.setBio(updateUserDTO.getBio());
}
userMapper.updateById(user);
UserVO userVO = new UserVO();
BeanUtils.copyProperties(user, userVO);
return Result.success("更新成功", userVO);
}
@Override
public Result searchUsers(String keyword, int page, int size) {
IPage<User> userPage = null;
if (StringUtils.hasText(keyword)) {
userPage = userMapper.selectPage(
new Page<>(page, size),
new LambdaQueryWrapper<User>()
.like(User::getUsername, keyword)
.or()
.like(User::getNickname, keyword)
);
} else {
userPage = userMapper.selectPage(new Page<>(page, size), null);
}
return Result.success(userPage);
}
}
PostServiceImpl.java
package com.social.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.social.common.Result;
import com.social.dto.CreatePostDTO;
import com.social.entity.Post;
import com.social.entity.User;
import com.social.exception.BusinessException;
import com.social.mapper.PostMapper;
import com.social.mapper.UserMapper;
import com.social.service.PostService;
import com.social.util.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Service
public class PostServiceImpl implements PostService {
@Autowired
private PostMapper postMapper;
@Autowired
private UserMapper userMapper;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public Result createPost(CreatePostDTO createPostDTO) {
Post post = new Post();
BeanUtils.copyProperties(createPostDTO, post);
postMapper.insert(post);
// 将帖子ID加入用户的时间线缓存
String timelineKey = "timeline:user:" + post.getUserId();
redisTemplate.opsForList().leftPush(timelineKey, post.getId());
return Result.success("发布成功", post.getId());
}
@Override
public Result deletePost(Long id) {
Post post = postMapper.selectById(id);
if (post == null) {
throw new BusinessException("帖子不存在");
}
// 逻辑删除
post.setDeleted(1);
postMapper.updateById(post);
return Result.success("删除成功");
}
@Override
public Result getPost(Long id) {
// 尝试从缓存获取
String cacheKey = "post:" + id;
Object cached = redisTemplate.opsForValue().get(cacheKey);
if (cached != null) {
return Result.success(cached);
}
Post post = postMapper.selectById(id);
if (post == null) {
throw new BusinessException("帖子不存在");
}
// 填充用户信息
User user = userMapper.selectById(post.getUserId());
post.setUser(user);
// 获取点赞数和评论数
post.setLikeCount(getLikeCount(id));
post.setCommentCount(getCommentCount(id));
// 存入缓存,5分钟过期
redisTemplate.opsForValue().set(cacheKey, post, 5, TimeUnit.MINUTES);
return Result.success(post);
}
@Override
public Result getTimeline(int page, int size) {
// 获取当前登录用户ID(从上下文获取)
Long currentUserId = SecurityUtil.getCurrentUserId();
// 获取关注用户的帖子(这里简化处理,使用Redis缓存实现)
String timelineKey = "timeline:user:" + currentUserId;
// 实际应用中可从数据库查询,这里简化实现
IPage<Post> postPage = postMapper.selectPage(
new Page<>(page, size),
new LambdaQueryWrapper<Post>()
.eq(Post::getDeleted, 0)
.orderByDesc(Post::getCreateTime)
);
// 填充用户信息
List<Post> records = postPage.getRecords();
records.forEach(post -> {
User user = userMapper.selectById(post.getUserId());
post.setUser(user);
});
return Result.success(postPage);
}
@Override
public Result getUserPosts(Long userId, int page, int size) {
IPage<Post> postPage = postMapper.selectPage(
new Page<>(page, size),
new LambdaQueryWrapper<Post>()
.eq(Post::getUserId, userId)
.eq(Post::getDeleted, 0)
.orderByDesc(Post::getCreateTime)
);
return Result.success(postPage);
}
@Override
public Result likePost(Long postId) {
Long currentUserId = SecurityUtil.getCurrentUserId();
String likeKey = "post:like:" + postId;
Boolean isLiked = redisTemplate.opsForSet().isMember(likeKey, currentUserId);
if (Boolean.TRUE.equals(isLiked)) {
// 取消点赞
redisTemplate.opsForSet().remove(likeKey, currentUserId);
return Result.success("已取消点赞");
} else {
// 点赞
redisTemplate.opsForSet().add(likeKey, currentUserId);
return Result.success("点赞成功");
}
}
@Override
public Result commentPost(Long postId, String content) {
Long currentUserId = SecurityUtil.getCurrentUserId();
// 创建评论记录
Comment comment = new Comment();
comment.setPostId(postId);
comment.setUserId(currentUserId);
comment.setContent(content);
commentMapper.insert(comment);
// 更新评论数缓存
String commentCountKey = "post:comment:count:" + postId;
redisTemplate.opsForValue().increment(commentCountKey);
return Result.success("评论成功", comment.getId());
}
private int getLikeCount(Long postId) {
String likeKey = "post:like:" + postId;
return redisTemplate.opsForSet().size(likeKey).intValue();
}
private int getCommentCount(Long postId) {
String commentCountKey = "post:comment:count:" + postId;
Integer count = (Integer) redisTemplate.opsForValue().get(commentCountKey);
return count == null ? 0 : count;
}
}
安全配置
SecurityConfig.java
package com.social.config;
import com.social.security.JwtAuthenticationFilter;
import com.social.security.JwtUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private JwtUserDetailsService jwtUserDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/user/register", "/api/user/login").permitAll()
.antMatchers("/swagger-ui/**", "/api-docs/**").permitAll()
.anyRequest().authenticated()
.and()
.userDetailsService(jwtUserDetailsService);
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}
}
JWT工具类
JwtUtil.java
package com.social.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component
public class JwtUtil {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
private Key key;
@PostConstruct
public void init() {
this.key = Keys.hmacShaKeyFor(secret.getBytes());
}
/**
* 生成Token
*/
public String generateToken(Long userId, String username) {
Map<String, Object> claims = new HashMap<>();
claims.put("userId", userId);
claims.put("username", username);
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(key, SignatureAlgorithm.HS256)
.compact();
}
/**
* 解析Token
*/
public Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody();
}
/**
* 验证Token是否有效
*/
public boolean validateToken(String token) {
try {
Jwts.parser()
.setSigningKey(key)
.build()
.parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 从Token获取用户ID
*/
public Long getUserIdFromToken(String token) {
Claims claims = parseToken(token);
return claims.get("userId", Long.class);
}
}
统一返回结果
Result.java
package com.social.common;
import lombok.Data;
@Data
public class Result {
private Integer code;
private String message;
private Object data;
public static Result success(Object data) {
Result result = new Result();
result.setCode(200);
result.setMessage("操作成功");
result.setData(data);
return result;
}
public static Result success(String message, Object data) {
Result result = new Result();
result.setCode(200);
result.setMessage(message);
result.setData(data);
return result;
}
public static Result error(Integer code, String message) {
Result result = new Result();
result.setCode(code);
result.setMessage(message);
return result;
}
}
配置文件
application.yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/social_system?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
redis:
host: localhost
port: 6379
password:
database: 0
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0
jwt:
secret: your-secret-key-here-at-least-256-bits-long
expiration: 604800000 # 7天
数据库脚本
-- 用户表 CREATE TABLE `user` ( `id` bigint NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(255) NOT NULL, `nickname` varchar(50) DEFAULT NULL, `avatar` varchar(255) DEFAULT NULL, `email` varchar(100) DEFAULT NULL, `phone` varchar(20) DEFAULT NULL, `bio` varchar(500) DEFAULT NULL, `gender` tinyint DEFAULT '0', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `deleted` tinyint DEFAULT '0', `status` tinyint DEFAULT '1', PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 帖子表 CREATE TABLE `post` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint NOT NULL, `content` text, `images` text, `location` varchar(200) DEFAULT NULL, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `deleted` tinyint DEFAULT '0', `status` tinyint DEFAULT '1', PRIMARY KEY (`id`), KEY `idx_user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 好友关系表 CREATE TABLE `friend` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint NOT NULL, `friend_id` bigint NOT NULL, `status` tinyint DEFAULT '0', `remark` varchar(100) DEFAULT NULL, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_user_friend` (`user_id`, `friend_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 评论表 CREATE TABLE `comment` ( `id` bigint NOT NULL AUTO_INCREMENT, `post_id` bigint NOT NULL, `user_id` bigint NOT NULL, `content` varchar(500) NOT NULL, `parent_id` bigint DEFAULT '0', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `deleted` tinyint DEFAULT '0', PRIMARY KEY (`id`), KEY `idx_post_id` (`post_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 点赞表 CREATE TABLE `post_like` ( `id` bigint NOT NULL AUTO_INCREMENT, `post_id` bigint NOT NULL, `user_id` bigint NOT NULL, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_post_user` (`post_id`, `user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 私信表 CREATE TABLE `message` ( `id` bigint NOT NULL AUTO_INCREMENT, `from_user_id` bigint NOT NULL, `to_user_id` bigint NOT NULL, `content` text NOT NULL, `message_type` tinyint DEFAULT '1', `is_read` tinyint DEFAULT '0', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_from_to` (`from_user_id`, `to_user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
核心功能演示
实际使用示例
@RestController
@RequestMapping("/api/demo")
public class DemoController {
@Autowired
private PostService postService;
@Autowired
private FriendService friendService;
/**
* 获取好友最新动态
*/
@GetMapping("/friends/feed")
public Result getFriendsFeed() {
Long userId = SecurityUtil.getCurrentUserId();
// 获取好友列表
List<Long> friendIds = friendService.getFriendIds(userId);
// 获取所有好友的帖子(简化实现)
List<Post> posts = postService.getPostsByUserIds(friendIds);
return Result.success(posts);
}
}
这个Java社交系统案例包含了:
- 用户系统:注册、登录、JWT认证
- 社交功能:发帖、点赞、评论
- 好友系统:添加好友、好友动态
- 缓存优化:Redis缓存热门数据
- 安全处理:Spring Security + JWT
可以根据实际需求扩展更多功能,如消息推送、群组、图片上传等。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播