멀티캠퍼스 백엔드 과정45일차[8월 8일] - controller, 인텔리제이랑 github연동, 스프링 Web MVC[DispatcherServlet, Front-Controller]

GoldenDusk·2023년 8월 8일
0
post-thumbnail

intellj이랑 github 연동하기

  1. github랑 intellj 연동

  1. 버전 관리 - 레포지토리 추가

  1. 불필요한 파일 제거 - 플러그인 설치

.idea
*.iml
out
gen
.gradle
build
  1. 커밋 및 푸시

스프링 프레임 워크 8월 7일 내용

🍀 스프링 프레임 워크 8월 7일 내용

  1. root-context.xml(요청서)
  2. 싱글톤 ApplicationContext 객체
    • 빈(객체)
    • ⇒ 코드가 없는 형태의 클래스 등록
    • @Service, @Respository, @Controller, @Component ⇒ 자동등록
  1. 의존성 주입
  • @Autowired 싱글톤 객체를 주입해서 사용
  1. ORM
  • O : Java Object(DTO, VO)
  • R : RDB(table row)
  • M : Mapping
  • CRUD 작업
    • Create(insert into)
    • Read(select from)
    • Update(update set)
    • Delete(delete from)
  1. MyBatis Framework(ORM기술을 실체화하여 제공하는 프레임워크)
  1. 스프링에서 싱글톤을 설정하고 사용하는 방법 2가지
    1. 설정파일 XML을 이용하는 방법 : root-context.xml
    2. @표시를 이용하는 방법
  1. 스프링을 배우는 이유?
    1. 서버측의 객체 생성을 최소화 시키는 것이 필요
    2. 되도록이면 객체 생성은 한번만 하자.(싱글톤 패턴)

예제 - 어제에 이어서

  1. TimeMapper2 만들기 - xml 파일로 sql 작성
package com.multicampus.springex.mapper;

import org.apache.ibatis.annotations.Select;

public interface TimeMapper2 { //데이터베이스의 현재시각을 문자열로 받아와서 처리
    String getNow();
}
  1. resources안에 TimeMapper2.xml 만들기

💥 주의 : 이름을 위에 Mapper와 똑같이 맞춰줘야 함

  • 어노테이션이 아니라 xml 파일로 sql 작성
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.multicampus.springex.mapper.TimeMapper2">

    <!--어노테이션이 아니라 xml 파일로 sql 작성-->
    <select id="getNow" resultType="string">
        select now()
    </select>

</mapper>

3. ApplicationContext에 추가 해주기 - root-context.xml

<!--세션에다가 connection을 연결해주겠다 = sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
<!--        classpath는 resource의 경로 mappers라는 폴더 밑에 ** : 모든 폴더-->
        <property name="mapperLocations" value="classpath:/mappers/**/*.xml"/>
    </bean>

4. 테스트 코드 작성

package com.multicampus.springex.mapper;

import lombok.extern.log4j.Log4j2;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@Log4j2
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/root-context.xml")
public class TimeMapperTests {
    @Autowired(required = false)
    private TimeMapper timeMapper;
    @Autowired(required = false)
    private TimeMapper2 timeMapper2;

    @Test
    public void testGetTime(){
        log.info(timeMapper.getTime());
    }

    @Test
    public void testGetNow(){

        log.info(timeMapper2.getNow());
    }
}

스프링 Web MVC

📌 스프링 Web MVC의 특징

  • 기존의 MVC 구조에서 추가적으로 Front-Controller 패턴 적용
  • 어노테이션의 적극적인 활용
  • 파라미터나 리턴타입에 대한 자유로운 형식
  • 추상화된 api들의 제공

📌MVC 기본 구조

  1. 사용자의 Request는 Front-Controller인 DispatcherServlet을 통하여 처리 ⇒ web.xml에 설정
 <!--frontController를 쓰기 위해 서블릿 등록-->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--설정 정보, 위치값을 받아옴-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/servlet-context.xml</param-value>
        </init-param>

        <init-param>
            <param-name>throwExceptionIfNoHandlerFound</param-name>
            <param-value>true</param-value>
        </init-param>

        <!--톰캣 로딩할 때 필요한 서블릿을 먼저 로딩-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

2, 3. HandlerMapping

  • Request의 처리를 담당하는 컨트롤러를 찾기 위해서 존재
  • HandlerMapping 인터페이스를 구현한 여러 객체들 중 RequestMappingHandlerMap-ping의 경우 개발자가 @RequestMapping 어노테이션이 적용된 것을 기준으로 판단
  • TodoController
package com.multicampus.springex.controller;

import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller //스프링 MVC에서 컨트롤러 역할, 스프링의 빈(Bean)으로 등록
@RequestMapping("/todo")
@Log4j2
public class TodoController {
    @RequestMapping("/list") //localhost:8090/todo/list
    public void list(){
        log.info("todo_lis.....");
    }

    //@RequestMapping(value="/register", method = RequestMethod.GET) //localhost:8090/todo/register
    @GetMapping("/register")
    /*제대로 불러오는지 확인하는 작업, 제대로 불러오면 콘솔에 뜬다. */
    public void register(){
        log.info("GET todo_register.....");
    }

    // register은 post와 get방식 따로 따로
    @PostMapping("/register")
    public void registerPost(){
        log.info("Post todo register");
    }
}
  1. Controller
  • 개발자가 작성하는 클래스로 실제 Request를처리하는 로직 작성
  • View에 전달해야 하는 데이터는 주로 Model이라는 객체에 담아서 전달
  • Controller는 다양한 타입의 결과를 반환 ⇒ 처리 : ViewResolver

  1. ViewResolver
  • Controller가 반환한 결과를 어떤 View를 통해서 처리하는 것이 좋을지 해석하는 역할
  • servlet-context.xml에서 정의된 InternalResourceViewResolver
 <!--3. InternalResourceViewResolver 클래 : 스프링 MVC에서 제공하는 뷰를 어떻게 결정할 것인지 설정하는 담당하는 (객체)-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--prefix : MVC에서 사용했던 WEB-INF/view 경로-->
        <property name="prefix" value="/WEB-INF/views/"></property>
        <!--suffix : `.jsp` 확장자 지정-->
        <property name="suffix" value=".jsp"></property>
    </bean>
		<!--자동으로 빈 설정해줘라-->
    <context:component-scan base-package="com.multicampus.springex.controller"/>

6, 7. View
  • 실제로 응답 보내야 하는 데이터를 jsp를 이용해서 생성하는역할
  • 만들어진 응답은 DispatcherServlet을 통해서 전송

🍀 결론

모든 Request는 DispatcherServlet을 통하도록 설계되는데, 이런 방식을 Front-Controller 패턴

  • Front-Controller 패턴을 이용하면 전체 흐름을 강제로 제한 가능
    EX. HttpServlet을 상속해서 만든 클래스를 이용하는 경우 특정 개발자는 이를 활용할 수 있지만 다른 개발자는 자신이 원래하던 방식대로 HttpServlet을 그대로 상속해서 개발 가능
  • 모든 Request의 처리에 대한 분배가정해진방식대로만 동작하기 때문에 좀 더 엄격한 구조를 만들수 있다.

스프링 MVC Controller

📌 DispatcherServlet과 Front Controller

  • Front Controller패턴은 모든 요청을 하나의 컨트롤러를 거치는 구조로 일관된
    흐름을 작성하는데 도움이 됨 ⇒ facade 패턴
  • 스프링 Web MVC에서는 DispatcherServletFront Controller

Dispatcher-Servlet(디스패처 서블릿)의 개념

  • 디스패처 서블릿의 dispatch는 "보내다"라는 뜻을 가지고 있습니다.
  • 프론트 컨트롤러(Front Controller)
    • 디스패처 서블릿은 HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임
    • Front Controller는 서블릿 컨테이너의 제일 앞에서 서버로 들어오는 클라이언트의 모든 요청을 받아서 처리해주는 컨트롤러로써, MVC 구조에서 함께 사용되는 디자인 패턴
  1. 클라이언트로부터 어떠한 요청이 오면 Tomcat(톰캣)과 같은 서블릿 컨테이너가 요청을 받는다.
  2. 이 모든 요청을 프론트 컨트롤러인 디스패처 서블릿이 가장 먼저 받게 된다.
  3. 디스패처 서블릿은 공통적인 작업을 먼저 처리한 후에 해당 요청을 처리해야 하는 컨트롤러를 찾아서 작업을 위임한다.

Dispatcher-Servlet(디스패처 서블릿)의 장점

  • Spring MVC는 DispatcherServlet이 등장함에 따라 web.xml의 역할 축소. 모든 서블릿을 URL 매핑을 위해 web.xml에 모두 등록해주어야 했지만, dispatcher-servlet이 해당 어플리케이션으로 들어오는 모든 요청을 핸들링해주고 공통 작업을 처리면서 편리하게 이용할 수 있게 되었다.
  • 컨트롤러를 구현해두기만 하면 디스패처 서블릿가 알아서 적합한 컨트롤러로 위임하는 구조

Dispatcher-Servlet(디스패처 서블릿)의 단점인 정적 자원의 처리 및 해결 방안

  1. 정적 자원(Static Resources)의 처리
    Dispatcher Servlet이 요청을 Controller로 넘겨주는 방식은 효율적이지만 Dispatcher Servlet이 모든 요청을 처리하다보니 이미지나 HTML/CSS/JavaScript 등과 같은 정적 파일에 대한 요청마저 모두 가로채는 까닭에 정적자원(Static Resources)을 불러오지 못하는 상황도 발생하는 문제를 해결하기 위해

  2. 정적 자원 요청과 애플리케이션 요청을 분리
    애플리케이션 요청을 탐색하고 없으면 정적 자원 요청으로 분리하여 처리하도록
    1. 클라이언트의 요청을 2가지로 분리하여 구분
    /apps 의 URL로 접근하면 Dispatcher Servlet이 담당한다.
    /resources 의 URL로 접근하면 Dispatcher Servlet이 컨트롤할 수 없으므로 담당하지 않는다.
    이 방식은 상당히 코드가 지저분해지며, 모든 요청에 대해서 저런 URL을 붙여주어야 하므로 직관적인 설계가 될 수 없다.


    2. Dispatcher Servlet이 요청을 처리할 컨트롤러먼저 찾고, 요청에 대한 컨트롤러를 찾을 수 없는 경우에, 2차적으로 설정된 자원(Resource) 경로를 탐색하여 자원을 탐색.
    - 이렇게 영역을 분리하면 효율적인 리소스 관리를 지원할 뿐 아니라 확장에 대한 여지를 용이하게 해준다는 장점이 있다.


    3. 애플리케이션 요청을 탐색하고 없으면 정적 자원 요청으로 처리
    두번째 방법은 Dispatcher Servlet이 요청을 처리할 컨트롤러를 먼저 찾고, 요청에 대한 컨트롤러를 찾을 수 없는 경우에, 2차적으로 설정된 자원(Resource) 경로를 탐색하여 자원을 탐색하는 것입니다. 이렇게 영역을 분리하면 효율적인 리소스 관리를 지원할 뿐 아니라 추후에 확장을 용이하게 해준다는 장점이 있습니다.


    4. 예제
    - @Controller 어노테이션으로 컨트롤러로 설정
    - hello() 메서드는 @GetMapping("/hello") 어노테이션으로 "/hello" 경로에 대한 요청을 처리하는 메서드
    - hello를 반환하므로, Dispatcher Servlet은 View Resolver를 통해 hello뷰를 찾아 렌더링

  • 구조를 만든다는 의미 webapp 디렉토리 하위 resources 디렉토리(정적 파일들의 저장소)의 위치를 등록
  • /resources 경로로 들어오는 요청은 정적파일을 요구하는 것으로 스프링 MVC에서 처리하지 않는다는 의미


📌 예제 이어서

  1. servelt-context.xml : 요청 문서

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--요청 문서-->
    <!--1. 스프링 MVC 설정을 에너테이션 기반으로 처리하겠다 의미-->
    <!--스프링 MVC의 여러객체들을 자동으로 스프링빈으로 등록하겠다라는 선언-->
    <mvc:annotation-driven></mvc:annotation-driven>

   <!-- 2. 구조를 만든다는 의미 webapp 디렉토리 하위 resources 디렉토리(정적 파일들의 저장소)의 위치를 등록-->
    <!--/resources 경로로 들어오는 요청은 정적파일을 요구하는 것으로 스프링 MVC에서 처리하지 않는다는 의미-->
    <mvc:resources mapping="/resources/**" location="/resources/"></mvc:resources>

    <!--3. InternalResourceViewResolver 클래 : 스프링 MVC에서 제공하는 뷰를 어떻게 결정할 것인지 설정하는 담당하는 (객체)-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--prefix : MVC에서 사용했던 WEB-INF/view 경로-->
        <property name="prefix" value="/WEB-INF/views/"></property>
        <!--suffix : `.jsp` 확장자 지정-->
        <property name="suffix" value=".jsp"></property>
    </bean>
		<!--자동으로 빈 설정해줘라-->
    <context:component-scan base-package="com.multicampus.springex.controller"/>

   <!-- <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <bean class="com.multicampus.springex.controller.formatter.LocalDateFormatter"/>
                <bean class="com.multicampus.springex.controller.formatter.CheckboxFormatter"/>
            </set>
        </property>
    </bean>-->

    <!--<mvc:annotation-driven  conversion-service="conversionService" />-->

</beans>
  1. web.xml 수정
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--싱글톤 패턴형태로 등록-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml</param-value>
    </context-param>

    <!--감시자를 넣음-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--frontController를 쓰기 위해 서블릿 등록-->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--설정 정보, 위치값을 받아옴-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/servlet-context.xml</param-value>
        </init-param>

        <init-param>
            <param-name>throwExceptionIfNoHandlerFound</param-name>
            <param-value>true</param-value>
        </init-param>

        <!--톰캣 로딩할 때 필요한 서블릿을 먼저 로딩-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>encoding</filter-name>
        <servlet-name>appServlet</servlet-name>
    </filter-mapping>

</web-app>
  1. Controller 만들기 - SampleController
package com.multicampus.springex.controller;

import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller //스프링 MVC에서 컨트롤러 역할, 스프링의 빈(Bean)으로 등록
@Log4j2 //Lombok 라이브러리에서 제공하는 어노테이션으로, 로깅(loggin) 기능을 자동으로 구현해주는 기능을 제공
public class SampleController {
    @GetMapping("/hello") //Get방식으로 들어오는 요청(request)을 처리하기 위한 에너테이션
    public void hello(){
        log.info("hello~"); //이것을 사용하기 위해 @Log4j2 선언
    }
}
  1. hello.jsp 만들기 - servelt-context.xml에 있던 경로 및 만들어주기

<property name="prefix" value="/WEB-INF/views/"></property>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>FrontController가 응답</title>
</head>
<body>
<h1>FrontController가 응답합니다.</h1>
<br/>
</body>
</html>
  1. TodoController
  • @RequestMapping
    • "특정한 경로의 요청(Request)을 지정" 하기 위해 사용
    • 컨트롤러 클래스의 선언부 , 컨트롤러 메소드에 모두 적용 가능
    • 현재 클래스의 모든메서드들의 기본적인 URL 경로가 지정
    • 여러개의 컨트롤러를 하나의 클래스로 묶을 수 있고 각 기능을 메소드 단위로 설계할 수 있어서 실제개발을 할때 많은 양의 코드를 줄일 수 있구나~
package com.multicampus.springex.controller;

import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller //스프링 MVC에서 컨트롤러 역할, 스프링의 빈(Bean)으로 등록
@RequestMapping("/todo")
@Log4j2
public class TodoController {
    @RequestMapping("/list") //localhost:8090/todo/list
    public void list(){
        log.info("todo_lis.....");
    }

    //@RequestMapping(value="/register", method = RequestMethod.GET) //localhost:8090/todo/register
    @GetMapping("/register")
    /*제대로 불러오는지 확인하는 작업, 제대로 불러오면 콘솔에 뜬다. */
    public void register(){
        log.info("GET todo_register.....");
    }

    // register은 post와 get방식 따로 따로
    @PostMapping("/register")
    public void registerPost(){
        log.info("Post todo register");
    }
}
  1. SampleController 수정 - 기본값 넣어주기
    1. 다양한 파라미터 수집해서 처리


    2. 스프링MVC파라미터는 기본적으로 요청(request)에 전달된 파라미터 이름을 기준으로 동작


    3. 간혹 @GetMapping @PostMapping @RequestMapping(/경로) ==> 전달이 안되는 경우


    4. @RequestParame 파라미터로 사용된 변수의 이름과 전달되는 파라미터의 이름이 다른 경우 유용하게 사용


    5. @InitBinder
    - 파라미터 수집 = 바인딩
    - 변환이 가능한 데이터는 자동으로 변환해서 처리해야 하는 경우도 존재
    - ex1. 밑에랑 다른 방식으로도 가능

    1. @DateTimeFormat

  • Controller 작성 시 가장 편리한 기능
    • 파라미터가 자동으로 수집되는 기능
    • 이 기능을 이용하면 request.getParameter() 이용하는 불편함이 적어짐
    • 파라미터를 수집하는 방식은 파라미터 타입에 따라 자동으로 변환하는 방식

package com.multicampus.springex.controller;

import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.time.LocalDate;

@Controller //스프링 MVC에서 컨트롤러 역할, 스프링의 빈(Bean)으로 등록
@Log4j2 //Lombok 라이브러리에서 제공하는 어노테이션으로, 로깅(loggin) 기능을 자동으로 구현해주는 기능을 제공
public class SampleController {
    @GetMapping("/hello") //Get방식으로 들어오는 요청(request)을 처리하기 위한 에너테이션
    public void hello(){
        log.info("hello~"); //이것을 사용하기 위해 @Log4j2 선언
    }

    @GetMapping("/ex1") //ex1을 만들기 전에는 http://localhost:8090/ex1?name=geumjulee&age=20을 넣어주면 동작시
    public void ex1(String name, int age){
        log.info("ex1.....");
        log.info("name : "+name); //잘 받아졌다면 이것들이 출력 됨 geumjulee
        log.info("age : "+age); //age 20으로 받아짐
    }

    @GetMapping("/ex2")
    // exception 처리가 날 수 있으니 defaultValue로 default값 설정
    public void ex2(@RequestParam(name="name", defaultValue="CCC") String name,
                    @RequestParam(name="age", defaultValue="20") int age
                    ) {
        log.info("ex2.....");
        log.info("name : "+name);
        log.info("age : "+age);
    }

    // 날자값이 문자열로 들어왔을 떄 LocalDate로 알아서 변환해주기 위해 LocalDateFormatter
    @GetMapping("/ex3")
    public void ex3(LocalDate dueDate){
        log.info("ex3.....");
        log.info(dueDate);
    }
}
  1. LocalDateFormatter : ex3에서 나온 LocalDate 변환을 위한 클래스
package com.multicampus.springex.formatter;

import org.springframework.format.Formatter;

import java.text.ParseException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class LocalDateFormatter implements Formatter<LocalDate> {

    @Override
    public LocalDate parse(String text, Locale locale) throws ParseException {

        return LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    // format이라는 외부 처리 빈 생성 => servlet-context.xml에서 빈 연결
    @Override
    public String print(LocalDate object, Locale locale) {
        return DateTimeFormatter.ofPattern("yyyy-MM-dd").format(object);
    }
}
  1. servlet-context .xml 수정 : 빈을 위해 - 추가 부분
<!--Formatter를 servelt-context.xml에 적용하여 스프링의 빈으로 등록
    이 등록을 위해 FormattingConversionServiceFactoryBean객체를 스프링의 빈으로 등록-->
   <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <!--빈을 넣어줌-->
            <set>
                <bean class="com.multicampus.springex.formatter.LocalDateFormatter"/>
                <!--<bean class="com.multicampus.springex.controller.formatter.CheckboxFormatter"/>-->
            </set>
        </property>
    </bean>

<!--conversionService이라는 빈을 등록 후 스프링 MVC를 처리할 때 mvc:annotation-driven 설정 반드시 필요-->
    <mvc:annotation-driven  conversion-service="conversionService" />
  1. TodoDTO 만들기

package com.multicampus.springex.dto;

import lombok.*;

import java.time.LocalDate;

@ToString
@Data //setter, getter, equals(), toString()등 메서드 자동 생성
@Builder
// 모든 속성에 대한 아규먼트 처리
@AllArgsConstructor //public Todo(Long tno, String title){}을 만들어줌
@NoArgsConstructor //Default 생성자를 만들어줌
public class TodoDTO {

    private Long tno;

    private String title;

    private LocalDate dueDate;

    private boolean finished;

    private String writer;
}
  1. register.jsp 만들기

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>FrontController가 응답</title>
</head>
<body>
<form action="/todo/register" method="post" >
    <div>
        Title : <input type="text" name="title">
    </div>
    <div>
        DueDate : <input type="date" name="dueDate" value="2023-08-08">
    </div>
    <div>
        Writer : <input type="text" name="writer">
    </div>
    <div>
        Finished : <input type="checkbox" name="finished">
    </div>
    <div>
        <button type="submit">Register</button>
    </div>
</form>
</body>
</html>
  1. SampleController.java 수정
@GetMapping("/ex4")
    public void ex4(Model model){
        log.info("ex4.....");
        model.addAttribute("message", "Hello Spring project!");
    }

@GetMapping("/ex4_1")
    public void ex4Extra(@ModelAttribute("dto") TodoDTO todoDTO, Model model){
        log.info("ex4_1.....");
        log.info(todoDTO);
        model.addAttribute("message", "Hello Spring project!");
    }
  1. ex4 만들어주기

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1> ${message}</h1>
<br />
<h1><c:out value="${message}"></c:out> </h1>
</body>
</html>
  • 결과창 : 위에서 설정 해준 message 내용을 볼 수 있음

  1. ex4_1 만들어보기
  • 결과창

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1> ${dto}</h1>
<br />
<h1><c:out value="${message}"></c:out> </h1>
</body>
</html>
  1. SampleController.java 수정 - Redirect 이용
// ex5으로 들어가고 redirect로 해서 ex6으로 가게 됨
    @GetMapping("/ex5")
    public String ex5(RedirectAttributes redirectAttributes){
        // 객체로 처리하겠다. RESPONCE에 추가하는 작업
        redirectAttributes.addAttribute("name", "AACCCDDD");
        redirectAttributes.addFlashAttribute("result", "success");
        // 원하는 곳으로 이동
        return "redirect:/ex6";
    }
    @GetMapping("/ex6")
    public void ex6(){}

  1. ex6.jsp 만들기
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1> Ex6 RedirectAttributes 결과</h1>
</body>
<h1>${result}</h1>
</html>

회고

점점.. 공부해야하는 양은 많아지고 코드는 짧아지나, 어노테이션 공부할 게 많네 ㅠㅠㅠㅠ 와 근데 다이어트로 쓰는 인아웃 앱 공고냈네ㅠㅠㅠ node.js랑 타입스크립트... 꼭 스프링 끝내고 나중에 공부해서 도전 해본다..
트위터에 연결해뒀더니 조회수가 늘었다. 행복

profile
내 지식을 기록하여, 다른 사람들과 공유하여 함께 발전하는 사람이 되고 싶다. gitbook에도 정리중 ~

0개의 댓글