7/11 [RE] 스프링 MVC

박세현·2024년 7월 11일

Spring

목록 보기
7/15
post-thumbnail

스프링 MVC 시작하기

1. 스프링 MVC를 위한 설정

1) spring webmvc

(의존성에 의존성으로 스프링콘텍스트가 여기에 이미 포함되어 있다)

  • implementation 'org.springframework:spring-webmvc:6.1.10'



2) 자바 웹기술 의존성

  • servlet-api

    • compileOnly 'jakarta.servlet:jakarta.servlet-api:6.0.0'
  • servlet.jsp-api

    • compileOnly 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.1.1'
  • jstl-api

    • implementation 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.0'
  • jstl-impl (구현체)

    • implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.1'


3) 기타 의존성

  • tomcat jdbc(커넥션풀)

    • implementation 'org.apache.tomcat:tomcat-jdbc:10.1.25'
  • spring-jdbc

    • implementation 'org.springframework:spring-jdbc:6.1.10'
    • JDBC를 사용하여 데이터베이스와 상호작용
  • spring-data jdbc

    • implementation 'org.springframework.data:spring-data-jdbc:3.3.1'
    • CRUDRepository 인터페이스 : 애가 DAO역할, 마이바티스의 매퍼와 비슷
    • Spring의 JDBC 기능을 확장하여 데이터베이스 액세스를 간소화
    • ORM(객체-관계 매핑) 없이 직접 SQL을 작성하고 결과를 매핑
  • 참고) 이거보다는 jpa를 더 많이 사용한다함

  • mybatis

    • implementation 'org.mybatis:mybatis:3.5.16'
  • mybatis-spring

    • implementation 'org.mybatis:mybatis-spring:3.0.3'
  • ojdbc11

    • runtimeOnly'com.oracle.database.jdbc:ojdbc11:23.4.0.24.05'
    • Oracle 데이터베이스에 접속하기 위한 JDBC 드라이버로, Oracle 데이터베이스와 Java 애플리케이션 간의 연결을 관리

  • lombok

    • compileOnly 'org.projectlombok:lombok:1.18.34'

    • getter/setter 메서드, 생성자, toString 메서드 등 반복적인 코드 작성을 자동화

    • @Data : @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 한 번에 적용

    • @Builder : 빌더 패턴을 사용하여 객체를 생성

      import lombok.Builder;
      
      @Builder
      public class User {
          private String username;
          private String email;
          private int age;
      }
      
      // 사용 예시
      User user = User.builder()
                      .username("john_doe")
                      .email("john.doe@example.com")
                      .age(25)
                      .build();
      
    • @NoArgsConstructor // 기본 생성자

    • @RequiredArgsConstructor // final 필드와 @NonNull 필드를 위한 생성자

    • @AllArgsConstructor // 모든 필드를 위한 생성자

  • slf4j-api(로거)

    • implementation 'org.slf4j:slf4j-api:2.0.13'
  • logback classic(로거 구현체)

    • implementation 'ch.qos.logback:logback-classic:1.5.6'

  • spring-test

    • testImplementation 'org.springframework:spring-test:6.1.10'

예시) 톰캣



예시) 디스패쳐서블릿

  • 서블릿 1개만 설정함
  • 디스패쳐서블릿 : 모든 요청과 응답의 창구가 되는 서블릿
  • 디스패쳐 서블릿이 스프링 컨테이너를 만들어줌
  • init-param : 스프링 컨테이너 뭘로 할지 설정해주는거
  • AnnotationConfigWebApplicationContext : 웹 전용 스프링 컨테이너
  • config.MvcConfig : 설정클래스 - 웹mvc 설정 탑재됨 + 뭐를 객체로 만들지 설정하는 클래스



예시) 스프링 4버전 까지는 한글 인코딩깨지는 문제가 있음

(우리가 현재 사용하고 있는 서블릿 6버전은 안해도 ㄱㅊㄱㅊ 벗 옛날버전꺼도 알아야 하니 try try)

  • 필터매핑 : 필터가 적용되는 범위
  • CharacterEncodingFilter : 스프링에서 제공하는 필터



예시) MvcConfig : 설정클래스 생성

  • @EnableWebMvc
  • implements WebMvcConfigurer
  • 여기서 핸들러매핑, 핸들러어댑터, 뷰리졸브 세팅 다 해야함
    -> 귀찮아
    -> @EnableWebMvc : 여기에 핸들러매핑, 핸들러어댑터, 뷰리졸브 세팅 알아서 해 줌
  • 핸들러 매핑 : 컨트롤러를 찾고 못찾으면 다음으로 정적경로를 찾음

ㄴ 웹mvc설정관련된 메서드



예시) 멤버 컨트롤러 생성

ㄴ @Controller : 모든 요청이 오면 여기서 찾아서 실행

ㄴ 휴 연동됨ㅠㅠㅠㅠㅠㅠㅠㅠㅠ



예시) 뷰.jsp 생성



예시) 로거 설정

  • <root level="INFO"> : 디버그로 되어있는거 변경, 디버그는 너무 길게 나옴
  • <logger name="org.springframework.jdbc" level="TRACE" />
  • <logger name="org.choongang.member.mappers" level="DEBUG" />



예시) DBConfig : db설정

  • db설정 시 해줘야 할 것
    • @Configuration(설정클래스이다 알려주기)
    • db연결 + 커넥션풀 설정 = DataSource (DataSource안에 연결 설정이랑 커넥션풀 설정이 내재되어 있다)
      • (destroyMethod = "close") // 자원 해제
      • db 연결설정 : 드라이버 세팅, url 설정, 스키마배정
      • 커넥션풀 설정 : 연결이 유효한가 쳌, 처음 연결할 때 몇개 생성?할지
    • JdbcTemplate(마이바티스 할거면 이거 안해도 됨) : 스프링 컨테이너 안에 관릴객체로 넣어주기
    • PlatformTransactionManager (이거 뭐징)
    • SqlSessionFactory(마이바티스 설정)
package org.choongang.config;

@Configuration
@EnableTransactionManagement // 트랜잭션관련된 설정 자동화
@MapperScan("org.choongang") // 정의하는데로 다 추가
@EnableJdbcRepositories("org.choongang") // 빈으로 만듬 + 구현체도 알아서 생성
public class DBConfig extends AbstractJdbcConfiguration {

   @Bean(destroyMethod = "close") // 자원 해제
    public DataSource dataSource() {
       DataSource ds = new DataSource();
       /* DB 연결 설정 S */
       ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
       ds.setUrl("jdbc:oracle:thin:@localhost:1521:XE");
       //ds.setUsername("SPRING");
      ds.setUsername(System.getenv("db.username"));
      //getenv: 환경변수 조회
       //ds.setPassword("oracle");
      ds.setPassword(System.getenv("db.password"));
       /* DB 연결 설정 E */

       /* 커넥션 풀 설정 S */
       ds.setTestWhileIdle(true); // 유휴 객체 유효성 체크
       ds.setInitialSize(2);
       ds.setMaxActive(10);
       ds.setTimeBetweenEvictionRunsMillis(10 * 1000); // 10초에 한번씩 연결 상태 체크(기본값 5초)
       ds.setMinEvictableIdleTimeMillis(1000 * 60); // 유휴 객체(아무것도 하지 않고 있는 객체) 생존 시간 1분(기본값 1분, 안해도 되는데 걍 씀)
       /* 커넥션 풀 설정 E */

       return ds;
    }

   @Bean // 외부꺼라서 수동빈 등록해주어야함
   public JdbcTemplate jdbcTemplate() { // 마이바티스 슬꺼면 안해도 되긴 함
      return new JdbcTemplate(dataSource());
   }

   @Bean
   public PlatformTransactionManager transactionManager() {
      DataSourceTransactionManager tm = new DataSourceTransactionManager();
      tm.setDataSource(dataSource());

      return tm;
   }

   @Bean // 마이바티스 설정
   public SqlSessionFactory sqlSessionFactory() throws Exception {
      SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
      sqlSessionFactoryBean.setDataSource(dataSource());

      SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBean.getObject();
      return sqlSessionFactory;
   }

   @Bean
   public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) {
      return new NamedParameterJdbcTemplate(dataSource);
   }
}

ㄴ db연결 + 커넥션풀 설정 = DataSource

ㄴ JdbcTemplate(마이바티스 할거면 이거 안해도 됨) : 스프링 컨테이너 안에 관릴객체로 넣어주기
ㄴ PlatformTransactionManager (이거 뭐징)
ㄴ SqlSessionFactory(마이바티스 설정)

ㄴ 설정 추가



예시) 어제꺼 복붙



예시) TDD 설정

  • @SpringJUnitWebConfig
  • @ContextConfiguration(classes = MvcConfig.class)

ㄴ 이거 뭐냥



예시) 응답코드

  • HttpStatus
    • int value() : 응답코드 가져기

ㄴ 응답코드 관련된 이넘상수

ㄴ 이거 가지고 응답코드 가져올 수 있음

ㄴ 응답코드 체크 가능한 메서드?

ㄴ 응답코드 설정

ㄴ 응답코드 400으로 고정



예시) Spring Data Jdbc 설정

  • CRUDRepository 인터페이스 : 애가 DAO역할, 마이바티스의 매퍼와 비슷
    • @EnableJdbcRepositories("org.choongang") // 빈으로 만듬 + 구현체도 알아서 생성
    • extends AbstractJdbcConfiguration
    • @Bean
       public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) {
          return new NamedParameterJdbcTemplate(dataSource);
       }

https://docs.spring.io/spring-data/commons/docs/current/api/index.html

ㄴ 애 뭐하는 역할이더라



예시) DAO(CRUDRepository 인터페이스)

  • extends CrudRepository<엔티티자료형, 기본키 자료형>

ㄴ @NoArgsConstructor @AllArgsConstructor 추가(왜?)
ㄴ @id : 기본키를 명시해야 함
ㄴ 래퍼 클래스 Long으로 바꿔줌 왜?

ㄴ 이게 지네릭 클래스라서(지네릭에는 기본형자료형못들어감)

ㄴ 매개변수 : 엔티티 자료형, 기본키 자료형



예시) TDD(기본키 이용해서 CRUD)

- 조회

ㄴ 쿼리 안썻는데 자바코드로 셀렉트 해줌


- 등록 혹은 수정


- 삭제

ㄴ 조회
ㄴ 옵셔널이 왜있지?
ㄴ 없는 값을 조회할 때 용이라는데 모르것,,,
ㄴ 파인드바이 아이디 반환값 : 옵셔널 형태

ㄴ 조회됨
ㄴ 애는 _사용시 자동으로 카멜케이스로 바꿔줌
= resultMap 따로 필요 없다ㅏㅏ



예시1) 기본키 아닌걸로 CRUD + 쿼리메서드 (where절)

쿼리 메서드 조건식 패턴
https://github.com/yonggyo1125/curriculum300H/blob/main/6.Spring%20%26%20Spring%20Boot(75%EC%8B%9C%EA%B0%84)/17~20%EC%9D%BC%EC%B0%A8(21h)%20-%20%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/Spring%20Data%20JPA/4.%20%EC%BF%BC%EB%A6%AC%20%EB%A9%94%EC%84%9C%EB%93%9C.md

- 조회

ㄴ 조회할 때 where절이 없어...

ㄴ 기본키가 아닌 이메일 이용해서 crud
ㄴ 쿼리메서드
ㄴ find(select)
ㄴ by (조건, where)
find + (엔티티 이름) + By + 변수이름

ㄴ 쿼리메서드통해 where절 극복



예시2) 쿼리메서드(Like 절)



예시3) 쿼리메서드

ㄴ 넘 길어...가독성 떨어져서 이렇게는 잘 사용안함
ㄴ 그래서 간단한 쿼리만 쿼리메서드 사용함



예시) @Query 애노테이션(복잡한 쿼리 직접 작성)

ㄴ 나중에는 이것도 안쓴다...(직접 쿼리 작성하는거는 위험하기 때문 현재는 지원해주는 기능 없음...하)
ㄴ 스프링jpa에선 알아서 쿼리를 써준다...



예시1) 페이징

  • Pageable - 인터페이스
  • PageRequest - Pageable의 구현체
    • 반환값 : Page 자료형

Interface Pageable
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/Pageable.html

Class PageRequest
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/PageRequest.html

ㄴ 생성자가 protected
ㄴ of() : 거의다 객체를 만드는 것

ㄴ 1,2번 메서드를 가장 많이 사용
ㄴ 매개변수 : ???, 한 페이지당 보여줄 갯수, sort(정렬 = order by)
ㄴ of : 거의다 객체를 만드는 것
ㄴ 페이지 번호는 0부터 시작

ㄴ 표준쿼리(11버전은 오류날거라고...)



예시2) 페이징

ㄴ 한페이지당 3개씩 조회

예시3) 페이징 : 매개변수 2개

Interface Page<T>
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/Page.html

ㄴ 쿼리가 2번 실행 됨



예시4) 페이징 : 매개변수 3개

- 매개변수 3번째 : sort(order by)

ㄴ 오더 : 솔트의 정적내부 메서드
ㄴ 너무길다

ㄴ import해서 코드 줄이기

ㄴ 2차 정렬 추가함

ㄴ order by 쿼리가 추가된 모습



예시) 클래스명과 DB테이블명이 다른경우

  • 데이터 클래스에 @Table("DB테이블명") 라고 명시하기

ㄴ DB테이블명 이렇게 알려주기



예시) 칼럼명이 변수명과 다른경우

  • 데이터 클래스에 @Column("...") 라고 명시하기



2. 스프링 MVC 프레임워크 동작 방식

  • 요청(/hello) -> DispatcherServlet -> HandlerMapping -> 컨트롤러 빈(스프링 컨테이너) -> HandlerAdapter -> 컨트롤러 빈 -> 실행 -> ModelAndView

  • HandlerAdapter : 컨트롤러 빈의 종류가 다양하기 때문에 맞춰서 실행하기 위한 목적
    • @Controller, Controller 인터페이스의 구현체, HttpRequestHandler 인터페이스 구현체

  • ModelAndView
    • Model : View에서 사용할 데이터(EL 속성으로 추가된 데이터), 리퀘스트 범위임
      • addAttribute(키, 값)
      • addAllAttribute(Map...)
        • Attribute : 속성
    • View : 출력 템플릿 경로 정보

참고) 커맨드 객체 : 요청 쪽 데이터를 자동 매핑

참고) request.setAttribute = model.addAttribute


예시) ModelAndView

  • Model = 뷰에서 사용할 데이터

ㄴ 속성 : 이름과 값 형태
ㄴ 범위는 리퀘스트와 똑같음
ㄴ 기존방식은 request.setAttribute로 함
ㄴ request.setAttribute = model.addAttribute



예시) 정적경로

  • 핸들러매핑 -> 요청에 맞는 컨트롤러빈을 찾아줘 // 애노테이션 보고 겟매핑, 포스트매핑...
    -> 못찾으면 정적경로설정한걸로 들어가서 찾아봄
  • 주로 정적경로는 resources파일에 정의
    • 정적인것 : css, javascript ...

1) **

  • /board/** -> /board 경로의 모든 파일과 하위 경로를 포함한 모든 파일
    • /board/list.jsp ⭕
    • /borad/sub/list.jsp ⭕

2) *

  • /board/* -> /board 경로의 모든 파일
    • /board/list.jsp ⭕
    • /board/sub/list.jsp ❌

3) ?

  • /m?01 -> 바뀔 수 있는 부분 정의 할 때 사용
    • /ma01 ⭕
    • /mb01 ⭕
    • /m101 ⭕

ㄴ 정적경로 여기다 정의할거임
ㄴ css, 자바스크립트 이런데서 찾아야 함...?
ㄴ 정적인거는 주로 여기에 정의함

ㄴ addResourceHandlers : 메서드 오버라이딩




3. 정리

1) DispatcherServlet

: 요청과 응답의 창구 역할을 하는 서블릿 클래스

  • 스프링 컨테이너 생성


2) HandlerMapping

: 요청 방식 + 주소 -> 스프링 컨테이너에 있는 컨트롤러 빈을 검색



3) HandlerAdapter

: 형태가 다양한 컨트롤러 빈(@Controller, Controller 인터페이스, HttpRequestHandler 인터페이스) -> 실행 -> ModelAndView로 반환

  • 요청메서드의 반환값이 String 이지만 -> HandlerAdpter에서 실행시 ModelAndView 객체로 변환

참고) ModelAndView

  • addAttribute(String name, String value) : EL 속성으로 추가되는 속성
  • setViewName(...) : 뷰 경로


4) ViewResolver

: ModelAndView 정보 -> 출력을 위한 View 객체 검색




4. 요청 처리에 대한 편의 기능 제공

  • 요청 데이터의 이름과 동일한 매개변수를 요청 메서드에 정의하면 자동으로 주입
  • 정의한 변수의 자료형으로 자동 형변환
  • 요청 데이터의 이름과 요청 메서드에 정의한 이름이 다른 경우
    • @RequestParam("요청 데이터의 이름")
    • required : true(기본값) : 요청 파라미터의 필수




요청 데이터

  • GET : ?이름=값&이름=값
  • POST : 요청 바디 이름=값&이름=값
		HttpServletRequest 
			String getParameter(String name)
			String[] getParameterValues(String name);
profile
귤귤

0개의 댓글