▮项目目录
【Spring Boot项目】博客系统-项目讲解

▮advice
▪ExceptionAdvice
@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {
@ExceptionHandler(Exception.class)
public ResultAjax exceptionHandler(Exception e){
log.error(e.getMessage());
return ResultAjax.fail(ResultCode.ERROR_SERVICES);
}
}
▪ResponseAdvice
@Slf4j
@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//1.body是统一返回类型则直接返回
if(body instanceof ResultAjax){
return body;
}
//2.非统一返回类型则主动包成返回类型返回
log.error("返回类型不为ResultAjax");
return ResultAjax.fail(ResultCode.ERROR_SERVICES,body);
}
}
▮common
▪AppVar
public class AppVar {
//1.会话的key值
public static final String SESSION_USER = "USER_KEY";
//2.正文剪切出简介的最大长度
public static final int SUB_CONTENT_LENGTH = 80;
}
▪ResultAjax
@Data
public class ResultAjax {
//状态码
private int code;
//描述信息
private String msg;
//数据
private Object data;
//1.私有化构造方法
private ResultAjax(ResultCode resultCode, Object data) {
this.code = resultCode.getCode();
this.msg = resultCode.getMessage();
this.data = data;
}
//2.“成功”的工厂方法
public static ResultAjax succ(Object data){
return new ResultAjax(ResultCode.SUCCESS,data);
}
public static ResultAjax succ(){
return new ResultAjax(ResultCode.SUCCESS,null);
}
//3.“失败”的工厂方法
public static ResultAjax fail(ResultCode resultCode){
return new ResultAjax(resultCode,null);
}
public static ResultAjax fail(ResultCode resultCode,Object data){
return new ResultAjax(resultCode,data);
}
}
▪ResultCode
public enum ResultCode {
//4.定义枚举
SUCCESS (200,"操作成功"),
FAILED (1000,"操作失败"),
FAILED_PARAMS_VALIDATE (1001,"参数校验失败"),
FAILED_CREATE (1002,"新增失败"),
FAILED_USER_EXISTS (1101,"⽤⼾已存在"),
FAILED_USER_NOT_EXISTS (1102,"⽤⼾不存在"),
FAILED_LOGIN (1103,"⽤⼾名或密码错误"),
ERROR_SERVICES (2000,"服务器内部错误"),
ERROR_IS_NULL (2001,"IS NULL.");
//1.定义属性
private int code; //状态码
private String message; //描述信息
//2. 定义构造
ResultCode(int code, String message) {
this.code = code;
this.message = message;
}
//3. 生成get方法
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
▮config
▪AppConfig
@Configuration
public class AppConfig implements WebMvcConfigurer {
//注入自定义的登录拦截器
@Autowired
LoginInterceptor loginInterceptor;
//配置登录拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加自定义登录拦截器
registry.addInterceptor(loginInterceptor)
//添加要拦截的url,“/**”表示拦截所有
.addPathPatterns("/**")
//添加不拦截的url
.excludePathPatterns("/user/reg") //注册请求
.excludePathPatterns("/user/login") //登录请求
.excludePathPatterns("/login.html") //登录界面
.excludePathPatterns("/reg.html") //注册界面
.excludePathPatterns("/css/*") //所有的css文件
.excludePathPatterns("/js/*") //所有的js文件
.excludePathPatterns("/editor.md/*")//editor.md编辑器
.excludePathPatterns("/img/*"); //所有的图片文件
}
}
▪LoginInterceptor
@Component
public class LoginInterceptor implements HandlerInterceptor {
/*------------------------------------------------------------------------------------------------------------------
* @Desc : 定义前置方法,即定义拦截器
* @Param : [request, response, handler]
* @Return: boolean
**/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.得到当前请求会话
HttpSession session = request.getSession(false);
//2.检验会话是否存在,则返回true,表示可以通过
if(session != null && session.getAttribute(AppVar.SESSION_USER) != null){
return true;
}
//3.不存在则跳转至登录界面,并返回false,表示不可通过
response.sendRedirect("login.html");
return false;
}
}
▮controller
▪BlogController
@Slf4j
@RestController
@RequestMapping("/blog")
public class BlogController {
@Autowired
BlogService blogService;
@Autowired
UserService userService;
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 获取主页博客列表和总页码数
* @Param : [pSize, page]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/blogList")
public ResultAjax blogList(Integer pSize,Integer page){
//1.检验参数
if (pSize == null || pSize <= 0
|| page == null || page <= 0) {
return ResultAjax.fail(ResultCode.FAILED_PARAMS_VALIDATE);
}
//2.计算总页数,调用service层
int count = blogService.blogAllCount();
int pCount = count / pSize;
if(count % pSize != 0){
pCount++;
}
//3.获取博客,根据页码和容量
List<Blog> list = blogService.selectAll(pSize,page);
//4.将数据集合进map返回
HashMap<String,Object> hashMap = new HashMap<>();
hashMap.put("list",list);
hashMap.put("pCount",pCount);
return ResultAjax.succ(hashMap);
}
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 获取博客信息和作者信息
* @Param : [id]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/content")
public ResultAjax blogContent(Integer id) {
//1.参数检验
if (id == null || id <= 0) {
return ResultAjax.fail(ResultCode.FAILED_PARAMS_VALIDATE, "参数异常");
}
//2.获取博客对象
Blog blog = blogService.selectOne(id);
//3.获取作者信息,根据作者id
int uid = blog.getUid();
String name = userService.selectById(uid).getUsername();
int count = blogService.count(uid);
//4.集合结果返回给前端
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("name", name);
hashMap.put("count", count);
hashMap.put("blog", blog);
return ResultAjax.succ(hashMap);
}
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 新增博客
* @Param : [blog, request]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/add")
public ResultAjax blogAdd(Blog blog, HttpServletRequest request){
//1.参数检验
if(blog.getTitle() == null || !StringUtils.hasLength(blog.getTitle())
|| blog.getContent() == null || !StringUtils.hasLength(blog.getContent())){
return ResultAjax.fail(ResultCode.FAILED_PARAMS_VALIDATE,"参数为空");
}
//2.补充用户uid
User user = SessionUtils.getUser(request);
if(user == null){
return ResultAjax.fail(ResultCode.FAILED_USER_EXISTS,"账号异常");
}
blog.setUid(user.getId());
//3.补充创建时间,修改时间,状态码
blog.setCreateTime(LocalDateTime.now());
blog.setUpdateTime(LocalDateTime.now());
blog.setState(0);
//4.添加blog进数据库
//5.返回响应给前端
return ResultAjax.succ(blogService.insert(blog));
}
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 获取我的博客列表
* @Param : [request]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/myBlogList")
public ResultAjax myBlogList(HttpServletRequest request){
//1.得到登录用户对象
User user = SessionUtils.getUser(request);
//2.检验用户会话是否正常
if(user == null){
return ResultAjax.fail(ResultCode.FAILED_USER_EXISTS,"账号异常");
}
//3.得到博客列表,用户名,博客总数
int uid = user.getId();
List<Blog> list = blogService.selectMyAll(uid);
String name = user.getUsername();
int count = blogService.count(uid);
//4.集合结果到map中
Map<String,Object> map = new HashMap<>();
map.put("list",list);
map.put("name",name);
map.put("count",count);
//3.返回响应给前端
return ResultAjax.succ(map);
}
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 获取博客详情,用于编辑
* @Param : [id]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/edit")
public ResultAjax blogEdit(Integer id){
//1.参数检验
if(id == null || id <= 0){
return ResultAjax.fail(ResultCode.FAILED_PARAMS_VALIDATE,"参数异常");
}
//2.获取博客对象并返回
Blog blog = blogService.selectOne(id);
return ResultAjax.succ(blog);
}
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 修改博客
* @Param : [blog, request]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/update")
public ResultAjax blogUpdate(Blog blog,HttpServletRequest request){
//1.参数检验
if(blog.getTitle() == null || !StringUtils.hasLength(blog.getTitle())
|| blog.getContent() == null || !StringUtils.hasLength(blog.getContent())
|| blog.getId() <= 0){
return ResultAjax.fail(ResultCode.FAILED_PARAMS_VALIDATE,"参数异常");
}
//2.得到当前登录用户
User user = SessionUtils.getUser(request);
if(user == null){
return ResultAjax.fail(ResultCode.FAILED_USER_EXISTS,"账号异常");
}
//3.补充blog属性
blog.setUpdateTime(LocalDateTime.now());
blog.setUid(user.getId());//把当前登录用户的id加入前端传来的blog里,送到sql那里去进行归属检验
//4..判断文章归属,并执行修改SQL
//5..返回响应给前端
return ResultAjax.succ(blogService.update(blog));
}
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 删除博客
* @Param : [id, request]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/delete")
public ResultAjax blogDelete(Integer id,HttpServletRequest request){
//1.参数校验
if(id == null || id <= 0){
return ResultAjax.fail(ResultCode.FAILED_PARAMS_VALIDATE,"参数异常");
}
//2.得到当前登录用户用户检验用户身份
User user = SessionUtils.getUser(request);
if(user == null){
return ResultAjax.fail(ResultCode.FAILED_USER_EXISTS,"账号异常");
}
//3.删除博客返回响应给前端
return ResultAjax.succ(blogService.delete(id,user.getId()));
}
}
▪UserController
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController{
@Autowired
UserService userService;
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 注册
* @Param : [user]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/reg")
public ResultAjax reg(User user) throws Exception {
//1.参数检验
if (user == null || !StringUtils.hasLength(user.getUsername())
|| !StringUtils.hasLength((user.getPassword()))) {
return ResultAjax.fail(ResultCode.FAILED_PARAMS_VALIDATE);
}
//2.密码加密
user.setPassword(PasswordUtils.encrypt(user.getPassword()));
//3.执行添加SQL
int result = userService.insertUser(user);
//4.返回响应给前端
if(result != 1){
log.error("数据库添加用户失败");
return ResultAjax.fail(ResultCode.FAILED_USER_EXISTS);
}
return ResultAjax.succ(result);
}
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 登录
* @Param : [user, request]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/login")
public ResultAjax login(User user, HttpServletRequest request){
//1.参数检验
if (user == null || !StringUtils.hasLength(user.getUsername())
|| !StringUtils.hasLength((user.getPassword()))) {
return ResultAjax.fail(ResultCode.FAILED_PARAMS_VALIDATE,"账号或密码错误");
}
//2.账号密码比对
//能不能根据传入用户名在数据库中查找到用户对象
User userDB = userService.selectByUsername(user.getUsername());
if(userDB == null){
return ResultAjax.fail(ResultCode.FAILED_LOGIN);
}
//数据库用户对象的密码跟传入密码是否对的上
if(!PasswordUtils.dcript(user.getPassword(),userDB.getPassword())){
return ResultAjax.fail(ResultCode.FAILED_LOGIN);
}
//3.新建会话
HttpSession session = request.getSession(true);
session.setAttribute(AppVar.SESSION_USER,userDB);
//4.返回响应回前端
return ResultAjax.succ(null);
}
/*------------------------------------普--通--方--法------------------------------------------------------------------
* @Desc : 退出登录
* @Param : [request]
* @Return: com.example.blog_system.common.ResultAjax
**/
@RequestMapping("/logout")
public ResultAjax logout(HttpServletRequest request){
//1.得到当前登录会话
HttpSession session = request.getSession(false);
if(session == null || session.getAttribute(AppVar.SESSION_USER) ==null){
return ResultAjax.succ("已退出会话");
}
//2.置空会话的value
session.setAttribute(AppVar.SESSION_USER,null);
//3.返回响应结果给前端
return ResultAjax.succ("退出成功");
}
}
▮dao
▪BlogMapper
@Mapper
public interface BlogMapper {
//1.获取博客总数
@Select("select COUNT(*) from blog where state=0")
int blogAllCount();
//2.获取博客列表,根据页码
@Select("select * from blog where state=0 order by updateTime desc limit #{pSize} offset #{page}")
List<Blog> selectAll(@Param("pSize")int pSize, @Param("page")int page);
//3.获取博客,根据博客id
@Select("select * from blog where id=#{id} and state=0")
Blog selectOne(@Param("id") int id);
//4.获取此作者博客总数,根据作者id
@Select("select COUNT(*) from blog where uid=#{uid} and state=0")
int count(@Param("uid") int uid);
//5.新增博客
@Insert("insert into blog(title, content,updateTime,createTime, uid, state) values (#{title},#{content},#{updateTime},#{createTime},#{uid},#{state})")
int insert(Blog blog);
//6.获取用户博客列表,根据用户id
@Select("select * from blog where uid=#{uid} and state=0 order by updateTime desc")
List<Blog> selectMyAll(@Param("uid") int uid);
//7.修改博客
@Update("update blog set title=#{title},content=#{content},updateTime=#{updateTime} where id=#{id} and uid=#{uid}")
int update(Blog blog);
//8.删除博客
@Update("update blog set state=1 where id=#{id} and uid=#{uid}")
int delete(@Param("id")int id,@Param("uid")int uid);
}
▪UserMapper
@Mapper
public interface UserMapper {
//1.新增用户
@Insert("insert into user(username,password) values(#{username},#{password})")
int insertUser(User user);
//2.获取用户,根据用户名
@Select("select * from user where username=#{username}")
User selectByUsername(@Param("username") String username);
//3.获取用户,根据用户id
@Select("select * from user where id=#{id} and state=0")
User selectById(@Param("id")int id);
}
▮model
▪Blog
@Data
public class Blog implements Serializable {
//博客id
private int id;
//博客标题
private String title;
//博客正文
private String content;
//博客创建时间
@JsonFormat( pattern = "yyyy-MM-dd",timezone = "GMT+8")
private LocalDateTime createTime;
//博客修改时间
@JsonFormat( pattern = "yyyy-MM-dd",timezone = "GMT+8")
private LocalDateTime updateTime;
//博客所属作者id
private int uid;
//状态码
private int state;
}
▪db.sql
-- 1.建库
create database if not exists blog_system charset utf8;
-- 2.使用库
use blog_system;
-- 3.1用户表
drop table if exists user;
create table user(
id int primary key auto_increment,
username varchar(20) not null unique,
password varchar(65) not null,
state int not null default 0
);
-- 3.2博客表
drop table if exists blog;
create table blog(
id int primary key auto_increment,
uid int not null,
title varchar(100) not null,
createTime datetime not null,
updateTime datetime not null,
content text not null,
state int not null default 0
);
-- 4.初始化,密码是123,这里写入的是123加密后的密文
insert into user(id, username, password) VALUE (null,'zhangsan','a65a070469a543b8a1ccf68ed8eb6c95$d37c6a2f7b129499c36ba0cfb36351d9');
insert into blog(id, title, content, createTime, updateTime, uid,state) VALUE
(null,'星空中的神奇光点','夜空中繁星点点,每一颗星星都映照出无尽的宇宙之美。其中,最神奇的莫过于流星。流星划破夜空时,如同一道闪电从天而降,瞬间吸引着人们的目光。纵然流星只是短暂的一刹那,但它的意义却不容忽视。它代表着希望和美好,象征着未来的无限可能性。每一颗流星都是宇宙的礼赞,也是我们自己的心愿。让我们仰望星空,期待着下一颗流星的降临,同时也许愿着属于自己的幸福和梦想之星.','2021-12-06 17:10:48','2021-12-06 17:10:48',1,0);
insert into blog(id, title, content, createTime, updateTime, uid,state) VALUE
(null,'小溪的歌声','小溪缓缓流淌,如同一首动听的歌曲,轻轻地响起来。它源自高山之巅,穿过密林流淌,碰撞着石头,发出一阵阵清脆的声音。溪水清澈见底,似乎洗涤了一切的尘埃和污浊,让人感到宁静与舒适。沿着小溪的岸边,鲜花盛开,青草如茵,生机盎然。小溪的歌声让人心旷神怡,仿佛能听到大自然的呼吸和欢笑。我们应该学会倾听小溪的歌声,感受大自然的美妙与宁静。','2021-12-06 17:10:48','2021-12-06 17:10:48',1,0);
insert into blog(id, title, content, createTime, updateTime, uid,state) VALUE
(null,'微笑的力量','微笑是一种奇妙的力量,它可以照亮别人的心灵,也能温暖自己的内心。无论是在喜悦中微笑,还是在困难中坚持微笑,它都能化解痛苦和困境。微笑是一种积极的表达,它传递出乐观与希望,让人感到舒适与快乐。当你微笑时,周围的人也会感到愉悦,这是一种愉悦的传染效应。不论遇到什么困难和挫折,都要保持微笑,相信它能给你带来力量和坚定。让微笑成为你生活中的常态,用它传递快乐和温暖。','2021-12-06 17:10:48','2021-12-06 17:10:48',1,0);
-- 5.展示
select * from user;
select * from blog;
▪User
@Data
public class User implements Serializable {
//用户id
private int id;
//用户账号
private String username;
//用户密码
private String password;
//状态码
private int state;
}
▮service
▪BlogService
@Slf4j
@Service
public class BlogService {
//Blog映射
@Autowired
BlogMapper blogMapper;
//1.获取博客总数
public int blogAllCount(){
return blogMapper.blogAllCount();
}
//2.获取博客列表,根据页码
public List<Blog> selectAll(int pSize, int page){
List<Blog> list = blogMapper.selectAll(pSize,pSize*(page-1));
subContent(list);
return list;
}
//3.获取博客,根据博客id
public Blog selectOne(int id){
return blogMapper.selectOne(id);
}
//4.获取此作者的博客总数,根据用户id
public int count(int uid){
return blogMapper.count(uid);
}
//5.新增博客
public int insert(Blog blog){
return blogMapper.insert(blog);
}
//6.获取用户博客列表,根据用户id
public List<Blog> selectMyAll(int uid){
List<Blog> list = blogMapper.selectMyAll(uid);
subContent(list);
return list;
}
//7.修改博客
public int update(Blog blog){
return blogMapper.update(blog);
}
//8.删除博客
public int delete(int id,int uid){
return blogMapper.delete(id,uid);
}
//私有方法,截取博客正文作为简介
private void subContent(List<Blog> list){
for(Blog blog:list){
//截取前80字符
if(blog.getContent().length()> AppVar.SUB_CONTENT_LENGTH){
//用截取后的简介替代正文
blog.setContent(blog.getContent().substring(0,AppVar.SUB_CONTENT_LENGTH));
}
}
}
}
▪UserService
@Slf4j
@Service
public class UserService {
//User映射
@Autowired
private UserMapper userMapper;
//1.新加用户
public int insertUser(User user){
return userMapper.insertUser(user);
}
//2.获取用户,根据用户名
public User selectByUsername(String username){
return userMapper.selectByUsername(username);
}
//3.获取用户,根据用户id
public User selectById(int id){
System.out.println(id);
return userMapper.selectById(id);
}
}
▮util
▪PasswordUtils
public class PasswordUtils {
//1.加密方法
public static String encrypt(String password){
//1.得到盐
String salt = UUID.randomUUID().toString().replace("-","");
//2.MD5加密得到密文
String dpPassword = DigestUtils.md5DigestAsHex((salt+password).getBytes(StandardCharsets.UTF_8));
//3.返回“盐+密文”的拼接
return salt+"$"+dpPassword;
}
//2.解密方法
public static boolean dcript( String password,String dbPassword){
//1.切割出盐和加密后的密文
String[] saltDp = dbPassword.split("\\$");
//2.加密“盐+登录密码”得到密文
String passwordEncrypt = DigestUtils.md5DigestAsHex((saltDp[0]+password).getBytes(StandardCharsets.UTF_8));
//3.比对2.的密文跟数据库中的密文dbPassword
if(passwordEncrypt.equals(saltDp[1])){
return true;
}
return false;
}
}
▪SessionUtils
public class SessionUtils {
public static User getUser(HttpServletRequest request){
//1.获取但不新建会话
HttpSession session = request.getSession(false);
//2检验会话
if(session == null || session.getAttribute(AppVar.SESSION_USER) == null){
return null;
}
//3.返回会话里保存的user对象
return (User) session.getAttribute(AppVar.SESSION_USER);
}
}
▮static
▪blog_add.html
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客编辑</title>
<!-- 引入自己写的样式 -->
<link rel="stylesheet" href="css/conmmon.css">
<link rel="stylesheet" href="css/blog_edit.css">
<!-- 引入 editor.md 的依赖 -->
<link rel="stylesheet" href="editor.md/css/editormd.min.css" />
<script src="js/jquery.min.js"></script>
<script src="editor.md/editormd.js"></script>
</head>
<body>
<!-- 导航栏 -->
<div class="nav">
<img src="img/logo2.jpg" alt="">
<span class="title">我的博客系统</span>
<!-- 用来占据中间位置 -->
<span class="spacer"></span>
<a href="blog_list.html">主页</a>
<a href="javascript:logout()">注销</a>
</div>
<!-- 编辑框容器 -->
<div class="blog-edit-container">
<!-- 标题编辑区 -->
<div class="title">
<input type="text" placeholder="在这里写下文章标题" id="title">
<button onclick="submit()">发布文章</button>
</div>
<!-- 创建编辑器标签 -->
<div id="editorDiv">
<textarea id="editor-markdown" style="display:none;"></textarea>
</div>
</div>
<script src="/js/logout.js"></script>
<script>
var editor;
function initEdit(md){
// 编辑器设置
editor = editormd("editorDiv", {
// 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉.
width: "100%",
// 高度 100% 意思是和父元素一样高. 要在父元素的基础上去掉标题编辑区的高度
height: "calc(100% - 50px)",
// 编辑器中的初始内容
markdown: md,
// 指定 editor.md 依赖的插件路径
path: "editor.md/lib/",
saveHTMLToTextarea: true //
});
}
initEdit("# 在这里写下一篇博客"); // 初始化编译器的值
function submit(){
let title = jQuery("#title");
let content = jQuery("#editor-markdown");
//3.1.参数检验
if(title.val() != title.val().trim()){
alert("标题不能使用空格");
title.focus();
return;
}
if(title.val() == null || title.val().length==0){
alert("标题不能为空");
title.focus();
return;
}
//3.2.发送请求
jQuery.ajax({
url:"/blog/add",
type:"POST",
data:{
"title":title.val(),
"content":content.val()
},
//3.3.处理服务器响应
success:function (res){
if(res.code == 200){
alert("博客添加成功") ;
location.href="myblog_list.html";
}else{
alert("系统错误: "+res.msg);
}
}
})
}
</script>
</body>
</html>
▪blog_content.html
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客正文</title>
<link rel="stylesheet" href="css/conmmon.css">
<link rel="stylesheet" href="css/blog_content.css">
<link rel="stylesheet" href="editor.md/css/editormd.preview.min.css" />
<script src="js/jquery.min.js"></script>
<script src="editor.md/editormd.js"></script>
<script src="editor.md/lib/marked.min.js"></script>
<script src="editor.md/lib/prettify.min.js"></script>
</head>
<body>
<!-- 导航栏 -->
<div class="nav">
<img src="img/logo2.jpg" alt="">
<span class="title">我的博客系统</span>
<!-- 用来占据中间位置 -->
<span class="spacer"></span>
<a href="blog_list.html">主页</a>
<a href="blog_add.html">写博客</a>
<a href="javascript:logout()">注销</a>
</div>
<!-- 版心 -->
<div class="container">
<!-- 左侧个人信息 -->
<div class="container-left">
<div class="card">
<img src="img/avatar.png" class="avtar" alt="">
<h3 id="name">小可爱</h3>
<a href="http:www.github.com">github 地址</a>
<div class="counter">
<span>文章</span>
<span>分类</span>
</div>
<div class="counter">
<span id="count"></span>
<span>1</span>
</div>
</div>
</div>
<!-- 右侧内容详情 -->
<div class="container-right">
<div id="blog-content">
<!-- <!– 博客标题 –>-->
<!-- <h3>我的第一篇博客</h3>-->
<!-- <!– 博客时间 –>-->
<!-- <div class="date">2021-06-02</div>-->
<!-- <!– 博客正文 –>-->
<!-- <div id="editorDiv">-->
<!-- </div>-->
</div>
</div>
</div>
<script src="/js/logout.js"></script>
<script type="text/javascript">
var blogId = new URLSearchParams(location.search).get("id");
jQuery.ajax({
url:"blog/content",
type:"GET",
data:{
id:blogId
},
success:function (res){
if(res.code==200){
//作者名
let name = res.data.name;
//文章总数
let count = res.data.count;
//博客信息
let blog = res.data.blog;
//修改作者信息
jQuery("#name").html(name);
jQuery("#count").html(count);
//插入博客信息
var content = "";
//3.1.拼接博客正文标签
content += '<div>';
content += '<h3>'+blog.title+'</h3>';
content += '<div class="date">'+blog.updateTime+'</div>';
content += '<div id="editorDiv"></div>';
content += '</div>';
//3.2.插入标签到界面
jQuery('#blog-content').html(content);
//3.3.使用editormd来解析markdown
//-------------------------------------标---记---特---殊------------------------------------------------------------------
/* @Desc : 使用editormd解析markdown文本
* editormd是editormd编辑器的对象,内含许多操作方法
* markdownToHTML(html标签id,{解析格式: 需解析的字符串}),
* 将'需解析字符串'按照'解析格式'解析到'id'对应的html标签
**/
editormd.markdownToHTML('editorDiv',{markdown: blog.content});
//----------------------------------------------------------------------------------------------------------------------
}else {
alert("系统错误:"+res.msg);
}
}
})
</script>
</body>
</html>
▪blog_edit.html
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客编辑</title>
<!-- 引入自己写的样式 -->
<link rel="stylesheet" href="css/conmmon.css">
<link rel="stylesheet" href="css/blog_edit.css">
<!-- 引入 editor.md 的依赖 -->
<link rel="stylesheet" href="editor.md/css/editormd.min.css" />
<script src="js/jquery.min.js"></script>
<script src="editor.md/editormd.js"></script>
</head>
<body>
<!-- 导航栏 -->
<div class="nav">
<img src="img/logo2.jpg" alt="">
<span class="title">我的博客系统</span>
<!-- 用来占据中间位置 -->
<span class="spacer"></span>
<a href="blog_list.html">主页</a>
<a href="javascript:logout()">注销</a>
</div>
<!-- 编辑框容器 -->
<div class="blog-edit-container">
<!-- 标题编辑区 -->
<div class="title">
<input type="text" placeholder="在这里写下文章标题" id="title">
<button onclick="mysub()">发布文章</button>
</div>
<!-- 创建编辑器标签 -->
<div id="editorDiv">
<textarea id="editor-markdown" style="display:none;"></textarea>
</div>
</div>
<script src="/js/logout.js"></script>
<script>
var editor;
function initEdit(md){
// 编辑器设置
editor = editormd("editorDiv", {
// 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉.
width: "100%",
// 高度 100% 意思是和父元素一样高. 要在父元素的基础上去掉标题编辑区的高度
height: "calc(100% - 50px)",
// 编辑器中的初始内容
markdown: md,
// 指定 editor.md 依赖的插件路径
path: "editor.md/lib/",
saveHTMLToTextarea: true //
});
}
//3.从服务器得到博客信息,加载进编辑页
jQuery.ajax({
url:"blog/edit"+location.search,
type:"GET",
success:function (res){
if(res.code == 200){
var blog = res.data;
jQuery("#title").val(blog.title);
initEdit(blog.content);
}else {
alert("系统错误"+res.msg);
}
}
})
// 提交
function mysub(){
//1.获取标题和正文
var title = jQuery("#title");
var content = jQuery("#editor-markdown");
//2.参数检验
if(title.val() != title.val().trim()){
alert("标题不能使用空格");
title.focus();
return;
}
if(title.val() == null || title.val().length==0){
alert("标题不能为空");
title.focus();
return;
}
//3.发送请求到服务器
jQuery.ajax({
url:"/blog/update",
type:"POST",
data: {
"title": title.val(),
"content": content.val(),
"id": new URLSearchParams(location.search).get("id")
},
success:function (res){
if(res.code == 200){
alert("博客修改成功") ;
location.href="myblog_list.html";
}else{
alert("系统错误: "+res.msg);
}
}
})
}
</script>
</body>
</html>
▪blog_list.html
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客列表</title>
<link rel="stylesheet" href="css/list.css">
<link rel="stylesheet" href="css/blog_list.css">
<script src="js/jquery.min.js"></script>
<style>
.nav{
position: fixed;
top: 0;
left: 0;
right: 0;
height: 50px;
}
.container{
padding-top: 80px;
height: auto;
}
.blog-pagnation-wrapper{
height: 40px;
margin: 16px 0;
text-align: center;
}
.blog-pagnation-item{
display: inline-block;
padding: 8px;
border: 1px solid #d0d0d5;
color: #333;
}
.blog-pagnation-item:hover{
background: #4e4eeb;
color: #fff;
}
.blog-pagnation-item.actvie{
background: #4e4eeb;
color: #fff;
}
</style>
</head>
<body>
<!-- 导航栏 -->
<div class="nav">
<img src="img/logo2.jpg" alt="">
<span class="title">我的博客系统</span>
<!-- 用来占据中间位置 -->
<span class="spacer"></span>
<a href="myblog_list.html">我的</a>
<a href="blog_add.html">编辑</a>
<a href="javascript:logout()">注销</a>
<!-- <a href="#">注销</a> -->
</div>
<!-- 版心 -->
<div class="container">
<!-- 右侧内容详情 -->
<div class="container-right" style="margin: 0 auto">
<h2 style="margin: 20px auto;text-align: center;">博客列表</h2>
<hr>
<div class="blog-list" id="blog-list" >
<!-- <!– 每一篇博客包含标题, 摘要, 时间 –>-->
<!-- <div class="blog" >-->
<!-- <div class="title">我的第一篇博客</div>-->
<!-- <div class="date">2021-06-02</div>-->
<!-- <div class="desc">正文</div>-->
<!-- <a href="blog_content.html?id=1" class="detail">查看全文 >></a>-->
<!-- </div>-->
<!-- <div class="blog">-->
<!-- <div class="title">我的第一篇博客</div>-->
<!-- <div class="date">2021-06-02</div>-->
<!-- <div class="desc">正文</div>-->
<!-- <a href="blog_content.html?id=1" class="detail">查看全文 >></a>-->
<!-- </div>-->
</div>
<hr>
<div class="blog-pagnation-wrapper">
<button class="blog-pagnation-item" onclick="startPage()">首页</button>
<button class="blog-pagnation-item" onclick="prePage()">上一页</button>
<button class="blog-pagnation-item" onclick="nextPage()">下一页</button>
<button class="blog-pagnation-item" onclick="endPage()">末页</button>
<span id="page"></span>
</div>
</div>
</div>
<script src="/js/logout.js"></script>
<script>
//页码
var page = 0; //页码
var pSize = 10;//每页容量
var pCount = 0;//总页码
page = new URLSearchParams(location.search).get("page");
if(page == null || page <= 0){
page = 1;
}
//2.从服务器得到数据,加载博客列表
jQuery.ajax({
url:"/blog/blogList",
type:"GET",
data:{
"page":page, //当前页码
"pSize":pSize//容量
},
success:function (res){
if(res.code == 200){
//得到总页数
pCount = res.data.pCount;
//显示关于页码的信息
jQuery("#page").text(" 当前是"+page+"页,总共有"+pCount+"页");
//在id为'.blog-list'的标签下拼接博客列表
var blogList = document.querySelector('.blog-list');
//拼接博客列表
for (var blog of res.data.list){
//-------------------------------------标---记---开---头------------------------------------------------------------------
/* @Desc : 组装blog标签插入blog-list标签
* 先创建div标签,再修改为指定类型,接着添入值,最后插入到上级标签
**/
//创建blog标签
let blogDiv = document.createElement("div");
blogDiv.className = 'blog';
//创建标题标签并添入值
let titleDiv = document.createElement('div');
titleDiv.className = 'title';
titleDiv.innerHTML = blog.title;
//创建时间标签并添入值
let dateDiv = document.createElement('div');
dateDiv.className = 'date';
dateDiv.innerHTML = blog.updateTime;
//创建正文内容标签并添入值
let contentDiv = document.createElement('div');
contentDiv.className = 'desc';
contentDiv.innerHTML = blog.content
//创建超链接标签并添入值
let a = document.createElement("a");
a.href = '/blog_content.html?id='+ blog.id;
a.innerHTML = '查看全文 >>';
//将所有新标签插入blog标签,使所有新建的标签成为一个整体,囊括在blog标签里
blogDiv.appendChild(titleDiv);
blogDiv.appendChild(dateDiv);
blogDiv.appendChild(contentDiv);
blogDiv.appendChild(a);
//blog标签插入blog-list标签,插入进HTMl
blogList.appendChild(blogDiv);
//-------------------------------------标---记---结---尾------------------------------------------------------------------
}
} else {
alert("系统异常"+res.msg);
}
}
})
function prePage(){
//页码不能小于等于1
if(page <= 1){
alert("已到首页");
return;
}
//跳转至首页,并在URL拼接page
location.href="/blog_list.html?page="+(parseInt(page)-1);
}
function nextPage(){
//页码不能大于等于总页码
if(page >= pCount){
alert("已到尾页");
return;
}
location.href="/blog_list.html?page="+(parseInt(page)+1);
}
function startPage(){
location.href="/blog_list.html?page=1";
}
function endPage(){
location.href="/blog_list.html?page="+pCount;
}
</script>
</body>
</html>
▪login.html
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录页面</title>
<link rel="stylesheet" href="css/conmmon.css">
<link rel="stylesheet" href="css/login.css">
<script src="js/jquery.min.js"></script>
</head>
<body>
<!-- 导航栏 -->
<div class="nav">
<img src="img/logo2.jpg" alt="">
<span class="title">我的博客系统</span>
<!-- 用来占据中间位置 -->
<span class="spacer"></span>
<a href="blog_list.html">主页</a>
<a href="reg.html">注册</a>
</div>
<!-- 版心 -->
<div class="login-container">
<!-- 2.1.中间的登录框 -->
<div class="login-dialog">
<h3>登录</h3>
<div class="row">
<span>用户名</span>
<input type="text" id="username">
</div>
<div class="row">
<span>密码</span>
<input type="password" id="password">
</div>
<div class="row">
<button id="submit" onclick="doLogin()">提交</button>
</div>
</div>
</div>
<script>
function doLogin(){
var username = jQuery("#username");
var password = jQuery("#password");
//2.1.校验参数
if(username.val() == ""){
//弹出提示框
alert("请输入用户名")
//跳转到username输入框
username.focus();
return false;
}
if(password.val() == ""){
//弹出提示框
alert("请输入密码")
//跳转到username输入框
password.focus();
return false;
}
//2.2.发送数据到后端
jQuery.ajax({
url:"/user/login",
type:"POST",
data:{
"username":username.val(),
"password":password.val()
},
//2.3.处理响应
success:function (res){
if(res.code == 200){
location.href = "blog_list.html"
}else {
alert(res.msg);
}
}
});
}
</script>
</body>
</html>
▪myblog_list.html
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客列表</title>
<link rel="stylesheet" href="css/conmmon.css">
<link rel="stylesheet" href="css/blog_list.css">
<script src="js/jquery.min.js"></script>
</head>
<body>
<!-- 导航栏 -->
<div class="nav">
<img src="img/logo2.jpg" alt="">
<span class="title">我的博客系统</span>
<!-- 用来占据中间位置 -->
<span class="spacer"></span>
<a href="blog_list.html">主页</a>
<a href="blog_add.html">编辑</a>
<a href="javascript:logout()">注销</a>
</div>
<!-- 版心 -->
<div class="container">
<!-- 左侧个人信息 -->
<div class="container-left">
<div class="card">
<img src="img/avatar.png" class="avtar" alt="">
<h3 id="name">小可爱</h3>
<a href="http:www.github.com">github 地址</a>
<div class="counter">
<span>文章</span>
<span>分类</span>
</div>
<div class="counter">
<span id="count"></span>
<span>1</span>
</div>
</div>
</div>
<!-- 右侧内容详情 -->
<div class="container-right">
<div id="blog-list">
<!-- <!– 每一篇博客包含标题, 摘要, 时间 –>-->
<!-- <div class="blog">-->
<!-- <div class="title">我的第一篇博客</div>-->
<!-- <div class="date">2021-06-02</div>-->
<!-- <div class="desc">-->
<!-- 从今天起, 我要认真敲代码. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Cum distinctio ullam eum ut-->
<!-- veroab laborum numquam tenetur est in dolorum a sint, assumenda adipisci similique quaerat vel.-->
<!-- Facere,-->
<!-- et.-->
<!-- </div>-->
<!-- <a href="blog_content.html?id=1" class="detail">查看全文 >></a> -->
<!-- <a href="blog_content.html?id=1" class="detail">修改 >></a> -->
<!-- <a href="blog_content.html?id=1" class="detail">删除 >></a>-->
<!-- </div>-->
</div>
</div>
</div>
<script src="/js/logout.js"></script>
<script>
jQuery.ajax({
url:"/blog/myBlogList",
type:"GET",
success:function (res){
if(res.code == 200){
//博客列表
let list = res.data.list;
//用户名
let name = res.data.name;
//用户博客总数
let count = res.data.count;
//用户信息
jQuery("#name").html(name);
jQuery("#count").html(count);
//博客列表
var blogList = "";
//3.1.当博客列表为空时加载的默认内容
if(list == null || list.length == 0){
blogList += "<h3 style='margin-left: 300px;margin-top: 100px'>暂无博客,请<a href='blog_add.html'>添加</a>!</h3>"
}
//3.2.拼接用户所属博客列表
for(let blog of list){
//-------------------------------------标---记---开---始------------------------------------------------------------------
/* @Desc : 组装blog标签插入blog-list标签
* blogList是一个字符串,在里面拼接一个html格式的字符串
* 标签.html()往标签里插入一个html格式的字符串
**/
blogList += '<div class="blog">';
blogList += '<div class="title">'+blog.title+'</div>';
blogList += '<div class="date">'+blog.updateTime+'</div>';
blogList += '<div class="desc">\n'+blog.content+'</div>';
blogList += '<a href="/blog_content.html?id='+blog.id+'" class="detail">查看全文 >></a> '
blogList += '<a href="/blog_edit.html?id='+blog.id+'" class="detail">修改 >></a> '
//-------------------------------------标---记---开---始------------------------------------------------------------------
/* @Desc : a标签调用js函数,能够保留参数
* javascript:function(),a标签调用js函数的格式
* dle(blog.id),传入到函数的参数是可以保存的,在a标签调用此函数时,会把参数传入到方法内
**/
blogList += '<a href="javascript:del('+blog.id+')" class="detail">删除 >></a>'
//-------------------------------------标---记---结---尾------------------------------------------------------------------
blogList += '</div>';
}
jQuery("#blog-list").html(blogList);
//-------------------------------------标---记---结---尾------------------------------------------------------------------
}else{
alert("系统错误"+res.msg);
}
}
})
function del(id){
//4.1.确认"删除"
if(!confirm("确定删除此博客?")){
return;
}
//4.2.发送请求
jQuery.ajax({
url: "/blog/delete",
type: "POST",
data:{
"id":id
},
success:function (res){
if(res.code==200){
alert("删除成功");
location.href="myblog_list.html";
}else {
alert("系统异常"+res.msg);
}
}
})
}
</script>
</body>
</html>
▪reg.html
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>注册页面</title>
<link rel="stylesheet" href="css/conmmon.css">
<link rel="stylesheet" href="css/login.css">
<script src="js/jquery.min.js"></script>
</head>
<body>
<!-- 导航栏 -->
<div class="nav">
<img src="img/logo2.jpg" alt="">
<span class="title">我的博客系统</span>
<!-- 用来占据中间位置 -->
<span class="spacer"></span>
<a href="blog_list.html">主页</a>
<a href="login.html">登录</a>
<!-- <a href="#">注销</a> -->
</div>
<!-- 版心 -->
<div class="login-container">
<!-- 中间的注册框 -->
<div class="login-dialog">
<h3>注册</h3>
<div class="row">
<span>用户名</span>
<input type="text" id="username">
</div>
<div class="row">
<span>密码</span>
<input type="password" id="password">
</div>
<div class="row">
<span>确认密码</span>
<input type="password" id="password2">
</div>
<div class="row">
<button id="submit" onclick="submit()">提交</button>
</div>
</div>
</div>
<script>
function submit(){
var username = jQuery("#username");
var password = jQuery("#password");
var password2 = jQuery("#password2");
//1.非空校验
if(username.val() == ""){
//弹出提示框
alert("请输入用户名")
//跳转到username输入框
username.focus();
return false;
}
if(password.val() == ""){
//弹出提示框
alert("请输入密码")
//跳转到username输入框
password.focus();
return false;
}
if(password2.val() == ""){
//弹出提示框
alert("请输入确认密码")
//跳转到username输入框
password2.focus();
return false;
}
//检验输入是否存在空格
if((username.val() != username.val().trim())
||(password.val() != password.val().trim())
||(password2.val() != password2.val().trim())){
alert("请不要输入空格");
return false;
}
//2.校验两次输入密码是否一致
if(password.val() != password2.val()){
alert("两次输入的密码不一致");
return false;
}
//3.发送数据到后端
jQuery.ajax({
url:"/user/reg",
type:"POST",
data:{
"username":username.val(),
"password":password.val()
},
//4.展示后端响应结果
success:function(res){
if(res.code == 200){
alert("注册成功");
//跳转页面
location.href = "login.html";
}else{
alert("系统错误"+res.msg);
}
}
})
}
</script>
</body>
</html>