目录
准备工作
创建用户类博客类与连接数据库
创建博客类
创建用户类
创建连接数据库工具类
实现对数据库数据博客的操作
实现对数据库用户的操作
创建数据库语句
登录页面
前端
后端
博客列表
前端
注销登录
写入数据
判断用户是否登录
替换页面用户昵称
后端
处理注销登录 LogoutServlet/doGet
处理获取所有博客 BlogServlet/doGet
处理判断用户是否登录 loginServlet/doGet
处理替换页面用户昵称 UserinfoServlet/doGet
博客详情页
前端
注销登录
查询博客
判断用户是否登录
将博客详情页昵称替换为当前博客作者昵称/是否显示删除博客
后端
处理注销登录 LogoutServlet/doGet
处理查询博客 BlogServlet/doGet
处理判断用户是否登录 LoginServlet/doGet
处理将博客详情页昵称替换为当前博客作者昵称/是否显示删除博客 UserinfoServlet/doGet
博客编辑页
前端
后端 BlogServlet/doPost
部署
准备工作
下载jdk
下载tomcat
加权限
安装mysql
使用maven打包
访问
准备工作
在main下创建webapp文件夹下再创建WEB-INF文件夹下再创建web.xml文件
web.xml
Archetype Created Web Application
需要用到
- javaservlet3.1
- jackson 版本随意
- mysql 根据你的mysql版本
这些均在Maven Repository: Search/Browse/Explore (mvnrepository.com)网址内下载
之后复制代码粘贴到pom.xml下的 标签内,并且设置打包格式为war这是tomcat要求的(之后部署需要使用),再设置包名
javax.servlet
javax.servlet-api
3.1.0
provided
com.fasterxml.jackson.core
jackson-databind
2.13.5
com.mysql
mysql-connector-j
8.0.33
war
blog_system
创建用户类博客类与连接数据库
创建博客类
博客包含
- 博客ID
- 博客标题
- 博客内容
- 创建它的作者ID
- 发布博客的时间
之后ALT+Insert生成Get和Set方法(时间的get方法有所改变,需要格式化为日期格式)
package model;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.SimpleTimeZone;
//表示博客
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 String getPostTime() {
//把时间戳构造成日期结构
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(this.postTime);
}
public void setPostTime(Timestamp postTime) {
this.postTime = postTime;
}
}
创建用户类
- 用户包含
- 用户ID
- 用户名称
- 用户密码
- 判定该博客是否是登录用户的博客(后续删除博客功能需要用到、此变量不会写入数据库)
生成Get、Set方法
package model;
//表示用户
public class User {
private int userId;
private String username;
private String password;
private int isYourBlog=0;
public int getIsYourBlog() {
return isYourBlog;
}
public void setIsYourBlog(int isYourBlog) {
this.isYourBlog = isYourBlog;
}
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;
}
}
创建连接数据库工具类
获取数据库连接 管理数据库的创建配置和管理
package model;
import com.mysql.cj.jdbc.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBUtil {
//定义私有静态的DataSource对象,用于存储数据库连接信息。
//volatile确保了对这个变量的读写操作都是原子性的,即使再多线程环境下
//对这个变量访问也是线程安全的
private volatile static DataSource dataSource=null;
//获取数据库连接 管理数据库的创建、配置和管理
private static javax.sql.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("monan1946");
}
}
}
return dataSource;
}
//这个方法是从DataSource获取一个具体的数据库连接
//它通常在需要执行数据库操作时调用,比如执行SQL查询或更新
public static Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
//关闭数据库连接
public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
if (resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
实现对数据库数据博客的操作
与数据库连接后,查询数据库,插入数据,删除数据操作
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;
//import static jdk.nashorn.internal.objects.NativeString.substring;
//Dao Data Access Object 用来访问数据的对象
//针对博客的增删改查
public class BlogDao {
//插入博客
public void insert(Blog blog){
Connection connection=null;
PreparedStatement statement=null;
try {
//与数据库建立连接
connection = DBUtil.getConnection();
//构造SQL语句
String sql = "insert into blog values(null,?,?,?,now())";
//写入sql语句
statement = connection.prepareStatement(sql);
//写入问号对应的数据
statement.setString(1, blog.getTitle());
statement.setString(2, blog.getContent());
statement.setInt(3, blog.getUserId());
//执行sql
int ret = statement.executeUpdate();
if (ret == 1) {
System.out.println("插入成功");
} else {
System.out.println("插入失败");
}
}catch (SQLException e) {
e.printStackTrace();
}finally {
//关闭连接
DBUtil.close(connection,statement,null);
}
}
//查询所有博客
public List selectAll(){
Connection connection=null;
PreparedStatement statement=null;
ResultSet resultSet=null;
List blogs=new ArrayList();
try {
//与数据库建立连接
connection=DBUtil.getConnection();
//构造sql
//让新的先读取 页面新的在最上面
String sql="select * from blog order by postTime desc";
//写入sql
statement=connection.prepareStatement(sql);
//执行SQL
resultSet=statement.executeQuery();
//遍历结果集合
while (resultSet.next()){
Blog blog=new Blog();
blog.setBlogId(resultSet.getInt("blogId"));
blog.setTitle(resultSet.getString("title"));
String content=resultSet.getString("content");
// //如果长度大于100时,只截取100个字符作为摘要
if(content.length()>100){
content=content.substring(0,100);
}
//如果不大于100 不截取
blog.setContent(content);
blog.setUserId(resultSet.getInt("userId"));
blog.setPostTime(resultSet.getTimestamp("postTime"));
blogs.add(blog);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//关闭连接
DBUtil.close(connection,statement,resultSet);
}
return blogs;
}
//查询一篇博客
public Blog selectOne(int blogId) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
// 1. 和数据库建立连接
connection = DBUtil.getConnection();
// 2. 构造 SQL
String sql = "select * from blog where blogId = ?";
statement = connection.prepareStatement(sql);
statement.setInt(1, blogId);
// 3. 执行 SQL
resultSet = statement.executeQuery();
// 4. 遍历结果集. 由于是按照 blogId 来查询. blogId 是自增主键, 不能重复.
// 此处的查询结果不可能是多条记录. 只能是 1 条或者 0 条.
if (resultSet.next()) {
Blog blog = new Blog();
blog.setBlogId(resultSet.getInt("blogId"));
blog.setTitle(resultSet.getString("title"));
blog.setContent(resultSet.getString("content"));
blog.setPostTime(resultSet.getTimestamp("postTime"));
blog.setUserId(resultSet.getInt("userId"));
return blog;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 5. 关闭资源
DBUtil.close(connection, statement, resultSet);
}
return null;
}
//删除博客
public void delete(int blogId){
Connection connection=null;
PreparedStatement statement=null;
ResultSet resultSet=null;
try {
//建立连接
connection =DBUtil.getConnection();
//构造SQL语句
String sql="delete from blog where blogId=?";
服务器托管//写入sql
statement=connection.prepareStatement(sql);
//替换?
statement.setInt(1,blogId);
//执行sql
int ret=statement.executeUpdate();
if(ret==1){
System.out.println("删除成功");
}
else{
System.out.println("删除失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,null);
}
}
}
实现对数据库用户的操作
对数据库内的数据进行操作
package model;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//Dao Data Access Object 用来访问数据的对象
//针对用户的增删改查
public class UserDao {
//查询用户
public User selectByName(String username){
Connection connection=null;
PreparedStatement statement=null;
ResultSet resultSet=null;
try {
//建立连接
connection=DBUtil.getConnection();
//构造sql语句
String sql="select * from user where username=?";
//写入sql
statement=connection.prepareStatement(sql);
//填入问号
statement.setString(1,username);
//执行sql
resultSet=statement.executeQuery();
if(resultSet.next()){
User user=new User();
user.setUserId(resultSet.getInt("userId"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
return user;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
return null;
}
public User selectById(int userId){
Connection connection=null;
PreparedStatement statement=null;
ResultSet resultSet=null;
try {
//建立连接
connection=DBUtil.getConnection();
//构造sql语句
String sql="select * from user where userId=?";
//写入sql
statement=connection.prepareStatement(sql);
//填入问号
statement.setInt(1,userId);
//执行sql
resultSet=statement.executeQuery();
if(resultSet.next()){
User user=new User();
user.setUserId(resultSet.getInt("userId"));
user.setUse服务器托管rname(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
return user;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
return null;
}
}
创建数据库语句
需要把创建数据库的语句放入db.sql中,方便后续更换数据库使用
create database blog_system;
use blog_system;
create table blog(
blogId int primary key auto_increment, --主键 自增 博客ID
title varchar(1024), --博客标题
content mediumtext, --博客正文 mediutext类型很长
userId int, --作者id
postTime datetime --发布事件
);
create table blog(
blogId int primary key auto_increment,
title varchar(1024),
content mediumtext,
userId int,
postTime datetime
);
create table user(
userId int primary key auto_increment, --用户id
username varchar(128) unique , --用户名
password varchar(128) --密码
);
create table user(
userId int primary key auto_increment,
username varchar(128) unique ,
password varchar(128)
);
登录页面
前端
login/loginServlet
前端将用户写入的数据已post方法提交给后端
登录页
登录
用户名
密码
后端
- 后端调用doPost方法
- 使用resp.getParameter方法获取数据
- 去数据库内查询数据。
- 查询不到则响应登录失败
- 若查询到时,创建session HttpSession session= req.getSession()
- 也就是浏览器内的cookie session.setAttribute把此用户存储进去,方便后续使用之后登录成功跳转至博客列表
package controller;
import model.User;
import model.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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class loginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//告诉servlet(服务器)按照utf格式解析请求中的body
//如果不使用这个 中文格式的会乱码
req.setCharacterEncoding("utf8");
//告诉浏览器 按照utf8格式解析响应
// resp.setCharacterEncoding("utf8");
resp.setContentType("text/html;charset=utf8");
String username=req.getParameter("username");
String password=req.getParameter("password");
// System.out.println(username);
// System.out.println(password);
// if(username.equals("user")&&password.equals("123")){
// resp.getWriter().write("登录成功");
// }
// else
// {
// resp.getWriter().write("用户名或密码错误");
// }
UserDao userDao=new UserDao();
User user=userDao.selectByName(username);
if(user==null){
resp.getWriter().write("用户名或密码错误");
return;
}
if(!user.getPassword().equals(password)){
resp.getWriter().write("用户名或密码错误");
return;
}
//到这里就是登录成功了
//构造会话 cookie
HttpSession session= req.getSession();
//把信息存到cookie内,方便后续使用
session.setAttribute("user",user);
//登录成功后 跳转页面
resp.sendRedirect("blog_list.html");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//验证登录状态
//如果用户未登录,强制重定向到登录页面
//如果用户已登录,不做动作
//取查询session
HttpSession session=req.getSession(false);
if(session==null){
//如果连session都没有 返回403状态码
//403状态码就是代表用户未登录的状态码
resp.setStatus(403);
return;
}
//取cookie查找是否有user这个用户
//这个user不是用户名 而是user内的用户名
User user= (User) session.getAttribute("user");
if(user==null){
//没有这个用户,说明未登录
resp.setStatus(403);
return;
}
//到这说明用户已经登录成功
resp.setStatus(200);
}
}
博客列表
前端
前端使用ajax方法,所以需要引入jquery
jquery需要从jQuery CDN链接内点击minified 复制
https://code.jquery.com/jquery-3.7.1.min.js
之后引入即可使用
前端整体代码
墨轩博客页
墨轩111
github链接
文章
分类
2
3
function getBlogs(){
//构造ajax
$.ajax({
type:'get',
url:'blog',
success: function(body){
let container=document.querySelector('.container-right');
//后端返回的是json数据
//如果Content-Type是application/json,jquery ajax会把body转成js对象
for(let blog of body){
//构造最外层的div
let blogDiv=document.createElement('div');
blogDiv.className='blog';
//创建博客标题
let titleDiv=document.createElement('div');
titleDiv.className='title';
//把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值
titleDiv.innerHTML=blog.title;
//把titleDiv添加在blogDiv内
blogDiv.appendChild(titleDiv);
//创建日期
let dateDiv=document.createElement('div');
dateDiv.className='date';
//把后端传来的json,被jackson解析成blog对象 对象内的时间属性赋值
dateDiv.innerHTML=blog.postTime;
//把dateDiv添加到blogDiv内
blogDiv.appendChild(dateDiv);
//创建内容
let descDiv=document.createElement('div');
descDiv.className='desc';
//把把后端传来的json,被jackson解析成blog对象 对象内的内容属性赋值
descDiv.innerHTML=blog.content;
//把descDiv添加到blogDiv内
blogDiv.appendChild(descDiv);
//创建按钮
let a=document.createElement('a');
a.innerHTML='查看全文 >>';
//传递这篇博客的ID是多少 后端才能取查询这篇博客的详细页
a.href='blog_detail.html?blogId='+blog.blogId;
blogDiv.appendChild(a);
//把blogDiv添加到container内
container.appendChild(blogDiv);
}
}
});
}
getBlogs();
//使用ajax构造get方法。判断当前是否用户
// 如果没登陆,强制跳转到登录页面
checkLogin();
//将博客列表的昵称替换为当前登录用户的昵称
function GetUser(){
$.ajax({
type: 'get',
url:'userInfo',
//后端查询失败时,发送状态码为403 403不会触发回调函数
success:function (body){
//将登录的用户名替换上去
let user=document.querySelector('.card h2');
user.innerHTML=body.username;
}
});
}
GetUser();
注销登录
注意:注销登录和注销账号是不同的,注销登录即退出登录,而注销账户是删除账号
注销
写入数据
- 前端构造ajax构造get方法,发送给后端。
- 调用回调函数。
- 遍历后端传来的数据(想要用遍历,那么后端传来的数据一定是像List这种可遍历的,如何只传来的对象,那就无法遍历)
- 创建div 分别把博客的标题,时间,内容创建,把后端数据都写入。并且创建查询博客详情页的按键。当按下这个按键时,会把博客ID传递给博客详情页,详情页就能拿着这个ID去后端查询此博客
- 把整体div放入原先的div内
function getBlogs(){
//构造ajax
$.ajax({
type:'get',
url:'blog',
success: function(body){
let container=document.querySelector('.container-right');
//后端返回的是json数据
//如果Content-Type是application/json,jquery ajax会把body转成js对象
for(let blog of body){
//构造最外层的div
let blogDiv=document.createElement('div');
blogDiv.className='blog';
//创建博客标题
let titleDiv=document.createElement('div');
titleDiv.className='title';
//把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值
titleDiv.innerHTML=blog.title;
//把titleDiv添加在blogDiv内
blogDiv.appendChild(titleDiv);
//创建日期
let dateDiv=document.createElement('div');
dateDiv.className='date';
//把后端传来的json,被jackson解析成blog对象 对象内的时间属性赋值
dateDiv.innerHTML=blog.postTime;
//把dateDiv添加到blogDiv内
blogDiv.appendChild(dateDiv);
//创建内容
let descDiv=document.createElement('div');
descDiv.className='desc';
//把把后端传来的json,被jackson解析成blog对象 对象内的内容属性赋值
descDiv.innerHTML=blog.content;
//把descDiv添加到blogDiv内
blogDiv.appendChild(descDiv);
//创建按钮
let a=document.createElement('a');
a.innerHTML='查看全文 >>';
//传递这篇博客的ID是多少 后端才能取查询这篇博客的详细页
a.href='blog_detail.html?blogId='+blog.blogId;
blogDiv.appendChild(a);
//把blogDiv添加到container内
container.appendChild(blogDiv);
}
}
});
}
getBlogs();
判断用户是否登录
因为这个功能是多个页面都会使用,所以写入js文件内,在前面引入js即可调用这个方法
//使用ajax构造get方法。判断当前是否用户
// 如果没登陆,强制跳转到登录页面
checkLogin();
这个在js内的app.js文件
function checkLogin(){
$.ajax({
type: 'get',
url:'login',
success:function (){
// 当客户端响应200状态码时,说明用户已登录,不做处理
},
error:function (){
//发客户端响应403时 就会触发error
//强制跳转登录页面
location.assign('login.html');
}
})
}
替换页面用户昵称
向后端发起get方法,把页面昵称替换为当前登录用户的昵称
function GetUser(){
$.ajax({
type: 'get',
url:'userInfo',
//后端查询失败时,发送状态码为403 403不会触发回调函数
success:function (body){
//将登录的用户名替换上去
let user=document.querySelector('.card h2');
user.innerHTML=body.username;
}
});
}
GetUser();
后端
处理注销登录 LogoutServlet/doGet
- req.getSession查询是否创建了session
- 使用session.removeAttribute删除session的当前的用户
- resp.sendRedirect强制跳转到登录页面
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//注销功能
//删除session中的对象 就相当于取消状态
//查找是否有session
HttpSession session=req.getSession(false);
if(session==null) {
resp.setStatus(403);
return;
}
//删除session中的user
session.removeAttribute("user");
//重定向到登录页面
resp.sendRedirect("login.html");
}
}
处理获取所有博客 BlogServlet/doGet
- 想要构造JSON格式,就得创建ObjectMapper
- 因为前端使用的是ajax,后端需要响应json格式。所以需要用resp.setContentType设置响应格式 (application/json;charset=utf8)
- 创建操作博客内容的数据库类
- 查看req.getParameter获取前端是否传来了博客ID,如果传来了,说明前端想要查询单个博客(这里是博客详情页,后续讲)
- 如果没传博客ID,说明前端想要查询所有博客,博客列表是查询所有博客
- 调用blogDo查询博客类,查询所有博客,并且把这些数据放入List,保证所有博客可以遍历。
- 使用objectMapper.writeValueAsString将数据构造成json格式
- 响应数据
@Override
//发送博客列表或博客详情页的内容
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//想要构造JSON格式,就得用到此类
private ObjectMapper objectMapper=new ObjectMapper();
resp.setContentType("application/json;charset=utf8");
//要拿到写数据库操作的类
BlogDao blogDao=new BlogDao();
//获取url中的博客ID
String blogId=req.getParameter("blogId");
System.out.println(blogId);
//为空时 说明时获取博客列表,而不是获取博客详情
if(blogId==null){
//查询所有 返回的是list 每个类型是一个博客类型
List blogs=blogDao.selectAll();
//转成json格式
String jsonString=objectMapper.writeValueAsString(blogs);
//响应
resp.getWriter().write(jsonString);
}else{
//如果获取到博客ID时,说明时获取博客详情页
//使用数据库查找这个博客ID
Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
//记住,传json格式,如果你要用for循环 那么你的对象一定要是可迭代的对象
//如果你单构造个类过去,你用for是肯定循环不了的,你必须使用List这种可以迭代的对象,才能使用这个迭代循环
List blogs=new ArrayList();
blogs.add(blog);
//你也可以单传个对象 到前端那不用循环直接使用也可以
// List blogs=new ArrayList();
// String jsonString=objectMapper.writeValueAsString(blog);
//转为json格式
String jsonString=objectMapper.writeValueAsString(blogs);
//响应
resp.getWriter().write(jsonString);
}
}
处理判断用户是否登录 loginServlet/doGet
- req.getSession查询是否创建了session(这里可以直接判断用户是否登录了,因为只要登录,那么就一定创建了session
- 为空时,resp.setStatus响应状态码403
- 如果不为空时,session.getAttribute查询session是否有该用户
- 如果为空,则有创建session,但没有此用户,setStatus响应状态码403
- 如果也不为空,说明该用户以及登录,setStatus响应状态码200
- 响应状态码403是为了不让前端调用回调函数,当返回200时,才调用
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//验证登录状态
//如果用户未登录,强制重定向到登录页面
//如果用户已登录,不做动作
//取查询session
HttpSession session=req.getSession(false);
if(session==null){
//如果连session都没有 返回403状态码
//403状态码就是代表用户未登录的状态码
resp.setStatus(403);
return;
}
//取cookie查找是否有user这个用户
//这个user不是用户名 而是user内的用户名
User user= (User) session.getAttribute("user");
if(user==null){
//没有这个用户,说明未登录
resp.setStatus(403);
return;
}
//到这说明用户已经登录成功
resp.setStatus(200);
}
处理替换页面用户昵称 UserinfoServlet/doGet
- 想要构造JSON格式,就得创建此类objectMapper
- req.getParameter获取blogId(如果为空,则是博客列表发来的,想要获取此博客的用户名,如果不为空,是博客详情页发来的,判断此博客是否是当前登录用户的博客)
- req.getSession判断是否有session
- session.getAttribute 查询session是否有该用户,获取此用户
- 当blogId为空时,博客列表发来的
- 首先用户的密码设为空串 (不是修改数据库内的数据)
- resp.setContentType设置响应格式
- objectMapper.writeValueAsString数据构造为JSON格式
- 响应数据
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//想要构造json 就要创建这个类
ObjectMapper objectMapper=new ObjectMapper();
String blogid=req.getParameter("blogId");
//直接取查找是否有cookie
HttpSession session=req.getSession(false);
if(session==null){
//后端查询失败时,发送状态码为403 403不会触发回调函数
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("没有该用户");
return;
}
//获取当前登录用户
User user= (User) session.getAttribute("user");
if(user==null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("没有该用户");
return;
}
if(blogid==null){
//查询登录的用户
//当url中的查询字符串中没有blogId时,说明是博客列表发来的请求
//不用让密码在body中明文显示
user.setPassword("");
resp.setContentType("application/json;charset=utf8");
//构造成json格式
//返回登录的用户
String jsonString=objectMapper.writeValueAsString(user);
//写入
resp.getWriter().write(jsonString);
博客详情页
前端
总体
博客详情页
墨轩111
github链接
文章
分类
2
3
function getBlogs() {
//构造ajax
$.ajax({
type: 'get',
//博客列表传来的
url: 'blog' + location.search,
success: function (body) {
let container = document.querySelector('.container-right');
//后端返回的是json数据
//如果Content-Type是application/json,jquery ajax会把body转成js对象
for (let blog of body) {
//构造最外层的div
let blogDiv = document.createElement('div');
blogDiv.className = 'blog';
//创建博客标题
let titleDiv = document.createElement('div');
titleDiv.className = 'title';
//把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值
titleDiv.innerHTML = blog.title;
//把titleDiv添加在blogDiv内
blogDiv.appendChild(titleDiv);
//创建日期
let dateDiv = document.createElement('div');
dateDiv.className = 'date';
//把后端传来的json,被jackson解析成blog对象 对象内的时间属性赋值
dateDiv.innerHTML = blog.postTime;
//把dateDiv添加到blogDiv内
blogDiv.appendChild(dateDiv);
//创建内容
let descDiv = document.createElement('div');
descDiv.className = 'desc';
//把把后端传来的json,被jackson解析成blog对象 对象内的内容属性赋值
descDiv.innerHTML = blog.content;
//把descDiv添加到blogDiv内
blogDiv.appendChild(descDiv);
//把blogDiv添加到container内
container.appendChild(blogDiv);
}
}
});
}
getBlogs();
checkLogin();
function GetUser(){
$.ajax({
type: 'get',
url:'userInfo'+location.search,//加个博客ID 让后端查找这篇博客
success:function (body){
//将这篇作者的用户名替换上去
let user=document.querySelector('.card h2');
user.innerHTML=body.username;
//当这篇博客是当前用户的 那么就显示删除按钮
if(body.isYourBlog){
let delet=document.createElement('a');
delet.className="delete";
delet.innerHTML="删除博客"
delet.href='blogdelete'+location.search;
let de=document.querySelector('.dete');
de.appendChild(delet);
}
}
});
}
GetUser();
注销登录
与博客列表一致这里不再赘述
查询博客
- 构造ajax的get方法,url是博客列表传来的博客ID,传给后端,后端才能根据这个ID查询博客
- 后端传来了数据,只要是json格式(application/json;charset=utf8)那么ajax就会把body转成js的对象。
- 创建div,分别把博客的标题、时间、内容写入
function getBlogs() {
//构造ajax
$.ajax({
type: 'get',
//博客列表传来的
url: 'blog' + location.search,
success: function (body) {
let container = document.querySelector('.container-right');
//后端返回的是json数据
//如果Content-Type是application/json,jquery ajax会把body转成js对象
for (let blog of body) {
//构造最外层的div
let blogDiv = document.createElement('div');
blogDiv.className = 'blog';
//创建博客标题
let titleDiv = document.createElement('div');
titleDiv.className = 'title';
//把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值
titleDiv.innerHTML = blog.title;
//把titleDiv添加在blogDiv内
blogDiv.appendChild(titleDiv);
//创建日期
let dateDiv = document.createElement('div');
dateDiv.className = 'date';
//把后端传来的json,被jackson解析成blog对象 对象内的时间属性赋值
dateDiv.innerHTML = blog.postTime;
//把dateDiv添加到blogDiv内
blogDiv.appendChild(dateDiv);
//创建内容
let descDiv = document.createElement('div');
descDiv.className = 'desc';
//把把后端传来的json,被jackson解析成blog对象 对象内的内容属性赋值
descDiv.innerHTML = blog.content;
//把descDiv添加到blogDiv内
blogDiv.appendChild(descDiv);
//把blogDiv添加到container内
container.appendChild(blogDiv);
}
}
});
}
getBlogs();
判断用户是否登录
这个与博客列表页一样,这里不再赘述
将博客详情页昵称替换为当前博客作者昵称/是否显示删除博客
- 构造ajax的get方法,url传入博客列表传来的博客ID
- 获取数据后,将后端的数据写入昵称
- 判断isYourBlog是否为1 (1是说明当前登录用户的ID与博客ID相同(此篇博客是当前用户写的),说明当前用户有支配此篇博客的权利,显示删除博客 0说明当前登录用户的ID与博客ID不同(此篇博客不是当前用户写的,没有支配全,不显示删除博客)
- 为1时,创建a标签,命名为删除博客,链接到删除博客的后端,并且传入博客ID
- 再放入原先的div
function GetUser(){
$.ajax({
type: 'get',
url:'userInfo'+location.search,//加个博客ID 让后端查找这篇博客
success:function (body){
//将这篇作者的用户名替换上去
let user=document.querySelector('.card h2');
user.innerHTML=body.username;
//当这篇博客是当前用户的 那么就显示删除按钮
if(body.isYourBlog){
let delet=document.createElement('a');
delet.className="delete";
delet.innerHTML="删除博客"
delet.href='blogdelete'+location.search;
let de=document.querySelector('.dete');
de.appendChild(delet);
}
}
});
}
GetUser();
后端
处理注销登录 LogoutServlet/doGet
这里与博客列表一致,不再赘述
处理查询博客 BlogServlet/doGet
- resp.setContentTyoe设置响应格式 (application/json;charset=utf8)
- 创建操作博客类
- req.getParameter获取前端传来的博客ID
- 这里是查询单个博客,所以是不为空的
- 将博客ID转为int 并且从数据库内查询
- 将博客放入List(这里最好不用放入List,因为只是单个博客,不需要迭代,我只是演示)
- objectMapper.writeVlueAsString构造成JSON格式
- 响应数据
else{
resp.setContentType("application/json;charset=utf8");
//如果获取到博客ID时,说明时获取博客详情页
//使用数据库查找这个博客ID
String blogId=req.getParameter("blogId");
Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
//记住,传json格式,如果你要用for循环 那么你的对象一定要是可迭代的对象
//如果你单构造个类过去,你用for是肯定循环不了的,你必须使用List这种可以迭代的对象,才能使用这个迭代循环
List blogs=new ArrayList();
blogs.add(blog);
//你也可以单传个对象 到前端那不用循环直接使用也可以
// List blogs=new ArrayList();
// String jsonString=objectMapper.writeValueAsString(blog);
//转为json格式
String jsonString=objectMapper.writeValueAsString(blogs);
//响应
resp.getWriter().write(jsonString);
}
处理判断用户是否登录 LoginServlet/doGet
这里是与博客列表是一样的,就不再赘述
处理将博客详情页昵称替换为当前博客作者昵称/是否显示删除博客 UserinfoServlet/doGet
- 创建要构造JSON的类
- resp.getParameter获取blogId
- req.GetSession查询是否有session
- session.getAttribute获取session是否有该用户
- 数据库中查询此篇博客
- 数据中查询用户类是否有此篇博客的作者
- 当都有时,判断当前session的用户ID与此篇博客的ID是否相同(相同时,用户类的isyourblog设置1反之设置0)
- 响应时,把用户密码设置为0不要名为显示,不修改数据库的数据
- resp.setContentType设置响应格式
- objectMapper.writeValueAsString构造为JSON格式
- 响应
//想要构造json 就要创建这个类
ObjectMapper objectMapper=new ObjectMapper();
String blogid=req.getParameter("blogId");
//直接取查找是否有cookie
HttpSession session=req.getSession(false);
if(session==null){
//后端查询失败时,发送状态码为403 403不会触发回调函数
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("没有该用户");
return;
}
//获取当前登录用户
User user= (User) session.getAttribute("user");
if(user==null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("没有该用户");
return;
}
else{
//查询这篇博客的作者
//如果有blogId时,说明是博客详情页发来的请求
BlogDao blogDao=new BlogDao();
Blog blog=blogDao.selectOne(Integer.parseInt(blogid));
if(blog==null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("没有该用户");
return;
}
UserDao userDao=new UserDao();
//用博客类里的用户id 去用户类去查询 查询用户是否有这个博客作者
User author=userDao.selectById(blog.getUserId());
if(author==null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("没有该用户");
return;
}
if(author.getUserId()== user.getUserId()){
author.setIsYourBlog(1);
}else {
author.setIsYourBlog(0);
}
//不用让密码在body中明文显示
user.setPassword("");
resp.setContentType("application/json;charset=utf8");
String jsonString=objectMapper.writeValueAsString(author);
//返回这篇博客的作者
resp.getWriter().write(jsonString);
}
博客编辑页
前端
通过from表单提交标题,内容
博客编辑页
// 初始化编辑器
var editor = editormd("editor", {
// 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉.
width: "100%",
// 设定编辑器高度
height: "calc(100% - 50px)",
// 编辑器中的初始内容
markdown: "# 在这里写下一篇博客",
// 指定 editor.md 依赖的插件路径
path: "editor.md/lib/",
// 加上这个属性, 效果就是把编辑器里的内容给自动保存到 textarea 里.
saveHTMLToTextArea: true,
});
后端 BlogServlet/doPost
- req.setCharacterEncoding设置后端读取的格式
- req.getSession判断session是否存在
- session.getAttribute判断用户是否在session内
- 使用req.getParameter获取标题、内容
- 如果标题内容为空或者为空串,则响应400状态码
- 创建一个博客类
- 将数据写入博客类中
- 博客的作者ID就是当前登录用户的ID
- 最后将这个类写入数据库(实际就是将类中的数据写入)
- 写入后,resp.sendRedirect跳转到博客列表
//提交博客
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf8");
//判断会话是否存在和会话中的用户是否存在
HttpSession session=req.getSession(false);
if (session == null) {
resp.setStatus(400);
return;
}
User user= (User) session.getAttribute("user");
// System.out.println(user.getUsername());
// System.out.println(user.getUserId());
if(user==null){
resp.setStatus(400);
return;
}
//2.获取博客的标题和正文
String title=req.getParameter("title");
String content=req.getParameter("content");
// System.out.println(title);
// System.out.println(content);
if(title==null||content==null||title.equals("")||content.equals("")){
resp.setStatus(400);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("标题或正文不符合");
return;
}
//把数据写入一个对象
Blog blog=new Blog();
blog.setTitle(title);
blog.setContent(content);
//博客作者的ID就是当前登录用户的ID 所以直接从session拿出当前用户 再拿出当前用户的id
blog.setUserId(user.getUserId());
//创建博客写入数据库的对象
BlogDao blogDao=new BlogDao();
//把这个博客对象写入数据库
blogDao.insert(blog);
//响应
resp.sendRedirect("blog_list.html");
}
部署
准备工作
均在Linux系统下
下载jdk
yum install java-1.8.0-openjdk-devel.x86_64
下载tomcat
把window下的tomcat8.0拖拽到linux上
解压
unzip apache-tomcat-8.5.100.zip
加权限
cd到tomcat的bin目录下
给所有.sh加上权限
chmod +x *.sh
./即可启动
startup.sh是linux启动脚本
startup.bat是window启动脚本
但是大概率启动不了,因为tomcat8080端口,服务器是默认不开放的,所有要进入你的服务器控制台开放端口
安装mysql
之后把db.sql里的sql语句复制到数据库内,重新建库建表
使用maven打包
记得改包格式和包名
把打好的包从window拖拽到Linux的Tomcat的webappsxia
访问
你服务器的地址:端口:包名:你也访问的页面
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
在软件系统的质量保证上,有多种方式,这次尝试是通过ApiKi服务器托管t,在接口层面,对系统开发过程中可能产生的bug进行拦截。 接口测试是软件开服务器托管发中不可或缺的一环,它能够有效地检测出系统间数据传输的错误。个人认为,这种测试基于黑盒和白盒测试之间。 …