package com.kuls.controller.admin;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.kuls.po.Blog;
import com.kuls.po.User;
import com.kuls.service.admin.BlogService;
import com.kuls.service.admin.TagService;
import com.kuls.service.admin.TypeService;
import com.kuls.vo.BlogQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//这个控制器类提供了后台博客管理的一系列功能,包括博客列表展示、搜索、编辑、保存、更新、删除以及图片上传等操作。
@Controller//Spring MVC 的控制器类,用于处理与博客管理相关的请求
@RequestMapping("/admin")//所有路径以/admin开头
public class BlogAdminController {
@Autowired
private BlogService blogService;
@Autowired
private TypeService typeService;
@Autowired
private TagService tagService;
/**
* 后台显示博客列表
*
* @param pageNum 显示第几页
* @param pageSize 每页展示的数量
* @param model 前端model
* @return
*/
@GetMapping("/blogs")
public String toBlogs(@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "5") int pageSize,
Model model) {
PageHelper.startPage(pageNum, pageSize);//使用PageHelper进行分页
//传递一个空对象即可
BlogQuery blog = new BlogQuery();
List<Blog> lists = blogService.listBlog(blog);
PageInfo<Blog> blogPageInfo = new PageInfo<>(lists);
model.addAttribute("blogs", blogPageInfo);
model.addAttribute("types", typeService.listType());
// mybatis plus
return "admin/blogs";
}
/**
* 后台博客搜索功能
*
* @param pageNum
* @param pageSize
* @param blog
* @param model
* @return
*/
@PostMapping("/blogs/search")
public String search(@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "5") int pageSize,
BlogQuery blog,
Model model) {
PageHelper.startPage(pageNum, pageSize);
// 根据BlogQuery对象的属性来进行查询
List<Blog> lists = blogService.listBlog(blog);
PageInfo<Blog> blogPageInfo = new PageInfo<>(lists);
model.addAttribute("blogs", blogPageInfo);
model.addAttribute("types", typeService.listType());
return "admin/blogs :: blogList";
}
/**
* 博客编辑和发表
*
* @param model
* @return
*/
@GetMapping("/blogs/input")
public String input(Model model) {
model.addAttribute("types", typeService.listType());
model.addAttribute("tags", tagService.listTag());
model.addAttribute("blog", new Blog());//所有博客类型和标签添加到Model中,并添加一个空的Blog对象,用于在视图中初始化表单。
return "admin/blogs-input";
}
/**
* 更新编辑博客
*
* @param id 指定博客的id
* @param model
* @return
*/
@GetMapping("/blogs/{id}/update")
public String editBlog(@PathVariable long id, Model model) {
model.addAttribute("types", typeService.listType());
model.addAttribute("tags", tagService.listTag());
Blog blog = blogService.getBlogByID(id);
model.addAttribute("blog", blog);
return "admin/blogs-input";
}
/**
* 保存或者发布博客
*
* @param blog
* @param session
* @param attributes
* @return
*/
@PostMapping("/blogs/save")
public String save(Blog blog, HttpSession session, RedirectAttributes attributes) {
User user = (User) session.getAttribute("user");
// 获取当前用户
if (user != null){
blog.setUser(user);
blog.setType(typeService.getType(blog.getType().getId()));
blog.setTages(tagService.listTag(blog.getTagIds()));
int save = blogService.save(blog);
if (save > 0) {
attributes.addFlashAttribute("msg", "操作成功");
} else {
attributes.addFlashAttribute("errormsg", "操作失败");
}
return "redirect:/admin/blogs";
}else {
return "redirect:/admin/index";
}
}
/**
* 更新博客
*
* @param blog
* @param session
* @param attributes
* @return
*/
@PostMapping("/updateBlogs")
public String updateBlogs(Blog blog, HttpSession session, RedirectAttributes attributes) {
blog.setUser((User) session.getAttribute("user"));
blog.setType(typeService.getType(blog.getType().getId()));
blog.setTages(tagService.listTag(blog.getTagIds()));
int update = blogService.updateBlog(blog);
if (update > 0) {
attributes.addFlashAttribute("msg", "操作成功");
} else {
attributes.addFlashAttribute("errormsg", "操作失败");
}
return "redirect:/admin/blogs";
}
/**
* 删除博客
*
* @param id
* @param redirectAttributes
* @return
*/
@GetMapping("/blogs/{id}/delete")
public String deleteBlog(@PathVariable Long id, RedirectAttributes redirectAttributes) {
int i = blogService.deleteBlog(id);
if (i > 0) {
redirectAttributes.addFlashAttribute("msg", "删除成功!");
} else {
redirectAttributes.addFlashAttribute("errormsg", "删除失败!");
}
return "redirect:/admin/blogs";
}
/**
* 博客内容中插入的图片
* @param file
* @param request
* @return
*/
@PostMapping(value = "/uploadfile")
@ResponseBody
public Map<String,Object> demo(@RequestParam(value = "editormd-image-file", required = false) MultipartFile file, HttpServletRequest request) {
Map<String,Object> resultMap = new HashMap<String,Object>();
//保存
try {
File imageFolder= new File(request.getServletContext().getRealPath("img/upload/blog/"));
File targetFile = new File(imageFolder,file.getOriginalFilename());
if(!targetFile.getParentFile().exists()){
targetFile.mkdirs();
}
// 将文件写入targetFile中
file.transferTo(targetFile);
resultMap.put("success", 1);
resultMap.put("message", "上传成功!");
resultMap.put("url","/img/upload/blog/"+file.getOriginalFilename());
} catch (Exception e) {
resultMap.put("success", 0);
resultMap.put("message", "上传失败!");
e.printStackTrace();
}
return resultMap;
}
}
package com.kuls.controller.front;
import com.kuls.exception.BlogNotFoundException;
import com.kuls.mapper.BlogTagMapper;
import com.kuls.po.Blog;
import com.kuls.service.CommentService;
import com.kuls.service.admin.BlogService;
import com.kuls.service.admin.LinkService;
import com.kuls.service.admin.TagService;
import com.kuls.service.admin.TypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class BlogFrontController {
@Autowired
private BlogService blogService;
@Autowired
private TagService tagService;
@Autowired
private BlogTagMapper blogTagMapper;
@Autowired
private LinkService linkService;
/**
* 显示指定博客详情信息
*
* @param id
* @param model
* @return
*/
@GetMapping({"/blog/{id}"})
public String blogDetail(
@PathVariable long id,
Model model) {
Blog blog = blogService.getBlogOnfront(id);
if (blog == null){
throw new BlogNotFoundException("很抱歉,这篇博客不存在~");
}
blogService.incView(id);
model.addAttribute("blog", blog);
model.addAttribute("tags", tagService.listTag(blogTagMapper.selectByBlogId(id)));
model.addAttribute("links", linkService.listAllOnFront());
return "blog";
}
}
package com.kuls.mapper;
import com.kuls.po.Blog;
import com.kuls.vo.BlogQuery;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
//接口部分:利用Mybatis框架对数据库表进行增删改查等操作
@Mapper//对MyBatis框架的注解,用于标记该接口为 MyBatis 的 Mapper 接口,Spring 会自动扫描并为其生成代理实现,使得接口方法能够与 SQL 语句进行绑定,从而实现对数据库的操作。
@Repository//Spring 框架的注解,用于将该接口标记为数据访问组件。它主要用于将数据访问层的异常转换为 Spring 统一的数据访问异常体系,同时便于将该组件纳入 Spring 的依赖注入和事务管理体系。
public interface BlogMapper {
Blog getBlogByID(Long id);//根据传入的博客id获取博客信息
//查出所有博客
List<Blog> listBlog(BlogQuery blog);
//查出所有博客显示在前端页面
List<Blog> listBlogOnFront(BlogQuery blog);
//热门文章查询
List<Blog> listBlogOnFrontHot(BlogQuery blog);
//实现博客阅读数的增加
int incView(Blog blog);
//实现博客喜欢数的增加
int incLikes(Blog blog);
int save(Blog blog);//保存博客
int updateBlog(Blog blog);//修改、更新博客
int deleteBlog(@Param("id") Long id);//删除博客
}
package com.kuls.po;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import java.util.List;
//Blog 类是一个 Java POJO(Plain Old Java Object),用于表示博客系统中的博客实体。
// 它包含了博客的各种属性,如基本信息、发布状态、时间戳、关联的类型、标签、用户以及评论等,通过这些属性全面地描述了一个博客的相关信息,为博客系统的业务逻辑和数据传输提供了数据载体。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
private Long id;
private String title;
private String content;
private String firstPicture;
private String flag;
private Integer view;
private Integer likes;
private String description;
private boolean appreciation;
private boolean shareStatement;
private boolean commentabled;
private boolean published;
private boolean recommend;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")//使用 @JsonFormat 注解确保在序列化时按照指定格式和时区展示。
private Date createTime;
private Date updateTime;
private Type type;
private List<Tag> tages;
//tagIds不会进入数据库
private String tagIds;
private User user;
private List<Comment> comments;
}
package com.kuls.service.admin.impl;
import com.kuls.exception.BlogNotFoundException;
import com.kuls.mapper.BlogMapper;
import com.kuls.mapper.BlogTagMapper;
import com.kuls.mapper.TagMapper;
import com.kuls.po.Blog;
import com.kuls.po.Tag;
import com.kuls.service.RedisService;
import com.kuls.service.admin.BlogService;
import com.kuls.service.admin.TagService;
import com.kuls.util.MarkdownUtils;
import com.kuls.util.MyBeanUtils;
import com.kuls.vo.BlogLikedCount;
import com.kuls.vo.BlogQuery;
import com.kuls.vo.BlogViewCount;
import io.lettuce.core.ScriptOutputType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
@Service
public class BlogServiceImpl implements BlogService {
@Autowired
private BlogMapper blogMapper;
@Autowired
private TagService tagService;
@Autowired
private BlogTagMapper blogTagMapper;
@Autowired
private TagMapper tagMapper;
@Autowired
private RedisService redisService;
@Transactional
@Override
public Blog getBlogByID(Long id) {
Blog blog = blogMapper.getBlogByID(id);
List<Long> longList = blogTagMapper.selectByBlogId(id);
List<Tag> tags = tagMapper.listTag1(longList);
String s = tagsToIds(tags);
blog.setTagIds(s);
return blog;
}
@Override
public Blog getBlogOnfront(Long id) {
Blog blog = blogMapper.getBlogByID(id);
if (blog == null) {
throw new BlogNotFoundException("博客不存在!");
}
Blog blog1 = new Blog();
BeanUtils.copyProperties(blog, blog1);
String content = blog1.getContent();
blog1.setContent(MarkdownUtils.markdownToHtmlExtensions(content));
return blog1;
}
//1,2,3
private String tagsToIds(List<Tag> tags) {
if (!tags.isEmpty()) {
StringBuffer ids = new StringBuffer();
boolean flag = false;
for (Tag tag : tags) {
if (flag) {
ids.append(",");
} else {
flag = true;
}
ids.append(tag.getId());
}
return ids.toString();
} else {
return null;
}
}
@Transactional
@Override
public int save(Blog blog) {
blog.setCreateTime(new Date());
blog.setUpdateTime(new Date());
blog.setLikes(1);
blog.setView(1);
int save = blogMapper.save(blog);
handlerBlogTag(blog.getId(), blog.getTages());
return save;
}
void handlerBlogTag(Long blogId, List<Tag> tags) {
for (Tag tag : tags) {
blogTagMapper.insertBlogTag(blogId, tag.getId());
}
}
@Transactional
@Override
public List<Blog> listBlog(BlogQuery blog) {
return blogMapper.listBlog(blog);
}
@Transactional
@Override
public List<Blog> listBlogOnFront(BlogQuery blog) {
return blogMapper.listBlogOnFront(blog);
}
@Override
public List<Blog> listBlogOnFrontHot(BlogQuery blog) {
return blogMapper.listBlogOnFrontHot(blog);
}
@Transactional
@Override
public int incView(long id) {
Blog blog = new Blog();
blog.setId(id);
return blogMapper.incView(blog);
}
@Transactional
@Override
public int incLikes() {
List<BlogLikedCount> likedCountsList = redisService.getLikedCountFromRedis();
for (BlogLikedCount count : likedCountsList) {
Blog blog = new Blog();
Integer blogId = count.getBlogId();
long l = blogId.longValue();
blog.setId(l);
blog.setLikes(count.getAddLikedCount());
System.out.println("这里是like的值:" + count.getAddLikedCount());
blogMapper.incLikes(blog);
}
return 1;
}
@Transactional
@Override
public int updateBlog(Blog blog) {
Blog blog1 = blogMapper.getBlogByID(blog.getId());
BeanUtils.copyProperties(blog, blog1, MyBeanUtils.getNullPropertyNames(blog));
blog1.setUpdateTime(new Date());
int update = blogMapper.updateBlog(blog1);
//删除所有标签(之后优化)
blogTagMapper.delete(blog.getId());
//插入新的标签
handlerBlogTag(blog.getId(), blog.getTages());
return update;
}
@Transactional
@Override
public int deleteBlog(Long id) {
return blogMapper.deleteBlog(id);
}
}
package com.kuls.service.admin;
import com.kuls.po.Blog;
import com.kuls.vo.BlogQuery;
import java.util.List;
public interface BlogService {
Blog getBlogByID(Long id);
Blog getBlogOnfront(Long id);
int save(Blog blog);
//查出所有博客
List<Blog> listBlog(BlogQuery blog);
List<Blog> listBlogOnFront(BlogQuery blog);
//热门文章
List<Blog> listBlogOnFrontHot(BlogQuery blog);
//实现博客阅读数的增加
int incView(long id);
//批量增加博客喜欢数
int incLikes();
int updateBlog(Blog blog);
int deleteBlog(Long id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--指定该映射文件对应的接口-->
<mapper namespace="com.kuls.mapper.BlogMapper">
<!--根据id获取文章
paramaterType 指定传入参数为long类型的博客ID,resultMap指定使用BlogMap进行结果映射-->
<select id="getBlogByID" parameterType="long" resultMap="BlogMap">
select id,title,content,first_picture,likes,
flag,view,description,appreciation,share_statement,commentabled,published,
recommend, create_time ,update_time
,type_id from t_blog where id=#{id};
</select>
<!--给前端页面显示的博客文章:已发布的-->
<select id="listBlogOnFront" resultMap="BlogMap">
select id,title,content,first_picture,likes,
flag,view,description,appreciation,share_statement,commentabled,published,
recommend, create_time ,update_time
,type_id from t_blog
-- 选择已经发布的博客,其中标题模糊查询、推荐状态精准查询、类型id精准查询
<where>
and published = true
<if test="title != null and title != ''">
and title like concat('%',#{title},'%')
</if>
<if test="recommend != null and recommend != ''">
and recommend = #{recommend}
</if>
<if test="typeId != null and typeId != ''">
and type_id = #{typeId}
</if>
</where>
order by update_time DESC
</select>
<!--给前端页面显示的博客文章:热门的前五-->
<select id="listBlogOnFrontHot" resultMap="BlogMap">
select id,title,content,first_picture,likes,
flag,view,description,appreciation,share_statement,commentabled,published,
recommend, create_time ,update_time
,type_id from t_blog
<where>
and published = true
</where>
order by view DESC limit 0,5<!--降序排序,显示前5条-->
</select>
<!--后台获取博客信息、用于后台管理-->
<select id="listBlog" resultMap="BlogMap">
select id,title,content,first_picture,likes,
flag,view,description,appreciation,share_statement,commentabled,published,
recommend, create_time ,update_time
,type_id from t_blog
<where>
<if test="title != null and title != ''">
and title like concat('%',#{title},'%')<!--标题模糊查询-->
</if>
<if test="recommend != null and recommend != ''">
and recommend = #{recommend}<!--推荐状态精准查询-->
</if>
<if test="typeId != null and typeId != ''">
and type_id = #{typeId}<!--//类型id精准查询-->
</if>
</where>
order by update_time DESC
</select>
<!--使用id分别获取博客类型和用户信息-->
<select id="getType" resultType="Type">
select * from t_type where id=#{id};
</select>
<select id="getUser" resultType="User">
select * from t_user where id=#{id};
</select>
<!--BlogMap结果映射-->
<resultMap id="BlogMap" type="Blog">
<result property="id" column="id"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
<result property="firstPicture" column="first_picture"/>
<result property="flag" column="flag"/>
<result property="view" column="view"/>
<result property="appreciation" column="appreciation"/>
<result property="shareStatement" column="share_statement"/>
<result property="commentabled" column="commentabled"/>
<result property="published" column="published"/>
<result property="recommend" column="recommend"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="description" column="description"/>
<result property="likes" column="likes"/>
<association property="type" column="type_id" javaType="Type" select="getType">
<result property="name" column="tname"/>
</association>
</resultMap>
<!--useGeneratedKeys="true" keyProperty="id" 这两个属性会返回id主键的值-->
<!--通过 MyBatis 实现了将一个新的博客记录插入到t_blog表中,
并在插入成功后获取数据库自动生成的主键值填充到传入的Blog对象的id属性中-->
<insert id="save" parameterType="Blog" useGeneratedKeys="true" keyProperty="id">
insert into t_blog(id,title,content,first_picture,likes,
flag,view,description,appreciation,share_statement,commentabled,published,
recommend,create_time,update_time,type_id,user_id) values (#{id},
#{title},#{content},#{firstPicture},#{likes},#{flag},#{view},#{description},#{appreciation},#{shareStatement},
#{commentabled},#{published},#{recommend},#{createTime},#{updateTime},#{type.id},#{user.id}
);
</insert>
<update id="incView" parameterType="Blog">
update t_blog set
view = view + 1
where id =#{id}
<!--//#{id}是 MyBatis 的占位符,在执行 SQL 时,MyBatis 会从传入的Blog对象中获取id属性的值,并替换这个占位符。
--> </update>
<update id="incLikes" parameterType="Blog">
update t_blog set
likes = likes + #{likes}
where id =#{id}
</update>
<!--这段 MyBatis 的<update>标签定义了一个用于更新博客信息的 SQL 操作。
它根据传入的Blog对象中的id,找到数据库中对应的博客记录,并使用Blog对象中的其他属性值更新该记录的相应字段。-->
<update id="updateBlog" parameterType="Blog" useGeneratedKeys="true" keyProperty="id">
update t_blog set title = #{title},
content = #{content},
first_picture=#{firstPicture},
description=#{description},
flag = #{flag},
view = #{view},
appreciation=#{appreciation},
share_statement=#{shareStatement},
commentabled=#{commentabled},
published=#{published},
recommend=#{recommend},
create_time=#{createTime},
update_time=#{updateTime},
type_id=#{type.id},
user_id=#{user.id}
where id = #{id};
</update>
<delete id="deleteBlog" parameterType="long">
delete from t_blog where id=#{id}
</delete>
</mapper>
根据以上代码,给出我个人博客管理系统文章管理方面的类图