当前位置:网站首页>Implement a blog system -- using template engine technology
Implement a blog system -- using template engine technology
2022-07-05 14:31:00 【Little bits that can't learn binary tree】
Main idea :
1) Server render , Based on template engine ( Here we implement the first )
2) Fore and aft end separation , be based on AJAX, The server returns to the front end json Formatted data , The front end is spliced by itself HTML fragment ;
1) Blog list page ( Dynamic pages )<--------- Render the page
1.1 Provide all blog information ( Render each one on the right div Blog ):OperatorBlog Medium SelectAll() Method ------------ From the database
1.2 Provide the personal information of the login :----------> Get the user identity information of the login ------>HttpSession Key value pairs in When clicking on the title of the article , Send... To the server GET request , close BlogID, Visit the blog details page
2) Blog details page ( Dynamic pages )<--------- Render the page
1.1 Provide specific blog data ------> according to blogID adopt OperatorBlog Medium SelectOne Method to query the blog for rendering ------> From the database
1.2 Get the author information in the article ----> according to blogID adopt OperatorBlog Medium SelectorOne Method query to blog, Get blog Medium userID, Then according to the call OperatorUser Medium selectByUserID To find the author of the article -----> From the database
3) Realize blog editing page ( Static page )-------> Send the blog title and content written by the user to the server
First construct a Blog object , Insert data into the database -------->MYSQL
4) Realize the blog login page ( Static page )-------> Submit the user name and password in the input box to the server
4.1 Query user information according to user name ( Query to User object )------>MYSQL
4.2 Put user information (User object ) writes HttpSession Inside
5) Implement the logout function ( There is no separate interface , Just in the navigation bar )
according to a The tag sends a Http Of Get request , Directly delete the user's identity information saved in the session
6) Realize the function of deleting blog ( There is no separate interface , There will be a delete button on the blog details page , The premise is that the currently logged in author is the author of the article )
Send requests like services through hyperlinks , Bring... With you in the request blogID Such a parameter , Then delete the blog ------> Operating the database
1. establish maven project :
1) Let's introduce Servlet Dependence , introduce Thymeleaf and MYSQL Dependence
2) stay main Create under directory webapp Catalog , stay webapp Create... In the directory web.xml file , stay webapp It creates WEB-INF Catalog , Again from WEB-INF It creates template Catalog , Copy all the front pages of the blog system we wrote before
3) Use Smart-Tomact Packaged deployment
2. Design database
We need to store blog information and user identity information in the database
1) Let's create a blog table
Create the database first ----Java200, Blog list : Blog ID, Blog title , Blog text ( Use... In this mediumetext The data range represented is larger than varchar It's going to be longer ), Blog release time , The author of a blog ( Use one ID To mark )
Create blog tables
create table blog(
blogID int primary key auto_increment,// The identity of each blog
title varchar(1024),// Every blog post
content mediumtext,// The body of every blog
postTime datetime,// The release time of each blog
userID int);// The author of every blog
2) Let's create a user table
The identity of the user ID, User name , User's password , Besides, the user ID in our user table ID And in the blog table userID It can also be associated with foreign keys ;
create table user(
userID int,
name varchar(20),
password varchar(30));
3) Encapsulate database operations ,JDBC Code , Now let's write some MYSQL Common methods in
We are Java Create a package called MYSQL
1) We create the first class , be called ConnectionDatabase, Inside the store JDBC link MYSQL Code for , I have written before
package MYSQL;
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 ConnectionDatabase {
private static final String url="jdbc:mysql://127.0.0.1:3306/java200?characterEncoding=utf-8&userSSL=true";
private static final String password="12503487";
private static final String user="root";
public static DataSource datasource=null;
public static DataSource getDataSource()
{
if(datasource==null)
{
synchronized(Object.class)
{
if(datasource==null)
{
datasource=new MysqlDataSource();
((MysqlDataSource)datasource).setURL(url);
((MysqlDataSource)datasource).setUser(user);
((MysqlDataSource)datasource).setPassword(password);
}
}
}
return datasource;
}
public static Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
public void close(ResultSet resultSet, PreparedStatement statement, Connection connection) throws SQLException {
resultSet.close();
statement.close();
connection.close();
}
}
2. Create entity class , Through each entity class object , To represent a record data in the table ; We create them separately Blog Such classes and User Such a class to represent ; The various attributes in the class correspond to those in the database , And for the attributes inside Set and Get Method ----- They are all classes created according to the content in the database ; We are MYSQL This package , establish Blog and User class ;
1) Pay attention to java Which means time is available timestamp type , You can also use java.sql.Date, But this Date Type can only represent date , When it is impossible to express , branch , Of a second
2) stay MYSQL Middle means time can be used String, But I'm not sure whether the current time is legal , We can also use datetime and timestamp type ( here we are 2038 Years may not be enough )
3. In the process of creating some classes , To pass some JDBC Code to realize some operations of the database ;
1. Let's create the first class , To achieve the right Blog Some operations on objects ;
1) Add a new blog ---- We have the function of publishing articles in the front-end code
2) Get all blog list pages ----- It corresponds to our blog list page , The function is to display all blogs ;
3) According to blog ID You can find the corresponding blog , It is mainly to click in the blog list page to view the full text , You can see the details of a blog post ;
4) According to blog ID To delete the blog ;
5) We can write some test cases to verify our above operations ;
package MYSQL;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class OperateBlog {
public void insert(Blog blog) throws SQLException, SQLException {
System.out.println(" Add a new blog ");
//1 Establish a connection to the database
Connection connection=null;
connection=ConnectionDatabase.getConnection();
String SQL="insert into blog values(null,?,?,?,?)";
//2 establish SQL sentence
PreparedStatement statement=connection.prepareStatement(SQL);
statement.setString(1,blog.getTitle());
statement.setString(2,blog.getContent());
statement.setTimestamp(3,blog.getPostTime());
statement.setInt(4,blog.getUserID());
//3 perform SQL sentence
int ret=statement.executeUpdate();
if(ret==1)
{
System.out.println(" New blog succeeded ");
}else{
System.out.println(" Failed to add blog ");
}
ConnectionDatabase.close(null,statement,connection);
}
public List<Blog> SelectAll() throws SQLException {
System.out.println(" Start looking for all blogs ");
List<Blog> list=new ArrayList<>();
Connection connection=ConnectionDatabase.getConnection();
String SQL="select * from blog";
PreparedStatement statement=connection.prepareStatement(SQL);
ResultSet set=statement.executeQuery();
// Traverse the structure set inside
while(set.next())
{
Blog blog=new Blog();
blog.setBlogID(set.getInt("blogID"));
blog.setTitle(set.getString("title"));
blog.setContent(set.getString("content"));
blog.setPostTime(set.getTimestamp("postTime"));
blog.setUserID(set.getInt("userID"));
list.add(blog);
}
ConnectionDatabase.close(set,statement,connection);
return list;
}
public Blog SelectOne(int blogID) throws SQLException {
System.out.println(" Start to find the specified blog ");
Connection connection=null;
PreparedStatement statement=null;
connection=ConnectionDatabase.getConnection();
String SQL="select * from blog where blogID = ?";
statement=connection.prepareStatement(SQL);
statement.setInt(1,blogID);
ResultSet set=statement.executeQuery();
if(set.next()) {// Don't write the conditions wrong if(set!=null)
Blog blog = new Blog();
// Traverse the result set and , The query here is based on the self incrementing primary key , Or 1 Records are either 0 Bar record ;
blog.setBlogID(set.getInt("blogID"));
blog.setTitle(set.getString("title"));
blog.setContent(set.getString("content"));
blog.setPostTime(set.getTimestamp("postTime"));
blog.setUserID(set.getInt("userID"));
ConnectionDatabase.close(set, statement, connection);
return blog;
}
return null;
}
public void DeleteBlog(int blogID) throws SQLException {
Connection connection=null;
PreparedStatement statement=null;
connection=ConnectionDatabase.getConnection();
String SQL="delete from blog where blogID = ?";
statement=connection.prepareStatement(SQL);
statement.setInt(1,blogID);
int len=statement.executeUpdate();
if(len==1)
{
System.out.println(" Delete successful ");
}
}
public static void main(String[] args) throws SQLException {
//1 Test the insertion function
Blog blog=new Blog();
blog.setUserID(1);
blog.setBlogID(1);
blog.setTitle("ABCDEFG");
blog.setContent("I am a boy");
blog.setPostTime(new Timestamp(System.currentTimeMillis()));// Must be java.sql The bag inside
//setPostTime There needs to be a Timestamp type , You need it inside new One Timestamp object ,Timestamp The parameter inside is a timestamp
// statement The subscript is set from 0 The subscript starts to be set
OperateBlog blogdemo=new OperateBlog();
blogdemo.insert(blog);
//2. Test and find all blog functions
List<Blog> list=blogdemo.SelectAll();
// System.out.println(list);
//3 Find the specified blog
Blog blog1=blogdemo.SelectOne(1);
System.out.println(blog1);
}
}
2. Let's create a second object , To do something about user To operate
1) Add new users , To realize the registration function ( Insert data into the database )
2) Find the user object according to the user name , When logging in, you should find the user object according to the user name , To judge and compare , The password entered in the input box is compared with the found user password , So whether it is correct ;
3) According to the user ID( According to the blog list page ) To find user objects , When we click to view the full text , Show the author's specific identity information on the blog page ( Click on the blog details page );
We need to know , The identity information of the login is displayed on the blog list page , But after clicking on the blog list page , The identity information of the corresponding author of this article is displayed ;
4) When registering , There is only one user name user object , The user name is not repeated ;
package MYSQL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class OperateUser {
public void insert(User user) throws SQLException {
Connection connection=null;
PreparedStatement statement=null;
connection=ConnectionDatabase.getConnection();
String SQL="insert into user values(?,?,?)";
statement=connection.prepareStatement(SQL);
statement.setInt(1,user.getUserID());
statement.setString(2, user.getName());
statement.setString(3, user.getPassword());
int len=statement.executeUpdate();
if(len==1)
{
System.out.println(" Insert the success ");
}else{
System.out.println(" Insert the failure ");
}
}
public User selectByName(String username) throws SQLException {
Connection connection=null;
PreparedStatement statement=null;
connection=ConnectionDatabase.getConnection();
String SQL="select * from user where name = ?";
statement= connection.prepareStatement(SQL);
statement.setString(1,username);
ResultSet set=statement.executeQuery();
if(set.next())
{
User user=new User();
user.setPassword(set.getString("password"));
user.setName(username);
user.setUserID(set.getInt("userID"));
return user;
}
return null;
}
public User selectByUserID(int userID) throws SQLException {
Connection connection=null;
PreparedStatement statement=null;
connection=ConnectionDatabase.getConnection();
String SQL="select * from user where userID = ?";
statement=connection.prepareStatement(SQL);
statement.setInt(1,userID);
ResultSet set=statement.executeQuery();
if(set.next())
{
User user=new User();
user.setUserID(userID);
user.setName(set.getString("name"));
user.setPassword(set.getString("password"));
return user;
}
return null;
}
}
4. At this time, we start to write the operation of realizing the page , We let the server be based on the template engine , To find the data from the database , Return to the page
1) So let's do the initialization first Thymeleaf
2) Implement blog list page
3) Realize the blog details page
4) Realize the blog login page
5) Realize blog editing page
1. Initialize the template engine
We need to put the initialization code into ServletContextListener in , And then put TemplateEngine After initialization, put it in ServletContext Inside ;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener// Be sure to add notes
public class StartThymeleaf implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println(" Start initializing the template engine ");
//1 establish TemplateEngine Objects and resolver object
ServletContext context=servletContextEvent.getServletContext();
TemplateEngine engine=new TemplateEngine();
ServletContextTemplateResolver solver=new ServletContextTemplateResolver(context);
solver.setPrefix("/WEB-INF/template/");
solver.setSuffix(".html");
solver.setCharacterEncoding("utf-8");
//2 take resolver Objects and engine Object to associate
engine.setTemplateResolver(solver);
//3 We will create a good engine Objects in the ServletContext Inside the object
context.setAttribute("engine",engine);
System.out.println(" The operation of initializing the template engine is over ");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
2. Implement blog list page
1) In the blog list page , Every blog we write on the page cannot be a dead data , Instead, you should find every record in the database , Every blog is a class=blog Of div, Besides, no blog has a title , Release time , Content , These attributes are related to those in our database blog The corresponding fields in the table are the same ; We can use it on the front page th:each, According to the server blog Array , Traverse to each one in turn blog, Then build it on our list page ;
2) We can't call all the links on the details page blog2.html, stay href Attribute plus blogID, In this way, our server will know which blog list we are currently visiting ;
3) We put each blog corresponding to view the full text a The label has been changed , This blogID stay QueryString Set it up
<a href="'blog2.html?blogID='+blog.blogID" class="detail" target="_blank"> View full text >></a>
When we visit the blog details page of each blog , Bring one blogID, In this way, the server will know which blog we are visiting ;
4) We are writing back end Servlet Code time ,WebServlet The path of the association in , It can contain points , Visit the browser later blog1.html When , It's not a static page , But a dynamically generated page
5) If too much content leads to overflow , Add a scroll bar automatically overflow:auto; If the blog text is too long , Let's cut a paragraph from the blog list page , Part of the ( Just intercept the first few words ), We can operate directly in the database Blog In the category of , When getting all blogs , Determine whether the length of blog content exceeds 90, exceed 90 Characters , Just call subString Method to intercept ; In splicing strings ".......";
When we query the database again , Get the text directly and then judge , If it is too long , Direct truncation
<!-- On the right is the blog list page -->
<div class="right">
<!-- On the right side , We mean blog by blog -->
<div class="blog" th:each="blog : ${blogs}">
<!-- Article title -->
<h2 class="title" th:text="${blog.title}"></h2>
<!-- Release date -->
<div class="date" th:text="${blog.postTime}"></div>
<!-- Article content -->
<div class="text" th:text="${blog.content}"></div>
<!-- View full text button -->
<a href="${'blog2.html?blogID'+blog.blogID}" class="detail" target="_blank"> View full text >></a>
</div>
</div>
The content here depends on template rendering , One comes from the back end blogs Array or list, We will automatically traverse to each of them blog, Take out every attribute inside , Then go to the rendering operation ;
OperateBlog operateBlog=new OperateBlog();
//1 Get a list of all blogs from the database
List<Blog> list= null;
try {
list = operateBlog.SelectAll();
} catch (SQLException e) {
e.printStackTrace();
}
resp.setContentType("text/html;charset=utf-8");
//2 Get the template engine object , Perform page rendering operation
ServletContext context=req.getServletContext();
TemplateEngine engine=(TemplateEngine)context.getAttribute("engine");
//3 establish WebContext object , Set key value pairs
WebContext webContext=new WebContext(req,resp,context);
webContext.setVariable("blogs",list);
//4 Rendering
String html= engine.process("blog1",webContext);
resp.getWriter().write(html);
3. Realize the blog details page
1) On the blog list page , We explicitly specify all blogs , Just get all the blogs , But in the blog details page , We have to rely on a Request in tag BlogID To specify which blog it is , According to blogID To query the database , So we get the details of the blog ; This blogID Is set at QueryString Inside
2) At present, we are still one place away , That is to say, in the current blog details page , What is displayed inside , Not according to Markdown To render , For example, the three-level title here still cannot be displayed normally ;
<!-- On the right is the blog details page , This div Represents the whole new background of the right version -->
<div class="right">
<!-- There is no need to write th:each-->
<div class="blog">
<!-- Article title -->
<h3 th:text="${blog.title}"></h3>
<!-- Blog release time -->
<div class="date" th:text="${blog.postTime}">2022 year 12 month 3 Japan </div>
<P th:text="${blog.content}"></P>
</div>
</div>
We hope that in the blog details page , Can pass one blog object , Find the corresponding attribute to render
resp.setContentType("text/html;charset=utf-8");
OperateBlog operateBlog=new OperateBlog();
String blogID=req.getParameter("blogID");
if(blogID==""||blogID.equals(""))
{
String html="<h3>blogID Field deletion </h3>";
resp.getWriter().write(html);
}
Blog blog= null;
try {
blog = operateBlog.SelectOne(Integer.parseInt(blogID));
} catch (SQLException e) {
e.printStackTrace();
}
if(blog==null)
{
String html="<h3> According to blog ID The current blog obtained does not exist </h3>";
resp.getWriter().write(html);
}
ServletContext context=req.getServletContext();
TemplateEngine engine=(TemplateEngine)context.getAttribute("engine");
WebContext webContext=new WebContext(req,resp,context);
webContext.setVariable("blog",blog);
String html=engine.process("blog2",webContext);
resp.getWriter().write(html);
}
4. Achieve blog login interface
1) Landing page HTML There is no need for dynamic replacement , That is to say, the content is fixed , There is no need for dynamic replacement of templates , There is no content in the page that needs to be dynamically generated
2) Achieve one Servlet To implement the login request ( Static pages are put directly into webapp Inside , Don't put it in the file of the template engine )
3) We also need to fine tune the page , When we click the button , Can send a HTTP request , Inside input Tag plus name attribute , Only one form Form to package ;
4) When implementing the code of the server , The logic we write is like this , Direct use loginServlet To implement
One : First read the user name and password from the request
Two : Then read out from the database according to the user name User, Then compare whether the password is correct , Input correct , Then log in successfully , Put the current user Objects in the HttpSession in , For later use
3、 ... and : After successful login , We directly 302 Redirect to blog list page
5) We want to target the blog list page , Blog details page , Whether you have logged in for a verification , It is agreed here , If you are currently not logged in , You cannot access the blog list page and blog details page , At this time, if you visit , Redirect to the blog landing page ; After this matter, we need to revise what we wrote before , Two Servlet;
Our standard for judging whether users log in is to see whether they can get a suitable one at present session, And you can get the inside user object , It means that the user is logged in ;
6) Put the following code in blog1Servlet and blog2Servlet Inside , When we perform redirection , Be sure to end the current program ;
7) When we restart the server , Direct access blog1.html perhaps blog2.html, Will jump to the blog landing page , Let the current user log in ;
8) Why can we get the login after login user What about objects? ? That's because after we implement the blog landing page , We're on our own httpsession There's one in store user The object is inside ;
Realize the code of specific landing page :
import MYSQL.OperateUser;
import MYSQL.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.sql.SQLException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. Get the parameters in the request
resp.setContentType("text.html;charset=utf-8");
req.setCharacterEncoding("utf-8");
String username=req.getParameter("name");
String password=req.getParameter("password");
System.out.println(username);
System.out.println(password);
if(username==null||password==null||username.equals("")||password.equals(""))
{ String html="<h3> The user name or password in the current request is missing </h3>";
resp.getWriter().write(html);
return;
}
OperateUser operateUser=new OperateUser();
//2 Query users from the database
User user=null;
try {
user=operateUser.selectByName(username);
} catch (SQLException e) {
e.printStackTrace();
}
//3 check , There is no direct redirection to the login interface , Here are some cases of login failure , We can't find it user Or the passwords do not match
if(user==null)
{
String html="<h3> Wrong user name or password </h3>";
resp.getWriter().write(html);
return;
}
if(!user.getPassword().equals(password))
{
String html="<h3> Wrong user name or password </h3>";
resp.getWriter().write(html);
return;
}
//4 hold user The object size is enlarged HttpSession Inside
HttpSession httpSession=req.getSession(true);
httpSession.setAttribute("user",user);
resp.sendRedirect("blog1.html");
}
}
Before visiting each page , Code to judge whether the user logs in :
// Determine whether the current user is logged in
HttpSession session=req.getSession(false);
if(session==null||session.equals(""))
{
System.out.println(" The current user is not logged in ");
// Not logged in
resp.sendRedirect("blog3.html");
return;
}
User userx= (User) session.getAttribute("user");
if(userx==null)
{
System.out.println(" The current user is not logged in ");
// Not logged in
resp.sendRedirect("blog3.html");
return;
}
1) above HttpSession The object is based on the same SessionID To find objects , When we reach req.getSession() When , We will base on SessionID To find out Session Object ;
2) But at present, we still find some problems , After our successful login , The data in our personal information list on the left is dead , When we go to the blog details page , The author of the article shown is also dead ; The reason why the above information is dead is that we have not implemented the login function before , There is no way to get user information , Now you can log in , Next, you can put the identity information on the current page , Dynamic replacement based on template engine ;
If it is on the blog list page , Then the user information here will display the user information of the current login ;
If the blog details page , Then the user information at this time will display the user information of the current article author ;
Currently, there is no implementation to modify the avatar and gitup This function , These implementations are no different from dynamically replacing user names , It's just that you need to expand fields in the database to save this information ;
For example, we want to save avatars , You can store the path of some pictures in the database , Then you can return the image path to the front page ;img In the label src Attribute is enough
Let's modify the blog list page first ;
What is set here userx It was when we checked the login status just now , from session Read inside user, This userx It is the information of the user who logged in by the current user ;
Every time we restart the server , The one in the server memory that saves the session hash The watch is gone , So the previous login status is gone ( Because this hash table is stored in memory ), The next time our client accesses the server Cookie In the field sessionID The server will not recognize , It can only be regarded as not logged in ;
But in fact, not all session information is in memory ,Servlet The default session is in memory , Want to put hash Tables are stored in files or databases , It should be implemented through code ;
Modify the blog details page :
The front-end modification method is the same :
Back end code :
We can't be here webContext It is set from session Read inside user, But according to what we passed on the blog list page before we went again blogID To query users user, This user That's what we need to do with template rendering user;
The above writing is wrong , How can it be based on blogID To query User Well ? The following is true :
OperateUser operateUser=new OperateUser();
try {
User user=operateUser.selectByUserID(blog.getUserID());
webContext.setVariable("user",user);
} catch (SQLException e) {
e.printStackTrace();
}
5. Implement the logout function
1) We expect , When we click the logout button , You can exit the login status , Before we judge whether the user logs in , Based on SessionID To find HttpSession object , Then take out the inside user;
2) We must get one user Login is successful , take user Can't get , Or can't get session All login failures ;
3) At present, our logout button is a label , There is a path in it , We can write a Servlet To handle the requests , In the code, we can according to SessionID To find and store in Session Inside User object , And put this User The object was deleted ; stay HttpSession One is provided in removeAttribute() This way ; Then redirect directly to the login interface ;
4) We are on the server side java Create... In the directory deleteServlet To process the logout request ;
<a href="delete" target="_blank"> Cancellation </a>
import MYSQL.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/delete")
public class deleteServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Determine whether the current user is logged in
HttpSession session=req.getSession(false);
if(session==null||session.equals(""))
{
System.out.println(" The current user is not logged in ");
// Not logged in
resp.sendRedirect("blog3.html");
return;
}
User userx= (User) session.getAttribute("user");
if(userx==null)
{
System.out.println(" The current user is not logged in ");
// Not logged in
resp.sendRedirect("blog3.html");
return;
}
resp.setContentType("text/html;charset=utf-8");
session.removeAttribute("user");
// Redirect login interface
resp.sendRedirect("blog3.html");
}
}
6. Realize the blog publishing function
1) Adjust the blog editing page , Our current blog editor page , There is no need for dynamic replacement , Just like the previous login interface , I just have to add form Forms , Just click the submit button at the end , Trigger HTTP request , To submit ;
We will be having input It's labeled with name attribute , It is convenient for the server to get the title of this article , Then the submit button needs to be modified ;
2) In addition, we need to write one by ourselves Servlet For the request to submit a blog , To process ;
3) The function of each modification , Develop new logic , Both need to be matched at the front and rear , This leads to the fact that the interaction between the front and back ends cannot be completely separated
4) however Markdown How to submit the content in the compiler ?
We can do it in id="editor" Of div Add a hidden textarea label , Inside plus name attribute , This thing doesn't need to be displayed , It's just for the following forms to construct data
5) We still need to do one more step , Take us markDown The contents of the compiler are put in textarea Inside , Easy to submit ; We just need to initialize editor When , stay script It's labeled with saveHTMLToTextarea:true, That is, it can make editor.md Save the contents in the edit box to the user's own writing in real time textarea Inside the ; Then you can submit the form further and bring the body of the blog ;
The front-end code :
<!-- This is the heart of the blog editing page -->
<form action="edit" method="post">
<div class="edit">
<div class="writetitle">
<input type="text" id="title" name="title">
<input type="submit" value=" Click post " id="submit">
</div>
<div id="editor">
<textarea name="content" style="display:none"></textarea>
</div>
</form>
</div>
<script>
// First, initialize the compiler
// First create a textinner object
//editormd It is equivalent to a function , Generate a editor object
// The first parameter is to specify which html In the label , Yuan a html Label Association , The parameter is the corresponding ID;
var editor=editormd("editor", {
// The size here must be set here , Can't rely on CSS Set it up
width:"100%",
// This is calculation makdown The height of the text
height:"1000px",
// The initial content of the editor
markdown:"# Write your first blog here ",
// The path of the plug-in used by the compiler
path:"editor.md/lib/",
saveHTMLToTextarea:true
});
Back end code :
import MYSQL.Blog;
import MYSQL.OperateBlog;
import MYSQL.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Timestamp;
@WebServlet("/edit")
public class editServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Determine whether the current user is logged in
HttpSession session=req.getSession(false);
if(session==null||session.equals(""))
{
System.out.println(" The current user is not logged in ");
// Not logged in
resp.sendRedirect("blog3.html");
return;
}
User userx= (User) session.getAttribute("user");
if(userx==null)
{
System.out.println(" The current user is not logged in ");
// Not logged in
resp.sendRedirect("blog3.html");
return;
}
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//2 Get the title and content of the article in the request
String content=req.getParameter("content");
String title=req.getParameter("title");
if(content==null||content.equals("")||title==null||title.equals(""))
{
String html="<h3> Failed to publish blog , The title or content of the article is empty </h3>";
resp.getWriter().write(html);
return;
}
//3 Construct a blog object , Insert into the database
Blog blog=new Blog();
blog.setContent(content);
// Note that the author of the current article is the current login
blog.setUserID(userx.getUserID());
blog.setTitle(title);
blog.setPostTime(new Timestamp(System.currentTimeMillis()));
OperateBlog operateBlog=new OperateBlog();
try {
operateBlog.insert(blog);
} catch (SQLException e) {
e.printStackTrace();
}
//4 Redirect to blog list page
resp.sendRedirect("blog1.html");
}
}
7. Now we find , The blog details page shows the original of the blog Markdown Content , Instead of rendered markdown, First level title , The secondary titles are not displayed
One # Will be rendered as a first-class Title , Three # It will be rendered as a three-level Title ( Write on the left , The right side shows the specific rendered results )
We need to adjust our blog details page at this time , At the same time, we also need to introduce editor.md This library , Then there is an operation in this library markdownHTML, The function of this method is to put the original markDown The text is rendered into a HTML
<script>
// First, initialize the compiler
// First create a textinner object
//editormd It is equivalent to a function , Generate a editor object
// The first parameter is to specify which html In the label , Yuan a html Label Association , The parameter is the corresponding ID;
var editor=editormd("editor", {
// The size here must be set here , Can't rely on CSS Set it up
width:"100%",
// This is calculation makdown The height of the text
height:"1000px",
// The initial content of the editor
markdown:"# Write your first blog here ",
// The path of the plug-in used by the compiler
path:"editor.md/lib/",
saveHTMLToTextarea:true
});
</script>
In the blog details page , There is a code :
<P th:text="${blog.content}"></P> This div It contains markDown Original message
markdown The original content of , That's it div Inside , We can put this div Take out the contents , Then pass the just markdownToHTML Method ( This method is script Inside the label ) convert , Then give some of the conversion results back to the previous one div in ;
<div id="content"th:text="${blog.content}"></div>
<script>
function rendMo(){
//1 Take out first div What's in it
let markDownDiv=document.querySelector("#content");
let markdown=markDownDiv.innerHTML;
console.log(markdown);
//2 hold div The content inside is set to empty
markDownDiv.innerHTML="";
//3 Replace
editormd.markdownToHTML('content',{
markdown:markdown
});// First parameter representation ID
}
rendMo();
</script>
8. After we have completed the above adjustments , I found that the current code can indeed be run and rendered , But the background and the previous translucent effect , Seem out of place ;
Here you can give the one just now div Set a pure transparent background (back-groundcolor Inside rgbc Transparency can be set ;
<div id="content"th:text="${blog.content}" style="background-color:transparent;"></div>
This style Attribute represents completely transparent , The background you see is the background of a father element ;
Our previous blog list is not very scientific , Because the new blog appears at the bottom , Usually new blogs are on top , We modified the query statement in the database to find all blogs , add order by postTime desc attribute
9. We implement the function of deleting blogs
1) You can only delete your own blog , For example, A Users cannot delete after logging in B Author's blog
2) We add a delete blog button to the navigation bar in the blog details page , We have clicked on this to delete the blog , It will send a request to the back-end server , Write a Servlet, The server will delete this blog ;
3) If the author of this blog is the user who is currently logged in , Then display the delete button , Otherwise it doesn't show
<a target="_blank" th:if="${showdeleteButton}"th:href="${'deleteblog?blogID='+blog.blogID}"></a>
1) We add such code to the front end , First of all, we must judge whether the current login user is the same as the user of the article author , Just use th:if To judge , If the same , Just put showdeleteButton set true, And display it on the page ; Otherwise, it will be set to false;
2) When we click a When labeling , The parameters passed must be brought blogID In this way, we can use the server in the back according to blogID To delete ;
We are blog2Servlet Code modified in :
webContext.setVariable("showdeleteButton",user.getUserID()==userx.getUserID());
We use deleteblogServlet The code in
import MYSQL.Blog;
import MYSQL.OperateBlog;
import MYSQL.OperateUser;
import MYSQL.User;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import javax.servlet.ServletContext;
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.sql.SQLException;
@WebServlet("/blog2.html")
public class Blog2Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
// Determine whether the current user is logged in
HttpSession session=req.getSession(false);
if(session==null||session.equals(""))
{
System.out.println(" The current user is not logged in ");
// Not logged in
resp.sendRedirect("blog3.html");
return;
}
User userx= (User) session.getAttribute("user");
if(userx==null)
{
System.out.println(" The current user is not logged in ");
// Not logged in
resp.sendRedirect("blog3.html");
return;
}
resp.setContentType("text/html;charset=utf-8");
OperateBlog operateBlog=new OperateBlog();
String blogID=req.getParameter("blogID");
if(blogID==""||blogID.equals(""))
{
String html="<h3>blogID Field deletion </h3>";
resp.getWriter().write(html);
}
Blog blog= null;
try {
blog = operateBlog.SelectOne(Integer.parseInt(blogID));
} catch (SQLException e) {
e.printStackTrace();
}
if(blog==null)
{
String html="<h3> According to blog ID The current blog obtained does not exist </h3>";
resp.getWriter().write(html);
}
ServletContext context=req.getServletContext();
TemplateEngine engine=(TemplateEngine)context.getAttribute("engine");
WebContext webContext=new WebContext(req,resp,context);
OperateUser operateUser=new OperateUser();
try {
User user=operateUser.selectByUserID(blog.getUserID());
webContext.setVariable("user",user);
webContext.setVariable("showdeleteButton",user.getUserID()==userx.getUserID());
} catch (SQLException e) {
e.printStackTrace();
}
webContext.setVariable("blog",blog);
String html=engine.process("blog2",webContext);
resp.getWriter().write(html);
}
}
10. Project summary :
One : Functions that have been implemented :
1) Realize the display of blog list
2) Realize the display of blog details
3) Realized login , User logout , Verification of login status , Display of user information , Writing a blog post , The blog details page can display the rendered markdown effect
4) Realize the function of deleting blog
Two : Functions that are still not implemented
1) User's Avatar function ( Upload your avatar , Different users display different avatars )
2) User gitup Show , At present, it is written dead
3) Support article classification , Create a classification table for the database , Allow users to specify a category when publishing articles
4) Realize editing blog , Modify blog content , Add such a button to the blog details page , Click to enter the blog editing page , Take the content in the blog just now
5) Comment on .......
First modify the front-end code , Then modify the back-end code ;
边栏推荐
- Intelligent supply chain collaboration system solution for daily chemical products industry: digital intelligent SCM supply chain, which is the "acceleration" of enterprise transformation
- Niuke: intercepting missiles
- Assembly language
- dynamic programming
- Thymeleaf common functions
- Disjoint Set
- R language ggplot2 visual density map: Visual density map by group and custom configuration geom_ The alpha parameter in the density function sets the image transparency (to prevent multiple density c
- 外盘入金都不是对公转吗,那怎么保障安全?
- 如何将电脑复制的内容粘贴进MobaXterm?如何复制粘贴
- Matrix chain multiplication dynamic programming example
猜你喜欢
freesurfer运行完recon-all怎么快速查看有没有报错?——核心命令tail重定向
Thymeleaf th:classappend属性追加 th:styleappend样式追加 th:data-自定义属性
Intelligent supply chain collaboration system solution for daily chemical products industry: digital intelligent SCM supply chain, which is the "acceleration" of enterprise transformation
黑马程序员-软件测试-10阶段2-linux和数据库-44-57为什么学习数据库,数据库分类关系型数据库的说明Navicat操作数据的说明,Navicat操作数据库连接说明,Navicat的基本使用,
What are the advantages and characteristics of SAS interface
Which Internet companies are worth going to in Shenzhen for software testers [Special Edition for software testers]
openGauss数据库源码解析系列文章—— 密态等值查询技术详解(下)
Thymeleaf th:classappend attribute append th:styleappend style append th:data- custom attribute
Section - left closed right open
分享 12 个最常用的正则表达式,能解决你大部分问题
随机推荐
Postman简介、安装、入门使用方法详细攻略!
Explain Vue's plan to clean up keepalive cache in time
R language ggplot2 visualization: visual line graph, using legend in theme function The position parameter defines the position of the legend
Qingda KeYue rushes to the science and Innovation Board: the annual revenue is 200million, and it is proposed to raise 750million
Make the seckill Carnival more leisurely: the database behind the promotion (Part 2)
APR protocol and defense
Solution of commercial supply chain collaboration platform in household appliance industry: lean supply chain system management, boosting enterprise intelligent manufacturing upgrading
Postgresql 13 安装
Tidb DM alarm DM_ sync_ process_ exists_ with_ Error troubleshooting
LeetCode_ 69 (square root of x)
外盘入金都不是对公转吗,那怎么保障安全?
Show strength. In this way, the mobile phone will not be difficult to move forward
Chow Tai Fook fulfills the "centenary commitment" and sincerely serves to promote green environmental protection
R language uses the polR function of mass package to build an ordered multi classification logistic regression model, and uses the coef function to obtain the log odds ratio corresponding to each vari
Disjoint Set
R语言ggplot2可视化:可视化折线图、使用theme函数中的legend.position参数自定义图例的位置
Section - left closed right open
乌卡时代下,企业供应链管理体系的应对策略
Catch all asynchronous artifact completable future
Tdengine biweekly selection of community issues | phase III