Начало работ над 4-й лабораторной.
This commit is contained in:
parent
c4e3593fa4
commit
2844d545ce
8
.idea/discord.xml
Normal file
8
.idea/discord.xml
Normal 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>
|
@ -20,6 +20,9 @@ dependencies {
|
|||||||
|
|
||||||
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5'
|
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'
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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("*");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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> {
|
||||||
|
}
|
@ -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> {
|
||||||
|
}
|
@ -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> {
|
||||||
|
}
|
@ -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> {
|
||||||
|
}
|
@ -3,27 +3,32 @@ package premium_store.service;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import premium_store.model.Level;
|
import premium_store.model.Level;
|
||||||
|
import premium_store.repository.LevelRepository;
|
||||||
|
import premium_store.util.validation.ValidatorUtil;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.EntityNotFoundException;
|
import javax.persistence.EntityNotFoundException;
|
||||||
import javax.persistence.PersistenceContext;
|
import javax.persistence.PersistenceContext;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
//сервис после удаления EntityManager и добавления нашего репозитория. То есть у него уже все методы работы с полями прописаны за нас?
|
||||||
@Service
|
@Service
|
||||||
public class LevelService {
|
public class LevelService {
|
||||||
@PersistenceContext
|
@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
|
@Transactional
|
||||||
public Level addLevel(int newLevel) {
|
public Level addLevel(int newLevel) {
|
||||||
if (newLevel <= 0) {
|
|
||||||
throw new IllegalArgumentException("Level name is zero or less");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Level level = new Level(newLevel);
|
final Level level = new Level(newLevel);
|
||||||
em.persist(level);
|
validatorUtil.validate(level);
|
||||||
|
|
||||||
return level;
|
return levelRepository.save(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
spring.main.banner-mode=off
|
spring.main.banner-mode=off
|
||||||
#server.port=8080
|
server.port=8080
|
||||||
spring.datasource.url=jdbc:h2:file:./data
|
spring.datasource.url=jdbc:h2:file:./data
|
||||||
spring.datasource.driverClassName=org.h2.Driver
|
spring.datasource.driverClassName=org.h2.Driver
|
||||||
spring.datasource.username=sa
|
spring.datasource.username=sa
|
||||||
|
Loading…
Reference in New Issue
Block a user