Skip to content
IT-МИР. ПОМОЩЬ В IT-МИРЕ. BLOCKCHAIN. WEB 3.0

IT-МИР. ПОМОЩЬ В IT-МИРЕ. BLOCKCHAIN. WEB 3.0

BLOCKCHAIN. ОБУЧЕНИЕ И УСЛУГИ IT-ТЕХНОЛОГИЯМ. WEB 3.0

  • ГЛАВНАЯ
  • НОВОСТИ
  • СТАТЬИ
    • CSS
    • DEVOPS
    • JAVASCRIPT
    • HTML
    • LINUX
    • REACT
    • PHP
    • PYTHON
    • WINDOWS
    • WORDPRESS
    • ZABBIX
  • ОБУЧЕНИЕ
    • NODE.JS
    • WORDPRESS
  • АЙТИ-МИР
  • САЙТЫ
    • МИР-БЛОКЧЕЙН
    • МИР-ИНВЕСТИЦИЙ
    • ITBOT
  • УСЛУГИ
    • ДИЗАЙН В СОЦСЕТЯХ
      • YOUTUBE
    • WINDOWS
    • ZABBIX
  • ПОДДЕРЖКА

Java простое веб-приложения. Логин и регистрация

СТАТЬИdao, Java, jdbc, login, maven, registration, service, spring, spring framework, web-application

Всем доброго времени суток.

Эта статья рассчитана для новичков в мире Web и Java. Мы рассмотрим стандартную архитектуру веб-приложения и сделаем небольшой проект с нуля.

Будем использовать Spring (Огромный фреймворк для веба), но по минимуму. Если не иметь предыдущего опыта использования и сразу пытаться использовать весь функционал, то не будет базового понимания, так как имеется перечень подводных камней.

Что будет делать приложение

Хочу представить короткий и в то же время полезный пример. Он минимально загружен и по итогу вы сможете использовать его как шаблон.

Думая, с чем люди часто должны сталкиваться при разработки веб-приложения, понял что реализация логина и регистрации будет достаточно показательной и полезной.

Исходный код вы сможете найти здесь.

Что будем использовать

  • любимую IDE (я использую IntelliJ IDEA)
  • не замутненную голову
  • Maven (сборщик проекта)
  • JDBC (звено между Java и СУБД)

Создание проекта

Создайте простой Maven проект. Делаем все с чистого листа, не добавляя никаких архетипов.
IDE должна сгенерировать такую структуру.

image

И так, что мы видим.

  • java — основное место где будет происходить "магия"
  • resources — место где хранятся наши ресурсы. (Это могут быть файлы, картинки и чего только душа пожелает, зачастую тут хранится front часть приложения)
  • test — место где принято писать тесты к приложению. (Вы можете с чистой совестью удалять эту папку, тестирование мы рассматривать не будем)
  • pom.xml — сердце Maven. В нем содержится информация о проекте, тут прописываются все зависимости, указывается какой тип "упаковки" должен быть у проекта и тд.

Кстати, не пропустите сообщения от IDE, и разрешите авто-импорт для Maven.

image

Архитектура веб-приложения

Чтобы начать кодить, нужно подкрепиться немного теорией.
Простите за мой дизайнерский талант, я в этом не силен.

image

На картинке показаны слои веб-приложения, каждый слой может взаимодействовать только со своими соседями, если приложение написано "по-правильному".

И так пробежимся по каждому слою и разберем их назначения.

  1. Browser — это лицо нашего приложения. То что видит пользователь и что называют Frontend. Он может взаимодействовать с Backend — серверной частью, а именно с контроллером. Этот слой должен уметь отправлять и получать данные от контроллера.
  2. Controller — должен контролировать запросы от Frontend, уметь их обрабатывать и возвращать данные. И, конечно же, задачей контролера является общение со следующим слоем.
  3. Service — в этом слое должна быть реализована бизнес-логика приложения. Можно считать этот слой корнем приложения. В нем происходят самые тяжеловесные операции.
  4. DAO(data access object) — этот слой должен общаться с нашей БД. В нём реализованы все запросы к БД, которые нужны для приложения, а именно запросы на выборку, изменения и тд.
  5. Database — она же БД, структурированная туса данных.

Проектирование базы данных

Один из самых первых этапов разработки веб-приложения является проектирование БД.

Выбор БД предоставляется на ваше усмотрение, но у меня в примере будет использоваться H2.

Так как я хочу чтобы пример вышел небольшой, но чтобы в нем удалось рассмотреть как можно больше скользких моментов и понять всеобщие принципы построения веб-приложений. В примере будет только одна таблица User.

create table DATABASE.USER
(
    ID INT auto_increment,
    NAME VARCHAR not null,
    SURNAME VARCHAR not null,
    LOGIN VARCHAR not null,
    PASSWORD VARCHAR not null,
    constraint USER_PK
        primary key (ID)
);

Добавляем Spring в проект

Вспоминаем про нашу папку java.

Создаем внутри java пакет com.zuk(вы можете называть иначе), в нем класс App с обычной main функцией.

И добавим щепотку магии Spring. Не будем вдаваться сильно в то что здесь происходит, с помощью @SpringBootApplication мы просто говорим Spring, чтобы он делал автоматическую настройку, чтобы он сканировал все что ему нужно. Сейчас рекомендую рассматривать Spring как автономную республику.

//com.zuk.App
@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

Не впадаем в панику если все красное и не забываем подключать зависимости в 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>org.zuk</groupId>
    <artifactId>LoginAndRegistration</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
    </dependencies>

</project>

Если вы все сделали правильно у вас появится возможность сделать билд проекта, и Spring скажет вам привет.

image

Spring говорит что он стартанул сервер на порту 8080. Мы можем сами убедиться в этом, сходив на http://localhost:8080.

Подключаем БД к проекту

И так мы уже создали нашу Базу даных, подключили Spring к проекту, но они ещё не знают о существование друг друга.

Давайте создадим application.properties по пути src.main.resources.

Этот файл служит для хранения конфигурационных параметров в формате ключ-значение.

spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:~/test

spring.datasource.username=sa
spring.datasource.password=

Это стандартные ключи для Spring, и он сам может их прочитать.

Чтобы вы смогли убедиться, предлагаю проверить сможем ли мы подключиться в БД.

По пути java.com.zuk.connection создадим класс ConnectionManager, он должен отдавать нам соединение с БД, и с этим соединением мы в дальнейшем будем работать.
Для этого нам понадобится вытянуть наши properties, сделаем это с помощью FileInputStream.

//ConnectionManager
FileInputStream fis;
Properties property = new Properties();

Проберемся к нашему application.properties, и вытянем с него properties.

//ConnectionManager
fis = new FileInputStream("src/main/resources/application.properties");
property.load(fis);

Создаем метод getConnection.

  //ConnectionManager
  public Connection getConnection() {
            Connection connection = null;
            try {
                connection = DriverManager.getConnection(property.getProperty("spring.datasource.url"),property.getProperty("spring.datasource.username"),property.getProperty("spring.datasource.password"));
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return connection;
        }

Теперь можете проверить есть ли соединение, сделать это можно и в App.

Если у вас все получилось, должно вывести такое.

conn2: url=jdbc:h2:~/test user=SA

Ах да, не забываем добавить зависимость в наш любимый pom.

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.200</version>
</dependency>

POJO (Plain Old Java Objects)

Не пугайтесь странных аббревиатур, я расскажу простыми словами зачем это нам надо, и что мы с этим будем делать.

Представьте простой класс, который ничего не наследуют, в который не должно быть реализованы ничего сложно. Это просто класс, который служит носителем информации, в котором есть некоторые поля, геттеры и сеттеры для них. Максимум, что может быть, это реализация стандартных методов объекта. Это и есть наш POJO.

Для нашего проекта, это будет описание сущности таблицы User.
То есть мы реализуем таблицу в виде класса.

И так создаем пакет java.com.zuk.entity, в нем класс User.
Запишем в поля класса поля таблицы, и реализуем для каждого геттер и сеттер.

User.java

public class User {

    int id;
    String name;
    String surname;
    String login;
    String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

DAO

Что же, самое время приступить к следующему слою, а именно DAO. Тут будут реализованы все запросы к нашей БД, которые нам понадобятся.

Создаем пакет java.com.zuk.dao в нем интерфейс UserDao (принято сначала писать имя таблицы). Опишем пока что только два метода findByLogin, save.

public interface UserDao {
    User findByLogin(User user);
    Boolean save(User user);
}

Дальше напишем реализацию для этого интерфейса, создаем пакет java.com.zuk.dao.impl,
в нем класс UserDaoImpl.
Вы можете спросить зачем так сильно разделять все — это будет служить хорошей привычкой, вдруг вам придется работать в большом проекте, там скорее всего будут специфические реализации (например, если используется несколько БД).

public class UserDaoImpl implements UserDao {
    @Override
    public User findByLogin(User user) {
        return null;
    }

    @Override
    public Boolean save(User user) {
        return null;
    }
}

Начнем с findByLogin. Нам нужно сделать такой SQL запрос.

SELECT  * from DATABASE.User where LOGIN=login

Далее нужно вернуть объект класса User.

Проверим есть ли у нас соединение с базой, если же его не будет мы вернем null.

//UserDaoImpl
ConnectionManager cm = new ConnectionManager();
Connection con = cm.getConnection();

@Override
    public User findByLogin(String login) {
        User user = null;
        if (con != null) {
              //..  
        }
        return user;
     }

Если условие в if правильное, мы выполним SQL запрос, и запишем значение в user.

//findByLogin
PreparedStatement pr = con.prepareStatement("SELECT * FROM DATABASE.User where LOGIN=?");
pr.setString(1 , login);
ResultSet resultSet = pr.executeQuery();//return sql result
if(resultSet.next()) {
       user = new User();
       user.setId(resultSet.getInt("ID"));
       user.setName(resultSet.getString("NAME"));
       user.setSurname(resultSet.getString("SURNAME"));
       user.setLogin(login);
       user.setPassword(resultSet.getString("PASSWORD"));
       return user;
}

Не забываем покрывать возможные исключения.

Попробуйте реализовать save своими руками.
Код оставлю под спойлером.

save

//UserDaoImpl
@Override
    public Boolean save(User user) {
        if (con != null) {
            try {
                PreparedStatement pr = con.prepareStatement("insert into DATABASE.USER (NAME,SURNAME,LOGIN,PASSWORD) values (?,?,?,?)");
                pr.setString(1,user.getName());
                pr.setString(2,user.getSurname());
                pr.setString(3,user.getLogin());
                pr.setString(4,user.getPassword());
                pr.executeUpdate();
                return true;
            } catch (SQLException e) {
                e.printStackTrace();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

Service

В сервисе будет находится наша бизнес-логика. Создаем пакет java.com.zuk.service, в нем интерфейс UserService с двумя методами: login, registration. И создаем класс UserServiceImpl в java.com.zuk.service.impl, который имплементирует UserService.

public class UserServiceImpl implements UserService {
    @Override
    public String login(User user) {
        return null;
    }

    @Override
    public String registration(User user) {
        return null;
    }
}

Предлагаю начать с login.
Алгоритм будет таким:

  1. Проверим существует ли поле "login" в БД.
  2. Если условие 1 выполняется, проверяем совпадает ли пароль.
  3. Если условие 2 выполняется, скажем "life is beautiful"

//UserServiceImpl
UserDaoImpl userDao = new UserDaoImpl();
    @Override
    public String login(User user) {
        User findUser = userDao.findByLogin(user.getLogin());
        if(findUser!=null){
            if(findUser.getPassword().equals(user.getPassword())){
                return "life is beautiful";
            }
        }
        return "do not give up";
    }

Попытайтесь сделать регистрацию своими руками.

registration

 @Override
    public String registration(User user) {
        User findUser = userDao.findByLogin(user.getLogin());
        if(findUser==null) {
            userDao.save(user);
            return "life is beautiful";
        }
        return "this login is not available";
    }

Controller

Настала звездный час контроллера, и мы наконец-то сможем увидеть результат наших деяний.
Создаём пакет java.com.zuk.controller в нем класс Controller. Перед классом разместим "магическую" аннотацию RestController, она поможет Spring понять, что этот класс будет служить нам как Rest Controller.
Создаём метод, который возвращает строку и аннотируем его с помощью @RequestMapping("/") и @ResponseBody.

@RestController
public class Controller {
    @RequestMapping("/")
    @ResponseBody
    String main() {
        return "Hello from Controller";
    }
}

Делаем билд проекта, и переходим на http://localhost:8080.
Мы должны увидеть "Hello from Controller".

Теперь создаём два html файла. Один будет с формой регистрации, второй с формой логина.
Правильным тоном будет сохранение этих файлы внутри resources, а еще лучше в папку resources.static.

html

<!--loginFrom.html-->
<html>
<title>Login</title>
<body>
<form action="http://localhost:8080/login">
    <input type="text" required name="login" placeholder="login" />
    <input type="password" required name="password" placeholder="password" />
    <button>login</button>
</form>
<a href="http://localhost:8080/registrationForm">don't have account</a>
</body>
</html>

<!--registrationForm.html-->
<html>
<title>Registration</title>
<body>
<form action="http://localhost:8080/registration">
    <input type="text" required name="name" placeholder="name" />
    <input type="text" required name="surname" placeholder="surname" />
    <input type="text" required name="login" placeholder="login" />
    <input type="password" required name="password" placeholder="password" />
    <button>registration</button>
</form>
<a href="http://localhost:8080/loginForm">already have account</a>
</body>
</html>

Теперь я хочу, чтобы при переходе по ссылке http://localhost:8080/loginForm, или http://localhost:8080/registrationForm выводились наши html файлы с формами.
Возвращаемся к нашему контроллеру, тут мы должны добавить мапинг для /loginForm, /registrationForm и отдавать соответствующую html. В этом нам поможет ModelAndView.

//Controller
 @RequestMapping("/loginForm")
    @ResponseBody
    ModelAndView loginForm() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("loginForm.html");
        return modelAndView;
    }

    @RequestMapping("/registrationForm")
    @ResponseBody
    ModelAndView registrationForm() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("registrationForm.html");
        return modelAndView;
    }

Если вы заметили, то в форме я уже написал action на http://localhost:8080/login и registration, но мы ещё не ловим эти переходы в контроллере.
Пора это исправлять и связаться с нашим service.

//Controller
UserServiceImpl userService = new UserServiceImpl();
//..
 @RequestMapping("/login")
    @ResponseBody
    String login(@RequestParam String login,@RequestParam String password) {
        User user = new User();
        user.setLogin(login);
        user.setPassword(password);
        return userService.login(user);
    }

    @RequestMapping("/registration")
    @ResponseBody
    String registration(@RequestParam String name,@RequestParam String surname, @RequestParam String login,@RequestParam String password) {
        User user = new User();
        user.setName(name);
        user.setSurname(surname);
        user.setLogin(login);
        user.setPassword(password);
        return userService.registration(user);
    }

Мы видим, что наши методы в Controller начали принимать параметры. Это те параметры, которые мы пишем в наших формах. Их имена должны совпадать с именами input.

Заключение

Надеюсь эта статья смогла ответь на некоторые ваши вопросы, и помогла расширить свои горизонты.

Всем приятного развития.

Специально для сайта ITWORLD.UZ. Новость взята с сайта Хабр

Навигация по записям

Previous Previous post: Многопоточная сортировка с использованием пула потоков на Java
Next Next post: Шпаргалка по Smali на Русском

  • Telegram
  • VK
  • Facebook
  • Instagram
  • LinkedIn
  • YouTube
  • ANDROID
  • ANGULAR
  • BLOCKCHAIN
  • C#
  • C++
  • CISCO
  • CSS
  • DATA SCIENCE
  • DEVOPS
  • DOCKER
  • GIT И GITHUB
  • GOLANG
  • HTML
  • JAVA
  • JAVASCRIPT
  • KOTLIN
  • LINUX
  • NODE.JS
  • NODE.JS
  • PHP
  • POSTGRESQL
  • PYTHON
  • REACT
  • RUST
  • SQL
  • SYMFONY
  • TYPESCRIPT
  • VISUAL STUDIO CODE
  • WINDOWS
  • WINDOWS
  • WORDPRESS
  • YOUTUBE
  • ZABBIX
  • ZABBIX
  • НОВОСТИ
  • ОБУЧЕНИЕ
  • СТАТЬИ
  • УСЛУГИ
  • ЯНДЕКС
  • Telegram
  • VK
  • Facebook
  • Instagram
  • ГЛАВНАЯ
  • НОВОСТИ
  • СТАТЬИ
  • ОБУЧЕНИЕ
  • АЙТИ-МИР
  • САЙТЫ
  • УСЛУГИ
  • ПОДДЕРЖКА
COPYRIGHT © - ITWORLD.UZ, 2023. ВСЕ ПРАВА ЗАЩИЩЕНЫ
Education Soul by WEN Themes