package cafe.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc // Spring MVC 활성화
@ComponentScan("cafe.web") // 컴포넌트 스캐닝 활성화
public class WebConfig extends WebMvcConfigurerAdapter {
// 뷰 리졸버 생성
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
// 기본 뷰 리졸버 = JSP를 뷰로 사용할 때 사용
resolver.setPrefix("/WEB-INF/views/"); // 프리픽스 지정
resolver.setSuffix(".jsp"); // 서픽스 지정
resolver.setExposeContextBeansAsAttributes(true); // 스프링 빈을, ApplicationContext에서 접근 가능하게 설정 ${..} 플레이스 홀더 사용 가능
return resolver;
}
@Override
// 정적 콘텐츠 처리 설정
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable(); // 고정적인 리소스에 대한 요청을 직접 처리하지 않고, 서블릿 컨테이너의 디폴트 서블릿 전달 요청
}
}
* WebConfig : 컴포넌트 스캔을 통해, 컨트롤러를 가져올 수 있다, 이로인해 내부에 컨트롤러를 선언할 필요가 없음,
// 컴포넌트 스캐닝을 하는 기본 RootConfig
@Configuration
@ComponentScan(basePackages = {"spittr"},
excludeFilters = {
@ComponentScan.Filter(type= FilterType.ANNOTATION, value = EnableWebMvc.class)
})
public class RootConfig {
}
* RootConfig : 해당 클래스는 컴포넌트 스캐닝을 한다는 점 이외에는, 다음에 다뤄보기로 함.
간단한 컨트롤러 작성하기
@RequestMapping : 컨트롤러가 처리할, 요청의 종류를 정의하는 애너테이션 ( value로 요청 패스를, method로 요청 메소드를..)
@Controller // @Component에 기반을 둔, 정형화된 애너테이션, 컴포넌트 스캔 가능
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
// 요청패스 "/"에 관하여, Http Get 요청을 함
public String home() {
return "home"; // 뷰의 이름이 home
// view는, webConfig에서 /WEB-INF/views 프리픽스, .jsp 서픽스를 지정했으므로, /WEB-INF/views/home.jsp 가 해당 뷰
}
}
==> 혹은 이렇게 클래스 레벨 요청으로 처리 가능
@Controller
@RequestMapping({"/", "/hompage"}) // "/"와 "/hompage"에 관하여 클레스 레벨로 처리
public class HomeController {
@RequestMapping(method = RequestMethod.GET)
public String home() {
return "home"; // 뷰의 이름이 home
}
}
일반적인, POJO 테스트로는, 리턴되는 home이 뷰에관한 리턴이 아닌, 단순히 String인 "home"이 리턴된다.
따라서, MVC를 위한 컨트롤러 테스팅이 필요함
public class HomeControllerTest {
@Test
public void testHomePage() throws Exception{
HomeController controller = new HomeController();
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
// mockMvc 관련 셋업...
mockMvc.perform(get("/")).andExpect(view().name("home"));
// "/"요청에 관한 get을 수행하는 뷰의 이름이, "home"인지 체크
}
}
뷰에 모델 데이터 전달하기
* 데이터에 엑세스를 위한 저장소를 정의해주어야 함. 실제 구현은 나중에
public interface CoffeeRepository {
List<Coffee> findCoffees(int min, int max);
}
-> 커피를 찾기 위한, 저장소 인터페이스( 최소가격, 최대가격)
public class Coffee {
private final String name;
private final int price;
...
생성자, getter 생략
}
==> Coffee 클래스, 커피의 id번호, 이름, 샷, 물, 우유의 양 저장
Coffee 데이터를 처리할 수 있는 컨트롤러 작성
@Controller
@RequestMapping("/coffees")
public class CoffeeController {
private CoffeeRepository coffeeRepository;
@Autowired // coffeeReposi
public CoffeeController(CoffeeRepository coffeeRepository){
this.coffeeRepository = coffeeRepository;
}
@RequestMapping(method = RequestMethod.GET)
public String coffees(Model model){
model.addAllAttributes(
coffeeRespository.findCoffees(1000, 5000)
);
// 해당 List<Coffee>를 모델에 추가함
return "coffees";
// 뷰 : /WEB-INF/views/coffees.jsp
}
}
==> Model에 직접, 뷰로 전달할 데이터를 넣어줄 수 있다 - 위 코드에선, 1000~5000원 사이의 커피 목록
==> 모델로 받은 데이터 coffeeList를 간단하게 사용하는 jsp파일 // coffeeList를 그대로 사용 가능(플레이스 홀더)
요청입력받기
스프링 MVC는 클라이언트가 데이터를 전달해줄 몇 가지 방법을 제공함
* 쿼리파라미터, 폼 파라미터, 패스 변수
쿼리파라미터 입력받기
* 이전 글에서 사용한 방식은, 코드 내에 1000이나 5000이 직접 적혀있었고, 클라이언트는 이를 바꾸지 못하는 구조였다. 만약 4천원~ 5천원 사이인 커피의 목록을 알고싶은 사용자는 어떻게 해야할까? => 클라이언트의 GET 요청에서, min과 max의 파라미터값을 받으면 됨
@RequestMapping(method = RequestMethod.GET)
public List<Coffee> coffees( @RequestParam(value="min", defaultValue = "1000") int min
, @RequestParam(value="max", defaultValue = "5000") int max
){
return coffeeRepository.findCoffees(min, max);
}
=> @RequestParam 애너테이션을 통해, value 값, 기본값을 지정할 수 있다. 아무것도 입력하지 않으면 1000~5000원 사이의 커피
=> 가장 일반적인 방식 => [url]/coffees?min=4000&max=5000 ==> 4~5천원 커피 찾기