做视频网站违法,葫芦岛建设工程信息网站,现在在百度做网站要多少钱,绍兴网站制作套餐基于 Servlet 的博客系统 一、准备工作1、创建项目2、创建包3、导入前端静态页面 二、数据库设计1、blog#xff08;博客表#xff09;2、user#xff08;用户表#xff09;3、建库建表的 SQL 语句 三、封装数据库操作1、为什么要封装数据库#xff1f;2、封装数据库的连接… 基于 Servlet 的博客系统 一、准备工作1、创建项目2、创建包3、导入前端静态页面 二、数据库设计1、blog博客表2、user用户表3、建库建表的 SQL 语句 三、封装数据库操作1、为什么要封装数据库2、封装数据库的连接/关闭操作3、创建实体类4、封装必要的增删改查操作 四、前后端业务逻辑实现1、登录功能1约定前后端交互接口2编写后端代码3编写前端代码 2、检查用户登录1约定前后端交互接口2编写后端代码3编写前端代码 3、博客列表1约定前后端交互接口2编写后端代码3编写前端代码 4、博客列表页用户信息1约定前后端交互接口2编写后端代码3编写前端代码 5、博客详情页1约定前后端交互接口2编写后端代码3编写前端代码 6、博客详情页用户信息1约定前后端交互接口2编写后端代码3编写前端代码 7、发布博客1约定前后端交互接口2编写后端代码3编写前端代码 8、注销功能1约定前后端交互接口2编写后端代码3编写前端代码 五、总结 一、准备工作
1、创建项目
这里需要创建一个Maven项目在 pom.xml 中引入项目的依赖文件Servlet、Mysql、Jackson并创建必要的目录结构 2、创建包
为了使代码层次更加清晰这里采用经典的Web项目设计结构——MVC Mmodel表示和数据相关的部分。 Vview表示和界面相关的部分。 Ccontroller表示数据和界面之间的业务逻辑。 因此在后端业务逻辑方面在Java目录下创建两个包分别是 model存放和数据相关的逻辑代码controller存放前后端交互的业务逻辑。对于博客的前端页面部分可以在导入时直接放到 webapp 目录下。 3、导入前端静态页面 二、数据库设计
对于当前博客系统的数据库设计相对比较简单主要涉及到两个实体分别是 博客 和 用户它们之间的 ER 关系图如下以及各自的表结构如下所示 1、blog博客表
列名数据类型描述blogIdINT博客ID主键titleVARCHAR博客标题contentVARCHAR博客内容userIdINT用户ID外键postTimeDATETIME发布时间
2、user用户表
列名数据类型描述userIdINT用户ID主键usernameVARCHAR用户名passwordVARCHAR密码
3、建库建表的 SQL 语句
create database if not exists blog_system charset utf8;;use blog_system;drop table if exists users;
create table users (userId int primary key auto_increment,username varchar(50) unique,password varchar(50)
);drop table if exists blogs;
create table blogs (blogId int primary key auto_increment,title varchar(32),content varchar(4096),postTime datetime,userId int,foreign key(userId) references users(userId)
);-- 为了方便后续调试这里插入一些初始内容
insert into users values(null,张三,123),(null,李四,456);insert into blogs values(null,我的第一篇博客,编程之路道阻且长。,2022-4-26 14:22:00,1);
insert into blogs values(null,我的第一篇博客,C生万物编程之本。,2022-5-26 14:22:00,1);
insert into blogs values(null,我的第一篇博客,Java 面向对象。,2022-6-26 14:22:00,1);注意一般对于建表的 sql 都会单独搞个 .sql 文件来保存。因为后续程序可能需要在不同的主机上部署部署的时候就需要在对应的主机上把数据库也给创建好。把建表 sql 保存好方便后续在不同的机器上进行建库建表。
三、封装数据库操作
1、为什么要封装数据库
在解答这个问题之前我们先假设在项目中不封装数据库操作的情形倘若我们对数据库不做任何的封装试想一下当我们在后续的业务逻辑中比如想要查询数据库的数据、或是想要向数据库中插入一些数据无论我们针对数据库进行任何操作都需要进行 JDBC 的五个步骤 创建并初始化一个数据源和数据库服务器建立连接构造SQL语句执行SQL语句释放必要的资源 在业务逻辑中像这样和数据库的交互操作可能有很多如果每个操作我们都按部就班地进行 JDBC在代码层面将会是非常冗余并且代码的可读性将会大大降低更糟糕的是这样做还会使得我们在开发中不能专注于业务逻辑大大降低开发效率。
恰恰相反我们对数据库相关逻辑进行封装对外提供接口方法不仅使代码更加简洁、增加代码的可读性而且可以使我们专注于业务逻辑的开发提升开发效率。
2、封装数据库的连接/关闭操作
这里创建一个 DBUtil 类对外提供数据库连接和关闭接口注意里面使用到单例模式
package model;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;// 封装数据库的 连接/关闭 操作
public class DBUtil {// 1.创建并初始化一个数据源// 这个类中需要提供 DataSource而 DataSource 对于一个项目来说存在一个就行因此需要使用单例。private static volatile 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?characterEncodingutf8useSSLfalse);((MysqlDataSource)dataSource).setUser(root);((MysqlDataSource)dataSource).setPassword(123456);}}}return dataSource;}// 2.和数据库服务器建立连接public static Connection getConnection() throws SQLException {return getDataSource().getConnection();}// 3.释放必要的资源public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {if (resultSet ! null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement ! null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection ! null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}3、创建实体类
实体类是为了将数据库中的表结构映射到代码中方便后续进行数据的操作和管理。对于实体类的每一行数据都是对应数据库表中的一行记录。由于我们的数据库中有两张表users、blogs因此我们根据表结构分别创建 User 实体类、Blog 实体类
User 实体类
package model;
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;}
}Blog 实体类
package model;
import java.sql.Timestamp;
public class Blog {private int blogId;private String title;private String content;private Timestamp postTime;private int userId;public int getUserId() {return userId;}public void setUserId(int userId) {this.userId userId;}public int getBlogId() {return 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 Timestamp getPostTime() {return postTime;}public void setPostTime(Timestamp postTime) {this.postTime postTime;}
}4、封装必要的增删改查操作
1封装 users 表的查询操作 由于当期博客系统不涉及用户的注册、销户因此仅封装必要的查询操作即可
package model;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserDao {// 1.根据用户 id 查询用户public User selectUserById(int userId) {Connection connection null;PreparedStatement statement null;ResultSet resultSet null;try {connection DBUtil.getConnection();String sql select * from users where userId ?;statement connection.prepareStatement(sql);statement.setInt(1,userId);resultSet statement.executeQuery();if (resultSet.next()) {User user new User();user.setUserId(resultSet.getInt(userId));user.setUsername(resultSet.getString(username));user.setPassword(resultSet.getString(password));return user;}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection,statement,resultSet);}return null;}// 2.根据用户名查询哟用户public User selectUserByName(String username) {Connection connection null;PreparedStatement statement null;ResultSet resultSet null;try {connection DBUtil.getConnection();String sql select * from users where username ?;statement connection.prepareStatement(sql);statement.setString(1,username);resultSet statement.executeQuery();if (resultSet.next()) {User user new User();user.setUserId(resultSet.getInt(userId));user.setUsername(resultSet.getString(username));user.setPassword(resultSet.getString(password));return user;}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection,statement,resultSet);}return null;}
}2封装 blogs 表的增删改查操作
package model;
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 {// 1.把一个 Blog 对象插入到数据库中.public void insert(Blog blog) {Connection connection null;PreparedStatement statement null;try {connection DBUtil.getConnection();String sql insert into blogs values(null,?,?,?,?);statement connection.prepareStatement(sql);statement.setString(1, blog.getTitle());statement.setString(2, blog.getContent());statement.setTimestamp(3, blog.getPostTime());statement.setInt(4,blog.getUserId());// 执行sqlstatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection,statement,null);}}// 2.查询 blog 表中所有的博客数据.public ListBlog selectAll() {ListBlog lists new ArrayList();Connection connection null;PreparedStatement statement null;ResultSet resultSet null;try {connection DBUtil.getConnection();String sql select * from blogs order by postTime desc;statement connection.prepareStatement(sql);// 执行sqlresultSet statement.executeQuery();while (resultSet.next()) {Blog blog new Blog();blog.setBlogId(resultSet.getInt(blogId));blog.setTitle(resultSet.getString(title));blog.setContent(resultSet.getString(content));blog.setPostTime(resultSet.getTimestamp(postTime));blog.setUserId(resultSet.getInt(userId));lists.add(blog);}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection,statement,resultSet);}return lists;}// 3.指定一个博客id 来查询对应的博客public Blog selectBlogById(int blogId) {Connection connection null;PreparedStatement statement null;ResultSet resultSet null;try {connection DBUtil.getConnection();String sql select * from blogs where blogId ?;statement connection.prepareStatement(sql);statement.setInt(1,blogId);// 执行sqlresultSet 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.setPostTime(resultSet.getTimestamp(postTime));blog.setUserId(resultSet.getInt(userId));return blog;}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection,statement,resultSet);}return null;}// 4.指定 博客id 来删除博客public void deleteBlogById(int blogId) {Connection connection null;PreparedStatement statement null;try {connection DBUtil.getConnection();String sql delete from blogs where blogId ?;statement connection.prepareStatement(sql);statement.setInt(1,blogId);// 执行sqlstatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection,statement,null);}}// 5.指定博客 id 来修改博客内容public void updateBlog(int blogId,String newContent) {Connection connection null;PreparedStatement statement null;try {connection DBUtil.getConnection();String sql update blogs set content ? where id ?;statement connection.prepareStatement(sql);statement.setString(1,newContent);statement.setInt(2,blogId);// 执行sqlstatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection,statement,null);}}
}
四、前后端业务逻辑实现
1、登录功能 1约定前后端交互接口
我们约定通过 form 表单发送一个 post 请求服务端根据请求内容验证用户登录。 2编写后端代码
WebServlet(/login)
public class LoginServlet extends HttpServlet {Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1.从请求中获取用户名和密码req.setCharacterEncoding(utf8);String username req.getParameter(username);String password req.getParameter(password);if (username null || username.equals() || password null || password.equals()) {resp.setContentType(text/html;charsetutf8);resp.getWriter().write(h3缺少用户名或密码h3);return;}// 2.读取数据库检查用户名或密码是否存在UserDao userDao new UserDao();User user userDao.selectUserByName(username);if (user null) {// 用户不存在resp.setContentType(text/html;charsetutf8);resp.getWriter().write(h3用户名或密码错误h3);return;}if (!user.getPassword().equals(password)) {// 密码错误resp.setContentType(text/html;charsetutf8);resp.getWriter().write(h3用户名或密码错误h3);return;}// 3.用户登录成功设置会话HttpSession session req.getSession(true);// 把用户对象存储到 session 中了. 下次用户访问其他页面, // 就可以直接拿到会话, 进一步拿到之前的 user 对象session.setAttribute(user,user);// 4. 返回一个重定向响应, 跳转到博客列表页resp.sendRedirect(blog_list.html);}
}3编写前端代码
前端代码这里稍作修改即可将 action 路径补充完整添加 input 输入框 name 属性。
form actionlogin methodposttabletrth colspan2登 录/th/trtrtd classt1用户名/tdtdinput typetext idusername name username/td/trtrtd classt1密码/tdtdinput typepassword idpassword name password/td/trtrtd colspan2input typesubmit value提交 idsubmit/td/tr/table/form2、检查用户登录
对于一个网站来说访问网站中的任何页面通常需要是登录状态如果是未登录则跳转到登录页要求用户强制登录。
1约定前后端交互接口
我们约定当访问博客列表页、详情页、编辑页的时候、使用 AJAX 发送一个 get 请求服务端根据会话返回一个状态码在 ajax 的回调函数中判定响应状态码是否为 403如果是则使用 location.assign 进行页面跳转。 2编写后端代码
由于规定的关联路径不变我们只需要在 LoginServlet 下增加一个 doGet 方法即可
Override
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 时直接打印日志即可console.log(用户已登录!);},error:function(body) {// 返回 403 时跳转到登录页location.assign(login.html);}})
}3、博客列表 1约定前后端交互接口
我们约定浏览器给服务器发送一个 GET /blog 这样的 HTTP 请求时服务器给浏览器返回了一个 JSON 格式的数据。 2编写后端代码
WebServlet(/blog)
public class BlogServlet extends HttpServlet {private ObjectMapper objectMapper new ObjectMapper();Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {BlogDao blogDao new BlogDao();ListBlog blogs blogDao.selectAll();String respString objectMapper.writeValueAsString(blogs);resp.setContentType(application/json;charsetutf8);resp.getWriter().write(respString);}
}3编写前端代码
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 title document.createElement(h3);title.innerHTML blog.title;let dateDiv document.createElement(div);dateDiv.className date;dateDiv.innerHTML blog.postTime;let descDiv document.createElement(div);descDiv.className desc;descDiv.innerHTML blog.content;let a document.createElement(a);a.href blog_detail.html?blogIdblog.blogId;a.innerHTML 查看全文 gt;gt;;// 组合标签blogDiv.appendChild(title);blogDiv.appendChild(dateDiv);blogDiv.appendChild(descDiv);blogDiv.appendChild(a);containerRight.appendChild(blogDiv);}}})
}
// 调用方法
getBlogs();注意事项
1时间格式化 在使用 getPostTime() 获取博客发布时间时我们很可能得到一个时间戳因此需要对getPostTime 进行必要的格式化处理
public String getPostTime() {SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);return sdf.format(postTime);
}2提取文章摘要 文章的摘要通常是文章内容的一部分由于我们使用的博客编辑方式是 Markdown如果直接提取文章部分内容可能出现一些语法符号为此我们可以使用第三方库 commonmark-java将 Markdown 文本转换为纯文本
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.text.TextContentRenderer;
// markdown 纯文本转换方法
public static String convert(String markdown) {if (markdown null || markdown.isEmpty()) {return ;}// 创建 Markdown 解析器Parser parser Parser.builder().build();// 解析 Markdown 内容并生成 AST抽象语法树Node document parser.parse(markdown);// 创建纯文本渲染器并禁用生成的纯文本中的空行TextContentRenderer textRenderer TextContentRenderer.builder().stripNewlines(true).build();// 渲染 AST 并以纯文本格式输出return textRenderer.render(document);
}由于摘要只在博客列表页blog_list.html展示并且每次调用selectAll()方法所以我们可以在方法内部增加一些逻辑实现文章摘要的转换和提取操作 // ...这里省略上文String content resultSet.getString(content);// 这里简单设置一下文章的摘要将markdown文本转换为纯文本并摘取前200字符content convert(content);if (content.length() 200) {content content.substring(0,200) . . .;}// ...这里省略下文4、博客列表页用户信息
博客列表页展示的登录用户的信息。
1约定前后端交互接口
我们约定当访问博客列表页使用 AJAX 发送一个 get 请求服务端将用户信息以 Json 格式返回。 2编写后端代码
这里在 LoginServlet 的基础上做出修改如果用户是登录状态则将用户信息以 Json 格式一起返回。 Overrideprotected 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);// 密码置空防止泄漏user.setPassword();String respString objectMapper.writeValueAsString(user);resp.setContentType(application/json;charsetutf8);resp.getWriter().write(respString);}3编写前端代码
这里可以复用 getLoginStatus 方法登录成功后将用户信息显示在页面上。
function getLoginStatus() {$.ajax({type:get,url:login,success:function (body) {// 返回 200 时将用户信息显示到页面上console.log(用户已登录!);let userName document.querySelector(.card h3);userName.innerHTML body.username;},error:function(body) {// 返回 403 时跳转到登录页location.assign(login.html);}})
}5、博客详情页 1约定前后端交互接口
我们约定浏览器给服务器发送一个 GET /blog?blogIdxxx 这样的 HTTP 请求时服务器给浏览器返回了一个 JSON 格式的数据。 2编写后端代码
在获取每一篇博客的时候由于约定请求地址形如blog?blogIdxxx相比于访问博客列表页多了一个 string query但他们关联的路径都是 blog因此我们只需要在 BlogServlet 稍作调整即可
WebServlet(/blog)
public class BlogServlet extends HttpServlet {private ObjectMapper objectMapper new ObjectMapper();Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {BlogDao blogDao new BlogDao();// 获取 query stringString blogId req.getParameter(blogId);if (blogId null) {ListBlog blogs blogDao.selectAll();String respString objectMapper.writeValueAsString(blogs);resp.setContentType(application/json;charsetutf8);resp.getWriter().write(respString);} else {Blog blog blogDao.selectBlogById(Integer.parseInt(blogId));String respString objectMapper.writeValueAsString(blog);resp.setContentType(application/json;charsetutf8);resp.getWriter().write(respString);}}
}3编写前端代码
function getBlog() {$.ajax({type:get,// location.search是用于获取当前页面 URL 的查询字符串部分url:blog location.search,success: function(body) {// 设置博客的标题let h3 document.querySelector(.right h3);h3.innerHTML body.title;// 设置发布时间let dateDiv document.querySelector(.right .date);dateDiv.innerHTML body.postTime;// 设置正文. 正文内容应该是 markdown 格式的数据. // 此处要显示的应该是渲染过的 markdown 的内容, 而不是 markdown 的原始字符串. // 第一个参数, 是一个 html 元素的 id, 接下来渲染的结果会放到对应的 元素中. editormd.markdownToHTML(content, {markdown: body.content});}})}// 调用方法getBlog();6、博客详情页用户信息
博客详情页展示的当前文章的作者信息。
1约定前后端交互接口
我们约定当访问博客列表页使用 AJAX 发送一个 get 请求服务端将用户信息以 Json 格式返回。 2编写后端代码
WebServlet(/user)
public class UserServlet extends HttpServlet {private ObjectMapper objectMapper new ObjectMapper();Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取 blogIdString blogId req.getParameter(blogId);if (blogId null || blogId.equals()) {// 直接返回一个 userId 为 0 的对象,因为最终返回的是一个 json 数据.// 如果返回一个 html,前端处理就要麻烦String respJson objectMapper.writeValueAsString(new User());resp.setContentType(application/json; charsetutf8);resp.getWriter().write(respJson);System.out.println(参数给定的 blogId 为空!);return;}// 2. 查询数据库, 查询对应的 Blog 对象BlogDao blogDao new BlogDao();Blog blog blogDao.selectBlogById(Integer.parseInt(blogId));if (blog null) {// 同上String respJson objectMapper.writeValueAsString(new User());resp.setContentType(application/json; charsetutf8);resp.getWriter().write(respJson);System.out.println(参数给定的 blogId 不存在!);return;}// 3. 根据 blog 中的 userId, 查询作者信息.int userId blog.getUserId();UserDao userDao new UserDao();User user userDao.selectUserById(userId);if (user null) {// 同上String respJson objectMapper.writeValueAsString(new User());resp.setContentType(application/json; charsetutf8);resp.getWriter().write(respJson);System.out.println(该博客对应的作者不存在!);return;}// 4. 把 user 对象返回给页面user.setPassword();String respString objectMapper.writeValueAsString(user);resp.setContentType(application/json;charsetutf8);resp.getWriter().write(respString);}
}3编写前端代码
function getAuthor () {$.ajax({type:get,url:user location.search,success:function(body) {let userName document.querySelector(.card h3);userName.innerHTML body.username;}})}
// 调用方法
getAuthor();7、发布博客
在博客编辑页点击发布按钮用户编写的博客标题、正文、系统时间就可以保存到数据库中后续就可以在博客列表页和博客详情页中进行访问了。 1约定前后端交互接口
我们约定我们通过 form 表单发送一个 post 请求服务端将请求中的内容保存到数据库中。 2编写后端代码
Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding(utf8);// 1.从请求中拿到标题和正文String title req.getParameter(title);String content req.getParameter(content);if (title null || title.equals() || content null || content.equals()) {String html h3title 或者 content 为空! 新增博客失败!/h3;resp.setContentType(text/html; charsetutf8);resp.getWriter().write(html);return;}// 2.从会话中拿到作者 idHttpSession session req.getSession(false);// 因为只有登录了才能提交博客因此此时session一定不为空User user (User) session.getAttribute(user);int userId user.getUserId();// 3.构造 blog 对象Blog blog new Blog();blog.setUserId(userId);blog.setTitle(title);blog.setContent(content);blog.setPostTime(new Timestamp(System.currentTimeMillis()));// 4.将 blog 插入到数据库中BlogDao blogDao new BlogDao();blogDao.insert(blog);// 5.跳转到博客列表页resp.sendRedirect(blog_list.html);}3编写前端代码
完善 form 表单
form actionblog methodpostdiv classtitleinput typetext idtitle_input placeholder在这里写下文章标题 nametitleinput typesubmit idsubmit/divdiv ideditor!-- 放一个隐藏的textarea标签用于输入内容 --textarea namecontent styledisplay: none;/textarea/div
/form调整 editormd var editor editormd(editor, {// 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. width: 100%,// 设定编辑器高度height: calc(100% - 50px),// 编辑器中的初始内容markdown: # 在这里写下一篇博客,// 指定 editor.md 依赖的插件路径path: editor.md/lib/,saveHtmlToTextarea:true});8、注销功能
1约定前后端交互接口
我们约定浏览器通过 a 标签给服务器发送一个 GET /logout 这样的 HTTP 请求时服务端删除会话并将页面跳转到登录页。 2编写后端代码
我们这里主要通过删除 session 对象中的 user 来实现“注销”的目的在检查登录状态的逻辑中对 user 做出了判定。
WebServlet(/logout)
public class LogoutServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1.删除session中的会话信息userHttpSession session req.getSession(false);session.removeAttribute(user);// 2.跳转到登录页面resp.sendRedirect(login.html);}
}3编写前端代码
这里只需要填写一下 href 即可。
a hreflogout注销/a五、总结
本篇文章到这里就结束了为了大家更容易理解文章中展示了代码的的具体实现这也就导致整体内容有点长。最后回顾一下本篇内容本篇主要介绍了【基于Servlet的博客系统】带着大家从前期准备工作开始一步步实现了整个项目的构建希望有需要的小伙伴看完能有所收获。
最后大家需要明白当前的项目是基于 Servlet 实现的有很多地方在实现上还不够“优雅”还存在着优化和拓展的空间。那么如何让项目更“优雅”呢答案就是将项目改造为SpringBoot。那么什么又是SpringBootSpring 又是什么我们下篇文章见分晓敬请期待吧…