
주요 컨테이너 종류

오늘 다룰 대표적 클래스는 GenericXmlApplicationContext (스포. 안다룸. 왜 안다뤘지)
뒤에 피피티 더 설명해준건 어제 복습이라 생략
AppConfig.java
@Configuration // IocContainer에 bean을 등록하는 클래스
public class AppConfig {
// 메소드를 bean으로 등록하기 위해서 @Bean을 추가
@Bean
public Calculator calc() { // 반환타입 = 클래스, 메소드 이름 == bean 이름
return new Calculator();
}
@Bean
public Person man() {
Person person = new Person();
person.setName("뽀로로");
person.setAge(20);
person.setCalculator(calc());
return person;
}
@Bean
public Person woman() {
return new Person("루피",20,calc());
}
}
비교해보기

반환타입이 클래스가 되고 메소드 이름이 bean의 이름(id)이 됨
1.
<bean class="com.gdu.app.xml01.Calculator" id="calc" scope="singleton"/>
2.
@Bean
public Calculator calc() {
return new Calculator();
}
1번과 2번은 서로 같은 역할하는 코드임
MainWrapper
실행
public static void ex01() {
// AppConfig.java에 등록된 bean 생성하기
AbstractApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
// bean 가져오기
Calculator calc = ctx.getBean("calc",Calculator.class);
// 확인
calc.add(1, 2);
calc.sub(3, 4);
calc.mul(5, 6);
calc.div(7, 8);
// ctx 닫기
ctx.close();
}
AnnotationConfigApplicationContext은 애노테이션으로 만들어놓은 bean 전용으로 생성해줌
실행결과

어제 한 것 중 다른 것도 응용해보기
@Bean
public Person man() {
Person person = new Person();
person.setName("뽀로로");
person.setAge(20);
person.setCalculator(calc());
return person;
}
@Bean
public Person woman() {
return new Person("루피",20,calc());
}
실행결과

@Bean을 사용하는 것의 이점은 무엇일까
xml은 계산이 안됨. 만약 뽀로로 나이를 2023-2020으로 하고 싶어서 그 식을 그대로 value에 대입한다고 해도 빼기 계산 불가능임. 이에 반해 자바로 set해주면 setAge(2023-2020)하면 바로 계산
그래서 추세는 xml -> java에서 @Bean 쓰는 걸로 바뀌는 중
@Bean에 name 속성으로 bean 이름을 등록할 수 있다.
AppConfig.java (anno02)
@Bean(name="user")
public User zxcvbnm() {
User user = new User();
user.setUserNo(1);
user.setUserId("admin");
return user;
}
bean 애노테이션 뒤에 (name="user")로 객체에 들어올 값 연결해줄 수 있음. 그래서 메소드 이름은 zxcvbnm()처럼 ㄹㅇ 아무렇게나 지을 수 있다.
실행 생략 (잘됨)
app-context(xml03 packate)
<bean class="com.gdu.app.xml03.Student" id="student">
<!-- List -->
<property name="subjects">
<list>
<value>국어</value>
<value>영어</value>
<value>수학</value>
</list>
</property>
<!-- Set -->
<property name="contacts">
<set>
<value>010-0000-0000</value>
<value>010-0000-0000</value>
<value>031-9999-9999</value>
</set>
</property>
<!-- Map -->
<property name="friends">
<map>
<entry key="동네친구" value="루피"></entry>
<entry key="학교친구" value="뚜비"></entry>
<entry key="사회친구" value="포비"></entry>
</map>
</property>
</bean>
이 코드를 @Bean 써서 표현해보자
AppConfig.java (anno03)
@Bean
public Student student() {
Student student = new Student();
student.setSubjects(Arrays.asList("국어", "영어", "수학"));
student.setContacts(new HashSet<String>(Arrays.asList("010-0000-0000", "010-9999-9999")));
student.setFriends(Map.of("동네친구", "루피", "학교친구", "뚜비", "사회친구", "포비"));
return student;
}
엄청나게 간단해진다.
실행 생략 (잘됨)
오늘 수업 응용 예시라서 새로운 내용 없는 것 같다. 혼자 공부는 해야겠다.
02_IoC_ex xml02를 @Bean으로 바꾼거다. 새로운 내용 없는 것 같으니까 생략. 혼자 풀어보기

이거 어제 배운 것 중
<bean class="com.gdu.app02.xml02.MyJdbcService" id="service">
<property name="myJdbcDao" ref="dao"/>
</bean>
이 부분이네
갑자기 프로젝트 구조 추가 설명

mvc 구조에서 처음 소개할 아이는 root-context.xml
Spring Bean Configuration File임. <bean>추가하고 싶으면 여기와서 추가하면 된다<!--
<resources> 태그
정적 자원(css, js, image 등)의 경로와 주소를 관리하는 태그
mapping="/resources/**" : 주소(URL)가 /resources로 시작하는 경우
location="/resources/ : /resources/ 디렉터리로 연결하시오!
-->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.gdu.app03" />
1) resources는 webapp 하위에 만들어져있다.
프로젝트 선택 > property > Deployment Assembly에서 path 확인해보면

세번째 src/main/webapp은 contextPath다.
dynamic web project때도 동일한 내용 있었다.
resources도 webapp 하위에 있으므로 resources를 찾아갈 땐 contextPath(/)쓰고 바로 resources를 적으면 되는 거
2) InternalResourceViewResolver prefix, suffix 설정 (6교시에 설명한 내용)
3) component-scan (7교시에 설명한 내용)
component는 쉽게 말하면 bean을 이르는 말
bean 등록하는 법 중 <bean>태그 쓰는 것과 @Configulation,@Bean 애노테이션 쓰는 건 배웠고 한가지 안 배운게 있는데 그게 바로 component
@Configulation는 클래스단에 붙이지지만 @Bean은 클래스 자체를 조종(?)하는건 아니고 @Configulation붙은 클래스 안에서 메소드에 붙여지는 거임
이에 반해 @Component는 클래스단 자체에 붙옂이는 bean
Componen-scan은 이렇게 등록해준 bean을 찾는 역할을 하는 것이다
전에 강사님이 첫 패키지 생성하면 절대 이름은 바꾸지 말라고 했던게 예를 들어 abc 패키지를 생성하고 그 패키지 이름을 abc.controller라는 걸로 바꾸면

component에서 base-package 역시 abc.controller로 변경되어버림. base-package는 abc여야 다른 패키지에서도 통용될 수 있는건데 이렇게 되면 abc.controller에서밖에 못쓰게 됨
1004 1교시 servlet-context.xml에서 resources 폴더 이름 바꾸는거 등 추가배우네
에는 각종 jsp 파일을 넣는다.
server로 실행할 때 welcome파일(index.jsp)은 자동으로 실행되지 않는다. 스프링은 웰컴 파일 리스트(?)가 없어서 시작하면 자동으로 웰컴파일 찾아서 실행하겠다는 개념이 없다.
대신 contextPath("/","/app03")경로에 요청하면 views/index.jsp를 열도록 할 수는 있다. 해보자
com.gdu.app03.controller, MyController01MyController01
/*
* 요청/응답을 처리할 메소드를 만든다.
*
* 1. 반환타입
* 1) String : 응답할 Jsp의 이름을 반환한다.
* 2) void : 컨트롤러가 호출한 서비스에서 직접 응답한다. 요청 주소를 Jsp 이름으로 인식한다.
* 3) 기타 : 비동기 통신에서 데이터를 응답한다.
* 2. 메소드명
* - 아무 일도 안 한다.
* 3. 매개변수
* 1) HttpServletRequest를 선언해서 사용할 수 있다.
* 2) HttpServletResponse를 선언해서 사용할 수 있다.
* 3) Model을 선언해서 forward할 정보를 저장할 수 있다.
* 4) HttpSession을 선언해서 사용할 수 있다.
* 4. 요청(@RequestMapping)
* 1) 메소드 : GET, POST
* 2) URL : 요청 주소
@Controller: 컨트롤러를 만드는 Annotation
@RequestMapping:
만들어보는건 6교시에 이어서
5교시에 이어서 MyController01 만들어보기
MyController01
@Controller
public class MyController01 {
// value="/" : contextPath 요청을 의미한다. http://localhost/app03/ 주소를 의미한다.
// value="/main.do" : /main.do 요청을 의미한다. http://localhost/app03/main.do 주소를 의미한다.
@RequestMapping(value={"/", "/main.do"}, method=RequestMethod.GET)
public String welcome() {
// ViewResolver의 prefix : /WEB-INF/views/
// ViewResolver의 suffix : .jsp
return "index";
}
@RequestMapping(value="/board/list.do", method=RequestMethod.GET)
public String boardList() {
// ViewResolver의 prefix : /WEB-INF/views/
// ViewResolver의 suffix : .jsp
return "board/list"; // /WEB-INF/views/board/list.jsp
}
return 값으로 index.jsp 반환하려면 "/WEB-INF/views/index.jsp"로 적어야하는데 index만 적은 이유
--> Servlet-context.xml에서 prefix랑 suffix 설정을 해뒀기 때문. prefix, suffix 설정해둔 건 안적어도 적용된다.
component 설명은 servlet-context에 포함되는거라서 5교시에 적음
Spring 4 버전 이후 사용 가능한 @RequestMapping
1. @GetMapping
2. @PostMapping
(우리는 스프링 5라서 사용 가능)
MyController02
@Controller
public class MyController02 {
@GetMapping(value="/notice/list.do")
public String noticeList() {
// ViewResolver의 prefix : /WEB-INF/views/
// ViewResolver의 suffix : .jsp
return "notice/list"; // /WEB-INF/views/notice/list.jsp
}
@GetMapping(value={"/member/list.do","/member/list"})
public void memberList() {
}
}
/notice/list.do
만약 @GetMapping(value="/notice/list.do") 주소를 notice가 아닌 board로 적어줬다면?

MyController01에서 board/list.do로 매핑해줬던 적(왼쪽)이 있기 때문에 오류남. 똑같은 주소를 두 개 이상 적어 또 요청하면 실행 안됨. controller는 몇개가 있어도 상관없지만 매핑 주소는 유일하게 적어줘야 한다. jsp에서는 이런걸 거를 능력이 없었지만 스프링은 거른다.
주의

PostMapping으로 적으면 실행가능함.

아직 안배운 rest방식이 서로 다른 RequestMethod 방식인데 주소가 같은 것
member/list.do
여긴 리턴값을 안만들어줬다. 5교시에 적은 반환타입 설명을 보면 반환이 void일 경우 컨트롤러가 호출한 서비스에서 직접 응답한다고 되어 있는데 과연 실행이 될까
해당 주소에 member 패키지와 list.jsp 만들고 실행한 결과

정상적으로 열림
동작한 원리: 분명히 list.jsp를 이용하겠다고 명시한 것이 없음에도 잘 동작된다. 이유는 void일때는 주소(GetMapping의 value값)를 경로로 바꿔 jsp로 적용하기 때문임. .do가 들어가있으면 .do를 삭제하고 그 자리를 .jsp로 바꿔준다.
반환타입을 적었을 때 기대하는 1차동작은 서비스가 응답되는 것이고 지금처럼 서비스가 없을 때 기대할 수 있는 2차동작은 주소를 경로로 바꿔주는 것
반환이 없는 경우에는 요청 주소를 Jsp 경로로 인식한다.
(그런데 이거 추천은 안한다고 하네)
index.jsp 작성해서 톰캣 서버로 실행해주는 작업만 하고 끝냄
index.jsp
jsp 파일이니까 taglib으로 jstl 설정해주고 contextPath 적어줌
상단부
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
body내용
<%-- MyController01으로 요청 --%>
<div>
<a href="${contextPath}/board/list.do">board 목록</a>
</div>
<hr>
<%-- MyController02으로 요청 --%>
<div>
<a href="${contextPath}/notice/list.do">notice 목록</a>
<br>
<a href="${contextPath}/member/list.do">member 목록</a>
</div>
실행결과

누르면 각 경로로 잘 간다. 성공