博客系统
- 准备工作
- servlrt依赖
- mysql依赖
- jackson依赖
- 服务器和数据库的交互
- 设计数据库/数据表
- 封装DBUtil,实现建立连接和断开连接
- 创建实体类
- blog
- user
- 编写Dao类
- BlogDao
- UserDao
- 前端和服务器的交互
- 功能一:博客列表页
- 约定格式
- 后端代码
- 前端代码
- 功能二:实现博客详情页
- 约定格式
- 后端代码
- 前端代码
- 功能三:实现登录功能
- 约定格式:
- 后端代码
- 前端代码
- 功能四:强制检查登录
- 约定格式
- 后端代码
- 前端代码
- 前端代码
- 功能五:实现显示用户信息
- 约定格式
- 博客列表页
- 博客详情页
- 后端代码
- 后端代码
- 功能六:退出登录(注销)
- 约定格式
- 后端代码
- 前端代码
- 功能七:发布博客
- 约定格式
- 后端代码
- 前端代码
准备工作
通过ideal创建一个maven文件 在pom.xml中引入依赖
servlrt依赖
<!-- 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>
mysql依赖
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
jackson依赖
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.2</version>
</dependency>
接下来要进行的操作,分为两个大的方面
服务器和数据库的交互
设计数据库/数据表
在main中创建一个
dp.sql
文件,在这里面编写SQL完成建库建表操作
在这里插入代码片//编写SQL完成建库建表操作
//建库
create database if not exists blog_system charset utf8;
//建表,使用一个表表示博客,另一个表表示用户
use blog_system;
drop table if exists user;
drop table if exists blog;
create table blog(
blogId int primary key auto_increment,
title varchar(256),
content varchar(4096),
userId int,
postTime datetime
);
create table user(
userId int primary key auto_increment,
username varchar(64) unique,
password varchar(64)
);
通过封装JDBC代码,来实现基础的数据库操作,因为在咱们的程序里,是需要针对blog表和user表进行一些增删查改的
首先,我们在Java这个包中再创建一个dao
包(data access object
数据访问对象),在里面写一些类,通过这些类里的方法封装了数据库,之后的数据库就是通过这样的对象来访问的
封装DBUtil,实现建立连接和断开连接
在dao包中创建一个类,通过这个类,把数据库建立连接和断开连接的逻辑进行封装
package dao;
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;
//此处需要为单例模式
private 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?useSSL=false&characterEncoding=utf8");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("111111");
}
}
}
return dataSource;
}
//提供一个方法,和数据库建立连接
public static Connection getConnection(){
try {
return getDataSource().getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//提供一个方法,和数据库断开连接
public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) throws SQLException {
if (resultSet!=null){
resultSet.close();
}
if (statement!=null){
statement.close();
}
if (connection!=null){
connection.close();
}
}
}
创建实体类
此处的实体类,就是要和数据库的表有对应关系,每个表都需要有一个实体类(不绝对),然后就可以使用这个类的对象来表示这个表里的一条记录了(因此,就要求这个对象的属性,能和表里的属性一一对应)
后续数据库操作是围绕实体类来展开的
同样的,我们需要在dao这个包里面创建blog类和user类
blog
package dao;
import java.sql.Timestamp;
//通过这个类的一个对象,来表示一条blog表中的记录
//这个类的属性,要和表中的列一致
public class blog {
private int blogId;
private String title;
private String content;
private int userId;
//SQL里面有Timestamp类型(4个字节,2038年就不够用了),还有 datetime类型
//使用SQL时,推荐使用datetime
private Timestamp postTime;
public int getBlogId() {
return blogId;
}
public String getTitle() {
return title;
}
public String getContent() {
return content;
}
public int getUserId() {
return userId;
}
public String getPostTime() {
//此处需要把时间戳转换为格式化时间
//先构造一个对象,构造的时候,指定具体的格式.
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
return format.format(postTime);
}
public void setBlogId(int blogId) {
this.blogId = blogId;
}
public void setTitle(String title) {
this.title = title;
}
public void setContent(String content) {
this.content = content;
}
public void setUserId(int userId) {
this.userId = userId;
}
public void setPostTime(Timestamp postTime) {
this.postTime = postTime;
}
@Override
public String toString() {
return "blog{" +
"blogId=" + blogId +
", title='" + title + '\'' +
", content='" + content + '\'' +
", userId=" + userId +
", postTime=" + postTime +
'}';
}
}
user
package dao;
public class user {
private int userId;
private String username;
private String password;
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;
}
@Override
public String toString() {
return "user{" +
"userId=" + userId +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
编写Dao类
通过实现Dao类,来封装对实体类(数据表)的增删查改
BlogDao
package dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
//通过这个类,封装对blog表的增删查改
public class BlogDao {
//1.新增一个blog
//调用insert的时候,需要先构造一个blog对象
//作为参数,传递给insert,再由insert内部完成数据库的插入操作
public void insert(blog blog) throws SQLException {
Connection connection =null;
PreparedStatement statement =null;
try{
//1.和数据库建立连接
connection = DBUtil.getConnection();
//2.构造一个SQL语句
String sql = "insert into blog values(null,?,?,?,now())";
statement = connection.prepareStatement(sql);
statement.setString(1,blog.getTitle());
statement.setString(2,blog.getContent());
statement.setInt(3,blog.getUserId());
//3.执行sql语句
statement.executeUpdate();
}catch (SQLException e){
e.printStackTrace();
} finally{
//4.关闭连接,释放资源
DBUtil.close(connection,statement,null);
}
}
//2.查询blog表里的所有的博客
public List<blog>getblogs() throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet =null;
List<blog>blogs = new ArrayList<>();
try{
//1.建立连接
connection = DBUtil.getConnection();
//2.构造一个SQL语句
String sql = "select * from blog";
statement = connection.prepareStatement(sql);
//3.执行语句
resultSet = statement.executeQuery();
//4.遍历结果集合
while(resultSet.next()){
blog blog =new blog();
blog.setBlogId(resultSet.getInt("blogId"));
blog.setTitle(resultSet.getString("title"));
blog.setContent(resultSet.getString("content"));
blog.setUserId(resultSet.getInt("userId"));
blog.setPostTime(resultSet.getTimestamp("postTime"));
blogs.add(blog);
}
return blogs;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
return null;
}
//3.指定blogId,查询某一个博客
public blog getblog(int blogId) throws SQLException {
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(sql);
//4.获取blog
if(resultSet.next()){
blog blog =new blog();
blog.setBlogId(resultSet.getInt("blogId"));
blog.setTitle(resultSet.getString("title"));
blog.setContent(resultSet.getString("content"));
blog.setUserId(resultSet.getInt("userId"));
blog.setPostTime(resultSet.getTimestamp("postTime"));
return blog;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
return null;
}
//4.指定blogId进行删除
public void delete(int blogId) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
try{
//1.建立连接
connection = DBUtil.getConnection();
//2.创建SQL语句
String sql = "delete from blog where blogId=?";
statement = connection.prepareStatement(sql);
statement.setInt(1,blogId);
//3.执行sql语句
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection, statement, null);
}
}
}
UserDao
package dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserDao {
//1.根据userId来查询用户信息(后续根据博客查询出作者详情)
public user getuserById(int userId) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try{
connection = DBUtil.getConnection();
String sql = "select * from user where userId=?";
statement = connection.prepareStatement(sql);
statement.setInt(1,userId);
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;
}
//2.根据username来查询用户信息(实现登录功能)
public user getuserByName(String username) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try{
connection = DBUtil.getConnection();
String sql = "select * from where username=?";
statement = connection.prepareStatement(sql);
statement.setString(1,username);
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;
}
}
前端和服务器的交互
接下来,就可以进行一些前后端交互的逻辑的实现了 接下来以功能点为维度进行展开
针对每个功能点,分别进行"设计前后端交互接口",“开发后端代码”,“开发前端代码”,“调试”
功能一:博客列表页
让博客列表页能够加载出博客列表内容
1.发起一个http请求,向后端索要博客列表数据
2.后端收到请求之后查询数据库获取到数据库中的博客列表,并返回给前端
3.前端拿到响应之后,就依据响应中的内容,构造出html片段,最终显示出来 在进行这三个操作之前,还需要约定好前后端交互接口,后续前端和后端要进行很多种不同的数据交互,每一种数据交互都需要发送不同的请求,返回不同的响应,此处就需要把请求和响应具体都约定好
首先创建一个名为api的包,用来存放一些前后端交互的代码,也就是一些重要的servlet,这些servlet给前端提供功能支持,也可以理解为服务器给前端提供的api(编程接口),也可以叫做Controller
约定格式
以下是一种典型的约定方式
请求:
方法: GET
路径: blog
响应: HTTP/1.1 200 OK
Content-Type:application/json json格式如下:
[
{
blogId:1,
title:"西游记",
content:"三打白骨精“,
userId:1,
postTime:"2023-09-25 12:00:00"
}
{
blogId:2,
title:"水浒传",
content:"武松打虎“,
userId:1,
postTime:"2023-09-25 12:00:00"
}
]
后端代码
后端要做的事,就是当收到一个上述约定的请求的时候,构造并返回一个约定的响应数据即可
在api这个包种创建一个BlogServlet
package api;
import com.fasterxml.jackson.databind.ObjectMapper;
import dao.BlogDao;
import dao.blog;
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.sql.SQLException;
import java.util.List;
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//查询数据库,获取到数据后,构造成要求的json格式并返回
BlogDao blogDao = new BlogDao();
List<blog>blogs = null;
try {
blogs = blogDao.getblogs();
} catch (SQLException e) {
e.printStackTrace();
}
String respJson = objectMapper.writeValueAsString(blogs);
//jackson看到blogs是一个List,就会构造出一个json数组[],针对List种的每个blog对象,分别构造出json对象
//具体构造的过程,也就是根据blog的属性来的,属性的名字,就是json的key,属性的值,就是json的value
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
}
}
前端代码
让页面通过js ajax的方式发起一个http请求,来获取到刚才服务器这里的数据
这里需要先引入jquery的依赖:
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
创建一个script标签,在里面编写前端代码
<script>
//编写js代码
//构造http请求,获取到博客列表数据,并展示到页面上
function getBlogs(){
$.ajax({
type:'get',
url:'blog',
success:function(body){
//根据响应的内容,构造出html片段,展示到页面上
//由于服务器在响应种已经设置了content-type为application/json,此时
//jQuery就能够自动 的把此处响应的内容给解析成js对象数组
let container = document.querySelector('.container-right');
for(let blog of body){
//相当于Java中的for each
//根据当前这个blog来构造出一个html片段
let blogDiv = document.createElement('div');
blogDiv.className = 'blog';
//构造标题
let titleDiv = document.createElement('div');
titleDiv.className = 'title';
titleDiv.innerHTML = blog.title;
blogDiv.appendChild(titleDiv);
//构造时间
let dateDiv = document.createElement('div');
dateDiv.className = 'date';
dateDiv.innerHTML = blog.postTime;
blogDiv.appendChild(dateDiv);
//构造摘要
let descDiv = document.createElement('div');
descDiv.className = 'desc';
descDiv.innerHTML = blog.content;
blogDiv.appendChild(descDiv);
//构造查看全文按钮
let a = document.createElement("a");
a.href = "blog_detail.html?blogId="+blog.blogId;
a.innerHTML = '查看全文 >>';
blogDiv.appendChild(a);
container.appendChild(blogDiv);
}
}
});
}
getBlogs();
功能二:实现博客详情页
约定格式
请求:
方法: GET
路径: blog?query string
此处与博客列表页访问的是同一个路径,通过请求中是否携带query string来区分两个业务
响应: HTTP/1.1 200 OK
Content-Type:application/json json格式如下:
{
blogId:1,
title:"西游记",
content:"三打白骨精“,
userId:1,
postTime:"2023-09-25 12:00:00"
}
这里的数据格式和博客列表页返回的非常相似,这里是一条记录,博客列表则是一个数组
后端代码
package api;
import com.fasterxml.jackson.databind.ObjectMapper;
import dao.Blog;
import dao.BlogDao;
import dao.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;
import java.util.List;
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 查询数据库, 获取到数据之后, 构造成要求的 json 格式并返回.
// 先尝试获取下 blogId 这个参数, 看看能不能获取到.
BlogDao blogDao = new BlogDao();
String blogId = req.getParameter("blogId");
if (blogId == null) {
// 此时说明是获取博客列表. 没有 blogId 参数
List<Blog> blogs = null;
blogs = blogDao.getBlogs();
String respJson = objectMapper.writeValueAsString(blogs);
resp.setContentType("application/json; charset=utf8");
resp.getWriter().write(respJson);
} else {
// 此时说明是获取博客详情. 有 blogId 参数.
Blog blog = null;
blog = blogDao.getBlog(Integer.parseInt(blogId));
if (blog == null) {
// 返回一个 id 为 0 的 blog 对象. 前端再根据这里进行判定.
blog = new Blog();
}
String respJson = objectMapper.writeValueAsString(blog);
resp.setContentType("application/json; charset=utf8");
resp.getWriter().write(respJson);
}
}
}
前端代码
function getBlog() {
$.ajax({
url: 'blog' + location.search,
type: 'get',
success: function(body) {
// 根据拿到的响应数据, 构造页面内容.
let h3 = document.querySelector('.container-right h3');
h3.innerHTML = body.title;
let dateDiv = document.querySelector('.container-right .date');
dateDiv.innerHTML = body.postTime;
editormd.markdownToHTML('content', { markdown: body.content });
}
});
}
getBlog();
这里为了使用markdown编辑器来渲染博客,因此需要引入markdown的依赖
<link rel="stylesheet" href="editor.md/css/editormd.min.css" />
<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>
注意:这里的markdown的依赖是建立在jQuery中引入的前提下的,因此我们需要先引入jQuery,再引入markdown
功能三:实现登录功能
约定格式:
请求:
方法: post
路径: login
Content-Type:application/x-www-form-urlencoded(使用form表单的形式提交)
username=zhangsan&password=123
响应: HTTP/1.1 200 OK
Location:blog_list_html
后端代码
package api;
import dao.User;
import 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 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 {
//1.请求中的用户名和密码
//给请求对象设置字符集,保证请求中的用户名或者密码为中文的情况下也是可以的
req.setCharacterEncoding("utf8");
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username == null || password == null || "".equals(username) || "".equals(password)) {
//提交的密码有误
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前传过来的username或者password为空");
}
//2.和数据库的数据进行对比,看是否匹配
UserDao userDao = new UserDao();
User user = userDao.getUserByName(username);
if (user==null){
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("您的用户名或者密码错误");
return;
}
//当前用户名正确,看密码是否正确
if (!password.equals(user.getPassword())){
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("您的用户名或者密码错误");
return;
}
//3.创建会话
HttpSession session = req.getSession(true);
//把当前用户的登录信息保存到session中,方便后续进行获取
session.setAttribute("user",user);
//4.跳转到博客列表页
resp.sendRedirect("blog_list_html");
}
}
前端代码
<form action="login" method="post">
<div class="row">
<span>用户名</span>
<input type="text" id="username" name="username">
</div>
<div class="row">
<span>密码</span>
<input type="password" id="password" name="password">
</div>
<div class="row">
<input type="submit" id="submit" value="登录">
</div>
</form>
功能四:强制检查登录
如果用户在未登录的情况下,访问博客详情列/列表页/编辑页,就会自动的跳转到登录页
在博客详情列/列表页/编辑页,再发起一个get的ajax,询问服务器看当前是否已经登录
约定格式
请求:
方法: get
路径: login
响应: HTTP/1.1 200 OK(已登录)
HTTP/1.1 403 Forbidden(未登录)
后端代码
前端代码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//会话不存在,就是未登录
HttpSession session = req.getSession(false);
if (session==null){
//未登录
resp.setStatus(403);
return;
}
//不仅仅是看session对象本身是否存在,还需要看user对象是否存在(为了后续实现退出登录的功能)
User user = (User) session.getAttribute("user");
if (user==null){
resp.setStatus(403);
return;
}
//返回200表示已登录
resp.setStatus(200);
}
前端代码
function checkLogin() {
$.ajax({
type: 'get',
url: 'login',
success: function(body) {
},
error: function(body) {
location.assign('login.html');
}
});
}
功能五:实现显示用户信息
在当前博客列表页中,显示出当前登录的用户的个人信息,在博客详情页中,显示出这个文章的作者
让博客详情列表页和详情页分别发起ajax请求,博客列表中.就需要获取到当前登录的用户的信息
博客详情页中,就需要获取到当前文章作者的信息
约定格式
博客列表页
请求:
方法: get
路径: user
响应:
HTTP/1.1 200 OK
json格式
{
userId:1,
username:‘zhangsan’
}
博客详情页
请求:
方法: get
路径: user?blogId=
响应:
HTTP/1.1 200 OK
json格式
{
userId:1,
username:‘zhangsan’
}
后端代码
package api;
import com.fasterxml.jackson.databind.ObjectMapper;
import dao.Blog;
import dao.BlogDao;
import dao.User;
import dao.UserDao;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class UserServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String blogId = req.getParameter("blogId");
if (blogId==null){
//说明是博客列表页
HttpSession session = req.getSession(false);
if (session==null){
User user = new User();
String respJson = objectMapper.writeValueAsString(user);
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
return;
}
User user = (User) session.getAttribute("user");
if (user==null){
user = new User();
String respJson = objectMapper.writeValueAsString(user);
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
return;
}
String respJson = objectMapper.writeValueAsString(user);
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
}else {
//博客详情页
//需要查询数据库
BlogDao blogDao = new BlogDao();
Blog blog = blogDao.getBlog(Integer.parseInt(blogId));
if (blog==null){
User user = new User();
String respJson = objectMapper.writeValueAsString(user);
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
return;
}
UserDao userDao = new UserDao();
User user = userDao.getUserById(blog.getUserId());
if (user==null){
user = new User();
String respJson = objectMapper.writeValueAsString(user);
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
return;
}
String respJson = objectMapper.writeValueAsString(user);
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
}
}
}
后端代码
function getUser() {
$.ajax({
type: 'get',
url: 'user',
success: function(body) {
// body 就是解析后的 user 对象了.
let h3 = document.querySelector('.card h3');
h3.innerHTML = body.username;
}
})
}
getUser();
function getUser() {
$.ajax({
type: 'get',
url: 'user' + location.search,
success: function(body) {
// body 就是解析后的 user 对象了.
let h3 = document.querySelector('.card h3');
h3.innerHTML = body.username;
}
})
}
getUser();
功能六:退出登录(注销)
判定登录状态逻辑中,
1.会话存在
2.会话中存储的user对象存在
两个条件同时具备,才认为用户是已经登录了
破坏上述的任何一个条件,都可以达成注销这样的效果
但是servlet中,并没有直接提供一个api来删除会话
但是有api能够删除会话中的user(attribute)
约定格式
请求:
方法: get
路径: logout
响应:
HTTP/1.1 302
location:login.html
后端代码
package api;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession(false);
if (session==null){
//当前是未登录状态,谈不上注销
resp.sendRedirect("login.html");
return;
}
//之前在登录成功之后,就会给session中存储user这样的attribute
//现在需要将其删除
session.removeAttribute("user");
resp.sendRedirect("login.html");
}
}
前端代码
<a href="logout">注销</a>
通过点击a标签就能实现退出登录
功能七:发布博客
这里本质上和登录非常相似
核心都是通过form表单,把页面中用户的内容,给提交到服务器这边,服务器就可以把内容保存到数据中即可
约定格式
请求:
方法:post
路径:blog
Content-Type:application/x-www-form-urlencoded
body:title=xxxxx&content=xxxx
响应:
HTTP/1.1 302
location:blog_list.html
提交成功后,跳转到博客列表页,来到列表页之后,就能够看到刚才发布的博客了
后端代码
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取到当前的登录用户
HttpSession session = req.getSession(false);
if (session==null){
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("未登录");
}
User user = (User) session.getAttribute("user");
if (user==null){
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("未登录");
}
//获取到请求中传递过来的内容
req.setCharacterEncoding("utf8");
String title = req.getParameter("title");
String content = req.getParameter("content");
if(title==null||content==null||"".equals(title)||"".equals(content)){
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("标题或正文为空");
return;
}
//构造Blog对象,并且插入到数据库中
Blog blog = new Blog();
blog.setTitle(title);
blog.setContent(content);
blog.setUserId(user.getUserId());
//由于在sql中插入数据的时候,已经使用sql自带的now获取到当前的时间,不需要此处代码中手动设置时间了
// blog.setPostTime(new Timestamp(System.currentTimeMillis()));
BlogDao blogDao = new BlogDao();
blogDao.insert(blog);
resp.sendRedirect("blog_list.html");
}
}
前端代码
<form action="blog" method="post">
<!-- 标题编辑区 -->
<div class="title">
<input type="text" id="title-input" name="title">
<input type="submit" id="submit">
</div>
<!-- 博客编辑器 -->
<!-- 把 md 编辑器放到这个 div 中 -->
<div id="editor">
<textarea name="content" style="display: none;"></textarea>
//此处是editor.md文档上给出的解决方案,在此处写一个隐藏的text area(多行编辑框),就可以实现form表单的提交了,在这里就可以指定name的值了
</div>
</form>