0


博客项目- SSM 实现

文章目录

博客系统

前言 : 本文主要 是通过 ssm 搭配之前的 博客系统页面, 来完成一个小项目 .

项目完整代码

1. 创建项目

在这里插入图片描述

使用到的技术 :

  1. 后端 : Spring Boot + Spring MVC + MyBatis + 拦截器 / 统一异常处理 + 统一数据返回 (Spring AOP)
  2. 前端 : HTML + CSS + javaScript + jquery

2. 数据库设计

通过我们需要实现的功能 ,能够知道 需要两张表 , 第一张表 用户表 ,用来完成登录 注册 注销等功能 , 第二张表 用来存储 博客 , 查看博客等 .

  1. 创建 用户列表
-- 如果存在 这个数据库就删除dropdatabaseif exits mywebsite;-- 创建数据库createdatabase mywebsite;-- 选中数据库use
mywebsite

-- 创建用户表createtableuser(-- 系统分配
    id        intprimarykeyauto_increment,-- 必填
    username  varchar(255)notnull,
    password  varchar(255)notnull,-- 非必填
    qq        varchar(255)default'',
    address   varchar(255)default'',
    crateTime datetimedefaultnow(),
    sex       varchar(2)default'男',-- url 用来存放 用户 头像 图片 如果用户没有上传就使用默认的 .
    url       varchar(1024)default'阳台.png');
  1. 创建 blog 表
createtable blog
(
    blogId   intprimarykeyauto_increment,

    title    varchar(1024)notnull,-- 这里 一篇博客的内容可能非常多 使用 varchar可能不够 ,这里就是用 mediumtext
    content  mediumtext,--  用户 id
    userid   int,-- 发布时间
    postTime datetimedefaultnow(),-- 类型typevarchar(255)notnull,);

表创建好了 ,下面就可以完成一些 准备工作 ,比如 配置好环境 , 写好 拦截器 ,统一数据格式 等 .

这里统一数据格式 可以写一个类 , 通过这个类来返回 或者 通过 @ControllerAdvice + ResponseBodyAdvice 来完成 , 这里我会使用 写一个类来返回信息 .

3. 前置任务

这里先来完成 拦截器 , 统一异常处理 , 统一数据格式 .

在这里插入图片描述

application.yml

# 配置当前运行的环境 (配置文件)# spring > profiles > activespring:profiles:active: dev # 使用开发环境的配置文件# 配置 mybatis xml 保存路径mybatis:mapper-locations: classpath:mybatis/**Mapper.xml# 在公共 yml 文件 来 配置 mybatis 的保存路径

application-dev.yml

# 开发环境的配置文件spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mywebsite?characterEncoding=utf8
    username: root
    password:1234driver-class-name: com.mysql.cj.jdbc.Driver # 在 8.0 之前 是没有点 jc的 -> com.mysql.jdbc.Driver# 设置日志级别logging:level:com:example:usermanager: debug
        # 对具体类机型日志级别设定# 开启 MyBatis SQL 打印mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3.1 拦截器

这里我们实现拦截器 主要有两部 : 1. 自定义拦截器 , 2. 给拦截器设置规则 (那些 需要拦截 , 那些不需要拦截)

在这里插入图片描述

附上代码 :

AppConfig 类

packagecom.example.usermanager.config;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Configurable;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/**
 * 系统配置文件
 */@ConfigurationpublicclassAppConfigimplementsWebMvcConfigurer{// 注入拦截器@AutowiredprivateLoginIntercept loginIntercept;@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(loginIntercept).addPathPatterns("/**").excludePathPatterns("/user/login").excludePathPatterns("/insert").excludePathPatterns("/css/**").excludePathPatterns("/fonts/**").excludePathPatterns("/images/**").excludePathPatterns("/js/**").excludePathPatterns("/login.html");}}

LoginIntercept

packagecom.example.blog_ssm.config;importorg.springframework.stereotype.Component;importorg.springframework.web.servlet.HandlerInterceptor;importorg.springframework.web.servlet.ModelAndView;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjavax.servlet.http.HttpSession;/**
 * 自定义拦截器
 */@ComponentpublicclassLoginInterceptimplementsHandlerInterceptor{/**
     * true  表示已经登录 ,会继续访问目标方法
     * false  表示未登录 , 跳转到登录页面
     */@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{// false : 如果 没有 session 也不会创建HttpSession session = request.getSession(false);if(session !=null&& session.getAttribute("user")!=null){// 表示登录成功returntrue;}// 403 当前你没有资格访问
        response.setStatus(403);// 重定向
        response.sendRedirect("/login.html");returnfalse;}}

拦截器 弄好了 , 我们可以看看效果 :

在这里插入图片描述

xml 配置文件

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.example.blog_ssm.mapper.UserMapper"></mapper>

3.2 统一数据格式

  1. 创建一个类用来 统一 数据格式

在这里插入图片描述

附上代码 :

packagecom.example.blog_ssm.util;importlombok.Data;/**
 * 用来统一数据格式
 *
 * @param <T>
 */@DatapublicclassResponseBodyMessage<T>{// 1. 状态码privateInteger status;// 2. 信息描述privateString message;// 3. 数据privateT data;publicResponseBodyMessage(Integer status,String message,T data){this.status = status;this.message = message;this.data = data;}}
  1. 使用注解

在这里插入图片描述

3.3 创建一个 Constant

之前我们写拦截器的使用 ,通过 session 中的key 获取 user 对象时 ,写了一个 “user” , 这里可以使用一个类 ,在类里面写一个 常量 ,然后 只需要通过这个 来获取 user 即可 。

在这里插入图片描述

3.4 统一异常处理

在这里插入图片描述

代码 :

packagecom.example.blog_ssm.config;importorg.springframework.web.bind.annotation.ControllerAdvice;importorg.springframework.web.bind.annotation.ExceptionHandler;importorg.springframework.web.bind.annotation.RestControllerAdvice;importjava.util.HashMap;/**
 * 统一异常的拦截处理类
 */@RestControllerAdvice// 使用 @ControllerAdvice 需要再加一个注解 @ResponseBody (返回一个非静态页面)publicclassMyExceptionAdvice{@ExceptionHandler(Exception.class)publicObjectexceptionAdvice(Exception e){HashMap<String,Object> result =newHashMap<>();

        result.put("status",-1);

        result.put("message","程序异常 : "+ e.getMessage());

        result.put("data","");return result;}}

3.5 密码加密

在 util 包内 创建 PasswordUtil 类

packagecom.example.blog_ssm.util;importcn.hutool.core.util.IdUtil;importcn.hutool.crypto.SecureUtil;importorg.springframework.util.StringUtils;/**
 * 密码工具类
 */publicclassPasswordUtil{/**
     * 1. 加密 (加盐)
     */publicStringencrypt(String password){// 密码 : 随机盐值 + 密码String salt =IdUtil.simpleUUID();String finalPassword =SecureUtil.md5(salt + password);return salt +"$"+ finalPassword;}/**
     * 解密
     *
     * @param password 要验证的密码 (未加密)
     * @return 数据库中的加了盐值的密码
     */publicbooleandecrypt(String password,String securePassword){boolean result =false;if(StringUtils.hasLength(password)&&StringUtils.hasLength(securePassword)){// 注意 : $ 是特殊字符 , 使用 split 分割时 需要转移if(securePassword.length()==65&& securePassword.contains("$")){// 随机盐值 为 32  , md5 加密的 密码 32 加上 $ 1字符 总共 65 字符String[] securePasswordArr = securePassword.split("\\$");// 盐值String salt = securePasswordArr[0];// 根据盐值 加密的密码String finalPassword = securePasswordArr[1];// 根据盐值 对新的密码进行加密
                password =SecureUtil.md5(salt + password);// 进行对比if(finalPassword.equals(password)){
                    result =true;}}}return result;}}

将 工具类 交给 spring 管理 ,后面使用 只需要注入即可 .

在这里插入图片描述

到此我们就完成了前置任务, 下面来写我们的功能

4. 功能实现

4.1 登录功能

约定一下 : 请求和响应

请求:[{
      
      post,(登录一般使用 post)/user/login  
    data:{username:"张三",password:"1234"}}]响应:[{"status":1/-1(1 表示成功 ,-1 表示失败)."message":"登录成功"/"登录失败","data":true/false}]

图一 :

在这里插入图片描述

图二 :

在这里插入图片描述

此时 后端就完成了 下面就可以来写前端了 :

图一 :

在这里插入图片描述

图二 :

在这里插入图片描述

代码 :

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>登录页面</title><linkrel="stylesheet"href="./css/common.css"><linkrel="stylesheet"href="./css/login.css"><scriptsrc="./js/jquery.js"></script></head><body><!-- 导航栏 --><divclass="nav"><imgsrc="./imgs/阳台.png"><spanclass="title">我的博客系统</span><!--    这个标签仅仅用于占位 ,把下面几个a 标签挤到右边--><divclass="spacer"></div><ahref="#">主页</a><ahref="#">写博客</a></div><!--
    正文部分

    这个 login-container 是贯穿整个页面的容器
--><divclass="login-container"><!-- 垂直水平居中的登录对话框    --><divclass="login-dialog"><h3>登录</h3><divclass="row"><span>用户名</span><inputtype="text"id="username"placeholder="输入用户名"></div><divclass="row"><span>密码</span><inputtype="password"id="password"placeholder="输入密码"></div><divclass="row"><buttonid="submit">提交</button></div><divclass="row"><aid="insert"href="add.html">
                注册
            </a></div><divclass="a">没有账户? 点击上面进行注册</div></div></div><script>// 通过 id 选中输入框 ,let username = document.querySelector("#username");// 通过 id 选中密码框let password = document.querySelector("#password");let submit = document.querySelector("#submit");// 点击按钮后触发
    submit.onclick=function(){// 1. 判断 username or passwordif(jQuery.trim(username.value)===''){alert("请先输入用户名");}if(jQuery.trim(password.value)===''){alert("请先输入密码")}// 此时 用户 和密码 都有了 ,发送 请求

        $.ajax({url:"/user/login",type:"POST",data:{"username": username.value,"password": password.value
            },// 回调函数success:function(result){if(result !=null&& result.data.status >0){// 登录成功 , 跳转到 博客列表页
                    location.href ="blog_list.html";}else{//登录 登录失败 ,alert("登录失败,请重新输入")}}})}</script></body></html>

登录功能搞完 : 下面就可以来弄 注册功能

4.2 注册功能

约定一下请求和响应 :

在这里插入图片描述

请求:[{
        post,url:/user/add
        data:{
            必填
            "username": xxx,"password": xxx,
            
            非必填
            "address": xxx,......}}]响应:[{data:{"status":1/-1  (注册成功 / 注册失败)
            "message":"","data":true/false}}]

图一 :

在这里插入图片描述

图二 :

在这里插入图片描述

图三 :

在这里插入图片描述

图四 :

在这里插入图片描述

附上代码 :

/**
     * 2. 注册功能
     */@RequestMapping(value ="/add")@TransactionalpublicResponseBodyMessage<Boolean>addUser(User user,@RequestPart(required =false, value ="filename")MultipartFile file){if(user ==null){returnnewResponseBodyMessage(-1,"注册失败",false);}// 1. 判断 必填参数是否为空 (这里可以不写 ,前端大概率 是会判断的 。 )if("".equals(user.getUsername())){returnnewResponseBodyMessage<>(-1,"注册失败, 当前用户为输入用户名",false);}if("".equals(user.getPassword())){returnnewResponseBodyMessage<>(-1,"注册失败,当前用户未输入密码",false);}// 2. 校验用户名的 唯一性 :  如果 用户名已经纯在了 那么就不能注册User user2 = userService.getUserByUserName(user.getUsername());if(user2 !=null){returnnewResponseBodyMessage<>(-1,"注册失败, 用户名已存在",false);}// 3. 手动设置 为 '' 的数据if("".equals(user.getAddress())){
            user.setAddress(null);}if("".equals(user.getQq())){
            user.setQq(null);}if("".equals(user.getSex())){
            user.setSex(null);}if("".equals(user.getUrl())){
            user.setUrl(null);}// 4. 对密码进行加密操作

        user.setPassword(passwordUtil.encrypt(user.getPassword()));// 5. 如果用户 上传了头像 ,可以将图片存入到本地if(file !=null){// 此时上传了头像 :// 获取到文件名 + 类型String fileNameAndType = file.getOriginalFilename();// 比如文件名为 : 阳台.png , 此时可以获取到 . 的 下标int index = fileNameAndType.lastIndexOf(".");// 从 index 位置开始截取String postfix = fileNameAndType.substring(index);// 判断一下 图片的格式是否符合预期要求if(".jpg".equals(postfix)||".png".equals(postfix)){// 通过 uuid 来设置文件名String uuid =IdUtil.simpleUUID();String imgFileStr = uuid + postfix;// 创建文件String path = IMAGE_PATH + imgFileStr;File imgFile =newFile(path);if(!imgFile.exists()){
                    imgFile.mkdir();}try{//                指定图片 , 上传之后的存储位置
                    file.transferTo(imgFile);// 文件上传成功 :

                    user.setUrl(imgFileStr);

                    userService.addUser(user);returnnewResponseBodyMessage<>(1,"注册成功",true);}catch(IOException e){//                e.printStackTrace();// 如果 创建失败 , 手动事务回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}// 此时 注册失败returnnewResponseBodyMessage<>(-1,"注册失败",false);}else{returnnewResponseBodyMessage<>(-1,"图片格式有误",false);}}// 6. 调用 userService 中的 addUser 方法 进行用户添加 (此时未上传图片 , 图片 为 默认)Integer ret = userService.addUser(user);if(ret !=1){returnnewResponseBodyMessage<>(-1,"注册失败",false);}returnnewResponseBodyMessage<>(1,"注册成功",true);}

后端写完, 来完成我们的前端 :

之前并没有完成 注册页面 , 这里直接来拷贝一下

  1. add.html
<!DOCTYPEhtml><!-- 网页使用的语言 --><htmllang="zh-CN"><head><!-- 指定字符集 --><metacharset="utf-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1"><title>添加用户</title><linkhref="css/bootstrap.min.css"rel="stylesheet"><style>body{background-image:url("./images/阳台.png");background-repeat: no-repeat;background-size: cover;}</style></head><body><divclass="container"style="width: 400px;"><h3style="text-align: center;">添加用户</h3><divclass="form-group"><labelfor="loginname">登录名:</label><inputtype="text"class="form-control"id="loginname"name="username"placeholder="请输入登录名"/></div><divclass="form-group"><labelfor="username">姓名:</label><inputtype="text"class="form-control"id="username"name="name"placeholder="请输入姓名"/></div><divclass="form-group"><labelfor="password">密码:</label><inputtype="password"class="form-control"id="password"name="password"placeholder="请输入密码"/></div><divclass="form-group"><labelfor="password2">确认密码:</label><inputtype="password2"class="form-control"id="password2"name="password"placeholder="请输入密码"/></div><divclass="form-group"><label>性别:</label><inputid="man"type="radio"name="sex"value="男"checked="checked"/>男
        &nbsp;&nbsp;&nbsp;<inputid="women"type="radio"name="sex"value="女"/>女
    </div><divclass="form-group"><labelfor="age">年龄:</label><inputtype="number"class="form-control"id="age"name="age"placeholder="请输入年龄"/></div><divclass="form-group"><labelfor="address">籍贯:</label><selectname="address"id="address"class="form-control"><optionvalue="北京">北京</option><optionvalue="上海">上海</option><optionvalue="广州">广州</option><optionvalue="深圳">深圳</option><optionvalue="成都">成都</option><optionvalue="杭州">杭州</option><optionvalue="重庆">重庆</option><optionvalue="西安">西安</option><optionvalue="武汉">武汉</option><optionvalue="沧州">沧州</option><optionvalue="江西">江西</option></select></div><divclass="form-group"><labelfor="qq">QQ:</label><inputtype="text"id="qq"class="form-control"name="qq"placeholder="请输入QQ号码"/></div><divclass="form-group"><labelfor="email">Email:</label><inputtype="text"id="email"class="form-control"name="email"placeholder="请输入邮箱地址"/></div><!--    style="display: none;"--><divclass="form-group"id="adminDiv"><labelfor="email">管理员:</label><inputid="admin_yes"type="radio"name="isadmin"value="1"/>是
        &nbsp;&nbsp;&nbsp;<inputid="admin_no"type="radio"name="isadmin"value="0"checked="checked"/>否
    </div><divclass="form-group"style="text-align: center"><inputid="btn_sub"class="btn btn-primary"type="button"value="提交"onclick="mysub()"/><inputid="btn_back"class="btn btn-default"type="button"value="返回"onclick="location.href='list.html'"/></div></div></body></html>

用到的 css 可以到 我 的资源里面下载 出来 , 比较多 这里就不拷贝到上面 了 .

在这里插入图片描述

这里我们需要使用 FormData 来 发送我们的数据 可以看来看一下这 : FormData

在这里插入图片描述

代码 :

<!DOCTYPEhtml><!-- 网页使用的语言 --><htmllang="zh-CN"><head><!-- 指定字符集 --><metacharset="utf-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1"><title>添加用户</title><linkhref="./css/bootstrap.min.css"rel="stylesheet"><scriptsrc="./js/jquery.js"></script><style>body{background-image:url("./imgs/阳台.png");background-repeat: no-repeat;background-size: cover;}#image{width: 400px;height: 250px;border: 1px solid #eee;}.message{width: 110px;height: 50px;line-height: 50px;font-weight: 600;}</style></head><body><formenctype="multipart/form-data"id="form1"><divclass="container"style="width: 400px;"><h3style="text-align: center;">添加用户</h3><divclass="form-group"><labelfor="username">姓名:</label><inputtype="text"class="form-control"id="username"name="name"placeholder="请输入姓名"/></div><divclass="form-group"><labelfor="password">密码:</label><inputtype="password"class="form-control"id="password"name="password"placeholder="请输入密码 "/></div><divclass="form-group"><labelfor="password2">确认密码:</label><inputtype="password2"class="form-control"id="password2"name="password"placeholder="请输入密码"/></div><divclass="form-group"><label>性别:</label><inputid="man"type="radio"name="sex"value="男"checked="checked"/>男
            &nbsp;&nbsp;&nbsp;<inputid="women"type="radio"name="sex"value="女"/>女
        </div><divclass="form-group"><labelfor="address">籍贯:</label><selectname="address"id="address"class="form-control"><optionvalue="">可以不选择</option><optionvalue="北京">北京</option><optionvalue="上海">上海</option><optionvalue="广州">广州</option><optionvalue="深圳">深圳</option><optionvalue="成都">成都</option><optionvalue="杭州">杭州</option><optionvalue="重庆">重庆</option><optionvalue="西安">西安</option><optionvalue="武汉">武汉</option><optionvalue="沧州">沧州</option><optionvalue="江西">江西</option></select></div><divclass="form-group"><labelfor="qq">QQ:</label><inputtype="text"id="qq"class="form-control"name="qq"placeholder="请输入QQ号码 (非必填) "/></div><divclass="form-group"><inputtype="file"name="filename"id="imgFile"><spanclass="message">图片样式: </span><imgsrc=""id="image"/></div><divclass="form-group"style="text-align: center"><inputid="btn_sub"class="btn btn-primary"type="button"value="提交"/><inputid="btn_back"class="btn btn-default"type="button"value="返回"onclick="location.href='list.html'"/></div></div></form><!--
     //   拿到 input  type 为 radio 中的内容 即 获取 男 女
        let sex = $('input[name=sex]:checked').val();

        let address = $("#address").val();
--><script>let imgFile = document.querySelector("#imgFile");// 这一部分 : 当我们上传图片后 , 我们的 图片样式 就会将图片显示出来

    imgFile.onchange=function(){let img = document.querySelector("#image");let image = imgFile.files[0];// let formData = new FormData();if(image){// formData.append('filename', image);
            img.src = window.URL.createObjectURL(image);}}// 当点击 提交按钮后 构造数据 , 通过 ajax 发送请求给后端let submit = document.querySelector("#btn_sub");

    submit.onclick=function(){let username = document.querySelector("#username");let password = document.querySelector("#password");let password2 = document.querySelector("#password2");// 通过 jquery 拿到  性别框里面的内容let sex =jQuery('input[name=sex]:checked').val();let address = document.querySelector('#address').value;let qq = document.querySelector("#qq").value;// jQuery.trim 去掉 前后空格if(jQuery.trim(username.value)===''){alert("请先输入用户名!!")// 将焦点设置到 id 为 username 的输入 框上
            username.focus();returnfalse;}if(jQuery.trim(password.value)===''){alert("请先输入密码");
            password.focus();returnfalse;}if(jQuery.trim(password2.value)===''){alert("请输入确认密码");
            password2.focus();}if(password.value !== password2.value){alert("两次密码不同,请重新输入")
            password.focus();returnfalse;}// 使用 formData 类来返回 let formData =newFormData();

        formData.append('username', username.value);

        formData.append('password', password.value);

        formData.append('qq', qq);

        formData.append('sex', sex);

        formData.append('address', address);let img = document.querySelector("#image");// 获取文件let image = imgFile.files[0];// 这里也可以通过 image 判断 if(img.src ===''){
            console.log('未上传图片 !!! ');
            formData.append('filename',null);}else{
            formData.append('filename', image)}// 通过 ajax 发送请求
        jQuery.ajax({type:"POST",url:"/user/add",data: formData,processData:false,contentType:false,success:function(result){if(result !=null&& result.data.status >0){alert('注册成功!');
                    location.href ="login.html";}else{alert('注册失败')}},error:function(){alert("出错了, 请稍后再试!!!")}})}</script></body></html>

上传文件使用到的 input 标签, 和 使用到的change 事件 : input 标签 change 事件

效果 :

在这里插入图片描述

到此我们的注册功能就完成了 , 下面就来写我们的博客列表页 .

4.3 博客列表页 (功能实现)

4.3.1 左侧框

图一 :

在这里插入图片描述

AppConfig 类

packagecom.example.blog_ssm.config;importcom.example.blog_ssm.util.PasswordUtil;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;@ConfigurationpublicclassAppConfigimplementsWebMvcConfigurer{// 1. 注入拦截器@AutowiredprivateLoginIntercept loginIntercept;@OverridepublicvoidaddResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/product/**").addResourceLocations("file:D:/ret/");}@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(loginIntercept).addPathPatterns("/**").excludePathPatterns("/user/login").excludePathPatterns("/user/add").excludePathPatterns("/css/**").excludePathPatterns("/js/**").excludePathPatterns("/imgs/**").excludePathPatterns("/login.html").excludePathPatterns("/add.html").excludePathPatterns("/product/**");}@BeanpublicPasswordUtilpasswordUtil(){returnnewPasswordUtil();}}

图二 :

在这里插入图片描述

后端完成了 ,下面就可以来完成我们的前端 :

在这里插入图片描述

图三 :

在这里插入图片描述

图四 :

在这里插入图片描述

图五 :

在这里插入图片描述

图六 :

在这里插入图片描述

图七 :

在这里插入图片描述

<script>// 这个 ajax 获取登录状态 :
    jQuery.ajax({type:"GET",url:"/user/getuser",success:function(result){if(result !=null&& result.data.status >0){let image = document.querySelector("#image1");

                image.src ="product/"+ result.data.data.url;let image2 = document.querySelector("#image2");

                image2.src ="product/"+ result.data.data.url;// 将用户名 换上去let username = document.querySelector("#username");

                username.innerHTML = result.data.data.username;}}})// 这个 ajax 获取 分类
    jQuery.ajax({type:"GET",url:"/blog/gettype",success:function(result){if(result !=null&& result.data.status >0){let number1 = document.querySelector("#number1");let number2 = document.querySelector("#number2");

                number1.innerHTML = result.data.data[0]
                number2.innerHTML = result.data.data[1];}else{alert("分类设置失败 !!! ")}},error:function(){alert("出错了, 请稍后再试!!!")}})</script>

左侧部分 就完成了, 下面就来完成我们的右侧部分 ,这里我们可以写一个分页器

4.3.2 右侧框 (分页功能 + 页面显示)

图一 :

在这里插入图片描述

图二 :

在这里插入图片描述

图三 :

在这里插入图片描述

图四 :

在这里插入图片描述

这里不好截图 直接看代码 :

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>博客列表页</title><link rel="stylesheet" href="./css/common.css"><link rel="stylesheet" href="./css/blog_list.css"><script src="./js/jquery.js"></script><link href="css/bootstrap.min.css" rel="stylesheet"></head><body><!-- 导航栏 --><div class="nav"><img src="./imgs/阳台.png" id="image1"><span class="title">我的博客系统</span><!--    这个标签仅仅用于占位 ,把下面几个a 标签挤到右边--><div class="spacer"></div><a href="#">主页</a><a href="#">写博客</a><a href="#">注销</a></div><!-- 页面主体部分 --><div class="container"><!--    左侧信息--><div class="container-left"><!--        使用 这个 .card 表示用户信息--><div class="card"><img src="./imgs/girl.png" alt="图片显示失败" id="image2"><!--            用户名--><h3 id="username"></h3><a href="#">Gitee 地址</a><div class='counter'><span>文章</span><span>分类</span></div><div class="counter"><span id="number1">1</span><span id="number2">2</span></div></div></div><!--    右侧信息--><div class="container-right"><!--&lt;!&ndash;--><!--            表示一篇博客--><!--&ndash;&gt;--><!--<div class="blog">--><!--&lt;!&ndash;--><!--                   博客标题--><!--&ndash;&gt;--><!--<div class="title">我的第一篇博客</div>--><!--&lt;!&ndash;--><!--                发布时间--><!--&ndash;&gt;--><!--<div class="data">--><!--2023-03-02--><!--</div>--><!--&lt;!&ndash;--><!--                博客的摘要--><!--&ndash;&gt;--><!--<div class="desc">--><!--                从今天起 , 我要认真敲代码--><!--                Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint eaque facilis perferendis! Numquam--><!--                neque voluptatum ab vero expedita possimus fuga eos, illo sapiente delectus quidem natus maiores,--><!--                ipsum impedit rerum?--><!--</div>--><!--&lt;!&ndash;--><!--                查看全文按钮--><!--&ndash;&gt;--><!--<a href="#">查看全文 &gt;&gt;</a>--><!--</div>--><div id="page"><nav aria-label="Page navigation"><ul id="all"class="pagination"><li class="active"><a href="javascript:firstPage();">首页</a></li><li><a href="javascript:beforePage();">上一页</a></li><li><a href="javascript:nextPage();">下一页</a></li><li><a href="javascript:lastPage();">末页</a></li><span id="pageinfo" style="font-size: 20px;margin-left: 10px;"></span></ul></nav></div></div></div><script>// 这个 ajax 获取登录状态 :
    jQuery.ajax({type:"GET",url:"/user/getuser",success:function(result){if(result !=null&& result.data.status >0){let image = document.querySelector("#image1");

                image.src ="product/"+ result.data.data.url;let image2 = document.querySelector("#image2");

                image2.src ="product/"+ result.data.data.url;// 将用户名 换上去let username = document.querySelector("#username");

                username.innerHTML = result.data.data.username;}}})// 这个 ajax 获取 分类
    jQuery.ajax({type:"GET",url:"/blog/gettype",success:function(result){if(result !=null&& result.data.status >0){let number1 = document.querySelector("#number1");let number2 = document.querySelector("#number2");

                number1.innerHTML = result.data.data[0]
                number2.innerHTML = result.data.data[1];}else{alert("分类设置失败 !!! ")}},error:function(){alert("出错了, 请稍后再试!!!")}})//  分页功能 :// 1. 当前的页码let pIndex =1;// 2. 每页显示多少篇博客let pSize =2;// 3. 总页数let totalPage =0;// 4. 总条数 (当前所有的博客数目)let totalCount =0;// 通过 ajax 获取 总页数 和 总条数functiongetList(){

        jQuery.ajax({type:"GET",url:"/blog/listbypage",data:{"pIndex": pIndex,"pSize": pSize
            },success:function(result){if(result !=null&& result.data.status >0){// 总博客数
                    totalCount = result.data.data.count;// ceil 四舍五入并返回大于等于给定数字的最小整数。

                    totalPage = Math.ceil(parseInt(totalCount)/ pSize);let size = result.data.data.list.length;// rightDiv  后面创建的 元素需要挂载 rightDiv 上let rightDiv = document.querySelector(".container-right");for(let i =0; i < size; i++){let ret = result.data.data.list[i];let blogDiv = document.createElement('div');// 引入 class 属性
                        blogDiv.className ="blog";// 1. 构造标题let titleDiv = document.createElement('div');

                        titleDiv.innerHTML = ret.title;

                        titleDiv.className ="title";// 将 titleDiv 挂到 blogDiv上
                        blogDiv.appendChild(titleDiv);// 2. 构造 发布时间let dataDiv = document.createElement('div');

                        dataDiv.innerHTML = ret.postTime;

                        dataDiv.className ="data";

                        blogDiv.appendChild(dataDiv);// 3. 构造 文章描述let descDiv = document.createElement('div');

                        descDiv.innerHTML = ret.content;

                        descDiv.className ="desc";

                        blogDiv.appendChild(descDiv);// 4. 构造 查看全文按钮let a = document.createElement('a');

                        a.innerHTML ="查看全文 &gt;&gt;";// 重点 : 这里我们点击查看全文 跳转到 博客详情页 ,这里可以 在 url 里面添加一个 博客id ,// 后面在 博客详情页就可以通过这个 blogId 获取到文章.

                        a.href ="blog_detail.html?blogId="+ ret.blogId;

                        blogDiv.appendChild(a);

                        rightDiv.appendChild(blogDiv);}// 将 分页器 挂载 构造好的数据 最后面 .let page = document.querySelector("#page");

                    rightDiv.appendChild(page);}else{alert("获取失败!!!")}},error:function(){alert("出错了,请稍后在尝试!!!")}})}// getList();// 首页functionfirstPage(){
        location.href ="blog_list.html?pIndex=1"}// 上一页functionbeforePage(){if(pIndex >1){

            pIndex =parseInt(pIndex)-1;

            location.href ="blog_list.html?pIndex="+ pIndex;}else{alert("已经是首页了!!!")}}// 下一页functionnextPage(){if(pIndex < totalPage){

            pIndex =parseInt(pIndex)+1;

            location.href ="blog_list.html?pIndex="+ pIndex;}else{alert("已经是末页了!!!")}}// 末页functionlastPage(){
        location.href ="blog_list.html?pIndex="+ totalPage;}// 使用这个 方法来初始话页面functioninitPage(){// 获取 当前页面的 查询字符串  比如 :?pIndex=2let url = location.search;if(url !=''){// 将 问好 去掉 此时就剩下了 pIndex=2 (假设页数是2)
            url = url.substring(1);// let kvs = url.split("&");let kvs = url.split("=");// 获取到 跳转后的页数 ,
             pIndex = kvs[1];}// 通过 getList 方法去获取到数据getList();}// 通过 initPage 方法来 初始化页面 .initPage();</script></body></html>

Math.ceil() - JavaScript | MDN (mozilla.org)

页面效果:

在这里插入图片描述

上面我们的代码其实还有一个没中不足的地方 , 我们的文章 应该是 后发布的在前面, 而不是 以前发布的在前面 ,这里就来修改一下 ,也非常简单 , 就是给我们的SQL 加一个 排序 (按照时间排序即可)

在这里插入图片描述

到此我们的博客列表页的内容就完成了 , 下面就来完成我们的 博客详情页

4.4 博客详情页

这里我们主要实现查看 博客的功能 .

图一 :

在这里插入图片描述

图二 :

在这里插入图片描述

图三 :

在这里插入图片描述

图四 :

在这里插入图片描述

图五 :

在这里插入图片描述

图六 :

在这里插入图片描述

图七 :

在这里插入图片描述

前端代码 :

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>博客详情页</title><linkrel="stylesheet"href="./css/common.css"><linkrel="stylesheet"href="./css/blog_detail.css"><scriptsrc="./js/jquery.js"></script><!--    引入 editor.md 的依赖--><linkrel="stylesheet"href="./editor.md/css/editormd.min.css"><scriptsrc="./editor.md/lib/marked.min.js"></script><scriptsrc="./editor.md/lib/prettify.min.js"></script><scriptsrc="./editor.md/editormd.min.js"></script></head><body><!-- 导航栏 --><divclass="nav"><imgsrc="./imgs/阳台.png"><spanclass="title">我的博客系统</span><!--    这个标签仅仅用于占位 ,把下面几个a 标签挤到右边--><divclass="spacer"></div><ahref="#">主页</a><ahref="#">写博客</a><ahref="#">注销</a></div><!-- 页面主体部分 --><divclass="container"><!--    左侧信息--><divclass="container-left"><!--        使用 这个 .card 表示用户信息--><divclass="card"><imgsrc="./imgs/girl.png"alt="图片显示失败"><!--            用户名--><h3>牧</h3><ahref="#">Gitee 地址</a><divclass='counter'><span>文章</span><span>分类</span></div><divclass="counter"><span>1</span><span>2</span></div></div></div><!--    右侧信息--><divclass="container-right"><!-- 博客标题 --><h3class="title"id="title">我的第一篇博客</h3><!-- 博客发布时间--><divclass="date">2023-03-02</div><!-- 博客正文 --><divid="content"><!--            <P>--><!--                从今天开始我要认真敲代码--><!--                从今天开始我要认真敲代码--><!--                从今天开始我要认真敲代码--><!--                从今天开始我要认真敲代码--><!--            </P>--><!--            <P>--><!--                从今天开始我要认真敲代码--><!--                从今天开始我要认真敲代码--><!--                从今天开始我要认真敲代码--><!--                从今天开始我要认真敲代码--><!--            </P>--><!--            <P>--><!--                从今天开始我要认真敲代码--><!--                从今天开始我要认真敲代码--><!--                从今天开始我要认真敲代码--><!--                从今天开始我要认真敲代码--><!--            </P>--></div></div></div><script>functiongetBlogDetail(){
        jQuery.ajax({type:"GET",// location.search 就是 ?blogId=xurl:"/blog/getblog"+ location.search,success:function(result){if(result !=null&& result.data.status >0){let data = result.data.data;// 1. 构造博客标题let title = document.querySelector("#title");

                    title.innerHTML = data.title;// 2. 构造发布时间let dateDiv = document.querySelector(".date");

                    dateDiv.innerHTML = data.postTime;// 3. 构造正文部分// let content = document.querySelector(".content");//// content.innerHTML = data.content;// 使用 editormd.md 自带的方法 对内容进行渲染
                    editormd.markdownToHTML('content',{markdown: data.content
                    })let userid = data.userid;

                    jQuery.ajax({type:"GET",url:"/user/getuserbyid",data:{"userid": userid,},success:function(result){if(result !=null&& result.data.status >0){let data = result.data.data;// 通过子类选择器选中 img 元素let img = document.querySelector(".card>img");

                                img.src ="product/"+ data.user.url;let title = document.querySelector(".card>h3");

                                title.innerHTML = data.user.username;let spanArr = document.querySelectorAll(".counter>span")

                                spanArr[2].innerHTML = data.blogNumber;

                                spanArr[3].innerHTML = data.type;}else{alert("设置错误!!!")}},error:function(){alert("出错了,请稍后再试!!")}})}}})}getBlogDetail();functiongetLoginUser(){
        jQuery.ajax({type:"GET",url:"/user/getuser",success:function(result){if(result !=null&& result.data.status >0){let img = document.querySelector(".nav>img");

                    img.src ="product/"+ result.data.data.url;}}})}getLoginUser();</script></body></html>

4.5 写博客功能

图一 :

在这里插入图片描述

图二 :

在这里插入图片描述

图三 :

在这里插入图片描述

图四 :

在这里插入图片描述

图五 :

在这里插入图片描述

最后完成我们的注销 功能 这个 小项目就完成了 .

4.6 注销功能

图一 :

在这里插入图片描述

图二 :

在这里插入图片描述

到此 这个 小项目就完成了, 其实这个项目还有很多东西可以加 ,这些大家都可以 自由发挥 .

标签: 前端 mybatis java

本文转载自: https://blog.csdn.net/mu_tong_/article/details/129425270
版权归原作者 牧.. 所有, 如有侵权,请联系我们删除。

“博客项目- SSM 实现”的评论:

还没有评论