使用servlet,实现前后端交互,通过jdbc和mysql数据库进行数据传输,使得可以将用户信息和博客列表存储在数据库中,实现真正的服务器,客户端,数据库三者的交互
在sql数据库中建立数据库,建立用户表和博客列表
create database if not exists Lx_blog charset utf8mb4;
use Lx_blog;drop table if exists blog;
create table blog (blogId int primary key auto_increment,title varchar(1024),content mediumtext,userId int,postTime datetime
);insert into blog values(null,"这是第一篇博客", "从今天开始,我要一天写一篇博客",1,now());
insert into blog values(null,"这是第二篇博客", "从今天开始,我要一天写两篇博客",1,now());
insert into blog values(null,"这是第三篇博客", "从今天开始,我要一天写三篇博客",1,now());
insert into blog values(null,"这是第一篇博客", "从今天开始,我胡汉三要一天写一篇博客",2,now());
insert into blog values(null,"这是第一篇博客", "从昨天开始,我胡汉三要一天写两篇博客",2,now());
insert into blog values(null,"这是第三篇博客", "# 一级标题\n ### 三级标题\n > 引用内容",2,now());drop table if exists user;
create table user (userId int primary key auto_increment,username varchar(128) unique,password varchar(128)
);insert into user values(null, '123', 1234);
insert into user values(null, 'xiao', 8830);
实现jdbc的基础代码——获取DataSource的方法,获取connection的方法,close各种资源的方法
package model;import com.mysql.cj.jdbc.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 final String URL = "jdbc:mysql://127.0.0.1:3306/Lx_blog?characterEncoding=utf-8";private static final String USERNAME = "root";private static final String PASSWORD = "";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(URL);((MysqlDataSource)dataSource).setUser(USERNAME);((MysqlDataSource)dataSource).setPassword(PASSWORD);}}}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) {e.printStackTrace();}}if(statement != null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if(connection != null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}
是博客列表中每一个博客对象,里面包含博客id,标题,内容,用户id,提交时间,及一系列get和set方法
package model;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 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;}
}
用户对象,其包括用户id,用户名和密码,及一系列get和set方法
package model;public class User {private int userId = 0;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;}
}
通过调用jdbc中的一系列查询和插入方法,实现新增博客,获取所有博客,通过博客id获取单一博客的方法
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 {public void insert(Blog blog){Connection connection = null;PreparedStatement statement = null;try {connection = DBUtil.getConnection();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());statement.executeUpdate();} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection,statement,null);}}public List selectAll(){List blogs = 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("title"));String content = resultSet.getString("content");if(content.length() > 50){content = content.substring(0, 50) + "...";}blog.setContent(content);blog.setUserId(resultSet.getShort("userId"));blog.setPostTime(resultSet.getTimestamp("postTime"));blogs.add(blog);}} catch (SQLException e) {e.printStackTrace();}finally {DBUtil.close(connection,statement,resultSet);}return blogs;}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.getShort("userId"));blog.setPostTime(resultSet.getTimestamp("postTime"));return blog;}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection,statement,resultSet);}return null;}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) {e.printStackTrace();}finally {DBUtil.close(connection,statement,null);}}
}
通过jdbc中的查询和增加方法,实现通过用户名查询用户和根据用户id查询用户
package model;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class UserDao {public User selectByName(String username){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 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;}public User selectById(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 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;}
}
实现get方法,以json的数据格式返回数据,如果参数中没有blogid,则返回所有博客的信息,如果有blogid则返回对应的一篇博客
实现post方法,先通过session中数据判断是否登陆,若未登陆则强制要求登陆,再判断前端传输过来的的博客是否有题目和内容,若没有则返回,若符合规范,则调用BlogDao中的插入方法,将新的博客插入到数据库中
package controller;import com.fasterxml.jackson.databind.ObjectMapper;
import model.Blog;
import model.BlogDao;
import model.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.util.List;@WebServlet("/blog")
public class BlogServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json; charset=utf8");String param = req.getParameter("blogId");BlogDao blogDao = new BlogDao();if(param == null){//博客列表List blogs = blogDao.selectAll();String respJson = objectMapper.writeValueAsString(blogs);resp.getWriter().write(respJson);} else {//博客详情int blogId = Integer.parseInt(param);Blog blog = blogDao.selectOne(blogId);String respJson = objectMapper.writeValueAsString(blog);resp.getWriter().write(respJson);}}@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("当前用户未登陆,请登陆后提交博客");return;}User user = (User) session.getAttribute("user");if(user == null){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前用户未登陆,请登陆后提交博客");return;}req.setCharacterEncoding("utf8");String title = req.getParameter("title");String content = req.getParameter("content");if(title == null || title.equals("") || content == null || content.equals("")){resp.setContentType("text/html;charset=utf8");resp.getWriter().write("提交博客失败,缺少参数");return;}Blog blog = new Blog();blog.setTitle(title);blog.setContent(content);blog.setUserId(user.getUserId());BlogDao blogDao = new BlogDao();blogDao.insert(blog);resp.sendRedirect("blogList.html");}
}
实现get方法,先判定用户是否登陆,再判断博客中的参数是否存在,判断博客的用户id和用户的id是否一致(判断是否操作者为文章作者),全部确定为真时,调用BlogDao中的blogDelete方法,实现博客的删除功能
package controller;import model.Blog;
import model.BlogDao;
import model.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;@WebServlet("/blogDelete")
public class BlogDeleteServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession(false);if(session == null){resp.setContentType("text/html; charset=utf8");resp.getWriter().write("当前尚未登录,无法删除!!");return;}User user = (User) session.getAttribute("user");if(user == null){resp.setContentType("text/html; charset=utf8");resp.getWriter().write("当前尚未登录,无法删除!!");return;}String blogId = req.getParameter("blogId");if(blogId == null || blogId.equals("")){resp.setContentType("text/html; charset=utf8");resp.getWriter().write("当前blogId参数错误!!");return;}BlogDao blogDao = new BlogDao();Blog blog = blogDao.selectOne(Integer.parseInt(blogId));if(blog == null){resp.setContentType("text/html; charset=utf8");resp.getWriter().write("当前要删除的博客不存在!!");return;}if(user.getUserId() != blog.getUserId()){resp.setContentType("text/html; charset=utf8");resp.getWriter().write("当前登陆用户无访问权限!!");return;}blogDao.delete(Integer.parseInt(blogId));resp.sendRedirect("blogList.html");}
}
实现get方法,判断是否传输了blogid,判断blogid在数据库中是否存在,然后通过这个blogid,调用blogDao中的select方法,拿到blog对象,将密码设置为空(保护用户隐私),然后将用户信息以json格式传输给后端
package controller;import com.fasterxml.jackson.databind.ObjectMapper;
import model.Blog;
import model.BlogDao;
import model.User;
import model.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 java.io.IOException;@WebServlet("/authorInfo")
public class AuthorServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json; charset=utf8");String param = req.getParameter("blogId");if(param == null || param.equals("")){resp.getWriter().write("{\"ok\": false, \"reason \": \"参数缺失!\"}");return;}BlogDao blogDao = new BlogDao();Blog blog = blogDao.selectOne(Integer.parseInt(param));if(blog == null){resp.getWriter().write("{\"ok\": false, \"reason \": \"查询的博客不存在!\"}");return;}UserDao userDao = new UserDao();User author = userDao.selectById(blog.getUserId());if(author == null){resp.getWriter().write("{\"ok\": false, \"reason \": \"查询的用户不存在!\"}");return;}author.setPassword("");resp.getWriter().write(objectMapper.writeValueAsString(author));}
}
实现post方法,获取前端传输的用户名和密码,判断是否符合规范,用UserDao中的select方法查询用户是否存在,如果存在则用user对象构造session,最后重定向到blogList.html
实现get方法,获取sessoin,将其转换为user对象,然后将其以json数据格式传输给前端
package controller;import com.fasterxml.jackson.databind.ObjectMapper;
import model.User;
import model.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 {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf8");resp.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; charset=utf8");resp.getWriter().write("输入用户名/密码为空!!!");return;}UserDao userDao = new UserDao();User user = userDao.selectByName(username);if(user == null || !user.getPassword().equals(password)){resp.setContentType("text/html; charset=utf8");resp.getWriter().write("用户名不存在/密码错误!!!");return;}HttpSession session = req.getSession(true);session.setAttribute("user",user);resp.sendRedirect("blogList.html");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json;charset=utf8");HttpSession session = req.getSession(false);if(session == null){User user = new User();resp.getWriter().write(objectMapper.writeValueAsString(user));return;}User user = (User) session.getAttribute("user");if(user == null){user = new User();resp.getWriter().write(objectMapper.writeValueAsString(user));return;}user.setPassword("");resp.getWriter().write(objectMapper.writeValueAsString(user));}
}
实现get方法,拿到session,通过是否为空判断用户是否登陆,如果登陆了,则移除该session,然后重定向到login.html
package controller;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("/logout")
public class LogoutServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession(false);if(session == null){resp.getWriter().write("当前用户尚未登录,无法注销!");return;}session.removeAttribute("user");resp.sendRedirect("login.html");}
}
在之前的博客中有前端的代码,改动的地方如下
实现changeUserName的方法,获取页面左侧的用户名对应的h3标签,将其内容设置为当前登陆的用户的用户名
实现getUserInfo方法,参数是页名,类型是get方法,url是login,对应LoginServlet中的get方法。其功能是判断用户是否曾路,如果登陆了,就调用changeUserName方法,传输用户的名字
function getUserInfo(pageName){$.ajax({type: 'GET',url: 'login',success: function(body) {if(body.userId && body.userId > 0){console.log("登录成功! 用户名:" + body.username);if(pageName == 'blogList.html'){changeUserName(body.username);}} else {alert("当前未登陆!!!");location.assign('login.html');}},error: function(){alert("当前未登陆!!!");location.assign('login.html');}});
}function changeUserName(username){let h3 = document.querySelector('.card>h3');h3.innerHTML = username;
}
用户名,密码,提交按钮用form表单包裹,action是login,对应LoginServlet,method则是post方法,将用户名,密码增加id属性,并且将提交改成submit
将script中加入saveHTMLToTextarea: true的属性,将html中的标题,发布按钮和内容改成下面对应的格式,外面使用form表单包裹,action是blog,方法是post,对应BlogServlet中的post方法,实现博客编辑后提交给服务器,服务器传输给数据库的功能
用ajax实现getBlogDetail方法,类型为get,url为blog+location.search,对应后端的BlogServlet中的get方法,实现通过blogid获取blog对象功能,成功时将后端传输过来的blog对象中的题目,时间,内容等添加到dom树上
用ajax实现getAuthorInfo的方法,类型为get,url为authorInfo+location.search,对应AuthorServlet中的get方法,从前端获得登陆的用户信息,如果登陆的用户和文章的用户名相同,代表这个人可以删除自己的文章,在dom树上加删除的a标签,a标签中是blogDelete + location.search,对应后端的BlogDeleteServlet,实现将文章id传输给后端,后端让数据库删除该文章的操作
用ajax实现getUserInfo功能,大体功能和common.js中的getUserInfo功能大体相同,只是在其中调用getAuthorInfo方法