博客系统
- 准备工作
- servlrt依赖
- mysql依赖
- jackson依赖
- 服务器和数据库的交互
- 设计数据库/数据表
- 封装DBUtil,实现建立连接和断开连接
- 创建实体类
- blog
- user
- 编写Dao类
- BlogDao
- UserDao
- 前端和服务器的交互
- 功能一:博客列表页
- 约定格式
- 后端代码
- 前端代码
- 功能二:实现博客详情页
- 约定格式
- 后端代码
- 前端代码
- 功能三:实现登录功能
- 约定格式:
- 后端代码
- 前端代码
- 功能四:强制检查登录
- 约定格式
- 后端代码
- 前端代码
- 前端代码
- 功能五:实现显示用户信息
- 约定格式
- 博客列表页
- 博客详情页
- 后端代码
- 后端代码
- 功能六:退出登录(注销)
- 约定格式
- 后端代码
- 前端代码
- 功能七:发布博客
- 约定格式
- 后端代码
- 前端代码
这里贴一个链接,大家可以看看成品http://115.159.31.84:8080/blog_system/blog_list.html
用户名是zhangsan或者lisi,密码是123
准备工作
通过ideal创建一个maven文件 在pom.xml中引入依赖
servlrt依赖
<!-- 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>
mysql依赖
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version>
</dependency>
jackson依赖
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.2</version>
</dependency>
接下来要进行的操作,分为两个大的方面
服务器和数据库的交互
设计数据库/数据表
在main中创建一个
dp.sql
文件,在这里面编写SQL完成建库建表操作
在这里插入代码片//编写SQL完成建库建表操作
//建库
create database if not exists blog_system charset utf8;
//建表,使用一个表表示博客,另一个表表示用户
use blog_system;
drop table if exists user;
drop table if exists blog;
create table blog(blogId int primary key auto_increment,title varchar(256),content varchar(4096),userId int,postTime datetime
);
create table user(userId int primary key auto_increment,username varchar(64) unique,password varchar(64)
);
通过封装JDBC代码,来实现基础的数据库操作,因为在咱们的程序里,是需要针对blog表和user表进行一些增删查改的
首先,我们在Java这个包中再创建一个dao
包(data access object
数据访问对象),在里面写一些类,通过这些类里的方法封装了数据库,之后的数据库就是通过这样的对象来访问的
封装DBUtil,实现建立连接和断开连接
在dao包中创建一个类,通过这个类,把数据库建立连接和断开连接的逻辑进行封装
package dao;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 {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?useSSL=false&characterEncoding=utf8");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("111111");}}}return dataSource;}//提供一个方法,和数据库建立连接public static Connection getConnection(){try {return getDataSource().getConnection();} catch (SQLException e) {e.printStackTrace();}return null;}//提供一个方法,和数据库断开连接public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) throws SQLException {if (resultSet!=null){resultSet.close();}if (statement!=null){statement.close();}if (connection!=null){connection.close();}}
}
创建实体类
此处的实体类,就是要和数据库的表有对应关系,每个表都需要有一个实体类(不绝对),然后就可以使用这个类的对象来表示这个表里的一条记录了(因此,就要求这个对象的属性,能和表里的属性一一对应)
后续数据库操作是围绕实体类来展开的
同样的,我们需要在dao这个包里面创建blog类和user类
blog
package dao;
import java.sql.Timestamp;
//通过这个类的一个对象,来表示一条blog表中的记录
//这个类的属性,要和表中的列一致
public class blog {private int blogId;private String title;private String content;private int userId;//SQL里面有Timestamp类型(4个字节,2038年就不够用了),还有 datetime类型//使用SQL时,推荐使用datetimeprivate Timestamp postTime;public int getBlogId() {return blogId;}public String getTitle() {return title;}public String getContent() {return content;}public int getUserId() {return userId;}public String getPostTime() {//此处需要把时间戳转换为格式化时间//先构造一个对象,构造的时候,指定具体的格式.SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");return format.format(postTime);}public void setBlogId(int blogId) {this.blogId = blogId;}public void setTitle(String title) {this.title = title;}public void setContent(String content) {this.content = content;}public void setUserId(int userId) {this.userId = userId;}public void setPostTime(Timestamp postTime) {this.postTime = postTime;}@Overridepublic String toString() {return "blog{" +"blogId=" + blogId +", title='" + title + '\'' +", content='" + content + '\'' +", userId=" + userId +", postTime=" + postTime +'}';}
}
user
package dao;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;}@Overridepublic String toString() {return "user{" +"userId=" + userId +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
编写Dao类
通过实现Dao类,来封装对实体类(数据表)的增删查改
BlogDao
package dao;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;//通过这个类,封装对blog表的增删查改
public class BlogDao {//1.新增一个blog//调用insert的时候,需要先构造一个blog对象//作为参数,传递给insert,再由insert内部完成数据库的插入操作public void insert(blog blog) throws SQLException {Connection connection =null;PreparedStatement statement =null;try{//1.和数据库建立连接connection = DBUtil.getConnection();//2.构造一个SQL语句String sql = "insert into blog values(null,?,?,?,now())";statement = connection.prepareStatement(sql);statement.setString(1,blog.getTitle());statement.setString(2,blog.getContent());statement.setInt(3,blog.getUserId());//3.执行sql语句statement.executeUpdate();}catch (SQLException e){e.printStackTrace();} finally{//4.关闭连接,释放资源DBUtil.close(connection,statement,null);}}//2.查询blog表里的所有的博客public List<blog>getblogs() throws SQLException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet =null;List<blog>blogs = new ArrayList<>();try{//1.建立连接connection = DBUtil.getConnection();//2.构造一个SQL语句String sql = "select * from blog";statement = connection.prepareStatement(sql);//3.执行语句resultSet = statement.executeQuery();//4.遍历结果集合while(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"));blogs.add(blog);}return blogs;} catch (SQLException e) {e.printStackTrace();}finally {DBUtil.close(connection,statement,resultSet);}return null;}//3.指定blogId,查询某一个博客public blog getblog(int blogId) throws SQLException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try{//1.建立连接connection = DBUtil.getConnection();//2.构造SQL语句String sql = "select * from blog where blogId=?";statement = connection.prepareStatement(sql);statement.setInt(1,blogId);//3.执行sql语句resultSet = statement.executeQuery(sql);//4.获取blogif(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) {e.printStackTrace();}finally {DBUtil.close(connection,statement,resultSet);}return null;}//4.指定blogId进行删除public void delete(int blogId) throws SQLException {Connection connection = null;PreparedStatement statement = null;try{//1.建立连接connection = DBUtil.getConnection();//2.创建SQL语句String sql = "delete from blog where blogId=?";statement = connection.prepareStatement(sql);statement.setInt(1,blogId);//3.执行sql语句statement.executeUpdate();} catch (SQLException e) {e.printStackTrace();}finally {DBUtil.close(connection, statement, null);}}
}
UserDao
package dao;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class UserDao {//1.根据userId来查询用户信息(后续根据博客查询出作者详情)public user getuserById(int userId) throws SQLException {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 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.根据username来查询用户信息(实现登录功能)public user getuserByName(String username) throws SQLException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try{connection = DBUtil.getConnection();String sql = "select * from 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;}
}
前端和服务器的交互
接下来,就可以进行一些前后端交互的逻辑的实现了 接下来以功能点为维度进行展开
针对每个功能点,分别进行"设计前后端交互接口",“开发后端代码”,“开发前端代码”,“调试”
功能一:博客列表页
让博客列表页能够加载出博客列表内容
1.发起一个http请求,向后端索要博客列表数据
2.后端收到请求之后查询数据库获取到数据库中的博客列表,并返回给前端
3.前端拿到响应之后,就依据响应中的内容,构造出html片段,最终显示出来 在进行这三个操作之前,还需要约定好前后端交互接口,后续前端和后端要进行很多种不同的数据交互,每一种数据交互都需要发送不同的请求,返回不同的响应,此处就需要把请求和响应具体都约定好
首先创建一个名为api的包,用来存放一些前后端交互的代码,也就是一些重要的servlet,这些servlet给前端提供功能支持,也可以理解为服务器给前端提供的api(编程接口),也可以叫做Controller
约定格式
以下是一种典型的约定方式
请求:
方法: GET
路径: blog
响应: HTTP/1.1 200 OK
Content-Type:application/json json格式如下:
[{blogId:1,title:"西游记",content:"三打白骨精“,userId:1,postTime:"2023-09-25 12:00:00"}{blogId:2,title:"水浒传",content:"武松打虎“,userId:1,postTime:"2023-09-25 12:00:00"}
]
后端代码
后端要做的事,就是当收到一个上述约定的请求的时候,构造并返回一个约定的响应数据即可
在api这个包种创建一个BlogServlet
package api;import com.fasterxml.jackson.databind.ObjectMapper;
import dao.BlogDao;
import dao.blog;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.sql.SQLException;
import java.util.List;@WebServlet("/blog")
public class BlogServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//查询数据库,获取到数据后,构造成要求的json格式并返回BlogDao blogDao = new BlogDao();List<blog>blogs = null;try {blogs = blogDao.getblogs();} catch (SQLException e) {e.printStackTrace();}String respJson = objectMapper.writeValueAsString(blogs);//jackson看到blogs是一个List,就会构造出一个json数组[],针对List种的每个blog对象,分别构造出json对象//具体构造的过程,也就是根据blog的属性来的,属性的名字,就是json的key,属性的值,就是json的valueresp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);}
}
前端代码
让页面通过js ajax的方式发起一个http请求,来获取到刚才服务器这里的数据
这里需要先引入jquery的依赖:
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
创建一个script标签,在里面编写前端代码
<script>//编写js代码//构造http请求,获取到博客列表数据,并展示到页面上function getBlogs(){$.ajax({type:'get',url:'blog',success:function(body){//根据响应的内容,构造出html片段,展示到页面上//由于服务器在响应种已经设置了content-type为application/json,此时//jQuery就能够自动 的把此处响应的内容给解析成js对象数组let container = document.querySelector('.container-right');for(let blog of body){//相当于Java中的for each//根据当前这个blog来构造出一个html片段let blogDiv = document.createElement('div');blogDiv.className = 'blog';//构造标题let titleDiv = document.createElement('div');titleDiv.className = 'title';titleDiv.innerHTML = blog.title;blogDiv.appendChild(titleDiv);//构造时间let dateDiv = document.createElement('div');dateDiv.className = 'date';dateDiv.innerHTML = blog.postTime;blogDiv.appendChild(dateDiv);//构造摘要let descDiv = document.createElement('div');descDiv.className = 'desc';descDiv.innerHTML = blog.content;blogDiv.appendChild(descDiv);//构造查看全文按钮let a = document.createElement("a");a.href = "blog_detail.html?blogId="+blog.blogId;a.innerHTML = '查看全文 >>';blogDiv.appendChild(a);container.appendChild(blogDiv);}}});}getBlogs();
功能二:实现博客详情页
约定格式
请求:
方法: GET
路径: blog?query string
此处与博客列表页访问的是同一个路径,通过请求中是否携带query string来区分两个业务
响应: HTTP/1.1 200 OK
Content-Type:application/json json格式如下:
{blogId:1,title:"西游记",content:"三打白骨精“,userId:1,postTime:"2023-09-25 12:00:00"}
这里的数据格式和博客列表页返回的非常相似,这里是一条记录,博客列表则是一个数组
后端代码
package api;import com.fasterxml.jackson.databind.ObjectMapper;
import dao.Blog;
import dao.BlogDao;
import dao.User;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;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.List;@WebServlet("/blog")
public class BlogServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 查询数据库, 获取到数据之后, 构造成要求的 json 格式并返回.// 先尝试获取下 blogId 这个参数, 看看能不能获取到.BlogDao blogDao = new BlogDao();String blogId = req.getParameter("blogId");if (blogId == null) {// 此时说明是获取博客列表. 没有 blogId 参数List<Blog> blogs = null;blogs = blogDao.getBlogs();String respJson = objectMapper.writeValueAsString(blogs);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);} else {// 此时说明是获取博客详情. 有 blogId 参数.Blog blog = null;blog = blogDao.getBlog(Integer.parseInt(blogId));if (blog == null) {// 返回一个 id 为 0 的 blog 对象. 前端再根据这里进行判定.blog = new Blog();}String respJson = objectMapper.writeValueAsString(blog);resp.setContentType("application/json; charset=utf8");resp.getWriter().write(respJson);}}
}
前端代码
function getBlog() {$.ajax({url: 'blog' + location.search,type: 'get',success: function(body) {// 根据拿到的响应数据, 构造页面内容. let h3 = document.querySelector('.container-right h3');h3.innerHTML = body.title;let dateDiv = document.querySelector('.container-right .date');dateDiv.innerHTML = body.postTime;editormd.markdownToHTML('content', { markdown: body.content });}});}getBlog();
这里为了使用markdown编辑器来渲染博客,因此需要引入markdown的依赖
<link rel="stylesheet" href="editor.md/css/editormd.min.css" /><script src="editor.md/lib/marked.min.js"></script><script src="editor.md/lib/prettify.min.js"></script><script src="editor.md/editormd.js"></script>
注意:这里的markdown的依赖是建立在jQuery中引入的前提下的,因此我们需要先引入jQuery,再引入markdown
功能三:实现登录功能
约定格式:
请求:
方法: post
路径: login
Content-Type:application/x-www-form-urlencoded(使用form表单的形式提交)
username=zhangsan&password=123
响应: HTTP/1.1 200 OK
Location:blog_list_html
后端代码
package api;import dao.User;
import dao.UserDao;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 {@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 || password == null || "".equals(username) || "".equals(password)) {//提交的密码有误resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前传过来的username或者password为空");}//2.和数据库的数据进行对比,看是否匹配UserDao userDao = new UserDao();User user = userDao.getUserByName(username);if (user==null){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("您的用户名或者密码错误");return;}//当前用户名正确,看密码是否正确if (!password.equals(user.getPassword())){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("您的用户名或者密码错误");return;}//3.创建会话HttpSession session = req.getSession(true);//把当前用户的登录信息保存到session中,方便后续进行获取session.setAttribute("user",user);//4.跳转到博客列表页resp.sendRedirect("blog_list_html");}
}
前端代码
<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>
功能四:强制检查登录
如果用户在未登录的情况下,访问博客详情列/列表页/编辑页,就会自动的跳转到登录页
在博客详情列/列表页/编辑页,再发起一个get的ajax,询问服务器看当前是否已经登录
约定格式
请求:
方法: get
路径: login
响应: HTTP/1.1 200 OK(已登录)
HTTP/1.1 403 Forbidden(未登录)
后端代码
前端代码
@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//会话不存在,就是未登录HttpSession session = req.getSession(false);if (session==null){//未登录resp.setStatus(403);return;}//不仅仅是看session对象本身是否存在,还需要看user对象是否存在(为了后续实现退出登录的功能)User user = (User) session.getAttribute("user");if (user==null){resp.setStatus(403);return;}//返回200表示已登录resp.setStatus(200);}
前端代码
function checkLogin() {$.ajax({type: 'get',url: 'login',success: function(body) {},error: function(body) {location.assign('login.html');}});
}
功能五:实现显示用户信息
在当前博客列表页中,显示出当前登录的用户的个人信息,在博客详情页中,显示出这个文章的作者
让博客详情列表页和详情页分别发起ajax请求,博客列表中.就需要获取到当前登录的用户的信息
博客详情页中,就需要获取到当前文章作者的信息
约定格式
博客列表页
请求:
方法: get
路径: user
响应:
HTTP/1.1 200 OK
json格式
{
userId:1,
username:‘zhangsan’
}
博客详情页
请求:
方法: get
路径: user?blogId=
响应:
HTTP/1.1 200 OK
json格式
{
userId:1,
username:‘zhangsan’
}
后端代码
package api;import com.fasterxml.jackson.databind.ObjectMapper;
import dao.Blog;
import dao.BlogDao;
import dao.User;
import dao.UserDao;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;public class UserServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String blogId = req.getParameter("blogId");if (blogId==null){//说明是博客列表页HttpSession session = req.getSession(false);if (session==null){User user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);return;}User user = (User) session.getAttribute("user");if (user==null){user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);return;}String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);}else {//博客详情页//需要查询数据库BlogDao blogDao = new BlogDao();Blog blog = blogDao.getBlog(Integer.parseInt(blogId));if (blog==null){User user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);return;}UserDao userDao = new UserDao();User user = userDao.getUserById(blog.getUserId());if (user==null){user = new User();String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);return;}String respJson = objectMapper.writeValueAsString(user);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);}}
}
后端代码
function getUser() {$.ajax({type: 'get',url: 'user',success: function(body) {// body 就是解析后的 user 对象了. let h3 = document.querySelector('.card h3');h3.innerHTML = body.username;}})}getUser();
function getUser() {$.ajax({type: 'get',url: 'user' + location.search,success: function(body) {// body 就是解析后的 user 对象了. let h3 = document.querySelector('.card h3');h3.innerHTML = body.username;}})}getUser();
功能六:退出登录(注销)
判定登录状态逻辑中,
1.会话存在
2.会话中存储的user对象存在
两个条件同时具备,才认为用户是已经登录了
破坏上述的任何一个条件,都可以达成注销这样的效果
但是servlet中,并没有直接提供一个api来删除会话
但是有api能够删除会话中的user(attribute)
约定格式
请求:
方法: get
路径: logout
响应:
HTTP/1.1 302
location:login.html
后端代码
package api;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;public class LogoutServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession(false);if (session==null){//当前是未登录状态,谈不上注销resp.sendRedirect("login.html");return;}//之前在登录成功之后,就会给session中存储user这样的attribute//现在需要将其删除session.removeAttribute("user");resp.sendRedirect("login.html");}
}
前端代码
<a href="logout">注销</a>
通过点击a标签就能实现退出登录
功能七:发布博客
这里本质上和登录非常相似
核心都是通过form表单,把页面中用户的内容,给提交到服务器这边,服务器就可以把内容保存到数据中即可
约定格式
请求:
方法:post
路径:blog
Content-Type:application/x-www-form-urlencoded
body:title=xxxxx&content=xxxx
响应:
HTTP/1.1 302
location:blog_list.html
提交成功后,跳转到博客列表页,来到列表页之后,就能够看到刚才发布的博客了
后端代码
@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取到当前的登录用户HttpSession session = req.getSession(false);if (session==null){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("未登录");}User user = (User) session.getAttribute("user");if (user==null){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("未登录");}//获取到请求中传递过来的内容req.setCharacterEncoding("utf8");String title = req.getParameter("title");String content = req.getParameter("content");if(title==null||content==null||"".equals(title)||"".equals(content)){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("标题或正文为空");return;}//构造Blog对象,并且插入到数据库中Blog blog = new Blog();blog.setTitle(title);blog.setContent(content);blog.setUserId(user.getUserId());//由于在sql中插入数据的时候,已经使用sql自带的now获取到当前的时间,不需要此处代码中手动设置时间了
// blog.setPostTime(new Timestamp(System.currentTimeMillis()));BlogDao blogDao = new BlogDao();blogDao.insert(blog);resp.sendRedirect("blog_list.html");}
}
前端代码
<form action="blog" method="post"><!-- 标题编辑区 --><div class="title"><input type="text" id="title-input" name="title"><input type="submit" id="submit"></div><!-- 博客编辑器 --><!-- 把 md 编辑器放到这个 div 中 --><div id="editor"><textarea name="content" style="display: none;"></textarea>//此处是editor.md文档上给出的解决方案,在此处写一个隐藏的text area(多行编辑框),就可以实现form表单的提交了,在这里就可以指定name的值了</div></form>