- •Курсовая работа по дисциплине
- •Введение
- •Постановка задачи
- •Обоснование выбора технологий
- •Разработка структуры программы
- •1. Основные компоненты программы
- •2. Архитектура взаимодействия компонентов
- •3. Структура базы данных
- •4. Конфигурация проекта Maven
- •Разработка собственных классов
- •5.1. Модель данных (Model)
- •5.1.1. Класс Book
- •1. Поля:
- •2. Методы:
- •5.1.2. Класс User
- •1. Поля:
- •2. Методы:
- •5.1.3. Класс CartItem
- •1. Поля:
- •2. Методы:
- •5.2. Слой доступа к данным (dao)
- •5.2.1. Класс BookDao
- •1. Поля:
- •2. Методы:
- •5.2.2. Класс UserDao
- •1. Поля:
- •2. Методы:
- •5.2.3. Класс CartDao
- •1. Поля:
- •2. Методы:
- •5.2.4. Класс DatabaseConnection
- •1. Поля (константы подключения):
- •2. Методы:
- •5.3. Сервлеты
- •5.3.1. Класс BookServlet
- •1. Поля:
- •2. Методы http обработки:
- •5.3.2. Класс AuthServlet
- •1. Поля:
- •2. Методы http обработки:
- •5.3.3. Класс CartServlet
- •1. Поля:
- •2. Методы http обработки:
- •5.4. Конфигурация проекта Maven
- •5.4.1. Файл pom.Xml
- •Сценарии пользователя
- •Удаление книг из корзины.
- •Оформление заказа.
- •Инструкция пользователю
- •Начало работы с приложением
- •Создание личного кабинета
- •Вход в систему для постоянных клиентов
- •Исследование книжного каталога
- •Фильтрация книг
- •Формирование корзины покупок
- •Управление корзиной
- •Оформление заказа
- •Завершение работы
- •Заключение
- •Список литературы
- •Приложение
Список литературы
Бирюков, М.А. Лекции по дисциплине «Web-технологии». – СПб.: СПбГУТ, – [Электронный ресурс], [дата обращения – ноябрь 2025 г.].
Oracle Corporation. MySQL 8.0 Reference Manual. — [Электронный ресурс]. — Режим доступа: https://dev.mysql.com/doc/refman/8.0/en/, свободный. — [Дата обращения: ноябрь 2025 г.]
Курняван Б. Создание WEB-приложений на языке Java с помощью сервлетов, JSP и EJB [Электронный ресурс] — СПб.:Лори, 2005. — 857 с. – Режим доступа: https://clck.ru/3Qcow4 , [дата обращения – ноябрь 2025 г.]
JavaRush. Знакомство с DAO — [Электронный ресурс]. – Режим доступа: https://javarush.com/quests/lectures/questhibernate.level16.lecture04, [дата обращения – ноябрь 2025 г.].
JavaRush. Знакомство с паттерном MVC— [Электронный ресурс]. – Режим доступа: https://javarush.com/groups/posts/2536-chastjh-7-znakomstvo-s-patternom-mvc-model-view-controller, [дата обращения – ноябрь 2025 г.].
JavaRush. Сервлеты, Java servlet API. Пишем простое веб-приложение — [Электронный ресурс]. – Режим доступа: https://javarush.com/groups/posts/2529-chastjh-5-servletih-pishem-prostoe-veb-prilozhenie, [дата обращения – ноябрь 2025 г.].
JavaRush. Основы Maven — [Электронный ресурс]. – Режим доступа: https://javarush.com/groups/posts/2523-chastjh-4osnovih-maven, [дата обращения – ноябрь 2025 г.].
Приложение
10.1. Book.java
package com.ivanov.bookstore.model;
public class Book {
private int id;
private String title;
private String author;
private double price;
private String imageUrl;
private int quantity;
public Book() {}
public Book(String title, String author, double price, String imageUrl, int quantity) {
this.title = title;
this.author = author;
this.price = price;
this.imageUrl = imageUrl;
this.quantity = quantity;
}
// Геттеры и сеттеры
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getAuthor() { return author; }
public void setAuthor(String author) { this.author = author; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
public String getImageUrl() { return imageUrl; }
public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { this.quantity = quantity; }
}
10.2. CartItem.java
package com.ivanov.bookstore.model;
public class CartItem {
private int id;
private int userId;
private int bookId;
private int quantity;
private Book book;
public CartItem() {}
public CartItem(int userId, int bookId, int quantity) {
this.userId = userId;
this.bookId = bookId;
this.quantity = quantity;
}
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
public int getBookId() { return bookId; }
public void setBookId(int bookId) { this.bookId = bookId; }
public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { this.quantity = quantity; }
public Book getBook() { return book; }
public void setBook(Book book) { this.book = book; }
}
10.3. User.java
package com.ivanov.bookstore.model;
public class User {
private int id;
private String username;
private String password;
private String email;
public User() {}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public int getId() { return id; }
public void setId(int id) { this.id = id; }
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; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
10.4. BookDao.java
package com.ivanov.bookstore.dao;
import com.ivanov.bookstore.model.Book;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class BookDao {
public List<Book> getAllBooks() {
List<Book> books = new ArrayList<>();
String sql = "SELECT * FROM books";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
Book book = new Book();
book.setId(rs.getInt("id"));
book.setTitle(rs.getString("title"));
book.setAuthor(rs.getString("author"));
book.setPrice(rs.getDouble("price"));
book.setImageUrl(rs.getString("image_url"));
book.setQuantity(rs.getInt("quantity"));
books.add(book);
}
} catch (SQLException e) {
e.printStackTrace();
}
return books;
}
public boolean decreaseBookQuantity(int bookId, int quantity) {
String sql = "UPDATE books SET quantity = quantity - ? WHERE id = ? AND quantity >= ?";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, quantity);
stmt.setInt(2, bookId);
stmt.setInt(3, quantity);
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
}
10.5. CartDao.java
package com.ivanov.bookstore.dao;
import com.ivanov.bookstore.model.CartItem;
import com.ivanov.bookstore.model.Book;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class CartDao {
public List<CartItem> getCartItemsByUserId(int userId) {
List<CartItem> cartItems = new ArrayList<>();
String sql = "SELECT ci.*, b.title, b.author, b.price, b.image_url, b.quantity as book_quantity " +
"FROM cart_items ci " +
"JOIN books b ON ci.book_id = b.id " +
"WHERE ci.user_id = ?";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, userId);
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
CartItem item = new CartItem();
item.setId(rs.getInt("id"));
item.setUserId(rs.getInt("user_id"));
item.setBookId(rs.getInt("book_id"));
item.setQuantity(rs.getInt("quantity"));
Book book = new Book();
book.setId(rs.getInt("book_id"));
book.setTitle(rs.getString("title"));
book.setAuthor(rs.getString("author"));
book.setPrice(rs.getDouble("price"));
book.setImageUrl(rs.getString("image_url"));
book.setQuantity(rs.getInt("book_quantity"));
item.setBook(book);
cartItems.add(item);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return cartItems;
}
public boolean addToCart(int userId, int bookId) {
// Сначала проверяем, есть ли уже такая книга в корзине
CartItem existingItem = findCartItem(userId, bookId);
if (existingItem != null) {
// Если книга уже есть - увеличиваем количество
String updateSql = "UPDATE cart_items SET quantity = quantity + 1 WHERE id = ?";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(updateSql)) {
stmt.setInt(1, existingItem.getId());
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
} else {
// Если книги нет - добавляем новую запись
String insertSql = "INSERT INTO cart_items (user_id, book_id, quantity) VALUES (?, ?, 1)";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(insertSql)) {
stmt.setInt(1, userId);
stmt.setInt(2, bookId);
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
}
public boolean removeFromCart(int cartItemId) {
String sql = "DELETE FROM cart_items WHERE id = ?";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, cartItemId);
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
public void clearUserCart(int userId) {
String sql = "DELETE FROM cart_items WHERE user_id = ?";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, userId);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
public CartItem findCartItem(int userId, int bookId) {
String sql = "SELECT * FROM cart_items WHERE user_id = ? AND book_id = ?";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, userId);
stmt.setInt(2, bookId);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
CartItem item = new CartItem();
item.setId(rs.getInt("id"));
item.setUserId(rs.getInt("user_id"));
item.setBookId(rs.getInt("book_id"));
item.setQuantity(rs.getInt("quantity"));
return item;
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public boolean updateCartItemQuantity(int cartItemId, int quantity) {
String sql = "UPDATE cart_items SET quantity = ? WHERE id = ?";
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, quantity);
stmt.setInt(2, cartItemId);
return stmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
}
10.6. UserDao.java
package com.ivanov.bookstore.dao;
import com.ivanov.bookstore.model.User;
import java.sql.*;
public class UserDao {
public User findUserByUsername(String username) {
String sql = "SELECT * FROM users WHERE username = ?";
User user = null;
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, username);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
public boolean registerUser(User user) {
String sql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)";
System.out.println(" Attempting to register user: " + user.getUsername());
try (Connection conn = DatabaseConnection.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
stmt.setString(3, user.getEmail());
boolean result = stmt.executeUpdate() > 0;
System.out.println(" Registration result: " + result);
return result;
} catch (SQLException e) {
System.out.println(" Database error: " + e.getMessage());
e.printStackTrace();
return false;
}
}
public boolean validatePassword(String plainPassword, String hashedPassword) {
return plainPassword.equals(hashedPassword);
}
}
10.7. DatabaseConnection.java
package com.ivanov.bookstore.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
private static final String URL = "jdbc:mysql://localhost:3306/bookstore";
private static final String USER = "root";
private static final String PASSWORD = "??????";
public static Connection getConnection() throws SQLException {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new SQLException("MySQL Driver not found", e);
}
return DriverManager.getConnection(URL, USER, PASSWORD);
}
}
10.8. AuthServlet.java
package com.ivanov.bookstore.servlets;
import com.ivanov.bookstore.dao.UserDao;
import com.ivanov.bookstore.model.User;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/auth/*")
public class AuthServlet extends HttpServlet {
private UserDao userDao = new UserDao();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
String pathInfo = request.getPathInfo();
if ("/login".equals(pathInfo)) {
handleLogin(request, response);
} else if ("/register".equals(pathInfo)) {
handleRegister(request, response);
} else if ("/logout".equals(pathInfo)) {
handleLogout(request, response);
}
}
private void handleLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userDao.findUserByUsername(username);
if (user != null && userDao.validatePassword(password, user.getPassword())) {
HttpSession session = request.getSession();
session.setAttribute("user", user);
session.setAttribute("userId", user.getId());
response.getWriter().write("{\"success\": true, \"message\": \"Login successful\"}");
} else {
response.getWriter().write("{\"success\": false, \"message\": \"Invalid username or password\"}");
}
}
private void handleRegister(HttpServletRequest request, HttpServletResponse response) throws IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
// Проверяем, не существует ли уже пользователь
if (userDao.findUserByUsername(username) != null) {
response.getWriter().write("{\"success\": false, \"message\": \"Username already exists\"}");
return;
}
User newUser = new User(username, password, email);
if (userDao.registerUser(newUser)) {
response.getWriter().write("{\"success\": true, \"message\": \"Registration successful\"}");
} else {
response.getWriter().write("{\"success\": false, \"message\": \"Registration failed\"}");
}
}
private void handleLogout(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.getSession().invalidate();
response.getWriter().write("{\"success\": true, \"message\": \"Logout successful\"}");
}
}
10.9. BookServlet.java
package com.ivanov.bookstore.servlets;
import com.ivanov.bookstore.dao.BookDao;
import com.ivanov.bookstore.model.Book;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.List;
@WebServlet("/books")
public class BookServlet extends HttpServlet {
private BookDao bookDao = new BookDao();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
List<Book> books = bookDao.getAllBooks();
StringBuilder json = new StringBuilder("[");
for (Book book : books) {
json.append("{")
.append("\"id\":").append(book.getId()).append(",")
.append("\"title\":\"").append(escapeJson(book.getTitle())).append("\",")
.append("\"author\":\"").append(escapeJson(book.getAuthor())).append("\",")
.append("\"price\":").append(book.getPrice()).append(",")
.append("\"imageUrl\":\"").append(escapeJson(book.getImageUrl())).append("\",")
.append("\"quantity\":").append(book.getQuantity())
.append("},");
}
if (books.size() > 0) {
json.deleteCharAt(json.length() - 1);
}
json.append("]");
response.getWriter().write(json.toString());
}
private String escapeJson(String str) {
if (str == null) return "";
return str.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
}
10.10. CartServlet.java
package com.ivanov.bookstore.servlets;
import com.ivanov.bookstore.dao.CartDao;
import com.ivanov.bookstore.model.CartItem;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.List;
import com.ivanov.bookstore.dao.BookDao;
@WebServlet("/cart/*")
public class CartServlet extends HttpServlet {
private CartDao cartDao = new CartDao();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
HttpSession session = request.getSession();
Integer userId = (Integer) session.getAttribute("userId");
if (userId == null) {
response.getWriter().write("{\"error\": \"Not logged in\"}");
return;
}
List<CartItem> cartItems = cartDao.getCartItemsByUserId(userId);
StringBuilder json = new StringBuilder("[");
for (CartItem item : cartItems) {
json.append("{")
.append("\"id\":").append(item.getId()).append(",")
.append("\"bookId\":").append(item.getBookId()).append(",")
.append("\"quantity\":").append(item.getQuantity()).append(",")
.append("\"title\":\"").append(escapeJson(item.getBook().getTitle())).append("\",")
.append("\"author\":\"").append(escapeJson(item.getBook().getAuthor())).append("\",")
.append("\"price\":").append(item.getBook().getPrice()).append(",")
.append("\"imageUrl\":\"").append(escapeJson(item.getBook().getImageUrl())).append("\",")
.append("\"bookQuantity\":").append(item.getBook().getQuantity())
.append("},");
}
if (cartItems.size() > 0) {
json.deleteCharAt(json.length() - 1);
}
json.append("]");
response.getWriter().write(json.toString());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
HttpSession session = request.getSession();
Integer userId = (Integer) session.getAttribute("userId");
String pathInfo = request.getPathInfo();
if (userId == null) {
response.getWriter().write("{\"success\": false, \"message\": \"Not logged in\"}");
return;
}
if ("/add".equals(pathInfo)) {
int bookId = Integer.parseInt(request.getParameter("bookId"));
boolean success = cartDao.addToCart(userId, bookId);
response.getWriter().write("{\"success\": " + success + "}");
} else if ("/remove".equals(pathInfo)) {
int cartItemId = Integer.parseInt(request.getParameter("cartItemId"));
boolean success = cartDao.removeFromCart(cartItemId);
response.getWriter().write("{\"success\": " + success + "}");
} else if ("/update".equals(pathInfo)) {
int cartItemId = Integer.parseInt(request.getParameter("cartItemId"));
int quantity = Integer.parseInt(request.getParameter("quantity"));
boolean success = cartDao.updateCartItemQuantity(cartItemId, quantity);
response.getWriter().write("{\"success\": " + success + "}");
} else if ("/purchase".equals(pathInfo)) {
handlePurchase(userId, response);
}
}
private void handlePurchase(int userId, HttpServletResponse response) throws IOException {
BookDao bookDao = new BookDao();
List<CartItem> cartItems = cartDao.getCartItemsByUserId(userId);
// Проверяем достаточно ли книг на складе
for (CartItem item : cartItems) {
if (item.getQuantity() > item.getBook().getQuantity()) {
response.getWriter().write("{\"success\": false, \"message\": \"Недостаточно книг: \" + item.getBook().getTitle() + \" (доступно: \" + item.getBook().getQuantity() + \")\"}");
return;
}
}
// Уменьшаем количество книг
boolean allUpdated = true;
for (CartItem item : cartItems) {
boolean updated = bookDao.decreaseBookQuantity(item.getBookId(), item.getQuantity());
if (!updated) {
allUpdated = false;
break;
}
}
if (allUpdated) {
// Очищаем корзину только если все обновления прошли успешно
cartDao.clearUserCart(userId);
response.getWriter().write("{\"success\": true, \"message\": \"Покупка завершена успешно!\"}");
} else {
response.getWriter().write("{\"success\": false, \"message\": \"Ошибка при обновлении количества книг\"}");
}
}
private String escapeJson(String str) {
if (str == null) return "";
return str.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
}
10.11. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ivanov</groupId>
<artifactId>bookstore</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
<build>
<finalName>bookstore</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.51.v20230217</version>
<configuration>
<httpConnector>
<port>8081</port>
</httpConnector>
</configuration>
</plugin>
</plugins>
</build>
</project>
