diff --git a/3.spring-MVC1/1.servlet/src/main/java/hello/servlet/web/servlet/MemberListServlet.java b/3.spring-MVC1/1.servlet/src/main/java/hello/servlet/web/servlet/MemberListServlet.java index 96063c6..44c2353 100644 --- a/3.spring-MVC1/1.servlet/src/main/java/hello/servlet/web/servlet/MemberListServlet.java +++ b/3.spring-MVC1/1.servlet/src/main/java/hello/servlet/web/servlet/MemberListServlet.java @@ -31,7 +31,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) w.write(" Title"); w.write(""); w.write(""); - w.write("메인"); + w.write("메인"); w.write(""); w.write(" "); w.write(" "); diff --git a/3.spring-MVC1/1.servlet/src/main/java/hello/servlet/web/servlet/MemberSaveServlet.java b/3.spring-MVC1/1.servlet/src/main/java/hello/servlet/web/servlet/MemberSaveServlet.java index 32fe39f..5ca2e22 100644 --- a/3.spring-MVC1/1.servlet/src/main/java/hello/servlet/web/servlet/MemberSaveServlet.java +++ b/3.spring-MVC1/1.servlet/src/main/java/hello/servlet/web/servlet/MemberSaveServlet.java @@ -37,7 +37,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) "
  • username="+member.getUsername()+"
  • \n" + "
  • age="+member.getAge()+"
  • \n" + "\n" + - "메인\n" + + "메인\n" + "\n" + ""); } diff --git a/3.spring-MVC1/1.servlet/src/main/webapp/WEB-INF/views/members.jsp b/3.spring-MVC1/1.servlet/src/main/webapp/WEB-INF/views/members.jsp index 1a183c8..9b941b6 100644 --- a/3.spring-MVC1/1.servlet/src/main/webapp/WEB-INF/views/members.jsp +++ b/3.spring-MVC1/1.servlet/src/main/webapp/WEB-INF/views/members.jsp @@ -6,7 +6,7 @@ Title -메인 +메인
    id
    diff --git a/3.spring-MVC1/1.servlet/src/main/webapp/WEB-INF/views/save-result.jsp b/3.spring-MVC1/1.servlet/src/main/webapp/WEB-INF/views/save-result.jsp index 8655385..c5d81a1 100644 --- a/3.spring-MVC1/1.servlet/src/main/webapp/WEB-INF/views/save-result.jsp +++ b/3.spring-MVC1/1.servlet/src/main/webapp/WEB-INF/views/save-result.jsp @@ -12,6 +12,6 @@ <%-- 이런것도 가능함, 그러나 더 불편--%> <%-- --%> -메인 +메인 \ No newline at end of file diff --git a/3.spring-MVC1/1.servlet/src/main/webapp/index.html b/3.spring-MVC1/1.servlet/src/main/webapp/index.jsp similarity index 100% rename from 3.spring-MVC1/1.servlet/src/main/webapp/index.html rename to 3.spring-MVC1/1.servlet/src/main/webapp/index.jsp diff --git a/3.spring-MVC1/1.servlet/src/main/webapp/jsp/members.jsp b/3.spring-MVC1/1.servlet/src/main/webapp/jsp/members.jsp index a0e3db0..10df698 100644 --- a/3.spring-MVC1/1.servlet/src/main/webapp/jsp/members.jsp +++ b/3.spring-MVC1/1.servlet/src/main/webapp/jsp/members.jsp @@ -12,7 +12,7 @@ Title - 메인 + 메인
    id
    diff --git a/3.spring-MVC1/1.servlet/src/main/webapp/jsp/members/save.jsp b/3.spring-MVC1/1.servlet/src/main/webapp/jsp/members/save.jsp index 3ad5f64..fb3dff1 100644 --- a/3.spring-MVC1/1.servlet/src/main/webapp/jsp/members/save.jsp +++ b/3.spring-MVC1/1.servlet/src/main/webapp/jsp/members/save.jsp @@ -30,6 +30,6 @@
  • username=<%=member.getAge()%>
  • age=<%=member.getAge()%>
  • -메인 +메인 diff --git a/3.spring-MVC1/3.item-service/src/main/java/hello/itemservice/web/basic/BasicItemController.java b/3.spring-MVC1/3.item-service/src/main/java/hello/itemservice/web/basic/BasicItemController.java index a4d93d6..19d8940 100644 --- a/3.spring-MVC1/3.item-service/src/main/java/hello/itemservice/web/basic/BasicItemController.java +++ b/3.spring-MVC1/3.item-service/src/main/java/hello/itemservice/web/basic/BasicItemController.java @@ -2,6 +2,7 @@ import hello.itemservice.domain.item.Item; import hello.itemservice.domain.item.ItemRepository; +import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; @@ -10,11 +11,13 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.annotation.PostConstruct; +import java.io.Serializable; import java.util.List; +import java.util.Map; @Slf4j @Controller -@RequestMapping("/basic/items") +//@RequestMapping("/basic/items") @RequiredArgsConstructor public class BasicItemController { private final ItemRepository itemRepository; @@ -142,4 +145,46 @@ public void init(){ itemRepository.save(new Item("itemA", 10000, 10)); itemRepository.save(new Item("itemB", 20000, 20)); } + +// @ResponseBody +// @PostMapping("/orderpro123") +// public void test(@RequestBody TestDto testDto){ +// System.out.println("testDto = " + testDto); +// List numbers = testDto.getNumbers(); +// for (Long number : numbers) { +// System.out.println("number = " + number); +// } +// } + + @ResponseBody + @GetMapping("/orderpro124") + public void test2(@RequestBody Map> testDto){ + System.out.println("testDto = " + testDto); + List id = testDto.get("id"); + List password = testDto.get("password"); + List strings = testDto.get("email"); + for (String string : strings) { + System.out.println("string = " + string); + } +// List numbers = testDto.getNumbers(); +// for (Object o : numbers) { +// System.out.println("o = " + o); +// } + } + + @ResponseBody + @GetMapping("/orderpro125") + public void test2(@RequestParam TestDto testDto){ + System.out.println("testDto = " + testDto); + } + + @Data + static class TestDto implements Serializable { + String numbers; + } + + @Data + static class TestDto2{ + String abc; + } } diff --git a/4.spring-MVC2/exception/src/main/java/hello/exception/WebServerCustomizer.java b/4.spring-MVC2/exception/src/main/java/hello/exception/WebServerCustomizer.java index 76328a5..61b37cb 100644 --- a/4.spring-MVC2/exception/src/main/java/hello/exception/WebServerCustomizer.java +++ b/4.spring-MVC2/exception/src/main/java/hello/exception/WebServerCustomizer.java @@ -6,6 +6,10 @@ import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; +/** + * WebServerFactoryCustomizer를 사용하게 되면 Spring의 기본 옵션인 BasciErrorController에서 처리하는 옵션대로 진행이 안된다. + * 에러 경로를 커스터 마이징하고 싶을때 사용하자 + */ //@Component //errorPage를 등록하는 과정 public class WebServerCustomizer implements WebServerFactoryCustomizer { diff --git a/4.spring-MVC2/exception/src/main/java/hello/exception/exhandler/advice/ExControllerAdvice.java b/4.spring-MVC2/exception/src/main/java/hello/exception/exhandler/advice/ExControllerAdvice.java index 25998a4..d9d1e3e 100644 --- a/4.spring-MVC2/exception/src/main/java/hello/exception/exhandler/advice/ExControllerAdvice.java +++ b/4.spring-MVC2/exception/src/main/java/hello/exception/exhandler/advice/ExControllerAdvice.java @@ -15,6 +15,8 @@ @RestControllerAdvice public class ExControllerAdvice { //IllegalArgumentException 발생시 예외 처리 + //중요. 정상 흐름이 반환되기 때문에 이런 방식으로 응답할거면 응답 코드가 정상 200이 반환됨, 응답 코드도 400을 요청하고 싶으면 @ResponseStatus를 설정해야함 + //200이 반환되는 이뉴는 ModelAndView로 객체를 반환하기때문에 정상 프로세스로 종료되기 때문이다. @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(IllegalArgumentException.class) public ErrorResult illegalExHandle(IllegalArgumentException e){ @@ -27,6 +29,8 @@ public ErrorResult illegalExHandle(IllegalArgumentException e){ //위와 다르게 동적으로 응답메시지를 바꿔서 반환이 가능함. 조건문 사용이 가능하기 때문에 //ExceptionHandler의 ()매개변수는 메소드의 매개변수로 생략이 가능함. 위의 illegalExhandle 메소드랑 비교해서 보면된다. @ExceptionHandler + //위와 아래는 같다. 매개변수의 자료형이 기본값으로 설정되어 있다. +// @ExceptionHandler(UserException.class) public ResponseEntity userExHandle(UserException e){ log.error("[exceptionHandle] ex", e); ErrorResult errorResult = new ErrorResult("USER-EX", e.getMessage()); diff --git a/4.spring-MVC2/exception/src/main/resources/application.properties b/4.spring-MVC2/exception/src/main/resources/application.properties index f1f9424..ec14736 100644 --- a/4.spring-MVC2/exception/src/main/resources/application.properties +++ b/4.spring-MVC2/exception/src/main/resources/application.properties @@ -1,5 +1,5 @@ server.error.whitelabel.enabled=false server.error.include-exception=true -server.error.include-message=always +#server.error.include-message=always #server.error.include-stacktrace=always #server.error.include-binding-errors=always \ No newline at end of file diff --git a/4.spring-MVC2/login/src/main/java/hello/login/WebConfig.java b/4.spring-MVC2/login/src/main/java/hello/login/WebConfig.java index 32d4c2b..79be979 100644 --- a/4.spring-MVC2/login/src/main/java/hello/login/WebConfig.java +++ b/4.spring-MVC2/login/src/main/java/hello/login/WebConfig.java @@ -2,6 +2,8 @@ import hello.login.web.argumentresolver.LoginMemberArgumentResolver; import hello.login.web.filter.LogFilter; +import hello.login.web.filter.LogFilter1; +import hello.login.web.filter.LogFilter2; import hello.login.web.filter.LoginCheckFilter; import hello.login.web.interceptor.LogInterceptor; import hello.login.web.interceptor.LoginCheckInterceptor; @@ -13,6 +15,7 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.FilterRegistration; import java.util.List; @@ -25,32 +28,55 @@ public void addArgumentResolvers(List resolvers) resolvers.add(new LoginMemberArgumentResolver()); } - @Override - public void addInterceptors(InterceptorRegistry registry){ - //더할인터셉터, 순서, 응답패턴, 제외패턴순 - registry.addInterceptor(new LogInterceptor()) - .order(1) - .addPathPatterns("/**") - .excludePathPatterns("/css/**", "/*.ico", "/error"); - - registry.addInterceptor(new LoginCheckInterceptor()) - .order(2) - .addPathPatterns("/**") - .excludePathPatterns("/", "/members/add", "/login", "/logout", - "/css/**", "/*.ico", "/error"); - } +// @Override +// public void addInterceptors(InterceptorRegistry registry){ +// //더할인터셉터, 순서, 응답패턴, 제외패턴순 +// registry.addInterceptor(new LogInterceptor()) +// .order(1) +// .addPathPatterns("/**") +// .excludePathPatterns("/css/**", "/*.ico", "/error"); +// +// registry.addInterceptor(new LoginCheckInterceptor()) +// .order(2) +// .addPathPatterns("/**") +// .excludePathPatterns("/", "/members/add", "/login", "/logout", +// "/css/**", "/*.ico", "/error"); +// } - // @Bean - public FilterRegistrationBean logFilter(){ + @Bean + public FilterRegistrationBean logFilter0(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new LogFilter()); filterRegistrationBean.setOrder(1); +// filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST); + //모든 URL에서 작동하게 설정 + filterRegistrationBean.addUrlPatterns("/*"); + return filterRegistrationBean; + } + + @Bean + public FilterRegistrationBean logFilter1(){ + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); + filterRegistrationBean.setFilter(new LogFilter1()); + filterRegistrationBean.setOrder(2); +// filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR); + //모든 URL에서 작동하게 설정 + filterRegistrationBean.addUrlPatterns("/*"); + return filterRegistrationBean; + } + + @Bean + public FilterRegistrationBean logFilter2(){ + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); + filterRegistrationBean.setFilter(new LogFilter2()); + filterRegistrationBean.setOrder(3); +// filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR); //모든 URL에서 작동하게 설정 filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } - //@Bean + // @Bean public FilterRegistrationBean loginCheckFilter(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new LoginCheckFilter()); diff --git a/4.spring-MVC2/login/src/main/java/hello/login/web/argumentresolver/LoginMemberArgumentResolver.java b/4.spring-MVC2/login/src/main/java/hello/login/web/argumentresolver/LoginMemberArgumentResolver.java index 8c1f8b5..b4a66ca 100644 --- a/4.spring-MVC2/login/src/main/java/hello/login/web/argumentresolver/LoginMemberArgumentResolver.java +++ b/4.spring-MVC2/login/src/main/java/hello/login/web/argumentresolver/LoginMemberArgumentResolver.java @@ -16,7 +16,6 @@ public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { //내부에 캐쉬가 있어서 최초 1회만 실행된다. - @Override public boolean supportsParameter(MethodParameter parameter) { log.info("supportsParameter 실행"); //Login 어노테이션이 붙어 있는지 확인 diff --git a/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter.java b/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter.java index 2ce4c34..b528eac 100644 --- a/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter.java +++ b/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter.java @@ -17,7 +17,7 @@ public void init(FilterConfig filterConfig) throws ServletException { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - log.info("log filter doFilter"); + log.info("log filter doFilter-0"); //ServletRequest는 HttpServletRequest의 부모인데 ServletRequest의 기능은 너무 적기 때문에 HttpServletRequest로 캐스팅 해줘야한다. HttpServletRequest httpRequest = (HttpServletRequest) request; String requestURI = httpRequest.getRequestURI(); @@ -26,18 +26,20 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha String uuid = UUID.randomUUID().toString(); try{ - log.info("REQUEST [{}][{}]", uuid, requestURI); + log.info("REQUEST-0 [{}][{}]", uuid, requestURI); //chain은 filter과정이 더 남아있으면 더 남은 과정으로 이동하고 아닐경우 servlet과정을 진행한다. 현재 스프링을 사용하므로 정확히는 DispatchServlet으로 넘어가서 mapping과정을 진행한다. chain.doFilter(request, response); }catch (Exception e){ throw e; - }finally { - log.info("RESPONSE [{}][{}]", uuid, requestURI); } + finally { + log.info("RESPONSE-0 [{}][{}]", uuid, requestURI); + } + log.info("Survie Response-0! [{}][{}]", uuid, requestURI); } @Override public void destroy() { - System.out.println("log filter destroy"); + System.out.println("log filter destroy-0"); } } diff --git a/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter1.java b/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter1.java new file mode 100644 index 0000000..aa6f005 --- /dev/null +++ b/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter1.java @@ -0,0 +1,45 @@ +package hello.login.web.filter; + +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.UUID; + +@Slf4j +public class LogFilter1 implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + log.info("log filter init-1"); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + log.info("log filter doFilter1"); + //ServletRequest는 HttpServletRequest의 부모인데 ServletRequest의 기능은 너무 적기 때문에 HttpServletRequest로 캐스팅 해줘야한다. + HttpServletRequest httpRequest = (HttpServletRequest) request; + String requestURI = httpRequest.getRequestURI(); + + + String uuid = UUID.randomUUID().toString(); + + try{ + log.info("REQUEST-1[{}][{}]", uuid, requestURI); + //chain은 filter과정이 더 남아있으면 더 남은 과정으로 이동하고 아닐경우 servlet과정을 진행한다. 현재 스프링을 사용하므로 정확히는 DispatchServlet으로 넘어가서 mapping과정을 진행한다. + chain.doFilter(request, response); + }catch (Exception e){ + throw e; + } + finally { + log.info("RESPONSE1 [{}][{}]", uuid, requestURI); + } + log.info("Survie Response-1! [{}][{}]", uuid, requestURI); + } + + @Override + public void destroy() { + System.out.println("log filter destroy-1"); + } +} diff --git a/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter2.java b/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter2.java new file mode 100644 index 0000000..5110a94 --- /dev/null +++ b/4.spring-MVC2/login/src/main/java/hello/login/web/filter/LogFilter2.java @@ -0,0 +1,45 @@ +package hello.login.web.filter; + +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.UUID; + +@Slf4j +public class LogFilter2 implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + log.info("log filter init-2"); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + log.info("log filter doFilter2"); + //ServletRequest는 HttpServletRequest의 부모인데 ServletRequest의 기능은 너무 적기 때문에 HttpServletRequest로 캐스팅 해줘야한다. + HttpServletRequest httpRequest = (HttpServletRequest) request; + String requestURI = httpRequest.getRequestURI(); + + + String uuid = UUID.randomUUID().toString(); + + try{ + log.info("REQUEST-2[{}][{}]", uuid, requestURI); + //chain은 filter과정이 더 남아있으면 더 남은 과정으로 이동하고 아닐경우 servlet과정을 진행한다. 현재 스프링을 사용하므로 정확히는 DispatchServlet으로 넘어가서 mapping과정을 진행한다. + chain.doFilter(request, response); + }catch (Exception e){ + throw e; + } + finally { + log.info("RESPONSE2 [{}][{}]", uuid, requestURI); + } + log.info("Survie Response-2! [{}][{}]", uuid, requestURI); + } + + @Override + public void destroy() { + System.out.println("log filter destroy-2"); + } +} diff --git a/4.spring-MVC2/login/src/main/java/hello/login/web/filter/TestController.java b/4.spring-MVC2/login/src/main/java/hello/login/web/filter/TestController.java new file mode 100644 index 0000000..35058d2 --- /dev/null +++ b/4.spring-MVC2/login/src/main/java/hello/login/web/filter/TestController.java @@ -0,0 +1,21 @@ +package hello.login.web.filter; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@RestController +public class TestController { + @GetMapping("/testFilteSignal/{code}") + public String testSignal(@PathVariable("code") String code){ + log.info("controller Section"); + + if(code.equals("response")){ + throw new RuntimeException("예외 호출"); + } + return "OK"; + } +} diff --git a/4.spring-MVC2/message/src/main/java/hello/itemservice/ItemServiceApplication.java b/4.spring-MVC2/message/src/main/java/hello/itemservice/ItemServiceApplication.java index 1311934..d4bc6da 100644 --- a/4.spring-MVC2/message/src/main/java/hello/itemservice/ItemServiceApplication.java +++ b/4.spring-MVC2/message/src/main/java/hello/itemservice/ItemServiceApplication.java @@ -2,6 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.support.ResourceBundleMessageSource; @SpringBootApplication public class ItemServiceApplication { @@ -9,5 +12,15 @@ public class ItemServiceApplication { public static void main(String[] args) { SpringApplication.run(ItemServiceApplication.class, args); } - +/** + * 스프링이 MessageSource를 자동 등록해준다. + */ +// @Bean +// public MessageSource messageSource() { +// ResourceBundleMessageSource messageSource = new +// ResourceBundleMessageSource(); +// messageSource.setBasenames("messages", "errors"); +// messageSource.setDefaultEncoding("utf-8"); +// return messageSource; +// } } diff --git a/4.spring-MVC2/validation/src/main/resources/errors.properties b/4.spring-MVC2/validation/src/main/resources/errors.properties index fc87498..ccfe738 100644 --- a/4.spring-MVC2/validation/src/main/resources/errors.properties +++ b/4.spring-MVC2/validation/src/main/resources/errors.properties @@ -1,43 +1,43 @@ -#required.item.itemName=상품 이름은 필수입니다. -#range.item.price=가격은 {0} ~ {1} 까지 허용합니다. -#max.item.quantity=수량은 최대 {0} 까지 허용합니다. -#totalPriceMin=가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1} +#required.item.itemName=?? ??? ?????. +#range.item.price=??? {0} ~ {1} ?? ?????. +#max.item.quantity=??? ?? {0} ?? ?????. +#totalPriceMin=?? * ??? ?? {0}? ????? ???. ?? ? = {1} #==ObjectError== #Level1 -totalPriceMin.item=상품의 가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1} +totalPriceMin.item=??? ?? * ??? ?? {0}? ????? ???. ?? ? = {1} -#Level2 - 생략 -totalPriceMin=전체 가격은 {0}원 이상이어야 합니다. 현재 값 = {1} +#Level2 - ?? +totalPriceMin=?? ??? {0}? ????? ???. ?? ? = {1} #==FieldError== #Level1 -required.item.itemName=상품 이름은 필수입니다. -range.item.price=가격은 {0} ~ {1} 까지 허용합니다. -max.item.quantity=수량은 최대 {0} 까지 허용합니다. +required.item.itemName=?? ??? ?????. +range.item.price=??? {0} ~ {1} ?? ?????. +max.item.quantity=??? ?? {0} ?? ?????. -#Level2 - 생략 +#Level2 - ?? #Level3 -required.java.lang.String = 필수 문자입니다. -required.java.lang.Integer = 필수 숫자입니다. -min.java.lang.String = {0} 이상의 문자를 입력해주세요. -min.java.lang.Integer = {0} 이상의 숫자를 입력해주세요. -range.java.lang.String = {0} ~ {1} 까지의 문자를 입력해주세요. -range.java.lang.Integer = {0} ~ {1} 까지의 숫자를 입력해주세요. -max.java.lang.String = {0} 까지의 숫자를 허용합니다. -max.java.lang.Integer = {0} 까지의 숫자를 허용합니다. +required.java.lang.String = ?? ?????. +required.java.lang.Integer = ?? ?????. +min.java.lang.String = {0} ??? ??? ??????. +min.java.lang.Integer = {0} ??? ??? ??????. +range.java.lang.String = {0} ~ {1} ??? ??? ??????. +range.java.lang.Integer = {0} ~ {1} ??? ??? ??????. +max.java.lang.String = {0} ??? ??? ?????. +max.java.lang.Integer = {0} ??? ??? ?????. #Level4 -required = 필수 값 입니다. -min= {0} 이상이어야 합니다. -range= {0} ~ {1} 범위를 허용합니다. max= {0} 까지 허용합니다. -max= {0} 까지 허용합니다. +required = ?? ? ???. +min= {0} ????? ???. +range= {0} ~ {1} ??? ?????. max= {0} ?? ?????. +max= {0} ?? ?????. -typeMismatch.java.lang.Integer=숫자를 입력해주세요. -typeMismatch=타입 오류입니다. +typeMismatch.java.lang.Integer=??? ??????. +typeMismatch=?? ?????. -#Bean Validation 추가 -NotBlank.item.itemName=상품 이름을 적어주세요. -NotBlank={0} 공백X -Range={0}, {2} ~ {1} 허용 -Max={0}, 최대 {1} \ No newline at end of file +#Bean Validation ?? +NotBlank.item.itemName=?? ??? ?????. +NotBlank={0} ??X +Range={0}, {2} ~ {1} ?? +Max={0}, ?? {1} \ No newline at end of file diff --git a/7.spring-DB DataAccess Application Skill/1.itemservice-db/src/main/java/hello/itemservice/testcontrolelr.java b/7.spring-DB DataAccess Application Skill/1.itemservice-db/src/main/java/hello/itemservice/testcontrolelr.java new file mode 100644 index 0000000..6e9dc76 --- /dev/null +++ b/7.spring-DB DataAccess Application Skill/1.itemservice-db/src/main/java/hello/itemservice/testcontrolelr.java @@ -0,0 +1,22 @@ +package hello.itemservice; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +@Controller +public class testcontrolelr { + @PostMapping("/testPage") + public void hello(String test){ + System.out.println("test = " + test); + } + + @GetMapping ("/testPage2") + public void hello2(String test){ + System.out.println("test = " + test); + } + + static class testDto{ + String test; + } +} diff --git a/7.spring-DB DataAccess Application Skill/1.itemservice-db/src/main/resources/application.properties b/7.spring-DB DataAccess Application Skill/1.itemservice-db/src/main/resources/application.properties index 3a171c3..4e71b2a 100644 --- a/7.spring-DB DataAccess Application Skill/1.itemservice-db/src/main/resources/application.properties +++ b/7.spring-DB DataAccess Application Skill/1.itemservice-db/src/main/resources/application.properties @@ -7,4 +7,7 @@ spring.datasource.password= logging.level.org.springframework.jdbc=debug logging.level.org.hibernate.SQL=DEBUG -logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE \ No newline at end of file +logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE + + + diff --git a/practice/communicationProject/src/main/java/connected/communication/InitDB.java b/practice/communicationProject/src/main/java/connected/communication/InitDB.java index 8d70846..3a594d6 100644 --- a/practice/communicationProject/src/main/java/connected/communication/InitDB.java +++ b/practice/communicationProject/src/main/java/connected/communication/InitDB.java @@ -42,7 +42,8 @@ public class InitDB { public void initDB(){ log.info("initialize database"); initRole(); - + initTestAdmin(); + initTestMember(); } private void initRole(){ diff --git a/practice/communicationProject/src/main/java/connected/communication/controller/MemberController.java b/practice/communicationProject/src/main/java/connected/communication/controller/MemberController.java index 9b2316a..d142357 100644 --- a/practice/communicationProject/src/main/java/connected/communication/controller/MemberController.java +++ b/practice/communicationProject/src/main/java/connected/communication/controller/MemberController.java @@ -7,21 +7,42 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; +//@RestController +//@RequiredArgsConstructor +//@Slf4j +//public class MemberController { +// private final MemberService memberService; +// +// @GetMapping("/api/members/{id}") +// @ResponseStatus(HttpStatus.OK) +// public Response read(@PathVariable Long id){ +// return Response.success(memberService.read(id)); +// } +// +// @DeleteMapping("/api/members/{id}") +// @ResponseStatus(HttpStatus.OK) +// public Response delete(@PathVariable Long id){ +// memberService.delete(id); +// return Response.success(); +// } +//} + @RestController @RequiredArgsConstructor @Slf4j public class MemberController { + private final MemberService memberService; @GetMapping("/api/members/{id}") @ResponseStatus(HttpStatus.OK) - public Response read(@PathVariable Long id){ + public Response read(@PathVariable Long id) { return Response.success(memberService.read(id)); } @DeleteMapping("/api/members/{id}") @ResponseStatus(HttpStatus.OK) - public Response delete(@PathVariable Long id){ + public Response delete(@PathVariable Long id) { memberService.delete(id); return Response.success(); } diff --git a/practice/communicationProject/src/main/java/connected/communication/dto/sign/RefreshTokenResponse.java b/practice/communicationProject/src/main/java/connected/communication/dto/sign/RefreshTokenResponse.java new file mode 100644 index 0000000..1a18f5e --- /dev/null +++ b/practice/communicationProject/src/main/java/connected/communication/dto/sign/RefreshTokenResponse.java @@ -0,0 +1,10 @@ +package connected.communication.dto.sign; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class RefreshTokenResponse { + private String accessToken; +} diff --git a/practice/communicationProject/src/main/java/connected/communication/exception/AccessDeniedException.java b/practice/communicationProject/src/main/java/connected/communication/exception/AccessDeniedException.java index a7b1569..18b1392 100644 --- a/practice/communicationProject/src/main/java/connected/communication/exception/AccessDeniedException.java +++ b/practice/communicationProject/src/main/java/connected/communication/exception/AccessDeniedException.java @@ -1,4 +1,6 @@ package connected.communication.exception; +import org.springframework.beans.factory.annotation.Autowired; + public class AccessDeniedException extends RuntimeException { } diff --git a/practice/communicationProject/src/test/java/connected/communication/advice/ExceptionControllerAdviceTest.java b/practice/communicationProject/src/test/java/connected/communication/advice/ExceptionControllerAdviceTest.java index 0873ee7..8811020 100644 --- a/practice/communicationProject/src/test/java/connected/communication/advice/ExceptionControllerAdviceTest.java +++ b/practice/communicationProject/src/test/java/connected/communication/advice/ExceptionControllerAdviceTest.java @@ -18,25 +18,54 @@ class ExceptionControllerAdviceTest { @InjectMocks ExceptionController exceptionController; MockMvc mockMvc; - + @BeforeEach - void beforeEach(){ + void beforeEach() { mockMvc = MockMvcBuilders.standaloneSetup(exceptionController).setControllerAdvice(new ExceptionAdvice()).build(); } @Test - public void entryPointTes1t() throws Exception{ - //given//when//then - mockMvc.perform(get("/exception/entry-point")) + void entryPointTest() throws Exception{ + // given, when, then + mockMvc.perform( + get("/exception/entry-point")) .andExpect(status().isUnauthorized()) .andExpect(jsonPath("$.code").value(-1001)); } @Test - public void accessDeniedTest() throws Exception{ - //given//when//then - mockMvc.perform(get("/exception/access-denied")) + void accessDeniedTest() throws Exception { + // given, when, then + mockMvc.perform( + get("/exception/access-denied")) .andExpect(status().isForbidden()) .andExpect(jsonPath("$.code").value(-1002)); } -} \ No newline at end of file + +} +//@ExtendWith(MockitoExtension.class) +//class ExceptionControllerAdviceTest { +// @InjectMocks ExceptionController exceptionController; +// MockMvc mockMvc; +// +// @BeforeEach +// void beforeEach(){ +// mockMvc = MockMvcBuilders.standaloneSetup(exceptionController).setControllerAdvice(new ExceptionAdvice()).build(); +// } +// +// @Test +// public void entryPointTes1t() throws Exception{ +// //given//when//then +// mockMvc.perform(get("/exception/entry-point")) +// .andExpect(status().isUnauthorized()) +// .andExpect(jsonPath("$.code").value(-1001)); +// } +// +// @Test +// public void accessDeniedTest() throws Exception{ +// //given//when//then +// mockMvc.perform(get("/exception/access-denied")) +// .andExpect(status().isForbidden()) +// .andExpect(jsonPath("$.code").value(-1002)); +// } +//} \ No newline at end of file diff --git a/practice/communicationProject/src/test/java/connected/communication/controller/member/MemberControllerIntegrationTest.java b/practice/communicationProject/src/test/java/connected/communication/controller/member/MemberControllerIntegrationTest.java new file mode 100644 index 0000000..e838530 --- /dev/null +++ b/practice/communicationProject/src/test/java/connected/communication/controller/member/MemberControllerIntegrationTest.java @@ -0,0 +1,128 @@ +package connected.communication.controller.member; + +import connected.communication.dto.sign.SignInRequest; +import connected.communication.dto.sign.SignInResponse; +import connected.communication.entity.member.Member; +import connected.communication.exception.MemberNotFoundException; +import connected.communication.init.TestInitDB; +import connected.communication.repository.member.MemberRepository; +import connected.communication.service.SignService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.context.WebApplicationContext; + +import static connected.communication.factory.dto.SignInRequestFactory.createSignInRequest; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +//현재 Spring에 의존적인 테스트이기 때문에 SpringSecurity를 추가해준다. +@SpringBootTest +/** + * 스프링의 기본 웹 관련 설정은 WebEnviroment.MOCK이다 + * 그러나 자동으로 스프링 Bean에 추가하지 않기 때문에 @AutoConfigureMockMvc를 추가해줘야한다. + * 내장 톰켓을 실제로 띄우고 싶다면 WebEnviroment 설정을 RAMDOM_PORT로 설정하자 + */ +@AutoConfigureMockMvc +@ActiveProfiles(value = "test") +@Transactional +public class MemberControllerIntegrationTest { + @Autowired + WebApplicationContext context; + @Autowired + MockMvc mockMvc; + @Autowired + TestInitDB initDB; + @Autowired + SignService signService; + @Autowired + MemberRepository memberRepository; + + @BeforeEach + void beforeEach(){ + mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build(); + initDB.initDB(); + } + + @Test + void readTest() throws Exception { + // given + Member member = memberRepository.findByEmail(initDB.getMember1Email()).orElseThrow(MemberNotFoundException::new); + + // when, then + mockMvc.perform( + get("/api/members/{id}", member.getId())) + .andExpect(status().isOk()); + } + + @Test + void deleteTest() throws Exception { + // given + Member member = memberRepository.findByEmail(initDB.getMember1Email()).orElseThrow(MemberNotFoundException::new); + SignInResponse signInRes = signService.signIn(new SignInRequest(initDB.getMember1Email(), initDB.getPassword())); + + // when, then + mockMvc.perform( + delete("/api/members/{id}", member.getId()).header("Authorization", signInRes.getAccessToken())) + .andExpect(status().isOk()); + } + + @Test + void deleteByAdminTest() throws Exception { + // given + Member member = memberRepository.findByEmail(initDB.getMember1Email()).orElseThrow(MemberNotFoundException::new); + SignInResponse adminSignInRes = signService.signIn(new SignInRequest(initDB.getAdminEmail(), initDB.getPassword())); + + // when, then + mockMvc.perform( + delete("/api/members/{id}", member.getId()).header("Authorization", adminSignInRes.getAccessToken())) + .andExpect(status().isOk()); + } + + @Test + void deleteUnauthorizedByNoneTokenTest() throws Exception { + // given + Member member = memberRepository.findByEmail(initDB.getMember1Email()).orElseThrow(MemberNotFoundException::new); + + // when, then + mockMvc.perform( + delete("/api/members/{id}", member.getId())) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("/exception/entry-point")); + } + + @Test + void deleteAccessDeniedByNotResourceOwnerTest() throws Exception { + // given + Member member = memberRepository.findByEmail(initDB.getMember1Email()).orElseThrow(MemberNotFoundException::new); + SignInResponse attackerSignInRes = signService.signIn(new SignInRequest(initDB.getMember2Email(), initDB.getPassword())); + + // when, then + mockMvc.perform( + delete("/api/members/{id}", member.getId()).header("Authorization", attackerSignInRes.getAccessToken())) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("/exception/access-denied")); + } + + @Test + void deleteAccessDeniedByRefreshTokenTest() throws Exception { + // given + Member member = memberRepository.findByEmail(initDB.getMember1Email()).orElseThrow(MemberNotFoundException::new); + SignInResponse signInRes = signService.signIn(createSignInRequest(initDB.getMember1Email(), initDB.getPassword())); + // when, then + mockMvc.perform( + delete("/api/members/{id}", member.getId()).header("Authorization", signInRes.getRefreshToken())) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("/exception/entry-point")); + } + +}
    id