(SERVLET) 스프링 MVC 연동
public class HelloController {
@Autowired
HelloService helloService;
@GetMapping("/hello")
public String Hello() {
return "hello, "+helloService.getName();
}
}
위의 코드를 구현하려면 어떻게 해야 하는가?
- 위의 핸들러로 요청을 Dispatch 해줄 수 있어야 하고
- 해당 애노테이션을 읽을 수 있어야 하고
- return 값을 HttpResponse로 만들어 줄 수 있어야 한다.
위의 조건을 만족시키는 방법은 DispatcherServlet을 사용하는 것이다.
계층 구조로 Bean을 생성하기
이전에 만들었던 HelloService는
Root WebApplicationContext에 Bean을 만들어야 하고
(By ContextLoaderListener)
지금 만든 HelloController는
Servlet WebApplicationContext에 Bean을 만들어야 한다.
(DispatcherServlet)
AppConfig 클래스의 ComponentScan 수정 - 자식에 해당하는 Controller 제외
@Configuration
@ComponentScan(excludeFilters = @ComponentScan.Filter(Controller.class))
public class AppConfig {
}
WebConig 클래스의 ComponentScan 수정 - 자식에 해당하는 Controller만 Bean으로 등록할 수 있다.
@Configuration
@ComponentScan(useDefaultFilters = false, includeFilters = @ComponentScan.Filter(Controller.class))
public class WebConfig {
}
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>me.choi.WebConfig</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
여기서 나의 실수 발생 (30분이나 고민하였다)
404 에러가 떨어져서
문제가 무엇이었을까?
@Controller
public class HelloController {
@Autowired
HelloService helloService;
@GetMapping("/hello")
public String hello() {
return "hello, "+helloService.getName();
}
}
문제는 위의 코드에 존재한다.
답은 접은 글로 할 테니 충분히 생각해보고 열어보길 바란다.
@Controller
public class HelloController {
@Autowired
HelloService helloService;
@GetMapping("/hello")
public @ResponseBody String hello() {
return "hello, "+helloService.getName();
}
}
@Controller를 사용하였고 그에 따라 @ResponseBody를 선언하지 않았기 때문이었다.
@ResponseBody 이해하기
메서드에 @ResponseBody로 어노테이션이 되어 있다면 메서드에서 리턴되는 값은 View를 통해서
출력되지 않고 HTTP Response Body에 직접 쓰이게 됩니다.
이때 쓰이기 전에 리턴되는 데이터 타입에 따라 MessageConverter에서 변환이 이뤄진 후 쓰이게 됩니다.
또는 @Controller를 쓰지 않고 @RestController를 사용하면 ViewResolver를 타지 않고 HTTP Response Body로 간다.
(@RestController는 @ResponseBody를 내장하고 있다.)
@RestController
public class HelloController {
@Autowired
HelloService helloService;
@GetMapping("/hello")
public String hello() {
return "hello, "+helloService.getName();
}
}
현재는 스프링 부트와는 많이 다른 상태이다.
서블릿 컨텍스트 안에 스프링이 들어간 구조라면 (tomcat 안에 Spring을 넣은 형태)
스프링 부트는 스프링 부트 Java Application이 먼저 뜨고 그 안에 Tomcat이 내장되있는 형태이다.
즉 구조가 상당히 다르다.
코드 참조
https://github.com/mike6321/Spring/tree/master/SpringMVC/java-servlet-demo