[오류 내용]

HelloControll가 필요한 bean인 HelloService가 2개 존재할 경우(여러 빈이 조회되었을시 ) 발생하는 오류

 

 

[해결방안]

현대 helloDecorator과 simplerHelloService에 총 2개가 존재하는데 이때 어디꺼를 쓸것인지 우선 순위를 정해줘야함

@Primary우선순위 부여하여 해결

@Service
@Primary    //HelloController가 필요한 bean이 2개 존재할때 얘를 우선적으로 가져다가 쓰겠다는 의미
public class HelloDecorator implements HelloService{

@Primary : 우선적으로 가져다가 쓰겠다는 의미

'SpringBoot > 프로젝트' 카테고리의 다른 글

자동 구성 정보 대체하기  (0) 2023.11.30
@Conditional 학습 테스트  (0) 2023.11.30
[Spring Boot] jetty 서버 구성 추가하기  (0) 2023.11.29
Test Code 작성  (0) 2023.11.27
섹션2. 스프링 부트 시작하기  (0) 2023.11.21

[오류내용]

프로젝트를 수행 중 test run해보니 아래와 같은 오류 발생

Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

 

[오류해결]

@SpringBootTest(classes = HellobootApplication.class)

test 파일에 해당 java 파일 아래 해당 파일 경로 추가 해주면 오류 해결됨

스탠드언론 프로젝트 : 서블릿 컨테이너 자동으로 띄워줌

 

2. 빈 서블릿 컨테이너 띄우기

 

- 스프링부트 사용하지 않고 톰캣 띄우기

- 톰캣은 대표적인 서블릿

 

  • Tomcat Sublet Web Sever Factory

스프링 부트가 Tomcat Sublet 컨테이너를 내장해서 프로그램 코드로 쉽게 사용할 수 있게 만들어주는 도우미 클래스

 

TomcatServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
WebServer webServer = serverFactory.getWebServer();
  • .getWebServer();    진짜 웹 서버 우리 Sublet 컨테이너를 만드는 생성 함수
  • 톰캣 말고 다른걸 사용하고 싶을 경우 TomcatServletWebServerFactory 앞에 Tomcat 부분을 Jetty 등 사용하고 싶은걸로 적으면 동일하게 사용 가능
webServer.start();
  • Tomcat Sublet Container 동작

- 톰캣이 잘 떴는지 확인하는 방법

localhost 8080 시 404 뜸

 

 

3. 서블릿 등록

 

 

 

  • Mapping

Sublet 컨테이너가 웹 클라이언트로부터 요청을 받으면 여러개의 Sublet 중 어떤 Sublet에게 맡기면 될지 결정하는 작업

 

- 서블릿 등록

servletContext.addServlet("hello", new HttpServlet() {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ... }).addMapping("/*");
  • .addServlet                     - 서블릿 등록
  • .addMapping("/ 경로")    - 서블릿 만든 후 해당 경로로 들어올 경우 해당 서블리소가 맵핑해줘야함

 

- 웹 응답 3가지 필요

 

1)상태라인에서 상태 코드

resp.setStatus(200);

200 이 외 값을 설정하지 않는 다면 생략 가능

스프링에 enum 사용시 더 편리

 

2) 헤더

resp.setHeader("Content-Type","text/plain");

 

3)바디부분

resp.getWriter().println("Hello" + name);

 

 

-  프론트 컨트롤러

서블릿에 공통되는 부분들을 앞에 프론트컨트롤러라고 이름을 붙인 오브젝트에서 공통적인 작업함

 

 

1)프론트 컨트롤러로 변경

       servletContext.addServlet("frontController", new HttpServlet() {
           @Override
           protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
               // 인증, 보안, 다국어, 공통 기능
               // Sublet 컨테이너의 맵핑 기능을 front Controller가 담당
               // 3개 요청 method, path url, header body
               if(req.getRequestURI().equals("/hello") && req.getMethod().equals(HttpMethod.GET.name())){
                   String name = req.getParameter("name");
                   
                   resp.setStatus(HttpStatus.OK.value());
                   resp.setContentType(MediaType.TEXT_PLAIN_VALUE);
                   resp.getWriter().println("hello" + name);
               }
else if(req.getRequestURI().equals("/user")){
    //
}
               else{
                   //404
                   resp.setStatus(HttpStatus.NOT_FOUND.value());
               }


           }
           //frontController로 반을 경우 *으로 모두 받아야함
       }).addMapping("/*");    // 해당 경로로 들어올 경우 해당 서블릿과 맵핑 시킨다

helloController 에서 @GetMapping으로 했으므로 post로 /hello로 요청을 받으면 오류 뜸

 

 

-HelloController 사용해서 프론트 컨트롤러

WebServer webServer = serverFactory.getWebServer(servletContext ->  {
    //프론트 컨트롤러 분리 작업
    HelloController helloController = new HelloController();


    servletContext.addServlet("frontController", new HttpServlet() {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 인증, 보안, 다국어, 공통 기능
            // Sublet 컨테이너의 맵핑 기능을 front Controller가 담당
            // 3개 요청 method, path url, header body
            if(req.getRequestURI().equals("/hello") && req.getMethod().equals(HttpMethod.GET.name())){
                String name = req.getParameter("name");

                //bean 오브젝트 가져오기
                HelloController helloController =  applicationContext.getBean(HelloController.class);

                //프론트 컨트롤러 분리 작업
                //추출된 파라미터를 메소드를 호출하는데서 사용하고
                // ret으로 결과값 리턴
                String ret = helloController.hello(name);

                resp.setStatus(HttpStatus.OK.value());
                resp.setContentType(MediaType.TEXT_PLAIN_VALUE);
                resp.getWriter().println(ret);
            }
            else{
                //404
                resp.setStatus(HttpStatus.NOT_FOUND.value());
            }


        }
        //frontController로 반을 경우 *으로 모두 받아야함
    }).addMapping("/*");    // 해당 경로로 들어올 경우 해당 서블릿과 맵핑 시킨다

 

여기까지 스프링 부트는 사용하지 않음

 

HelloController.java

 

@GetMapping("/xxx")

해당 /xxx 경로로 들어오는 요청을 받아서 return 해줌

 

@RestController

웹 응답이 만들어질 때 이 컨트롤러 메소드의 return type인 저 스트링을 보고

content type 자동으로 결정해줌

스트링이 return 되는 경우 텍스트 슬래시 플레이 이타입의 컨텐츠 타입이 만들어지고

리턴한 저 문자열이 그대로 응답의 바디에 들어감

 

 

Tomcat

자바 서블릿의 컨테이너

 

 

 

 

 

'SpringBoot > 프로젝트' 카테고리의 다른 글

자동 구성 정보 대체하기  (0) 2023.11.30
@Conditional 학습 테스트  (0) 2023.11.30
[Spring Boot] jetty 서버 구성 추가하기  (0) 2023.11.29
Test Code 작성  (0) 2023.11.27
DI를 이용한 Decorator  (2) 2023.11.27

+ Recent posts