Java社交系统案例

wen java案例 3

本文目录导读:

Java社交系统案例

  1. 项目结构
  2. Maven配置 (pom.xml)
  3. 实体类设计
  4. 控制器层
  5. 服务层实现
  6. 安全配置
  7. JWT工具类
  8. 统一返回结果
  9. 配置文件
  10. 数据库脚本
  11. 核心功能演示

我来为您设计一个完整的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社交系统案例包含了:

  1. 用户系统:注册、登录、JWT认证
  2. 社交功能:发帖、点赞、评论
  3. 好友系统:添加好友、好友动态
  4. 缓存优化:Redis缓存热门数据
  5. 安全处理:Spring Security + JWT

可以根据实际需求扩展更多功能,如消息推送、群组、图片上传等。

抱歉,评论功能暂时关闭!