Spring WebMVC Framework - 1013

Yung·2022년 10월 13일
0

Java223bitcamp

목록 보기
20/26

082. Spring WebMVC Framework 사용법

  1. @RequestMapping 사용법
  2. 스프링의 CharacterEncodingFilter 사용법
  3. 필터를 자바 코드로 배치하는 방법
  4. 요청 핸들러의 파라미터 다루는 방법

요청 핸들러 request handler : 요청이 들어왔을 때 호출되는 메서드
예) add(), list(), detail() 등

요청이들어오면 DispatcherServlet(Front Controller)가 받는다.
DispatcherServlet가 하는 일
1) 요청 URL을 처리할 페이지 컨트롤러의 핸들러를 찾는다.
2) 핸들러의 파라미터를 알아낸다.
3) 핸들러에게 넘겨줄 파라미터 값을 준비한다.
4) 준비한 파라미터 값을 가지고 핸들러를 호출한다.
5) 핸들러가 리턴한 값을 리턴한다.
6) ServletRequest 보관소에 담아야 할 값은 담고, 뷰컴포넌트 URL은 해당 뷰 컴포넌트를 실행
7) 클라이언트에 응답

Model, View, Controller
Model : Service, DAO
Page Controller : Controller
View : View

  1. 요청이 들어오면 Front Controller가 요청을 받고,
  2. Front Controller는 파라미터에 전달된 값(argument)을 준비하고
  3. Front ControllerPage Controller에게 핸들러를 호출한다.
    호출할 때 2번에서 생성된 argument를 파라미터값으로 넘겨준다.
  4. Page Controller는 서블릿, DAO, DBMS를 통해서 리턴된값을 다시 Front Controller에게 리턴한다.
  5. Front Controller는 리턴받은 값을 이용해서 ServletRequest보관소에 작업결과를 저장한다.
  6. Front ControllerView를 호출하는데 ViewServletRequest보관소에 저장된 값을 사용
    하고 출력 콘텐트를 생성(html,css,javascript), XML, JSON등의 작업결과를 Front Controller에게 다시 리턴한다.
  7. Front Controller를 통해 Client에게 응답한다.

3단계 - 요청 핸들러의 파라미터 값을 조정한다.

- controller.XxxxContorller 클래스 변경

  • 요청을 처리하는 메서드에 필요한 값만 파라미터로 받는다.
    		//  public String form(HttpServletResponse response, HttpServletRequest request) 	throws Exception {
     public String form(HttpServletResponse response) throws Exception {

- 요청 파라미터 값을 핸들러의 파라미터로 직접 받을 수 있다.:@RequestParam

  // 변경 전
 @PostMapping("/board/add") 
 public String add(HttpServletRequest request, HttpServletResponse response) throws Exception {
   Board board = new Board();
   board.setTitle(request.getParameter("title"));
   board.setContent(request.getParameter("content"));
   board.setAttachedFiles(saveAttachedFiles(request));
   board.setWriter((Member) request.getSession().getAttribute("loginMember"));

   boardService.add(board);
   return "redirect:list";
 }

 // 변경 후
 @PostMapping("add")
 public String add(@RequestParam("title") String title, @RequestParam("content") String content,
     HttpServletRequest request, HttpSession session) throws Exception {
   Board board = new Board();
   board.setTitle(title);
   board.setContent(content);
   board.setAttachedFiles(saveAttachedFiles(request));
   board.setWriter((Member) session.getAttribute("loginMember"));
   boardService.add(board);

   return "redirect:list";
 }

- @RequestParam 생략할 수 있는 경우

클라이언트에서 보내는 파라미터 변수이름과 값을 받을 변수의 이름이 같을경우 @RequestParam을 생략할 수 있다.

 // 변경전 
@PostMapping("add")
public String add(@RequestParam("title") String title, @RequestParam("content") String content,
HttpServletRequest request, HttpSession session) throws Exception {

 // 변경후
 @PostMapping("add")
 public String add(String title, String content, HttpServletRequest request, HttpSession session)
     throws Exception {

- ServletContext를 받는 방법 : 생성자를 통해 주입 받는다.

public class BoardController {

ServletContext sc;
BoardService boardService;

public BoardController(BoardService boardService, ServletContext sc) {
  this.boardService = boardService;
  this.sc = sc;
}

- 첨부파일을 파라미터로 받을 수 있다.

 @PostMapping("add")
 public String add(String title, String content, Part[] files, HttpServletRequest request,
     HttpSession session) throws Exception {
   Board board = new Board();
   board.setTitle(title);
   board.setContent(content);
   board.setAttachedFiles(saveAttachedFiles(files));
   board.setWriter((Member) session.getAttribute("loginMember"));
   boardService.add(board);

   return "redirect:list";
 }

 private List<AttachedFile> saveAttachedFiles(Part[] files) throws IOException, ServletException {
   List<AttachedFile> attachedFiles = new ArrayList<>();
   String dirPath = sc.getRealPath("/board/files");
   //Collection<Part> parts = request.getParts();

   for (Part part : files) {
     if (!part.getName().equals("files") || part.getSize() == 0) {
       continue;
     }

     String filename = UUID.randomUUID().toString();
     part.write(dirPath + "/" + filename);
     attachedFiles.add(new AttachedFile(filename));
   }
   return attachedFiles;
 }

- Part 대신 스프링에서 제공하는 MultiPartFile 타입으로 첨부파일을 받는다.

  private List<AttachedFile> saveAttachedFiles(MultipartFile[] files)
    throws IOException, ServletException {
  List<AttachedFile> attachedFiles = new ArrayList<>();
  String dirPath = sc.getRealPath("/board/files");
  //Collection<Part> parts = request.getParts();

  for (MultipartFile part : files) {
    if (part.isEmpty()) { // 비어있다면 continue; 다음꺼로  빈파일 있다면 저장하지 않는다.
      continue;
    }

    String filename = UUID.randomUUID().toString();
    part.transferTo(new File(dirPath + "/" + filename));
    attachedFiles.add(new AttachedFile(filename));
  }
  return attachedFiles;
}

멀티파트 요청 데이터를 도메인 객체로 받기

multipart/form-data ----> 도메인 객체, 예) Board
multipart/form-data를 도메인 객체로 변환하기 위해서는 MultipartResolver가 필요하다
MultipartResolver를 사용하기 위해서는 별도 설정이 필요하다.

- 낱개의 파라미터 값을 도메인 객체로 받을 수 있다.

- 단, multipart/form-data 형식으로 전송된 데이터를 처리하려면 MultipartResolver를 설정해야 한다.
public class AppConfig {
   // multipart/form-data 형식으로 보내온 요청 데이터를
   // 도메인 객체로 받는 일을 할 도우미 객체를 등록한다. 
   // 이 객체가 등록된 경우 multipart/form-data를 도메인 객체로 받을 수 있다.
 @Bean("multipartResolver")
 public MultipartResolver createMultipartResolver() {
   return new StandardServletMultipartResolver();
 }

- ServletRequest 보관소에 작업 결과를 저장할 때 페이지 컨트롤러에서 하는 대신 프론트 컨트롤러에서 하기: ModelAndView 클래스

@GetMapping("list")
public ModelAndView list() throws Exception {
  ModelAndView mv = new ModelAndView();
  mv.addObject("boards", boardService.list());
  mv.setViewName("/board/list.jsp");
  return mv;
}

요청 핸들러의 리턴 타입

  1. void handle() {-}
    void <- JSP주소가 없다, 요청 URL을 JSP 주소로 사용한다.
  2. String handle() {-}
    String <- JSP URL
  3. Model handle() {-}
    Model <- ServletRequest 보관소에 담을 객체들을 리턴, JSP 주소가 포함되어 있지 않다.
    따라서 요청 URL을 JSP 주소로 사용한다.
  4. Map handle() {-}
    Map <- 3번과 같은 메서드로 취급한다.
  5. ModelAndView handle() {-}
    ModelAndView <- JSP 주소 + ServletRequest 보관소에 저장할 객체들
  @GetMapping("list")
  public ModelAndView list() throws Exception {
    ModelAndView mv = new ModelAndView();
    mv.addObject("boards", boardService.list()); // ServletRquest 보관소에 저장하고
    mv.setViewName("/board/list.jsp"); // jsp파일의 주소를 매핑한다.
    return mv;
  }
  1. View handle() {-}
    View <- JSP 주소를 View 객체에 담아 리턴한다.
  @GetMapping("form")
  public View form() throws Exception {
    return new JstlView("/auth/form.jsp");
  } // JSTL에 담아서 리턴해도 된다

Front Controller(DispatcherServlet)는 요청 핸들러의 리턴타입에 따라 적절하게 처리한다.

ModelAndView와 DispatcherServlet

DispatcherServlet BoardController
1. DispatcherServlet가 BoardController에게 list() 호출
2. BoardController는 BoardService에게 list() 호출하여 리턴받음.
3. BoardController는 ModelAndView객체를 만들고 ModelAndView객체에 List와 JSP주소를 받아서 DispatcherServlet에게 리턴한다.
4. DispatcherServlet은 ModalAndView객체에서 데이터를 꺼내서 ServletRequest 보관소에 담는다.
5. DispatcherServlet가 JSP 주소를 꺼내서 실행하면, JSP는 ServeltRequest보관소에 저장된 데이터를 사용한뒤 DispatcherServlet에게 리턴한다.

ViewResolver

DispatcherServlet list호출 BoardController에게 list 호출
BoardControllerDispatcherServlet에게 "board/list" 리턴

DispatcherServlet은 "board/list"를 IntenerallResourceViewResolversms에게 전달하면
"/" + "board/list" + ".jsp" ==> "/board/list.jsp"를 만들어서 JsltView에 넘긴다.
JstlView는 JSP를 실행한다.

- 기본 ViewResolverInternalResourceViewResolver로 교체한다.

- InternalResourceViewResolver JSP를 뷰로 사용할때 사용하며, DispatcherServlet에게 아무런 ViewResolver를 등록하지 않으면, 기본으로 동작하는 ViewResolver이다.
  • 접두사, 접미사를 이용하여 JSP 주소를 완성할 수 있다.
    • InternalResourceViewResolver를 설정해야한다.
// Spring WebMVC의 기본 ViewResolver를 교체한다.
  @Bean("viewResolver")
  public ViewResolver createViewResolver() {
    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    viewResolver.setViewClass(JstlView.class); // 주어진 URL을 처리할 객체 => JSP 실행시킨다.
    viewResolver.setPrefix("/WEB-INF/jsp/"); //
    viewResolver.setSuffix(".jsp");

    return viewResolver;
  }
//  InternalResourceViewResolver 사용 전:
  @GetMapping("form")
  public String form(HttpServletResponse response) throws Exception {
      return "board/form";
  }
//
//  InternalResourceViewResolver 사용 후:
  @GetMapping("form")
  public void form() throws Exception {}

4단계 - JSP 파일을 /WEB-INF 밑에 두어 직접 접근하지 못하도록 만든다.

  • /WEB-INF/jsp 디렉토리 생성
    • 기존의 JSP 파일을 이 디렉토리로 옮긴다.
  • com.bitcamp.board.config.AppConfig 클래스 변경
    • createViewResolver() 메서드 변경

0개의 댓글