【Java Web】实现帖子点赞功能——基于Redis

  • 点赞
    • 支持对帖子、评论点赞;
    • 第一次点赞,第二次点赞取消;
  • 首页显示点赞数量
    • 统计帖子点赞数量;
  • 详情页显示点赞数量
    • 统计点赞数量;
    • 显示点赞状态;

1. LikeService定义一些关于点赞的操作

  • 点赞:
    • 如果已经点过赞,就取消点赞;
    • 如果没点过赞,就add到redis;
  • 查询某个实体点赞的数量 ;
  • 查询某人某实体的点赞状态;
java 复制代码
package com.nowcoder.community.service;

import com.nowcoder.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class LikeService {
    @Autowired
    private RedisTemplate redisTemplate;

    // 点赞
    public void like(int userId, int entityType, int entityId){
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType,entityId);
        boolean isMember = redisTemplate.opsForSet().isMember(entityLikeKey,userId);
        if(isMember){ // 已经点过赞
            redisTemplate.opsForSet().remove(entityLikeKey,userId);
        } else { // 没点过赞
            redisTemplate.opsForSet().add(entityLikeKey,userId);
        }
    }

    // 查询某个实体点赞的数量
    public long findEntityLikeCount(int entityType, int entityId){
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType,entityId);
        return redisTemplate.opsForSet().size(entityLikeKey);
    }

    // 查询某人某实体的点赞状态
    public int findEntityLikeStatus(int userId, int entityType, int entityId){
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType,entityId);
         return redisTemplate.opsForSet().isMember(entityLikeKey, userId) ? 1 : 0;
    }
}

2. 点赞将提交异步请求,将结果以JSON传给页面

java 复制代码
package com.nowcoder.community.controller;

import com.nowcoder.community.annotation.LoginRequired;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.util.CommunityUtil;
import com.nowcoder.community.util.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

@Controller
public class LikeController {

    @Autowired
    private LikeService likeService;

    @Autowired
    private HostHolder hostHolder;

    @RequestMapping(path="/like",method = RequestMethod.POST)
    @ResponseBody
    public String like(int entityType, int entityId){
        // 当前用户
        User user = hostHolder.getUser();

        // 点赞
        likeService.like(user.getId(), entityType, entityId);

        // 返回点赞数量
        long likeCount = likeService.findEntityLikeCount(entityType, entityId);

        // 点赞状态
        int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId);

        // 封装传给页面
        Map<String,Object> map = new HashMap<>();
        map.put("likeCount",likeCount);
        map.put("likeStatus",likeStatus);

        return CommunityUtil.getJSONString(0, null, map);
    }
}

3. 帖子详情页面显示点赞信息

如果当前用户已经点赞,点赞处应当显示已赞

java 复制代码
package com.nowcoder.community.controller;

import com.nowcoder.community.entity.Comment;
import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.Page;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.CommentService;
import com.nowcoder.community.service.DiscussPostService;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.service.UserService;
import com.nowcoder.community.util.CommunityConstant;
import com.nowcoder.community.util.CommunityUtil;
import com.nowcoder.community.util.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;

@Controller
@RequestMapping("/discuss")
public class DiscussPostController implements CommunityConstant {

    @Autowired
    private DiscussPostService discussPostService;

    @Autowired
    private HostHolder hostHolder;

    @Autowired
    private UserService userService;

    @Autowired
    private CommentService commentService;

    @Autowired
    private LikeService likeService;

    @RequestMapping(path = "/add", method = RequestMethod.POST)
    @ResponseBody
    public String addDiscussPost(String title, String content) {
        User user = hostHolder.getUser();
        if (user == null) {
            return CommunityUtil.getJSONString(403, "你还没有登录哦!");
        }

        DiscussPost post = new DiscussPost();
        post.setUserId(user.getId());
        post.setTitle(title);
        post.setContent(content);
        post.setCreateTime(new Date());
        discussPostService.addDiscussPost(post);

        // 报错的情况,将来统一处理.
        return CommunityUtil.getJSONString(0, "发布成功!");
    }

    @RequestMapping(path = "/detail/{discussPostId}", method = RequestMethod.GET)
    public String getDiscussPost(@PathVariable("discussPostId") int discussPostId, Model model, Page page) {
        // 帖子
        DiscussPost post = discussPostService.findDiscussPostById(discussPostId);
        model.addAttribute("post", post);
        // 作者
        User user = userService.findUserById(post.getUserId());
        model.addAttribute("user", user);

        // 点赞
        long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostId);
        int likeStatus = hostHolder.getUser() == null ? 0 : likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_POST, post.getId());
        model.addAttribute("likeCount",likeCount);
        model.addAttribute("likeStatus",likeStatus);


        // 评论分页信息
        page.setLimit(5);
        page.setPath("/discuss/detail/" + discussPostId);
        page.setRows(post.getCommentCount());

        // 评论: 给帖子的评论
        // 回复: 给评论的评论
        // 评论列表
        List<Comment> commentList = commentService.findCommentsByEntity(
                ENTITY_TYPE_POST, post.getId(), page.getOffset(), page.getLimit());
        // 评论VO列表
        List<Map<String, Object>> commentVoList = new ArrayList<>();
        if (commentList != null) {
            for (Comment comment : commentList) {
                // 评论VO
                Map<String, Object> commentVo = new HashMap<>();
                // 评论
                commentVo.put("comment", comment);
                // 作者
                commentVo.put("user", userService.findUserById(comment.getUserId()));

                // 点赞
                likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, comment.getId());
                likeStatus = hostHolder.getUser() == null? 0 : likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_COMMENT, comment.getId());
                commentVo.put("likeCount",likeCount);
                commentVo.put("likeStatus",likeStatus);

                // 回复列表
                List<Comment> replyList = commentService.findCommentsByEntity(
                        ENTITY_TYPE_COMMENT, comment.getId(), 0, Integer.MAX_VALUE);
                // 回复VO列表
                List<Map<String, Object>> replyVoList = new ArrayList<>();
                if (replyList != null) {
                    for (Comment reply : replyList) {
                        Map<String, Object> replyVo = new HashMap<>();
                        // 回复
                        replyVo.put("reply", reply);
                        // 作者
                        replyVo.put("user", userService.findUserById(reply.getUserId()));
                        // 回复目标
                        User target = reply.getTargetId() == 0 ? null : userService.findUserById(reply.getTargetId());
                        replyVo.put("target", target);

                        // 点赞
                        likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_COMMENT, reply.getId());
                        likeStatus = hostHolder.getUser() == null? 0 : likeService.findEntityLikeStatus(hostHolder.getUser().getId(), ENTITY_TYPE_COMMENT, reply.getId());
                        replyVo.put("likeCount",likeCount);
                        replyVo.put("likeStatus",likeStatus);

                        replyVoList.add(replyVo);
                    }
                }
                commentVo.put("replys", replyVoList);

                // 回复数量
                int replyCount = commentService.findCommentCount(ENTITY_TYPE_COMMENT, comment.getId());
                commentVo.put("replyCount", replyCount);

                commentVoList.add(commentVo);
            }
        }

        model.addAttribute("comments", commentVoList);

        return "/site/discuss-detail";
    }

}

4. discuss-detail.html

java 复制代码
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	<link rel="icon" th:href="@{/img/ucas.png}"/>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
	<link rel="stylesheet" th:href="@{/css/global.css}" />
	<link rel="stylesheet" th:href="@{/css/discuss-detail.css}" />
	<title>牛客网-帖子详情</title>
</head>
<body>
<div class="nk-container">
	<!-- 头部 -->
	<header class="bg-dark sticky-top" th:replace="index::header">
		<div class="container">
			<!-- 导航 -->
			<nav class="navbar navbar-expand-lg navbar-dark">
				<!-- logo -->
				<a class="navbar-brand" href="#"></a>
				<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
					<span class="navbar-toggler-icon"></span>
				</button>
				<!-- 功能 -->
				<div class="collapse navbar-collapse" id="navbarSupportedContent">
					<ul class="navbar-nav mr-auto">
						<li class="nav-item ml-3 btn-group-vertical">
							<a class="nav-link" href="../index.html">首页</a>
						</li>
						<li class="nav-item ml-3 btn-group-vertical">
							<a class="nav-link position-relative" href="letter.html">消息<span class="badge badge-danger">12</span></a>
						</li>
						<li class="nav-item ml-3 btn-group-vertical">
							<a class="nav-link" href="register.html">注册</a>
						</li>
						<li class="nav-item ml-3 btn-group-vertical">
							<a class="nav-link" href="login.html">登录</a>
						</li>
						<li class="nav-item ml-3 btn-group-vertical dropdown">
							<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
								<img src="http://images.nowcoder.com/head/1t.png" class="rounded-circle" style="width:30px;"/>
							</a>
							<div class="dropdown-menu" aria-labelledby="navbarDropdown">
								<a class="dropdown-item text-center" href="profile.html">个人主页</a>
								<a class="dropdown-item text-center" href="setting.html">账号设置</a>
								<a class="dropdown-item text-center" href="login.html">退出登录</a>
								<div class="dropdown-divider"></div>
								<span class="dropdown-item text-center text-secondary">nowcoder</span>
							</div>
						</li>
					</ul>
					<!-- 搜索 -->
					<form class="form-inline my-2 my-lg-0" action="search.html">
						<input class="form-control mr-sm-2" type="search" aria-label="Search" />
						<button class="btn btn-outline-light my-2 my-sm-0" type="submit">搜索</button>
					</form>
				</div>
			</nav>
		</div>
	</header>

	<!-- 内容 -->
	<div class="main">
		<!-- 帖子详情 -->
		<div class="container">
			<!-- 标题 -->
			<h6 class="mb-4">
				<img src="http://static.nowcoder.com/images/img/icons/ico-discuss.png"/>
				<span th:utext="${post.title}">备战春招,面试刷题跟他复习,一个月全搞定!</span>
				<div class="float-right">
					<button type="button" class="btn btn-danger btn-sm">置顶</button>
					<button type="button" class="btn btn-danger btn-sm">加精</button>
					<button type="button" class="btn btn-danger btn-sm">删除</button>
				</div>
			</h6>
			<!-- 作者 -->
			<div class="media pb-3 border-bottom">
				<a href="profile.html">
					<img th:src="${user.headerUrl}" class="align-self-start mr-4 rounded-circle user-header" alt="用户头像" >
				</a>
				<div class="media-body">
					<div class="mt-0 text-warning" th:utext="${user.username}">寒江雪</div>
					<div class="text-muted mt-3">
						发布于 <b th:text="${#dates.format(post.createTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-15 15:32:18</b>
						<ul class="d-inline float-right">
							<li class="d-inline ml-2">
								<a href="javascript:;" th:onclick="|like(this,1,${post.id});|" class="text-primary">
									<b th:text="${likeStatus == 1 ? '已赞':'赞'}">赞</b> <i th:text="${likeCount}">11</i>
								</a>
							</li>
							<li class="d-inline ml-2">|</li>
							<li class="d-inline ml-2"><a href="#replyform" class="text-primary">回帖 <i th:text="${post.commentCount}">7</i></a></li>
						</ul>
					</div>
				</div>
			</div>
			<!-- 正文 -->
			<div class="mt-4 mb-3 content" th:utext="${post.content}">
				金三银四的金三已经到了,你还沉浸在过年的喜悦中吗?
				如果是,那我要让你清醒一下了:目前大部分公司已经开启了内推,正式网申也将在3月份陆续开始,金三银四,春招的求职黄金时期已经来啦!!!
				再不准备,作为19应届生的你可能就找不到工作了。。。作为20届实习生的你可能就找不到实习了。。。
				现阶段时间紧,任务重,能做到短时间内快速提升的也就只有算法了,
				那么算法要怎么复习?重点在哪里?常见笔试面试算法题型和解题思路以及最优代码是怎样的?
				跟左程云老师学算法,不仅能解决以上所有问题,还能在短时间内得到最大程度的提升!!!
			</div>
		</div>
		<!-- 回帖 -->
		<div class="container mt-3">
			<!-- 回帖数量 -->
			<div class="row">
				<div class="col-8">
					<h6><b class="square"></b> <i th:text="${post.commentCount}">30</i>条回帖</h6>
				</div>
				<div class="col-4 text-right">
					<a href="#replyform" class="btn btn-primary btn-sm">&nbsp;&nbsp;回&nbsp;&nbsp;帖&nbsp;&nbsp;</a>
				</div>
			</div>
			<!-- 回帖列表 -->
			<ul class="list-unstyled mt-4">
				<li class="media pb-3 pt-3 mb-3 border-bottom" th:each="cvo:${comments}">
					<a href="profile.html">
						<img th:src="${cvo.user.headerUrl}" class="align-self-start mr-4 rounded-circle user-header" alt="用户头像" >
					</a>
					<div class="media-body">
						<div class="mt-0">
							<span class="font-size-12 text-success" th:utext="${cvo.user.username}">掉脑袋切切</span>
							<span class="badge badge-secondary float-right floor">
									<i th:text="${page.offset + cvoStat.count}">1</i>#
								</span>
						</div>
						<div class="mt-2" th:utext="${cvo.comment.content}">
							这开课时间是不是有点晚啊。。。
						</div>
						<div class="mt-4 text-muted font-size-12">
							<span>发布于 <b th:text="${#dates.format(cvo.comment.createTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-15 15:32:18</b></span>
							<ul class="d-inline float-right">
								<li class="d-inline ml-2">
									<a href="javascript:;" class="text-primary" th:onclick="|like(this,2,${cvo.comment.id})|">
										<b th:text="${cvo.likeStatus==1?'已赞':'赞'}">赞</b>(<i th:text="${cvo.likeCount}">1</i>)
									</a>
								</li>
								<li class="d-inline ml-2">|</li>
								<li class="d-inline ml-2"><a href="#" class="text-primary">回复(<i th:text="${cvo.replyCount}">2</i>)</a></li>
							</ul>
						</div>
						<!-- 回复列表 -->
						<ul class="list-unstyled mt-4 bg-gray p-3 font-size-12 text-muted">

							<li class="pb-3 pt-3 mb-3 border-bottom" th:each="rvo:${cvo.replys}">
								<div>
										<span th:if="${rvo.target==null}">
											<b class="text-info" th:text="${rvo.user.username}">寒江雪</b>:&nbsp;&nbsp;
										</span>
									<span th:if="${rvo.target!=null}">
											<i class="text-info" th:text="${rvo.user.username}">Sissi</i> 回复
											<b class="text-info" th:text="${rvo.target.username}">寒江雪</b>:&nbsp;&nbsp;
										</span>
									<span th:utext="${rvo.reply.content}">这个是直播时间哈,觉得晚的话可以直接看之前的完整录播的~</span>
								</div>
								<div class="mt-3">
									<span th:text="${#dates.format(rvo.reply.createTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-15 15:32:18</span>
									<ul class="d-inline float-right">
										<li class="d-inline ml-2">
											<a href="javascript:;" class="text-primary" th:onclick="|like(this,2,${rvo.reply.id})|">
												<b th:text="${rvo.likeStatus == 1?'已赞':'赞'}">赞</b>(<i th:text="${rvo.likeCount}">1</i>)
											</a>
										</li>
										<li class="d-inline ml-2">|</li>
										<li class="d-inline ml-2"><a th:href="|#huifu-${rvoStat.count}|" data-toggle="collapse" class="text-primary">回复</a></li>
									</ul>
									<div th:id="|huifu-${rvoStat.count}|" class="mt-4 collapse">
										<form method="post" th:action="@{|/comment/add/${post.id}|}">
											<div>
												<input type="text" class="input-size" name="content" th:placeholder="|回复${rvo.user.username}|"/>
												<input type="hidden" name="entityType" value="2">
												<input type="hidden" name="entityId" th:value="${cvo.comment.id}">
												<input type="hidden" name="targetId" th:value="${rvo.user.id}">
											</div>
											<div class="text-right mt-2">
												<button type="submit" class="btn btn-primary btn-sm" onclick="#">&nbsp;&nbsp;回&nbsp;&nbsp;复&nbsp;&nbsp;</button>
											</div>
										</form>
									</div>
								</div>
							</li>

							<!-- 回复输入框 -->
							<li class="pb-3 pt-3">
								<form method="post" th:action="@{|/comment/add/${post.id}|}">
									<div>
										<input type="text" class="input-size" name="content" placeholder="请输入你的观点"/>
										<input type="hidden" name="entityType" value="2">
										<input type="hidden" name="entityId" th:value="${cvo.comment.id}">
									</div>
									<div class="text-right mt-2">
										<button type="submit" class="btn btn-primary btn-sm" onclick="#">&nbsp;&nbsp;回&nbsp;&nbsp;复&nbsp;&nbsp;</button>
									</div>
								</form>
							</li>
						</ul>
					</div>
				</li>
			</ul>
			<!-- 分页 -->
			<nav class="mt-5" th:replace="index::pagination">
				<ul class="pagination justify-content-center">
					<li class="page-item"><a class="page-link" href="#">首页</a></li>
					<li class="page-item disabled"><a class="page-link" href="#">上一页</a></li>
					<li class="page-item active"><a class="page-link" href="#">1</a></li>
					<li class="page-item"><a class="page-link" href="#">2</a></li>
					<li class="page-item"><a class="page-link" href="#">3</a></li>
					<li class="page-item"><a class="page-link" href="#">4</a></li>
					<li class="page-item"><a class="page-link" href="#">5</a></li>
					<li class="page-item"><a class="page-link" href="#">下一页</a></li>
					<li class="page-item"><a class="page-link" href="#">末页</a></li>
				</ul>
			</nav>
		</div>
		<!-- 回帖输入 -->
		<div class="container mt-3">
			<form class="replyform" method="post" th:action="@{|/comment/add/${post.id}|}">
				<p class="mt-3">
					<a name="replyform"></a>
					<textarea placeholder="在这里畅所欲言你的看法吧!" name="content"></textarea>
					<input type="hidden" name="entityType" value="1">
					<input type="hidden" name="entityId" th:value="${post.id}">
				</p>
				<p class="text-right">
					<button type="submit" class="btn btn-primary btn-sm">&nbsp;&nbsp;回&nbsp;&nbsp;帖&nbsp;&nbsp;</button>
				</p>
			</form>
		</div>
	</div>

	<!-- 尾部 -->
	<footer class="bg-dark" th:replace="index::foot">
		<div class="container">
			<div class="row">
				<!-- 二维码 -->
				<div class="col-4 qrcode">
					<img src="https://uploadfiles.nowcoder.com/app/app_download.png" class="img-thumbnail" style="width:136px;" />
				</div>
				<!-- 公司信息 -->
				<div class="col-8 detail-info">
					<div class="row">
						<div class="col">
							<ul class="nav">
								<li class="nav-item">
									<a class="nav-link text-light" href="#">关于我们</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">加入我们</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">意见反馈</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">企业服务</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">联系我们</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">免责声明</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">友情链接</a>
								</li>
							</ul>
						</div>
					</div>
					<div class="row">
						<div class="col">
							<ul class="nav btn-group-vertical company-info">
								<li class="nav-item text-white-50">
									公司地址:北京市朝阳区大屯路东金泉时代3-2708北京牛客科技有限公司
								</li>
								<li class="nav-item text-white-50">
									联系方式:010-60728802(电话)&nbsp;&nbsp;&nbsp;&nbsp;admin@nowcoder.com
								</li>
								<li class="nav-item text-white-50">
									牛客科技©2018 All rights reserved
								</li>
								<li class="nav-item text-white-50">
									京ICP备14055008号-4 &nbsp;&nbsp;&nbsp;&nbsp;
									<img src="http://static.nowcoder.com/company/images/res/ghs.png" style="width:18px;" />
									京公网安备 11010502036488号
								</li>
							</ul>
						</div>
					</div>
				</div>
			</div>
		</div>
	</footer>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" crossorigin="anonymous"></script>
<script th:src="@{/js/global.js}"></script>
<script th:src="@{/js/discuss.js}"></script>
</body>
</html>

5. discuss.js

java 复制代码
function like(btn, entityType, entityId){
    $.post(
        CONTEXT_PATH + "/like",
        {"entityType":entityType, "entityId":entityId},
        function (data) {
            data = $.parseJSON(data);
            if(data.code == 0){
                $(btn).children("i").text(data.likeCount);
                $(btn).children("b").text(data.likeStatus = 1 ? '已赞' : '赞');
            } else {
                alert(data.msg);
            }
        }
    )
}
相关推荐
驭渊的小故事17 分钟前
Spring AI Alibaba 实战:从maven依赖治理到声明式工具调用
java·人工智能·spring
Elastic 中国社区官方博客41 分钟前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn1881 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn1 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
y1su2 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
Elcker2 小时前
YnuoAgent(依诺):一个 npm 包,跑起属于自己的 AI 研发平台
前端·人工智能·npm
计算机魔术师2 小时前
发现2天,修复2个月:AI挖穿PHP后,卡兹克讲透攻防时间差
前端
风骏时光牛马3 小时前
测试标题001
前端
我命由我123453 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒3 小时前
Java性能优化完全指南
前端·人工智能·后端