코드로 배우는 스프링 웹 프로젝트 - 4

김상복·2022년 5월 17일
0

12번 영상 : 컨트롤러의 파라미터


Controller


[어노테이션 정리]
1. @Controller

  • 해당 클래스의 인스턴스를 스프링의 빈으로 등록하고 사용하게 하는 어노테이션
    단, 반드시 Component-scan과 같이 사용되어야한다(해당 패키지를 조사해서 빈을 등록)

2. @RequestMapping("url경로")

  • EX) ("sample/") 이면 sample로 시작하는 모든 경로는 해당 컨트롤러를 통해서 작동해야한다는 의미
    클래스 : @RequestMapping("/sample/
    ")
    메소드 : @RequestMapping("basic")
    으로 되어있으면 /sample/basic에 응하는 메소드이다

배열로 만들시 {"url", "url"} 동시에 반응하는 컨트롤러 생성가능

3. @Data

  • Getter,Setter, 빈 생성자를 만들어주는 어노테이션

Model

과거에는 ModelAndView를 사용했지만 스프링이 발전하면서 Model만 사용하게 되었다

Model에 담는 데이터 -> 파라미터가 아니라 다른 곳에서 발생한 데이터를 담기 위한 그릇이다

@ModelAttribute : 어떠한 데이터를 내가 어떤 변수에 넣어서 사용하겠다할 때 사용하는 것

  • @ModelAttribute("ABCD") sampleDTO dto 이면 slist 라는 변수에 sampleDTO라는 데이터를 넣어 준것이다

@RedirectAttribute : 화면에 한번만 전달되는 파라미터를 처리하는 용도

  • 내부적으로 HttpSession객체에 담아서 한 번만 사용하고 폐기한다
    (1) a.addFlashAttribute("변수명", 데이터)

13번 영상 : 컨트롤러 리턴타입


Controller의 리턴 타입

(1) String : jsp를 이용하는 경우에는 jsp 파일의 경로와 파일이름을 나타내기 위해서 사용
성공 - jsp, 실패 - ??
(2) void : 호출하는 URL과 동일한 이름의 jsp를 의미
(3) VO,DTO 타입 : JSON 타입의 데이터를 만들어서 반환하는 용도로 사용(추가적인 라이브러리 필요)
(4) ResponseEntity 타입 : response 할 때 Http 헤더 정보와 내용을 가공하는 용도로 사용
(5) Model, ModelAndView : Model로 데이터를 반환하거나 화면까지 같이 지정하는 경우에 사용(최근에는 사용하지 않음)
(6) HttpHeaders : 응답에 내용 없이 Http 헤더 메시지만 전달하는 용도로 사용

3,4번은 Web에서는 잘 사용하지 않음

String 타입

redirect : 강제로 이동시킬 때 사용함
사용법 : return "redirect:";

[예제]

	@GetMapping("/re1")
    public String re1( ){
    	log.info("re1......");
        return "redirect:/sample/re2";
    }
    
    @GetMapping("/re2")
    public void re2( ){
    	log.info("re1......");
    }
    

이렇게 되면 실제로 url에서는 re1을 호출 했지만 redirect로 인해서 re2를 이동하게 됨


14번 영상 : 파일 업로드


파일 업로드

  1. pom.xml에 해당 코드 추가

    <!-- commons-fileupload -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
    </dependency>
  2. multipartResolver 스프링 빈 추가 - servlet-context.xml

    <!-- 파일 업로드 관련 - multipartResolver -->
    
    <beans:bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <beans:property name="defaultEncoding" value="utf-8"/>
        <beans:property name="maxUploadSize" value="104857560" />
        <beans:property name="maxUploadSizePerFile" value="2097152"/>
        <beans:property name="uploadTempDir" value="file:/C:/upload/tmp"/>	
        <beans:property name="maxInMemorySize" value="10485756" />
    </beans:bean>
  3. 실행


위의 이미지에서 주목할 점
(1) 첫번째 사진의 GetMapping, PostMapping
(2) 첫번째 사진의 files라는 변수
(3) form action의 경로
(4) 파일을 보내기위한 form의 enctype

먼저 GetMapping으로 해당 Url을 호출 시 jsp파일의 웹을 띄우게 된다
그 곳에 파일 업로드를 한 뒤 submit 버튼을 통해서 from의 action url을 호출하게 되고
그로 인해 Controller의 PostMapping이 반응하게 되고
파일 업로드를한 input의 이름이 files이기에 files라는 ArrayList에 해당 파일들이 들어있고
그 파일들을 테스트 해보게 되는 시스템이다


15번 영상 : 컨트롤러 예외 처리


@ControllerAdvice : 예외처리와 원래의 컨트롤러가 혼합 된 형태의 클래스가 작성되는 방식

@ExceptionHandler(Exception.class) : 라는 방식으로 예외를 처리함


16번 영상 : 프로젝트 설명


Controller

스프링 MVC에서 동작하는 Controller 클래스

Service, ServiceImpl

비즈니스 영역을 담당하는 인터페이스는 'xxxService'라는 방식을 사용하고 인터페이스를 구현한 클래스는 'xxxServiceImpl'이라는 이름을 사용

DAO

DAO나 Repository(저장소)라는 이름으로 영역을 따로 구성하는 것이 보편적, 예제에서는 별도의 DAO를 구성하는 대신에 Mybatis의 Mapper 인터페이스를 활용

VO, DTO

VO의 경우 Read Only의 목적이 강한 변수의 집합소 이고, DTO의 주로 데이터 수집의 용도이다

CRUD

게시물 조회, 목록, 수정, 등록, 삭제 등으로 예제를 실습해봄

예제 셋팅

(1) Spring Legacy Project 생성
(2) pom.xml에서 스프링 및 자바 버전 변경
(3) spring-test, spring-jdbc, spring-tx 추가
(4) junit 버전 변경
(5) Servlet 버전 변경
(6) HikariCP, MyBatis, mybatis-spring, Log4jdbc 추가
(7) log4jdbc 프로퍼티파일
(8) JDBC 드라이버 프로젝트 내 추가
(9) 기타 Lombok의 설정 등

전체적인 셋팅 값을 여기에서 확인해볼 수 있다


17번 영상 : DB 셋팅


테이블 셋팅 및 기본키 설정

create sequence seq_board;

create table tbl_board(
bno number(10,0),
title varchar2(200) not null,
content varchar2(2000) not null,
writer varchar2(50) not null,
regdate date default sysdate,
updatedate date default sysdate
);

alter table tbl_board add constraint pk_board primary key(bno);

commit;


18번 영상 : BoardVO 클래스와 매퍼 클래스


BoardVO 클래스

BoardVO 클래스에는 DB에서 가져올 데이터를 저장할 변수들의 집합소로써 private로 보호하는 변수들을 만들어서 @Data로 Setter, Getter를 사용해서 데이터를 가져올 수 있게 셋팅한다

Mapper 클래스

Mapper클래스란 Mybatis로 DB에 접근 할 수 있는 경우 어노테이션을 사용하거나 xml을 사용하여서 해당 메소드에 DB의 데이터를 가져올 수 있게 한다

단, 주의 해야할 점은 xml을 만들 때 Mapper 인터페이스의 패키지와 같은 경로로 폴더를 일일히 나누어서 xml을 생성하는데 반드시 하나씩 폴더를 따로따로 만들어줘야한다. 여기서 오류가 발생할 가능성이 매우 높다

MyBatis에 대한 정보

https://mybatis.org/mybatis-3/ko/sqlmap-xml.html


19번 영상 : insert / selectkey


Insert


주의 해야 할 점은 mybatis에서 #은 Getter를 의미한다

즉 테스트코드와의 순서를 보면 먼저 VO 클래스에 insert할 데이터를 넣어준다
그리고 난 뒤 insert를 실행 시키면 현재 VO에 들어있는 데이터를
Mybatis에서 #{ }으로 인식하여 BoardVO에 있는 title, content, writer의 데이터를 가져와서 DB에 삽입시킨다

라는 의미이다

SelectKey

https://yookeun.github.io/java/2014/07/11/mybatis-selectkey/


20번 영상 : RUD 기능 구현


BoardMapper.xml

<insert id="insert">
	insert into tbl_board(bno, title,content,writer) 
	values (seq_board.nextval, #{title}, #{content}, #{writer})
</insert>

<select id="read" resultType="org.zerock.domain.BoardVO">
	select * from tbl_board where bno = #{bno}
</select>

<delete id="delete">
	delete tbl_board where bno = #{bno}
</delete>

<update id="update">
	update tbl_board set 
		title = #{title},
		content = #{content},
		writer = #{writer},
		updatedate = sysdate
			where bno = #{bno}
</update>

BoardMapper 인터페이스

List<BoardVO> getList();
void insert(BoardVO vo);
BoardVO read(Long bno);
int delete(Long bno);
int update(BoardVO board);

Test 코드

	@Test
    public void read() {

        BoardVO vo = boardMapper.read(7L);
        log.info(vo);
    }

    @Test
    public void delete() {

        int count = boardMapper.delete(1L);

        log.info("count : " + count);
    }

    @Test
    public void update() {

        BoardVO vo = new BoardVO();
        vo.setBno(3L);
        vo.setTitle("Updated Title");
        vo.setContent("Update Content");
        vo.setWriter("User00)");

        log.info("count : " + boardMapper.update(vo));

    }

21번 영상 : Service


Service

Service 계층을 나누는 이유는

(1) Repository Layer (저장소 DB)
(2) Service Layer (비즈니스)
(3) Presentation Layer (웹 표면)

이러한 구조로 이뤄지기 때문이다

저장소에서 바로 Presetation 으로 갈 수도 있지만 이런식으로 구현하지 않는다

그렇기에 아까 만들었던 Mapper 클래스를 사용해서 Service 클래스를 만들어서

Web으로 출력시킬수 있도록 한다

Service(인터페이스)

	public interface BoardService {

    public void register(BoardVO board); || insert
    public BoardVO get(Long bno);  || read
    int modify(BoardVO board);	|| update
    int remove(Long bno);	|| delete
    List<BoardVO> getList();	|| getList

}

ServiceImpl(실제 구현 클래스)

	public class BoardServiceImpl implements BoardService {

      private final BoardMapper mapper;

      @Override
      public void register(BoardVO board) {

          mapper.insert(board);

      }

      @Override
      public BoardVO get(Long bno) {
          return mapper.read(bno);
      }

      @Override
      public int modify(BoardVO board) {
          return mapper.update(board);
      }

      @Override
      public int remove(Long bno) {
          return mapper.delete(bno);
      }

      @Override
      public List<BoardVO> getList() {
          return mapper.getList();
      }
	
    }
    
    
    
    
    
    
    
    

22번 영상 : Controller 설정 및 테스트


Web 부분의 페이지를 만들기 전에 이러한 도표를 만들 필요성이 있다

profile
초보 개발자

0개의 댓글