1. 登録機能
1. フロントエンドとバックエンドのインターフェースについて合意する
2. バックエンドコードの作成
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置编码,告诉 Servlet 按照什么格式来理解请求
req.setCharacterEncoding("utf8");
//设置响应的编码,告诉 Servlet 按照什么格式来构造请求
resp.setContentType("text/html;charset=utf8");
//1、读取参数中的用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username == null || "".equals(username) || password == null || "".equals(password)){
//注册失败
String html = "<h3>注册失败!缺少 username 或者 password 字段!</h3>";
resp.getWriter().write(html);
return;
}
//2、读数据库,看看数据库中是否存在 username
UserDao userDao = new UserDao();
User user = userDao.selectByUsername(username);
if (user != null){
//用户已经存在
String html = "<h3>注册失败!该用户已经存在,请重新注册用户!";
resp.getWriter().write(html);
return;
}
//用户不存在,注册用户
userDao.add(username,password);
//注册完自动跳转到登录页面
resp.sendRedirect("login.html");
}
}
3. フロントエンドのコード作成
登録機能を追加するために、ログインページに似た登録専用のページを書き直しました。
また、ログインページに新規登録ボタンが追加され、ユーザーが登録ボタンをクリックすると、自動的に登録ページにジャンプして登録が行われます。
4. 発生した問題
登録機能を設計した後、新しいアカウントを登録してログインしたところ、そのアカウントはブログを公開していませんが、他のユーザーが公開したブログのコンテンツをクエリできることがわかったので、BlogDao Someのメソッドを使用しました。ブログ一覧ページのdoGetを修正しました
selectAll メソッドでは、すべてのブログ情報をクエリするのではなく、userId に対応するブログのみをクエリする、つまり、ログインしているユーザーが公開しているブログコンテンツをクエリするために必要な userId 情報をセッションから取得します。 2 つのアカウントによって公開されたブログを効果的に分離できます。
2. 公開記事の機能変更
1. フロントエンドとバックエンドのインターフェースについて合意する
編集ボタンをクリックして編集ページに飛ぶ場合はGETを使用します。
編集後に新しい記事を送信するには、POST を使用します。
2. バックエンドコードの作成
@WebServlet("/update")
public class updateServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
private int BlogId = 0;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 检查当前用户是否登录
resp.setContentType("application/json;charset=utf-8");
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();
BlogId = Integer.parseInt(blogId);
Blog blog = blogDao.selectById(Integer.parseInt(blogId));
if (blog == null) {
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前要修改的博客不存在!");
return;
}else{
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(objectMapper.writeValueAsString(blog));
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 检查当前用户是否登录
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf8");
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 title = req.getParameter("title");
String content = req.getParameter("content");
if(title == null || "".equals(title) || content == null || "".equals(content)){
resp.getWriter().write("<script>alert('有内容为空')</script>");
return;
}
int blogId = BlogId;
BlogDao blogDao = new BlogDao();
Blog blog = new Blog();
blog.setTitle(title);
blog.setContent(content);
blog.setBlogId(blogId);
blogDao.update(blog);
resp.sendRedirect("blog_list.html");
}
}
また、更新機能を実装するために、BlogDaoに新しい更新メソッドが追加されます
public void update(Blog blog) {
Connection connection = null;
PreparedStatement statement = null;
try {
// 1. 建立连接
connection = DBUtil.getConnection();
// 2. 拼装 SQL 语句
String sql = "update blog set content = ? ,title = ? where blogId = ?";
statement = connection.prepareStatement(sql);
statement.setString(1, blog.getContent());
statement.setString(2, blog.getTitle());
statement.setInt(3, blog.getBlogId());
// 3. 执行 SQL 语句
int ret = statement.executeUpdate();
if (ret == 1) {
System.out.println("编辑成功");
} else {
System.out.println("编辑失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(connection, statement, null);
}
}
3. フロントエンドのコード作成
記事公開のような長いページを記事編集用に書き換え、ブログ詳細ページに編集ボタンを追加しました。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客编辑页</title>
<link rel="stylesheet" href="CSS/common.css">
<link rel="stylesheet" href="CSS/blog_edit.css">
<!-- 引入 editor.md 的依赖 -->
<link rel="stylesheet" href="editor.md/css/editormd.min.css" />
<script src="js/jquery.mini.js"></script>
<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>
</head>
<body>
<!-- 这是导航栏 -->
<div class="nav">
<img src="image/logo2.png" alt="">
<span>我的博客系统</span>
<!-- 空白元素, 用来占位置 -->
<div class="spacer"></div>
<a href="blog_list.html">主页</a>
<a href="blog_edit.html">写博客</a>
<a href="logout">注销</a>
</div>
<!-- 包裹整个博客编辑页内容的顶级容器 -->
<div class="blog-edit-container">
<form action="update" method="post" style="height: 100%">
<div class="title">
<input type="text" placeholder="在此处输入标题" name="title" id="title">
<!--<button>发布文章</button>-->
<input type="submit" value="提交修改" id="submit">
</div>
<!-- 放置 md 编辑器 -->
<div id="editor">
<!-- 为了进行 form 的提交,此处搞一个 textarea 多行编辑器,借助这个编辑框来实现表单的提交 -->
<!-- 可以设置 editor.md,让编辑器把 markdown 内容也同步的保存到这个隐藏的 textarea 中,从而进行 form 提交 -->
<textarea class="content" name="content" style="display: none"></textarea>
</div>
</form>
</div>
<script>
function getEditUpdate(){
$.ajax({
type: 'get',
url: 'update' + location.search,
success: function(body){
let title = document.querySelector(".title>#title")
title.innerHTML = body.title;
let content = document.querySelector('.content')
content.innerHTML = body.content;
}
});
}
getEditUpdate();
</script>
<script>
//初始化编辑器
let editor = editormd("editor",{
//这里的尺寸必须在这里设置,设置样式会被editormd 自动覆盖掉
width: "100%",
//设定编辑器高度
height: "calc(100% - 50px)",
//编辑器中的初始内容
markdown: "# 在这里写下一篇博客",
//指定 editor.md 依赖的插件路径
path: "editor.md/lib/",
// 此处要加上一个重要的选项,然后 editor.md 就会自动把用户在编辑器输入的内容同步保存到 隐藏的 textarea 中了!
saveHTMLToTextarea: true,
});
</script>
<!-- <script src="js/common.js"></script>-->
</body>
</html>
4. 発生した問題
最初のコードを書いたとき、記事の内容を変更するために以前に記事が公開されたページを直接再利用しました。その後、これが公開機能と編集機能を混同しやすいことがわかりました。最終的に、2 つの機能ページを分離して、再-ブログ編集ページ
3. ユーザーのブログ総数の統計を実現
現在のコードでは、ブログの総数が固定されており、ユーザーのブログの総数をリアルタイムに表示することができないため、この機能を実装するインターフェースを追加します。
1. バックエンドコードを書く
@WebServlet("/num")
public class totalServlet extends HttpServlet {
@Override
protected 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;
}
//确保了登录之后
resp.setContentType("text/html;charset=utf8");
String blogId = req.getParameter("blogId");
BlogDao blogDao = new BlogDao();
if (blogId ==null){
resp.getWriter().write(blogDao.selectTotal(user.getUserId())+"");
}else{
Blog blog = blogDao.selectById(Integer.parseInt(blogId));
UserDao userDao = new UserDao();
User author = userDao.selectById(blog.getUserId());
resp.getWriter().write(blogDao.selectTotal(author.getUserId()) + "");
}
}
}
また、BlogDaoに個人記事の総数を計算する新しい方法が追加されました
//6. 计算个人文章的总数
public static Integer selectTotal(int userId){
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = DBUtil.getConnection();
String sql = "select count(userId) from blog where userId = ?";
statement = connection.prepareStatement(sql);
statement.setInt(1,userId);
resultSet = statement.executeQuery();
return resultSet.getInt(1);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
return null;
}
2. フロントエンド コードを記述します。
このコードをブログの詳細ページとブログ リスト ページの両方に追加します。
4. ブログを削除する
1. バックエンドコードを書く
BlogDao に削除メソッドを追加する
public void delete(int blogId){
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) {
throw new RuntimeException(e);
}finally {
//进行关闭
DBUtil.close(connection,statement,null);
}
}
@WebServlet("/delete")
public class DeleteServlet extends HttpServlet {
@Override
protected 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;
}
//获取 BlogId
String blogId = req.getParameter("blogId");
if (blogId == null || "".equals(blogId)){
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前 blogId 参数不对!");
return;
}
//获取要删除的博客信息
BlogDao blogDao = new BlogDao();
Blog blog = blogDao.selectById(Integer.parseInt(blogId));
if (blog == null){
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前要删除的博客不存在,blogId = " + blogId);
return;
}
//删除博客内容
blogDao.delete(Integer.parseInt(blogId));
//回到博客列表页
resp.sendRedirect("blog_list.html");
}
}
2. フロントエンドコードを書く
フロントエンドコードは以前と同じです
3. 発生した問題
コードを書いた後、ページをテストしたところ、コードは変更できても、元の記事コンテンツをエコーできないことが判明したため、フロントエンド コードを微調整してエコー機能を実装しました。
1. タイトルとコンテンツに value 属性を追加する
2. 関数内のタイトルと内容の割り当て方法を変更し、割り当てに値を使用します。
4. ブログを編集する
アイデア:
ブログ詳細ページで「ブログの編集」をクリックすると、自動的に編集ページに遷移し、同時に元のブログ内容がマークダウンエディタにエコー表示されますので、元のテキストを編集した後、再度修正を送信してください。
1. バックエンドコード
@WebServlet("/update")
public class updateServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
private int BlogId = 0;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 检查当前用户是否登录
resp.setContentType("application/json;charset=utf-8");
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();
BlogId = Integer.parseInt(blogId);
Blog blog = blogDao.selectById(Integer.parseInt(blogId));
if (blog == null) {
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("当前要修改的博客不存在!");
return;
}else{
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(objectMapper.writeValueAsString(blog));
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 检查当前用户是否登录
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf8");
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 title = req.getParameter("title");
String content = req.getParameter("content");
if(title == null || "".equals(title) || content == null || "".equals(content)){
resp.getWriter().write("<script>alert('有内容为空')</script>");
return;
}
int blogId = BlogId;
BlogDao blogDao = new BlogDao();
Blog blog = new Blog();
blog.setTitle(title);
blog.setContent(content);
blog.setBlogId(blogId);
blogDao.update(blog);
resp.sendRedirect("blog_list.html");
}
}
2. フロントエンドコード
5. 管理者によるブログのレビュー
1. バックエンドコード
@WebServlet("/admin")
public class adminServlet extends HttpServlet {
@Override
protected 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");
BlogDao blogDao = new BlogDao();
ObjectMapper objectMapper = new ObjectMapper();
if (blogId == null){
//query string 不存在,则是审核详情页列表页
List<Blog> blogs = blogDao.selectAudit();
String respJson = objectMapper.writeValueAsString(blogs);
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
}else {
//query string 存在,则是审核详情页
Blog blog = blogDao.selectById(Integer.parseInt(blogId));
String respJson = objectMapper.writeValueAsString(blog);
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//审核通过的 post 请求
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;
}
Blog blog = new Blog();
String blogId = req.getParameter("blogId");
BlogDao blogDao = new BlogDao();
blogDao.changeStatus(Integer.parseInt(blogId),1);
resp.sendRedirect("admin_list.html");
}
}
@WebServlet("/false")
public class falseServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//审核不通过的 post 请求
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;
}
Blog blog = new Blog();
String blogId = req.getParameter("blogId");
BlogDao blogDao = new BlogDao();
blogDao.changeStatus(Integer.parseInt(blogId),-1);
resp.sendRedirect("admin_list.html");
}
@Override
protected 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;
}
//确保了登录之后
resp.setContentType("text/html;charset=utf8");
String blogId = req.getParameter("blogId");
BlogDao blogDao = new BlogDao();
int num = blogDao.countSuccess();
resp.getWriter().write(num + "");
}
}
2. フロントエンドコード
フロントエンド コードは前のコードと似ていますが、ここではその一部のみを示します。
6. コメント
1. バックエンドコード
@WebServlet("/comments")
public class commentsServlet extends HttpServlet {
public int blogId;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
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;
}
CommentsDao commentsDao = new CommentsDao();
blogId = Integer.parseInt(req.getParameter("blogId"));
List<Comments> commentsList = commentsDao.selectAll(blogId);
//把 数据 转换成 json 格式
String respJson = objectMapper.writeValueAsString(commentsList);
resp.setContentType("application/json;charset=utf8");
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 content = req.getParameter("content");
if (content == null || "".equals(content)){
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前提交数据为空!");
return;
}//在博客详情页,对
//构造 comments 对象
String blogId = req.getParameter("blogId");
Comments comments = new Comments();
comments.setContent(content);
comments.setPostTime(new Timestamp(System.currentTimeMillis()));
comments.setBlogId(Integer.parseInt(blogId));
//插入数据
CommentsDao commentsDao = new CommentsDao();
commentsDao.add(comments);
//跳转到博客列表页
resp.sendRedirect("blog_list.html");
}
}
2. フロントエンドコード
ブログ詳細ページにコメントを配置するための小さなボックスが追加され、詳細ページの下部にコメント投稿機能が追加されます。
7. 統計
一般ユーザーページでは審査通過記事数と審査不合格記事数をカウントし、管理者ページでは審査対象記事数と審査成功記事数をカウントします。
統計は主にステータス列を通じて実行され、コードはここには表示されません。