├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ ├── codeql-analysis.yml │ └── test.yml ├── .gitignore ├── .gitpod.Dockerfile ├── .gitpod.yml ├── .sonarcloud.properties ├── README.md ├── SpringBootAOP ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── java │ │ │ ├── SpringBootAopApplication.java │ │ │ ├── component │ │ │ └── SimpleAspect.java │ │ │ ├── config │ │ │ └── AspectJConfig.java │ │ │ ├── service │ │ │ ├── TestService.java │ │ │ └── TestServiceImpl.java │ │ │ └── web │ │ │ └── TestController.java │ ├── kotlin │ │ └── com │ │ │ └── example │ │ │ └── kotlin │ │ │ ├── SpringBootAopApplication.kt │ │ │ ├── component │ │ │ └── SimpleAspect.kt │ │ │ ├── config │ │ │ └── AspectJConfig.kt │ │ │ ├── service │ │ │ ├── TestService.kt │ │ │ └── TestServiceImpl.kt │ │ │ └── web │ │ │ └── TestController.kt │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── java │ └── SpringBootAopApplicationTests.java ├── SpringBootAsync ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── java │ │ │ ├── SpringBootAsyncApplication.java │ │ │ ├── config │ │ │ └── AsyncConfig.java │ │ │ ├── service │ │ │ └── BasicService.java │ │ │ └── web │ │ │ └── BasicController.java │ ├── kotlin │ │ └── com │ │ │ └── example │ │ │ └── kotlin │ │ │ ├── SpringBootAsyncApplication.kt │ │ │ ├── config │ │ │ └── AsyncConfig.kt │ │ │ ├── service │ │ │ └── BasicService.kt │ │ │ └── web │ │ │ └── BasicController.kt │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── java │ └── SpringBootAsyncApplicationTests.java ├── SpringBootBatch ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── heowc │ │ │ ├── EndOfDayJobConfig.java │ │ │ ├── SimpleJobLauncherController.java │ │ │ └── SpringBootBatchApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── heowc │ └── BatchTest.java ├── SpringBootCache ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── java │ │ │ ├── SpringBootCacheApplication.java │ │ │ ├── component │ │ │ ├── BookRepository.java │ │ │ └── SimpleBookRepository.java │ │ │ └── domain │ │ │ └── Book.java │ ├── kotlin │ │ └── com │ │ │ └── example │ │ │ └── kotlin │ │ │ ├── SpringBootCacheApplication.kt │ │ │ ├── component │ │ │ ├── BookRepository.kt │ │ │ └── SimpleBookRepository.kt │ │ │ └── domain │ │ │ └── Book.kt │ └── resources │ │ └── application.properties │ └── test │ ├── java │ └── com │ │ └── example │ │ └── java │ │ └── SpringBootCacheApplicationTests.java │ └── kotlin │ └── com │ └── example │ └── kotlin │ └── SpringBootCacheApplicationTests.kt ├── SpringBootCors ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── java │ │ │ ├── SpringBootCorsApplication.java │ │ │ ├── config │ │ │ └── WebConfig.java │ │ │ ├── domain │ │ │ └── Message.java │ │ │ └── web │ │ │ └── MessageController.java │ ├── kotlin │ │ └── com │ │ │ └── example │ │ │ └── kotlin │ │ │ ├── SpringBootCorsApplication.kt │ │ │ ├── config │ │ │ └── WebConfig.kt │ │ │ ├── domain │ │ │ └── Message.kt │ │ │ └── web │ │ │ └── MessageController.kt │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── java │ └── SpringBootCorsApplicationTests.java ├── SpringBootCustomJackson ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── java │ │ │ ├── SpringBootCustomJacksonApplication.java │ │ │ ├── component │ │ │ └── EncodedJsonComponent.java │ │ │ ├── domain │ │ │ └── Model.java │ │ │ └── web │ │ │ └── BasicController.java │ ├── kotlin │ │ └── com │ │ │ └── example │ │ │ └── kotlin │ │ │ ├── SpringBootCustomJacksonApplication.kt │ │ │ ├── component │ │ │ └── EncodedJsonComponent.kt │ │ │ ├── domain │ │ │ └── Model.kt │ │ │ └── web │ │ │ └── BasicController.kt │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── java │ └── SpringBootCustomJacksonApplicationTests.java ├── SpringBootDocker ├── README.md ├── build.gradle ├── gradle.properties └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── java │ │ │ ├── SimpleController.java │ │ │ └── SpringBootDockerApplication.java │ ├── kotlin │ │ └── com │ │ │ └── example │ │ │ └── kotlin │ │ │ ├── SimpleController.kt │ │ │ └── SpringBootDockerApplication.kt │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── java │ └── SpringBootDockerApplicationTests.java ├── SpringBootDynamo ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── DynamoDBConfig.java │ │ │ └── SpringBootDynamoApplication.java │ └── resources │ │ └── application.properties │ └── test │ ├── java │ └── com │ │ └── example │ │ ├── AbstractIntegrationTest.java │ │ └── SpringBootDynamoApplicationTests.java │ └── resources │ └── application.properties ├── SpringBootEvent ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── heowc │ │ │ ├── SpringBootEventApplication.java │ │ │ ├── domain │ │ │ ├── Member.java │ │ │ ├── MemberRepository.java │ │ │ ├── MemberRequest.java │ │ │ ├── NotFoundMemberIdException.java │ │ │ └── PasswordNotMatchingException.java │ │ │ ├── event │ │ │ ├── PasswordChangedEvent.java │ │ │ └── PasswordChangedEventListener.java │ │ │ └── service │ │ │ ├── DefaultPasswordChangingService.java │ │ │ ├── DummySendService.java │ │ │ ├── PasswordChangingService.java │ │ │ └── SendService.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── heowc │ └── PasswordChangingServiceTest.java ├── SpringBootExcel ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── SpringBootExcelApplication.java │ │ │ ├── component │ │ │ ├── ExcelReader.java │ │ │ └── ExcelWriter.java │ │ │ ├── config │ │ │ └── WebConfig.java │ │ │ ├── constant │ │ │ └── ExcelConstant.java │ │ │ ├── domain │ │ │ └── Product.java │ │ │ ├── view │ │ │ ├── ExcelXlsView.java │ │ │ ├── ExcelXlsxStreamingView.java │ │ │ └── ExcelXlsxView.java │ │ │ └── web │ │ │ ├── DownloadExcelController.java │ │ │ └── UploadExcelController.java │ └── resources │ │ └── application.properties │ └── test │ ├── java │ └── com │ │ └── example │ │ └── SpringBootExcelApplicationTests.java │ └── resources │ ├── application.properties │ └── test.xlsx ├── SpringBootException ├── build.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── tistory │ │ └── heowc │ │ ├── SpringBootExceptionApplication.java │ │ ├── advice │ │ └── GlobalRestControllerAdvicer.java │ │ ├── domain │ │ └── ErrorInfo.java │ │ ├── exception │ │ └── ExtensionException.java │ │ └── web │ │ └── BasicController.java │ └── test │ └── java │ └── com │ └── tistory │ └── heowc │ └── SpringBootExceptionApplicationTests.java ├── SpringBootGRpc ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── SpringBootGRpcApplication.java │ ├── proto │ │ └── message_sender.proto │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── SpringBootGRpcApplicationTests.java ├── SpringBootGracefulShutdown ├── README.md ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── example │ │ └── SpringBootGracefulShutdownApplication.java │ └── resources │ └── application.properties ├── SpringBootHateoas ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── Message.java │ │ │ ├── MessageController.java │ │ │ ├── MessageModel.java │ │ │ ├── MessageResourceAssembler.java │ │ │ └── SpringBootHateoasApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── SpringBootHateoasApplicationTests.java ├── SpringBootInterceptor ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── SpringBootInterceptorApplication.java │ │ │ ├── advice │ │ │ └── HttpResponseAdvice.java │ │ │ ├── component │ │ │ └── HttpInterceptor.java │ │ │ ├── config │ │ │ └── WebMvcConfig.java │ │ │ └── controller │ │ │ ├── IndexController.java │ │ │ └── UserController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── SpringBootInterceptorApplicationTests.java ├── SpringBootJpa ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── java │ │ │ ├── SpringBootJpaApplication.java │ │ │ ├── onetomany │ │ │ ├── domain │ │ │ │ ├── Order.java │ │ │ │ └── Product.java │ │ │ └── repository │ │ │ │ ├── OrderRepository.java │ │ │ │ └── ProductRepository.java │ │ │ ├── onetoone │ │ │ ├── domain │ │ │ │ ├── Market.java │ │ │ │ └── Owner.java │ │ │ └── repository │ │ │ │ ├── MarketRepository.java │ │ │ │ └── OwnerRepository.java │ │ │ └── simple │ │ │ ├── domain │ │ │ ├── Customer.java │ │ │ └── TimeData.java │ │ │ ├── repository │ │ │ ├── CustomJpqlRepository.java │ │ │ ├── CustomerRepository.java │ │ │ ├── SimpleCustomJpqlRepository.java │ │ │ └── TimeDataRepository.java │ │ │ ├── service │ │ │ ├── CustomService.java │ │ │ └── SimpleCustomerService.java │ │ │ └── web │ │ │ └── TimeController.java │ ├── kotlin │ │ └── com │ │ │ └── example │ │ │ └── kotlin │ │ │ ├── SpringBootJpaApplication.kt │ │ │ ├── onetomany │ │ │ ├── domain │ │ │ │ ├── Order.kt │ │ │ │ └── Product.kt │ │ │ └── repository │ │ │ │ ├── OrderRepository.kt │ │ │ │ └── ProductRepository.kt │ │ │ ├── onetoone │ │ │ ├── domain │ │ │ │ ├── Market.kt │ │ │ │ └── Owner.kt │ │ │ └── repository │ │ │ │ ├── MarketRepository.kt │ │ │ │ └── OwnerRepository.kt │ │ │ └── simple │ │ │ ├── domain │ │ │ ├── Customer.kt │ │ │ └── TimeData.kt │ │ │ ├── repository │ │ │ ├── CustomJpqlRepository.kt │ │ │ ├── CustomerRepository.kt │ │ │ ├── SimpleCustomJpqlRepository.kt │ │ │ └── TimeDataRepository.kt │ │ │ ├── service │ │ │ ├── CustomService.kt │ │ │ └── SimpleCustomerService.kt │ │ │ └── web │ │ │ └── TimeController.kt │ └── resources │ │ └── application.properties │ └── test │ ├── java │ └── com │ │ └── example │ │ └── java │ │ ├── CustomerRepositoryTests.java │ │ ├── EntityManagerTests.java │ │ ├── OneToManyTests.java │ │ ├── OneToOneTests.java │ │ └── TimeTests.java │ └── kotlin │ └── com │ └── example │ └── kotlin │ ├── CustomerRepositoryTests.kt │ ├── EntityManagerTests.kt │ ├── OneToManyTests.kt │ ├── OneToOneTests.kt │ └── TimeTests.kt ├── SpringBootJpaSecurity ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── SpringBootJpaSecurityApplication.java │ │ │ ├── config │ │ │ ├── InitRunner.java │ │ │ └── security │ │ │ │ ├── RestAuthenticationProcessingFilter.java │ │ │ │ ├── RestAuthenticationSuccessHandler.java │ │ │ │ ├── SecurityConfig.java │ │ │ │ └── UserDetailsImpl.java │ │ │ ├── domain │ │ │ ├── User.java │ │ │ └── UserRepository.java │ │ │ ├── service │ │ │ └── UserDetailsServiceImpl.java │ │ │ └── web │ │ │ └── UserController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── web │ └── UserControllerTest.java ├── SpringBootLogStash ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tistory │ │ │ └── heowc │ │ │ └── SpringBootLogStashApplication.java │ └── resources │ │ └── logback-spring.xml │ └── test │ └── java │ └── com │ └── tistory │ └── heowc │ └── SpringBootLogStashApplicationTests.java ├── SpringBootMicroMeter ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── CompositeController.java │ │ │ ├── CompositeWithFilterController.java │ │ │ ├── ExecutorServiceController.java │ │ │ ├── GlobalController.java │ │ │ ├── SimpleController.java │ │ │ └── SpringBootMicroMeterApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── SpringBootMicroMeterApplicationTest.java ├── SpringBootMybatis ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tistory │ │ │ └── heowc │ │ │ ├── SpringBootMybatisApplication.java │ │ │ ├── config │ │ │ └── MybatisConfig.java │ │ │ ├── dao │ │ │ └── AccountDao.java │ │ │ ├── domain │ │ │ └── Account.java │ │ │ └── mapper │ │ │ └── AccountMapper.java │ └── resources │ │ ├── application.properties │ │ ├── com │ │ └── tistory │ │ │ └── heowc │ │ │ └── dao │ │ │ └── Account.xml │ │ └── schema.sql │ └── test │ ├── java │ └── com │ │ └── tistory │ │ └── heowc │ │ ├── AccountDaoTests.java │ │ └── AccountMapperTests.java │ └── resources │ └── application.properties ├── SpringBootNotice ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tistory │ │ │ └── heowc │ │ │ ├── SpringBootNoticeApplication.java │ │ │ ├── component │ │ │ └── InitRunner.java │ │ │ ├── config │ │ │ └── WebMvcConfig.java │ │ │ ├── domain │ │ │ ├── Notice.java │ │ │ ├── NoticeWithPage.java │ │ │ └── Page.java │ │ │ ├── repository │ │ │ ├── NoticeRepository.java │ │ │ ├── NoticeRepositoryCustom.java │ │ │ └── NoticeRepositoryImpl.java │ │ │ ├── service │ │ │ ├── NoticeService.java │ │ │ └── NoticeServiceImpl.java │ │ │ ├── util │ │ │ └── PageUtil.java │ │ │ └── web │ │ │ ├── NoticeController.java │ │ │ └── ViewController.java │ └── resources │ │ ├── application.properties │ │ ├── static │ │ └── notice.js │ │ └── templates │ │ ├── notice.ftl │ │ └── notice.html │ └── test │ └── java │ └── com │ └── tistory │ └── heowc │ └── SpringBootNoticeApplicationTests.java ├── SpringBootOAuth2 ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── SpringBootOath2Application.java │ │ │ └── web │ │ │ └── MainController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── SpringBootOath2ApplicationTests.java ├── SpringBootQuartz ├── build.gradle └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── example │ │ │ ├── QuartzJobsConfig.java │ │ │ ├── SimpleJob.java │ │ │ └── SpringBootQuartzApplication.java │ └── resources │ │ └── application.properties │ └── test │ ├── java │ └── org │ │ └── example │ │ └── SpringBootQuartzApplicationTests.java │ └── resources │ └── application-test.properties ├── SpringBootQueryDsl ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tistory │ │ │ └── heowc │ │ │ ├── SpringBootQueryDslApplication.java │ │ │ ├── config │ │ │ └── DatabaseConfig.java │ │ │ ├── domain │ │ │ ├── Grade.java │ │ │ └── Student.java │ │ │ └── repository │ │ │ ├── GradeRepository.java │ │ │ ├── GradeRepositoryCustom.java │ │ │ ├── GradeRepositoryImpl.java │ │ │ ├── StudentRepository.java │ │ │ ├── StudentRepositoryCustom.java │ │ │ └── StudentRepositoryImpl.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── tistory │ └── heowc │ ├── GradeTests.java │ └── StudentTests.java ├── SpringBootRabbitMQ ├── README.md ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── tistory │ │ └── heowc │ │ ├── common │ │ ├── Constant.java │ │ └── Message.java │ │ ├── receiver │ │ ├── MessageReceiver.java │ │ ├── RabbitReceiverConfig.java │ │ └── ReceiverApplication.java │ │ └── sender │ │ ├── SchedlerConfig.java │ │ ├── SendScheduler.java │ │ └── SenderApplication.java │ └── resources │ └── application.properties ├── SpringBootRedis ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tistory │ │ │ └── heowc │ │ │ ├── SpringBootRedisApplication.java │ │ │ └── domain │ │ │ ├── Person.java │ │ │ └── PersonRepository.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── tistory │ └── heowc │ ├── PersonRepositoryTest.java │ └── StringRedisTemplateTest.java ├── SpringBootRest ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── SpringRestApplication.java │ │ │ ├── domain │ │ │ └── Person.java │ │ │ ├── event │ │ │ └── PersonEventHandler.java │ │ │ └── repository │ │ │ └── PersonRepository.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── SpringRestApplicationTests.java ├── SpringBootRestDocs ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tistory │ │ │ └── heowc │ │ │ ├── SpringBootRestDocsApplication.java │ │ │ ├── domain │ │ │ └── Programming.java │ │ │ └── web │ │ │ └── ProgrammingController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── tistory │ └── heowc │ └── SpringBootRestDocsApplicationTests.java ├── SpringBootSecurityAddRedis ├── README.md ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── tistory │ │ └── heowc │ │ ├── SpringBootSecurityAddRedisApplication.java │ │ ├── component │ │ ├── InitRunner.java │ │ └── UserDetailsImpl.java │ │ ├── config │ │ ├── RedisSessionConfig.java │ │ └── SecurityConfig.java │ │ ├── domain │ │ └── Member.java │ │ ├── repository │ │ └── MemberRepository.java │ │ ├── service │ │ └── UserDetailsServiceImpl.java │ │ └── web │ │ └── UserController.java │ └── resources │ └── application.properties ├── SpringBootSecurityJwt ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tistory │ │ │ └── heowc │ │ │ ├── SpringBootSecurityJwtApplication.java │ │ │ ├── auth │ │ │ ├── BaseSecurityHandler.java │ │ │ ├── UserDetailsImpl.java │ │ │ ├── ajax │ │ │ │ ├── AjaxAuthenticationProvider.java │ │ │ │ ├── AjaxUserDetailsService.java │ │ │ │ └── filter │ │ │ │ │ └── AjaxAuthenticationFilter.java │ │ │ └── jwt │ │ │ │ ├── JwtAuthenticationProvider.java │ │ │ │ ├── JwtAuthenticationToken.java │ │ │ │ ├── JwtInfo.java │ │ │ │ ├── JwtUserDetailsService.java │ │ │ │ ├── filter │ │ │ │ └── JwtAuthenticationFilter.java │ │ │ │ └── matcher │ │ │ │ └── SkipPathRequestMatcher.java │ │ │ ├── component │ │ │ └── InitComponent.java │ │ │ ├── config │ │ │ ├── CommonConfig.java │ │ │ └── SecurityConfig.java │ │ │ ├── domain │ │ │ └── Member.java │ │ │ ├── repository │ │ │ └── MemberRepository.java │ │ │ ├── util │ │ │ ├── DateUtil.java │ │ │ └── JwtUtil.java │ │ │ └── web │ │ │ ├── RefreshController.java │ │ │ └── RoleController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── tistory │ └── heowc │ └── SpringBootSecurityJwtApplicationTests.java ├── SpringBootSpringDocOpenApi ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── SpringBootSpringDocOpenApiApplication.java │ │ │ ├── domain │ │ │ ├── Member.java │ │ │ └── MemberRepository.java │ │ │ └── web │ │ │ └── MemberController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── SpringBootSpringDocOpenApiApplicationTests.java ├── SpringBootSse ├── README.md ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── heowc │ │ │ ├── SpringBootSseApplication.java │ │ │ ├── api │ │ │ └── MemberApi.java │ │ │ └── domain │ │ │ ├── Member.java │ │ │ └── MemberRepository.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── heowc │ └── SpringBootSseTests.java ├── SpringBootStatemachine ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── OrderEvent.java │ │ │ ├── OrderState.java │ │ │ ├── Role.java │ │ │ ├── SpringBootStatemachineApplication.java │ │ │ └── StatemachineConfig.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── SpringBootStatemachineApplicationTests.java ├── SpringBootTest ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── SpringBootTestApplication.java │ │ │ ├── domain │ │ │ └── TestMessage.java │ │ │ ├── service │ │ │ ├── BasicService.java │ │ │ └── BasicServiceImpl.java │ │ │ └── web │ │ │ └── BasicController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ ├── MockMvcTest.java │ ├── MockitoBeanTest.java │ ├── SimpleTest.java │ └── TestBeanTest.java ├── SpringBootValidator ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── SpringBootValidatorApplication.java │ │ │ ├── config │ │ │ └── WebMvcConfig.java │ │ │ ├── domain │ │ │ └── Member.java │ │ │ ├── errorhandler │ │ │ ├── ErrorMessage.java │ │ │ └── GlobalExceptionHandler.java │ │ │ ├── validation │ │ │ ├── Phone.java │ │ │ └── PhoneValidator.java │ │ │ └── web │ │ │ └── MemberController.java │ └── resources │ │ ├── ValidationMessages.properties │ │ ├── ValidationMessages_ko.properties │ │ └── application.properties │ └── test │ ├── java │ └── com │ │ └── example │ │ ├── SpringBootValidatorApplicationTests.java │ │ └── web │ │ ├── MemberControllerGetTest.java │ │ └── MemberControllerPostTest.java │ └── resources │ └── application.properties ├── SpringBootVertx ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tistory │ │ │ └── heowc │ │ │ ├── SpringBootVertxApplication.java │ │ │ ├── config │ │ │ ├── AppConfig.java │ │ │ ├── VertxConfig.java │ │ │ └── loader │ │ │ │ ├── DefaultRouterLoader.java │ │ │ │ └── RouterLoader.java │ │ │ ├── domain │ │ │ └── Article.java │ │ │ ├── repository │ │ │ └── ArticleRepository.java │ │ │ ├── router │ │ │ └── ArticleRouter.java │ │ │ ├── service │ │ │ └── ArticleService.java │ │ │ └── verticle │ │ │ ├── ArticleRecipientVerticle.java │ │ │ └── ServerVerticle.java │ └── resources │ │ ├── application.properties │ │ └── banner.txt │ └── test │ └── java │ └── com │ └── tistory │ └── heowc │ └── SpringBootVertxApplicationTests.java ├── SpringBootWar ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── example │ │ ├── SpringBootWarApplication.java │ │ └── web │ │ └── BasicController.java │ └── resources │ └── application.properties ├── SpringBootWebFlux ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── tistory │ │ │ └── heowc │ │ │ ├── SpringBootWebFluxApplication.java │ │ │ ├── config │ │ │ └── AsyncConfig.java │ │ │ ├── domain │ │ │ └── Message.java │ │ │ ├── repository │ │ │ └── MessageRepository.java │ │ │ ├── service │ │ │ └── MessageService.java │ │ │ └── web │ │ │ ├── MessageController.java │ │ │ ├── MessageHandler.java │ │ │ └── MessageRouter.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── tistory │ └── heowc │ └── web │ └── MessageControllerTest.java ├── SpringBootWebSocket ├── build.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── SpringBootWebSocketApplication.java │ │ │ ├── config │ │ │ └── WebSocketConfig.java │ │ │ ├── controller │ │ │ └── ChatController.java │ │ │ └── message │ │ │ └── HelloMessage.java │ └── resources │ │ ├── application.properties │ │ └── static │ │ ├── app.js │ │ ├── index.html │ │ └── main.css │ └── test │ └── java │ └── com │ └── example │ └── SpringBootWebSocketApplicationTests.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gradle" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | timezone: "Asia/Seoul" 13 | time: "10:00" 14 | - package-ecosystem: "github-actions" 15 | directory: "/" 16 | schedule: 17 | interval: "weekly" 18 | timezone: "Asia/Seoul" 19 | time: "10:00" 20 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: [push] 3 | jobs: 4 | test: 5 | runs-on: ubuntu-latest 6 | services: 7 | dynamodb: 8 | image: amazon/dynamodb-local:1.11.477 9 | ports: 10 | - 8000:8000 11 | steps: 12 | - uses: actions/checkout@v4 13 | - name: Set up JDK 17 14 | uses: actions/setup-java@v4 15 | with: 16 | distribution: 'temurin' 17 | java-version: '17' 18 | cache: 'gradle' 19 | - name: Check Gradle Version 20 | run: | 21 | chmod +x gradlew 22 | ./gradlew --version 23 | - name: Test task with Gradle Wrapper 24 | run: | 25 | ./gradlew --parallel --max-workers=4 test 26 | - name: If failure then upload test reports 27 | if: failure() 28 | uses: actions/upload-artifact@v4 29 | with: 30 | path: '*/build/reports/tests' 31 | name: SpringBootSample-reports 32 | retention-days: 7 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | .gradle 5 | **/out 6 | **/build 7 | 8 | 9 | ### STS ### 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | .sts4-cache 17 | 18 | ### IntelliJ IDEA ### 19 | .idea 20 | *.iws 21 | *.iml 22 | *.ipr 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /build/ 27 | /nbbuild/ 28 | /dist/ 29 | /nbdist/ 30 | /.nb-gradle/ 31 | 32 | ## VS Code ## 33 | bin 34 | .vscode -------------------------------------------------------------------------------- /.gitpod.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-full 2 | 3 | RUN bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh && sdk install java 8.0.252.hs-adpt" 4 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: 2 | file: .gitpod.Dockerfile 3 | 4 | tasks: 5 | - init: 'cd "$project" && ../gradlew classes && cd ..' # runs during prebuild 6 | - command: 'cd "$project" && ../gradlew bootRun' 7 | - command: 'gp await-port 8080 && gp preview $(gp url 8080)/$path' 8 | 9 | ports: 10 | - port: 8080 11 | onOpen: ignore 12 | 13 | github: 14 | prebuilds: 15 | master: true 16 | -------------------------------------------------------------------------------- /.sonarcloud.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /SpringBootAOP/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | implementation 'org.springframework.boot:spring-boot-starter-aop' 11 | } 12 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/java/com/example/java/SpringBootAopApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootAopApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootAopApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/java/com/example/java/config/AspectJConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.java.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 5 | 6 | @Configuration 7 | @EnableAspectJAutoProxy 8 | public class AspectJConfig { 9 | } 10 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/java/com/example/java/service/TestService.java: -------------------------------------------------------------------------------- 1 | package com.example.java.service; 2 | 3 | public interface TestService { 4 | 5 | String testAop(); 6 | String test(); 7 | } 8 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/java/com/example/java/service/TestServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.java.service; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Service; 6 | 7 | @Service 8 | public class TestServiceImpl implements TestService { 9 | 10 | private static final Logger logger = LoggerFactory.getLogger(TestServiceImpl.class); 11 | 12 | @Override 13 | public String test() { 14 | String msg = "Hello, Spring Boot No AOP"; 15 | logger.info(msg); 16 | return msg; 17 | } 18 | 19 | @Override 20 | public String testAop() { 21 | String msg = "Hello, Spring Boot AOP"; 22 | logger.info(msg); 23 | return msg; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/java/com/example/java/web/TestController.java: -------------------------------------------------------------------------------- 1 | package com.example.java.web; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import com.example.java.service.TestService; 8 | 9 | @RestController 10 | public class TestController { 11 | 12 | @Autowired 13 | private TestService service; 14 | 15 | @GetMapping(value = "/noAop") 16 | public String noAop() { 17 | return service.test(); 18 | } 19 | 20 | @GetMapping(value = "/aop") 21 | public String aop() { 22 | return service.testAop(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/kotlin/com/example/kotlin/SpringBootAopApplication.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication 4 | import org.springframework.boot.runApplication 5 | 6 | @SpringBootApplication 7 | class SpringBootAopApplication 8 | 9 | fun main(args: Array) { 10 | runApplication(*args) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/kotlin/com/example/kotlin/config/AspectJConfig.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.config 2 | 3 | import org.springframework.context.annotation.Configuration 4 | import org.springframework.context.annotation.EnableAspectJAutoProxy 5 | 6 | @Configuration 7 | @EnableAspectJAutoProxy 8 | class AspectJConfig 9 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/kotlin/com/example/kotlin/service/TestService.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.service 2 | 3 | interface TestService { 4 | 5 | fun testAop(): String 6 | fun test(): String 7 | } 8 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/kotlin/com/example/kotlin/service/TestServiceImpl.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.service 2 | 3 | import org.slf4j.LoggerFactory 4 | import org.springframework.stereotype.Service 5 | 6 | @Service 7 | class TestServiceImpl : TestService { 8 | 9 | private val logger = LoggerFactory.getLogger(TestServiceImpl::class.java) 10 | 11 | override fun test(): String { 12 | val msg = "Hello, Spring Boot With Kotlin No AOP" 13 | logger.info(msg) 14 | return msg 15 | } 16 | 17 | override fun testAop(): String { 18 | val msg = "Hello, Spring Boot With Kotlin AOP" 19 | logger.info(msg) 20 | return msg 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/kotlin/com/example/kotlin/web/TestController.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.web 2 | 3 | import com.example.kotlin.service.TestService 4 | import org.springframework.beans.factory.annotation.Autowired 5 | import org.springframework.web.bind.annotation.GetMapping 6 | import org.springframework.web.bind.annotation.RestController 7 | 8 | @RestController 9 | class TestController (val service: TestService) { 10 | 11 | @GetMapping(value = ["/noAop"]) 12 | fun noAop(): String { 13 | return service.test() 14 | } 15 | 16 | @GetMapping(value = ["/aop"]) 17 | fun aop(): String { 18 | return service.testAop() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootAOP/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootAOP/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootAOP/src/test/java/com/example/java/SpringBootAopApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import com.example.java.component.SimpleAspect; 4 | import com.example.java.service.TestService; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | @SpringBootTest 12 | class SpringBootAopApplicationTests { 13 | 14 | @Autowired 15 | private TestService service; 16 | 17 | @Test 18 | void test_aopAndNoAop() { 19 | assertThat(SimpleAspect.count()).isEqualTo(0); 20 | service.testAop(); 21 | assertThat(SimpleAspect.count()).isEqualTo(1); 22 | service.test(); 23 | assertThat(SimpleAspect.count()).isEqualTo(1); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpringBootAsync/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | group = 'com.example' 3 | version = '0.0.1-SNAPSHOT' 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | 9 | dependencies { 10 | implementation 'org.springframework.boot:spring-boot-starter-webflux' 11 | } 12 | -------------------------------------------------------------------------------- /SpringBootAsync/src/main/java/com/example/java/SpringBootAsyncApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootAsyncApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootAsyncApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootAsync/src/main/java/com/example/java/config/AsyncConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.java.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.scheduling.annotation.AsyncConfigurer; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | 7 | import java.util.concurrent.Executor; 8 | import java.util.concurrent.Executors; 9 | 10 | @Configuration 11 | @EnableAsync 12 | public class AsyncConfig implements AsyncConfigurer { 13 | 14 | @Override 15 | public Executor getAsyncExecutor() { 16 | // ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 17 | // executor.setCorePoolSize(2); 18 | // executor.setMaxPoolSize(10); 19 | // executor.setQueueCapacity(500); 20 | // executor.setThreadNamePrefix("heowc-async-"); 21 | // executor.initialize(); 22 | return Executors.newWorkStealingPool(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpringBootAsync/src/main/java/com/example/java/service/BasicService.java: -------------------------------------------------------------------------------- 1 | package com.example.java.service; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.scheduling.annotation.Async; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class BasicService { 10 | 11 | private static final Logger logger = LoggerFactory.getLogger(BasicService.class); 12 | 13 | @Async 14 | public void onAsync() { 15 | try { 16 | Thread.sleep(1000); 17 | } catch (InterruptedException e) { 18 | e.printStackTrace(); 19 | } 20 | logger.info("onAsync"); 21 | } 22 | 23 | public void onSync() { 24 | try { 25 | Thread.sleep(1000); 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | logger.info("onSync"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SpringBootAsync/src/main/kotlin/com/example/kotlin/SpringBootAsyncApplication.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication 4 | import org.springframework.boot.runApplication 5 | 6 | @SpringBootApplication 7 | class SpringBootAsyncApplication 8 | 9 | fun main(args: Array) { 10 | runApplication(*args) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /SpringBootAsync/src/main/kotlin/com/example/kotlin/config/AsyncConfig.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.config 2 | 3 | import org.springframework.context.annotation.Configuration 4 | import org.springframework.scheduling.annotation.AsyncConfigurer 5 | import org.springframework.scheduling.annotation.EnableAsync 6 | import java.util.concurrent.Executor 7 | import java.util.concurrent.Executors 8 | 9 | @Configuration 10 | @EnableAsync 11 | class AsyncConfig : AsyncConfigurer { 12 | 13 | override fun getAsyncExecutor(): Executor { 14 | // ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 15 | // executor.setCorePoolSize(2); 16 | // executor.setMaxPoolSize(10); 17 | // executor.setQueueCapacity(500); 18 | // executor.setThreadNamePrefix("heowc-async-"); 19 | // executor.initialize(); 20 | return Executors.newWorkStealingPool() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SpringBootAsync/src/main/kotlin/com/example/kotlin/service/BasicService.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.service 2 | 3 | import org.slf4j.LoggerFactory 4 | import org.springframework.scheduling.annotation.Async 5 | import org.springframework.stereotype.Service 6 | 7 | @Service 8 | class BasicService { 9 | 10 | companion object { 11 | private val logger = LoggerFactory.getLogger(BasicService::class.java) 12 | } 13 | 14 | @Async 15 | fun onAsync() { 16 | Thread.sleep(1000) 17 | logger.info("onAsync") 18 | } 19 | 20 | fun onSync() { 21 | Thread.sleep(1000) 22 | logger.info("onSync") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpringBootAsync/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootAsync/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootAsync/src/test/java/com/example/java/SpringBootAsyncApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import com.example.java.service.BasicService; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | 8 | import java.time.Duration; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertTimeout; 11 | import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; 12 | 13 | @SpringBootTest 14 | class SpringBootAsyncApplicationTests { 15 | 16 | @Autowired 17 | private BasicService service; 18 | 19 | @Test 20 | void test_async() { 21 | assertTimeoutPreemptively(Duration.ofMillis(1000), () -> service.onAsync()); 22 | } 23 | 24 | @Test 25 | void test_sync() { 26 | assertTimeout(Duration.ofMillis(1100), () -> service.onSync()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SpringBootBatch/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | implementation 'org.springframework.boot:spring-boot-starter-jdbc' 11 | implementation 'org.springframework.boot:spring-boot-starter-batch' 12 | 13 | runtimeOnly 'com.h2database:h2' 14 | 15 | testImplementation "org.springframework.batch:spring-batch-test" 16 | } 17 | -------------------------------------------------------------------------------- /SpringBootBatch/src/main/java/com/heowc/SpringBootBatchApplication.java: -------------------------------------------------------------------------------- 1 | package com.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootBatchApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootBatchApplication.class, args); 11 | } 12 | } -------------------------------------------------------------------------------- /SpringBootBatch/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.batch.jdbc.initialize-schema=embedded 2 | spring.batch.job.enabled=true -------------------------------------------------------------------------------- /SpringBootBatch/src/test/java/com/heowc/BatchTest.java: -------------------------------------------------------------------------------- 1 | package com.heowc; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.batch.core.ExitStatus; 5 | import org.springframework.batch.core.Job; 6 | import org.springframework.batch.core.JobExecution; 7 | import org.springframework.batch.core.JobParameters; 8 | import org.springframework.batch.test.JobLauncherTestUtils; 9 | import org.springframework.batch.test.context.SpringBatchTest; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; 13 | 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | 16 | @SpringBatchTest 17 | @SpringJUnitConfig(EndOfDayJobConfig.class) 18 | class BatchTest { 19 | 20 | @Autowired 21 | private JobLauncherTestUtils jobLauncherTestUtils; 22 | 23 | @Test 24 | void test(@Autowired Job job) throws Exception { 25 | jobLauncherTestUtils.setJob(job); 26 | JobExecution execution = jobLauncherTestUtils.launchJob(); 27 | assertThat(execution.getExitStatus()).isEqualTo(ExitStatus.COMPLETED); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SpringBootCache/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.jetbrains.kotlin.plugin.jpa' 3 | } 4 | 5 | group = 'com.example' 6 | version = '0.0.1-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation 'org.springframework.boot:spring-boot-starter-cache' 14 | } 15 | -------------------------------------------------------------------------------- /SpringBootCache/src/main/java/com/example/java/SpringBootCacheApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | 7 | @SpringBootApplication 8 | @EnableCaching 9 | public class SpringBootCacheApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringBootCacheApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SpringBootCache/src/main/java/com/example/java/component/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.component; 2 | 3 | import com.example.java.domain.Book; 4 | 5 | public interface BookRepository { 6 | 7 | Book getByIsbn(String isbn); 8 | 9 | void refresh(String isbn); 10 | 11 | } -------------------------------------------------------------------------------- /SpringBootCache/src/main/java/com/example/java/component/SimpleBookRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.component; 2 | 3 | import com.example.java.domain.Book; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.cache.annotation.CacheEvict; 7 | import org.springframework.cache.annotation.Cacheable; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class SimpleBookRepository implements BookRepository { 12 | 13 | private static final Logger logger = LoggerFactory.getLogger(SimpleBookRepository.class); 14 | 15 | private static final String CACHE_BOOK = "book"; 16 | 17 | @Override 18 | @Cacheable(value = CACHE_BOOK, key = "#isbn") 19 | public Book getByIsbn(String isbn) { 20 | simulateSlowService(); 21 | return new Book(isbn, "Some book"); 22 | } 23 | 24 | private void simulateSlowService() { 25 | try { 26 | Thread.sleep(3000L); 27 | } catch (InterruptedException e) { 28 | throw new IllegalStateException(e); 29 | } 30 | } 31 | 32 | @Override 33 | @CacheEvict(value = CACHE_BOOK, key = "#isbn") 34 | public void refresh(String isbn) { 35 | logger.info("cache clear => " + isbn); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /SpringBootCache/src/main/java/com/example/java/domain/Book.java: -------------------------------------------------------------------------------- 1 | package com.example.java.domain; 2 | 3 | public class Book { 4 | 5 | private String isbn; 6 | private String title; 7 | 8 | protected Book() {} 9 | 10 | public Book(String isbn, String title) { 11 | this.isbn = isbn; 12 | this.title = title; 13 | } 14 | 15 | public String getIsbn() { 16 | return isbn; 17 | } 18 | 19 | public void setIsbn(String isbn) { 20 | this.isbn = isbn; 21 | } 22 | 23 | public String getTitle() { 24 | return title; 25 | } 26 | 27 | public void setTitle(String title) { 28 | this.title = title; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "Book{" + "isbn='" + isbn + '\'' + ", title='" + title + '\'' 34 | + '}'; 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /SpringBootCache/src/main/kotlin/com/example/kotlin/SpringBootCacheApplication.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication 4 | import org.springframework.boot.runApplication 5 | import org.springframework.cache.annotation.EnableCaching 6 | 7 | @SpringBootApplication 8 | @EnableCaching 9 | class SpringBootCacheApplication 10 | 11 | fun main(args: Array) { 12 | runApplication(*args) 13 | } -------------------------------------------------------------------------------- /SpringBootCache/src/main/kotlin/com/example/kotlin/component/BookRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.component 2 | 3 | import com.example.kotlin.domain.Book 4 | 5 | interface BookRepository { 6 | 7 | fun getByIsbn(isbn: String): Book 8 | 9 | fun refresh(isbn: String) 10 | 11 | } -------------------------------------------------------------------------------- /SpringBootCache/src/main/kotlin/com/example/kotlin/component/SimpleBookRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.component 2 | 3 | import com.example.kotlin.domain.Book 4 | import org.slf4j.LoggerFactory 5 | import org.springframework.cache.annotation.CacheEvict 6 | import org.springframework.cache.annotation.Cacheable 7 | import org.springframework.stereotype.Component 8 | 9 | @Component 10 | class SimpleBookRepository : BookRepository { 11 | 12 | companion object { 13 | private val logger = LoggerFactory.getLogger(SimpleBookRepository::class.java) 14 | private const val CACHE_BOOK = "book" 15 | } 16 | 17 | @Cacheable(value = [CACHE_BOOK], key = "#isbn") 18 | override fun getByIsbn(isbn: String): Book { 19 | simulateSlowService() 20 | return Book(isbn, "Some book") 21 | } 22 | 23 | private fun simulateSlowService() { 24 | try { 25 | Thread.sleep(3000L) 26 | } catch (e: InterruptedException) { 27 | throw IllegalStateException(e) 28 | } 29 | 30 | } 31 | 32 | @CacheEvict(value = [CACHE_BOOK], key = "#isbn") 33 | override fun refresh(isbn: String) { 34 | logger.info("cache clear => $isbn") 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /SpringBootCache/src/main/kotlin/com/example/kotlin/domain/Book.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.domain 2 | 3 | data class Book(val isbn: String, val title: String) -------------------------------------------------------------------------------- /SpringBootCache/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootCache/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootCors/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | implementation 'org.springframework.boot:spring-boot-starter-webflux' 11 | } 12 | -------------------------------------------------------------------------------- /SpringBootCors/src/main/java/com/example/java/SpringBootCorsApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootCorsApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootCorsApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootCors/src/main/java/com/example/java/domain/Message.java: -------------------------------------------------------------------------------- 1 | package com.example.java.domain; 2 | 3 | public class Message { 4 | 5 | private String sender; 6 | private String content; 7 | 8 | public Message(String sender, String content) { 9 | this.sender = sender; 10 | this.content = content; 11 | } 12 | 13 | public String getSender() { 14 | return sender; 15 | } 16 | 17 | public String getContent() { 18 | return content; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootCors/src/main/java/com/example/java/web/MessageController.java: -------------------------------------------------------------------------------- 1 | package com.example.java.web; 2 | 3 | import com.example.java.domain.Message; 4 | import org.springframework.web.bind.annotation.*; 5 | 6 | @RestController 7 | @RequestMapping("message") 8 | public class MessageController { 9 | 10 | //@CrossOrigin 11 | @GetMapping("{value}") 12 | public String get(@PathVariable String value) { 13 | return value; 14 | } 15 | 16 | @PostMapping 17 | public Message post(@RequestBody Message message) { 18 | return message; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootCors/src/main/kotlin/com/example/kotlin/SpringBootCorsApplication.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication 4 | import org.springframework.boot.runApplication 5 | 6 | @SpringBootApplication 7 | class SpringBootCorsApplication 8 | 9 | fun main(args: Array) { 10 | runApplication(*args) 11 | } -------------------------------------------------------------------------------- /SpringBootCors/src/main/kotlin/com/example/kotlin/domain/Message.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.domain 2 | 3 | data class Message(val sender: String, val content: String) 4 | -------------------------------------------------------------------------------- /SpringBootCors/src/main/kotlin/com/example/kotlin/web/MessageController.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.web 2 | 3 | import com.example.kotlin.domain.Message 4 | import org.springframework.web.bind.annotation.* 5 | 6 | @RestController 7 | @RequestMapping("message") 8 | class MessageController { 9 | 10 | //@CrossOrigin 11 | @GetMapping("{value}") 12 | fun get(@PathVariable value: String): String { 13 | return value 14 | } 15 | 16 | @PostMapping 17 | fun post(@RequestBody message: Message): Message { 18 | return message 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootCors/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootCors/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootCustomJackson/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | } 11 | -------------------------------------------------------------------------------- /SpringBootCustomJackson/src/main/java/com/example/java/SpringBootCustomJacksonApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.ApplicationContext; 8 | 9 | @SpringBootApplication 10 | public class SpringBootCustomJacksonApplication { 11 | 12 | public static void main(String[] args) { 13 | ApplicationContext ctx = SpringApplication.run(SpringBootCustomJacksonApplication.class, args); 14 | 15 | System.out.println("Let's inspect the beans provided by Spring Boot:"); 16 | 17 | Arrays.stream(ctx.getBeanDefinitionNames()).sorted().forEach(System.out::println); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpringBootCustomJackson/src/main/java/com/example/java/domain/Model.java: -------------------------------------------------------------------------------- 1 | package com.example.java.domain; 2 | 3 | public class Model { 4 | 5 | private String name; 6 | private int type; 7 | 8 | protected Model() { } 9 | 10 | public Model(String name, int type) { 11 | this.name = name; 12 | this.type = type; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | public int getType() { 24 | return type; 25 | } 26 | 27 | public void setType(int type) { 28 | this.type = type; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "Model [name=" + name + ", type=" + type + "]"; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SpringBootCustomJackson/src/main/kotlin/com/example/kotlin/SpringBootCustomJacksonApplication.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication 4 | import org.springframework.boot.runApplication 5 | import java.util.* 6 | 7 | @SpringBootApplication 8 | class SpringBootCustomJacksonApplication 9 | 10 | fun main(args: Array) { 11 | 12 | val context = runApplication(*args) 13 | 14 | println("Let's inspect the beans provided by Spring Boot:") 15 | 16 | context.beanDefinitionNames.asList().sorted().forEach { println(it) } 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootCustomJackson/src/main/kotlin/com/example/kotlin/domain/Model.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.domain 2 | 3 | data class Model(val name: String, val type: Int) 4 | -------------------------------------------------------------------------------- /SpringBootCustomJackson/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootCustomJackson/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootCustomJackson/src/test/java/com/example/java/SpringBootCustomJacksonApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class SpringBootCustomJacksonApplicationTests { 8 | 9 | @Test 10 | public void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootDocker/README.md: -------------------------------------------------------------------------------- 1 | ## Docker Image Build 2 | 3 | [Jib](https://github.com/GoogleContainerTools/jib) 4 | 5 | ``` 6 | .\gradlew jib 7 | ``` -------------------------------------------------------------------------------- /SpringBootDocker/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.google.cloud.tools.jib' version '3.4.4' 3 | } 4 | 5 | group = 'com.example' 6 | version = '0.0.1-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation 'org.springframework.boot:spring-boot-starter-web' 14 | } 15 | 16 | jib { 17 | from { 18 | image = 'registry.hub.docker.com/openjdk:8-jre-alpine' 19 | } 20 | to { 21 | image = 'registry.hub.docker.com/heowc1992/my-app' 22 | auth { 23 | username = dockerUsername 24 | password = dockerPassword 25 | } 26 | } 27 | container { 28 | jvmFlags = ['-Djava.security.egd=file:/dev/./urandom', '-Duser.timezone=GMT+09'] 29 | mainClass = 'com.example.java.SpringBootDockerApplication' 30 | // mainClass = 'com.example.kotlin.SpringBootDockerApplicationKt' 31 | ports = ['8080'] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SpringBootDocker/gradle.properties: -------------------------------------------------------------------------------- 1 | dockerUsername= 2 | dockerPassword= -------------------------------------------------------------------------------- /SpringBootDocker/src/main/java/com/example/java/SimpleController.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("/") 9 | public class SimpleController { 10 | 11 | @GetMapping 12 | public String message() { 13 | return "Hello Jib With Java!!"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SpringBootDocker/src/main/java/com/example/java/SpringBootDockerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootDockerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootDockerApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootDocker/src/main/kotlin/com/example/kotlin/SimpleController.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import org.springframework.web.bind.annotation.GetMapping 4 | import org.springframework.web.bind.annotation.RequestMapping 5 | import org.springframework.web.bind.annotation.RestController 6 | 7 | @RestController 8 | @RequestMapping("/") 9 | class SimpleController { 10 | 11 | @GetMapping 12 | fun message(): String { 13 | return "Hello Jib With Kotlin!!" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SpringBootDocker/src/main/kotlin/com/example/kotlin/SpringBootDockerApplication.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication 4 | import org.springframework.boot.runApplication 5 | 6 | @SpringBootApplication 7 | class SpringBootDockerApplication 8 | 9 | fun main(args: Array) { 10 | runApplication(*args) 11 | } 12 | -------------------------------------------------------------------------------- /SpringBootDocker/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootDocker/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootDocker/src/test/java/com/example/java/SpringBootDockerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class SpringBootDockerApplicationTests { 8 | 9 | @Test 10 | public void contextLoad() { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootDynamo/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation platform('software.amazon.awssdk:bom:2.31.40') 10 | implementation 'software.amazon.awssdk:dynamodb' 11 | implementation 'org.springframework.boot:spring-boot-starter-web' 12 | 13 | testImplementation 'org.testcontainers:junit-jupiter:1.21.0' 14 | } -------------------------------------------------------------------------------- /SpringBootDynamo/src/main/java/com/example/SpringBootDynamoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootDynamoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootDynamoApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootDynamo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | aws.region= 2 | aws.dynamo.endpoint= 3 | aws.access-key= 4 | aws.secret-key= -------------------------------------------------------------------------------- /SpringBootDynamo/src/test/java/com/example/AbstractIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.test.context.SpringBootTest; 4 | import org.springframework.test.context.DynamicPropertyRegistry; 5 | import org.springframework.test.context.DynamicPropertySource; 6 | import org.testcontainers.containers.GenericContainer; 7 | import org.testcontainers.junit.jupiter.Testcontainers; 8 | 9 | @SpringBootTest 10 | @Testcontainers(disabledWithoutDocker = true) 11 | public abstract class AbstractIntegrationTest { 12 | 13 | private static final GenericContainer dynamodb = 14 | new GenericContainer("amazon/dynamodb-local:latest").withExposedPorts(8000); 15 | 16 | static { 17 | dynamodb.start(); 18 | } 19 | 20 | @DynamicPropertySource 21 | static void dynamoDbProperties(DynamicPropertyRegistry registry) { 22 | final String endpoint = String.format("http://%s:%s", 23 | dynamodb.getContainerIpAddress(), 24 | dynamodb.getMappedPort(8000)); 25 | registry.add("aws.dynamo.endpoint", () -> endpoint); 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /SpringBootDynamo/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | aws.region=eu-west-1 2 | aws.dynamo.endpoint=foobar 3 | aws.access-key=accessKey 4 | aws.secret-key=secretKey -------------------------------------------------------------------------------- /SpringBootEvent/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | 10 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 11 | 12 | runtimeOnly 'com.h2database:h2' 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/SpringBootEventApplication.java: -------------------------------------------------------------------------------- 1 | package com.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootEventApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootEventApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/domain/MemberRepository.java: -------------------------------------------------------------------------------- 1 | package com.heowc.domain; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface MemberRepository extends JpaRepository { 6 | } 7 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/domain/MemberRequest.java: -------------------------------------------------------------------------------- 1 | package com.heowc.domain; 2 | 3 | public class MemberRequest { 4 | 5 | private String id; 6 | 7 | private String password; 8 | 9 | public MemberRequest(String id, String password) { 10 | this.id = id; 11 | this.password = password; 12 | } 13 | 14 | public String getId() { 15 | return id; 16 | } 17 | 18 | public String getPassword() { 19 | return password; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/domain/NotFoundMemberIdException.java: -------------------------------------------------------------------------------- 1 | package com.heowc.domain; 2 | 3 | public class NotFoundMemberIdException extends RuntimeException { 4 | } 5 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/domain/PasswordNotMatchingException.java: -------------------------------------------------------------------------------- 1 | package com.heowc.domain; 2 | 3 | public class PasswordNotMatchingException extends RuntimeException { 4 | } 5 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/event/PasswordChangedEvent.java: -------------------------------------------------------------------------------- 1 | package com.heowc.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | public class PasswordChangedEvent extends ApplicationEvent { 6 | 7 | private final String memberId; 8 | 9 | public PasswordChangedEvent(Object source, String memberId) { 10 | super(source); 11 | this.memberId = memberId; 12 | } 13 | 14 | public String getMemberId() { 15 | return memberId; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/event/PasswordChangedEventListener.java: -------------------------------------------------------------------------------- 1 | package com.heowc.event; 2 | 3 | import com.heowc.service.SendService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.event.EventListener; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class PasswordChangedEventListener { 10 | 11 | public static final String MESSAGE_FORMAT = "%s's password is changed"; 12 | 13 | private final SendService sendService; 14 | 15 | public PasswordChangedEventListener(SendService sendService) { 16 | this.sendService = sendService; 17 | } 18 | 19 | @EventListener 20 | public void onChange(PasswordChangedEvent event) { 21 | sendService.send(String.format(MESSAGE_FORMAT, event.getMemberId())); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/service/DummySendService.java: -------------------------------------------------------------------------------- 1 | package com.heowc.service; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Service; 6 | 7 | @Service 8 | public class DummySendService implements SendService { 9 | 10 | private static final Logger logger = LoggerFactory.getLogger(DummySendService.class); 11 | 12 | @Override 13 | public void send(String message) { 14 | logger.info(message); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/service/PasswordChangingService.java: -------------------------------------------------------------------------------- 1 | package com.heowc.service; 2 | 3 | import com.heowc.domain.MemberRequest; 4 | 5 | public interface PasswordChangingService { 6 | 7 | void changePassword(MemberRequest memberRequest); 8 | } 9 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/java/com/heowc/service/SendService.java: -------------------------------------------------------------------------------- 1 | package com.heowc.service; 2 | 3 | public interface SendService { 4 | 5 | void send(String message); 6 | } 7 | -------------------------------------------------------------------------------- /SpringBootEvent/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.driver-class-name=org.h2.Driver 2 | spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 3 | 4 | # jpa setting 5 | spring.jpa.hibernate.ddl-auto=create 6 | spring.jpa.generate-ddl=false 7 | 8 | spring.jpa.show-sql=true 9 | spring.jpa.properties.hibernate.format_sql=true -------------------------------------------------------------------------------- /SpringBootExcel/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | var poiVersion='5.4.0' 9 | 10 | dependencies { 11 | implementation "org.apache.poi:poi-ooxml:${poiVersion}" // .xlsx 12 | implementation "org.apache.poi:poi:${poiVersion}" // .xls 13 | 14 | implementation 'eu.bitwalker:UserAgentUtils:1.21' 15 | 16 | implementation 'org.springframework.boot:spring-boot-starter-web' 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootExcel/src/main/java/com/example/SpringBootExcelApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootExcelApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootExcelApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootExcel/src/main/java/com/example/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.config; 2 | 3 | import com.example.view.ExcelXlsView; 4 | import com.example.view.ExcelXlsxStreamingView; 5 | import com.example.view.ExcelXlsxView; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; 9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 10 | 11 | @Configuration 12 | public class WebConfig implements WebMvcConfigurer { 13 | 14 | @Autowired 15 | private ExcelXlsView excelXlsView; 16 | 17 | @Autowired 18 | private ExcelXlsxView excelXlsxView; 19 | 20 | @Autowired 21 | private ExcelXlsxStreamingView excelXlsxStreamingView; 22 | 23 | @Override 24 | public void configureViewResolvers(ViewResolverRegistry registry) { 25 | registry.enableContentNegotiation(excelXlsView, excelXlsxView, excelXlsxStreamingView); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SpringBootExcel/src/main/java/com/example/constant/ExcelConstant.java: -------------------------------------------------------------------------------- 1 | package com.example.constant; 2 | 3 | public abstract class ExcelConstant { 4 | 5 | public static final String FILE_NAME = "fileName"; 6 | public static final String HEAD = "head"; 7 | public static final String BODY = "body"; 8 | 9 | public static final String XLS = "xls"; 10 | public static final String XLSX = "xlsx"; 11 | public static final String XLSX_STREAM = "xlsx-stream"; 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootExcel/src/main/java/com/example/view/ExcelXlsView.java: -------------------------------------------------------------------------------- 1 | package com.example.view; 2 | 3 | import com.example.component.ExcelWriter; 4 | import org.apache.poi.ss.usermodel.Workbook; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.servlet.view.document.AbstractXlsView; 7 | 8 | import jakarta.servlet.http.HttpServletRequest; 9 | import jakarta.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @Component 13 | public class ExcelXlsView extends AbstractXlsView { 14 | 15 | @Override 16 | protected void buildExcelDocument(Map model, Workbook workbook, HttpServletRequest request, HttpServletResponse response) { 17 | new ExcelWriter(workbook, model, request, response).create(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpringBootExcel/src/main/java/com/example/view/ExcelXlsxStreamingView.java: -------------------------------------------------------------------------------- 1 | package com.example.view; 2 | 3 | import com.example.component.ExcelWriter; 4 | import org.apache.poi.ss.usermodel.Workbook; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.servlet.view.document.AbstractXlsxStreamingView; 7 | 8 | import jakarta.servlet.http.HttpServletRequest; 9 | import jakarta.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @Component 13 | public class ExcelXlsxStreamingView extends AbstractXlsxStreamingView { 14 | 15 | @Override 16 | protected void buildExcelDocument(Map model, Workbook workbook, HttpServletRequest request, HttpServletResponse response) { 17 | new ExcelWriter(workbook, model, request, response).create(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpringBootExcel/src/main/java/com/example/view/ExcelXlsxView.java: -------------------------------------------------------------------------------- 1 | package com.example.view; 2 | 3 | import com.example.component.ExcelWriter; 4 | import org.apache.poi.ss.usermodel.Workbook; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.servlet.view.document.AbstractXlsxView; 7 | 8 | import jakarta.servlet.http.HttpServletRequest; 9 | import jakarta.servlet.http.HttpServletResponse; 10 | import java.util.Map; 11 | 12 | @Component 13 | public class ExcelXlsxView extends AbstractXlsxView { 14 | 15 | @Override 16 | protected void buildExcelDocument(Map model, Workbook workbook, HttpServletRequest request, HttpServletResponse response) { 17 | new ExcelWriter(workbook, model, request, response).create(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpringBootExcel/src/main/java/com/example/web/UploadExcelController.java: -------------------------------------------------------------------------------- 1 | package com.example.web; 2 | 3 | import com.example.component.ExcelReader; 4 | import com.example.domain.Product; 5 | import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestParam; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import org.springframework.web.multipart.MultipartFile; 12 | 13 | import java.io.IOException; 14 | import java.util.List; 15 | 16 | @RestController 17 | @RequestMapping("upload") 18 | public class UploadExcelController { 19 | 20 | @Autowired 21 | private ExcelReader excelReader; 22 | 23 | @PostMapping("excel") 24 | public List readExcel(@RequestParam("file") MultipartFile multipartFile) throws IOException, InvalidFormatException { 25 | return excelReader.readFileToList(multipartFile, Product::from); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SpringBootExcel/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.servlet.multipart.max-file-size=100KB 2 | spring.servlet.multipart.max-request-size=100KB -------------------------------------------------------------------------------- /SpringBootExcel/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.servlet.multipart.max-file-size=100KB 2 | spring.servlet.multipart.max-request-size=100KB -------------------------------------------------------------------------------- /SpringBootExcel/src/test/resources/test.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootExcel/src/test/resources/test.xlsx -------------------------------------------------------------------------------- /SpringBootException/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | } 11 | -------------------------------------------------------------------------------- /SpringBootException/src/main/java/com/tistory/heowc/SpringBootExceptionApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootExceptionApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootExceptionApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootException/src/main/java/com/tistory/heowc/domain/ErrorInfo.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | public class ErrorInfo { 4 | 5 | private final String url; 6 | private final String message; 7 | 8 | public ErrorInfo(String url, Exception ex) { 9 | this.url = url; 10 | this.message = ex.getMessage(); 11 | } 12 | 13 | public String getUrl() { 14 | return url; 15 | } 16 | 17 | public String getMessage() { 18 | return message; 19 | } 20 | } -------------------------------------------------------------------------------- /SpringBootException/src/main/java/com/tistory/heowc/exception/ExtensionException.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value = HttpStatus.NOT_FOUND) 7 | public class ExtensionException extends RuntimeException { 8 | 9 | private final String message; 10 | 11 | public ExtensionException(String message) { 12 | this.message = message; 13 | } 14 | 15 | @Override 16 | public String getMessage() { 17 | return message; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpringBootGRpc/src/main/proto/message_sender.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "com.example"; 4 | option java_outer_classname = "MessageSenderProto"; 5 | 6 | service MessageSender { 7 | 8 | rpc send (MessageRequest) returns (MessageResponse) {} 9 | } 10 | 11 | message MessageRequest { 12 | string from = 2; 13 | string to = 3; 14 | string contents = 4; 15 | } 16 | 17 | message MessageResponse { 18 | string status = 1; 19 | string reason = 2; 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootGRpc/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.main.web-application-type=none 2 | grpc.port=6565 -------------------------------------------------------------------------------- /SpringBootGracefulShutdown/README.md: -------------------------------------------------------------------------------- 1 | ### build 2 | 3 | ```bash 4 | $ java build 5 | ``` 6 | 7 | ### run 8 | 9 | ```bash 10 | $ java -jar $APPLICATION_JAR 11 | ``` 12 | 13 | ### check PID 14 | 15 | ```bash 16 | $ cat applicaion.pid 17 | ``` 18 | 19 | ### stop 20 | 21 | ```bash 22 | $ kill -15 `cat application.pid` 23 | ``` -------------------------------------------------------------------------------- /SpringBootGracefulShutdown/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | configurations { 5 | compileOnly { 6 | extendsFrom annotationProcessor 7 | } 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | implementation 'org.springframework.boot:spring-boot-starter-web' 16 | 17 | compileOnly 'org.projectlombok:lombok' 18 | annotationProcessor 'org.projectlombok:lombok' 19 | } 20 | 21 | bootJar { 22 | launchScript() 23 | } 24 | -------------------------------------------------------------------------------- /SpringBootGracefulShutdown/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.shutdown=graceful -------------------------------------------------------------------------------- /SpringBootHateoas/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | implementation 'org.springframework.boot:spring-boot-starter-hateoas' 11 | } 12 | -------------------------------------------------------------------------------- /SpringBootHateoas/src/main/java/com/example/Message.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | public class Message { 6 | 7 | private Long id; 8 | private String content; 9 | private LocalDateTime createdAt; 10 | 11 | protected Message() { } 12 | 13 | public Message(Long id, String content, LocalDateTime createdAt) { 14 | this.id = id; 15 | this.content = content; 16 | this.createdAt = createdAt; 17 | } 18 | 19 | public Long getId() { 20 | return id; 21 | } 22 | 23 | public void setId(Long id) { 24 | this.id = id; 25 | } 26 | 27 | public String getContent() { 28 | return content; 29 | } 30 | 31 | public void setContent(String content) { 32 | this.content = content; 33 | } 34 | 35 | public LocalDateTime getCreatedAt() { 36 | return createdAt; 37 | } 38 | 39 | public void setCreatedAt(LocalDateTime createdAt) { 40 | this.createdAt = createdAt; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SpringBootHateoas/src/main/java/com/example/MessageModel.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.hateoas.RepresentationModel; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | public class MessageModel extends RepresentationModel { 8 | 9 | private String content; 10 | private LocalDateTime createdAt; 11 | 12 | protected MessageModel() { } 13 | 14 | public MessageModel(Message message) { 15 | content = message.getContent(); 16 | createdAt = message.getCreatedAt(); 17 | } 18 | 19 | public String getContent() { 20 | return content; 21 | } 22 | 23 | public void setContent(String content) { 24 | this.content = content; 25 | } 26 | 27 | public LocalDateTime getCreatedAt() { 28 | return createdAt; 29 | } 30 | 31 | public void setCreatedAt(LocalDateTime createdAt) { 32 | this.createdAt = createdAt; 33 | } 34 | } -------------------------------------------------------------------------------- /SpringBootHateoas/src/main/java/com/example/MessageResourceAssembler.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; 4 | 5 | public class MessageResourceAssembler extends RepresentationModelAssemblerSupport { 6 | 7 | public MessageResourceAssembler() { 8 | super(MessageController.class, MessageModel.class); 9 | } 10 | 11 | @Override 12 | public MessageModel toModel(Message entity) { 13 | return createModelWithId(entity.getId(), entity); 14 | } 15 | 16 | @Override 17 | protected MessageModel instantiateModel(Message entity) { 18 | return new MessageModel(entity); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootHateoas/src/main/java/com/example/SpringBootHateoasApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootHateoasApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootHateoasApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /SpringBootHateoas/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootHateoas/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootHateoas/src/test/java/com/example/SpringBootHateoasApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class SpringBootHateoasApplicationTests { 8 | 9 | @Test 10 | public void contextLoad() { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootInterceptor/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | } 11 | -------------------------------------------------------------------------------- /SpringBootInterceptor/src/main/java/com/example/SpringBootInterceptorApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootInterceptorApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootInterceptorApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootInterceptor/src/main/java/com/example/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.beans.factory.annotation.Qualifier; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.servlet.HandlerInterceptor; 7 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | @Configuration 11 | public class WebMvcConfig implements WebMvcConfigurer { 12 | 13 | @Autowired 14 | @Qualifier(value = "httpInterceptor") 15 | private HandlerInterceptor interceptor; 16 | 17 | @Override 18 | public void addInterceptors(InterceptorRegistry registry) { 19 | registry.addInterceptor(interceptor) 20 | .addPathPatterns("/**") 21 | .excludePathPatterns("/user/**"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SpringBootInterceptor/src/main/java/com/example/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.example.controller; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | public class IndexController { 11 | 12 | private static final Logger logger = LoggerFactory.getLogger(IndexController.class); 13 | 14 | @GetMapping(value = "/") 15 | public ResponseEntity index() { 16 | String msg = "Hello, Spring Boot Interceptor"; 17 | logger.info(msg); 18 | return ResponseEntity.ok() 19 | .header("controller", "controller") 20 | .body(msg); 21 | } 22 | } -------------------------------------------------------------------------------- /SpringBootInterceptor/src/main/java/com/example/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.example.controller; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @RestController 11 | @RequestMapping(value = "/user") 12 | public class UserController { 13 | 14 | private static final Logger logger = LoggerFactory.getLogger(UserController.class); 15 | 16 | @GetMapping 17 | public ResponseEntity index() { 18 | String msg = "Hello, User!"; 19 | logger.info(msg); 20 | return ResponseEntity.ok() 21 | .header("controller", "controller") 22 | .body(msg); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpringBootInterceptor/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootInterceptor/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootInterceptor/src/test/java/com/example/SpringBootInterceptorApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class SpringBootInterceptorApplicationTests { 8 | 9 | @Test 10 | public void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootJpa/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.jetbrains.kotlin.plugin.jpa' 3 | } 4 | 5 | group = 'com.example' 6 | version = '0.0.1-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation 'org.springframework.boot:spring-boot-starter-web' 14 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 15 | 16 | runtimeOnly 'com.h2database:h2' 17 | } -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/SpringBootJpaApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootJpaApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootJpaApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/onetomany/repository/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.onetomany.repository; 2 | 3 | import com.example.java.onetomany.domain.Order; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface OrderRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/onetomany/repository/ProductRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.onetomany.repository; 2 | 3 | import com.example.java.onetomany.domain.Product; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface ProductRepository extends JpaRepository { 7 | 8 | Product findByName(String name); 9 | } -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/onetoone/repository/MarketRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.onetoone.repository; 2 | 3 | import com.example.java.onetoone.domain.Market; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface MarketRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/onetoone/repository/OwnerRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.onetoone.repository; 2 | 3 | import com.example.java.onetoone.domain.Owner; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface OwnerRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/simple/domain/TimeData.java: -------------------------------------------------------------------------------- 1 | package com.example.java.simple.domain; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.GeneratedValue; 5 | import jakarta.persistence.GenerationType; 6 | import jakarta.persistence.Id; 7 | import java.time.LocalDateTime; 8 | 9 | @Entity 10 | public class TimeData { 11 | 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.SEQUENCE) 14 | private Long idx; 15 | 16 | private LocalDateTime date; 17 | 18 | protected TimeData() { } 19 | 20 | public TimeData(LocalDateTime date) { 21 | this.date = date; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "TimeData{" + 27 | "idx=" + idx + 28 | ", date=" + date + 29 | '}'; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/simple/repository/CustomJpqlRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.simple.repository; 2 | 3 | import com.example.java.simple.domain.Customer; 4 | 5 | import java.util.List; 6 | 7 | public interface CustomJpqlRepository { 8 | 9 | List findByName(String name); 10 | } 11 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/simple/repository/CustomerRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.simple.repository; 2 | 3 | import com.example.java.simple.domain.Customer; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface CustomerRepository extends JpaRepository, CustomJpqlRepository { 7 | 8 | } 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/simple/repository/SimpleCustomJpqlRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.simple.repository; 2 | 3 | import com.example.java.simple.domain.Customer; 4 | 5 | import jakarta.persistence.EntityManager; 6 | import jakarta.persistence.PersistenceContext; 7 | import java.util.List; 8 | 9 | public class SimpleCustomJpqlRepository implements CustomJpqlRepository { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | @Override 15 | public List findByName(String name) { 16 | return em.createNamedQuery("Custom.findByName", Customer.class) 17 | .setParameter("name", name) 18 | .getResultList(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/simple/repository/TimeDataRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.java.simple.repository; 2 | 3 | import com.example.java.simple.domain.TimeData; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface TimeDataRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/simple/service/CustomService.java: -------------------------------------------------------------------------------- 1 | package com.example.java.simple.service; 2 | 3 | import com.example.java.simple.domain.Customer; 4 | 5 | import java.util.List; 6 | 7 | public interface CustomService { 8 | 9 | Customer upsert(Customer customer); 10 | 11 | Customer find(Long idx); 12 | 13 | List findByName(String name); 14 | 15 | Customer delete(Customer customer); 16 | } 17 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/simple/service/SimpleCustomerService.java: -------------------------------------------------------------------------------- 1 | package com.example.java.simple.service; 2 | 3 | import com.example.java.simple.domain.Customer; 4 | import com.example.java.simple.repository.CustomerRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | import java.util.List; 10 | 11 | @Service 12 | @Transactional 13 | public class SimpleCustomerService implements CustomService { 14 | 15 | @Autowired 16 | private CustomerRepository repository; 17 | 18 | @Override 19 | public Customer upsert(Customer customer) { 20 | return repository.save(customer); 21 | } 22 | 23 | @Override 24 | public Customer find(Long idx) { 25 | return repository.findById(idx).orElseThrow(RuntimeException::new); 26 | } 27 | 28 | @Override 29 | public List findByName(String name) { 30 | return repository.findByName(name); 31 | } 32 | 33 | @Override 34 | public Customer delete(Customer customer) { 35 | repository.delete(customer); 36 | return customer; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/java/com/example/java/simple/web/TimeController.java: -------------------------------------------------------------------------------- 1 | package com.example.java.simple.web; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | @RestController 10 | @RequestMapping("date") 11 | public class TimeController { 12 | 13 | @GetMapping 14 | public LocalDateTime getLocalDateTime() { 15 | return LocalDateTime.now(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/SpringBootJpaApplication.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication 4 | import org.springframework.boot.runApplication 5 | 6 | @SpringBootApplication 7 | class SpringBootJpaApplication 8 | 9 | fun main(args: Array) { 10 | runApplication(*args) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/onetomany/domain/Order.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.onetomany.domain 2 | 3 | import jakarta.persistence.* 4 | 5 | @Entity 6 | @Table(name = "TB_ORDER") 7 | data class Order( 8 | @Id @GeneratedValue @Column(name = "ORDER_IDX") 9 | var idx: Long? = null, 10 | @Column(name = "PRODUCT_COUNT") 11 | var productCount: Int? = null, 12 | @Column(name = "BIGO") 13 | var bigo: String? = null, 14 | @ManyToOne @JoinColumn(name = "PRODUCT_IDX") 15 | var product: Product? = null 16 | ) { 17 | override fun toString(): String { 18 | return "Order{" + 19 | "idx=" + idx + 20 | ", productCount=" + productCount + 21 | ", bigo='" + bigo + '\''.toString() + 22 | ", product=" + product?.name + 23 | '}'.toString() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/onetomany/domain/Product.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.onetomany.domain 2 | 3 | import jakarta.persistence.* 4 | 5 | @Entity 6 | @Table(name = "TB_PRODUCT") 7 | data class Product( 8 | @Id @GeneratedValue @Column(name = "PRODUCT_IDX") 9 | val idx: Long? = null, 10 | @Column(name = "NAME") 11 | var name: String? = null, 12 | @Column(name = "CONTENT") 13 | var content: String? = null 14 | ) 15 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/onetomany/repository/OrderRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.onetomany.repository 2 | 3 | import com.example.kotlin.onetomany.domain.Order 4 | import org.springframework.data.jpa.repository.JpaRepository 5 | 6 | interface OrderRepository : JpaRepository 7 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/onetomany/repository/ProductRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.onetomany.repository 2 | 3 | import com.example.kotlin.onetomany.domain.Product 4 | import org.springframework.data.jpa.repository.JpaRepository 5 | 6 | interface ProductRepository : JpaRepository { 7 | 8 | fun findByName(name: String): Product 9 | } -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/onetoone/domain/Market.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.onetoone.domain 2 | 3 | import jakarta.persistence.* 4 | 5 | @Entity 6 | @Table(name = "MARKET") 7 | data class Market( 8 | @Id @GeneratedValue @Column(name = "MARKET_ID") 9 | val idx: Long? = null, 10 | @Column(name = "MARKET_NAME") 11 | var name: String? = null, 12 | @Column(name = "MARKET_LOCATION") 13 | var location: String? = null, 14 | @OneToOne @JoinColumn(name = "MARKET_ID") 15 | var owner: Owner? = null) { 16 | 17 | override fun toString(): String { 18 | return "Market(idx=$idx, name=$name, location=$location, owner=${owner?.name})" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/onetoone/domain/Owner.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.onetoone.domain 2 | 3 | import jakarta.persistence.* 4 | 5 | @Entity 6 | @Table(name = "OWNER") 7 | data class Owner( 8 | @Id @GeneratedValue @Column(name = "OWNER_ID") 9 | val idx: Long? = null, 10 | @Column(name = "OWNER_NAME") 11 | var name: String? = null, 12 | @OneToOne @JoinColumn(name = "OWNER_ID") 13 | var market: Market? = null 14 | ) 15 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/onetoone/repository/MarketRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.onetoone.repository 2 | 3 | import com.example.kotlin.onetoone.domain.Market 4 | import org.springframework.data.jpa.repository.JpaRepository 5 | 6 | interface MarketRepository : JpaRepository 7 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/onetoone/repository/OwnerRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.onetoone.repository 2 | 3 | import com.example.kotlin.onetoone.domain.Owner 4 | import org.springframework.data.jpa.repository.JpaRepository 5 | 6 | interface OwnerRepository : JpaRepository 7 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/simple/domain/Customer.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.simple.domain 2 | 3 | import jakarta.persistence.* 4 | 5 | @Entity 6 | @NamedQuery(name = "Custom.findByName", query = "SELECT c FROM Customer c WHERE c.name = :name ") 7 | data class Customer( 8 | @Id @GeneratedValue val idx: Long? = null, 9 | @Column(length = 50) val name: String, 10 | @Column(length = 14) val tel: String, 11 | var bigo: String) { 12 | 13 | fun changeBigo(bigo: String) { 14 | this.bigo = bigo 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/simple/domain/TimeData.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.simple.domain 2 | 3 | import jakarta.persistence.Entity 4 | import jakarta.persistence.GeneratedValue 5 | import jakarta.persistence.GenerationType 6 | import jakarta.persistence.Id 7 | import java.time.LocalDateTime 8 | 9 | @Entity 10 | data class TimeData( 11 | @Id @GeneratedValue val idx: Long? = null, 12 | val date: LocalDateTime) 13 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/simple/repository/CustomJpqlRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.simple.repository 2 | 3 | import com.example.kotlin.simple.domain.Customer 4 | 5 | interface CustomJpqlRepository { 6 | 7 | fun findByName(name: String): List 8 | } 9 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/simple/repository/CustomerRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.simple.repository 2 | 3 | import com.example.kotlin.simple.domain.Customer 4 | import org.springframework.data.jpa.repository.JpaRepository 5 | 6 | interface CustomerRepository : JpaRepository, CustomJpqlRepository 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/simple/repository/SimpleCustomJpqlRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.simple.repository 2 | 3 | import com.example.kotlin.simple.domain.Customer 4 | import jakarta.persistence.EntityManager 5 | 6 | class SimpleCustomJpqlRepository(val em: EntityManager) : CustomJpqlRepository { 7 | 8 | override fun findByName(name: String): List { 9 | return em.createNamedQuery("Custom.findByName", Customer::class.java) 10 | .setParameter("name", name) 11 | .resultList 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/simple/repository/TimeDataRepository.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.simple.repository 2 | 3 | import com.example.kotlin.simple.domain.TimeData 4 | import org.springframework.data.jpa.repository.JpaRepository 5 | 6 | interface TimeDataRepository : JpaRepository 7 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/simple/service/CustomService.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.simple.service 2 | 3 | import com.example.kotlin.simple.domain.Customer 4 | 5 | interface CustomService { 6 | 7 | fun upsert(customer: Customer): Customer 8 | 9 | fun find(idx: Long?): Customer 10 | 11 | fun findByName(name: String): List 12 | 13 | fun delete(customer: Customer): Customer 14 | } 15 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/simple/service/SimpleCustomerService.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.simple.service 2 | 3 | import com.example.kotlin.simple.domain.Customer 4 | import com.example.kotlin.simple.repository.CustomerRepository 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.stereotype.Service 7 | import org.springframework.transaction.annotation.Transactional 8 | import java.util.function.Supplier 9 | 10 | @Service 11 | @Transactional 12 | class SimpleCustomerService(val repository: CustomerRepository) : CustomService { 13 | 14 | override fun upsert(customer: Customer): Customer { 15 | return repository.save(customer) 16 | } 17 | 18 | override fun find(idx: Long?): Customer { 19 | return repository.findById(idx!!).orElseThrow { RuntimeException() } 20 | } 21 | 22 | override fun findByName(name: String): List { 23 | return repository.findByName(name) 24 | } 25 | 26 | override fun delete(customer: Customer): Customer { 27 | repository.delete(customer) 28 | return customer 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/kotlin/com/example/kotlin/simple/web/TimeController.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin.simple.web 2 | 3 | import org.springframework.web.bind.annotation.GetMapping 4 | import org.springframework.web.bind.annotation.RequestMapping 5 | import org.springframework.web.bind.annotation.RestController 6 | 7 | import java.time.LocalDateTime 8 | 9 | @RestController 10 | @RequestMapping("date") 11 | class TimeController { 12 | 13 | val localDateTime: LocalDateTime 14 | 15 | @GetMapping 16 | get() = LocalDateTime.now() 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootJpa/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.driver-class-name=org.h2.Driver 2 | spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 3 | 4 | # jpa setting 5 | spring.jpa.hibernate.ddl-auto=create 6 | spring.jpa.generate-ddl=false 7 | 8 | spring.jpa.show-sql=true 9 | spring.jpa.properties.hibernate.format_sql=true -------------------------------------------------------------------------------- /SpringBootJpa/src/test/java/com/example/java/CustomerRepositoryTests.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import com.example.java.simple.domain.Customer; 4 | import com.example.java.simple.repository.CustomerRepository; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertNotEquals; 10 | 11 | @DataJpaTest 12 | class CustomerRepositoryTests { 13 | 14 | @Autowired 15 | private CustomerRepository repository; 16 | 17 | @Test 18 | void test_update() { 19 | Customer customer = repository.save(new Customer("heo won chul", "010-xxxx-xxxx", "developer")); // 비영속성 데이터 20 | customer.changeBigo("Developer"); 21 | 22 | assertNotEquals("developer", repository.save(customer).getBigo()); 23 | } 24 | } -------------------------------------------------------------------------------- /SpringBootJpa/src/test/java/com/example/java/TimeTests.java: -------------------------------------------------------------------------------- 1 | package com.example.java; 2 | 3 | import com.example.java.simple.domain.TimeData; 4 | import com.example.java.simple.repository.TimeDataRepository; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | 9 | import java.time.LocalDateTime; 10 | 11 | @SpringBootTest 12 | class TimeTests { 13 | 14 | @Autowired TimeDataRepository timeDataRepository; 15 | 16 | @Test 17 | void test_save() { 18 | timeDataRepository.save(new TimeData(LocalDateTime.now())); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /SpringBootJpa/src/test/kotlin/com/example/kotlin/CustomerRepositoryTests.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import com.example.kotlin.simple.domain.Customer 4 | import com.example.kotlin.simple.repository.CustomerRepository 5 | import org.junit.jupiter.api.Assertions.assertNotEquals 6 | import org.junit.jupiter.api.Test 7 | import org.springframework.beans.factory.annotation.Autowired 8 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest 9 | 10 | @DataJpaTest 11 | class CustomerRepositoryTests { 12 | 13 | @Autowired 14 | lateinit var repository: CustomerRepository 15 | 16 | @Test 17 | fun test_update() { 18 | val customer = repository.save(Customer(name = "heo won chul", tel = "010-xxxx-xxxx", bigo = "developer")) // 비영속성 데이터 19 | customer.changeBigo("Developer") 20 | 21 | assertNotEquals(repository.save(customer).bigo, "developer") 22 | } 23 | } -------------------------------------------------------------------------------- /SpringBootJpa/src/test/kotlin/com/example/kotlin/EntityManagerTests.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import com.example.kotlin.simple.domain.Customer 4 | import org.junit.jupiter.api.Assertions.assertNotEquals 5 | import org.junit.jupiter.api.Test 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest 8 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager 9 | 10 | @DataJpaTest 11 | class EntityManagerTests { 12 | 13 | @Autowired 14 | lateinit var testEntityManager: TestEntityManager 15 | 16 | @Test 17 | fun test_insertClearAndFindAndUpdateClear() { 18 | val customer = testEntityManager.persistFlushFind(com.example.kotlin.simple.domain.Customer(name = "heo won chul", tel = "010-xxxx-xxxx", bigo = "developer")) // 비영속성 데이터 19 | customer.changeBigo("Developer") 20 | testEntityManager.flush() // Database 동기화 21 | // testEntityManager.clear(); // Persistence Context 초기화 22 | 23 | val result = testEntityManager.find(Customer::class.java, customer.idx) 24 | assertNotEquals(result.bigo, "developer") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SpringBootJpa/src/test/kotlin/com/example/kotlin/TimeTests.kt: -------------------------------------------------------------------------------- 1 | package com.example.kotlin 2 | 3 | import com.example.kotlin.simple.domain.TimeData 4 | import com.example.kotlin.simple.repository.TimeDataRepository 5 | import org.junit.jupiter.api.Test 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.boot.test.context.SpringBootTest 8 | import java.time.LocalDateTime 9 | 10 | @SpringBootTest 11 | class TimeTests { 12 | 13 | @Autowired 14 | lateinit var timeDataRepository: TimeDataRepository 15 | 16 | @Test 17 | fun test_save() { 18 | timeDataRepository.save(TimeData(date = LocalDateTime.now())) 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /SpringBootJpaSecurity/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 10 | implementation 'org.springframework.boot:spring-boot-starter-security' 11 | implementation 'org.springframework.boot:spring-boot-starter-web' 12 | 13 | runtimeOnly 'com.h2database:h2' 14 | 15 | testImplementation 'org.springframework.security:spring-security-test' 16 | } 17 | -------------------------------------------------------------------------------- /SpringBootJpaSecurity/src/main/java/com/example/SpringBootJpaSecurityApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootJpaSecurityApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootJpaSecurityApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootJpaSecurity/src/main/java/com/example/config/InitRunner.java: -------------------------------------------------------------------------------- 1 | package com.example.config; 2 | 3 | import com.example.domain.User; 4 | import com.example.domain.UserRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.security.crypto.password.PasswordEncoder; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class InitRunner implements CommandLineRunner { 12 | 13 | @Autowired 14 | private UserRepository repository; 15 | 16 | @Autowired 17 | private PasswordEncoder passwordEncoder; 18 | 19 | @Override 20 | public void run(String... args) { 21 | User user = new User("heowc", "1234", "won chul", "010-xxxx-xxxx", "https://heowc.github.io"); 22 | user.setPassword(passwordEncoder.encode(user.getPassword())); 23 | repository.save(user); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpringBootJpaSecurity/src/main/java/com/example/config/security/RestAuthenticationSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.config.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.http.MediaType; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; 7 | 8 | import jakarta.servlet.http.HttpServletRequest; 9 | import jakarta.servlet.http.HttpServletResponse; 10 | import java.io.IOException; 11 | 12 | public class RestAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { 13 | 14 | private ObjectMapper objectMapper = new ObjectMapper(); 15 | 16 | @Override 17 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { 18 | response.setContentType(MediaType.APPLICATION_JSON_VALUE); 19 | response.getWriter().append(objectMapper.writeValueAsString(authentication.getDetails())); 20 | clearAuthenticationAttributes(request); 21 | } 22 | } -------------------------------------------------------------------------------- /SpringBootJpaSecurity/src/main/java/com/example/config/security/UserDetailsImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.config.security; 2 | 3 | import com.example.domain.User; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.authority.AuthorityUtils; 6 | 7 | import java.util.Collection; 8 | 9 | public class UserDetailsImpl extends org.springframework.security.core.userdetails.User { 10 | 11 | public UserDetailsImpl(User user) { 12 | super(user.getId(), user.getPassword(), authorities()); 13 | } 14 | 15 | private static Collection authorities() { 16 | return AuthorityUtils.createAuthorityList("USER"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SpringBootJpaSecurity/src/main/java/com/example/domain/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.domain; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface UserRepository extends JpaRepository { 6 | 7 | User findById(String userId); 8 | } -------------------------------------------------------------------------------- /SpringBootJpaSecurity/src/main/java/com/example/service/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.service; 2 | 3 | import com.example.config.security.UserDetailsImpl; 4 | import com.example.domain.User; 5 | import com.example.domain.UserRepository; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | import org.springframework.stereotype.Service; 11 | 12 | @Service 13 | public class UserDetailsServiceImpl implements UserDetailsService { 14 | 15 | @Autowired 16 | private UserRepository repository; 17 | 18 | @Override 19 | public UserDetails loadUserByUsername(String id) { 20 | User user = repository.findById(id); 21 | 22 | if (user == null) { 23 | throw new UsernameNotFoundException(String.format("Not Found : %s", id)); 24 | } 25 | 26 | return new UserDetailsImpl(user); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SpringBootJpaSecurity/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.driver-class-name=org.h2.Driver 2 | spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 3 | 4 | # jpa setting 5 | spring.jpa.hibernate.ddl-auto=create 6 | spring.jpa.show-sql=true 7 | 8 | # logging 9 | logging.level.root=INFO -------------------------------------------------------------------------------- /SpringBootLogStash/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | configurations { 5 | compileOnly { 6 | extendsFrom annotationProcessor 7 | } 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | implementation 'org.springframework.boot:spring-boot-starter-web' 16 | implementation 'net.logstash.logback:logstash-logback-encoder:8.0' 17 | 18 | compileOnly 'org.projectlombok:lombok' 19 | annotationProcessor 'org.projectlombok:lombok' 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootLogStash/src/main/java/com/tistory/heowc/SpringBootLogStashApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootLogStashApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootLogStashApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootLogStash/src/test/java/com/tistory/heowc/SpringBootLogStashApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | 8 | @SpringBootTest 9 | class SpringBootLogStashApplicationTests { 10 | 11 | private static final Logger logger = LoggerFactory.getLogger(SpringBootLogStashApplicationTests.class); 12 | 13 | @Test 14 | void test_log() { 15 | logger.info("test1"); 16 | logger.info("test2"); 17 | logger.info("test3"); 18 | logger.info("test4"); 19 | logger.info("test5"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpringBootMicroMeter/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | implementation 'org.springframework.boot:spring-boot-starter-actuator' 11 | } 12 | -------------------------------------------------------------------------------- /SpringBootMicroMeter/src/main/java/com/example/GlobalController.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import io.micrometer.core.instrument.Counter; 8 | import io.micrometer.core.instrument.Metrics; 9 | import io.micrometer.core.instrument.simple.SimpleMeterRegistry; 10 | 11 | @RestController 12 | @RequestMapping("/global") 13 | public class GlobalController { 14 | 15 | { 16 | Metrics.addRegistry(new SimpleMeterRegistry()); 17 | } 18 | 19 | @GetMapping("/count") 20 | public Double count() { 21 | Counter counter = Metrics.counter("http.requests", "uri", "/global/count"); 22 | counter.increment(); 23 | return counter.count(); 24 | } 25 | } -------------------------------------------------------------------------------- /SpringBootMicroMeter/src/main/java/com/example/SimpleController.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import io.micrometer.core.instrument.Counter; 8 | import io.micrometer.core.instrument.MeterRegistry; 9 | import io.micrometer.core.instrument.simple.SimpleMeterRegistry; 10 | 11 | @RestController 12 | @RequestMapping("/simple") 13 | public class SimpleController { 14 | 15 | private MeterRegistry registry = new SimpleMeterRegistry(); 16 | 17 | @GetMapping("/count") 18 | public Double count() { 19 | Counter counter = registry.counter("http.requests", "uri", "/simple/count"); 20 | counter.increment(); 21 | return counter.count(); 22 | } 23 | } -------------------------------------------------------------------------------- /SpringBootMicroMeter/src/main/java/com/example/SpringBootMicroMeterApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootMicroMeterApplication { 8 | 9 | // Meter set: 10 | // Timer, Counter, Gauge, DistributionSummary, LongTaskTimer, FunctionCounter, FunctionTimer, and TimeGauge 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringBootMicroMeterApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SpringBootMicroMeter/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | management.metrics.export.simple.enabled=false -------------------------------------------------------------------------------- /SpringBootMicroMeter/src/test/java/com/example/SpringBootMicroMeterApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.test.context.SpringBootTest; 4 | 5 | @SpringBootTest 6 | public class SpringBootMicroMeterApplicationTest { 7 | 8 | } -------------------------------------------------------------------------------- /SpringBootMybatis/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | configurations { 5 | compileOnly { 6 | extendsFrom annotationProcessor 7 | } 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | implementation 'org.springframework.boot:spring-boot-starter' 16 | implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.4' 17 | 18 | compileOnly 'org.projectlombok:lombok' 19 | annotationProcessor 'org.projectlombok:lombok' 20 | 21 | implementation 'com.h2database:h2' 22 | } 23 | -------------------------------------------------------------------------------- /SpringBootMybatis/src/main/java/com/tistory/heowc/SpringBootMybatisApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootMybatisApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootMybatisApplication.class,args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootMybatis/src/main/java/com/tistory/heowc/config/MybatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.config; 2 | 3 | import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | // mybatis config 8 | @Configuration 9 | public class MybatisConfig { 10 | 11 | @Bean 12 | ConfigurationCustomizer mybatisConfigurationCustomizer() { 13 | return configuration -> { 14 | // customize ... 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootMybatis/src/main/java/com/tistory/heowc/dao/AccountDao.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.dao; 2 | 3 | import com.tistory.heowc.domain.Account; 4 | import lombok.RequiredArgsConstructor; 5 | import org.apache.ibatis.session.SqlSession; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | @RequiredArgsConstructor 10 | public class AccountDao { 11 | 12 | private final SqlSession sqlSession; 13 | 14 | private static final String NAMESPACE = "com.tistory.heowc.dao.Account."; 15 | 16 | public Long insert(Account account) { 17 | boolean inserted = sqlSession.insert(NAMESPACE + "insert", account) == 1; 18 | 19 | if (inserted) { 20 | return account.getIdx(); 21 | } else { 22 | return null; 23 | } 24 | } 25 | 26 | public Account findByIdx(Long idx) { 27 | return sqlSession.selectOne(NAMESPACE + "findByIdx", idx); 28 | } 29 | 30 | public void deleteByIdx(Long idx) { 31 | sqlSession.delete(NAMESPACE + "deleteByIdx", idx); 32 | } 33 | 34 | public void setFixedNameByIdx(Account account) { 35 | sqlSession.update(NAMESPACE + "setFixedNameByIdx", account); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SpringBootMybatis/src/main/java/com/tistory/heowc/domain/Account.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class Account implements Serializable { 14 | 15 | private Long idx; 16 | private String name; 17 | private String local; 18 | } 19 | -------------------------------------------------------------------------------- /SpringBootMybatis/src/main/java/com/tistory/heowc/mapper/AccountMapper.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.mapper; 2 | 3 | import com.tistory.heowc.domain.Account; 4 | import org.apache.ibatis.annotations.*; 5 | 6 | @Mapper 7 | public interface AccountMapper { 8 | 9 | String COLUMN = "`IDX`, `NAME`, `LOCAL`"; 10 | 11 | @Options( 12 | useGeneratedKeys = true, 13 | keyProperty = "idx" 14 | ) 15 | @Insert("INSERT INTO ACCOUNT VALUES (#{account.idx}, #{account.name}, #{account.local})") 16 | int insert(@Param("account") Account account); 17 | 18 | @Select("SELECT " + COLUMN + " FROM ACCOUNT WHERE IDX = #{idx}") 19 | Account findByIdx(@Param("idx") Long idx); 20 | 21 | @Delete("DELETE FROM ACCOUNT WHERE IDX = #{idx}") 22 | void deleteByIdx(@Param("idx") Long idx); 23 | 24 | @Update("UPDATE ACCOUNT SET NAME = #{account.name} WHERE IDX = #{account.idx}") 25 | void setFixedNameByIdx(@Param("account") Account account); 26 | } 27 | -------------------------------------------------------------------------------- /SpringBootMybatis/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | mybatis.mapper-locations=classpath*:com/tistory/heowc/dao/*.xml -------------------------------------------------------------------------------- /SpringBootMybatis/src/main/resources/com/tistory/heowc/dao/Account.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | `IDX`, `NAME`, `LOCAL` 8 | 9 | 10 | INSERT INTO ACCOUNT VALUES (#{idx}, #{name}, #{local}) 11 | 12 | 13 | 16 | 17 | 18 | DELETE FROM ACCOUNT WHERE IDX = #{idx} 19 | 20 | 21 | 22 | UPDATE ACCOUNT SET NAME = #{name} WHERE IDX = #{idx} 23 | 24 | -------------------------------------------------------------------------------- /SpringBootMybatis/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE ACCOUNT ( 2 | IDX NUMBER PRIMARY KEY NOT NULL , 3 | NAME VARCHAR(20) NOT NULL , 4 | LOCAL VARCHAR(20) NOT NULL 5 | ); -------------------------------------------------------------------------------- /SpringBootMybatis/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | mybatis.mapper-locations=classpath*:com/tistory/heowc/dao/*.xml 2 | #logging.level.root=DEBUG 3 | logging.level.org.mybatis.spring.SqlSessionUtils=DEBUG 4 | logging.level.com.tistory.heowc.mapper=DEBUG 5 | logging.level.com.tistory.heowc.dao=DEBUG -------------------------------------------------------------------------------- /SpringBootNotice/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | configurations { 5 | compileOnly { 6 | extendsFrom annotationProcessor 7 | } 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | implementation 'org.springframework.boot:spring-boot-starter' 16 | 17 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 18 | 19 | implementation 'org.springframework.boot:spring-boot-starter-web' 20 | // implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 21 | implementation 'org.springframework.boot:spring-boot-starter-freemarker' 22 | 23 | compileOnly 'org.projectlombok:lombok' 24 | annotationProcessor 'org.projectlombok:lombok' 25 | 26 | runtimeOnly 'com.h2database:h2' 27 | 28 | implementation "org.webjars:bootstrap:5.3.3" 29 | implementation "org.webjars:jquery:3.7.1" 30 | } 31 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/SpringBootNoticeApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootNoticeApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootNoticeApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/component/InitRunner.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.component; 2 | 3 | import com.tistory.heowc.domain.Notice; 4 | import com.tistory.heowc.repository.NoticeRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.ApplicationArguments; 7 | import org.springframework.boot.ApplicationRunner; 8 | import org.springframework.stereotype.Component; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | @Component 12 | @Transactional 13 | public class InitRunner implements ApplicationRunner { 14 | 15 | @Autowired 16 | private NoticeRepository repository; 17 | 18 | @Override 19 | public void run(ApplicationArguments args) throws Exception { 20 | for (long i = 0; i < 50; i++) { 21 | repository.save(new Notice(i, "title " + i, "content " + i)); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/domain/Notice.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | import jakarta.persistence.Column; 7 | import jakarta.persistence.Entity; 8 | import jakarta.persistence.Id; 9 | import java.io.Serializable; 10 | 11 | @Entity 12 | @Data 13 | @AllArgsConstructor 14 | public class Notice implements Serializable { 15 | 16 | @Id 17 | private Long idx; 18 | private String title; 19 | 20 | @Column(columnDefinition = "text") 21 | private String content; 22 | 23 | protected Notice() { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/domain/NoticeWithPage.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | public class NoticeWithPage { 11 | 12 | private List notices; 13 | 14 | private Page page; 15 | 16 | protected NoticeWithPage() { } 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/domain/Page.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import lombok.Data; 4 | 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | 7 | @Data 8 | public class Page { 9 | 10 | private Integer pageNo; 11 | private Integer recodeSize; 12 | private Long totalSize; 13 | 14 | @JsonIgnore 15 | private Integer top; 16 | } 17 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/repository/NoticeRepository.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import com.tistory.heowc.domain.Notice; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface NoticeRepository extends JpaRepository, NoticeRepositoryCustom { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/repository/NoticeRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import com.tistory.heowc.domain.Notice; 4 | 5 | import java.util.List; 6 | 7 | public interface NoticeRepositoryCustom { 8 | 9 | List findTopByIdxLimit(Integer top, Integer limit); 10 | } 11 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/repository/NoticeRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import com.tistory.heowc.domain.Notice; 4 | 5 | import jakarta.persistence.EntityManager; 6 | import jakarta.persistence.PersistenceContext; 7 | import java.util.List; 8 | 9 | public class NoticeRepositoryImpl implements NoticeRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | @Override 15 | public List findTopByIdxLimit(Integer top, Integer limit) { 16 | return em.createQuery("SELECT n FROM Notice n", Notice.class) 17 | .setFirstResult(top) 18 | .setMaxResults(limit) 19 | .getResultList(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/service/NoticeService.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.service; 2 | 3 | import com.tistory.heowc.domain.NoticeWithPage; 4 | 5 | public interface NoticeService { 6 | 7 | NoticeWithPage getNotices(Integer page); 8 | } 9 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/util/PageUtil.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.util; 2 | 3 | import com.tistory.heowc.domain.Page; 4 | 5 | public abstract class PageUtil { 6 | 7 | public static Page of(int pageNo, int recodeSize, long totalSize) { 8 | Page page = new Page(); 9 | 10 | page.setPageNo(pageNo); 11 | page.setRecodeSize(recodeSize); 12 | page.setTotalSize(totalSize); 13 | 14 | page.setTop((pageNo - 1) * recodeSize); 15 | return page; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/web/NoticeController.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.web; 2 | 3 | import com.tistory.heowc.domain.NoticeWithPage; 4 | import com.tistory.heowc.service.NoticeService; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @RestController 12 | @RequestMapping("/notice") 13 | @RequiredArgsConstructor 14 | public class NoticeController { 15 | 16 | private final NoticeService service; 17 | 18 | @GetMapping 19 | public NoticeWithPage getNotices(@RequestParam(required = false, defaultValue = "1") Integer page) { 20 | if (page > 0) { 21 | return service.getNotices(page); 22 | } else { 23 | throw new IllegalArgumentException("Page must be 0 or greater."); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/java/com/tistory/heowc/web/ViewController.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.web; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | 6 | @Controller 7 | public class ViewController { 8 | 9 | @GetMapping("/") 10 | public String goNotice() { 11 | return "notice"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.hibernate.ddl-auto=create-drop 2 | spring.jpa.show-sql=true 3 | 4 | # FREEMARKER TEMPLATE SETTING 5 | 6 | # THYMELEAF TEMPLATE SETTING 7 | 8 | # SERVER SETTING 9 | spring.messages.encoding=UTF-8 10 | server.compression.enabled=true 11 | spring.resources.chain.cache=true 12 | server.compression.min-response-size=2048 13 | spring.resources.chain.enabled=true 14 | spring.resources.cache.period=3600 15 | 16 | -------------------------------------------------------------------------------- /SpringBootNotice/src/main/resources/templates/notice.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Spring Boot Notice Sample 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
idx.제목내용
25 | 26 |
27 | 31 |
32 |
33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /SpringBootNotice/src/test/java/com/tistory/heowc/SpringBootNoticeApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringBootNoticeApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootOAuth2/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | configurations { 5 | compileOnly { 6 | extendsFrom annotationProcessor 7 | } 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | runtimeOnly 'com.h2database:h2' 16 | 17 | compileOnly 'org.projectlombok:lombok' 18 | annotationProcessor 'org.projectlombok:lombok' 19 | 20 | implementation 'org.springframework.boot:spring-boot-starter-security' 21 | implementation 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.6.8' 22 | implementation 'org.springframework.boot:spring-boot-starter-web' 23 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 24 | } 25 | -------------------------------------------------------------------------------- /SpringBootOAuth2/src/main/java/com/example/web/MainController.java: -------------------------------------------------------------------------------- 1 | package com.example.web; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class MainController { 8 | 9 | @GetMapping(value="/") 10 | public String index(){ 11 | return "Hello, Spring Boot Oauth2"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootOAuth2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | security.account.name=root 2 | security.account.password=wonchul 3 | 4 | security.oauth2.client.client-id=wonchul 5 | security.oauth2.client.client-secret=wonchul 6 | 7 | spring.jpa.hibernate.ddl-auto=create-drop 8 | spring.jpa.show-sql=true 9 | 10 | -------------------------------------------------------------------------------- /SpringBootOAuth2/src/test/java/com/example/SpringBootOath2ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringBootOath2ApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootQuartz/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | configurations { 5 | compileOnly { 6 | extendsFrom annotationProcessor 7 | } 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | implementation 'org.springframework.boot:spring-boot-starter-quartz' 16 | implementation 'org.springframework.boot:spring-boot-starter-web' 17 | implementation 'org.springframework.boot:spring-boot-starter-jdbc' 18 | 19 | runtimeOnly 'com.h2database:h2' 20 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 21 | } -------------------------------------------------------------------------------- /SpringBootQuartz/src/main/java/org/example/SimpleJob.java: -------------------------------------------------------------------------------- 1 | package org.example; 2 | 3 | import org.quartz.Job; 4 | import org.quartz.JobExecutionContext; 5 | import org.quartz.JobExecutionException; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | public class SimpleJob implements Job { 10 | 11 | private static final Logger logger = LoggerFactory.getLogger(SimpleJob.class); 12 | 13 | @Override 14 | public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { 15 | logger.info("executing..."); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootQuartz/src/main/java/org/example/SpringBootQuartzApplication.java: -------------------------------------------------------------------------------- 1 | package org.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootQuartzApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootQuartzApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootQuartz/src/test/java/org/example/SpringBootQuartzApplicationTests.java: -------------------------------------------------------------------------------- 1 | package org.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringBootQuartzApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootQuartz/src/test/resources/application-test.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootQuartz/src/test/resources/application-test.properties -------------------------------------------------------------------------------- /SpringBootQueryDsl/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | configurations { 5 | compileOnly { 6 | extendsFrom annotationProcessor 7 | } 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 16 | runtimeOnly 'com.h2database:h2' 17 | 18 | compileOnly 'org.projectlombok:lombok' 19 | annotationProcessor 'org.projectlombok:lombok' 20 | 21 | annotationProcessor 'jakarta.persistence:jakarta.persistence-api' 22 | annotationProcessor 'com.querydsl:querydsl-apt::jakarta' 23 | implementation "com.querydsl:querydsl-jpa::jakarta" 24 | } 25 | -------------------------------------------------------------------------------- /SpringBootQueryDsl/src/main/java/com/tistory/heowc/SpringBootQueryDslApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootQueryDslApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootQueryDslApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootQueryDsl/src/main/java/com/tistory/heowc/config/DatabaseConfig.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.config; 2 | 3 | import jakarta.persistence.EntityManager; 4 | 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import com.querydsl.jpa.impl.JPAQueryFactory; 9 | 10 | @Configuration 11 | public class DatabaseConfig { 12 | 13 | @Bean 14 | public JPAQueryFactory queryFactory(EntityManager em) { 15 | return new JPAQueryFactory(em); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootQueryDsl/src/main/java/com/tistory/heowc/domain/Grade.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | import jakarta.persistence.Column; 7 | import jakarta.persistence.Entity; 8 | import jakarta.persistence.Id; 9 | import jakarta.persistence.OneToMany; 10 | import java.io.Serializable; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | @Entity 15 | @Data 16 | @AllArgsConstructor 17 | public class Grade implements Serializable { 18 | 19 | private static final long serialVersionUID = -4432332213569816450L; 20 | 21 | @Id 22 | @Column(name = "GRADE_NUM") 23 | private Integer gradeNum; 24 | 25 | @Column(name = "GRADE_NAME") 26 | private String gradeName; 27 | 28 | @OneToMany(mappedBy = "grade") 29 | private List students = new ArrayList<>(); 30 | 31 | protected Grade() { } 32 | 33 | public static Grade of(Integer gradeNum, String gradeName) { 34 | Grade grade = new Grade(); 35 | grade.setGradeNum(gradeNum); 36 | grade.setGradeName(gradeName); 37 | return grade; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SpringBootQueryDsl/src/main/java/com/tistory/heowc/repository/GradeRepository.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.querydsl.QuerydslPredicateExecutor; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import com.tistory.heowc.domain.Grade; 8 | 9 | @Repository 10 | public interface GradeRepository extends JpaRepository, 11 | GradeRepositoryCustom, 12 | QuerydslPredicateExecutor { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /SpringBootQueryDsl/src/main/java/com/tistory/heowc/repository/GradeRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import java.util.List; 4 | 5 | import com.tistory.heowc.domain.Grade; 6 | 7 | public interface GradeRepositoryCustom { 8 | 9 | List findGradeJoinNameOfStudent(String name); 10 | 11 | List findGradeSubQueryNameOfStudent(String name); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootQueryDsl/src/main/java/com/tistory/heowc/repository/StudentRepository.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.querydsl.QuerydslPredicateExecutor; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import com.tistory.heowc.domain.Student; 8 | 9 | @Repository 10 | public interface StudentRepository extends JpaRepository, 11 | StudentRepositoryCustom, 12 | QuerydslPredicateExecutor { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /SpringBootQueryDsl/src/main/java/com/tistory/heowc/repository/StudentRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import java.util.List; 4 | 5 | import com.querydsl.core.Tuple; 6 | import com.querydsl.core.types.Predicate; 7 | import com.tistory.heowc.domain.Student; 8 | 9 | public interface StudentRepositoryCustom { 10 | 11 | Predicate equalName(String name); 12 | 13 | List findStudentByNameExtension(String name); 14 | 15 | List findStudentByName(String name); 16 | 17 | List findStudentByNameAndHeight(String name, Double height); 18 | 19 | List findStudentOrderByName(); 20 | 21 | List findStudentGroupingByGradeNum(); 22 | 23 | List findCaseStudentAll_Tuple(); 24 | 25 | List findCaseStudentAll_Student(); 26 | } 27 | -------------------------------------------------------------------------------- /SpringBootQueryDsl/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.hibernate.ddl-auto=create-drop 2 | spring.jpa.show-sql=true 3 | spring.jpa.properties.hibernate.format_sql=true 4 | logging.level.org.hibernate.type.descriptor.sql=trace -------------------------------------------------------------------------------- /SpringBootRabbitMQ/README.md: -------------------------------------------------------------------------------- 1 | ## run rabbitmq 2 | 3 | ```bash 4 | $ docker run -d -p 5672:5672 -p 15672:15672 rabbitmq:3.7.8-management 5 | ``` -------------------------------------------------------------------------------- /SpringBootRabbitMQ/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-amqp' 10 | implementation 'org.springframework.boot:spring-boot-starter-json' 11 | } 12 | 13 | -------------------------------------------------------------------------------- /SpringBootRabbitMQ/src/main/java/com/tistory/heowc/common/Constant.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.common; 2 | 3 | public abstract class Constant { 4 | 5 | public static final String QUEUE_NAME = "spring"; 6 | 7 | public static final String TOPIC_EXCHANGE_NAME = QUEUE_NAME + "-exchange"; 8 | } 9 | -------------------------------------------------------------------------------- /SpringBootRabbitMQ/src/main/java/com/tistory/heowc/common/Message.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.common; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Message implements Serializable { 6 | 7 | private Long index; 8 | private String content; 9 | 10 | public Message() {} 11 | 12 | public static Message of(Long index, String content) { 13 | return new Message(index, content); 14 | } 15 | 16 | public Message(Long index, String content) { 17 | this.index = index; 18 | this.content = content; 19 | } 20 | 21 | public void setIndex(long index) { 22 | this.index = index; 23 | } 24 | public void setContent(String content) { 25 | this.content = content; 26 | } 27 | 28 | public Long getIndex() { 29 | return index; 30 | } 31 | public String getContent() { 32 | return content; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "Message [index=" + index + ", content=" + content + "]"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SpringBootRabbitMQ/src/main/java/com/tistory/heowc/receiver/MessageReceiver.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.receiver; 2 | 3 | import com.tistory.heowc.common.Message; 4 | import com.tistory.heowc.common.Constant; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class MessageReceiver { 12 | 13 | private static final Logger logger = LoggerFactory.getLogger(MessageReceiver.class); 14 | 15 | @RabbitListener(queues = Constant.QUEUE_NAME) 16 | public void onMessage(Message message) { 17 | logger.info(String.format("Received < %s >", message.toString())); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpringBootRabbitMQ/src/main/java/com/tistory/heowc/receiver/RabbitReceiverConfig.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.receiver; 2 | 3 | import com.tistory.heowc.common.Constant; 4 | import org.springframework.amqp.core.*; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class RabbitReceiverConfig { 10 | 11 | @Bean 12 | public Queue queue() { 13 | return QueueBuilder.nonDurable(Constant.QUEUE_NAME).build(); 14 | } 15 | 16 | @Bean 17 | public Exchange topicExchange() { 18 | return ExchangeBuilder.topicExchange(Constant.TOPIC_EXCHANGE_NAME).build(); 19 | } 20 | 21 | @Bean 22 | public Binding binding(Queue queue, TopicExchange topicExchange) { 23 | return BindingBuilder.bind(queue).to(topicExchange).with(Constant.QUEUE_NAME); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpringBootRabbitMQ/src/main/java/com/tistory/heowc/receiver/ReceiverApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.receiver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ReceiverApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(ReceiverApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootRabbitMQ/src/main/java/com/tistory/heowc/sender/SchedlerConfig.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.sender; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.scheduling.annotation.EnableScheduling; 5 | 6 | @Configuration 7 | @EnableScheduling 8 | public class SchedlerConfig { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /SpringBootRabbitMQ/src/main/java/com/tistory/heowc/sender/SenderApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.sender; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SenderApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SenderApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootRabbitMQ/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootRabbitMQ/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootRedis/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | configurations { 5 | compileOnly { 6 | extendsFrom annotationProcessor 7 | } 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | implementation 'org.springframework.boot:spring-boot-starter-data-redis' 16 | implementation 'com.github.kstyrc:embedded-redis:0.6' 17 | 18 | compileOnly 'org.projectlombok:lombok' 19 | annotationProcessor 'org.projectlombok:lombok' 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootRedis/src/main/java/com/tistory/heowc/SpringBootRedisApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootRedisApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootRedisApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootRedis/src/main/java/com/tistory/heowc/domain/Person.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.springframework.data.annotation.Id; 7 | import org.springframework.data.redis.core.RedisHash; 8 | 9 | @RedisHash("people") 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class Person { 14 | 15 | @Id 16 | private String id; 17 | private String firstname; 18 | private String lastname; 19 | } -------------------------------------------------------------------------------- /SpringBootRedis/src/main/java/com/tistory/heowc/domain/PersonRepository.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | public interface PersonRepository extends CrudRepository { 6 | } 7 | -------------------------------------------------------------------------------- /SpringBootRedis/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootRedis/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootRest/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | 5 | configurations { 6 | compileOnly { 7 | extendsFrom annotationProcessor 8 | } 9 | } 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-web' 17 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 18 | implementation 'org.springframework.boot:spring-boot-starter-data-rest' 19 | 20 | compileOnly 'org.projectlombok:lombok' 21 | annotationProcessor 'org.projectlombok:lombok' 22 | 23 | runtimeOnly 'com.h2database:h2' 24 | } 25 | -------------------------------------------------------------------------------- /SpringBootRest/src/main/java/com/example/SpringRestApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringRestApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringRestApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootRest/src/main/java/com/example/domain/Person.java: -------------------------------------------------------------------------------- 1 | package com.example.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | import jakarta.persistence.Entity; 7 | import jakarta.persistence.GeneratedValue; 8 | import jakarta.persistence.Id; 9 | 10 | @Entity 11 | @Data 12 | @AllArgsConstructor 13 | public class Person { 14 | 15 | @Id @GeneratedValue 16 | private Long id; 17 | 18 | private String firstName; 19 | private String lastName; 20 | 21 | protected Person() { } 22 | 23 | public Person(String firstName, String lastName) { 24 | this.firstName = firstName; 25 | this.lastName = lastName; 26 | } 27 | } -------------------------------------------------------------------------------- /SpringBootRest/src/main/java/com/example/event/PersonEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.event; 2 | 3 | import com.example.domain.Person; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.data.rest.core.annotation.HandleBeforeCreate; 7 | import org.springframework.data.rest.core.annotation.RepositoryEventHandler; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | @RepositoryEventHandler(Person.class) 12 | public class PersonEventHandler { 13 | 14 | private static final Logger logger = LoggerFactory.getLogger(PersonEventHandler.class); 15 | 16 | @HandleBeforeCreate 17 | public void handlePersonCreate(Person p){ 18 | logger.info("========================================= HandleBeforeCreate"); 19 | // validation logic... 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /SpringBootRest/src/main/java/com/example/repository/PersonRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.repository; 2 | 3 | import java.util.List; 4 | 5 | import com.example.domain.Person; 6 | import org.springframework.data.repository.CrudRepository; 7 | import org.springframework.data.repository.query.Param; 8 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 9 | import org.springframework.data.rest.core.annotation.RestResource; 10 | 11 | @RepositoryRestResource(collectionResourceRel = "people", path = "people") 12 | public interface PersonRepository extends CrudRepository { 13 | 14 | @RestResource(path="lastname", rel="people") 15 | List findByLastName(@Param("lastName") String lastName); 16 | 17 | } 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /SpringBootRest/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.hibernate.ddl-auto=create 2 | spring.jpa.show-sql=true -------------------------------------------------------------------------------- /SpringBootRest/src/test/java/com/example/SpringRestApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringRestApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootRestDocs/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation "org.springframework.boot:spring-boot-starter-web" 10 | 11 | testImplementation "org.springframework.restdocs:spring-restdocs-mockmvc" 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootRestDocs/src/main/java/com/tistory/heowc/SpringBootRestDocsApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootRestDocsApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootRestDocsApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootRestDocs/src/main/java/com/tistory/heowc/domain/Programming.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | public class Programming { 4 | 5 | private String name; 6 | private String url; 7 | 8 | public Programming(String name, String url) { 9 | this.name = name; 10 | this.url = url; 11 | } 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public String getUrl() { 18 | return url; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootRestDocs/src/main/java/com/tistory/heowc/web/ProgrammingController.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.web; 2 | 3 | import com.tistory.heowc.domain.Programming; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import java.util.Arrays; 9 | import java.util.List; 10 | 11 | @RestController 12 | @RequestMapping("programming") 13 | public class ProgrammingController { 14 | 15 | @GetMapping() 16 | public List findAll() { 17 | return Arrays.asList( 18 | new Programming("Java", "oracle.com"), 19 | new Programming("go", "golang.org/"), 20 | new Programming("kotlin", "kotlinlang.org") 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SpringBootRestDocs/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.database=H2 2 | spring.datasource.driver-class-name=org.h2.Driver 3 | spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 4 | spring.datasource.username=test 5 | spring.datasource.password=test 6 | 7 | spring.jpa.hibernate.ddl-auto=create-drop 8 | spring.jpa.show-sql=true -------------------------------------------------------------------------------- /SpringBootRestDocs/src/test/java/com/tistory/heowc/SpringBootRestDocsApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import com.tistory.heowc.web.ProgrammingController; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; 7 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 8 | import org.springframework.test.web.servlet.MockMvc; 9 | 10 | import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; 11 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 12 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 13 | 14 | @WebMvcTest(ProgrammingController.class) 15 | @AutoConfigureRestDocs(outputDir = "build/snippets") 16 | class SpringBootRestDocsApplicationTests { 17 | 18 | @Autowired 19 | private MockMvc mockMvc; 20 | 21 | @Test 22 | void shouldReturnDefaultMessage() throws Exception { 23 | mockMvc.perform(get("/programming")) 24 | .andExpect(status().isOk()) 25 | .andDo(document("programming")); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/README.md: -------------------------------------------------------------------------------- 1 | ## install redis 2 | 3 | ```bash 4 | $ docker pull redis 5 | ``` 6 | 7 | ## run redis 8 | 9 | ```bash 10 | $ docker run --name some-redis -d -p 6379:6379 redis 11 | ``` -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 10 | implementation 'org.springframework.boot:spring-boot-starter-data-redis' 11 | implementation 'org.springframework.session:spring-session-data-redis' 12 | implementation 'org.springframework.boot:spring-boot-starter-security' 13 | implementation 'org.springframework.boot:spring-boot-starter-web' 14 | runtimeOnly 'com.h2database:h2' 15 | } 16 | -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/src/main/java/com/tistory/heowc/SpringBootSecurityAddRedisApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 7 | import org.springframework.security.crypto.password.PasswordEncoder; 8 | 9 | @SpringBootApplication 10 | public class SpringBootSecurityAddRedisApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(SpringBootSecurityAddRedisApplication.class, args); 14 | } 15 | 16 | @Bean 17 | public PasswordEncoder passwordEncoder() { 18 | return new BCryptPasswordEncoder(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/src/main/java/com/tistory/heowc/component/UserDetailsImpl.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.component; 2 | 3 | import com.tistory.heowc.domain.Member; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.authority.AuthorityUtils; 6 | import org.springframework.security.core.userdetails.User; 7 | 8 | import java.util.Collection; 9 | 10 | public class UserDetailsImpl extends User { 11 | 12 | public UserDetailsImpl(Member member) { 13 | super(member.getId(), member.getPassword(), authorities()); 14 | } 15 | 16 | private static Collection authorities() { 17 | return AuthorityUtils.createAuthorityList("USER"); 18 | } 19 | } -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/src/main/java/com/tistory/heowc/config/RedisSessionConfig.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.config; 2 | 3 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; 4 | 5 | @EnableRedisHttpSession 6 | public class RedisSessionConfig { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/src/main/java/com/tistory/heowc/domain/Member.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | 4 | import jakarta.persistence.Entity; 5 | import jakarta.persistence.Id; 6 | 7 | @Entity 8 | public class Member { 9 | 10 | @Id 11 | private String id; 12 | 13 | private String password; 14 | 15 | protected Member() { } 16 | 17 | public Member(String id, String password) { 18 | this.id = id; 19 | this.password = password; 20 | } 21 | 22 | public String getId() { 23 | return id; 24 | } 25 | 26 | public void setId(String id) { 27 | this.id = id; 28 | } 29 | 30 | public String getPassword() { 31 | return password; 32 | } 33 | 34 | public void setPassword(String password) { 35 | this.password = password; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "Member{" + 41 | "id='" + id + '\'' + 42 | ", password='" + password + '\'' + 43 | '}'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/src/main/java/com/tistory/heowc/repository/MemberRepository.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import com.tistory.heowc.domain.Member; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface MemberRepository extends JpaRepository { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/src/main/java/com/tistory/heowc/service/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.service; 2 | 3 | import com.tistory.heowc.component.UserDetailsImpl; 4 | import com.tistory.heowc.domain.Member; 5 | import com.tistory.heowc.repository.MemberRepository; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | import org.springframework.stereotype.Service; 11 | 12 | @Service 13 | public class UserDetailsServiceImpl implements UserDetailsService { 14 | 15 | @Autowired 16 | private MemberRepository repository; 17 | 18 | @Override 19 | public UserDetails loadUserByUsername(String id) { 20 | Member member = repository.findById(id) 21 | .orElseThrow(() -> new UsernameNotFoundException(id)); 22 | 23 | return new UserDetailsImpl(member); 24 | } 25 | } -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/src/main/java/com/tistory/heowc/web/UserController.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.web; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/user") 11 | public class UserController { 12 | 13 | private static final Logger logger = LoggerFactory.getLogger(UserController.class); 14 | 15 | @GetMapping 16 | public String getUser() { 17 | String msg = "Hello, User!!"; 18 | logger.info(msg); 19 | return msg; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpringBootSecurityAddRedis/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.session.store-type=redis 2 | 3 | spring.redis.host=127.0.0.1 4 | spring.redis.port=6379 5 | 6 | spring.datasource.url=jdbc:h2:mem:test 7 | 8 | spring.jpa.hibernate.ddl-auto=create-drop 9 | spring.jpa.show-sql=true -------------------------------------------------------------------------------- /SpringBootSecurityJwt/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation'org.springframework.boot:spring-boot-starter-data-jpa' 10 | implementation'org.springframework.boot:spring-boot-starter-security' 11 | implementation'org.springframework.boot:spring-boot-starter-web' 12 | implementation'com.auth0:java-jwt:3.10.0' 13 | 14 | runtimeOnly 'com.h2database:h2' 15 | } 16 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/SpringBootSecurityJwtApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootSecurityJwtApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootSecurityJwtApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/auth/UserDetailsImpl.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.auth; 2 | 3 | import com.tistory.heowc.domain.Member; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.userdetails.User; 6 | 7 | import java.util.List; 8 | 9 | public class UserDetailsImpl extends User { 10 | 11 | public UserDetailsImpl(String id, List authorities) { 12 | super(id, "", authorities); 13 | } 14 | 15 | public UserDetailsImpl(Member member, List authorities) { 16 | super(member.getId(), member.getPassword(), authorities); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/auth/ajax/AjaxUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.auth.ajax; 2 | 3 | import com.tistory.heowc.auth.UserDetailsImpl; 4 | import com.tistory.heowc.domain.Member; 5 | import com.tistory.heowc.repository.MemberRepository; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.authority.AuthorityUtils; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Service 14 | public class AjaxUserDetailsService implements UserDetailsService { 15 | 16 | @Autowired 17 | private MemberRepository repository; 18 | 19 | @Override 20 | public UserDetails loadUserByUsername(String username) { 21 | Member user = repository.findById(username).orElse(null); 22 | 23 | if (user == null) { 24 | throw new UsernameNotFoundException(username + "라는 사용자가 없습니다."); 25 | } 26 | 27 | return new UserDetailsImpl(user, AuthorityUtils.createAuthorityList(user.getRole())); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/auth/jwt/JwtInfo.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.auth.jwt; 2 | 3 | import com.auth0.jwt.algorithms.Algorithm; 4 | 5 | public abstract class JwtInfo { 6 | 7 | public static final String HEADER_NAME = "jwt-header"; 8 | 9 | public static final String ISSUER = "wonchul"; 10 | 11 | public static final String TOKEN_KEY = "heowc.github.io"; 12 | 13 | public static final long EXPIRES_LIMIT = 3L; 14 | 15 | public static Algorithm getAlgorithm() { 16 | try { 17 | return Algorithm.HMAC256(JwtInfo.TOKEN_KEY); 18 | } catch (IllegalArgumentException e) { 19 | return Algorithm.none(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/auth/jwt/JwtUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.auth.jwt; 2 | 3 | import com.auth0.jwt.interfaces.DecodedJWT; 4 | import com.tistory.heowc.auth.UserDetailsImpl; 5 | import com.tistory.heowc.util.JwtUtil; 6 | import org.springframework.security.authentication.BadCredentialsException; 7 | import org.springframework.security.core.authority.AuthorityUtils; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.stereotype.Service; 11 | 12 | @Service 13 | public class JwtUserDetailsService implements UserDetailsService { 14 | 15 | @Override 16 | public UserDetails loadUserByUsername(String token) { 17 | DecodedJWT decodedJWT = JwtUtil.tokenToJwt(token); 18 | 19 | if (decodedJWT == null) { 20 | throw new BadCredentialsException("Not used Token"); 21 | } 22 | 23 | String id = decodedJWT.getClaim("id").asString(); 24 | String role = decodedJWT.getClaim("role").asString(); 25 | 26 | return new UserDetailsImpl(id, AuthorityUtils.createAuthorityList(role)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/auth/jwt/matcher/SkipPathRequestMatcher.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.auth.jwt.matcher; 2 | 3 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 4 | import org.springframework.security.web.util.matcher.OrRequestMatcher; 5 | import org.springframework.security.web.util.matcher.RequestMatcher; 6 | 7 | import jakarta.servlet.http.HttpServletRequest; 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | 11 | public class SkipPathRequestMatcher implements RequestMatcher { 12 | 13 | private OrRequestMatcher skipRequestMatcher; 14 | 15 | public SkipPathRequestMatcher(List skipPathList) { 16 | if(!skipPathList.isEmpty()) { 17 | List requestMatcherList = skipPathList.stream() 18 | .map(AntPathRequestMatcher::new) 19 | .collect(Collectors.toList()); 20 | skipRequestMatcher = new OrRequestMatcher(requestMatcherList); 21 | } 22 | } 23 | 24 | @Override 25 | public boolean matches(HttpServletRequest request) { 26 | return !skipRequestMatcher.matches(request); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/component/InitComponent.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.component; 2 | 3 | import com.tistory.heowc.domain.Member; 4 | import com.tistory.heowc.repository.MemberRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.ApplicationArguments; 7 | import org.springframework.boot.ApplicationRunner; 8 | import org.springframework.security.crypto.password.PasswordEncoder; 9 | import org.springframework.stereotype.Component; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | @Component 13 | public class InitComponent implements ApplicationRunner { 14 | 15 | @Autowired 16 | private MemberRepository repository; 17 | 18 | @Autowired 19 | private PasswordEncoder passwordEncoder; 20 | 21 | @Transactional 22 | @Override 23 | public void run(ApplicationArguments args) { 24 | Member user = new Member("wonchul", passwordEncoder.encode("1234"),"USER"); 25 | repository.save(user); 26 | 27 | Member admin = new Member("naeun", passwordEncoder.encode("1234"), "ADMIN"); 28 | repository.save(admin); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/config/CommonConfig.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | 7 | @Configuration 8 | public class CommonConfig { 9 | 10 | @Bean 11 | public BCryptPasswordEncoder passwordEncoder() { 12 | return new BCryptPasswordEncoder(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/domain/Member.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.Id; 5 | 6 | @Entity 7 | public class Member { 8 | 9 | @Id 10 | private String id; 11 | 12 | private String password; 13 | 14 | private String role; 15 | 16 | protected Member() { } 17 | 18 | public Member(String id, String password, String role) { 19 | this.id = id; 20 | this.password = password; 21 | this.role = role; 22 | } 23 | 24 | public String getId() { 25 | return id; 26 | } 27 | 28 | public void setId(String id) { 29 | this.id = id; 30 | } 31 | 32 | public String getPassword() { 33 | return password; 34 | } 35 | 36 | public void setPassword(String password) { 37 | this.password = password; 38 | } 39 | 40 | public String getRole() { 41 | return role; 42 | } 43 | 44 | public void setRole(String role) { 45 | this.role = role; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/repository/MemberRepository.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import com.tistory.heowc.domain.Member; 7 | 8 | @Repository 9 | public interface MemberRepository extends JpaRepository { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/util/DateUtil.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.util; 2 | 3 | import java.time.LocalDateTime; 4 | import java.time.ZoneOffset; 5 | import java.util.Date; 6 | 7 | public final class DateUtil { 8 | 9 | public static Date nowToDate() { 10 | return Date.from(LocalDateTime.now().toInstant(ZoneOffset.ofHours(9))); 11 | } 12 | 13 | public static Date nowAfterDaysToDate(Long days) { 14 | return Date.from(LocalDateTime.now().plusDays(days).toInstant(ZoneOffset.ofHours(9))); 15 | } 16 | 17 | private DateUtil() { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/java/com/tistory/heowc/web/RoleController.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.web; 2 | 3 | import org.springframework.security.access.prepost.PostAuthorize; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | public class RoleController { 11 | 12 | @PostAuthorize("hasAuthority('USER')") 13 | @GetMapping("/user") 14 | public String user(Authentication authentication) { 15 | System.out.println("RoleController : " + authentication.getAuthorities().toString()); 16 | System.out.println("RoleController : " + authentication.getPrincipal()); 17 | return "I'm Jwt Token User!"; 18 | } 19 | 20 | @PreAuthorize("hasAuthority('ADMIN')") 21 | @GetMapping("/admin") 22 | public String admin(Authentication authentication) { 23 | System.out.println("RoleController : " + authentication.getAuthorities().toString()); 24 | System.out.println("RoleController : " + authentication.getPrincipal()); 25 | return "I'm Jwt Token Admin!"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SpringBootSecurityJwt/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.driver-class-name=org.h2.Driver 2 | spring.datasource.url=jdbc:h2:mem:jwt;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 3 | 4 | spring.jpa.hibernate.ddl-auto=create 5 | spring.jpa.show-sql=true 6 | 7 | #logging.level.root=DEBUG -------------------------------------------------------------------------------- /SpringBootSpringDocOpenApi/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 10 | implementation 'org.springframework.boot:spring-boot-starter-web' 11 | 12 | implementation 'org.springdoc:springdoc-openapi-ui:1.8.0' 13 | 14 | runtimeOnly 'com.h2database:h2' 15 | } 16 | -------------------------------------------------------------------------------- /SpringBootSpringDocOpenApi/src/main/java/com/example/SpringBootSpringDocOpenApiApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootSpringDocOpenApiApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootSpringDocOpenApiApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootSpringDocOpenApi/src/main/java/com/example/domain/Member.java: -------------------------------------------------------------------------------- 1 | package com.example.domain; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.Id; 5 | 6 | @Entity 7 | public class Member { 8 | 9 | @Id 10 | private String id; 11 | 12 | private String pw; 13 | 14 | private String name; 15 | 16 | private String tel; 17 | 18 | protected Member() { } 19 | 20 | public Member(String id, String pw, String name, String tel) { 21 | this.id = id; 22 | this.pw = pw; 23 | this.name = name; 24 | this.tel = tel; 25 | } 26 | 27 | public String getId() { 28 | return id; 29 | } 30 | 31 | public void setId(String id) { 32 | this.id = id; 33 | } 34 | 35 | public String getPw() { 36 | return pw; 37 | } 38 | 39 | public void setPw(String pw) { 40 | this.pw = pw; 41 | } 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public void setName(String name) { 48 | this.name = name; 49 | } 50 | 51 | public String getTel() { 52 | return tel; 53 | } 54 | 55 | public void setTel(String tel) { 56 | this.tel = tel; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SpringBootSpringDocOpenApi/src/main/java/com/example/domain/MemberRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.domain; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface MemberRepository extends JpaRepository { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /SpringBootSpringDocOpenApi/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.driver-class-name=org.h2.Driver 2 | spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 3 | -------------------------------------------------------------------------------- /SpringBootSpringDocOpenApi/src/test/java/com/example/SpringBootSpringDocOpenApiApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringBootSpringDocOpenApiApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootSse/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | 10 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 11 | implementation 'org.springframework.boot:spring-boot-starter-web' 12 | 13 | runtimeOnly 'com.h2database:h2' 14 | 15 | testImplementation 'org.springframework.boot:spring-boot-starter-webflux' 16 | testImplementation 'io.projectreactor:reactor-test' 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootSse/src/main/java/com/heowc/domain/Member.java: -------------------------------------------------------------------------------- 1 | package com.heowc.domain; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | import jakarta.persistence.Entity; 6 | import jakarta.persistence.GeneratedValue; 7 | import jakarta.persistence.GenerationType; 8 | import jakarta.persistence.Id; 9 | 10 | @Entity 11 | public class Member { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.IDENTITY) 15 | private long id; 16 | 17 | private LocalDateTime createdAt; 18 | 19 | protected Member() {} 20 | 21 | public Member(LocalDateTime createdAt) { 22 | this.createdAt = createdAt; 23 | } 24 | 25 | public long getId() { 26 | return id; 27 | } 28 | 29 | public LocalDateTime getCreatedAt() { 30 | return createdAt; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "Member{" + 36 | "id=" + id + 37 | ", createdAt=" + createdAt + 38 | '}'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SpringBootSse/src/main/java/com/heowc/domain/MemberRepository.java: -------------------------------------------------------------------------------- 1 | package com.heowc.domain; 2 | 3 | import java.time.LocalDateTime; 4 | import java.util.stream.Stream; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Transactional(readOnly = true) 10 | public interface MemberRepository extends JpaRepository { 11 | 12 | Stream streamByCreatedAtAfter(LocalDateTime createdAt); 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootSse/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.driver-class-name=org.h2.Driver 2 | spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 3 | 4 | # jpa setting 5 | spring.jpa.hibernate.ddl-auto=create 6 | spring.jpa.generate-ddl=false 7 | spring.jpa.properties.hibernate.format_sql=true 8 | 9 | spring.mvc.format.date-time=iso 10 | 11 | logging.level.org.hibernate.SQL=DEBUG 12 | -------------------------------------------------------------------------------- /SpringBootStatemachine/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.statemachine:spring-statemachine-starter' 10 | testImplementation 'org.springframework.statemachine:spring-statemachine-test' 11 | 12 | } 13 | 14 | dependencyManagement { 15 | imports { 16 | mavenBom 'org.springframework.statemachine:spring-statemachine-bom:4.0.0' 17 | } 18 | } -------------------------------------------------------------------------------- /SpringBootStatemachine/src/main/java/com/example/OrderEvent.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | public enum OrderEvent { 4 | TAKE_OVER("TAKEOVER", "배송 업체 인계", Role.ADMIN), 5 | OUT_OF_STOCK("OUT_OF_STOCK", "재고부족", Role.ADMIN), 6 | // ... 7 | 8 | OFFER_RECEIPT("OFFER_RECEIPT", "주문 신청", Role.USER), 9 | RECEIPT_CANCEL("RECEIPT_CANCEL", "주문 취소", Role.USER), 10 | PURCHASE("PURCHASE", "구매", Role.USER), 11 | PURCHASE_CANCEL("PURCHASE_CANCEL", "구매 취소", Role.USER), 12 | REFUND("REFUND", "환불", Role.USER), 13 | EXCHANGE("EXCHANGE", "교환", Role.USER), 14 | RETURN("RETURN", "반품", Role.USER), 15 | CONFIRM("CONFIRM", "확정", Role.USER); 16 | 17 | private final String code; 18 | private final String description; 19 | private final Role role; 20 | 21 | OrderEvent(String code, String description, Role role) { 22 | this.code = code; 23 | this.description = description; 24 | this.role = role; 25 | } 26 | 27 | public String getCode() { 28 | return code; 29 | } 30 | 31 | public String getDescription() { 32 | return description; 33 | } 34 | 35 | public Role getRole() { 36 | return role; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SpringBootStatemachine/src/main/java/com/example/OrderState.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | public enum OrderState { 4 | RECEIPTING("RECEIPTING", "접수"), 5 | ORDER_PENDING("PENDING", "주문 대기"), 6 | DELIVERY_PENDING("DELIVERY_PENDING", "배송 대기"), 7 | DELIVERY_PROCEEDING("DELIVERY_PROCEEDING", "배송 중"), 8 | CANCEL("CANCEL", "취소"), 9 | COMPLETED("COMPLETED", "완료"); 10 | 11 | private final String code; 12 | private final String description; 13 | 14 | OrderState(String code, String description) { 15 | this.code = code; 16 | this.description = description; 17 | } 18 | 19 | public String getCode() { 20 | return code; 21 | } 22 | 23 | public String getDescription() { 24 | return description; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SpringBootStatemachine/src/main/java/com/example/Role.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | public enum Role { 4 | USER, 5 | ADMIN 6 | } 7 | -------------------------------------------------------------------------------- /SpringBootStatemachine/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootStatemachine/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootStatemachine/src/test/java/com/example/SpringBootStatemachineApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class SpringBootStatemachineApplicationTests { 8 | 9 | @Test 10 | public void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootTest/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | } 11 | -------------------------------------------------------------------------------- /SpringBootTest/src/main/java/com/example/SpringBootTestApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootTestApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootTestApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootTest/src/main/java/com/example/domain/TestMessage.java: -------------------------------------------------------------------------------- 1 | package com.example.domain; 2 | 3 | public class TestMessage { 4 | 5 | String name; 6 | int type; 7 | 8 | protected TestMessage() { } 9 | 10 | public TestMessage(String name, int type) { 11 | this.name = name; 12 | this.type = type; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | public int getType() { 24 | return type; 25 | } 26 | 27 | public void setType(int type) { 28 | this.type = type; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SpringBootTest/src/main/java/com/example/service/BasicService.java: -------------------------------------------------------------------------------- 1 | package com.example.service; 2 | 3 | import com.example.domain.TestMessage; 4 | 5 | public interface BasicService { 6 | 7 | String test(int flag); 8 | 9 | TestMessage jsonTest(); 10 | } 11 | -------------------------------------------------------------------------------- /SpringBootTest/src/main/java/com/example/service/BasicServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.service; 2 | 3 | import com.example.domain.TestMessage; 4 | import org.springframework.stereotype.Service; 5 | 6 | @Service 7 | public class BasicServiceImpl implements BasicService { 8 | 9 | @Override 10 | public String test(int flag) { 11 | return flag == 0 ? "Spring Boot Service Test" : ""; 12 | } 13 | 14 | @Override 15 | public TestMessage jsonTest() { 16 | return new TestMessage("wonchul", 0); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SpringBootTest/src/main/java/com/example/web/BasicController.java: -------------------------------------------------------------------------------- 1 | package com.example.web; 2 | 3 | import com.example.domain.TestMessage; 4 | import com.example.service.BasicService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @RestController 11 | public class BasicController { 12 | 13 | @Autowired 14 | private BasicService service; 15 | 16 | @GetMapping("/test") 17 | public String test(@RequestParam("flag") int flag) { 18 | return service.test(flag); 19 | } 20 | 21 | @GetMapping("/jsonTest") 22 | public TestMessage jsonTest() { 23 | return service.jsonTest(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpringBootTest/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootTest/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootValidator/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-web' 10 | implementation 'org.springframework.boot:spring-boot-starter-validation' 11 | 12 | runtimeOnly 'com.h2database:h2' 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/java/com/example/SpringBootValidatorApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootValidatorApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootValidatorApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/java/com/example/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.config; 2 | 3 | import org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.support.ResourceBundleMessageSource; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 8 | 9 | import java.nio.charset.StandardCharsets; 10 | import java.util.Locale; 11 | 12 | @Configuration 13 | public class WebMvcConfig implements WebMvcConfigurer { 14 | 15 | // See AbstractApplicationContext#initMessageSource 16 | @Component("messageSource") 17 | static class ValidationMessageSource extends ResourceBundleMessageSource { 18 | 19 | ValidationMessageSource() { 20 | setBasename(AbstractMessageInterpolator.USER_VALIDATION_MESSAGES); 21 | setDefaultEncoding(StandardCharsets.UTF_8.displayName()); 22 | setDefaultLocale(Locale.KOREAN); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/java/com/example/domain/Member.java: -------------------------------------------------------------------------------- 1 | package com.example.domain; 2 | 3 | import com.example.validation.Phone; 4 | 5 | import jakarta.validation.constraints.Min; 6 | import jakarta.validation.constraints.NotNull; 7 | 8 | public class Member { 9 | 10 | private long idx; 11 | 12 | @NotNull 13 | private String name; 14 | 15 | @NotNull 16 | @Min(14) 17 | private Integer age; 18 | 19 | @Phone 20 | private String phone; 21 | 22 | protected Member() { } 23 | 24 | public Member(String name, Integer age, String phone) { 25 | this.name = name; 26 | this.age = age; 27 | this.phone = phone; 28 | } 29 | 30 | public long getIdx() { 31 | return idx; 32 | } 33 | 34 | public void setIdx(long idx) { 35 | this.idx = idx; 36 | } 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | public void setName(String name) { 43 | this.name = name; 44 | } 45 | 46 | public Integer getAge() { 47 | return age; 48 | } 49 | 50 | public void setAge(Integer age) { 51 | this.age = age; 52 | } 53 | 54 | public String getPhone() { 55 | return phone; 56 | } 57 | 58 | public void setPhone(String phone) { 59 | this.phone = phone; 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/java/com/example/errorhandler/ErrorMessage.java: -------------------------------------------------------------------------------- 1 | package com.example.errorhandler; 2 | 3 | public class ErrorMessage { 4 | 5 | private final String field; 6 | private final String message; 7 | 8 | public static ErrorMessage of(String field, String message) { 9 | return new ErrorMessage(field, message); 10 | } 11 | 12 | protected ErrorMessage(String field, String message) { 13 | this.field = field; 14 | this.message = message; 15 | } 16 | 17 | public String getField() { 18 | return field; 19 | } 20 | 21 | public String getMessage() { 22 | return message; 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/java/com/example/validation/Phone.java: -------------------------------------------------------------------------------- 1 | package com.example.validation; 2 | 3 | import jakarta.validation.Constraint; 4 | import jakarta.validation.Payload; 5 | import java.lang.annotation.*; 6 | 7 | @Documented 8 | @Constraint(validatedBy = PhoneValidator.class) 9 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface Phone { 12 | String message() default "{com.example.validation.Phone.message}"; 13 | 14 | Class[] groups() default {}; 15 | 16 | Class[] payload() default {}; 17 | } 18 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/java/com/example/validation/PhoneValidator.java: -------------------------------------------------------------------------------- 1 | package com.example.validation; 2 | 3 | import jakarta.validation.ConstraintValidator; 4 | import jakarta.validation.ConstraintValidatorContext; 5 | import java.util.regex.Pattern; 6 | 7 | public class PhoneValidator implements ConstraintValidator { 8 | 9 | private static final Pattern PATTERN = Pattern.compile("[0-9]+"); 10 | 11 | @Override 12 | public void initialize(Phone constraintAnnotation) { 13 | 14 | } 15 | 16 | @Override 17 | public boolean isValid(String field, ConstraintValidatorContext cxt) { 18 | return field != null && PATTERN.matcher(field).matches() 19 | && (field.length() > 8) && (field.length() < 14); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/java/com/example/web/MemberController.java: -------------------------------------------------------------------------------- 1 | package com.example.web; 2 | 3 | import com.example.domain.Member; 4 | import com.example.validation.Phone; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.validation.annotation.Validated; 7 | import org.springframework.web.bind.annotation.*; 8 | 9 | import jakarta.validation.Valid; 10 | import jakarta.validation.constraints.Min; 11 | import jakarta.validation.constraints.NotNull; 12 | 13 | 14 | @Validated 15 | @RestController 16 | @RequestMapping("member") 17 | public class MemberController { 18 | 19 | @PostMapping 20 | public ResponseEntity postAdd(@Valid @RequestBody Member member) { 21 | return ResponseEntity.ok(member); 22 | } 23 | 24 | @GetMapping 25 | public ResponseEntity getAdd(@NotNull String name, 26 | @NotNull @Min(14) Integer age, 27 | @Phone String phone) { 28 | return ResponseEntity.ok(new Member(name, age, phone)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/resources/ValidationMessages.properties: -------------------------------------------------------------------------------- 1 | com.example.validation.Phone.message=must be a well-formed phone number 2 | body.incorrect.message=body is incorrect 3 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/resources/ValidationMessages_ko.properties: -------------------------------------------------------------------------------- 1 | com.example.validation.Phone.message=올바른 형식의 전화번호여야 합니다 2 | body.incorrect.message=본문이 올바르지 않습니다 3 | -------------------------------------------------------------------------------- /SpringBootValidator/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.database=H2 2 | spring.datasource.driver-class-name=org.h2.Driver 3 | spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 4 | spring.datasource.username=test 5 | spring.datasource.password=test 6 | 7 | spring.jpa.generate-ddl=false 8 | spring.jpa.hibernate.ddl-auto=create 9 | spring.jpa.show-sql=true -------------------------------------------------------------------------------- /SpringBootValidator/src/test/java/com/example/SpringBootValidatorApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringBootValidatorApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootValidator/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.servlet.encoding.force-response=true 2 | spring.web.locale=ko 3 | -------------------------------------------------------------------------------- /SpringBootVertx/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | configurations { 9 | compile.exclude module: "spring-boot-starter-tomcat" 10 | compileOnly { 11 | extendsFrom annotationProcessor 12 | } 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | implementation 'com.fasterxml.jackson.core:jackson-databind' 19 | implementation 'io.vertx:vertx-web:4.5.14' 20 | runtimeOnly 'com.h2database:h2' 21 | 22 | compileOnly 'org.projectlombok:lombok' 23 | annotationProcessor 'org.projectlombok:lombok' 24 | } 25 | -------------------------------------------------------------------------------- /SpringBootVertx/src/main/java/com/tistory/heowc/SpringBootVertxApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import com.tistory.heowc.verticle.ServerVerticle; 4 | import io.vertx.core.Vertx; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | 9 | import jakarta.annotation.PostConstruct; 10 | 11 | @SpringBootApplication 12 | public class SpringBootVertxApplication { 13 | 14 | @Autowired 15 | private ServerVerticle serverVerticle; 16 | 17 | // @Autowired 18 | // private ArticleRecipientVerticle articleRecipientVerticle; 19 | 20 | @Autowired 21 | private Vertx vertx; 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(SpringBootVertxApplication.class, args); 25 | } 26 | 27 | @PostConstruct 28 | public void create() { 29 | vertx.deployVerticle(serverVerticle); 30 | // vertx.deployVerticle(articleRecipientVerticle); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SpringBootVertx/src/main/java/com/tistory/heowc/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.core.env.Environment; 6 | 7 | @Configuration 8 | public class AppConfig { 9 | 10 | @Autowired 11 | private Environment environment; 12 | 13 | public String applicationName() { 14 | return environment.getProperty("spring.application.name"); 15 | } 16 | 17 | public int httpPort() { 18 | return environment.getProperty("server.port", Integer.class); 19 | } 20 | } -------------------------------------------------------------------------------- /SpringBootVertx/src/main/java/com/tistory/heowc/config/VertxConfig.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.config; 2 | 3 | import io.vertx.core.Vertx; 4 | import io.vertx.core.VertxOptions; 5 | import io.vertx.core.eventbus.EventBus; 6 | import io.vertx.ext.web.Router; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @Configuration 11 | public class VertxConfig { 12 | 13 | @Bean 14 | public Vertx vertx() { 15 | return Vertx.vertx(vertxOptions()); 16 | } 17 | 18 | @Bean 19 | public VertxOptions vertxOptions() { 20 | return new VertxOptions(); 21 | } 22 | 23 | @Bean 24 | public Router router() { 25 | return Router.router(vertx()); 26 | } 27 | 28 | @Bean 29 | public EventBus eventBus() { 30 | return vertx().eventBus(); 31 | } 32 | } -------------------------------------------------------------------------------- /SpringBootVertx/src/main/java/com/tistory/heowc/config/loader/DefaultRouterLoader.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.config.loader; 2 | 3 | import com.tistory.heowc.router.ArticleRouter; 4 | import io.vertx.ext.web.Router; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class DefaultRouterLoader implements RouterLoader { 10 | 11 | @Autowired 12 | private Router router; 13 | 14 | @Autowired 15 | private ArticleRouter articleRouter; 16 | 17 | public Router load() { 18 | articleRouter.route(); 19 | return router; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SpringBootVertx/src/main/java/com/tistory/heowc/config/loader/RouterLoader.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.config.loader; 2 | 3 | import io.vertx.ext.web.Router; 4 | 5 | public interface RouterLoader { 6 | 7 | Router load(); 8 | } 9 | -------------------------------------------------------------------------------- /SpringBootVertx/src/main/java/com/tistory/heowc/domain/Article.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import jakarta.persistence.Entity; 8 | import jakarta.persistence.Id; 9 | 10 | @Entity 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class Article { 15 | 16 | @Id 17 | private Long id; 18 | private String content; 19 | } -------------------------------------------------------------------------------- /SpringBootVertx/src/main/java/com/tistory/heowc/repository/ArticleRepository.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import com.tistory.heowc.domain.Article; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface ArticleRepository extends JpaRepository { 7 | } -------------------------------------------------------------------------------- /SpringBootVertx/src/main/java/com/tistory/heowc/service/ArticleService.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.service; 2 | 3 | import com.tistory.heowc.domain.Article; 4 | import com.tistory.heowc.repository.ArticleRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.List; 9 | 10 | @Service 11 | public class ArticleService { 12 | 13 | @Autowired 14 | private ArticleRepository articleRepository; 15 | 16 | public List
getAllArticle() { 17 | return articleRepository.findAll(); 18 | } 19 | } -------------------------------------------------------------------------------- /SpringBootVertx/src/main/java/com/tistory/heowc/verticle/ServerVerticle.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.verticle; 2 | 3 | import com.tistory.heowc.config.AppConfig; 4 | import com.tistory.heowc.config.loader.RouterLoader; 5 | import io.vertx.core.AbstractVerticle; 6 | import io.vertx.ext.web.Router; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class ServerVerticle extends AbstractVerticle { 12 | 13 | @Autowired 14 | private AppConfig appConfig; 15 | 16 | @Autowired 17 | private RouterLoader routerLoader; 18 | 19 | @Override 20 | public void start() throws Exception { 21 | super.start(); 22 | 23 | Router router = routerLoader.load(); 24 | vertx.createHttpServer().requestHandler(router::handle).listen(appConfig.httpPort()); 25 | } 26 | } -------------------------------------------------------------------------------- /SpringBootVertx/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.database=H2 2 | spring.datasource.driver-class-name=org.h2.Driver 3 | spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 4 | 5 | # jpa setting 6 | spring.jpa.hibernate.ddl-auto=create 7 | spring.jpa.generate-ddl=false 8 | spring.jpa.show-sql=true 9 | 10 | server.port=8080 -------------------------------------------------------------------------------- /SpringBootVertx/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _____ _ ____ __ ___ _ __ __ 2 | / ___/____ _____(_)___ ____ _ / __ )____ ____ / /_ ( _ ) | | / /__ _____/ /_ _ __ 3 | \__ \/ __ \/ ___/ / __ \/ __ `/ / __ / __ \/ __ \/ __/ / __ \/| | | / / _ \/ ___/ __/ | |/_/ 4 | ___/ / /_/ / / / / / / / /_/ / / /_/ / /_/ / /_/ / /_ / /_/ < | |/ / __/ / / /__ _> < 5 | /____/ .___/_/ /_/_/ /_/\__, / /_____/\____/\____/\__/ \____/\/ |___/\___/_/ \__(_)_/|_| 6 | /_/ /____/ -------------------------------------------------------------------------------- /SpringBootVertx/src/test/java/com/tistory/heowc/SpringBootVertxApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringBootVertxApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /SpringBootWar/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'war' 3 | } 4 | 5 | group = 'com.example' 6 | version = '0.0.1-SNAPSHOT' 7 | 8 | bootWar { 9 | archiveFileName = 'spring-boot.war' 10 | } 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' 19 | } 20 | -------------------------------------------------------------------------------- /SpringBootWar/src/main/java/com/example/SpringBootWarApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 7 | 8 | @SpringBootApplication 9 | public class SpringBootWarApplication extends SpringBootServletInitializer { 10 | 11 | @Override 12 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 13 | return application.sources(SpringBootWarApplication.class); 14 | } 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(SpringBootWarApplication.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SpringBootWar/src/main/java/com/example/web/BasicController.java: -------------------------------------------------------------------------------- 1 | package com.example.web; 2 | 3 | 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | public class BasicController { 10 | 11 | @GetMapping("${message}") 12 | public String getMessage(@RequestParam String message) { 13 | return message; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SpringBootWar/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootWar/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootWebFlux/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation 'org.springframework.boot:spring-boot-starter-webflux' 10 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 11 | 12 | runtimeOnly 'com.h2database:h2' 13 | 14 | testImplementation('io.projectreactor.addons:reactor-test:3.0.7.RELEASE') 15 | } 16 | -------------------------------------------------------------------------------- /SpringBootWebFlux/src/main/java/com/tistory/heowc/SpringBootWebFluxApplication.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc; 2 | 3 | import com.tistory.heowc.domain.Message; 4 | import com.tistory.heowc.service.MessageService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.ApplicationRunner; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.context.annotation.Bean; 10 | import reactor.core.publisher.Mono; 11 | 12 | @SpringBootApplication 13 | public class SpringBootWebFluxApplication { 14 | 15 | @Autowired 16 | private MessageService messageService; 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(SpringBootWebFluxApplication.class, args); 20 | } 21 | 22 | @Bean 23 | public ApplicationRunner applicationRunner() { 24 | return arguments -> messageService.add(Mono.just(new Message("hi"))); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SpringBootWebFlux/src/main/java/com/tistory/heowc/config/AsyncConfig.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.scheduling.annotation.AsyncConfigurerSupport; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | 7 | import java.util.concurrent.Executor; 8 | import java.util.concurrent.Executors; 9 | 10 | @Configuration 11 | @EnableAsync 12 | public class AsyncConfig extends AsyncConfigurerSupport { 13 | 14 | @Override 15 | public Executor getAsyncExecutor() { 16 | return Executors.newWorkStealingPool(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SpringBootWebFlux/src/main/java/com/tistory/heowc/domain/Message.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.domain; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.GeneratedValue; 5 | import jakarta.persistence.GenerationType; 6 | import jakarta.persistence.Id; 7 | 8 | @Entity 9 | public class Message { 10 | 11 | @Id @GeneratedValue(strategy = GenerationType.AUTO) 12 | private Long idx; 13 | private String content; 14 | 15 | protected Message() {} 16 | 17 | public Message(String content) { 18 | this.content = content; 19 | } 20 | 21 | public Long getIdx() { 22 | return idx; 23 | } 24 | 25 | public void setIdx(Long idx) { 26 | this.idx = idx; 27 | } 28 | 29 | public String getContent() { 30 | return content; 31 | } 32 | 33 | public void setContent(String content) { 34 | this.content = content; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SpringBootWebFlux/src/main/java/com/tistory/heowc/repository/MessageRepository.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.repository; 2 | 3 | import com.tistory.heowc.domain.Message; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface MessageRepository extends JpaRepository { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /SpringBootWebFlux/src/main/java/com/tistory/heowc/web/MessageController.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.web; 2 | 3 | import com.tistory.heowc.domain.Message; 4 | import com.tistory.heowc.service.MessageService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.*; 7 | import reactor.core.publisher.Mono; 8 | 9 | @RestController 10 | @RequestMapping("message") 11 | public class MessageController { 12 | 13 | @Autowired 14 | private MessageService messageService; 15 | 16 | @GetMapping("{idx}") 17 | public Mono findByOne(@PathVariable Long idx) { 18 | return Mono.fromCompletionStage(messageService.findByOne(idx)); 19 | } 20 | 21 | @PostMapping 22 | public Mono add(@RequestBody Mono messageMono) { 23 | return Mono.fromCompletionStage(messageService.add(messageMono)); 24 | } 25 | 26 | @PutMapping 27 | public Mono modify(@RequestBody Mono messageMono) { 28 | return Mono.fromCompletionStage(messageService.modify(messageMono)); 29 | } 30 | 31 | @DeleteMapping("{idx}") 32 | public void remove(@PathVariable Long idx) { 33 | messageService.remove(idx); 34 | } 35 | } -------------------------------------------------------------------------------- /SpringBootWebFlux/src/main/java/com/tistory/heowc/web/MessageRouter.java: -------------------------------------------------------------------------------- 1 | package com.tistory.heowc.web; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.http.MediaType; 6 | import org.springframework.web.reactive.function.server.RouterFunction; 7 | import org.springframework.web.reactive.function.server.ServerResponse; 8 | 9 | import static org.springframework.web.reactive.function.server.RequestPredicates.*; 10 | import static org.springframework.web.reactive.function.server.RouterFunctions.route; 11 | 12 | @Configuration 13 | public class MessageRouter { 14 | 15 | @Bean 16 | public RouterFunction routerFunction(MessageHandler messageHandler) { 17 | return route(GET("message/{id}").and(accept(MediaType.APPLICATION_JSON)), messageHandler::findByOne) 18 | .andRoute(POST("message").and(accept(MediaType.APPLICATION_JSON)), messageHandler::add) 19 | .andRoute(PUT("message").and(accept(MediaType.APPLICATION_JSON)), messageHandler::modify) 20 | .andRoute(DELETE("message/{id}").and(accept(MediaType.APPLICATION_JSON)), messageHandler::remove); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SpringBootWebFlux/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.database=H2 2 | spring.datasource.driver-class-name=org.h2.Driver 3 | spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 4 | spring.datasource.username=test 5 | spring.datasource.password=test 6 | 7 | # jpa setting 8 | spring.jpa.hibernate.ddl-auto=create 9 | spring.jpa.generate-ddl=false 10 | spring.jpa.show-sql=true -------------------------------------------------------------------------------- /SpringBootWebSocket/build.gradle: -------------------------------------------------------------------------------- 1 | group = 'com.example' 2 | version = '0.0.1-SNAPSHOT' 3 | 4 | repositories { 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | implementation"org.springframework.boot:spring-boot-starter-websocket" 10 | implementation"org.webjars:webjars-locator:0.39" 11 | implementation"org.webjars:sockjs-client:1.1.2" 12 | implementation"org.webjars:stomp-websocket:2.3.3" 13 | implementation"org.webjars:bootstrap:4.4.1-1" 14 | implementation"org.webjars:jquery:3.4.0" 15 | } 16 | -------------------------------------------------------------------------------- /SpringBootWebSocket/src/main/java/com/example/SpringBootWebSocketApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootWebSocketApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootWebSocketApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SpringBootWebSocket/src/main/java/com/example/config/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.messaging.simp.config.MessageBrokerRegistry; 6 | import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; 7 | import org.springframework.web.socket.config.annotation.StompEndpointRegistry; 8 | import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; 9 | 10 | @Configuration 11 | @EnableWebSocketMessageBroker 12 | public class WebSocketConfig { 13 | 14 | @Bean 15 | public WebSocketMessageBrokerConfigurer webSocketMessageBrokerConfigurer() { 16 | return new WebSocketMessageBrokerConfigurer() { 17 | @Override 18 | public void registerStompEndpoints(StompEndpointRegistry registry) { 19 | registry.addEndpoint("/wonchul-websocket").withSockJS(); 20 | } 21 | 22 | @Override 23 | public void configureMessageBroker(MessageBrokerRegistry registry) { 24 | registry.enableSimpleBroker("/chat"); 25 | registry.setApplicationDestinationPrefixes("/"); 26 | } 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /SpringBootWebSocket/src/main/java/com/example/controller/ChatController.java: -------------------------------------------------------------------------------- 1 | package com.example.controller; 2 | 3 | import com.example.message.HelloMessage; 4 | import org.springframework.messaging.handler.annotation.MessageMapping; 5 | import org.springframework.messaging.handler.annotation.SendTo; 6 | import org.springframework.stereotype.Controller; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | @Controller 11 | public class ChatController { 12 | 13 | @MessageMapping("hello") 14 | @SendTo("/chat/hello") 15 | public HelloMessage hello(HelloMessage message) throws Exception { 16 | Thread.sleep(100); 17 | return message; 18 | } 19 | 20 | @MessageMapping("bye") 21 | @SendTo("/chat/bye") 22 | public HelloMessage bye(HelloMessage message) throws Exception { 23 | Thread.sleep(100); 24 | return message; 25 | } 26 | 27 | @MessageMapping("detail") 28 | @SendTo("/chat/detail") 29 | public HelloMessage detail(HelloMessage message) throws Exception { 30 | Thread.sleep(100); 31 | message.setSendDate(LocalDateTime.now()); 32 | return message; 33 | } 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /SpringBootWebSocket/src/main/java/com/example/message/HelloMessage.java: -------------------------------------------------------------------------------- 1 | package com.example.message; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | public class HelloMessage { 6 | 7 | private String name; 8 | private String contents; 9 | private LocalDateTime sendDate; 10 | 11 | protected HelloMessage() { } 12 | 13 | public HelloMessage(String name, String contents, LocalDateTime sendDate) { 14 | this.name = name; 15 | this.contents = contents; 16 | this.sendDate = sendDate; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public void setName(String name) { 24 | this.name = name; 25 | } 26 | 27 | public String getContents() { 28 | return contents; 29 | } 30 | 31 | public void setContents(String contents) { 32 | this.contents = contents; 33 | } 34 | 35 | public LocalDateTime getSendDate() { 36 | return sendDate; 37 | } 38 | 39 | public void setSendDate(LocalDateTime sendDate) { 40 | this.sendDate = sendDate; 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /SpringBootWebSocket/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/SpringBootWebSocket/src/main/resources/application.properties -------------------------------------------------------------------------------- /SpringBootWebSocket/src/main/resources/static/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #f5f5f5; 3 | } 4 | 5 | #main-content { 6 | max-width: 940px; 7 | padding: 2em 3em; 8 | margin: 0 auto 20px; 9 | background-color: #fff; 10 | border: 1px solid #e5e5e5; 11 | -webkit-border-radius: 5px; 12 | -moz-border-radius: 5px; 13 | border-radius: 5px; 14 | } 15 | 16 | .chat-panel .panel-body { 17 | height: 700px; 18 | overflow-y: scroll; 19 | } 20 | 21 | .chat { 22 | list-style: none; 23 | margin: 0px; 24 | padding: 0px; 25 | } 26 | 27 | .chat li { 28 | margin-bottom: 10px; 29 | padding-bottom: 5px; 30 | border-bottom: 1px dotted #999999; 31 | } 32 | 33 | .form-group { 34 | margin-bottom: 0px !important; 35 | } -------------------------------------------------------------------------------- /SpringBootWebSocket/src/test/java/com/example/SpringBootWebSocketApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringBootWebSocketApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heowc/SpringBootSample/9631cf5080383c5776f7e4a5891bfa1be7f2d1e9/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | --------------------------------------------------------------------------------