国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

這篇具有很好參考價(jià)值的文章主要介紹了Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

1. MVC架構(gòu)模式簡(jiǎn)介

2. maven的配置和使用

3.?項(xiàng)目總述??

3.1???Controller層

3.2???Model層

3.3???View層

4. 頁(yè)面的主要功能實(shí)現(xiàn)??

4.1 ??登陸頁(yè)面(login.html)

4.2 ??博客列表頁(yè)面(blog_index.html)

4.3 ??博客詳情頁(yè)面(blog_detail.html)

4.4 ??博客編輯頁(yè)(blog_editor.html)

5.Contorller層(控制層)??

5.1 ??UserServlet

5.2 ??UserRemLoginServlet

5.3 ??UserLoginOutServlet

5.4 ??LoadAuthorInfoServlet

5.5 ??BlogServlet

5.6 ??BlogDeleteServlet

6. Model層(模型層)??

6.1 ??Bean對(duì)象

??Userbean

??BlogBean

6.2 ??BlogDao類

6.3 ??UserDao類

6.4 ??JDBC工具類

7. View層(視圖層源碼)??

7.1 ??公共樣式文件

7.1 ??登陸頁(yè)面login的實(shí)現(xiàn)

7.2 ??博客列表頁(yè)blog_index的實(shí)現(xiàn)

7.3 ??博客詳情頁(yè)blog_detail的實(shí)現(xiàn)

7.4 ??博客編輯頁(yè)面blog_editor的實(shí)現(xiàn)

8. 配置文件??

8.1 ??maven配置文件


1. MVC架構(gòu)模式簡(jiǎn)介

MVC是 Model、View、和Controller的縮寫,是軟件工程中的一種架構(gòu)模式,把軟件系統(tǒng)分為模型、視圖、控制器三部分。這三部分的作用如下:

  • Model(模型)
    使應(yīng)用程序中用于處理數(shù)據(jù)邏輯的部分,通常負(fù)責(zé)在數(shù)據(jù)庫(kù)中存取數(shù)據(jù)
  • View(視圖層)
    是應(yīng)用程序中處理數(shù)據(jù)顯示的部分,通常視圖是依據(jù)模型數(shù)據(jù)來(lái)創(chuàng)建的
  • Controller(控制器)
    是應(yīng)用程序中用于處理用戶交互的部分,通??刂破髫?fù)責(zé)從視圖讀取數(shù)據(jù),控制用戶輸入并向模型響應(yīng)數(shù)據(jù)

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

?2. maven的配置和使用

Idea內(nèi)置了maven,在我們創(chuàng)建maven項(xiàng)目后可以直接使用。下面我們主要介紹自定義maven配置。

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

?創(chuàng)建maven項(xiàng)目,導(dǎo)入依賴文件

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)


3.?項(xiàng)目總述??

博客系統(tǒng)共包含登陸頁(yè)面、博客列表頁(yè)、博客詳情頁(yè)博客編輯頁(yè)四個(gè)頁(yè)面。

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

3.1???Controller層

這個(gè)包里邊主要存放了一些Servlet小程序,對(duì)應(yīng)著用戶的指定請(qǐng)求路徑,調(diào)用Model層進(jìn)行數(shù)據(jù)的讀寫,調(diào)用View層進(jìn)行數(shù)據(jù)的展示,處理用戶特定的請(qǐng)求。

3.2???Model層

在這個(gè)包中封裝了一些bean對(duì)象和Dao(Data Access Object)類。DAO層對(duì)象負(fù)責(zé)數(shù)據(jù)的讀取和存儲(chǔ),讀取到的數(shù)據(jù)將會(huì)倍封裝成一個(gè)個(gè)bean對(duì)象。這些bean對(duì)象會(huì)返回給Controller層通過(guò)特定操作轉(zhuǎn)換為指定的格式響應(yīng)給View頁(yè)面供用戶體驗(yàn)。

3.3???View層

這個(gè)層次中主要存放了一些用戶展示數(shù)據(jù)的頁(yè)面,進(jìn)行交互的響應(yīng),向HTML,CSS,JS...

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

4. 頁(yè)面的主要功能實(shí)現(xiàn)??

4.1 ??登陸頁(yè)面(login.html)

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

實(shí)現(xiàn)的主要功能:

  • 發(fā)送ajax請(qǐng)求驗(yàn)證用戶的賬號(hào)和密碼是否正確并根據(jù)返回的數(shù)據(jù)進(jìn)行彈窗提示,如果用戶信息正確,則跳轉(zhuǎn)進(jìn)入blog_index.html頁(yè)面?
  • 當(dāng)用戶勾選了十天內(nèi)免登錄的復(fù)選框在服務(wù)器端會(huì)創(chuàng)建cookie信息添加了客戶端中,實(shí)現(xiàn)十天內(nèi)免登錄的效果

  • 點(diǎn)擊注銷按鈕,后臺(tái)清除該用戶的會(huì)話對(duì)象,前端頁(yè)面跳轉(zhuǎn)到登陸頁(yè)面,用戶即可退出登錄

4.2 ??博客列表頁(yè)面(blog_index.html)

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

?實(shí)現(xiàn)的主要功能:

  • 在進(jìn)行頁(yè)面加載時(shí)會(huì)先發(fā)送ajax請(qǐng)求驗(yàn)證用戶的登陸狀態(tài),如果用戶的身份信息不合法,則彈窗提示并跳轉(zhuǎn)到登陸頁(yè)面讓用戶進(jìn)行登錄;如果身份信息合法,則繼續(xù)向服務(wù)器請(qǐng)求博客列表信息和登錄用戶信息
  • 根據(jù)登錄用戶的不同顯示不同的用戶信息,包括文章數(shù)、用戶名、頭像信息
  • 點(diǎn)擊注銷按鈕,后臺(tái)清除該用戶的會(huì)話對(duì)象,前端頁(yè)面跳轉(zhuǎn)到登陸頁(yè)面,用戶即可退出登錄

4.3 ??博客詳情頁(yè)面(blog_detail.html)

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

實(shí)現(xiàn)的主要功能:

  • 頁(yè)面加載時(shí)驗(yàn)證用戶的登錄狀態(tài)
  • 通過(guò)注冊(cè)攜帶查詢字符串跳轉(zhuǎn)到詳情頁(yè)面攜帶的博客ID,查詢數(shù)據(jù)庫(kù),顯示當(dāng)前博客的詳細(xì)信息
  • ?當(dāng)用戶信息和當(dāng)前頁(yè)面作者信息一致時(shí),用戶點(diǎn)擊刪除按鈕可以對(duì)當(dāng)前博客進(jìn)行刪除操作
  • 對(duì)markdown語(yǔ)法進(jìn)行解析,顯示到博客詳情區(qū)域
  • 點(diǎn)擊注銷按鈕,后臺(tái)清除該用戶的會(huì)話對(duì)象,前端頁(yè)面跳轉(zhuǎn)到登陸頁(yè)面,用戶即可退出登錄

4.4 ??博客編輯頁(yè)(blog_editor.html)

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

實(shí)現(xiàn)的主要功能:

  • 驗(yàn)證用戶身份信息的合法性
  • 引用開(kāi)源插件editor.md實(shí)現(xiàn)博客的markdown語(yǔ)法編輯功能
  • 用戶提交博客信息,跳轉(zhuǎn)博客列表頁(yè)面
  • 點(diǎn)擊注銷按鈕,后臺(tái)清除該用戶的會(huì)話對(duì)象,前端頁(yè)面跳轉(zhuǎn)到登陸頁(yè)面,用戶即可退出登錄

5.Contorller層(控制層)??

5.1 ??UserServlet

? ? ? 該后臺(tái)小程序用戶處理用戶的普通登錄請(qǐng)求和驗(yàn)證用戶身份信息的合法性。其中的doPost方法接受來(lái)自login.html中登錄的ajax——Post請(qǐng)求,這個(gè)登錄的HTTP請(qǐng)求將用戶的登錄信息攜帶在請(qǐng)求體發(fā)送給服務(wù)器,服務(wù)器中的UserServlet對(duì)其中的登陸數(shù)據(jù)進(jìn)行解析并根據(jù)用戶是否選擇一定時(shí)期內(nèi)免登錄選擇性創(chuàng)建cookie對(duì)象返回給客戶端;并且調(diào)用Model層的UserDao對(duì)象查詢底層數(shù)據(jù)路判斷是否有該用戶的信息,如果用戶身份信息合法,則創(chuàng)建該用戶的session會(huì)話對(duì)象,將該用戶的信息添加用戶本次的會(huì)話域當(dāng)中并在查詢結(jié)束后返回一個(gè)字符串格式的登錄判定結(jié)果,前端負(fù)責(zé)登錄的ajax請(qǐng)求在接收到這個(gè)登陸結(jié)果后進(jìn)行彈窗提示和頁(yè)面跳轉(zhuǎn)。其中的doGet方法用于處理前端頁(yè)面驗(yàn)證用戶身份信息合法性的ajax請(qǐng)求,當(dāng)前端發(fā)送這個(gè)請(qǐng)求時(shí),后端的UserServlet試圖獲取該用戶對(duì)應(yīng)的session會(huì)話對(duì)象,如果獲取成功,則說(shuō)明用戶身份信息合法;如果因非法登錄和session過(guò)期等原因?qū)е碌挠脩羯矸菪畔⑹?,則會(huì)返回一個(gè)JSON格式的對(duì)象,前端頁(yè)面解析這個(gè)JSON對(duì)象并且在用戶身份信息不合法時(shí)給出彈窗提示并強(qiáng)制頁(yè)面跳轉(zhuǎn)到登陸頁(yè)面;在身份信息合法時(shí)將用戶信息加載到頁(yè)面左側(cè)的用戶信息上。其中返回的JSON格式的數(shù)據(jù)前后端約定如下:

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

package com.shuai.blogapp.controller.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.shuai.blogapp.model.bean.User;
import com.shuai.blogapp.model.dao.BlogDao;
import com.shuai.blogapp.model.dao.UserDao;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet({"/user/loginIn", "/user/verify"})
public class UserServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String remember = request.getParameter("remember");
        if (username == null || password == null || "".equals(username) || "".equals(password)) {
            response.getWriter().write("empty");
            return;
        }
        //檢查用戶名和密碼是否正確
        UserDao userDao = new UserDao();
        User user = userDao.selectByName(username);
        if (user == null || !password.equals(user.getPassword())) {
            response.getWriter().print("error");
            return;
        }
        //登陸成功了
        //創(chuàng)建和該用戶關(guān)聯(lián)的session信息
        HttpSession session = request.getSession(true);
        session.setMaxInactiveInterval(60 * 60 * 12);
        Cookie usernameCookie = new Cookie("username", username);
        Cookie passwordCookie = new Cookie("password",password);
        usernameCookie.setMaxAge(60*60*24*10);
        passwordCookie.setMaxAge(60*60*24*10);
        //將cookie信息保存在客戶端
        response.addCookie(usernameCookie);
        response.addCookie(passwordCookie);
        session.setAttribute("user", user);
        response.getWriter().print("success");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession(false);    //獲取該用戶綁定的session信息
        response.setContentType("application/json;charset=utf8");
        User user = new User();
        if (session == null || session.getAttribute("user") == null) {
            user.setUsername("");
            user.setPassword("");
            response.getWriter().print(objectMapper.writeValueAsString(user));
            return;
        }
        user = (User) session.getAttribute("user");
        user.setPassword("");   //用戶密碼就不要返回給前端了
        long blogNum = new BlogDao().getBlogNumByUserId(user.getUserId());
        user.setBlogNum(blogNum);
        response.getWriter().write(objectMapper.writeValueAsString(user));  //用戶信息存在,就返回這個(gè)用戶信息
    }
}

5.2 ??UserRemLoginServlet

該小程序用于處理用戶的記憶登錄功能,在登陸頁(yè)面加載時(shí)會(huì)先發(fā)送一個(gè)記憶登錄的ajax請(qǐng)求,如果之前用戶選擇了一定時(shí)期內(nèi)免登錄的這個(gè)按鈕,則這次的請(qǐng)求會(huì)攜帶之前服務(wù)器返回的用戶信息的cookie。后臺(tái)的UserRemLoginServlet嘗試獲取這些cookie對(duì)象并解析出包含用戶信息的cookie,并將創(chuàng)建UserDao對(duì)象從數(shù)據(jù)庫(kù)查詢?cè)撚脩粜畔?,返回用戶記憶登錄的結(jié)果,前后端之間的約定如下:

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

package com.shuai.blogapp.controller.servlet;

import com.shuai.blogapp.model.bean.User;
import com.shuai.blogapp.model.dao.UserDao;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet({"/user/remLogin"})
public class UserRemLoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Cookie[] cookies = request.getCookies();
        response.setContentType("application/json;charset=utf8"); //以json的形式返回?cái)?shù)據(jù)
        String username = null;
        String password = null;
        //遍歷cookie信息,尋找用戶保存的用戶名和密碼
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("username".equals(cookie.getName())) {
                    username = cookie.getValue();
                }
                if ("password".equals(cookie.getName())) {
                    password = cookie.getValue();
                }
            }
        }
        //如果username或者password為空,說(shuō)明沒(méi)有保存用戶登錄信息的cookie
        if (username == null || password == null) {
            response.getWriter().write("{\"ok\":\"0\"}");
            return;
        }
        //如果有用戶名和密碼,就連接數(shù)據(jù)庫(kù)驗(yàn)證這個(gè)用戶信息是否正確
        UserDao userDao = new UserDao();
        User user = userDao.selectByName(username);
        if (user == null || !password.equals(user.getPassword())) {
            //說(shuō)明cookie中保存的用戶信息不正確
            response.getWriter().write("{\"ok\":\"0\"}");
            return;
        }

        //用戶信息正確
        //創(chuàng)建包含用戶信息的session
        HttpSession session = request.getSession(true);
        session.setAttribute("user", user);
        //響應(yīng)登錄成功的結(jié)果給前端
        response.getWriter().write("{\"ok\":\"1\"}");
    }
}

5.3 ??UserLoginOutServlet

該后臺(tái)小程序接收用戶點(diǎn)擊注銷按鈕時(shí)通過(guò)超鏈接發(fā)送的GET請(qǐng)求,當(dāng)接收到請(qǐng)求后,會(huì)創(chuàng)建包含用戶登錄信息的同名cookie對(duì)象,并設(shè)置cookie對(duì)象的生命周期為0,將這些cookie添加到客戶端更新原來(lái)的包含用戶信息的cookie(即使得原來(lái)包含用戶登錄信息的cookie信息失效)。并且會(huì)從request對(duì)象中獲取到該用戶對(duì)應(yīng)的session對(duì)象,并將會(huì)話域中的用戶信息刪除并使當(dāng)前用戶的session對(duì)象失效。然后重定向到登陸頁(yè)面。頁(yè)面得處理邏輯如下:

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

package com.shuai.blogapp.controller.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet({"/user/loginOut"})
public class UserLoginOutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.removeAttribute("user");
            Cookie usernameCookie = new Cookie("username", "");
            Cookie passwordCookie = new Cookie("password", "");
            usernameCookie.setMaxAge(0);
            passwordCookie.setMaxAge(0);
            response.addCookie(usernameCookie);
            response.addCookie(passwordCookie);
            session.invalidate();   //使該session對(duì)象失效
        }
        response.sendRedirect(request.getContextPath()+"/login.html");
    }
}

5.4 ??LoadAuthorInfoServlet

該Servlet用于在博客詳情頁(yè)面加載用戶的詳細(xì)信息,包括用戶名、文章數(shù),頭像。當(dāng)用戶在博客列表頁(yè)點(diǎn)擊查看全文時(shí)會(huì)在查詢字符串里攜帶待查尋博客的id跳轉(zhuǎn)到詳情頁(yè)面,在詳情頁(yè)面加載時(shí)還是會(huì)先發(fā)送驗(yàn)證用戶身份信息的ajax請(qǐng)求。通過(guò)后,將該當(dāng)前頁(yè)面URL中的blogId取出,攜帶這個(gè)參數(shù)發(fā)送請(qǐng)求到該Servlet,該小程序創(chuàng)建BlogDao對(duì)象查詢改編號(hào)對(duì)應(yīng)的blog是否存在,如果存在,則再根據(jù)查詢到博客的作者信息去查詢作者表中該作者的信息,并將查詢結(jié)果響應(yīng)給前端;如果不存在,則直接響應(yīng)。該接口前后端之間的約定和響應(yīng)流程如下:

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

package com.shuai.blogapp.controller.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.shuai.blogapp.model.bean.Blog;
import com.shuai.blogapp.model.bean.User;
import com.shuai.blogapp.model.dao.BlogDao;
import com.shuai.blogapp.model.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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet({"/author/authorInfo"})
public class LoadAuthorInfoServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("application/json,charset=UTF-8");
        PrintWriter out = response.getWriter();
        String blogId = request.getParameter("blogId");
        //從數(shù)據(jù)庫(kù)查詢這篇博客的詳細(xì)信息,返回這篇博客的作者編號(hào)
        BlogDao blogDao = new BlogDao();
        Blog blog = blogDao.queryBlogById(Integer.parseInt(blogId));
        User user = new User();
        if(blog == null) {
            user.setUserId(-1);
            out.write(objectMapper.writeValueAsString(user));
            return;
        }
        UserDao userDao = new UserDao();
        user = userDao.selectById(blog.getUserId());
        if(user == null) {
            User user1 = new User();
            user1.setUserId(0);
            out.write(objectMapper.writeValueAsString(user1));
            return;
        }
        user.setPassword("");
        //顯示該用戶的博客數(shù)量
        long blogNum = blogDao.getBlogNumByUserId(user.getUserId());
        user.setBlogNum(blogNum);
        out.write(objectMapper.writeValueAsString(user));
    }
}

5.5 ??BlogServlet

該小程序主要用于處理請(qǐng)求博客列表、加載博客詳情內(nèi)容以及進(jìn)行博客的保存。其中,不論前端發(fā)送何種請(qǐng)求,都是先驗(yàn)證用戶身份信息的合法性。通過(guò)驗(yàn)證后,當(dāng)前端發(fā)送博客列表請(qǐng)求時(shí),該Servlet中的doGet方法會(huì)從blog表中查詢所有的blog信息,并對(duì)每一篇長(zhǎng)度大于50的blog進(jìn)行截取加工(優(yōu)化前端頁(yè)面博客列表的博客概要的顯示)。將查詢并加工后的所有博客信息響應(yīng)給前端。該請(qǐng)求和響應(yīng)接口的數(shù)據(jù)約定如下:

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

?當(dāng)前端發(fā)送博客詳情請(qǐng)求時(shí),該Servlet根據(jù)前端發(fā)送過(guò)來(lái)的blogId船艦BlogDao對(duì)象查詢數(shù)據(jù)庫(kù)并返回該blogId對(duì)應(yīng)的博客全文。

?當(dāng)前端發(fā)送博客提交請(qǐng)求時(shí),該Servlet的doPsot方法執(zhí)行,在進(jìn)行一系列用戶以及用戶博客信息的合法性驗(yàn)證后將該篇博客插入到底層數(shù)據(jù)庫(kù),其中該篇博客的用戶編號(hào)從該用戶的會(huì)話域中獲取即可。

package com.shuai.blogapp.controller.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.shuai.blogapp.model.bean.Blog;
import com.shuai.blogapp.model.bean.User;
import com.shuai.blogapp.model.dao.BlogDao;

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(value = {"/blog/list","/blog/detail","/blog/save"})
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("application/json;charset=UTF-8");
        String servletPath = request.getServletPath();
        BlogDao blogDao = new BlogDao();
        String responseJson = null;
        if("/blog/list".equals(servletPath)) {
            List<Blog> blogs = blogDao.queryAll();
            for (Blog blog : blogs) {
                String content = blog.getContent();
                if (content.length() > 100) {
                    blog.setContent(content.substring(0, 100) + "...");
                }
            }
            responseJson = objectMapper.writeValueAsString(blogs);
        } else if("/blog/detail".equals(servletPath)) {
            String blogId = request.getParameter("blogId");
            int id = Integer.parseInt(blogId);
            Blog blog = blogDao.queryBlogById(id);
            responseJson = objectMapper.writeValueAsString(blog);
        }
        response.getWriter().write(responseJson);

    }


    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf8");
        HttpSession session = request.getSession(false);
        //這里要優(yōu)化。萬(wàn)一用戶編輯博客時(shí)間長(zhǎng),session過(guò)期,就會(huì)市區(qū)編輯的博客的內(nèi)容了
        if(session == null) {
            //重定向到登錄頁(yè)面
            response.sendRedirect(request.getContextPath()+"/login.html");
            return;
        }
        User user = (User)session.getAttribute("user");
        if(user == null) {
            //重定向到登錄頁(yè)面
            response.sendRedirect(request.getContextPath()+"/login.html");
            return;
        }
        //保存客戶端發(fā)送過(guò)來(lái)的內(nèi)容
        String title = request.getParameter("title");
        String content = request.getParameter("content");
        int userId = user.getUserId();  //獲取編輯這篇博客的作者編號(hào)
        BlogDao blogDao = new BlogDao();
        Blog blog = new Blog();
        blog.setContent(content);
        blog.setUserId(userId);
        blog.setTitle(title);
        blogDao.insertBlog(blog);
        //保存成功后跳轉(zhuǎn)到博客列表頁(yè)面
        response.sendRedirect(request.getContextPath() + "/blog_index.html");
    }
}

5.6 ??BlogDeleteServlet

根據(jù)前端頁(yè)面發(fā)送過(guò)來(lái)的blogId,該Servlet創(chuàng)建BlogDao對(duì)象從blog表中將該篇blog刪除,相應(yīng)刪除結(jié)果然后跳轉(zhuǎn)到博客列表頁(yè)。該接口的響應(yīng)數(shù)據(jù)約定如下:

Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)

package com.shuai.blogapp.controller.servlet;


import com.shuai.blogapp.model.bean.Blog;
import com.shuai.blogapp.model.bean.User;
import com.shuai.blogapp.model.dao.BlogDao;

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 BlogDeleteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf8");
        String blogId = request.getParameter("blogId");
        HttpSession session = request.getSession(false);    //驗(yàn)證用戶登陸狀態(tài)
        if (session == null) {
            response.getWriter().print("login_out_of_date");
            return;
        }
        User user = (User) session.getAttribute("user");
        if (user == null) {
            response.getWriter().print("login_out_of_date");
            return;
        }
        BlogDao blogDao = new BlogDao();
        Blog blog = blogDao.queryBlogById(Integer.parseInt(blogId));
        if(blog == null) {
            response.getWriter().print("blog_not_exists");
            return;
        }
        if(user.getUserId() != blog.getUserId()) {
            response.getWriter().print("user_info_mismatching");
            return;
        }
        //到這里,初步確定信息無(wú)誤,進(jìn)行刪除
        Blog blog1 = blogDao.deleteBlog(blog.getBlogId());
        if(blog1 != null) {
            response.getWriter().print("delete_success");
        } else {
            response.getWriter().print("delete_fault");
        }

    }
}

6. Model層(模型層)??

6.1 ??Bean對(duì)象

??Userbean

對(duì)應(yīng)數(shù)據(jù)庫(kù)中的user表,作為載體封裝了user表中每一條博客的信息存在,并且提供了相應(yīng)的屬性的getter和setter方法。

package com.shuai.blogapp.model.bean;

public class User {
    private int userId;


    private String username;
    private String password;
    private long blogNum;

    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 long getBlogNum() {
        return blogNum;
    }

    public void setBlogNum(long blogNum) {
        this.blogNum = blogNum;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

??BlogBean

對(duì)應(yīng)數(shù)據(jù)庫(kù)中的blog表,作為載體封裝了blog表中每一條博客的信息存在,并且提供了相應(yīng)的屬性的getter和setter方法。

package com.shuai.blogapp.model.bean;

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 void setPostTime(Timestamp postTime) {
        this.postTime = postTime;
    }

    /**
     * 重寫postTime的get方法,來(lái)做格式化輸出
     */
    public String getPostTime() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(postTime);
    }

    @Override
    public String toString() {
        return "Blog{" +
                "blogId=" + blogId +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", userId=" + userId +
                ", postTime=" + postTime +
                '}';
    }
}

6.2 ??BlogDao類

該類作為博客的數(shù)據(jù)邏輯處理類,對(duì)插入博客、刪除博客、查詢博客(根據(jù)blogId查詢單個(gè)以及查詢?nèi)浚┖瞳@取指定用戶對(duì)應(yīng)博客數(shù)目的方法進(jìn)行了封裝供controller層Servlet調(diào)用處理數(shù)據(jù)。

package com.shuai.blogapp.model.dao;

import com.shuai.blogapp.model.bean.Blog;
import com.shuai.blogapp.model.bean.User;
import com.shuai.utils.BaseDaoUtil;

import java.sql.SQLException;
import java.util.List;

/**
 * Date Access Object which handle the request of blog from user
 */
public class BlogDao {
    /**
     * The method which insert the blog which was written by user
     * @param blog
     */
    public void insertBlog(Blog blog) {
        if(blog == null) {
            return;
        }
        String sql = "insert into blog(title,content,userId,postTime) values(?,?,?,now())";
        try {
            BaseDaoUtil.executeUpdate(sql,blog.getTitle(),blog.getContent(),blog.getUserId());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * The method which is used to delete the blog by blogId and return the blog object which is deleted
     * @param id
     * @return The blg object which is deleted
     */
    public Blog deleteBlog(int id) {
        List<Blog> blogs = null;
        Blog res = null;
        String sqlQuery = "select blogId,title,content,userId,postTime from blog where blogId=?";
        try {
            blogs = BaseDaoUtil.executeQuery(Blog.class,sqlQuery,id);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        if((res = blogs.get(0)) == null) {
            return null;
        }
        String sqlDelete = "delete from blog where blogId=?";
        try {
            BaseDaoUtil.executeUpdate(sqlDelete,id);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        if(blogs.get(0) != null) {
            return blogs.get(0);
        }
        return res;
    }

    /**
     * User can through this method to query the blog by blogId
     * @param id a count which deputy a blog
     * @return return an object which is queried by user
     */
    public Blog queryBlogById(int id) {
        List<Blog> blogs = null;
        String sql = "select blogId,title,content,userId,postTime from blog where blogId=?";
        try {
            blogs = BaseDaoUtil.executeQuery(Blog.class, sql, id);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        if((blogs.size()>0)) {
            return blogs.get(0);
        }
        return null;
    }

    public List<Blog> queryAll() {
        String sql = "select blogId,title,content,userId,postTime from blog order by postTime desc" ;
        List<Blog> blogs = null;
        try {
            blogs = BaseDaoUtil.executeQuery(Blog.class,sql);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        return blogs;
    }

    public long getBlogNumByUserId(int userId) {
        String sql = "select count(*) as blogNum from blog where userId=?";
        List<User> users = null;
        try {
            users = BaseDaoUtil.executeQuery(User.class, sql, userId);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        return users.get(0).getBlogNum();
    }
}

6.3 ??UserDao類

該類作為User數(shù)據(jù)的邏輯處理類,對(duì)向數(shù)據(jù)庫(kù)中添加用戶、刪除用戶、查詢用戶(重載方法)的功能進(jìn)行了封裝,供controller層調(diào)用。

package com.shuai.blogapp.model.dao;

import com.shuai.blogapp.model.bean.User;
import com.shuai.utils.BaseDaoUtil;

import java.sql.SQLException;
import java.util.List;

/**
 * The method which counters the service for users
 */
public class UserDao{
    /**
     * The method which is used to add user
     * @param user
     */
    public void addUser(User user) {
        if(user == null) {
            return;
        }
        String sql = "insert into user(username,password) values(?,?);";
        try {
            BaseDaoUtil.executeUpdate(sql,user.getUsername(),user.getPassword());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * The method which is used to delete user from user table by userId
     * @param user
     * @return The user object which is deleted
     */
    public User deleteUser(User user) {
        if(user == null) {
            return null;
        }
        List<User> users = null;
        User res = null;
        String sqlQuery = "select userId,username,password from user where userId=?;";
        try {
            users = BaseDaoUtil.executeQuery(User.class,sqlQuery,user.getUserId());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }

        if(users.size() == 0) {
            return null;
        }
        String sqlDelete = "delete from user where userId=?;";
        try {
            BaseDaoUtil.executeUpdate(sqlDelete,user.getUserId());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return users.get(0);
    }

    public User selectByName(String username) {
        List<User> users = null;
        String sql = "select userId,username,password from user where username=?";
        try {
            users = BaseDaoUtil.executeQuery(User.class,sql,username);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        if(users.size()>0) {
            return users.get(0);
        }
        return null;
    }

    public User selectById(int id) {
        List<User> users = null;
        String sql = "select userId,username,password from user where userId=?";
        try {
            users = BaseDaoUtil.executeQuery(User.class,sql,id);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        if(users.size()> 0) {
            return users.get(0);
        }
        return null;
    }

}

6.4 ??JDBC工具類

我對(duì)于mysql連接的獲取和數(shù)據(jù)的增刪改查基于JDBC原生操作封裝了兩個(gè)工具類。其中的JDBCUtil提供了獲取連接和回收連接的方法;BaseDaoUtil提供了對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)進(jìn)行增刪改查操作的封裝。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-445515.html

//JDBCUtil.java
package com.shuai.utils;


import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class JDBCUtil {
    private static DataSource dataSource;
    private static ThreadLocal<Connection> th = new ThreadLocal<>();
    static {
        Properties properties = new Properties();
        InputStream inputStream = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try {
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public static Connection getConnection() throws SQLException {
        Connection connection = th.get();
        if(connection == null) {
            synchronized (JDBCUtil.class) {
                connection = dataSource.getConnection();
                th.set(connection);
            }
        }
        return connection;
    }


    public static void close() throws SQLException {
        Connection connection = th.get();
        if(connection != null) {
            connection.setAutoCommit(true);
            connection.close();
            th.remove();
        }
    }
}
//BaseDaoUtil.java
package com.shuai.utils;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class BaseDaoUtil {
    /**
     * The method which package the operation to delete,update or insert the blog
     *
     * @param sql
     * @param param
     * @return
     */
    public static int executeUpdate(String sql, Object... param) throws SQLException {
        Connection connection = JDBCUtil.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        if (param != null) {
            //設(shè)置sql語(yǔ)句中的參數(shù)
            for (int i = 0; i < param.length; i++) {
                preparedStatement.setObject(i + 1, param[i]);
            }
        }
        int i = preparedStatement.executeUpdate();
        if(preparedStatement != null) {
            preparedStatement.close();
        }
        if(connection.getAutoCommit()) {    //如果沒(méi)有開(kāi)啟事務(wù),就關(guān)閉連接。否則讓服務(wù)層關(guān)閉
            JDBCUtil.close();
        }
        return i;
    }


    public static <T> List<T> executeQuery(Class<T> clazz, String sql, Object... param) throws SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Connection connection = JDBCUtil.getConnection();
        List<T> beans = new ArrayList<>();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        if (param != null) {
            for (int i = 0; i < param.length; i++) {
                preparedStatement.setObject(i + 1, param[i]);
            }
        }
        ResultSet resultSet = preparedStatement.executeQuery();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        while (resultSet.next()) {
            //通過(guò)反射創(chuàng)建對(duì)象實(shí)例
            T t = clazz.newInstance();
            for (int i = 0; i < columnCount; i++) {
                Object object = resultSet.getObject(i + 1);
                Field declaredField = clazz.getDeclaredField(metaData.getColumnLabel(i + 1));
                declaredField.setAccessible(true);
                declaredField.set(t, object);
            }
            beans.add(t);
        }
        if(resultSet != null) {
            resultSet.close();
        }
        if(preparedStatement != null) {
            preparedStatement.close();
        }
        if(connection.getAutoCommit()) {
            JDBCUtil.close();
        }
        return beans;
    }
}

7. View層(視圖層源碼)??

7.1 ??公共樣式文件

<!-- commom.css -->
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html,
body {
    width: 100%;
    height: 100%;
}

body {
    background-image: url(../images/bgi.png);
    background-repeat: no-repeat;
    background-position: center center;
    background-size: cover;
}

.nav {
    height: 40px;
    font-size: 14px;
    display: flex;
    align-items: center;
    background-color: rgba(51, 51, 51, 0.8);
    color: white;
    text-decoration: none;
}

.nav p {
    padding: 0px 10px;
    margin-right: 1050px;
    cursor: default;
}

.nav a {
    display: block;
    color: white;
    text-decoration: none;
    float: right;
    padding: 0 16px;
}

.nav img {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    margin-left: 40px;
}


.container {
    display: flex;
    width: 1000px;
    margin: 0 auto;
    height: calc(100vh - 40px);
    justify-content: space-between;
}

.container .left {
    cursor: default;
    /* background-color: green; */
    width: 200px;
    height: 360px;
    border-radius: 10px;
    padding: 30px;
    background-color: rgba(255, 255, 255, 0.6);
}


.container .left img {
    width: 140px;
    height: 140px;
    border-radius: 50%;
    padding: 10px;
}

.container .left p {
    font-size: 22px;
    text-align: center;
    font-weight: bold;
    padding: 10px;
}

.container .left a {
    display: block;
    text-decoration: none;
    text-align: center;
    color: rgb(114, 102, 218);
    padding: 10px;
}

.container .left .counter {
    display: flex;
    justify-content: space-around;
    padding: 4px;
}


.container .right {
    width: 795px;
    height: 100%;
    background-color: rgba(255, 255, 255, 0.6);
    border-radius: 10px;
}

.container .right {
    overflow: auto;
}

.container .right .content {
    text-indent: 2em;
}

7.1 ??登陸頁(yè)面login的實(shí)現(xiàn)

<!-- login.html -->
<!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>登陸頁(yè)面</title>
    <link rel="stylesheet" href="./CSS/login.css">
</head>

<body>
<!-- 導(dǎo)航欄 -->
<div class="nav">
    <img src="./images/logo.png" alt="">
    <p>我的博客系統(tǒng)</p>
    <a href="./blog_index.html">主頁(yè)</a>
    <a href="">寫博客</a>
</div>
<div class="container">
    <p>登錄</p>
    <div class="login"><span>用戶名:</span><input type="text" id="username" placeholder="請(qǐng)輸入用戶名"></div>
    <div class="login"><span>密碼:</span><input type="password" id="password" placeholder="請(qǐng)輸入密碼"></div>
    <div id="rem"><input type="checkbox" id="remember">十天內(nèi)免登錄</div>
    <button id="submit" type="button">登錄</button>
</div>
<script type="text/javascript" src="./JS/login.js"></script>
<script src="./JS/jquery.min.js"></script>
<!--    為了能夠?qū)崿F(xiàn)登錄時(shí)彈窗的效果,這里登錄我們使用ajax請(qǐng)求-->
<script>
    $(function () {

        document.querySelector("#rem").addEventListener('click', function () {
            let myCheckbox = document.querySelector("#rem input")
            if (myCheckbox.hasAttribute("checked")) {
                myCheckbox.removeAttribute("checked")
            } else {
                myCheckbox.setAttribute("checked", "checked")
            }
        })
        let isRemLogin = function () {
            $.ajax({
                type: "get",
                url: "user/remLogin",
                success: function (jsonObj) {
                    console.log(jsonObj.ok)
                    if (jsonObj.ok === "1") {   //cookie信息登錄
                        document.location.href = 'blog_index.html'
                    }
                }, error: function () {
                    console.log("error.......")
                }
            })
        }

        let doLoginRequest = function () {
            let $username = $("#username").val()
            let $password = $("#password").val()
            let $remember = $("#remember").attr("checked") ? "1" : "0"
            $.ajax({
                type: "post",
                url: "user/loginIn",
                data: {
                    username: $username,
                    password: $password,
                    remember: $remember
                },
                success: function (reqRes) {
                    console.log("接收登錄響應(yīng)成功")
                    if (reqRes === "error") {
                        alert('賬號(hào)或密碼錯(cuò)誤!')
                        return
                    } else if (reqRes === "empty") {
                        alert("請(qǐng)補(bǔ)全賬號(hào)或密碼!")
                        return
                    } else {
                        alert("登錄成功!")
                        //登錄成功
                        document.location.href = "blog_index.html"
                    }
                }, errno: function () {
                    alert('請(qǐng)求失敗')
                }
            })
        }
        $('#submit').click(function () {
            doLoginRequest()
        })

        isRemLogin()    //判斷是否保存了用戶信息進(jìn)行登錄

    })
</script>
</body>

</html>
<!-- login.css -->

html,
body {
    height: 100%;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    background-image: url(../images/bgi.png);
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
}

.nav {
    height: 40px;
    display: flex;
    align-items: center;
    background-color: rgba(51, 51, 51, 0.8);
    color: white;
    font-size: 14px;
}

.nav img {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    margin-left: 40px;
}

.nav p {
    padding: 10px;
    margin-right: 1050px;
}

.nav a {
    display: block;
    padding: 25px;
    text-decoration: none;
    color: white;
}

.container {
    user-select: none;
    width: 400px;
    height: 500px;
    border-radius: 15px;
    margin: 0 auto;
    margin-top: 80px;

    background-color: rgba(255, 255, 255, 0.6);
}

.container p {
    text-align: center;
    padding: 30px;
    font-size: 36px;
    font-weight: bold;
    padding-bottom: 150px;
}

.container input {
    height: 30px;
    background-color: rgba(236, 194, 104, 0.4);
    padding: 5px 10px;
    border-radius: 4px;
    transition: all .3s;
    border: none;
    outline: none;
}


.container input:focus {
    box-shadow: 2px 2px 2px 2px;
}

.container span {
    display: inline-block;
    width: 80px;
    font-size: 18px;
    font-weight: 400;
}

.container .login {
    text-align: center;
    padding: 10px;
}

.container button {
    display: block;
    padding: 6px 15px;
    background-color: rgb(143, 175, 143);
    border-radius: 6px;
    margin: 0 auto;
    position: relative;
    top: 60px;
    width: 120px;
    cursor: pointer;
    user-select: none;
    transition: all .5s;
    border: none;
    outline: none;
}

.container button:hover {
    background-color: #809c21;
}

#rem {
    width: 110px;
    text-align: center;
    background-color: rgba(143, 175, 143, 0.4);
    border-radius: 6px;
    position: relative;
    top: 10px;
    padding: 0;
    font-size: 11px;
    left: 250px;
    cursor: pointer;
    user-select: none;
    transition: all .3s;
}

#rem input {
    display: inline-block;
    /* height: 14px; */
    margin-right: 3px;
    vertical-align: middle;
}

7.2 ??博客列表頁(yè)blog_index的實(shí)現(xiàn)

<!-- blog_index.html -->
<!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>博客首頁(yè)</title>

    <link rel="stylesheet" href="./CSS/common.css">
    <link rel="stylesheet" href="./CSS/blogIndex.css">
</head>

<body>
<!-- 導(dǎo)航欄 -->
<div class="nav">
    <img src="./images/logo.png" alt="">
    <p>我的博客系統(tǒng)</p>
    <a href="./blog_index.html">主頁(yè)</a>
    <a href="blog_editor.html">寫博客</a>
    <a href="user/loginOut">注銷</a>
</div>
<div class="container">
    <div class="left">
        <div class="card">
            <img src="./images/touxiang.jpg" alt="">
            <p></p>
            <a href="#">GitHub地址</a>
            <div class="counter">
                <div>文章</div>
                <div>分類</div>
            </div>
            <div class="counter">
                <div id="blog_num">2</div>
                <div>1</div>
            </div>
        </div>
    </div>
    <div class="right">
    </div>
</div>
<script src="./JS/jquery.min.js"></script>
<!--驗(yàn)證用戶身份信息的合法性-->
<script src="./JS/verify_user_legal.js"></script>
<script>
    $(function () {
        //發(fā)送異步ajax獲取所有的博客列表信息
        let getBlogList = function () {
            $.ajax({
                type: "GET",
                url: "blog/list",
                async: true,
                success: function (jsonArr) {
                    let right = document.querySelector('.right')
                    right.innerHTML = ''
                    for (const json of jsonArr) {
                        let textDiv = document.createElement('div')
                        textDiv.className = 'text'
                        //創(chuàng)建標(biāo)題節(jié)點(diǎn)
                        let h3 = document.createElement('h3')
                        h3.innerHTML = json.title
                        textDiv.appendChild(h3)
                        //創(chuàng)建date節(jié)點(diǎn)
                        let dateDiv = document.createElement('div')
                        dateDiv.className = 'date'
                        dateDiv.innerHTML = json.postTime
                        textDiv.appendChild(dateDiv)
                        //創(chuàng)建內(nèi)容節(jié)點(diǎn)
                        let contentDiv = document.createElement('div')
                        contentDiv.className = 'content'
                        contentDiv.innerHTML = json.content
                        textDiv.appendChild(contentDiv)
                        //創(chuàng)建超鏈接節(jié)點(diǎn)
                        let a = document.createElement('a')
                        a.href = 'blog_detail.html?blogId=' + json.blogId
                        a.innerHTML = '查看全文&gt;&gt;'
                        textDiv.appendChild(a)
                        //將text節(jié)點(diǎn)掛到dom樹(shù)上
                        right.appendChild(textDiv)
                        //作者的編號(hào)信息還沒(méi)有用上
                        let hr = document.createElement('hr');
                        right.appendChild(hr)
                    }
                }, errno: function () {
                    alert('獲取博客列表失敗!')
                }
            })
        }
        getUserInfo("blog_index.html")  //獲取用戶登錄信息,這是一個(gè)異步請(qǐng)求
        getBlogList()
    })
</script>
</body>

</html>
<!-- blog_index.css -->
.container .right .text {
    padding: 25px;
    width: 100%;
}

.container .right h3 {

    text-align: center;
    padding: 10px 0;
}

.container .right .date {
    text-align: center;
    padding-bottom: 10px;
}

.container .right .content {
    display: block;
    width: 100%;
    word-break: break-all;
    padding: 10px 0;
}

.container .right .text a {
    text-decoration: none;
    display: block;
    width: 110px;
    border-radius: 10px;
    text-align: center;
    padding: 5px;
    margin: 0 auto;
    border: 2px solid black;
    transition: all .3s;
    color: black;
}


.container .right .text a:hover {
    background-color: pink;
}

7.3 ??博客詳情頁(yè)blog_detail的實(shí)現(xiàn)

<!-- blog_detail.html -->
<!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>博客詳情頁(yè)</title>

    <link rel="stylesheet" href="./CSS/common.css">
    <link rel="stylesheet" href="./CSS/blogIndex.css">
    <link rel="stylesheet" href="./CSS/blogDetail.css">
    <!--    引入editor.md相關(guān)文件,將普通的字符串內(nèi)容渲染成md語(yǔ)法解析后的內(nèi)容顯示-->
    <link rel="stylesheet" href="./editor.md/css/editormd.min.css">
    <script src="./JS/jquery.min.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>
<!-- 導(dǎo)航欄 -->
<div class="nav">
    <img src="./images/logo.png" alt="">
    <p>我的博客系統(tǒng)</p>
    <a href="./blog_index.html">主頁(yè)</a>
    <a href="blog_editor.html">寫博客</a>
    <a href="user/loginOut">注銷</a>
</div>
<div class="container">
    <div class="left">
        <div class="card">
            <img src="./images/touxiang.jpg" alt="">
            <p></p>
            <a href="#">GitHub地址</a>
            <div class="counter">
                <div>文章</div>
                <div>分類</div>
            </div>
            <div class="counter">
                <div id="blog_num">2</div>
                <div>1</div>
            </div>
        </div>
    </div>
    <div class="right">
        <div class="text">
            <h3>我的第一篇博客</h3>
            <div class="date">2023-04-08</div>
            <div id="content">

            </div>
        </div>
    </div>
</div>
<script>
    $(function () {

        let getAuthorInfo = function (user) {
            $.ajax({
                type: "get",
                url: "author/authorInfo" + location.search,
                success: function (userJson) {
                    if (userJson.userId === -1) {
                        alert("訪問(wèn)的博客不存在...")
                        document.location.href = "blog_index.html"
                        return
                    }
                    if (userJson.userId === 0) {
                        setUserInfo("[該用戶已注銷...]", "XXX")
                        return
                    }
                    //能執(zhí)行到這里,說(shuō)明作者信息已經(jīng)加載完成了
                    setUserInfo(userJson.username, userJson.blogNum)
                    isShowDeleteBtn(userJson.username, user.username)  //將作者信息傳入,判斷當(dāng)前作者信息和登錄的用戶的信息是否相同
                }
            })
        }

        let setUserInfo = function (username, blogNum) {
            $(".card p").html(username)
            $(".card #blog_num").html(blogNum)
        }
        let getUserInfo = function (path) {
            $.ajax({
                type: "get",
                url: "user/verify",
                async: false,
                success: function (jsonObj) {
                    if (jsonObj.userId === 0) {
                        alert('您還未登錄,請(qǐng)登錄后訪問(wèn)...')
                        document.location.href = 'login.html'   //如果不存在用戶信息,就跳轉(zhuǎn)到登錄頁(yè)面
                        return
                    }

                    getAuthorInfo(jsonObj)

                }
            })

        }
        let doGetRequest = function () {
            $.ajax({
                type: "get",
                url: "blog/detail" + location.search,    //得到blog_list頁(yè)面的blogId查詢對(duì)應(yīng)博客的詳細(xì)信息
                success: function (json) {
                    $(".text h3").html(json.title)
                    $(".date").html(json.postTime)
                    //將后端相應(yīng)的普通字符串?dāng)?shù)據(jù)經(jīng)過(guò)markdown語(yǔ)法解析后顯示
                    editormd.markdownToHTML("content", {
                        markdown: json.content
                    })
                }, error: function () {
                    alert('內(nèi)容加載失敗!')
                }
            })
        }
        //發(fā)送同步請(qǐng)求,驗(yàn)證用戶身份信息的合法性
        getUserInfo("blog_detail.html")
        //執(zhí)行函數(shù),發(fā)送請(qǐng)求
        doGetRequest()

        let isShowDeleteBtn = function (authorName, username) {
            console.log(authorName + "    " + username)
            if (username === authorName) {
                //顯示按鈕信息
                let navDiv = document.querySelector(".nav")
                let a = document.createElement('a')
                a.innerHTML = '刪除'
                navDiv.appendChild(a)   //將創(chuàng)建的a標(biāo)簽掛到dom樹(shù)上
                a.addEventListener('click', function () {
                    if (!window.confirm("確定刪除嗎?")) {
                        return;
                    }
                    $.ajax({
                        type: "get",
                        url: "blog/delete" + location.search,
                        success: function (delRes) {
                            //接收刪除的返回信息
                            switch (delRes) {
                                case "login_out_of_date":
                                    alert("丟失登陸狀態(tài),請(qǐng)重新登錄...")
                                    document.location.href = 'login.html'
                                    break;
                                case "blog_not_exists":
                                    alert("blog信息不存在,請(qǐng)檢查")
                                    break
                                case "user_info_mismatching":
                                    alert("無(wú)法刪除他人的文章...")
                                    break
                                case "delete_success":
                                    alert("刪除成功!")
                                    document.location.href = 'blog_index.html'
                                    break
                                case "delete_fault":
                                    alert("刪除失敗,未知錯(cuò)誤...")
                                    break
                            }
                        }
                    })
                })
            }

        }



    })
</script>
</body>

</html>
<!-- blog_deatil.css -->

#content {
    opacity: 70%;
}


.nav a {
    cursor: pointer;
    padding: 0 10px;
}

7.4 ??博客編輯頁(yè)面blog_editor的實(shí)現(xiàn)

<!-- blog_editor.html -->
<!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>博客編輯頁(yè)面</title>
    <link rel="stylesheet" href="./CSS/common.css">
    <link rel="stylesheet" href="./CSS/blog_editor.css">
    <link rel="stylesheet" href="./editor.md/css/editormd.min.css">
    <script src="./JS/jquery.min.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>
<!-- 導(dǎo)航欄 -->
<div class="nav">
    <img src="./images/logo.png" alt="">
    <p>我的博客系統(tǒng)</p>
    <a href="./blog_index.html">主頁(yè)</a>
    <a href="">寫博客</a>
    <a href="user/loginOut">注銷</a>
</div>
<div class="content_editor">
    <form action="blog/save" method="post">
        <div class="title_content">
            <input type="text" placeholder="請(qǐng)輸入文章標(biāo)題" name="title" id="ipt">
            <input type="submit" id="subm" value="發(fā)布">
        </div>
        <div id="editor">
            <textarea name="content" cols="30" rows="10" style="display: none"></textarea>
        </div>
    </form>
</div>
<!-- 驗(yàn)證用戶身份信息的合法性 -->
<script src="./JS/verify_user_legal.js"></script>
<script>
    let editor = editormd("editor", {
        width: "100%",
        height: "calc(100% - 40px)",
        markdown: "# 在這里寫下一篇博客",
        path: "./editor.md/lib/",
        saveHTMLToTextarea: true         //將editor編輯的內(nèi)容保存在textarea文本框中,方便form表單的提交
    })
    $(function () {
        getUserInfo("blog_editor.html") //驗(yàn)證用戶身份信息的合法性
    })
</script>
</body>

</html>
<!-- blog_editor.css -->
.content_editor {
    margin: 0 auto;
    width: 1000px;
    height: calc(100vh - 40px);
}

.content_editor .title_content {
    width: 100%;
    height: 40px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.title_content #ipt {
    width: 890px;
    height: 30px;
    border: none;
    outline: none;
    padding-left: 15px;
    font-size: 16px;
    border-radius: 10px;
    transition: all .3s;
}

.title_content #subm {
    width: 100px;
    height: 30px;
    background-color: pink;
    border: none;
    outline: none;
    cursor: pointer;
    transition: all .3s;
    border-radius: 10px;
    font-size: 12px;
    padding-left: -10px;
}


.title_content #ipt:hover,
.title_content #sub:hover {
    box-shadow: 3px 5px 3px;
}

.content_editor #editor {
    opacity: 80%;
    border-radius: 10px;
}


.content_editor form {
    width: 100%;
    height: 100%;
}

8. 配置文件??

8.1 ??maven配置文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>


    <groupId>org.example</groupId>
    <artifactId>BlogSystem</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <!-- 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>

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.6.1</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>

    </dependencies>
    <packaging>war</packaging>

    <build>
        <finalName>test_last</finalName>
    </build>


</project>

到了這里,關(guān)于Servlet-搭建個(gè)人博客系統(tǒng)(MVC架構(gòu)模式簡(jiǎn)介,maven的配置和使用)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 自己動(dòng)手搭網(wǎng)站(六):javaweb搭建一個(gè)簡(jiǎn)單的個(gè)人博客系統(tǒng)

    自己動(dòng)手搭網(wǎng)站(六):javaweb搭建一個(gè)簡(jiǎn)單的個(gè)人博客系統(tǒng)

    這篇博主會(huì)介紹下我用javaweb搭建的個(gè)人博客系統(tǒng),源碼也會(huì)打包放到gitee上,需要的朋友可以自取,大家互相學(xué)習(xí),請(qǐng)不要直接CV。 tip:本篇承上篇,許多基本內(nèi)容在上篇談到,建議看之前先瀏覽下上篇博客。 上篇:自己動(dòng)手搭網(wǎng)站(五):javaweb基礎(chǔ):登錄功能 系列總目錄

    2024年02月07日
    瀏覽(28)
  • MVC設(shè)計(jì)模式、JSP開(kāi)發(fā)模式、三層架構(gòu)&MVC練習(xí)學(xué)生信息管理系統(tǒng)

    本文將介紹MVC設(shè)計(jì)模式、JSP開(kāi)發(fā)模式、三層架構(gòu)和MVC練習(xí)的基本概念,并演示如何使用這些技術(shù)來(lái)構(gòu)建一個(gè)學(xué)生信息管理系統(tǒng)。該系統(tǒng)將包括數(shù)據(jù)庫(kù)準(zhǔn)備、查詢、增加、刪除、更新和分頁(yè)功能。 MVC是一種軟件架構(gòu)模式,將應(yīng)用程序分為三個(gè)部分:模型(Model)、視圖(View)和

    2023年04月25日
    瀏覽(441)
  • 【Microsoft Azure 的1024種玩法】六十.通過(guò)Azure Virtual Machines快速搭建個(gè)人Ghost博客系統(tǒng)

    【Microsoft Azure 的1024種玩法】六十.通過(guò)Azure Virtual Machines快速搭建個(gè)人Ghost博客系統(tǒng)

    Ghost 是一套基于Node.js 語(yǔ)言開(kāi)發(fā)構(gòu)建的開(kāi)源博客系統(tǒng),它的整體架構(gòu)為前端管理系統(tǒng)基于Ember.js, 后端的模板引擎采用的handlebars, 數(shù)據(jù)庫(kù)是基于MySQL的,本篇文章主要介紹了如何通過(guò)Azure Virtual Machines快速搭建個(gè)人Ghost博客系統(tǒng) 【Microsoft Azure 的1024種玩法】一.一分鐘快速上手搭

    2024年02月06日
    瀏覽(27)
  • 云計(jì)算模式的區(qū)域LIS系統(tǒng)源碼,基于ASP.NET+JQuery、EasyUI+MVC技術(shù)架構(gòu)開(kāi)發(fā)

    云計(jì)算模式的區(qū)域LIS系統(tǒng)源碼,基于ASP.NET+JQuery、EasyUI+MVC技術(shù)架構(gòu)開(kāi)發(fā)

    云計(jì)算模式的區(qū)域LIS系統(tǒng)源碼?云LIS系統(tǒng)源碼,自主版權(quán) LIS系統(tǒng) 是專為醫(yī)院檢驗(yàn)科的儀器設(shè)備能與計(jì)算機(jī)連接。可通過(guò)LIS系統(tǒng)向儀器發(fā)送指令,讓儀器自動(dòng)操作和接收儀器數(shù)據(jù)。并快速的將檢驗(yàn)儀器中的數(shù)據(jù)導(dǎo)入到醫(yī)生工作站中進(jìn)行管理,且可將檢驗(yàn)結(jié)果發(fā)布到各個(gè)受檢(門

    2024年02月08日
    瀏覽(24)
  • 搭建個(gè)人博客詳細(xì)教程

    搭建個(gè)人博客詳細(xì)教程

    由于國(guó)外的github page訪問(wèn)總是非常慢的,本文選擇國(guó)內(nèi)開(kāi)源代碼托管平臺(tái)碼云,因而可以在國(guó)內(nèi)搭建訪問(wèn)與SEO檢索都優(yōu)于GitHub的個(gè)人網(wǎng)站。自己親手勉強(qiáng)搭起個(gè)人博客,首先感謝木千之博主的詳細(xì)教程,給了清晰的思路,寫下這篇博客將詳細(xì)過(guò)程記錄,希望幫助更多的人,減

    2023年04月08日
    瀏覽(35)
  • ? 個(gè)人博客的搭建和設(shè)置

    ? 個(gè)人博客的搭建和設(shè)置

    閑暇時(shí)候自己試著做了一個(gè)自己的個(gè)人博客,博客使用的Github進(jìn)行托管,還在阿里云買了屬于自己的域名 具體步驟如下 git --version 4、進(jìn)入自己想要搭建的放在Github的文件夾 一、clone倉(cāng)庫(kù)到本地 git clone 自己的代碼倉(cāng)庫(kù)地址 git clone 你的代碼倉(cāng)庫(kù)地址 二、添加自己的東西到文件

    2024年02月03日
    瀏覽(57)
  • gitee搭建個(gè)人博客教程

    gitee搭建個(gè)人博客教程

    基礎(chǔ)環(huán)境: gitee賬號(hào)、git、node.js、npm、Typora(需要版本高一點(diǎn)) 個(gè)人博客 創(chuàng)建賬號(hào)同名的倉(cāng)庫(kù) 獲取賬號(hào)名方式如下,去掉@號(hào)的部分。 創(chuàng)建一個(gè)和你gitee賬號(hào)同名的倉(cāng)庫(kù),這樣就可以用https://賬號(hào)名.gitee.io/來(lái)訪問(wèn)。 填寫倉(cāng)庫(kù)名稱即可,但建議勾選上設(shè)置模板----Readme文件。

    2024年02月09日
    瀏覽(24)
  • 如何使用Github搭建個(gè)人博客

    如何使用Github搭建個(gè)人博客

    在本文中,我將介紹如何使用GitHub搭建個(gè)人博客( 免費(fèi) )。GitHub是一個(gè)功能強(qiáng)大的版本控制和協(xié)作平臺(tái),它也可以用來(lái)托管和發(fā)布靜態(tài)網(wǎng)頁(yè)。通過(guò)將你的個(gè)人博客托管在GitHub上,你可以享受到版本控制的好處,并且能夠與其他開(kāi)發(fā)者進(jìn)行協(xié)作。 在GitHub官網(wǎng)上創(chuàng)建一個(gè)賬號(hào),

    2024年02月15日
    瀏覽(23)
  • Hexo搭建個(gè)人博客(github)

    Hexo搭建個(gè)人博客(github)

    記錄搭建個(gè)人博客的過(guò)程 本文使用Hexo+GitHub Page的方法搭建博客,下面是環(huán)境準(zhǔn)備的步驟,包括nodejs的安裝和git的安裝(注:本教程僅適用于windows用戶) 詳情請(qǐng)參考這篇博客: NVM的安裝使用與配置(node, npm, yarn 為了把本地的網(wǎng)頁(yè)上傳到git上,需要在系統(tǒng)上下載git,詳情參考

    2024年02月21日
    瀏覽(22)
  • 基于Hugo 搭建個(gè)人博客網(wǎng)站

    基于Hugo 搭建個(gè)人博客網(wǎng)站

    目錄 1.環(huán)境搭建 2.生成博客 3.設(shè)置主題 4.將博客部署到github上 1)安裝Homebrew brew是一個(gè)在 macOS 操作系統(tǒng)上用于管理軟件包的包管理器。類似于centos下的yum或者ubuntu下的apt,它允許用戶通過(guò)命令行安裝、更新和管理各種軟件工具、庫(kù)和應(yīng)用程序。 前往hb官網(wǎng),復(fù)制下載命令,打

    2024年02月09日
    瀏覽(27)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包