25강 - Anotation 을 활용한 서비스 객체 DI
자바 프로그램의 초기화 또는 설정 파일
방법1) .xml 파일
방법2) @(어노테이션)
noticeService 를 DI 할때 초기화 또는 설정을 [.xml] ===변경===> [어노테이션] 해보자!
밑줄 친 부분을 xml 파일에서 제거 후 ListController에서 @Autowired 추가
=> field 와 setter에 @Autowired 추가 가능
1) setter 메세드에 @Autowired 붙이기
=> setter 메서드에 특정 작업이 필요할때 setter 메서드에 @Autowired 를 붙여준다.
ex.
private NoticeService noticeService;
@Autowired
public void setNoticeService(NoticeService noticeService){
this.noticeService = noticeService;
System.out.println("Hello World"); //특정작업
}
2) field 에 @Autowired 붙이기
=> setter 메서드가 없어도 된다.
26강 - Annotation 으로 서비스 객체 생성하기
※ <context:component-scan base-package="com.newlecture.web.service" /> 설명
base-package("com.newlecture.web.service") 안에 있는 모든 클래스를 조회해서 어노테이션 되어있는 클래스를 찾아 생성한다.
=> 따라서 이전에 생성해둔 <context:annotation-config /> 은 제거해도 된다. (중복됨으로)
27강 - Annotation 으로 URL 매핑하기
※ 어노테이션을 등록하는 이유
=> 해당 클래스를 IoC 컨테이너에 담기위해서이다.
컨트롤러 클래스를 어노테이션 할때 URL을 맵핑해주는 작업을 추가해주어야한다.(@RequestMapping(""))
ex.
@RequestMapping("/index")
public void index(){
...
}
을 해줌으로써 /index 라는 url이 들어오면 index() 함수 내부에서 처리. 즉, url은 함수에 맵핑된다.
※ <mvc:annotation-driven /> xml 파일에 설정 추가 작업
클라이언트 요청에 대한 url 맵핑 역할을 해주는 설정이다.
ex. Client로 부터 "/index" 요청(request)이 왔을때 IndexCotnroller 컨트롤러 클래스에서 index()함수를 찾는 작업
28강 - HomeController 만들기
이제 클래스에 url을 맵핑하여 처리하는 것이 아니라 함수에 맵핑하여 각각의 함수가 컨트롤러 역할을 맡아 수행된다.
함수가 컨트롤러가 됨으로써 기존의 indexController 클래스는 홈 디렉토리에 존재하는 View(.jsp 파일)들을 관리하는
HomeController 로 클래스명을 바꾸는게 적절하다.
[정리]
함수가 컨트롤러 역할
클래스는 컨트롤러를 담고있는 폴더 역할
게시판을 관리하는 notice 패키지 내부의 DetailController 와 ListController 는 어떻게 바꿀 수 있을까?
[인덱스 컨트롤러의 Tiles 전달하는 방법]
@RequestMapping("/index")
public String index(){
return "root.index"; //Client의 요청 정보에 해당하는 View 정보를 Tiles 로 전달
}
29강 - Notice 컨트롤러 정리하기
이제는 클래스 자체를 url 맵핑하는 것이 아니라 한아ㅢ 클래스 내의 함수로 컨트롤러를 만들어 낼 수 있다.
컨트롤러(함수)를 담고있는 클래스의 구성은 어떻게 구성해야할까?
=> view의 구조에 따라 다르다
아래와 같은 view 구조를 예를 들어보자.
view 포러 아래에 customer 폴더가 있고, 그 아래에 event, faq, inc, notice 폴더가 존재한다.
이와 같은 구조를 자바 구조로 만들려면,
customer 이라는 패키지를 만들고 그 안에 event, faq, inc, notice 클래스들을 만들어준다.
notice 에 관련된 컨트롤러를 관리하는 NoticeController 클래스를 만들어주고,
view/notice 내부의 detail.jsp 와 list.jsp 인 view 페이지가 있으므로
NoticeController 클래스에서 detail 관련 함수(컨트롤러)와 list 관련 함수(컨트롤러)를 2개 만들어주면 된다.
# 중복된 URL 맵핑 관리하는 방법
중복된 URL을 클래스 위에 선언해줌으로써 중복 관리를 할 수 있다.
클래스 위에 선언을 해주면 url 맵핑할때 알아서 먼저 결합후 함수 위에 있는 url을 결합한다.
30강 - 컨트롤러를 위한 Annotation 개념정리
@RequestMapping 한 함수의 반환 값을 void로 설정한 경우,
Front Controller 에 대한 응답 값이 없게 되는 것이고, Front Controller 는 요청에 대한 404, 500 에러를 클라이언트에게 보여준다.
그럼 void 가 아닌 String 값으로 하고 타일즈 정보를 반환하면 TilesResolver 가 그 반환 값을 보고 해당 view 페이지를 조합하여 Front Controller 에게 반환한다.
그럼 Front Controller 는 만들어진 View 페이지를 클라이언트에게 응답한다.
31강 - 문서 출력 방법 4가지
기존에 "ResourceViewResolver 를 이용한 문서 출력하기" 와 "TilesViewResolver 를 이용한 문서 출력하기" 는 구현해보았다.
# 이번에는 "서블릿 객체를 얻어서 문자열 출력하기" 를 해보자
=> HttpServletResponse 객체를 Controller 함수에 가져와야하는데 어떻게 가져올까?
예를 들어보자!
index() 함수에 매개변수 HttpServletResponse response 받는다고 정의하면
Front Controller 에서 invoke() 할때 index() 함수의 매개변수를 보고 HttpServletResponse 가 필요하다는 것을 인지하여
HttpServletResponse request객체를 넣어서 index() 함수를 invoke(호출)한다.
따라서 서블릿 객체를 얻어오려면 Controller 함수에서 매개변수로 HttpServletResponse request 를 명시해주어야한다.
# 이번에는 "@ResponseBody 설정을 통한 문자열 출력하기" 를 해보자
HttpServletResponse 객체를 쓰지말고 @ResponseBody 를 index() 함수 위에 선언해주면
==> index() 함수의 리턴값은 ResponseBody 이다.
ViewResolver 사용하지 않고 리턴값 자체를 바로 사용자에게 보내라!
ex.
@RequestMapping("index")
@ResponseBody
public String index(){
return "Hello Index";
}
32강 - @RestController 와 한글 출력
@Controller 는 문서를 반환하는 역할을 하는 컨트롤러이다.
반면에 @RestController 는 데이터를 제공해주는 역할을 하는 컨트롤러이다.
=> 마치 @ResponseBody 와 같은 역할이다.
package com.newlecture.web.controller.customer.api;
@RestController
@RequestMapping("/api/notice")
public class NoticeController{
@RequestMapping("list")
public String list(){
return "notice list";
}
}
위와 같이 만들었을때 아래와 같이 디폴트로 객체가 만들어져 IoC 컨테이너에 들어간다.
//NoticeController noticeController = new NoticeController();
//<bean id="noticeController" class="...NoticeController">
※ 여기서 문제 발생!!!!!!!
noticeController 로 객체를 만들어 IoC 컨테이너에 들어가면 이전에 만들었던
com.newlecture.web.controller.customer.NoticeController 와 같은 이름의 객체가 만들어져 찾을때 충돌이 일어난다.
=> 따라서 생성할때 @RestController("apiNoticeController") 으로 객체 생성시 id값을 명시해주어야
충돌을 방지할 수 있다.
# @RestController 는 언제 사용되는가?
자바스크립트 개발자에게 데이터를 제공할때 @RestController 을 활용해서 제공한다.
※ 한글 출력 문제
servlet-context.xml 파일에서 url 맵핑을 도와주는 명령어가 <mvc:annotation-driven /> 이다.
url 맵핑할때 text/html;charset=UTF-8 로 converters(변환) 해줌으로써 한글 깨짐을 방지하는 설정을 넣을 수 있다.
<mvc:annotation-driven>
<mvc:message-converters> <!-- @ResponseBody로 String 처리할때 한글처리 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
33강 - JSON 출력하기
Spring 에서는 @RestController 를 선언한 클래스에서
해당 컨트롤러에 반환 객체를 던지면 알아서 JSON으로 변환해서 값을 Client에게 전달해준다.
ex.
@RestController("apiNoticeController")
@RequestMapping("/api/notice/")
public class NoticeController {
@Autowired
private NoticeService service;
@RequestMapping("list")
public List<Notice> list() throws ClassNotFoundException, SQLException {
List<Notice> list = service.getList(1, "title", "");
return list; //데이터를 담은 list 객체를 return한다.
}
}
[결과]
34강 - 지금까지 다루었던 내용과 이번에 다루게 될 사용자 입력 5가지
지금까지 다루었던 내용
앞으로 다룰 내용 => Client로 부터 요청한 데이터값 "입력"
사용자로부터 전달되는 값은 5가지 있다.
35강 - QueryString 입력 #1
# Front Controller 로 부터 입력 도구(HttpServletRequest request) 를 얻어오는 방법
=> 이전에 배웠던 "서블릿 객체를 얻어서 문자열 출력하기" 와 같이 Controller 함수의 매개변수를 HttpServletRequest request
넣어 줌으로써 Front Controller 에서 request객체를 얻어온다.
# Front Controller 로 부터 입력 값 얻어오는 방법
=> Client로부터 p=1의 값을 넘겨 받을때 index() 컨트롤러의 매개변수에도 똑같이 p를 정의해놓으면
Spring 에서 알아서 Front Controller 에서 String p = request.getParameter("p"); 해서 p 의 값을 받아
index() 컨트롤러에게 전달해준다.
36강 - QueryString 입력 #2 : 변수명 별칭과 기본값 처리
현재 Client에게 request "/list?p=1" 로 넘어올때 Controller 함수에서 매개변수를 넘어오는 값의 이름과 똑같이 p로 지정했다.
ex.
@RequestMapping("/list")
public void list(String p){ ... }
QueryString 으로 넘어오는 매개값은 QueryString의 길이 한계로 인하여 짧게 쓰는게 맞지만,
Controller 함수에는 그러한 제약을 받지 않기때문에 짧게 쓰지 않고 원하는데로 변수명을 설정하고 싶다.
ex. QueryString 으로 넘어온 p는 page를 나타낸 것임으로 Controller 함수에서 String page로 매개변수를 쓰고싶다.
어떻게 해야할까?
=> String page 매개변수 앞에 @RequestParam("p") 를 명시해줌으로써
page 라는 이름으로 가져오는게 아니고 p라는 이름으로 Front Controller 에서 가져와 page에 변수에 담아줘라
ex.
@RequestMapping("/list")
public void list(@RequestParam("p") String page){ ... }
그런데 말입니다...
만약 Client 의 request가 "/list?p=1" 와 같이 p=1을 요청하는 것이 아닌 단순 "/list" 를 요청할때 어떻게 해야할까?
=> 404 error 발생
단순히 /list 요청이 들어왔을때는 index(@RequestParam("p") String page) 컨트롤러에서 p의 디폴트 값을 설정해준다.
==> @RequestParam() 의 옵션 속성 중에 defaultValue 라는 것을 활용하면 된다.
ex.
public String list(@RequestParam(name="p", defaultValue = "1") String page) { ... }
(※ 주의: request로 넘어오는 값은 String 값임으로 defaultValue 값을 String 으로 설정하는 것이다.)
위의 메소드를 조금 변형하자면 String 값으로 넘어온 page 값은 결국 int 로 변형해야하기때문에
public String list(@RequestParam(name="p", defaultValue = "1") int page) { ... } 로 설정해준다.
37강 - @RequestParam Optional 속성
@RequestParam 의 Oprtional 속성 종류
1. defaultValue 속성 : 파라미터로 전달되는 값이 전달되지 않았을때 디폴트 값 설정
2. name 속성 : 파라미터로 넘어오는 값을 name으로 지정
3. required 속성 : required="false" 로 하면 "p 로 부터 전달된 값이 반드시 넘어오지 않아도 된다." 를 의미한다.
public String list(@RequestParam(name="p", required="false") String page) { ... } 로 설정하면
Client 의 request 가 "/list" 의 경우(값이 전달되는게 없을때) 404 error 을 발생시키지 않는다.
(required 의 default 값은 true 이다.)
4. value 속성 : name 과 같은 역할을 한다.(단, 둘다 같이 쓰면 안된다.)
ex. public String list(@RequestParam(name="p", value="a") String page) { ... } [X] 틀린 설정이다.
38강 - POST 입력을 위한 Admin 컨트롤러 추가하기
39강 - POST 입력방법
40강 - POST 입력방법 #2 (콤보박스 값 입력)
콤보 박스를 서버로 받으려면 어떻게 할까?
1. View page 의 카테고리 생성
<tr>
<th>카테고리</th>
<td class="text-align-left text-indent text-strong text-orange" colspan="3">
<select name="category">
<option>카테고리1</option>
<option>카테고리2</option>
<option>카테고리3</option>
<option>카테고리4</option>
</select>
</td>
</tr>
2. 서버쪽에 category로 받기 ( 테스트 실행에서 선택한 category: 카테고리2 )
@RequestMapping("reg")
@ResponseBody
public String reg(String title, String content, String category){
return String.format("title:%s<br>content:%s<br>category:%s<br>", title, content, category);
}
3. 결과
카테고리 2
4. 우리가 원하는 값은 option의 value 값이다.
=> view page의 카테고리의 value="" 옵션 추가
<tr>
<th>카테고리</th>
<td class="text-align-left text-indent text-strong text-orange" colspan="3">
<select name="category">
<option value="1">카테고리1</option>
<option value="2">카테고리2</option>
<option value="3">카테고리3</option>
<option value="4">카테고리4</option>
</select>
</td>
</tr>
[결과]
2
결과는 value 값 2만 뜨는 것을 확인할 수 있다.
41강 - POST 입력 #3 (체크박스, 라디오버튼 입력)
체크박스 [view page]
<tr>
<th>좋아하는 음식</th>
<td class="text-align-left text-indent text-strong text-orange" colspan="3">
<input type="checkbox" name="foods" value="1" id="ch1"><label for="ch1">짜장면</label>
<input type="checkbox" name="foods" value="2" id="ch2"><label for="ch2">짬뽕</label>
<input type="checkbox" name="foods" value="3" id="ch3"><label for="ch3">볶음밥</label>
<input type="checkbox" name="foods" value="4" id="ch4"><label for="ch4">탕수육</label>
</td>
</tr>
[서버에 값이 보내질때]
아래 사진과 같이 food 값이 보내진다.
체크박스는 다중 선택이 가능!!
서버에서는 어떻게 받을까?
=> String[] foods 배열로 받으면 된다. (체크박스는 다중선택이 가능하기 때문이다.)
@RequestMapping("reg")
@ResponseBody
public String reg(String title, String content, String category, String[] foods) {
for(String food : foods) {
System.out.println(food);
}
return String.format("title:%s<br>content:%s<br>category:%s<br>", title, content, category);
}
출처: 뉴렉처
www.youtube.com/watch?v=9Tmzt6Q9WI8&list=PLq8wAnVUcTFUHYMzoV2RoFoY2HDTKru3T&index=27
'스프링 프레임워크' 카테고리의 다른 글
MyBatis3 와 MyBatis3-Spring 의 프로세스 (0) | 2021.04.19 |
---|---|
PointCut 표현식 문법 (0) | 2021.04.19 |
Spring MVC (스프링 웹 MVC) 14강 ~ 24강 (0) | 2021.03.24 |
Spring MVC (스프링 웹 MVC) 1강 ~ 13강 (0) | 2021.03.19 |
뉴렉처[스프링 프레임워크_AOP] 1강 ~8강 (2) | 2021.03.11 |