当前位置: 首页 > news >正文

博客管理系统--项目说明

  • 项目体验地址(账号:123,密码:123)http://120.53.20.213:8080/blog_system/login.html

  • 项目码云Gitee地址:https://gitee.com/GoodManSS/project/tree/master/blog_system

(一)准备工作

因为是一个简单的博客系统,所以软件开发的基本流程这里我们就简要一些,主要分为 需求分析,数据库设计
  1. 需求分析

① 实现博客列表的展示功能

② 实现博客详情的展示功能

③ 登录功能

  • login登录页面

  • 注册页面

④ 限制用户权限(强制要求用户登录)

⑤ 显示用户的信息

  • 文章详情页显示信息

  • 用户能够修改个人资料,如头像,昵称,Gitee地址

⑥ 实现注销(退出账号功能)

⑦ 发布博客

⑧ 删除博客

2.数据库设计

① 博客表blog

  • blogId(Id)自增主键

  • title(文章标题)

  • content(文章内容) 类型:text 最大64k

  • postTime(发布时间)

  • userId(文章所属用户)

② 用户表user

  • useId(ID/账号)

  • passWord(登录密码)

  • userName(昵称)

  • head(头像) 这里采用保存头像路径的方式

  • Gitee地址

③ 代码

// 1.创建一个库
create database if not exists blog_system;
use blog_system;
// 2.创建blog表
drop table if exists blog;
create table blog(blogId int primary key auto_increment,title varchar(256),content text,postTime datetime,userId varchar(50)
);
// 3.创建user表
drop table if exists user;
create table user(userId varchar(50) primary key,userName varchar(50),passWord varchar(50),gitDress varchar(50),head varchar(100)
);

3.引入依赖

博客管理系统,必不可获取的有Servlet,mysql,Jackson,还有编辑页要使用到Markdown语法
<dependencies><!-- mysql的依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!-- servlet的依赖 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!-- Jackson的依赖 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.1</version></dependency>
</dependencies>

4.引入前端代码

① 在main目录下新建一个webapp文件夹。

② 把前段的代码复制粘贴到这个目录

③ 加入WEB-INF\web.xml文件内容

④ 最终目录截图

(二)写后端代码

  1. 连接数据库DBUtil

连接数据库 使用单例模式的 懒汉模式实现
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;public 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("SHANhaonan521");}}}return dataSource;}//与数据库进行连接public static Connection getConnection() throws SQLException {return getDataSource().getConnection();}//关闭连接public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {throw new RuntimeException(e);}}if (preparedStatement != null) {try {preparedStatement.close();} catch (SQLException e) {throw new RuntimeException(e);}}if (connection != null) {try {connection.close();} catch (SQLException e) {throw new RuntimeException(e);}}}}

2.Blog和User类

两个类对应数据库的两个表

① Blog类

不仅要有get set方法,还要有一个compareTo,用来对文章进行排序(按照发布时间)
import java.sql.Timestamp;
import java.text.SimpleDateFormat;public class Blog implements Comparable<Blog> {private int blogId;private String title;private String content;private Timestamp postTime;private String 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 String getPostTime() {SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm");return simpleDateFormat.format(postTime);}public void setPostTime(Timestamp postTime) {this.postTime = postTime;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}//这是一个排序方法@Overridepublic int compareTo(Blog o) {return this.getPostTime().compareTo(o.getPostTime());}
}

② User类

public class User {private String userId;private String userName;private String passWord;private String gitDress;private String head;public String getUserId() {return userId;}public void setUserId(String 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 String getHead() {return head;}public void setHead(String head) {this.head = head;}public String getGitDress() {return gitDress;}public void setGitDress(String gitDress) {this.gitDress = gitDress;}
}

③ BlogAndUserVO

在博客详情页,不仅要显示博客的相关信息,还要有一些作者的信息,加入一个VO类来实现这一功能
public class BlogAndUserVO {private int blogId;private String title;private String content;private String postTime;private String userId;private String userName;private String head;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 String getPostTime() {return postTime;}public void setPostTime(String postTime) {this.postTime = postTime;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getHead() {return head;}public void setHead(String head) {this.head = head;}
}

3.BlogDao和UserDao

BlogDao 和 UserDao主要功能就是和数据库建立连接,实现对数据库的增删查改。

① BLogDao

实现了增加博客,删除博客,查找博客,查找所有博客四个方法
    import java.sql.*;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Comparator;import java.util.List;public class BlogDao {// 1.增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.setString(3, blog.getUserId());int n = statement.executeUpdate();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm");if (n == 1) {System.out.println(simpleDateFormat.format(System.currentTimeMillis()));System.out.println("新增博客成功  title:"+blog.getTitle());} else {System.out.println(simpleDateFormat.format(System.currentTimeMillis()));System.out.println("新增博客失败");}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection, statement, null);}}// 2.删---通过主键blogId删除public void deleteOneByBlogId(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);int n = statement.executeUpdate();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm");System.out.println(simpleDateFormat.format(System.currentTimeMillis()));if (n == 1) {System.out.println("删除博客成功  blogId:"+blogId);} else {System.out.println("删除博客失败");}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection, statement, null);}}// 3.查--通过BlogId查询博客public Blog selectOneByBlogId(int blogId) {Blog blog = new Blog();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.setBlogId(resultSet.getInt("blogId"));blog.setTitle(resultSet.getString("title"));blog.setContent(resultSet.getString("content"));blog.setPostTime(Timestamp.valueOf(resultSet.getString("postTime")));blog.setUserId(resultSet.getString("userId"));}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection, statement, resultSet);}return blog;}//3. 查找所有的博客--排序好的主要是为了显示主页面public List<Blog> selectAllBlog() {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;List<Blog> list = new ArrayList<>();try {connection = DBUtil.getConnection();String sql = "select * from blog";statement = connection.prepareStatement(sql);resultSet = 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(Timestamp.valueOf(resultSet.getString("postTime")));blog.setUserId(resultSet.getString("userId"));list.add(blog);}//进行时间排序list.sort(new Comparator<Blog>() {@Overridepublic int compare(Blog o1, Blog o2) {return o1.getPostTime().compareTo(o2.getPostTime());}});} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection, statement, resultSet);}return list;}}

② UserDao

四个方法,分别是增删查改
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;public class UserDao {// 1.增public void insert(User user) {Connection connection = null;PreparedStatement statement = null;try {connection = DBUtil.getConnection();String sql = "insert into user values(?,?,?,?,?)";statement = connection.prepareStatement(sql);statement.setString(1, user.getUserId());statement.setString(2, user.getUserName());statement.setString(3, user.getPassWord());statement.setString(4, user.getHead());statement.setString(5, user.getGitDress());int n = statement.executeUpdate();if (n == 1) {System.out.println("新增数据成功!");} else {System.out.println("新增失败!");}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection, statement, null);}}// 2.删public void deleteOne(User user) {Connection connection = null;PreparedStatement statement = null;try {connection = DBUtil.getConnection();String sql = "delete from user where userId = ?";statement = connection.prepareStatement(sql);statement.setString(1, user.getUserId());int n = statement.executeUpdate();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm");System.out.println(simpleDateFormat.format(System.currentTimeMillis()));if (n == 1) {System.out.println("注销成功  user:" + user.getUserName());} else {System.out.println("注销失败");}} catch (SQLException e) {throw new RuntimeException(e);} finally {DBUtil.close(connection, statement, null);}}// 3.查--根据UserIdpublic User selectOneByUserId(String userId) {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;User user = null;try {connection = DBUtil.getConnection();String sql = "select * from user where userId = ?";statement = connection.prepareStatement(sql);statement.setString(1, userId);resultSet = statement.executeQuery();user = new User();if (resultSet.next()) {user.setUserId(resultSet.getString("userId"));user.setUserName(resultSet.getString("userName"));user.setPassWord(resultSet.getString("passWord"));user.setHead(resultSet.getString("header"));user.setGitDress(resultSet.getString("gitee"));}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection, statement, resultSet);}return user;}// 4.改--个人资料修改public void update(User user) {Connection connection = null;PreparedStatement statement = null;try {connection = DBUtil.getConnection();String sql = "update user set gitee=?,userName=? where userId=?";statement = connection.prepareStatement(sql);statement.setString(1, user.getGitDress());statement.setString(2, user.getUserName());statement.setString(3, user.getUserId());int n = statement.executeUpdate();if (n == 1) {System.out.println("update 成功");} else {System.out.println("update 失败");}} catch (SQLException e) {e.printStackTrace();} finally {DBUtil.close(connection, statement, null);}}
}

  1. Servlet类

Servlet类主要就是通过@WebServlet注解来实现前后端信息的交互,前端发送请求后,都端实现对数据库的增删查改功能

① "blog"显示/增加博客

doGet:get实现两个功能,当传入blogId的时候显示博客详情页,当没有的时候显示博客列表页。
doPost:增加一个新博客
import com.fasterxml.jackson.databind.ObjectMapper;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 ServletBlog extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json;charset=utf8");String blogId = req.getParameter("blogId");BlogDao blogDao = new BlogDao();UserDao userDao = new UserDao();ObjectMapper objectMapper = new ObjectMapper();if (blogId == null) {//返回博客列表List<Blog> list = blogDao.selectAllBlog();for (Blog blog : list) {if (blog.getContent().length() > 100) {blog.setContent(blog.getContent().substring(0, 145));}}resp.getWriter().write(objectMapper.writeValueAsString(list));} else {//返回博客详情  使用VO类//1.把 blog的内容加入到这个类中Blog blog = blogDao.selectOneByBlogId(Integer.parseInt(blogId));BlogAndUserVO blogAndUserVO = new BlogAndUserVO();blogAndUserVO.setBlogId(blog.getBlogId());blogAndUserVO.setPostTime(blog.getPostTime());blogAndUserVO.setTitle(blog.getTitle());blogAndUserVO.setContent(blog.getContent());//把user的内容加入到这个类User user = userDao.selectOneByUserId(blog.getUserId());blogAndUserVO.setUserName(user.getUserName());blogAndUserVO.setUserId(user.getUserId());blogAndUserVO.setHead(user.getHead());//返回VO类resp.getWriter().write(objectMapper.writeValueAsString(blogAndUserVO));}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf8");resp.setContentType("text/html;charset=utf8");// 1.要先检查一下用户的登录状态HttpSession session = req.getSession();if (session == null) {resp.setStatus(403);resp.getWriter().write("当前未登录");return;}User user = (User) session.getAttribute("user");if (user == null) {resp.setStatus(403);resp.getWriter().write("当前未登录");return;}// 2.获取请求的参数String title = req.getParameter("title");String content = req.getParameter("content");// 3.构造一个blog对象Blog blog = new Blog();blog.setTitle(title);blog.setContent(content);blog.setUserId(user.getUserId());// 4.插入到数据库BlogDao blogDao = new BlogDao();blogDao.insert(blog);// 5.构造重定向  返回到这个博客的详情页resp.sendRedirect("blog_list.html");}
}

② "blogDelete'删除博客

只有一个doGet方法,实现了博客的删除。没有登录或者不是自己的博客的时候是无法删除的。
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("/blog_delete")
public class ServletBlogDelete extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 先判定用户的登陆状态HttpSession session = req.getSession(false);if (session == null) {resp.setStatus(403);resp.setContentType("text/html; charset=utf8");resp.getWriter().write("您当前未登录, 不能删除!");return;}User user = (User) session.getAttribute("user");if (user == null) {resp.setStatus(403);resp.setContentType("text/html; charset=utf8");resp.getWriter().write("您当前未登录, 不能删除!");return;}// 2. 获取到 blogIdString blogId = req.getParameter("blogId");if (blogId == null) {// 这个 blogId 参数不存在, 无法删除resp.setStatus(404);resp.setContentType("text/html; charset=utf8");resp.getWriter().write("您当前删除的 blogId 有误");return;}// 3. 查询出这个 blogId 对应的 Blog 对象BlogDao blogDao = new BlogDao();Blog blog = blogDao.selectOneByBlogId(Integer.parseInt(blogId));if (blog == null) {// 这个 blogId 参数不存在, 无法删除resp.setStatus(404);resp.setContentType("text/html; charset=utf8");resp.getWriter().write("您当前删除的 博客 不存在! blogId=" + blogId);return;}// 4. 判定登陆用户是否就是文章作者if (!blog.getUserId().equals(user.getUserId())) {// blog.getUserId() 文章的作者// user.getUserId() 从 session 里拿的登陆的用户是谁.// 不一样, 说明在删别人的文章.// 直接返回 403System.out.println(user.getUserId());resp.setStatus(403);resp.setContentType("text/html; charset=utf8");resp.getWriter().write("当前您不能删除别人的博客!");return;}// 5. 真正执行删除操作.blogDao.deleteOneByBlogId(Integer.parseInt(blogId));// 6. 返回 302 重定向resp.sendRedirect("blog_list.html");}
}

③ "login"登录状态/注册

doGet:主要是获取登录状态,对应前端getLoginStatus方法
doPost:对应前端login页面,实现用户登录逻辑
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.awt.dnd.MouseDragGestureRecognizer;
import java.io.IOException;@WebServlet("/login")
public class ServletLogin extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 从请求中获取到用户名和密码req.setCharacterEncoding("utf-8");String userId = req.getParameter("userid");String passWord = req.getParameter("password");if (userId == null || userId.equals("") || passWord == null || passWord.equals("")) {// 用户名密码为空. 直接返回登陆失败resp.setContentType("text/html; charset=utf8");resp.getWriter().write("用户名或密码为空! 登陆失败!");return;}// 2. 查询数据库, 验证用户名密码是否正确UserDao userDao = new UserDao();User user = userDao.selectOneByUserId(userId);if (user == null || !user.getPassWord().equals(passWord)) {// 用户名不存在, 或者密码不相同, 返回登陆失败resp.setContentType("text/html; charset=utf8");resp.getWriter().write("用户名或密码错误! 登陆失败!");return;}// 3. 如果正确, 创建一个会话对象HttpSession session = req.getSession(true);// 在会话中保存一下 user, 以备后面使用. 后续访问其他页面, 就可以直接通过会话拿到当前是哪个用户在访问了.session.setAttribute("user", user);// 4. 构造 302 响应报文resp.sendRedirect("blog_list.html");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 使用这个方法来针对当前登陆状态进行判定// 1. 获取一下当前的会话.HttpSession session = req.getSession(false);if (session == null) {// 没有会话, 当前是未登录状态resp.setStatus(403);return;}// 这里的 user 对象是否存在, 还是要判定的.// 是否会出现, session 存在, user 不存在的情况呢? 是的!!// 当下没有这个情况, 后面写到 "退出登陆" (注销), 就会涉及到这个情况User user = (User) session.getAttribute("user");if (user == null) {// 虽然有会话, 但是里面没有 user 对象, 也认为是未登录状态resp.setStatus(403);return;}// 2. 返回 200 这样的响应即可//    不写这个代码也行. 默认状态码就是 200resp.setStatus(200);}
}

④ "logout"注销退出账号

doGet:实现了用户登录注销功能,主要就是删除浏览器的session,然后返回登录页面
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 ServletLogout extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession(false);if (session == null) {resp.setStatus(403);return;}// 直接把 session 中之前的 user 对象给删掉即可!!session.removeAttribute("user");// 不要忘记重定向到登陆页面!resp.sendRedirect("login.html");}
}

⑤ "userInfo"获取登录信息

doGet:在博客列表页 和 博客详情页,的左侧会有用户信息的展示,而获取用户信息就是通过get方法请求"userInfo"来实现的
import com.fasterxml.jackson.databind.ObjectMapper;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("/userInfo")
public class ServletUserInfo 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) {// 列表页, 获取当前登陆用户的信息// 直接从 session 中获取即可~~getUserInfoFromSession(req, resp);} else {// 详情页, 获取文章作者的信息// 查询数据库getUserInfoFromDB(req, resp, Integer.parseInt(blogId));}}private void getUserInfoFromDB(HttpServletRequest req, HttpServletResponse resp, int blogId) throws IOException {// 1. 先根据 blogId 查询 Blog 对象, 获取到 userId (作者是谁)BlogDao blogDao = new BlogDao();Blog blog = blogDao.selectOneByBlogId(blogId);if (blog == null) {// 如果参数传来的这个 blogId 是随便瞎写的. 数据库里没有.resp.setStatus(404);resp.setContentType("text/html;charset=utf8");resp.getWriter().write("blogId 不存在");return;}// 2. 根据 userId 查询对应的 User 对象即可UserDao userDao = new UserDao();User user = userDao.selectOneByUserId(blog.getUserId());if (user == null) {resp.setStatus(404);resp.setContentType("text/html;charset=utf8");resp.getWriter().write("blogId 不存在");return;}// 3. 把 user 对象返回给浏览器了user.setPassWord("");resp.setContentType("application/json;charset=utf8");resp.getWriter().write(objectMapper.writeValueAsString(user));}private void getUserInfoFromSession(HttpServletRequest req, HttpServletResponse resp) throws IOException {HttpSession session = req.getSession(false);if (session == null) {resp.setStatus(403);resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前未登录");return;}User user = (User) session.getAttribute("user");if (user == null) {resp.setStatus(403);resp.setContentType("text/html;charset=utf8");resp.getWriter().write("当前未登录");return;}// user 获取到了, 把 user 中的 password 给干掉, 然后返回.user.setPassWord("");resp.setContentType("application/json; charset=utf8");resp.getWriter().write(objectMapper.writeValueAsString(user));}
}

⑥ "userRegister"注册

实现用户的注册功能,通过接受发来的信息,然后再修改数据库内容即可
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/register")
public class ServletUserRegister extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf8");resp.setContentType("text/html;charset=utf8");// 1.获取请求的参数String userId = req.getParameter("username");String passWord = req.getParameter("password");String userName = req.getParameter("name");// 3.构造一个User对象User user = new User();user.setUserId(userId);user.setUserName(userName);user.setPassWord(passWord);// 4.插入到数据库UserDao userDao = new UserDao();userDao.insert(user);// 5.构造重定向  返回到这个博客的详情页resp.sendRedirect("login.html");}
}

⑦ "userUpdate"头像更新

实现了用户头像的上传和数据库内容更新
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.File;
import java.io.IOException;
@MultipartConfig
@WebServlet("/userUpdate")
public class ServletUserUpdate extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf8");resp.setContentType("text/html;charset=utf8");// 1.上传文件Part part = req.getPart("file");//获取HTTP头信息headerInfo=(form-data; name="file" filename="文件名")String headerInfo = part.getHeader("content-disposition");//从HTTP头信息中获取文件名fileName=(文件名)String fileName = headerInfo.substring(headerInfo.lastIndexOf("=") + 2, headerInfo.length() - 1);//获得存储上传文件的文件夹路径String fileSavingFolder = this.getServletContext().getRealPath("/head");//获得存储上传文件的完整路径(文件夹路径+文件名)//文件夹位置固定,文件夹采用与上传文件的原始名字相同String fileSavingPath = fileSavingFolder + File.separator + fileName;//如果存储上传文件的文件夹不存在,则创建文件夹File f = new File(fileSavingFolder + File.separator);if(!f.exists()){f.mkdirs();}//将上传的文件内容写入服务器文件中part.write(fileSavingPath);//2.修改用户信息HttpSession session = req.getSession(false);if (session == null) {// 没有会话, 当前是未登录状态System.out.println("session为空");resp.setStatus(403);return;}User user = (User) session.getAttribute("user");user.setHead("./head/"+fileName);//3.修改数据库内容UserDao userDao = new UserDao();userDao.update(user);//4.完成后,重定位到博客列表页resp.sendRedirect("blog_list.html");System.out.println("上传文件成功");}
}

(三)其他

文件说明:

相关文章:

博客管理系统--项目说明

项目体验地址&#xff08;账号&#xff1a;123&#xff0c;密码&#xff1a;123&#xff09;http://120.53.20.213:8080/blog_system/login.html项目码云Gitee地址&#xff1a;https://gitee.com/GoodManSS/project/tree/master/blog_system&#xff08;一&#xff09;准备工作…...

一文带你了解MySQL的Server层和引擎层是如何交互的?

对于很多开发小伙伴来说&#xff0c;每天写SQL是必不可少的一项工作。 那不知道大家有没有深入了解过&#xff0c;当我们的一条SQL命令被执行时&#xff0c;MySQL是如何把数据从硬盘/内存中查出来并展示到用户面前的呢&#xff1f; 其实&#xff0c;MySQL也没有大家想象的那么…...

CVNLP 常用数据集语料库资源汇总

​ 深度学习常用数据集汇总CVClassificationNLPSentiment AnalysisText ClassificationDialogue Generation其他AudioMulti-ModalClassificationSearch & MatchingImage CaptioningVisualQATri-Modal其他CV ghcnclimate_sphereModelNet40Shrec17 data labelcosmo Spherica…...

lisp 表达式求值规则

lisp 表达式求值规则 一个要求值的 lisp 对象被称为lisp表达式&#xff08;form&#xff09;。 lisp 表达式分三种 1. 自求值表达式。前面说过数字、字符串、向量都是自求值表达式。还有两个特殊的符号 t 和 nil 也可以看成是自求值表达式。 2. 符号表达式。符号的求值…...

Sophos Firewall OS (SFOS) 19.5 MR1 - 同步下一代防火墙

Sophos Firewall OS (SFOS) 19.5 MR1 - 同步下一代防火墙 请访问原文链接&#xff1a;https://sysin.org/blog/sfos-19-5/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org Sophos Firewall v19.5 现已推出 Sophos Firewall…...

为什么很多人转行IT考虑后端开发Java?

顺应互联网时代发展的选择 在计算机广泛运用于社会的各个角落的今天&#xff0c;选择学习一门计算机语言真的很不错&#xff0c;它会让你的生活从此与众不同。软件渗透到组织的运营和管理的后台之中&#xff0c;形成了组织运营支撑平台。这种形态是传统软件的重要应用场景。在…...

WebDAV之π-Disk派盘+Cloud Player

Cloud Player 支持WebDAV方式连接π-Disk派盘。 推荐一款云媒体播放器是存储在常见云平台中的内容的通用播放器。 Cloud Player云媒体播放器是存储在常见云平台中的内容的通用播放器,无需将其下载到设备。支持以下云平台:Google Drive、DropBox、One Drive、WebDav等。此外,…...

Python-datetime、time包常用功能汇总

目录基础知识时间格式有哪些&#xff1f;Python中的时间格式化时间戳datetimedatedatetimetimedeltatime常用获取今天凌晨字符串&#xff1f;将一个时间格式的字符串转为时间戳将一个时间戳转为指定格式的字符串全部代码参考基础知识 时间格式有哪些&#xff1f; 「格林威治标…...

Spring MVC 源码- HandlerAdapter 组件(四)之 HandlerMethodReturnValueHandler

HandlerAdapter 组件HandlerAdapter 组件&#xff0c;处理器的适配器。因为处理器 handler 的类型是 Object 类型&#xff0c;需要有一个调用者来实现 handler 是怎么被执行。Spring 中的处理器的实现多变&#xff0c;比如用户的处理器可以实现 Controller 接口或者 HttpReques…...

2023面试必备:web自动化测试POM设计模式详解

1.背景 为UI页面写自动化测试用例时&#xff08;如&#xff1a;web自动化、app自动化&#xff09;&#xff0c;使用普通的线性代码&#xff0c;测试用例中会存在大量的元素定位及操作细节&#xff0c;当UI界面变化时&#xff0c;测试用例也要跟着变化&#xff0c;在自动化测试…...

【人工智能 AI】Robotic Process Automation (RPA) 机器人流程自动化 (RPA)

目录 ROBOTIC PROCESS AUTOMATION SERVICES机器人流程自动化服务 What is RPA? 什么是机器人流程自动化?...

ubuntu/linux系统知识(37)systemd管理临时文件的方法systemd-tmpfiles

1、systemd-tmpfiles Linux产生大量的临时文件和目录&#xff0c;例如/tmp、/run 。systemd提供了一个结构化的可配置方法来管理临时文件和目录&#xff0c;即systemd-tmpfiles工具和配套的几个服务&#xff0c;以实现创建、删除和管理临时文件。 systemd创建了几个调用syste…...

云计算专业和计算机专业哪个好就业?

云计算专业其实也是属于计算机类专业呢&#xff0c;他包括了计算机硬件设备、计算机网络、磁盘柜、操作系统、中间件、数据库、服务器/虚拟机、应用软件开发等技术内容&#xff0c;云计算技术是以IT服务的形式面向用户的&#xff1b;所以云计算不是一门技术&#xff0c;而是众多…...

electron sha512 checksum mismatch

sha512 checksum mismatch错误 此错误常常发生在electron检查更新时&#xff0c;导致检查更新失败。 自动更新使用的模块 electron-updater or electron-differential-updater win下electron-builder打包 使用electron-builder打包之后&#xff0c;进行版本增量更新遇到的…...

使用Chemistry Development Kit (CDK) 来进行化学SMILES子结构匹配

摘要 SMILES是一种用于描述化合物结构的字符串表示法&#xff0c;其中子结构搜索是在大规模化合物数据库中查找特定的结构。然而&#xff0c;这种搜索方法存在一个误解&#xff0c;即将化合物的子结构视为一个独立的实体进行搜索&#xff0c;而忽略了它们在更大的化合物中的上…...

CMake模块的使用和自定义模块

CMake模块的使用和自定义模块一、前言二、使用Find模块2.1、准备工作2.2、添加头文件路径和库文件2.3、< name >_FOUND 来控制工程特性三、编写自定义的Find模块3.1、 准备工作3.2、cmake 模块3.3、使用自定义的FindHELLO 模块构建工程3.4、如果没有找到hello library四、…...

jvm调优参数配置

在JVM启动参数中&#xff0c;可以设置跟内存、垃圾回收相关的一些参数设置&#xff0c;默认情况不做任何设置JVM会工作的很好&#xff0c;但对一些配置很好的Server和具体的应用必须仔细调优才能获得最佳性能。通过设置我们希望达到一些目标&#xff1a; GC的时间足够的小 GC的…...

Leetcode.1567 乘积为正数的最长子数组长度

题目链接 Leetcode.1567 乘积为正数的最长子数组长度 Rating &#xff1a; 1710 题目描述 给你一个整数数组 nums&#xff0c;请你求出乘积为正数的最长子数组的长度。 一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。 请你返回乘积为正数的最长子数组长度…...

部分库与使用方法总结(自用)

1.tqdm tqdm是Python的进度条库&#xff0c;可以在长循环操作中显示进度提示 tqdm.tqdm:传入数字 from tqdm import tqdm for i in tqdm(range(1, 5)):print(i)使用bar_format "{l_bar}{bar}"可以只显示进度条 from tqdm import tqdm for i in tqdm(range(1, 5), ba…...

C++实现日期类

文章目录前言1.日期类的功能分析1.大致分析2.接口设计2.具体实现1.日期类的成员函数和成员变量2.初始化(构造函数&#xff09;3.对日期进行天数推算4.比较相关的运算符重载5.前置后置自增或自减6.日期相减与流插入流提取1.日期相减2.重载流插入和流提取3.总结前言 之前介绍了C…...

想成为一名专业黑客,但不知道从哪里学起?我来教你。

成为一名黑客需要学什么&#xff1f; 想成为一名专业黑客&#xff0c;但不知道从哪里学起”很多人在后台问过这个问题&#xff0c;今天就为你介绍成为专业黑客必须学习的十个方面的知识&#xff0c;希望能为迷惘中的你指明方向。 想要成为网络hacker黑客&#xff1f;先来学习…...

VMware ESXi 7.0 U3k Unlocker OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版)

ESXi 7 U3 标准版集成 Intel 网卡、USB 网卡 和 NVMe 驱动 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-7-u3-sysin/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org 本次针对 2023-02-21 发布的 ESXi …...

新的计算方法:预测益生菌在不同生长条件下的相互作用

谷禾健康 益生菌可以产生有益的维生素、消化酶、必需氨基酸、免疫调节和抗菌代谢产物&#xff0c;从而促进人体健康&#xff0c;预防肠道炎症性疾病、自身免疫性疾病和胃肠道感染。其宝贵特性已得到健康行业、医疗专业人士和公众的认可。 比起单菌株益生菌&#xff0c;多菌株益…...

python自学之《21天学通Python》(13)——第16章 数据库编程

数据库指的是以一定方式存储在一起、能为多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合。而我们平时所说的数据库实际上是包含了数据库管理系统&#xff08;DBMS&#xff09;的&#xff0c;数据库管理系统是为管理数据库而设计的软件系统&#xff0c;它一…...

[架构之路-118]-《软考-系统架构设计师》-软架构设计-11-可靠性相关设计

第11节 可靠性相关设计11.1 可靠性基本概念可靠性工程是研究产品生命周期中故障的发生、发展规律&#xff0c;达到预防故障&#xff0c;消灭故障&#xff0c;提高产品可用性的工程技术。信息系统的可靠性是指系统在满足一定条件的应用环境中能够正常工作的能力&#xff0c;可以…...

电阻串联的作用

电阻串联常见作用 第一个作用是&#xff1a;阻抗匹配&#xff1a; 因为信号源的阻抗很低&#xff0c;跟信号线之间阻抗不匹配&#xff0c;串上一个电阻后&#xff0c;可以改善匹配情况&#xff0c;以减少反射&#xff0c;避免振荡等。 常见的阻抗匹配方法 1、使用变压器来做…...

leetcode 1675. Minimize Deviation in Array(最小化数组偏差)

数组里面有n个正整数&#xff0c;里面的数字可以无限次进行如下操作&#xff1a; 1.偶数可以除以2 2.奇数可以乘以2 数组中任意两元素差的最大值称为偏差。 把数组中的元素进行上面2种操作&#xff0c;使偏差最小。 思路&#xff1a; 数组中现有2种数字&#xff0c;一种是奇数…...

特征向量中心度(eigenvector centrality)算法原理与源码解析

前言 随着图谱应用的普及&#xff0c;图深度学习技术也逐渐被越来越多的数据挖掘团队所青睐。传统机器学习主要是对独立同分布个体的统计学习&#xff0c;而图深度学习则是在此基础上扩展到了非欧式空间的图数据之上&#xff0c;通过借鉴NLP和CV方向的模型思想&#xff0c;衍生…...

Vue3 中组件的使用(上)

目录前言&#xff1a;一、什么是组件二、注册组件1. 全局注册2. 局部注册二、传递数据【父 -> 子】1. 字符串数组的形式2. 对象的形式三、组件事件【子 -> 父】1. 字符串数组式声明自定义事件2. 【子组件】触发组件事件3. 【父组件】监听子组件自定义事件4. 组件事件例子…...

spring-boot、spring-cloud、spring-cloud-alibaba版本对应

一、查询 spring-boot(spring-boot-starter-parent) 版本号 https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent 二、查询 spring-cloud(spring-cloud-dependencies) 版本号 https://mvnrepository.com/artifact/org.springframework…...