JavaWeb中點贊功能的實現及完整實例


實現原理
1、功能描述:一個用戶對同一文章只能點贊一次,第二次就是取消贊
2、建立一個點贊表great,字段有文章ID(aid),點贊用戶ID(uid)
3、當有用戶進行點贊行為時,使用aid和uid搜索點贊表。

若有該記錄,則表示用戶已經點過贊,本次點擊是取消點贊行為,故刪除great表中的該條記錄,同時將該文章的點贊數減1。
若無該記錄,則表示用戶是要點贊,故在great表中添加該記錄,同時該文章的點贊數加1。
核心代碼分析
核心控制器BaseController:

@Controller
public class BaseController {
    private final GreatRepository greatRepository;
    private final ArticleRepository articleRepository;
    //Spring團隊推薦的做法是用構造器來引入依賴,而不是直接使用@Autowired引入
    @Autowired
    public BaseController(GreatRepository greatRepository,
                          ArticleRepository articleRepository) {
        this.greatRepository = greatRepository;
        this.articleRepository=articleRepository;
    }

    @RequestMapping({"/","/index"})
    public String index(){
        return "index";
    }

    //添加事務支持
    @Transactional
    @RequestMapping("/great")
    public String great(@Param("aid") int aid, @Param("uid") int uid, Model model){
        //查詢是否有該用戶對該文章的點贊記錄
        List<Great> list=greatRepository.findByAidAndUid(aid,uid);
        if (list!=null && list.size()>0){
            //如果找到了這條記錄,則刪除該記錄,同時文章的點贊數減1
            Great great=list.get(0);
            //刪除記錄
            greatRepository.delete(great.getId());
            //文章點贊數減1,查詢時使用Mysql行級鎖解決並發覆蓋問題
            Article article=articleRepository.findByIdForUpdate(aid);
            article.setGreatNum(article.getGreatNum()-1);
            articleRepository.saveAndFlush(article);
        }else {
            //如果沒有找到這條記錄,則添加這條記錄,同時文章點贊數加1
            Great great=new Great();
            great.setAid(aid);
            great.setUid(uid);
            //添加記錄
            greatRepository.saveAndFlush(great);
            //文章點贊數加1,查詢時使用Mysql行級鎖解決並發覆蓋問題
            Article article=articleRepository.findByIdForUpdate(aid);
            article.setGreatNum(article.getGreatNum()+1);
            articleRepository.saveAndFlush(article);
        }
        model.addAttribute("details",articleRepository.findAll());
        return "detail";
    }

}


Aritcle實體的持久化倉庫ArticleRepository

@Repository
public interface ArticleRepository extends JpaRepository<Article,Integer>{
    @Lock(value = LockModeType.PESSIMISTIC_WRITE)
    Article findByIdForUpdate(Integer id);
}

注意其中使用了@Lock注解以及 LockModeType.PESSIMISTIC_WRITE來讓JPA使用數據庫層的行級鎖,在事務中,該行級鎖能解決對同一條記錄的並發修改問題。

代碼中已經附有詳細注解

完整實例的相關信息
為了突出重點,項目前端較為簡陋,功能已經通過測試。
項目采用的框架:
1、容器框架:SpringBoot
2、持久層框架:Spring Data JPA
3、渲染框架:Thymeleaf
4、版本控制:Git
5、依賴:Maven
6、數據庫:Mysql
數據庫建表文件Schema.sql:

DROP TABLE IF EXISTS `article`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `article` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `num` int(11) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `article`
--

LOCK TABLES `article` WRITE;
/*!40000 ALTER TABLE `article` DISABLE KEYS */;
INSERT INTO `article` VALUES (1,1),(2,0);
/*!40000 ALTER TABLE `article` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `great`
--

DROP TABLE IF EXISTS `great`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `great` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `aid` int(11) NOT NULL,
  `uid` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `great`
--

LOCK TABLES `great` WRITE;
/*!40000 ALTER TABLE `great` DISABLE KEYS */;
INSERT INTO `great` VALUES (5,1,1);
/*!40000 ALTER TABLE `great` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;


特別說明:本文章的目的只是單純向大家說明點贊這個功能的實現思路。為了保證邏輯盡量清晰和簡單,因而並沒有涉及到性能優化。示例代碼中的鎖機制能保證並發訪問下的安全性,但會對系統並發性能產生一定的影響,但在一般系統中,由於大量用戶同時對同一文章集中點贊的情況並不常見,因此性能損耗扔在可以接受的范圍內。

如果大家在使用過程中確實有高並發的需要,那么可以考慮使用Redis這類緩存數據庫來替代mysql。Redis是高性能的內存KV數據庫,且是單線程運行的,因此性能和安全性問題都能得到完美的解決。

關於JPA中如何使用行級鎖,可以參考這篇文章:https://blog.csdn.net/fengyuxue11011/article/details/47039765


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM