目录
一、功能和效果
1、实现的功能
2、页面效果
二、功能具体实现
1、数据库
(1)设计数据库
(2)创建数据库表
(3)实现对blogs表和users表的操作并封装
2、登陆功能实现
(1)客户端发送请求
(2)服务器接收请求并做出响应
(3)效果
3、显示博客列表页
(1)客户端发送请求
(2)服务器接收请求并做出响应
(3)客户端收到响应后显示在页面上
(4)效果
4、显示博客详情页
(1)客户端发送请求
(2)服务器接收请求并做出响应
(3)客户端收到响应后显示在页面上
(4)效果
5、显示列表页用户信息
(1)客户端发送请求
(2)服务器接收请求并做出响应
(3)客户端收到响应后显示在页面
(4)效果
6、显示详情页用户信息
(1)客户端发送请求
(2)服务器接收请求并做出响应
(3)客户端收到响应后显示在页面
(4)效果
7、发布博客
(1)客户端发送请求
(2)服务器接收请求并做出响应
(3)效果
8、强制要求登陆
(1)客户端发送请求
(2)服务器接收请求并做出响应
编辑
(3)效果
9、退出登陆
(1)客户端发送请求
(2)服务器处理请求 并做出响应
(3)效果
一、功能和效果
1、实现的功能
登陆功能、显示博客列表页、显示博客详情页、显示列表页用户信息、显示详情页用户信息、强制要求登陆、发布博客、退出登陆。
2、页面效果
(1)登陆
(2)博客列表页
(3)博客详情页
(4)列表页用户信息
(5)详情页用户信息
(5)发布博客
以上markdown编辑器需要引入第三方库editor.md,editor.md需要在github上下载好,放入webapp目录即可。
需注意:以上效果图只是基于前端代码,还未写入后端代码具体实现。
二、功能具体实现
1、数据库
(1)设计数据库
考虑到博客和用户两个实体,设计两张表。blogs表包括博客id、用户id、标题、时间、正文。users表包括用户id、密码、用户名。
(2)创建数据库表
create database if not exists blog_system charset utf8;
use blog_system;
drop table if exists blogs;
create table blogs (
blogid int primary key auto_increment,
useid int,
title varchar(1024),
postTime datetime,
content varchar(4096)
);
drop table if exists users;
create table users(
useid int primary key auto_increment,
username varchar(50) unique,
password varchar(50)
);
insert into blogs values (1 ,1, '这是第一篇博客',now(), '# 从前天开始我要认真写代码');
insert into blogs values (2, 1, '这是第二篇博客', now(), '# 从昨天开始我要认真写代码');
insert into blogs values (3, 1, '这是第三篇博客', now(), '# 从今天开始我要认真写代码');
insert into users values (1, 'gyn', '123');
insert into users values (2, 'gyq', '000');
(3)实现对blogs表和users表的操作并封装
①blog类对应的对象即为blogs表的每条数据
package model;
import java.sql.Timestamp;
public class blog {
private int blogid;
private int useid;
private String title;
private String content;
private Timestamp postTime;
public int getBlogid() {
return blogid;
}
public void setBlogid(int blogid) {
this.blogid = blogid;
}
public int getUseid() {
return useid;
}
public void setUseid(int useid) {
this.useid = useid;
}
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 Timestamp getPostTime() {
return postTime;
}
public void setPostTime(Timestamp postTime) {
this.postTime = postTime;
}
@Override
public String toString() {
return "blog{" +
"blogid=" + blogid +
", useid=" + useid +
", title='" + title + '\'' +
", content='" + content + '\'' +
", postTime=" + postTime +
'}';
}
}
②user类对应的对象即为user表中的每条数据
package model;
public class user {
private int useid;
private String username;
private String password;
public int getUseid() {
return useid;
}
public void setUseid(int useid) {
this.useid = useid;
}
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;
}
@Override
public String toString() {
return "user{" +
"useid=" + useid +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
③建立数据库连接和释放资源
获取数据源时,可以考虑使用单例模式中的懒汉模式。又考虑到懒汉模式是线程不安全的,且一个服务器会处理不同客户端的请求,所以需要加锁。
package model;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBUtil {
private static volatile DataSource dataSource=null;
public static DataSource getdataSource(){ //获得数据源
if(dataSource==null){
synchronized (DBUtil.class){
if (dataSource==null){
dataSource=new MysqlDataSource();
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/blog_system?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("272222");
}
}
}
return dataSource;
}
public static Connection getConnection() throws SQLException { //建立连接
return getdataSource().getConnection();
}
//释放资源
public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){
if(resultSet==null){
try {
resultSet.close();
}catch (SQLException e){
throw new RuntimeException();
}
}
if(preparedStatement==null){
try {
preparedStatement.close();
}catch (SQLException e){
throw new RuntimeException();
}
}
if(connection!=null){
try {
connection.close();
}catch (SQLException e){
throw new RuntimeException();
}
}
}
}
④针对blogs表的一些操作
获取blogs表全部信息 -- 显示博客列表页;
根据blogid查找博客 -- 显示博客详情页;
增加博客 -- 发布博客。
package model;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class blogDo {
//获取blog表全部信息--显示博客列表页需要
public List<blog> getblogs(){
List<blog> list=new ArrayList<>();
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try {
connection=DBUtil.getConnection();
String sql="select * from blogs order by postTime desc"; //根据时间降序
preparedStatement=connection.prepareStatement(sql);
resultSet=preparedStatement.executeQuery();
while (resultSet.next()){
blog blog1=new blog();
blog1.setBlogid(resultSet.getInt("blogid"));
blog1.setUseid(resultSet.getInt("useid"));
blog1.setPostTime(resultSet.getTimestamp("postTime"));
blog1.setTitle(resultSet.getString("title"));
blog1.setContent(resultSet.getString("content"));
if(blog1.getContent().length()>=20){ //
blog1.setContent(blog1.getContent().substring(0,21)+"......");
}
list.add(blog1);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(connection,preparedStatement,resultSet);
}
return list;
}
//根据blogid查找blog信息--显示博客详情页需要
public blog getblog(int blogid){
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
blog blog1=new blog();
try {
connection=DBUtil.getConnection();
String sql="select * from blogs where blogid=?";
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setInt(1,blogid);
resultSet=preparedStatement.executeQuery();
if(resultSet.next()){
blog1.setContent(resultSet.getString("content"));
blog1.setTitle(resultSet.getString("title"));
blog1.setPostTime(resultSet.getTimestamp("postTime"));
blog1.setUseid(resultSet.getInt("useid"));
blog1.setBlogid(resultSet.getInt("blogid"));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(connection,preparedStatement,resultSet);
}
return blog1;
}
//增加blog--发布博客需要
public void addblog(blog blog1){
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try {
connection=DBUtil.getConnection();
String sql="insert into blogs values(null,?,?,now(),?)";
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setInt(1,blog1.getUseid());
preparedStatement.setString(2,blog1.getTitle());
preparedStatement.setString(3,blog1.getContent());
preparedStatement.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(connection,preparedStatement,resultSet);
}
}
}
⑤针对users表的一些操作
根据username获取用户信息 --博客列表页显示用户信息;
根据useid获取用户信息 --博客详情页显示用户信息;
根据username获取密码 --登陆检验密码是否正确。
package model;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class userDo {
//1、根据username获取用户信息 --博客列表页显示用户信息
public user getuser(String username){
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
user user1=new user();
try {
connection=DBUtil.getConnection();
String sql="select * from users where username=?";
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setString(1,username);
resultSet=preparedStatement.executeQuery();
if(resultSet.next()){
user1.setUseid(resultSet.getInt("useid"));
user1.setUsername(resultSet.getString("username"));
user1.setPassword(resultSet.getString("password"));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return user1;
}
//2、根据useid获取用户信息 -- 博客详情页显示用户信息
public user getuser(int useid){
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
user user1=new user();
try {
connection=DBUtil.getConnection();
String sql="select * from users where useid=?";
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setInt(1,useid);
resultSet=preparedStatement.executeQuery();
if(resultSet.next()){
user1.setUseid(resultSet.getInt("useid"));
user1.setUsername(resultSet.getString("username"));
user1.setPassword(resultSet.getString("password"));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(connection,preparedStatement,resultSet);
}
return user1;
}
//3、根据username获取用户密码 -- 登陆需要
public String getpassword(String username){
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
String password=null;
try {
connection=DBUtil.getConnection();
String sql="select * from users where username=?";
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setString(1,username);
resultSet=preparedStatement.executeQuery();
if(resultSet.next()){
password=(resultSet.getString("password"));
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(connection,preparedStatement,resultSet);
}
return password;
}
}
2、登陆功能实现
(1)客户端发送请求
请求路径:/login,方法为post,内容为form表单形式
username="username"&password="password"
(2)服务器接收请求并做出响应
(3)效果
3、显示博客列表页
(1)客户端发送请求
请求路径:/blog;方法:get方法;格式:json
(2)服务器接收请求并做出响应
(3)客户端收到响应后显示在页面上
类似前端这种效果:
代码实现:
(4)效果
发现时间的格式是按时间戳的形式,不是按年--月--日的格式,得调整。需要确定是不是服务器做出响应时就是时间戳的形式。
抓包响应的正文:
抓包发现服务器做出响应的正文就是按时间戳的形式,得修改数据库该属性的返回形式。Java 标准库提供了一个 SimpleDateFormat 类, 完成时间戳到格式化时间的转换
4、显示博客详情页
(1)客户端发送请求
请求路径:/blog?blogid="blogid";请求方法:get;请求格式:json
查看全文时,跳转到一个链接:
博客详情页发送get请求时包含blogid
(2)服务器接收请求并做出响应
(3)客户端收到响应后显示在页面上
类似前端这种效果:
实现代码:
(4)效果
发现上面显示的内容不是按照md后的格式,而是md的原始数据,需要渲染为html
引入editor库:
改变html的正文标签内容:
效果图:
5、显示列表页用户信息
(1)客户端发送请求
显示博客列表页的同时也要显示列表页用户信息。
请求路径:/userinfo;请求方式:get;请求类型:json。
(2)服务器接收请求并做出响应
(3)客户端收到响应后显示在页面
只需改变前端代码的用户名
实现代码:
(4)效果
登陆gyq账号:
6、显示详情页用户信息
(1)客户端发送请求
显示博客详情页的同时也要显示详情页用户信息。
请求路径:/autherinfo;请求方式:get;请求类型:json。
(2)服务器接收请求并做出响应
(3)客户端收到响应后显示在页面
(4)效果
7、发布博客
(1)客户端发送请求
点击“写博客”按钮时,页面会跳转,在跳转页面发送请求。
请求路径:/blogs;请求方法:post;请求类型:form;title="title"&content="content";
(2)服务器接收请求并做出响应
(3)效果
8、强制要求登陆
在进入页面时,要求用户必须登陆,每个页面发送请求判断是否已经登陆,没有登陆跳转到登陆页面进行登陆。
(1)客户端发送请求
请求路径:/force;请求方法:get;请求类型:json;
(2)服务器接收请求并做出响应
(3)效果
在未登陆情况下点击主页或写文章都会跳转到博客登录页面。
9、退出登陆
(1)客户端发送请求
点击注销会跳转到logout路径下,发起请求
(2)服务器处理请求 并做出响应
(3)效果
点击注销按钮,页面会跳转到博客登录页面。