此项目是基于servlet建立的关于博客的项目,后续有转换为springboot的源码
代码编写不易,若觉得对你有所帮助,请帮我点点赞和关注。谢谢各位大佬了。
后端代码
目录
创建对象:User,Blog
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;
}
}
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 String getPostTime() {
// 使用 SimpleDateFormat 来完成时间戳到格式化日期时间的转换.
// 这个转换过程, 需要在构造方法中指定要转换的格式, 然后调用 format 来进行转换
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(postTime);
}
public void setPostTime(Timestamp postTime) {
this.postTime = postTime;
}
}
与数据库建立连接:DBUtil
public class DBUtil {
private static final String URL = "jdbc:mysql://127.0.0.1:3306/blog_system?characterEncoding=utf8&useSSL=false";
//连接数据库 blog_system是数据库中的库
private static final String USERNAME = "root";
private static final String PASSWORD = "XXXX";
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();
}
}
}
针对用户表的操作
public class UserDao {
public int insert(String username,String password){
Connection connection = null;
PreparedStatement statement = null;
int count = 0;
try {
// 1) 和数据库建立连接.
connection = DBUtil.getConnection();
// 2) 构造 SQL 语句
String sql = "insert into user values(null, ?, ?)";
statement = connection.prepareStatement(sql);
statement.setString(1,username);
statement.setString(2,password);
// 3) 执行 SQL
count = statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 4) 关闭连接, 释放资源
DBUtil.close(connection, statement, null);
}
return count;
}
// 主要实现,
// 1. 根据用户名来查找用户信息.
// 会在登录逻辑中使用~~
public User selectByName(String username) {
// 代表与数据库的链接,并拥有创建SQL语句的方法
Connection connection = null;
// 它包含的SQL语句是预编译的,所以当多次执行一条SQL语句时用它会更快
PreparedStatement statement = null;
// 包含了Statement和PreparedStatement的executeQuery方法中select的结果集
ResultSet resultSet = null;
try {
//连接数据库
connection = DBUtil.getConnection();
//建立sql语句
String sql = "select * from user where username = ?";
//预编译sql语句
statement = connection.prepareStatement(sql);
//给第一个?赋值
statement.setString(1, username);
// 结果集
resultSet = statement.executeQuery();
// 此处 username 使用 unique 约束, 要么能查到一个, 要么一个都查不到.
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 throwables) {
throwables.printStackTrace();
} finally {
DBUtil.close(connection, statement, resultSet);
}
return null;
}
// 2. 根据用户 id 来找用户信息.
// 博客详情页, 就可以根据用户 id 来查询作者的名字, 把作者名字显示出来.
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();
// 此处 username 使用 unique 约束, 要么能查到一个, 要么一个都查不到.
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 throwables) {
throwables.printStackTrace();
} finally {
DBUtil.close(connection, statement, resultSet);
}
return null;
}
}
针对博客表的操作
public class BlogDao {
// 1. 往博客表里, 插入一个博客.
public void insert(Blog blog) {
// JDBC 基本代码~~
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. 能够获取到博客表中的所有博客的信息 (用于在博客列表页, 此处每篇博客不一定会获取到完整的正文)
public List<Blog> selectAll() {
List<Blog> 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");
// 这个 50 纯属拍脑门出来的!! 这个数字具体写多少, 都可以灵活应对!!
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 throwables) {
throwables.printStackTrace();
} finally {
DBUtil.close(connection, statement, resultSet);
}
return blogs;
}
// 3. 能够根据博客 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();
// 此处我们是使用 主键 来作为查询条件的. 查询结果, 要么是 1 , 要么是 0.
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 throwables) {
throwables.printStackTrace();
} finally {
DBUtil.close(connection, statement, resultSet);
}
return null;
}
// 4. 从博客表中, 根据博客 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 throwables) {
throwables.printStackTrace();
} finally {
DBUtil.close(connection, statement, null);
}
}
// 注意, 上述操作是 增删查, 没有改~~
}
登录
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置页面静态文字
req.setCharacterEncoding("utf8");
resp.setCharacterEncoding("utf8");
// 1. 获取到请求中的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// System.out.println("username=" + username + ", password=" + password);
if (username == null || "".equals(username) || password == null || "".equals(password)) {
// 请求的内容缺失, 肯定是登录失败!!
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前的用户名或密码为空!");
return;
}
// 2. 和数据库中的内容进行比较
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;
}
// 3. 如果比较通过, 就创建会话.
HttpSession session = req.getSession(true);
// 把刚才的用户信息, 存储到会话中.
session.setAttribute("user", user);
// 4. 返回一个重定向报文, 跳转到博客列表页.
resp.sendRedirect("blog_list.html");
}
// 这个方法用来让前端检测当前的登录状态.
@Override
protected 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 对象, 也视为未登录.
user = new User();
resp.getWriter().write(objectMapper.writeValueAsString(user));
return;
}
// 已经登录的状态!!
// 注意, 此处不要把密码给返回到前端~~
user.setPassword("");
resp.getWriter().write(objectMapper.writeValueAsString(user));
}
}
注册
@WebServlet("/enroll")
public class EnrollServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username == null || "".equals(username) || password == null || "".equals(password)) {
// 请求的内容缺失, 肯定是登录失败!!
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("请输入用户名和密码");
return;
}
User user = new User();
user.setUsername(username);
user.setPassword(password);
UserDao userDao = new UserDao();
int count = userDao.insert(username,password);
if(count > 0){
// resp.getWriter().write("注册成功");
resp.sendRedirect("blog_login.html");
}else {
resp.getWriter().write("注册失败");
}
}
}
博客列表
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
// 这个方法用来获取到数据库中的博客列表.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json; charset=utf8");
BlogDao blogDao = new BlogDao();
// 先尝试获取到 req 中的 blogId 参数. 如果该参数存在, 说明是要请求博客详情
// 如果该参数不存在, 说明是要请求博客的列表.
String param = req.getParameter("blogId");
if (param == null) {
// 不存在参数, 获取博客列表
List<Blog> blogs = blogDao.selectAll();
// 把 blogs 对象转成 JSON 格式.
String respJson = objectMapper.writeValueAsString(blogs);
resp.getWriter().write(respJson);
} else {
// 存在参01数, 获取博客详情
int blogId = Integer.parseInt(param);
Blog blog = blogDao.selectOne(blogId);
String respJson = objectMapper.writeValueAsString(blog);
resp.getWriter().write(respJson);
}
}
@Override
protected 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 || "".equals(title) || content == null || "".equals(content)) {
// 直接告诉客户端, 请求参数不对
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("提交博客失败! 缺少必要的参数!");
return;
}
// 构造 Blog 对象, 把当前的信息填进去, 并插入数据库中
// 此处要给 Blog 设置的属性, 主要是 title, content, userId (作者信息)
// postTime 和 blogId 都不需要手动指定, 都是插入数据库的时候自动生成的.
Blog blog = new Blog();
blog.setTitle(title);
blog.setContent(content);
// 作者 id 就是当前提交这个博客的用户的身份信息!!
blog.setUserId(user.getUserId());
BlogDao blogDao = new BlogDao();
blogDao.insert(blog);
// 重定向到, 博客列表页!
resp.sendRedirect("blog_list.html");
}
}
博客详情页
@WebServlet("/blogDelete")
public class BlogDeleteServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 检查当前用户是否登录
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;
}
// 2. 获取到参数中的 blogId
String blogId = req.getParameter("blogId");
if (blogId == null || "".equals(blogId)) {
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前 blogId 参数不对!");
return;
}
// 3. 获取要删除的博客信息.
BlogDao blogDao = new BlogDao();
Blog blog = blogDao.selectOne(Integer.parseInt(blogId));
if (blog == null) {
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前要删除的博客不存在!");
return;
}
// 4. 再次校验, 当前的用户是否就是博客的作者
if (user.getUserId() != blog.getUserId()) {
// 这一点在前端这里其实也处理过~~ 但是此处还是再校验一次, 不是坏事!!!
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前登录的用户不是作者, 没有权限删除!");
return;
}
// 5. 确认无误, 开始删除
blogDao.delete(Integer.parseInt(blogId));
// 6. 重定向到博客列表页
resp.sendRedirect("blog_list.html");
}
}
作者信息
@WebServlet("/authorInfo")
public class AuthorServlet 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 param = req.getParameter("blogId");
if (param == null || "".equals(param)) {
// 参数缺少了.
resp.getWriter().write("{ \"ok\": false, \"reason\": \"参数缺失!\" }");
return;
}
// 根据当前 blogId 在数据库中进行查找, 找到对应的 Blog 对象, 再进一步的根据 blog 对象, 找到作者信息.
BlogDao blogDao = new BlogDao();
Blog blog = blogDao.selectOne(Integer.parseInt(param));
if (blog == null) {
resp.getWriter().write("{ \"ok\": false, \"reason\": \"要查询的博客不存在!\" }");
return;
}
// 根据 blog 对象, 查询到用户对象
UserDao userDao = new UserDao();
User author = userDao.selectById(blog.getUserId());
if (author == null) {
resp.getWriter().write("{ \"ok\": false, \"reason\": \"要查询的用户不存在!\" }");
return;
}
// 把 author 返回到浏览器这边
// 注意要把密码给干掉!
author.setPassword("");
resp.getWriter().write(objectMapper.writeValueAsString(author));
}
}
退出
@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.getWriter().write("当前用户尚未登录! 无法注销!");
return;
}
// 然后把这个用户的会话中的信息给删掉就行了!!
session.removeAttribute("user");
resp.sendRedirect("blog_login.html");
}
}
前端代码若有需要的可以私聊我。