crud implementation #2

Open
romanov73 wants to merge 7 commits from crud into master
11 changed files with 426 additions and 28 deletions

View File

@ -13,10 +13,6 @@ apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'gs-serving-web-content'
version = '0.1.0'
}
repositories {
mavenCentral()
@ -27,9 +23,13 @@ targetCompatibility = 17
dependencies {
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
implementation group: 'org.springframework.boot', name: 'spring-boot-devtools'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
implementation group: 'com.h2database', name: 'h2'
implementation group: 'javax.xml.bind', name: 'jaxb-api'
implementation group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
implementation group: 'javassist', name: 'javassist', version: '3.12.1.GA'
implementation group: 'junit', name: 'junit'
}

View File

@ -1,6 +1,8 @@
package email;
import email.model.Email;
import email.model.EmailForm;
import email.service.EmailService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@ -9,6 +11,11 @@ import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class EmailController {
private final EmailService emailService;
public EmailController(EmailService emailService) {
this.emailService = emailService;
}
@GetMapping("/")
public String indexForm(Model model) {
@ -22,7 +29,14 @@ public class EmailController {
model.addAttribute("error", "'Кому' не должно быть пустым");
return "index";
}
return "result";
emailService.save(new Email(emailForm.getTo(), emailForm.getSubject(), emailForm.getMessage()));
model.addAttribute("emails", emailService.getAllEmails());
return "list";
}
@GetMapping("/list")
public String list(Model model) {
model.addAttribute("emails", emailService.getAllEmails());
return "list";
}
}

View File

@ -0,0 +1,49 @@
package email.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/{articlename:\\w+}");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("/webjars/");
}
@Bean
public LocaleResolver localeResolver() {
return new CookieLocaleResolver();
}
@Bean
public LocaleChangeInterceptor localeInterceptor() {
LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
localeInterceptor.setParamName("lang");
return localeInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeInterceptor());
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}

View File

@ -0,0 +1,83 @@
package email.core;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@MappedSuperclass
public abstract class BaseEntity implements Serializable, Comparable<BaseEntity> {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Integer id;
@Version
private Integer version;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!getClass().isAssignableFrom(obj.getClass())) {
return false;
}
BaseEntity other = (BaseEntity) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (id == null ? 0 : id.hashCode());
return result;
}
@Override
public String toString() {
return getClass().getSimpleName() + "{" +
"id=" + id +
", version=" + version +
'}';
}
@Override
public int compareTo(@NotNull BaseEntity o) {
return id != null ? id.compareTo(o.getId()) : -1;
}
public void reset() {
this.id = null;
this.version = null;
}
}

View File

@ -0,0 +1,46 @@
package email.model;
import email.core.BaseEntity;
import javax.persistence.Entity;
@Entity
public class Email extends BaseEntity {
private String to;
private String subject;
private String message;
public Email() {
}
public Email(String to, String subject, String message) {
this.to = to;
this.subject = subject;
this.message = message;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -0,0 +1,10 @@
package email.repository;
import email.model.Email;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface EmailRepository extends JpaRepository<Email, Integer> {
}

View File

@ -0,0 +1,33 @@
package email.service;
import email.model.Email;
import email.repository.EmailRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class EmailService {
private final EmailRepository emailRepository;
public EmailService(EmailRepository emailRepository) {
this.emailRepository = emailRepository;
}
public List<Email> getAllEmails() {
return emailRepository.findAll();
}
public Email save(Email email) {
return emailRepository.save(email);
}
public Email getEmailById(Integer id) {
return emailRepository.getOne(id);
}
public void delete(Integer setId) {
emailRepository.deleteById(setId);
}
}

View File

@ -0,0 +1,14 @@
# Server Settings
spring.main.banner-mode=off
server.port=8080
# Log settings (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF)
logging.level.ru.ulstu=DEBUG
#JPA
# go to http://localhost:8080/h2-console
spring.datasource.url=jdbc:h2:file:./data/emails
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -2,29 +2,77 @@
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Простая обработка формы на Spring MVC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
</head>
<body>
<h1>Форма</h1>
<!-- компонент меню-->
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Название web-приложения</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/">Главная страница</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/list">Список отправленных сообщений</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Выпадающее меню
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Пункт 1</a></li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled">Недоступно</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 col-sm-12">
<h2>Форма</h2>
<form action="#" th:action="@{/sendEmail}" th:object="${emailForm}" method="post">
<p style="color:red" th:text="${error}"></p>
<table>
<tr>
<td>Тема:</td>
<td><input type="text" th:field="*{subject}"/></td>
</tr>
<tr>
<td>Кому:</td>
<td><input type="text" th:field="*{to}"/></td>
</tr>
<tr>
<td>Сообщение:</td>
<td><textarea th:field="*{message}"/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Отправить"/></td>
</tr>
</table>
<div class="form-group">
<label for="theme">Тема</label>
<input type="text" class="form-control" id="theme" placeholder="Введите тему" th:field="*{subject}">
</div>
<div class="form-group">
<label for="to">Кому</label>
<input class="form-control" type="email" id="to" th:field="*{to}" placeholder="Кому"/>
</div>
<div class="form-group">
<label for="message">Сообщение</label>
<textarea class="form-control" id="message" th:field="*{message}" placeholder="Сообщение"/>
</div>
<input class="form-group" type="submit" value="Отправить"/>
</form>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8"
crossorigin="anonymous"></script>
</body>
</html>

View File

@ -0,0 +1,101 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Список записей в БД</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
</head>
<body>
<!-- компонент меню-->
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Название web-приложения</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/">Главная страница</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/list">Список отправленных сообщений</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Выпадающее меню
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Пункт 1</a></li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Пункт 3</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled">Недоступно</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 col-sm-12">
<h2>Список записей в БД:</h2>
<div class="row">
<div class="col-md-4" style="font-weight: bold">
Кому
</div>
<div class="col-md-4" style="font-weight: bold">
Тема
</div>
<div class="col-md-4" style="font-weight: bold">
Сообщение
</div>
</div>
<div class="row" th:each="email: ${emails}">
<div class="col-md-4" th:text="${email.to}"/>
<div class="col-md-4" th:text="${email.subject}"/>
<div class="col-md-4" th:text="${email.message}"/>
</div>
<!--<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th scope="col">Кому</th>
<th scope="col">Тема</th>
<th scope="col">Сообщение</th>
</tr>
</thead>
<tbody>
<tr th:each="email: ${emails}">
<td th:text="${email.to}">
</td>
<td th:text="${email.subject}">
</td>
<td th:text="${email.message}">
</td>
</tr>
</tbody>
</table>-->
<a class="btn btn-primary" href="/">Отправить другое сообщение</a>
<!-- <img src="img/logo.png"/>-->
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8"
crossorigin="anonymous"></script>
</body>
</html>