Начало работ над 4-й лабораторной.

This commit is contained in:
Programmist73 2023-04-08 23:01:18 +04:00
parent c4e3593fa4
commit 2844d545ce
16 changed files with 194 additions and 8 deletions

8
.idea/discord.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="ASK" />
<option name="nameOverrideEnabled" value="true" />
<option name="description" value="" />
</component>
</project>

View File

@ -20,6 +20,9 @@ dependencies {
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5'
implementation 'org.hibernate.validator:hibernate-validator'
implementation 'org.springdoc:springdoc-openapi-ui:1.6.5'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

View File

@ -0,0 +1,15 @@
package premium_store;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//отключение Cors фильтра - не позволяет организовавыть взаимодействие с разных доменов
@Configuration
class WebConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
}

View File

@ -0,0 +1,7 @@
package premium_store.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import premium_store.model.Client;
public interface ClientRepository extends JpaRepository<Client, Long> {
}

View File

@ -0,0 +1,9 @@
package premium_store.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import premium_store.model.Level;
//класс для взаимодействия с БД вместо низкоуровневого EntityManager
//передаём тип класса и тип id его элементов
public interface LevelRepository extends JpaRepository<Level, Long> {
}

View File

@ -0,0 +1,9 @@
package premium_store.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import premium_store.model.Nation;
//класс для взаимодействия с БД вместо низкоуровневого EntityManager
//передаём тип класса и тип id его элементов
public interface NationRepository extends JpaRepository<Nation, Long> {
}

View File

@ -0,0 +1,7 @@
package premium_store.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import premium_store.model.Tank;
public interface TankRepository extends JpaRepository<Tank, Long> {
}

View File

@ -3,27 +3,32 @@ package premium_store.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import premium_store.model.Level;
import premium_store.repository.LevelRepository;
import premium_store.util.validation.ValidatorUtil;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;
import java.util.List;
//сервис после удаления EntityManager и добавления нашего репозитория. То есть у него уже все методы работы с полями прописаны за нас?
@Service
public class LevelService {
@PersistenceContext
private EntityManager em;
private final LevelRepository levelRepository;
private final ValidatorUtil validatorUtil;
public LevelService(LevelRepository levelRepository, ValidatorUtil validatorUtil){
this.levelRepository = levelRepository;
this.validatorUtil = validatorUtil;
}
@Transactional
public Level addLevel(int newLevel) {
if (newLevel <= 0) {
throw new IllegalArgumentException("Level name is zero or less");
}
final Level level = new Level(newLevel);
em.persist(level);
validatorUtil.validate(level);
return level;
return levelRepository.save(level);
}
@Transactional(readOnly = true)

View File

@ -0,0 +1,7 @@
package premium_store.service.exception;
public class ClientNotFoundException extends RuntimeException {
public ClientNotFoundException(Long id) {
super(String.format("Student with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,10 @@
package premium_store.service.exception;
//класс-обработчик ошибки, когда вытаемся вытащить студента из бд по некорректному id
//наследуем от RuntimeException, т. к. он позволяет его проще вызывать
public class LevelNotFoundException extends RuntimeException {
public LevelNotFoundException(Long id) {
super(String.format("Level with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,7 @@
package premium_store.service.exception;
public class NationNotFoundException extends RuntimeException {
public NationNotFoundException(Long id) {
super(String.format("Student with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,7 @@
package premium_store.service.exception;
public class TankNotFoundException extends RuntimeException {
public TankNotFoundException(Long id) {
super(String.format("Student with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,50 @@
package premium_store.util.error;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import premium_store.service.exception.ClientNotFoundException;
import premium_store.service.exception.LevelNotFoundException;
import premium_store.service.exception.NationNotFoundException;
import premium_store.service.exception.TankNotFoundException;
import premium_store.util.validation.ValidationException;
import java.util.stream.Collectors;
//контроллер для обработки разнообразных ошибок при работе с запросами к БД
@ControllerAdvice
public class AdviceController {
//метод handleException будет вызываться при возникновении исключений типа LevelNotFoundException и т. д.
@ExceptionHandler({
LevelNotFoundException.class,
NationNotFoundException.class,
ClientNotFoundException.class,
TankNotFoundException.class,
ValidationException.class
})
public ResponseEntity<Object> handleException(Throwable e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
//при исключении автоматической валидации данных
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleBindException(MethodArgumentNotValidException e) {
final ValidationException validationException = new ValidationException(
e.getBindingResult().getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toSet()));
return handleException(validationException);
}
//обработка неизвестных ошибок
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleUnknownException(Throwable e) {
e.printStackTrace();
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}

View File

@ -0,0 +1,10 @@
package premium_store.util.validation;
import java.util.Set;
//класс для передачи списка ошибок, если они возникают
public class ValidationException extends RuntimeException {
public ValidationException(Set<String> errors) {
super(String.join("\n", errors));
}
}

View File

@ -0,0 +1,32 @@
package premium_store.util.validation;
import org.springframework.stereotype.Component;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Set;
import java.util.stream.Collectors;
//компонент для ручной валидации данных (проверка на заполнение или пустоту, выход за допустимые диапазоны значений и т. д.)
@Component
public class ValidatorUtil {
private final Validator validator;
public ValidatorUtil() {
try (ValidatorFactory factory = Validation.buildDefaultValidatorFactory()) {
this.validator = factory.getValidator();
}
}
public <T> void validate(T object) {
final Set<ConstraintViolation<T>> errors = validator.validate(object);
if (!errors.isEmpty()) {
throw new ValidationException(errors.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toSet()));
}
}
}

View File

@ -1,5 +1,5 @@
spring.main.banner-mode=off
#server.port=8080
server.port=8080
spring.datasource.url=jdbc:h2:file:./data
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa