需求分析
- 用户管理
-
用户注册
- 静态:GET/register.html
- 动态:POST/register
-
用户推出
- 动态 :GET/logout
-
用户登录
- 静态:GET/login
- 动态:POST/login.html
-
- 文章管理
- 文章发表
- 动态 GET/publish
- 动态 POST/publish.html
- 文章查看
- GET/a?id=<文章id> GET/a/id
- 文章发表
- 图片管理
- 图片查看
- GET/i?id=<图片id> GET/i/id
- 图片查看
以上就是本次小项目进行的需求分析,下面来实现
动态就是根据用户状态显示不同的内容
静态就是不论用户状态什么样 显示的都是html文件
用户管理
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
<h1>用户注册</h1>
<form method="post" action="/register">
<div>
<label>用户名</label>
<input type="text" name="username">
</div>
<div>
<label>密码</label>
<input type="password" name="password">
</div>
<div>
<button type="submit">注册</button>
</div>
</form>
</body>
</html>
register
package com.jsj;
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("/register")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 读取用户提交的信息
req.setCharacterEncoding("utf-8"); // 保证字符集编码一定不会出错
String username = req.getParameter("username");
String password = req.getParameter("password");
// 2. 验证用户信息信息的合法性
if (username == null) {
System.out.println("用户名必须填写");
resp.sendRedirect("/register.html");
return;
}
// TODO: 其他合法性验证
// 3. 保存到 users 表中
User user = User.insert(username, password);
// TODO: 插入失败的处理
// 4. 利用 Session 进行用户登录
HttpSession session = req.getSession();
session.setAttribute("user", user);
// 5. 跳转到 发表文章页面
resp.sendRedirect("/publish.jsp"); // 完全等于下面的写法
//resp.setStatus(302);
//resp.setHeader("Location", "/publish.html");
// sendRedirect 就是发送一个 302 Location: /publish.html
}
}
登录
package com.jsj;
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("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
// 2. TODO: 合法性校验
// 3. 从 MySQL 中查询登录的用户
User user = User.getByUsernameAndPassword(username, password);
if (user == null) {
// 给出提示 OR 302 到 /login.html
resp.sendRedirect("/login.html");
return;
}
// 4. 写入 Session 中,表示登录成功
HttpSession session = req.getSession();
session.setAttribute("user", user);
// 5. 登录成功,跳转到文章发表页面
resp.sendRedirect("/publish.jsp");
}
}
退出
package com.jsj;
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("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 删除 Session 中的当前用户对象
HttpSession session = req.getSession();
session.removeAttribute("user");
// 2. 跳转回登录页面
resp.sendRedirect("/login.html");
}
}
发表文章
package com.jsj;
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("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 删除 Session 中的当前用户对象
HttpSession session = req.getSession();
session.removeAttribute("user");
// 2. 跳转回登录页面
resp.sendRedirect("/login.html");
}
}
查看文章列表
package com.jsj;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
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.util.List;
@WebServlet("/api/list.json")
public class ListAPIServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json; charset=utf-8");
List<Article> articleList = Article.list();
String jsonText = toJSON(articleList);
resp.getWriter().println(jsonText);
}
private String toJSON(List<Article> articleList) {
JSONArray array = new JSONArray();
for (Article article : articleList) {
JSONObject object = new JSONObject();
object.put("id", article.id);
JSONObject author = new JSONObject();
author.put("id", article.author.id);
author.put("username", article.author.username);
object.put("author", author);
object.put("image_id", article.image.id);
object.put("image_url", String.format("/i?id=%d", article.image.id));
object.put("title", article.title);
object.put("body", article.body);
array.add(object);
}
return array.toJSONString();
}
}
后台数据
文章与文章服务
package com.jsj;
import javax.servlet.ServletException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class Article {
int id;
User author;
String title;
Image image;
String body;
public Article(int id, User author, String title, Image image, String body) {
this.id = id;
this.author = author;
this.title = title;
this.image = image;
this.body = body;
}
public static Article publish(User author, String title, Image image, String body) throws ServletException {
try (Connection con = DB.getConnection()) {
String sql = "INSERT INTO articles (author_id, image_id, title, body) VALUES (?, ?, ?, ?)";
try (PreparedStatement stmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
stmt.setInt(1, author.id);
stmt.setInt(2, image.id);
stmt.setString(3, title);
stmt.setString(4, body);
stmt.executeUpdate();
try (ResultSet rs = stmt.getGeneratedKeys()) {
if (rs.next()) {
int id = rs.getInt(1);
return new Article(id, author, title, image, body);
} else {
return null;
}
}
}
} catch (SQLException e) {
e.printStackTrace();
throw new ServletException(e);
}
}
public static Article getById(int id) throws ServletException {
try (Connection con = DB.getConnection()) {
String sql = "SELECT title, author_id, users.username author_username, image_id, body FROM articles, users WHERE articles.author_id = users.id AND articles.id = ?";
try (PreparedStatement stmt = con.prepareStatement(sql)) {
stmt.setInt(1, id);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
String title = rs.getString("title");
int authorId = rs.getInt("author_id");
String authorUsername = rs.getString("author_username");
int imageId = rs.getInt("image_id");
String body = rs.getString("body");
User author = new User(authorId, authorUsername);
Image image = new Image(imageId);
return new Article(id, author, title, image, body);
} else {
return null;
}
}
}
} catch (SQLException e) {
e.printStackTrace();
throw new ServletException(e);
}
}
public static List<Article> list() throws ServletException {
List<Article> articleList = new ArrayList<>();
try (Connection con = DB.getConnection()) {
String sql = "SELECT " +
"articles.id article_id, " +
"users.id author_id, " +
"users.username author_username, " +
"image_id, " +
"title, " +
"body " +
"FROM articles, users " +
"WHERE articles.author_id = users.id " +
"ORDER BY articles.id DESC";
try (PreparedStatement stmt = con.prepareStatement(sql)) {
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
int articleId = rs.getInt("article_id");
int authorId = rs.getInt("author_id");
String authorUsername = rs.getString("author_username");
int imageId = rs.getInt("image_id");
String title = rs.getString("title");
String body = rs.getString("body");
User author = new User(authorId, authorUsername);
Image image = new Image(imageId);
Article article = new Article(articleId, author, title, image, body);
articleList.add(article);
}
}
}
} catch (SQLException e) {
e.printStackTrace();
throw new ServletException(e);
}
return articleList;
}
}
package com.jsj;
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.io.PrintWriter;
@WebServlet("/a")
public class ArticleServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = Integer.parseInt(req.getParameter("id"));
Article article = Article.getById(id);
if (article == null) {
resp.sendError(404, "没有这篇文章");
return;
}
resp.setContentType("text/html; charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.println("<!DOCTYPE html>");
writer.println("<html>");
writer.println("<head>");
writer.println("<meta charset='utf-8'>");
writer.println("<title>文章 | " + article.title + "</title>");
writer.println("</head>");
writer.println("<body>");
writer.println("<h1>" + article.title + "</h1>");
writer.println("<h2>" + article.author.username + "</h2>");
writer.println("<img src='/i?id=" + article.image.id + "'>");
writer.println("<p>");
writer.println(article.body);
writer.println("</p>");
writer.println("</body>");
writer.println("</html>");
}
}
图片 与 图片服务
package com.jsj;
import javax.servlet.ServletException;
import javax.servlet.http.Part;
import java.io.IOException;
import java.sql.*;
public class Image {
int id;
public Image(int id) {
this.id = id;
}
/**
* 根据用户输入,保存图片内容
* @param imagePart
* @return
*/
public static Image save(Part imagePart) throws IOException, ServletException {
// 通过 JDBC 保存图片内容
try (Connection con = DB.getConnection()) {
String sql = "INSERT INTO images (image) VALUES (?)";
try (PreparedStatement stmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
stmt.setBlob(1, imagePart.getInputStream(), imagePart.getSize());
stmt.executeUpdate();
try (ResultSet rs = stmt.getGeneratedKeys()) {
if (rs.next()) {
int id = rs.getInt(1);
return new Image(id);
}
return null;
}
}
} catch (SQLException e) {
e.printStackTrace();
throw new ServletException(e);
}
}
public static byte[] getById(int id) throws ServletException {
try (Connection con = DB.getConnection()) {
String sql = "SELECT image FROM images WHERE id = ?";
try (PreparedStatement stmt = con.prepareStatement(sql)) {
stmt.setInt(1, id);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return rs.getBytes("image");
} else {
return null;
}
}
}
} catch (SQLException e) {
e.printStackTrace();
throw new ServletException(e);
}
}
}
package com.jsj;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/i")
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = Integer.parseInt(req.getParameter("id"));
byte[] buffer = Image.getById(id);
if (buffer == null) {
resp.sendError(404, "没有这个图片");
return;
}
resp.setContentType("image/jpeg");
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.write(buffer);
outputStream.flush();
}
}
DB数据库连接
package com.jsj;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class DB {
private static DataSource dataSource;
static {
MysqlDataSource mysqlDataSource = new MysqlDataSource();
mysqlDataSource.setServerName("127.0.0.1");
mysqlDataSource.setPort(3306);
mysqlDataSource.setUser("root");
mysqlDataSource.setPassword("");
mysqlDataSource.setDatabaseName("mine_blog");
mysqlDataSource.setUseSSL(false);
mysqlDataSource.setCharacterEncoding("utf8");
dataSource = mysqlDataSource;
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
用户类
package com.jsj;
import javax.servlet.ServletException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.*;
public class User {
int id;
String username;
public User(int id, String username) {
this.id = id;
this.username = username;
}
public static User insert(String username, String password) throws ServletException {
// 1. 永远不用在数据库中保存用户的明文密码
// 1. 首先把 password 进行 hash 处理(这里使用 sha256 算法)
password = encrypted(password);
// 2. 利用 JDBC 保存 MySQL
try (Connection connection = DB.getConnection()) {
String sql = "INSERT INTO users (username, password) VALUES (?, ?)";
try (PreparedStatement stmt = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
stmt.setString(1, username);
stmt.setString(2, password);
stmt.executeUpdate();
// 插入成功
// 3. id 是自增主键,所以,利用 JDBC 的方法取出 id
try (ResultSet rs = stmt.getGeneratedKeys()) {
if (rs.next()) {
int id = rs.getInt(1);
// 4. 返回构建好的用户对象
return new User(id, username);
}
}
}
} catch (SQLException e) {
throw new ServletException(e);
}
// 如果插入过程中,出现问题,返回 null
return null;
}
// 利用 SHA-256 算法,给密码做 hash 处理
public static String encrypted(String password) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] input = password.getBytes("UTF-8");
byte[] output = messageDigest.digest(input);
StringBuilder sb = new StringBuilder();
for (byte b : output) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
return password;
}
}
public static User getByUsernameAndPassword(String username, String password) throws ServletException {
// 1. 先把明文密码 SHA-256 计算
password = encrypted(password);
// 2. 通过 JDBC,进行查询
try (Connection con = DB.getConnection()) {
String sql = "SELECT id FROM users WHERE username = ? AND password = ?";
try (PreparedStatement stmt = con.prepareStatement(sql)) {
stmt.setString(1, username);
stmt.setString(2, password);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
int id = rs.getInt("id");
return new User(id, username);
} else {
return null;
}
}
}
} catch (SQLException e) {
e.printStackTrace();
throw new ServletException(e);
}
}
}