五.进行前后端接口设计(基于HTTP基础上进行扩展)
注册
2.实现注册功能
package api;
import model.User;
import model.UserDao;
import view.HtmlGenerator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RegisterServlet extends HttpServlet {
// 浏览器是通过 POST 方法提交注册信息给服务器的.
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
// 1. 获取到前端提交的数据(用户名, 密码), 校验是否合法.
String name = req.getParameter("name");
String password = req.getParameter("password");
if (name == null || "".equals(name)
|| password == null || "".equals(password)) {
// 用户提交的数据有误.
// 返回一个错误页面. (一段字符串, html 构成得到)
//"用户名或者密码为空"是页面中的提示信息,"register.html"表示接下来要跳转到哪里去
String html = HtmlGenerator.getMessagePage("用户名或者密码为空",
"register.html");
resp.getWriter().write(html);
return;
}
// 2. 拿着用户名在数据库中查一下, 看看当前用户名是否已经存在. 如果存在, 认为注册失败(用户名不能重复)
UserDao userDao = new UserDao();
User existUser = userDao.selectByName(name);
if (existUser != null) {
// existUser 非空, 说明该用户名已经存在. 就提示用户, 注册失败, 用户名重复
String html = HtmlGenerator.getMessagePage("用户名重复! 请换个名字!",
"register.html");
resp.getWriter().write(html);
return;
}
// 3. 根据前端提交的数据, 构造 User 对象并插入到数据库中.
User user = new User();
user.setName(name);
user.setPassword(password);
userDao.add(user);
// 4. 返回一个结果页面, 提示当前注册成功.
String html = HtmlGenerator.getMessagePage("注册成功! 点击跳转到登陆页面!",
"login.html");
resp.getWriter().write(html);
}
}
3.获取登陆页面
登录
4.实现登录功能
package api;
import model.User;
import model.UserDao;
import view.HtmlGenerator;
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 LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
// 1. 获取到用户名和密码. 并进行简单校验
String name = req.getParameter("name");
String password = req.getParameter("password");
if (name == null || "".equals(name) || password == null || "".equals(password)) {
String html = HtmlGenerator.getMessagePage("用户名或密码为空","login.html");
resp.getWriter().write(html);
return;
}
// 2. 数据库中查找, 看用户是否存在.
// 3. 对比密码是否匹配
UserDao userDao = new UserDao();
User user = userDao.selectByName(name);
if (user == null || !password.equals(user.getPassword())) {
//用户不存在,提示错误
String html = HtmlGenerator.getMessagePage("用户名或密码错误","login.html");
resp.getWriter().write(html);
return;
}
// 4. 匹配成功则认为登陆成功, 创建一个 Session
HttpSession httpSession = req.getSession(true);
httpSession.setAttribute("name",user);
// 5. 返回一个登陆成功的提示页面
String html = HtmlGenerator.getMessagePage("登陆成功","article");
resp.getWriter().write(html);
}
}
5.获取文章列表
6.获取文章详细内容
7.新增/发布文章
package api;
import model.Article;
import model.ArticleDao;
import model.User;
import model.UserDao;
import view.HtmlGenerator;
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;
import java.util.List;
public class ArticleServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
// 1. 验证用户是否已经登陆了. 如果尚未登陆, 就提示用户要先登陆
HttpSession httpSession = req.getSession(false);
if (httpSession == null) {
// 当前是未登录状态
String html = HtmlGenerator.getMessagePage("请先登陆",
"login.html");
resp.getWriter().write(html);
return;
}
User user = (User) httpSession.getAttribute("user");
// 2. 判断请求中是否存在 articleId 参数.
String articleIdStr = req.getParameter("articleId");
if (articleIdStr == null) {
// a) 没有这个参数就去执行获取文章列表操作
getAllArticle(user, resp);
} else {
// b) 有这个参数就去执行获取文章详情操作.
getOneArticle(Integer.parseInt(articleIdStr), user, resp);
}
}
private void getAllArticle(User user, HttpServletResponse resp) throws IOException {
// 1. 查找数据库
ArticleDao articleDao = new ArticleDao();
List articles = articleDao.selectAll();
// 2. 构造页面
String html = HtmlGenerator.getArticleListPage(articles, user);
resp.getWriter().write(html);
}
private void getOneArticle(int articleId, User user, HttpServletResponse resp) throws IOException {
// 1. 查找数据库
ArticleDao articleDao = new ArticleDao();
Article article = articleDao.selectById(articleId);
if (article == null) {
// 文章未找到
String html = HtmlGenerator.getMessagePage("文章不存在",
"article");
resp.getWriter().write(html);
return;
}
// 为了验证换行消失的问题, 在这个环节把 Article 中的正文打出来, 看看是不是带换行.
// System.out.println("article.content: " + article.getContent());
// 2. 根据作者id 找到作者信息, 进一步得到作者姓名
UserDao userDao = new UserDao();
User author = userDao.selectById(article.getUserId());
// 3. 构造页面
String html = HtmlGenerator.getArticleDetailPage(article, user, author);
resp.getWriter().write(html);
}
// 实现新增文章的逻辑
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset=utf-8");
// 1. 判定用户的登陆状态. 如果用户尚未登陆, 就要提示用户来登陆.
HttpSession httpSession = req.getSession(false);
if (httpSession == null) {
String html = HtmlGenerator.getMessagePage("您尚未登陆",
"login.html");
resp.getWriter().write(html);
return;
}
User user = (User) httpSession.getAttribute("user");
// 2. 从请求中读取浏览器提交的数据(title, content), 并进行简单校验
String title = req.getParameter("title");
String content = req.getParameter("content");
if (title == null || "".equals(title)
|| content == null || "".equals(content)) {
String html = HtmlGenerator.getMessagePage("提交的标题或者正文为空",
"article");
resp.getWriter().write(html);
return;
}
// 3. 把数据插入到数据库中.
ArticleDao articleDao = new ArticleDao();
Article article = new Article();
article.setTitle(title);
article.setContent(content);
article.setUserId(user.getUserId());
articleDao.add(article);
// 4. 返回一个插入成功的页面.
String html = HtmlGenerator.getMessagePage("发布成功!",
"article");
resp.getWriter().write(html);
return;
}
}
8.删除文章
package api;
import model.Article;
import model.ArticleDao;
import model.User;
import view.HtmlGenerator;
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 DeleteServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
// 1. 验证用户的登陆状态, 如果未登陆, 肯定不能删除.
HttpSession httpSession = req.getSession(false);
if (httpSession == null) {
String html = HtmlGenerator.getMessagePage("您尚未登陆!",
"login.html");
resp.getWriter().write(html);
return;
}
User user = (User) httpSession.getAttribute("user");
// 2. 读取请求内容, 获取到要删除的文章 id
String articleIdStr = req.getParameter("articleId");
if (articleIdStr == null || "".equals(articleIdStr)) {
String html = HtmlGenerator.getMessagePage("要删除的文章 id 有误",
"article");
resp.getWriter().write(html);
return;
}
// 3. 根据文章 id 查找到该文章的作者. 当前用户如果就是作者, 才能删除, 否则删除失败.
ArticleDao articleDao = new ArticleDao();
Article article = articleDao.selectById(Integer.parseInt(articleIdStr));
if (article.getUserId() != user.getUserId()) {
String html = HtmlGenerator.getMessagePage("您只能删除自己的文章!",
"article");
resp.getWriter().write(html);
return;
}
// 4. 真正执行数据库删除操作
articleDao.delete(Integer.parseInt(articleIdStr));
// 5. 返回一个 "删除成功" 的页面.
String html = HtmlGenerator.getMessagePage("删除成功!",
"article");
resp.getWriter().write(html);
}
}
package view;
import model.Article;
import model.User;
import java.util.List;
public class HtmlGenerator {
// 通过字符串拼接的形式, 构造出一个 html 格式的内容来.
// 下面的代码实现起来非常麻烦. (HTML 嵌入到 Java 代码中)
// 如果页面简单还好, 如果页面复杂, 那就非常不好整了.
// 使用这种写法, 代码简单粗暴(不需要引入新的知识的)
// 实际开发中还有更科学的写法:
// 1. 服务器渲染页面, 把业务代码嵌入到 HTML (JSP, PHP);
// 2. 服务器渲染页面, 把 HTML 嵌入到业务代码中, 不使用字符串拼接的方式,
// 而是使用模板的方式. (FreeMarker)
// 3. 前端渲染页面, 通过前后端分离的方式, 服务器只是返回简单数据, 由前端代码同过 JS
// 构造页面内容. [主流]
public static String getMessagePage(String message, String nextUrl) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("提示页面 ");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append(message);
stringBuilder.append("
");
stringBuilder.append(String.format(" 点击这里进行跳转 ",
nextUrl));
stringBuilder.append("");
stringBuilder.append("");
return stringBuilder.toString();
}
// 按照字符串拼装的方式, 生成 html
public static String getArticleListPage(List articles, User user) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("提示页面 ");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append(" 欢迎您! " + user.getName() + "
");
stringBuilder.append("
");
// 要有一个文章列表. 显示每个文章的标题.
for (Article article : articles) {
stringBuilder.append(String.format("",
article.getArticleId(), article.getTitle(), article.getArticleId()));
}
stringBuilder.append("
");
stringBuilder.append(String.format("当前共有博客 %d 篇", articles.size()));
// 在这里新增发布文章的区域
stringBuilder.append(" 发布文章 ");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("");
return stringBuilder.toString();
}
public static String getArticleDetailPage(Article article, User user, User author) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("提示页面 ");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append("");
stringBuilder.append(" 欢迎您! " + user.getName() + "
");
stringBuilder.append("
");
stringBuilder.append(String.format("%s
", article.getTitle()));
stringBuilder.append(String.format("作者: %s
", author.getName()));
// 构造正文的地方.
// HTML 中本来就不是用 \n 表示换行的.
stringBuilder.append(String.format("%s", article.getContent()
.replace("\n", "
")));
stringBuilder.append("");
stringBuilder.append("");
return stringBuilder.toString();
}
}