博客设计(项目后端)

准备工作

1.创建项目

在这里插入图片描述

2.引入依赖

在这里插入图片描述
我的数据库:8.0.32版本,导入的驱动便是32版本

我的tomcat是8.5版本,所以Servlet的依赖便是3.1版本。

另一个json依赖随意,版本别太低就行。(如何导入依赖)
(具体情况可以看下面的一篇文章链接,关于Servlet)

<dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.32</version>
        </dependency>

    </dependencies>

3.创建必要的目录

在这里插入图片描述

数据库设计

1.博客数据
名字:blog
字段:id,标题(title),正文(content),userID,发布时间(postTime)

2.用户数据
名字:user
字段:userID,username(姓名),password(密码)

对于建表的sql,会单独搞一个sql文件,进行了保存。目的是为了在不同的主机上进行部署,我们就需要将数据库也创建好。

在这里插入图片描述

create database if not exists blog_system;
use blog_system;
drop table if exists blog;
create table blog(
    blogId int primary key auto_increment,
    title varchar(128),
    content varchar(4096),
    userId int,
    postTime datetime
);
drop table if exists user;
create table user(
    userId int primary key auto_increment,
    
  	 username varchar(20) unique ,
    password varchar(20)
);

insert into user values (null,"zhangsan","123456"),(null,"lisi","123546");

在这里插入图片描述

封装数据库操作(java)

就是对JDBC进行封装

1.封装数据库链接

创建一个目录model
在这里插入图片描述
在这个目录中建一个java文件(DBUtil),这个类用来封装数据库链接。
?号前面是数据库,后面不用管。
因为考虑到线程安全的问题,所以我这里使用了懒汉模式(具体情况可以去看下面我的文章:多线程)

import com.mysql.cj.jdbc.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class DBUtil {
    private volatile static DataSource dataSource=null;
    private static DataSource getDataSource(){
        //使用的时候在实例化,但是要用考虑多线程下的安全,所以加锁(单例)
        if (dataSource==null){
            synchronized (DBUtil.class){
                if (dataSource==null){
                    dataSource=new MysqlDataSource();
                    ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/blog_system?characterEncoding=utf8&useSSL=false");
                    ((MysqlDataSource)dataSource).setUser("root");
                    ((MysqlDataSource)dataSource).setPassword("xietian1314");
                }
            }
        }
        return dataSource;
    }
    
    public static Connection getConnection() throws SQLException {
        //建立连接
        return getDataSource().getConnection();
    }
     public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
        if (resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (statement!=null){
            try {
                statement.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

close方法中的关闭不能调换顺序(详情可以看我下面的文章:mysql)

2.创建实例对象(数据表有两个)

所以实例对象java文件也有两个。

  • User:对应数据库中的user表(字段有什么,那么User的成员就对应什么)
  • Blog:对应数据库中的blog表(字段有什么,那么Blog的成员就对应什么)

Blog类

import java.sql.Timestamp;
import java.text.SimpleDateFormat;

public class Blog {
    private  int blogId;
    private String title;
    private String content;
    private int userId;
    private Timestamp postTime;

    public int getBlogId() {
        return this.blogId;
    }

    public void setBlogId(int blogId) {
        this.blogId = blogId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

//    public Timestamp getPostTime() {
//        return postTime;
//    }

    public String getPostTime(){
        //返回格式化时间
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(postTime);
    }

    public void setPostTime(Timestamp postTime) {
        this.postTime = postTime;
    }
}

User类

public class User {
    private int userId;
    private String username;
    private String password;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

这里的get和set方法不需要自己敲,具体情况可以看我下面文章中:java中,目录:类与方法中体现

3.封装必要的增删改查操作

因为有两张表,所以需要分别对两张表的增删改查添加方法代码(UserDao,BlogDao)

Dao:data access object:通过这样的对象来访问数据。
在这里插入图片描述

BlogDao类

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class BlogDao {
    //把一个Blog对象插入到数据库中
    public void insert(Blog blog){
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            //建立连接
            connection=DBUtil.getConnection();
            //构造sql
            String sql="insert into blog values(null,?,?,?,?)";
            statement=connection.prepareStatement(sql);
            statement.setString(1,blog.getTitle());
            statement.setString(2,blog.getContent());
            statement.setInt(3,blog.getUserId());
            statement.setString(4,blog.getPostTime());
            //执行sql
            statement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,statement,null);
        }
    }
    //查询blog表中所以的博客数据
    public List<Blog> selectAll(){
        List<Blog> list=new ArrayList<>();
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
             String sql="select * from blog order by postTime desc ";
            statement=connection.prepareStatement(sql);
            resultSet=statement.executeQuery();
            while (resultSet.next()){
                Blog blog=new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("titlie"));
                //摘取100个字符长度做摘要
                if (content.length()>100){
                    content+=content.substring(0,100)+"...";
                }
                blog.setContent(content);
                blog.setUserId(resultSet.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                list.add(blog);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return list;
    }
    //查询一个博客id来查询对应的博客
    public Blog selectOne(int blogId){

        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
            String sql="select * from blog where blogId=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            resultSet=statement.executeQuery();
            if (resultSet.next()){
                Blog blog=new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("title"));
                blog.setContent(resultSet.getString("content"));
                blog.setUserId(resultSet.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                return blog;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;

    }
    //根据一个博客id来删除对应的博客
    public void delete(int blogId){

        Connection connection=null;
        PreparedStatement statement=null;
        try {
            connection=DBUtil.getConnection();
            String sql="delete  from blog where blogId=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            statement.executeUpdate();

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,statement,null);
        }

    }
}

UserDao

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserDao {

    //新增先不管

    public  User selectUserById(int userId){
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
            String sql="select * from user where userId=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,userId);
            resultSet=statement.executeQuery();
            if (resultSet.next()){
                User uer=new User();
                uer.setUserId(resultSet.getInt("userId"));
                uer.setUsername(resultSet.getString("username"));
                uer.setPassword(resultSet.getString("password"));
                return uer;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

    public User selectUserByName(String username){
        //无法重复,数据库写了unique
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
            String sql="select * from user where username=?";
            statement=connection.prepareStatement(sql);
            statement.setString(1,username);
            resultSet=statement.executeQuery();
            if (resultSet.next()){
                User uer=new User();
                uer.setUserId(resultSet.getInt("userId"));
                uer.setUsername(resultSet.getString("username"));
                uer.setPassword(resultSet.getString("password"));
                return uer;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

}

前后端逻辑的实现

博客列表页

展示博客列表
1.约定前后端交互接口

请求: Get  /blog
响应:json类型

2.写后端代码
创建一个Servlet来处理对应的请求

import com.fasterxml.jackson.databind.ObjectMapper;
import model.Blog;
import model.BlogDao;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        BlogDao blogDao=new BlogDao();
        List<Blog> blogs=blogDao.selectAll();
        
        String respString=objectMapper.writeValueAsString(blogs);
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write(respString);
    }
}

3.写前端代码
在前端构造ajax请求,按照上述约定,发送http请求
具体前端页面可以看我下面的文章(博客设计(项目前端))这里将ajax主要代码写一下。
用ajax实现构造div,实现获取到所有的博客数据,并且构造到页面上(blog_list.html)

 <script>
        // 通过ajax给服务器发请求,获取到所有的博客数据,并且构造到页面上
        function getBlogs(){
            $.ajax({
                type:'get',
                url:'blog',
                success:function(body){
                    let containerRight=document.querySelector('.container-right');
                    for(let blog of body){
                        let blogDiv=document.createElement("div");
                        blogDiv.className='blog';
                        let titleDiv=document.createElement("div");
                        titleDiv.className='title';
                        titleDiv.innerHTML=blog.title;
                        let dateDiv=decument.createElement("div");
                        dateDiv.className='date';
                        dateDiv.innerHTML=blog.postTime;
                        let descDiv=decument.createElement("div");
                        descDiv.className='desc';
                        descDiv.createElement=blog.content;
                        let a=document.createElement("a");
                        a.href='blog_datail.html?Id='+blog.blogID;
                        a.innerHTML='查看全文&gt;&gt;';

                        //将构造好的标签构造好之后,还需要组合起来
                        blogDiv.appendChild(titleDiv);
                        blogDiv.appendChild(dateDiv);
                        blogDiv.appendChild(descDiv);
                        blogDiv.appendChild(a);
                        containerRight.appendChild(blogDiv);
                    }
                }
            });
        }
        getBlogs();
    </script>

此时我们往数据库里插入一些数据,运行服务器和页面后,发现时间,为时间戳而不是格式化时间,博客的顺序也有问题,应该是最新的在上面。所以我们就需要查明问题的原因在哪里。通过抓包工具我发现抓到的数据是时间戳,意味着服务器返回的时间是时间戳。
(后端返回的数据是Jackson把blogs转化成json字符串,直接返回 Jason会遍历当前的blogs List.不要的对象去调用不了的对象的那个get方法,获取到对应的属性,构造成json字符串。)

所以我将关于时间的get方法给重写了,通过SimpleDateFormat格式化(但是格式不统一,用之前一定要查)

顺序:通过对时间进行排序完成(代码已做修改)

博客详情页

1.约定前后端交互接口

请求: Get  /blog/blogId=?
响应:json类型

2.编写后端代码
从query string 中查询一下是否有blogId,如果有就认为是指定博客;如果没有就是查询所有博客

@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从query string 中查询一下是否有blogId,如果有就认为是指定博客;如果没有就是查询所有博客
        BlogDao blogDao=new BlogDao();
        String blogId=req.getParameter("blogId");

       if (blogId==null){
           List<Blog> blogs=blogDao.selectAll();
           String respString=objectMapper.writeValueAsString(blogs);
           resp.setContentType("application/json;charset=utf8");
           resp.getWriter().write(respString);
       }else {
           Blog blog = blogDao.selectOne(Integer.parseInt(blogId));
           String respString = objectMapper.writeValueAsString(blog);
           resp.setContentType("application/json;charset=utf8");
           resp.getWriter().write(respString);
       }
    }
}

3.编写前端代码
跟上面一样,只粘贴最重要的部分。(具体情况看我的前端)

<script>
        function getBlog(){
            $.ajax({
                type:'get',
                url:'blog'+location.search,
                success:function(body){
                    //设置博客标题
                    let h3=document.querySelector('.conrainer-right h3');
                    h3.innerHTML=body.title;
                    //设置发布时间
                    let dateDiv=document.querySelector('.conrainer-right .date')
                    dateDiv.innerHTML=body.postTime;
                    //设置正文,正文内容应该是markdown格式的数据
                    //此处应该是渲染后的markdown内容。而不是markdown的原始字符串
                    //第一个参数,是一个html元素的id,接下来来渲染结果放到对应的元素中
                    editormd.markdownToHTML('content',{markdown:body.content});
                }
            });
        }
        getBlog();
    </script>

问题:
此时运行代码,发现代码根本没有渲染,原因在于浏览器缓存,从网络上获取数据的速度较为慢,所以浏览器呢对于这种情况,将一些数据放在了浏览器缓存中,等下一次或点击获取的时候会直接显示这个内容。从而就避免了。因网络原因所造成的明显风险。但是在我们这个页面中发现它并没有发生改变,其原因就在于这个问题我们需要将缓存进行更新,让他强制刷新一下。F5+ctrl;

此时可能会出现一些问题
比如导入的依赖出现了问题,换一个就好了。

登录功能

1.约定前后端交互接口
请求:
post /login
content-type:application/x-www-form=urlencided
query string 格式;
响应:
http/1.1 302
Location:blog_list.html

如果通过302跳转
前端必须使用from,不能用ajax,ajax,收到响应,不会触发页面跳转
2.编写后端代码
创建一个class类LoginServlet
在这里插入图片描述

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //设置编码
        req.setCharacterEncoding("utf8");
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        if (username==null||username.equals("")||password==null||password.equals("")){
            String html="<h3> 登录失败!缺少用户名密码 </h3>";
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write(html);
            return;
        }
        UserDao userDao=new UserDao();
        User user=userDao.selectUserByName(username);
        if (user==null){
            //用户名不存在
            String html="<h3>用户名或密码</h3>";
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write(html);
            return;
        }
        if (!password.equals(user.getPassword())){
            //用户名不存在
            String html="<h3>用户名或密码</h3>";
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write(html);
            return;
        }
        //登录成功建立会话。理解成一个哈希表
         HttpSession session= req.getSession(true);
         session.setAttribute("user",user);
         //返回一个重定向响应
        resp.sendRedirect("blog_list");

    }
}

3.编写前端代码
这个没啥好说的。主要可以去看我的HTML板块

   <div class="login-container">
        <div class="login-dialog">
            <h3>登录</h3>
            <!-- 用form包裹,方便后续代码的在提交给服务器 -->
            <form action="login" method="post">
                <div class="row">
                    <span>用户名</span>
                    <input type="text"  id="username" name="username">
                </div>
                <div class="row">
                    <span>密码</span>
                    <input type="password" id="password" name="password">
                </div>
                <div class="row">
                    <input type="submit" id="submit" value="登录">
                </div>
            </form>
        </div>

    </div>

强制登录设定

类似于在网上淘宝购物时,无论点什么都要登录。
在博客列表页,详情页登录页。页面加载的时候发起一个。ajax请求,通过这个请求访问服务器,获取当前的登录状态,如果当前灯未登录则跳转登录页面,如果已登录则不做任何处理。
1.约定一个前后端交互接口
请求:
get /login
响应:
登录成功,返回200这样的响应,body可以不要。登陆失败(未登录),返回403这样的响应。
2.后端代码
在LoginServlet写一个doget判断当前状态。
固定操作。

   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       HttpSession session= req.getSession(false);
       if (session==null){
           resp.setStatus(403);
           return;
       }
     User user  =(User)session.getAttribute("user");
       if (user==null){
           //虽然会话对象存在,但是用户对象没有,未登录状态
           resp.setStatus(403);
           return;
       }
       resp.setStatus(200);
    }

3.前端代码
(具体代码看我项目前端)

function getLoginStatus(){
    $.ajax({
        type:'get',
        url:'login',
        success:function(body){
            //响应200的时候,执行success回调
            //用户已经登录。啥都不用干
            console.log("用户已登录");
        },
        error:function(body){
            //响应403
            Location.assign("login.html");
        }
    });
}

显示作者信息

1.在博客列表页,要获取到登录用的信息
1.前后端交互
通过Json将当前信息返回回来
请求:GET/login
响应:json格式
2.后端代码

       resp.setStatus(200);
       resp.setContentType("application/json;charset=utf8");
       user.setPassword("");
       String respJson=objectMapper.writeValueAsString(user);
       resp.getWriter().write(respJson);

3.前端代码

2.在博客详情页,要获取文章作者的信息
1.前后端交互
请求:Get /user?blogId=1

响应:json格式
2.后端代码
建立一个新的java类
在这里插入图片描述

@WebServlet("/user")
public class UserServlet  extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        String blogId=req.getParameter("blogId");
        if (blogId==null||blogId.equals("blogId")){
            String respJson=objectMapper.writeValueAsString(new User());
            resp.getWriter().write(respJson);
            System.out.println("参数blogId为空");
            return;
        }
        BlogDao blogDao=new BlogDao();
        Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
        if (blog==null){
            String respJson=objectMapper.writeValueAsString(new User());
            resp.getWriter().write(respJson);
            System.out.println("参数blogId不存在");
            return;
        }
        
        UserDao userDao=new UserDao();
        User user=userDao.selectUserById(blog.getUserId());
        if (user==null){
            String respJson=objectMapper.writeValueAsString(new User());
            resp.getWriter().write(respJson);
            System.out.println("作者博客不存在");
            return;
        }
        
        String respJson=objectMapper.writeValueAsString(user);
        resp.getWriter().write(respJson);
    }
}

3.前端代码

        function getAuther(){
            $.ajax({
                type:'get',
                url:'user'+location.search,
                success:function(body){
                    if(body.userId==0){
                        alert("当前为找到作者信息");
                        return;
                    }
                    let h3=document.querySelector('.card h3');
                    h3.innerHTML=body.username;
                }
            });
        }
        getAuther();

注销

1.前后端交互
请求:
GET /logout

响应:
HTTP/1.1
location:login.html

2.编写后端
根据logout路径,设定新的Servlet

@WebServlet("logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session=req.getSession(false);
        if (session==null){
            resp.sendRedirect("login.html");
            return;
        }
        //user存在,就删除了,不存在,也不会有副作用
        session.removeAttribute("user");
        resp.sendRedirect("login.html");
    }
}

3.编写前端
在这里插入图片描述

实现发布博客

用户写的博客标题和正文,就可以随着点击发布,从而进行上传,服务器可以保存到数据库。

1.约定前后端交互接口

请求:POST /blog
响应:302 Location:blog_list.html

2.实现后端代码
从请求中拿到标题和正文
从会话中拿到用户的登录状态(作者id)
给blog对象

 @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String title=req.getParameter("title");
        String content= req.getParameter("content");
        if (title==null||title.equals("")||content==null||content.equals("")){
            String html="<h3> title 或者 content 为空!新增博客失败!</h3>";
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write(html);
            return;
        }
        
        //2.从会话中拿到作者的id
        HttpSession session= req.getSession(false);
        if (session==null){
            String html="<h3> 用户未登录!新增博客失败!</h3>";
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write(html);
            return;
        }
        User user=(User) session.getAttribute("user");
        if (user == null) {
            String html="<h3> 用户未登录!新增博客失败!</h3>";
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write(html);
            return;
        }
        //构造blog对象
        Blog blog=new Blog();
        blog.setUserId(user.getUserId());
        blog.setTitle(title);
        blog.setContent(content);
        blog.setPostTime(new Timestamp(System.currentTimeMillis()));
        
        BlogDao blogDao=new BlogDao();
        blogDao.insert(blog);
        
        resp.sendRedirect("blog_list.html");

    }

3.实现前端代码
如何把编辑框内的 MD内容作为form的一部分交给服务器?在editor点MD中的官方文件档中,demo里给。里面提示先给#editor div中放一个隐藏的textarea,后续编辑器输入框的内容就会被自动放到这个textarea中。在初始化代码中需要新增一个选项,savehtmltotextarea。

    <div class="blog-edit-container">
        <form action="blog" method="post">
            <div class="title">
                <input type="text" id="title-input" name="title">
                <input type="submit" id="submit">
            </div>
            <div id="editor">
                <textarea name="content" style="display: none;"></textarea>
            </div>
        </form>
        
    </div>
 <script>
        var editor=editormd("editor",{
            width:"100%",
            height:"calc(100% - 50px)",
            markdown:"# 在这里写下一篇博客",
            path:"editor.md/lib/",
            saveHTMLTotextarea:true
        });
        getLoginStatus();
    </script>

总结

构造http请求有很多方式
1.地址栏,输入url
2.特殊的html标签,a,img,link,script
3.form (form 会跳转页面,只支持get和post)
4.ajax (ajax不会跳转页面(可以使用js跳转) Location.assign(“login.html”);)
5.其他语言编写的客户端

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值