package repository; import hello.hellospring.domain.Member; import hello.hellospring.repository.MemoryMemberRepository; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import java.util.List; import java.util.Optional; import static org.assertj.core.api.Assertions.*; class MemoryMemberRepositoryTest { MemoryMemberRepository repository = new MemoryMemberRepository(); @AfterEach public void afterEach() { repository.clearStore(); } @Test public void save() { //given Member member = new Member(); member.setName("spring"); //when repository.save(member); //then Member result = repository.findById(member.getId()).get(); assertThat(result).isEqualTo(member); } @Test public void findByName() { //given Member member1 = new Member(); member1.setName("spring1"); repository.save(member1); Member member2 = new Member(); member2.setName("spring2"); repository.save(member2); //when Member result = repository.findByName("spring1").get(); assertThat(result).isEqualTo(member1); //then } @Test public void findAll() { //given Member member1 = new Member(); member1.setName("spring1"); repository.save(member1); Member member2 = new Member(); member2.setName("spring2"); repository.save(member2); //when List<Member> result = repository.findAll(); //then assertThat(result.size()).isEqualTo(2); } } package hello.hellospring.repository; import hello.hellospring.domain.Member; import java.util.List; import java.util.Optional; public interface MemberRepository { Member save(Member member); Optional<Member> findById(Long id); Optional<Member> findByName(String name); List<Member> findAll(); } package hello.hellospring.repository; import hello.hellospring.domain.Member; import java.util.*; public class MemoryMemberRepository implements MemberRepository { private static Map<Long, Member> store = new HashMap<>(); private static long sequence = 0L; @Override public Member save(Member member) { member.setId(++sequence); store.put(member.getId(), member); return member; } @Override public Optional<Member> findById(Long id) { return Optional.ofNullable(store.get(id)); } @Override public List<Member> findAll() { return new ArrayList<>(store.values()); } @Override public Optional<Member> findByName(String name) { return store.values().stream() .filter(member -> member.getName().equals(name)) .findAny(); } public void clearStore() { store.clear(); } } 이렇게 오류가 발생하는데 이유가 뭘까요? 아래와 같이 코드를 수정해보기도 하였습니다만, findAll 과 같이 노란색이 될뿐 초록색 마크가 나오지는 않습니다. @Test public void findByName() { // given Member member1 = new Member(); member1.setName("spring1"); repository.save(member1); Member member2 = new Member(); member2.setName("spring2"); repository.save(member2); // when Optional<Member> result = repository.findByName("spring1"); // then assertThat(result.isPresent()).isTrue(); assertThat(result.get()).isEqualTo(member1); }
질문 내용] 여기에 질문 내용을 남겨주세요. 일단 두 사진 보시면, 예외 처리를 해주면 예외 처리가 try 내부 코드가 예외를 안던지니까 catch 빼라고 하고, 예외 처리를 안해주면, IOException이 예외처리가 안됐다고 하네요.. 뭐가 문제죠..? 람다를 사용했다고 해서 안될리가 없어보이는데 ㅠㅠ 추가로 out.write();가 Writer 추상 클래스의 write(); 메서드고 checked예외를 던지던데, try-catch로 안잡아줘도 되는 이유가 뭔가요??
안녕하세요! 선생님 강의를 재밌고 유익하게 수강하고 있는 학생입니다. 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 강의의 bean validation - HTTP 메시지 컨버터 부분을 수강하던 중 강의 내용과 제 결과 케이스의 다른 부분이 있어 다른 결과가 나오게 된 원인이 궁금하여 질문 드립니다! 강의와 결과가 달랐던 부분은 postman으로 실패 요청을 send했을 때의 응답 결과 입니다. 강의의 결과입니다. { "timestamp": "2021-04-20T00:00:00.000+00:00", "status": 400, "error": "Bad Request", "message": "", "path": "/validation/api/items/add" } 제가 실행한 결과입니다. { "timestamp": "2021-04-20T00:00:00.000+00:00", "status": 400, "error": "Bad Request", "path": "/validation/api/items/add" } 보이는 바와 같이, 제가 실행한 결과에서는 message에 대한 json 객체가 존재하지 않습니다. 혹시 스프링 부트의 버전과 관련된 부분에 있어서 차이가 있을까요? 현재 사용 중인 스프링 부트 버전은 2.7.11 버전입니다.
로컬에서 파일 업로드를 구현할 때는 강의때 해준 방법 처럼 file.dir변수에 C:/test_img/ 이런식으로 변수를 지정하고 저장을 하였는데 이번에 cafe24를 사용해서 프로젝트를 배포하는 작업중인데 어떻게 경로를 설정해야할 지 모르겠어서 질문드립니다ㅠㅠ cafe24에 문의 해보았는데 server.xml 파일에서 해당 경로를 매핑 해줘야 한다고 하였습니다. <Context docBase ="서버의 업로드 폴더 경로" path=" localhost 뒤에 붙을 업로드 폴더의 경로" reloadable="true"/> https://yn971106.tistory.com/104?category=1016466 https://kang0312.tistory.com/95 https://tibang.tistory.com/entry/%EC%82%AC%EC%A7%84%EA%B0%99%EC%9D%80-%ED%8C%8C%EC%9D%BC-%EC%97%85%EB%A1%9C%EB%93%9C%EC%8B%9C-%EA%B2%BD%EB%A1%9C-%EC%84%A4%EC%A0%95%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95tomcat-%EA%B8%B0%EC%A4%80 아래 블로그를 참고하라고 하긴하던데 매핑하는 방법만 알려주고, 파일업 업로드하는 로직은 없고, 구글링을 해봐도 강사님께서 알려주신 파일 업로드 로직과는 다른 글들 뿐이여서 파일 업로드 로직을 다 뜯어 고쳐야 하는건가.... 고민입니다. 혹시 file.dir값만 딱 수정해서 서버에서 파일 업로드 할 수 있는 방법 아시면 알려주시면 감사하겠습니다.... 참고로 cafe24서버에 올린 폴더 경로입니다 upload폴더는 제가 생성한거고 권한도 777로 주었습니다. file.dir=/tomcat/webapps/upload/ 위와같이 경로 값을 주었는데 잘 작동하지 않습니다ㅠㅠ +추가 강사님이 알려주신 file.dir을 통해 파일 경로를 지정하는 방법은 spring boot에서 톰캣서버를 내장하고 있어서 가능한건가요?? cafe24에 배포할 때는 서버를 내장하지 않으므로 server.xml에 <Context docBase="D:\IMAGES" path="/IMAGES" reloadable="false"/> 이거를 추가해야하는 건가요?? 서버쪽 영역으로 가니까 아직 모르는게 많네요ㅠㅠㅠ
안녕하세요. 로그인 처리1 마지막 부분 세션 타임아웃 설정부분. pdf 41page가 안됩니다. application.properties 파일에서 server.servlet.session.timeout=10 이렇게 해보기도 하고 SessionInfoController에서 session.setMaxInactiveInterval(10); 이렇게 해보아도 타임아웃이 되지 않습니다. 제가 기대하는 것은 10초 뒤에는 세션아웃이 되어서 로그인이 필요한 페이지에 접근이 않되는 것인데요. 제가 잘못이해하거나 설정이 안된 부분이 있다면 알려주시면 감사하겠습니다. 제가 작성한 프로젝트는 여기에 올렸습니다. https://drive.google.com/file/d/1q1VbFHc21BpUgeTIjCvCd5WmXW-abwHm/view?usp=share_link
두가지 궁금사항이 있습니다. 1.첫번째 @Aspect 애노테이션 을 사용한다면 의존성 추가해야된다고 인터넷에 나와있는데, 꼭 안해도 되는건가요??? implementation 'org.springframework.boot:spring-boot-starter-aop' 2.두번째 TimeTraceAop class에 @Component 애노테이션을 추가하면 에러가 안나는데, SpringConfig class에 @bean 으로 등록시 에러가 납니다. 콘피그에 빈으로 등록코드를 적을경우 또다른 코드를 주입해야되나요?
@GetMapping("/formatter/edit") public String formatterForm(Model model){ Form form = new Form(); form.setNumber(10000); form.setLocalDateTime(LocalDateTime.now()); log.info("form={}",form); model.addAttribute("form",form); return "formatter-form"; } @PostMapping("/formatter/edit") public String formatterEdit(@ModelAttribute Form form){ log.info("post form={}",form); return "formatter-view"; } 로그를 통해 form, post form을 출력해보았습니다. 저는 처음 form은 그냥 입력한 값이 나오고 그다음 post form은 ModelAttribute에 들어갈 때 public String formatterEdit(@ModelAttribute Form form){ 포멧터가 form의 타입을 변경하고 입력한다고 예상했습니다. 하지만 로그를 보니 form=FormatterController.Form(number=10000, localDateTime=2023-04-23T12:39:53.251212) post form=FormatterController.Form(number=10000, localDateTime=2023-04-23T12:39:53) 값은 값이 나오는 것을 확인했습니다. 제가 생각했을 때는 Argument Resolver 안에 ConversionService 안에 Formatter 가 controller를 호출하기 전 @ModelAttribute에 입력할 때 실행되지만 @Data static class Form{ @NumberFormat(pattern = "###,###") private Integer number; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime localDateTime; } 에서 @NumberFormat(pattern = "###,###") 패턴이 적용 되는 시점은 html에서 "${{form.number}}" 중괄호2개가 있을 때다. 그래서 로그는 값은 같은 값이 출력이 되지만 html에서는 다른 값이 출력된다. 라고 이해를 했는 데 맞게 생각한 것인지 궁금합니다. 답변주시면 정말 감사하겠습니다.
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 안녕하세요. 패키지 구조에 대해서 문의 드립니다. 무료로 제공되는 Spring Introduction 강의에는 패키지 구조가 controller, domain, repository, service 이렇게 나누어 지는데요. Spring MVC1편, 2편으로 넘어오면서 controller, reposityory, service 패키지는 사라지고 domain, web 패키지 밑에 비지니스 요구사항에 대해서 나온 업무, 예를 들어 item, login, member를 기준으로 서브 패키지를 만들어서 각각 domain, web 패키지의 하부 패키지를 두고 여기서 controller, repository, service에 필요한 내용을 섞어서 집어 넣었습니다. 그리고 MVC 2편 강의로 가니까. web 패키지 밑에 argumentresolver, session 패키지 같이 비지니스 요구사항과 관련된 요구사항이라기 보다. 스프링 기능에 관련된 기능이 web 패키지 밑에 들어왔습니다. 그러다 보니 패키지 구조가 Spring Introduction 강의에서 나누었던 패키지 구조보다 뭐랄까 중구난방으로 섞여있는 느낌이 듭니다. 질문] 실무에서도 MVC 2편강의에 분리된 형태로 많이 하는지 아니면 Spring Introduction에서 제시한 controller, domain, repository, service 패키지를 기준으로 새로운 패키지가 추가 또는 세분화 되는지 궁금합니다. 그럼 답변 부탁드립니다. 감사합니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 컨트롤러에서 String 을 리턴하면 경로잖아요 근데 그게 static에 있는 정적 리소스인지 templates에 있는 동적리소스인지도 구분가능한가요? 아니면 무조건 동적으로 가는건가요?
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 안녕하세요 처음에 타임리프 의존성 추가 없이 해서 계속 페이지가 없다고 404오류가 나왔습니다. 다른분이 타임리프 없이 할 경우 어떻게 해야하는지 질문주신것에 restapi방식을 많이 사용한다고 답해주신것은 보았는데 템플릿엔진이 없으면 아예 뷰리졸버가 동작하지 않는 것인지 궁금합니다. application.properties 파일에 spring.mvc.view.prefix=/resources/templates/ spring.mvc.view.suffix=.html 이 코드도 추가해보고, static, templates 폴더에 모두 보여주고싶은 html파일도 넣어보았는데 controller는 동작하고 뷰가 없다고 합니다 감사합니다 :)
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 클래스에 컨트롤러 붙여주면 스프링빈에 자동등록되서 생성자에 Autowired 붙여줄필요없는거 아닌가요?