이제 대충쓰자
어제 8교시 복습 생략

<context:component-scan base-package="com.gdu.app05" />
필드, 생성자, setter에 붙일 수 있다. 셋 중 하나 선택해서 하면 됨
위의 @Component 부분 코드 이렇게 쓸 수도 있다
@Repository // DAO 전용 @Component, BoardDao boardDao 객체를 Spring Container에 생성해 둔다.
public class BoardDao {
public List<BoardDto> getBoardList() {
return Arrays.asList(
new BoardDto("제목1", "작성자1"),
new BoardDto("제목2", "작성자2"),
new BoardDto("제목3", "작성자3")
);
}
이렇게 전용 컴포넌트들이 있음
대표적으로
생성자를 사용하는 방법임. // 주입된 boardService 객체의 변경 방지를 위해 final 처리한다.
private final BoardService boardService;
// boardService에 final 처리를 하면 생성자 주입만 가능하다.(필드 주입과 Setter 주입은 불가능하다.)
// 생성자 주입의 @Autowired는 생략할 수 있으므로 @RequiredArgsConstructor와 같은 Annotation으로 대체할 수 있다.
@Autowired
public BoardController(BoardService boardService) {
super();
this.boardService = boardService;
}
@RequiredArgsConstructor // final field 전용 생성자
// @Autowired를 이용한 생성자 주입을 위해서 추가한다.
@Service // 서비스 계층(Business Layer) 전용 @Component, Spring Container에 BoardService boardServiceImpl 객체를 생성해 둔다.
public class BoardServiceImpl implements BoardService {
// 주입된 boardDao 객체의 변경 방지를 위해 final 처리한다.
private final BoardDao boardDao;
@Override
public List<BoardDto> getBoardList() {
return boardDao.getBoardList();
}
}
6장 만들기
config 연습을 해보겠다
@Configuration
public class BoardConfig {
@Bean
public BoardDto boardDto1() { // <bean class="BoardDto" id="boardDto1" />
return new BoardDto(1, "제목1", "작성자1");
}
@Bean
public BoardDto boardDto2() { // <bean class="BoardDto" id="boardDto2" />
return new BoardDto(2, "제목2", "작성자2");
}
@Bean
public BoardDto boardDto3() { // <bean class="BoardDto" id="boardDto3" />
return new BoardDto(3, "제목3", "작성자3");
}
@Bean
public BoardDao boardDao() {
return new BoardDao();
}
@Bean
public IBoardService iBoardService() {
return new BoardServiceImpl();
}
}
메소드 이름 boardDto1이 bean의 이름(id)
리턴 타입 BoardDto가 bean의 클래스 타입(class)

bean 만들어졌으니 가지고 와서 넣으면 된다.
타입이 BoardDto로 같은게 3개나 있기 때문에 이름이 같아야 주입될 수 있다
새로운 내용 없어서 생략
3장 MvcController03에서
모든 @RequestMapping 주소에 /blog가 공통포함되어있었는데 이럴땐 위로 빼주면 공통으로 적용된다.
@RequestMapping("/blog") // /blog로 시작하는 요청을 처리하는 컨트롤러, 모든 메소드의 요청에 "/blog"가 자동삽입
@Controller
public class MyController03 {
@RequestMapping("/detail.do") // GET 방식의 method는 생략 가능. value만 작성할 땐 value= 부분도 생략 가능
public String blogDetail(HttpServletRequest request, Model model) {
String blogNo = request.getParameter("blogNo");
model.addAttribute("blogNo",blogNo);
return "blog/detail"; // /WEB-INF/views//blog/detail.jsp로 forward한다 (스프링에서는 뭐라고 말 없으면 forward)
}
@RequestMapping("/detail.do")
public String blogDetail2(@RequestParam(value = "blogNo", required = false, defaultValue = "1") int blogNo, Model model) {
//@RequestParam(value = "blogNo") int blogNo은 int blogNo로만 써도 됨 (@RequestParam은 생략가능하니까)
model.addAttribute("blogNo",blogNo);
return "blog/detail";
}
@RequestMapping("/detail.do")
public String blogDetail3(BlogDto dto) { // Model에 저장된 이름은 dto가 아니라 blogDto
return "blog/detail";
}
@RequestMapping("/detail.do")
public String blogDetail4(@ModelAttribute("dto") BlogDto blogDto) { // Model에 저장되는 이름은 dto 이다.
return "blog/detail";
}
}
원래는 각 매핑주소마다 /blog/가 있었다
7장추가했음
Jackson Databind
2.15.2
-> pom.xml dependency에 추가
잭슨 = 스프링에서 가장 많이 사용하는 라이브러리, json을 안만들어도됨. 객체, 맵, 리스트 등 만들어서 넘기면 잭슨이 받아서 다 해준다고 함
이 뒤로는 열심히 파일들 만들기했음
잭슨 이용하면 json 안 만들어도된다.

리스트 반환해보기. string 이외의 반환 처음해보는 것이다. 원래는 json 직접 만들고 string으로 반환했었음.
ajax 처리 시 달라지는 부분은 컨트롤러
사진에서 오른쪽이 컨트롤러고 왼쪽은 데이터 받아야하는 ajax1.jsp다
우선 컨트롤러가 반환하는 건 디폴트 값이 jsp이기 때문에 리턴값이 jsp 이름이 아니고 데이터라는 걸 알려줘야 함. => @ResponseBody 애노테이션을 쓰면 된다 (중요) 메소드의 반환 값이 응답 데이터라는 것. ajax할때 없으면 안된다(jsp로 받아들이면 안되니까.) - 뒤에서 배우겠지만 RestController로 대체 가능하긴 하다
@RequestMapping("/ajax1")
@RequiredArgsConstructor
@Controller
public class AjaxController1 {
private final AjaxService ajaxService;
@ResponseBody // 메소드의 반환 값이 응답 데이터이다.
@RequestMapping(value="/list.do", method=RequestMethod.GET, produces="application/json; charset=UTF-8") // produces : 응답 데이터 타입
public List<AjaxDto> list() {
return ajaxService.getDtoList(); // jackson 라이브러리가 List<AjaxDto>를 json 데이터(배열)로 자동 변환한다.
}
@ResponseBody
@RequestMapping(value="/detail.do", method=RequestMethod.GET, produces="application/json; charset=UTF-8")
public AjaxDto detail(@RequestParam(value="name") String name) {
return ajaxService.getDto(name); // jackson 라이브러리가 AjaxDto를 json 데이터(객체)로 자동 변환한다.
}
}
응답데이터를 만들때는 항상 응답데이터 타입을 적어줬었다.
@RequestMapping에 produces 속성에 적어줌. produces="application/json; charset=UTF-8"
이렇게 적어주면 실제 반환 타입은 리스트지만 잭슨이 json으로 잘 받아준다
실행결과

콘솔로 잘 보내졌다.(resData)
클릭한 row의 name 전달하기 위해 ajax로 name 가져오기
function fnList(){
$('#btn_list').click(function(){
$.ajax({
// 요청
type: 'get',
url: '${contextPath}/ajax1/list.do',
// 응답
dataType: 'json',
success: function(resData){
$('#list').empty();
$.each(resData, function(i, elem){
$('#list').append('<div class="row"><span>' + elem.name + '</span>, ' + elem.age + '</div>');
})
}
})
})
}
원래는 클릭해도 이름만 전달 안됨. 그래서 elem.name 앞뒤로 span 추가해서 구분할 수 있게 해줌
function fnDetail(){
$(document).on('click', '.row', function(){
$.ajax({
// 요청
type: 'get',
url: '${contextPath}/ajax1/detail.do',
data: 'name=' + $(this).find('span').text(),
// 응답
dataType: 'json',
success: function(resData){
alert(resData.name + ', ' + resData.age);
}
})
})
}
클릭한 row = this(위 코드에서 append 안에 있는 div 태그 전체)
$(this).find('span')으로 하위 태그 중 span 찾아서 .text()로 내부텍스트, 즉 elem.name만 뽑아올 수 있게 해줬다.
마지막으로 컨트롤러에서 name 가져와서 출력시켜주면


클릭하면 이름만 콘솔에 출력된다
(컨트롤러에서 요청, 호출말고 딴 일하는건 좋지 않은데 여기선 임시로 했다)
한것들 좀 바꿔보기

Dto로도 똑같은거 했다. 클릭하면 하나씩 나옴. dto는 객체 형태로 전달해줌
모든 메소드에 @ResponseBody를 추가하는 @Controller이다. (@ResponseBody 추가할 필요 없어짐)
같은 역할이지만
@RequestMapping은 클래스 레벨과 메소드 둘다 맵핑 할 수 있고
@GetMapping은 메소드에만 맵핑 할 수 있다.
그러니까 @GetMapping이 더 세분화되었다고 볼수있다.

이렇게 적으면 너무 기니까 메소드 매핑일때는 @GetMapping으로 바꿔주고 method=RequestMethod.GET 지워버리면된다. (Post일땐 PostMapping)
스프링이 MediaType에 등록해놓음.
MediaType.APPLICATION_JSON_VALUE로 대체해서 쓸 수 있다.
@GetMapping(value="/list.do", produces=MediaType.APPLICATION_JSON_VALUE)
public List<AjaxDto> getDtoList() {
return ajaxService.getDtoList();
}
ajax는 나중에 Restful 배울 때 다시. db까지 사용해서