Validation 활용
- JSON 객체는 파라미터가 되는 필드들을 JSON 객체로 감싼다.
- 즉, 어떤 필드가 null인지 알 수 없다.
validation 적용
- 필드에 NotNull 조건 추가
- @NotNull 어노테이션 추가
public class UserVO implements Serializable{
...
@NotNull(message = "userName필드가 null입니다.")
private String userName;
...
}
- controller 클레스에 validation 적용
- @Validated 어노테이션 추가
@RequestMapping(value = "/regist")
public ResponseEntity<?> registUser(@Validated @RequestBody UserVO userVO){
System.out.println("controller vo check::" + userVO.toString() );
userService.createUser(userVO);
return new ResponseEntity(null, HttpStatus.OK);
}
예외 처리를 위한 ControllerAdvice
Controller에 대한 예외 처리
@ControllerAdvice
- Controller 클래스들의 모든 예외에 대해서 공통으로 초리할 수 있다.
- 이를 사용하려면
@EnableWebMvc
선언 또는<mvc:annotation-driven/>
추가
예외 클래스 작성
- 에러 정보 전달 클래스
public class UserNotFoundException extends RuntimeException{
private static final long serialVersionUID = 1L;
public UserNotFoundException() {
}
public UserNotFoundException(String message) {
super(message);
}
}
- 서비스 클래스
@Service
public class UserService {
@Autowired
UserRepository userRepository;
public Iterable<UserVO> findAllUserInfo(){
Iterable<UserVO> allUsers = userRepository.getUserInfoAll();
return allUsers;
}
public void dummyInfo(){
ServletUriComponentsBuilder.fromCurrentRequest()
.toUriString();
}
public void createUser(UserVO userVO){
System.out.println("userVO::" + userVO.toString());
userRepository.adduserInfo(userVO);
}
public Iterable<? extends UserVO> findByLikeUserName(String userName){
Iterable<UserVO> resultList = userRepository.findByUserNameLike(userName);
return resultList;
}
public UserVO findByOneUserName(String userName){
UserVO userVO = userRepository.findByUserName(userName);
return userVO;
}
}
ExceptionHadnler
@ControllerAdvice
선언 후@ExceptionHandler
로 예외를 명시할 수 있음@ResponseStatus
로 예외 응답 코드를 정의할 수도 있음
@ControllerAdvice
public class ApiExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ResponseEntity<ApiErrorDetail> handleUserNotFoundException(UserNotFoundException unfe){
ApiErrorDetail errorDetail = new ApiErrorDetail();
errorDetail.setTimeStamp(new Date());
errorDetail.setCode(1002);// 별도의 예외코드 추가
errorDetail.setMessage(unfe.getMessage());
return new ResponseEntity(errorDetail, HttpStatus.NOT_FOUND);
}
}
DB 예외 처리
Transaction
Database 참고
PlatformTransactionManager
- PlatformTransactionManager를 추상화해서 트랜잭션에 관련된 특정 기술에 대한 종속성을 낮춤
Transaction 설정
- TransactionManagerConfigure를 추가
@Configuration
@EnableTransactionManagement
@PropertySource("application.properties")
public class MariaDBConnectionConfig implements TransactionManagementConfigurer{
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String dbUsername;
@Value("${spring.datasource.password}")
private String dbPassword;
@Value("${spring.datasource.classname}")
private String dbClassName;
@Lazy
@Bean(destroyMethod = "close")
public DataSource dataSource(){
final HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setUsername(dbUsername);
hikariConfig.setPassword(dbPassword);
hikariConfig.addDataSourceProperty("url", dbUrl);
hikariConfig.setDataSourceClassName(dbClassName);
hikariConfig.setLeakDetectionThreshold(2000);
hikariConfig.setPoolName("jpubDBpool");
final HikariDataSource dataSource = new HikariDataSource(hikariConfig);
return dataSource;
}
@Bean
public DataSourceTransactionManager transactionManager(){
return new DataSourceTransactionManager(dataSource());
}
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return transactionManager();
}
}
spring transaction과 Service 레이어
- Repository Layer에서는 하나의 DB table을 대상으로 데이터 입력 조회 갱신 등의 기능을 가진 메서드들이 필요
- Service Layer에서는 위의 메서드들을 모아서 한 번의 요청 안에서 여러 테이블을 조회하거나 갱신할 필요가 있음
- 대부분 트랜잭션에 대한 롤백 설정은 Service Layer에서 처리
@Transacional 어노테이션
@Transacional
- 트랜잭션 제어가 필요한 메서드에 사용
- 인터페이스나 추상 클래스에는 사용 X
- 실제 구현 클래스 내에서 사용
- 롤벡에 관련된 속성값을 정의할 수 있음
- isolation
- propagation
- readOnly
- rollbackFor
- no-rollback-for
- timeout
Spring Boot Test
- 단위 테스트 작성 시
- junit, mockito, spring-test를 추가해 사용함
- spring-boot-test-starter는 테스트에 필요한 의존성들을 spring-starter로 만들어 모아 놓은 모듈
- 이를 사용하면 테스트 관련 라이브러리들을 별도로 추가하지 않아도 됨
DB 연동 테스트
- 의존성 추가
testCompile("org.springframework.boot:spring-boot-starter-test")
- testCompile은 테스트 시에만 의존성 추가됨DB 연동 테스트 코드
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyBatisConfig.class, loader = AnnotationConfigContextLoader.class)
@Rollback
public class MybatisTestConfig {
}
- UserRepository 클래스 테스트 클래스
public class UserDaoTest extends MybatisTestConfig {
@Autowired
private UserRepository userRepository;
@Test
public void testList(){
System.out.println(userRepository.getUserInfoAll());
}
@Test
public void createUser(){
UserVO userVO = new UserVO();
userVO.setId("jpub115");
userVO.setUserName("홍길동");
userVO.setEmail("test4@jpub.com");
userRepository.adduserInfo(userVO);
System.out.println(userRepository.getUserInfoAll());
}
}
Service 클래스의 단위 테스트
- 위와 동일하게 test에 Service 클래스를 스캐닝하는 설정 클래스를 로드
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ServiceConfig.class, loader = AnnotationConfigContextLoader.class)
@Rollback
public class ServiceTestConfig {
}
- 테스트 클래스
public class UserServiceTest extends ServiceTestConfig {
@Autowired
UserService userService;
@Test
public void findUserList(){
userService.findAllUserInfo();
}
@Test
public void findUserNameTest(){
String uname = "kim1";
System.out.println(userService.findByOneUserName(uname));
}
}
통합 테스트
- 최초의 사용자 액션에 접점이 되는 컨트롤러부터 지금까지 테스트해 온 모든 테스트를 합친 test
- 매우 복잡함
- 톰캣 또는 임베디드 톰캣을 실행
- 다른 모든 계층 클래스들의 메서드들의 정상 실행
- 통합 테스트와 단위 테스트는 분리해서 관리통합 테스트를 위한 gradle 설정
- 다음은 integrationTest 폴더 하위에 작성한 코드들이 클래스 패스에
integrationTest {
java.srcDir "src/integrationTest/java"
resources.srcDir "src/integrationTest/resources"
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
}
- 통합 테스트용 task 추가 및 단위 테스트와의 관계 설정
task integrationTest(type: Test) {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
outputs.upToDateWhen { false }
}
check.dependsOn integrationTest
integrationTest.mustRunAfter test
'WebStudy > Spring' 카테고리의 다른 글
Spring Security (0) | 2021.08.03 |
---|---|
Spring Cache (0) | 2021.07.28 |
Boot Starter (0) | 2021.07.22 |
Annotation (0) | 2021.07.21 |
REST API 2 (0) | 2021.07.20 |
최근댓글