前后端数据已有,根据已有进行操作
数据库部分
建表和导入表数据
示例:
REATE TABLE t_article (
`id` int(20) NOT NULL AUTO_INCREMENT COMMENT '文章id',
`title` varchar(200) DEFAULT NULL COMMENT '文章标题',
`content` longtext COMMENT '文章内容',
`created` datetime DEFAULT NULL COMMENT '创建时间',
`modified` date DEFAULT NULL COMMENT '修改时间',
`categories` varchar(200) DEFAULT NULL COMMENT '文章分类',
`tags` varchar(255) DEFAULT NULL COMMENT '文章标签',
`allow_comment` tinyint(1) DEFAULT '0' COMMENT '是否允许评论(默认1)',
`thumbnail` varchar(255) COMMENT '文章缩略图',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
项目部署
导入前后端资源
编写配置文件
# application-jdbc.properties:
#添加并配置第三方数据库连接池Druid
spring.datasource.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=20
spring.datasource.minIdle=10
spring.datasource.maxActive=100
#Mysql数据库连接配置serverTimezone=UTC
spring.datasource.url=jdbc:mysql://localhost:3306/jsrx?useSSL=false&useServerPrepStmts=true&serverTimezone=UTC
serverTimezone=UTC&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
# application-mail.properties
#QQ邮箱发送服务配置
spring.mail.host=smtp.qq.com
spring.mail.port=587
#配置个人QQ账户和密码(密码为加密后的授权码)
spring.mail.username=jsnorx@qq.com
spring.mail.password=123456jsrx
# application-redis.properties
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-wait=-1
spring.redis.jedis.pool.max-idle=8
分页展示
创建dao包,在dao包中创建接口文件 ArticleMapper
package com.example.demo111.dao;
import com.example.demo111.model.domain.Article;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface ArticleMapper {
//根据id查询文章信息
@Select("SELECT * FROM t_article WHERE id=#{id}")
public Article selectArticleWithId(Integer id);
@Insert("INSERT INTO t_article (title,created,modified,tags,categories,"+
"allow_comment, thumbnail, content)" +
"VALUES (#{title}, #{created},#{modified},#{tags},#{categories},"+
"#{allowComment},#{thumbnail},#{content})")
@Options(useGeneratedKeys = true,keyProperty = "id",keyColumn = "id")
public Integer publishArticle(Article article);
// 文章分布页查询
@Select("SELECT * FROM t_article ORDER BY id DESC")
public List<Article> selectArticleWithPage();
// 通过id删除文章
@Delete("DELETE FROM t_article WHERE id=#{id}")
public void deleteArticleWithId(int id);
//
@Select("SELECT COUNT(1) FROM t_article")
public Integer countArticle();
// 通过id更新文章
public Integer updateArticleWithId(Article article);
}
和接口文件StatisticMapper
package com.example.demo111.dao;
import com.example.demo111.model.domain.Article;
import com.example.demo111.model.domain.Statistic;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface StatisticMapper {
//
@Insert("INSERT INTO t_statistic(article_id,hits,comments_num) values (#{id},0,0)")
public void addStatistic(Article article);
//
@Select("SELECT * FROM t_statistic WHERE article_id=#{articleId}")
public Statistic selectStatisticWithArticleId(Integer articleId);
//
@Update("UPDATE t_statistic SET hits=#{hits}" + " WHERE article_id=#{articleId}")
public void updateArticleHitsWithId(Statistic statistic);
//
@Update("UPDATE t_statistic SET comments_num=#{commentsNum}"+" WHERE article_id=#{articleId}")
public void updateArticleCommentsWithId(Statistic statistic);
//
@Delete("DELETE FROM t_statistic WHERE article_id=#{aid}")
public void deleteStatisticWithId(int aid);
//
@Select("SELECT * FROM t_statistic WHERE hits !='0' " + "ORDER BY hits DESC, comments_num DESC")
public List<Statistic> getStatistic();
//
@Select("SELECT SUM(hits) FROM t_statistic")
public long getTotalVisit();
//
@Select("SELECT SUM(comments_num) FROM t_statistic")
public long getTotalComment();
}
在 resources 目录下创建 包mapper,在包下创建 ArticleMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo111.dao.ArticleMapper">
<update id="updateArticleWithId" parameterType="Article">
update t_article
<set>
<if test="title != null">
title = #{title},
</if>
<if test="created != null">
created = #{created},
</if>
<if test="modified != null">
modified = #{modified},
</if>
<if test="tags != null">
tags = #{tags},
</if>
<if test="categories != null">
categories = #{categories},
</if>
<if test="hits != null">
hits = #{hits},
</if>
<if test="commentsNum != null">
comments_num = #{commentsNum},
</if>
<if test="allowComment != null">
allow_comment = #{allowComment},
</if>
<if test="thumbnail != null">
thumbnail = #{thumbnail},
</if>
<if test="content != null">
content = #{content},
</if>
</set>
where id = #{id}
</update>
</mapper>
创建 包service ,在包中创建接口 IArticleService.java
package com.example.demo111.service;
import com.example.demo111.model.domain.Article;
import com.github.pagehelper.PageInfo;
import java.util.List;
public interface IArticleService {
public PageInfo<Article> selectArticleWithPage(Integer page, Integer count);
public List<Article> getHeatArticles();
}
在Service包下创建包 impl, 在该包下创建类ArticleServicelmapl
package com.example.demo111.service.impl;
import com.example.demo111.dao.ArticleMapper;
import com.example.demo111.dao.StatisticMapper;
import com.example.demo111.model.domain.Article;
import com.example.demo111.model.domain.Statistic;
import com.example.demo111.service.IArticleService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.vdurmont.emoji.EmojiParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
@Transactional
public class ArticleServiceImpl implements IArticleService {
@Autowired
private ArticleMapper articleMapper;
@Autowired
private StatisticMapper statisticMapper;
@Override
public PageInfo<Article> selectArticleWithPage(Integer page, Integer count){
PageHelper.startPage(page, count);
List<Article> articleList = articleMapper.selectArticleWithPage();
for (int i = 0; i < articleList.size();i++){
Article article = articleList.get(i);
Statistic statistic = statisticMapper.selectStatisticWithArticleId(article.getId());
article.setHits(statistic.getHits());
article.setCommentsNum(statistic.getCommentsNum());
}
PageInfo<Article> pageInfo=new PageInfo<>(articleList);
return pageInfo;
}
@Override
public List<Article> getHeatArticles(){
List<Statistic> list = statisticMapper.getStatistic();
List<Article> articlelist=new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
Article article =
articleMapper.selectArticleWithId(list.get(i).getArticleId());
article.setHits(list.get(i).getHits());
article.setCommentsNum(list.get(i).getCommentsNum());
articlelist.add(article);
if(i>=9){
break;
}
}
return articlelist;
}
}
在项目中创建 web.client 的包,在包client中创建 IndexController.java
package com.example.demo111.web.client;
import com.example.demo111.model.domain.Article;
import com.example.demo111.model.domain.Comment;
import com.example.demo111.service.IArticleService;
import com.example.demo111.service.ICommentService;
import com.example.demo111.service.ISiteService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Controller
public class IndexController {
private static final Logger logger = LoggerFactory.getLogger(IndexController.class);
@Autowired
private IArticleService articleServiceImpl;
//
@GetMapping(value = "/")
private String index(HttpServletRequest request){
return this.index(request, 1, 5);
}
//
@GetMapping(value = "/page/{p}")
public String index(HttpServletRequest request, @PathVariable("p") int page,
@RequestParam(value = "count",defaultValue = "5") int count) {
PageInfo<Article> articles = articleServiceImpl.selectArticleWithPage(page, count);
//
List<Article> articleList = articleServiceImpl.getHeatArticles();
request.setAttribute("articles", articles);
request.setAttribute("articleList", articleList);
logger.info("分页获取文章信息: 页码" +page+",条数 "+count);
return "client/index";
}
}
在 web目录下创建 interceptor包,在包中创建 类 BaseInterceptor.java
package com.example.demo111.web.interceptor;
import com.example.demo111.utils.Commons;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Configuration
public class BaseInterceptor implements HandlerInterceptor {
@Autowired
private Commons commons;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception{
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView)throws Exception{
request.setAttribute("commons", commons);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex)throws Exception{
}
}
在Interceptor包下,编写类 WebMvcConfig.java
package com.example.demo111.web.interceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private BaseInterceptor baseInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(baseInterceptor);
}
}
评论管理
在Service下的ICommentService中编写
//用户发表评论
public void pushComment(Comment comment);
在CommentServiceImpl中添加
@Autowired
private StatisticMapper statisticMapper;
//
@Override
public void pushComment(Comment comment){
commentMapper.pushComment(comment);
//
Statistic statistic =
statisticMapper.selectStatisticWithArticleId(comment.getArticleId());
statistic.setCommentsNum(statistic.getCommentsNum()+1);
statisticMapper.updateArticleCommentsWithId(statistic);
}
在web.client包下创建类CommentController.java:
package com.example.demo111.web.client;
import com.example.demo111.model.ResponseData.ArticleResponseData;
import com.example.demo111.model.domain.Comment;
import com.example.demo111.service.ICommentService;
import com.example.demo111.utils.MyUtils;
import com.vdurmont.emoji.EmojiParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
@Controller
@RequestMapping("/comments")
public class CommentController {
private static final Logger logger=
LoggerFactory.getLogger(CommentController.class);
@Autowired
private ICommentService commentServiceImpl;
//
@PostMapping(value = "/publish")
@ResponseBody
public ArticleResponseData publishComment(HttpServletRequest request,
@RequestParam Integer aid, @RequestParam String text){
//
text = MyUtils.cleanXSS(text);
text = EmojiParser.parseToAliases(text);
//
User user=
(User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//
Comment comments = new Comment();
comments.setArticleId(aid);
comments.setIp(request.getRemoteAddr());
comments.setCreated(new Date());
comments.setAuthor(user.getUsername());
comments.setContent(text);
try {
commentServiceImpl.pushComment(comments);
logger.info("发布评论成功,对应文章ID:"+aid);
return ArticleResponseData.ok();
} catch (Exception e){
logger.error("发布评论失败,对应文章ID:"+aid+";错误描述:"+e.getMessage());
return ArticleResponseData.fail();
}
}
}
文章发布
在Service下的IArticleService:
//发布文章
public void publish(Article article);
在ArticleServiceImpl中添加
//发布文章
@Override
public void publish(Article article){
//去除表情
article.setContent(EmojiParser.parseToAliases(article.getContent()));
article.setCreated(new Date());
article.setHits(0);
article.setCommentsNum(0);
//插入文章,同时插入文章统计数据
articleMapper.publishArticle(article);
statisticMapper.addStatistic(article);
}
在AdminController中添加
@Autowired
private IArticleService articleServiceImpl;
// 向文章发表页面跳转
@GetMapping(value = "/article/toEditPage")
public String newArticle( ){
return "back/article_edit";
}
// 发表文章
@PostMapping(value = "/article/publish")
@ResponseBody
public ArticleResponseData publishArticle(Article article) {
//isBlank
if (StringUtils.isBlank(article.getCategories())) {
article.setCategories("默认分类");
}
try {
articleServiceImpl.publish(article);
logger.info("文章发布成功");
return ArticleResponseData.ok();
} catch (Exception e) {
logger.error("文章发布失败,错误信息:"+e.getMessage());
return ArticleResponseData.fail();
}
}
// 跳转到后台文章列表页面
@GetMapping(value = "/article")
public String index(@RequestParam(value = "page", defaultValue = "1")int page,
@RequestParam(value = "count", defaultValue = "10") int count,
HttpServletRequest request) {
PageInfo<Article> pageInfo = articleServiceImpl.selectArticleWithPage
(page, count);
request.setAttribute("articles",pageInfo);
return "back/article_list";
}
文章修改
在IArticleService中添加
// 根据主键更新文章
public void updateArticleWithId(Article article);
在ArticleServiceImpl中添加
//更新文章
@Override
public void updateArticleWithId(Article article){
article.setModified(new Date());
articleMapper.updateArticleWithId(article);
redisTemplate.delete("article_" + article.getId());
}
在AdminController中添加
// 向文章修改页跳转
@GetMapping(value = "/article/{id}")
public String editArticle(@PathVariable("id") String
id, HttpServletRequest request) {
Article article = articleServiceImpl.selectArticleWithId(Integer.parseInt(id));
request.setAttribute("contents", article);
request.setAttribute("categories", article.getCategories());
return "back/article_edit";
}
//修改文章
@PostMapping(value = "/article/modify")
@ResponseBody
public ArticleResponseData modifyArticle(Article article) {
try {
articleServiceImpl.updateArticleWithId(article);
logger.info("文章更新成功");
return ArticleResponseData.ok();
} catch (Exception e){
logger.error("文章更新失败,错误信息:" +e.getMessage());
return ArticleResponseData.fail();
}
}