반응형

* 이동욱 저자의 스프링 부트와 AWS로 혼자 구현하는 웹서비스 교재 참고

1. 개요

 - JPA란?

 - H2란?

 - JPA 및 H2 설정 및 연동

 - Junit을 사용한 JPA CRUD 테스트

 

2. JPA란?

 - DB 처리를 쿼리 매핑(ex: ibatis, mybatis)이 아닌 객체 매핑으로 처리할 수 있도록 하는 기술

 - ORM (Object Relational Mapping) 기반

 - 기본적인 CRUD(Create, Read, Update, Delete) 메서드 자동 생성

 

3. H2란?

 - 인메모리 관계형 데이터베이스

 - 별도의 설치가 필요 없이 프로젝트 의존성만으로 관리가 가능

 - 메모리에서 실행되기 때문에 애플리케이션을 재시작할 때마다 초기화됨 (테스트용으로 많이 사용)

 

4. JPA 및 H2 의존성 설정 (build.gradle)

1
2
compile('org.springframework.boot:spring-boot-starter-data-jpa'//스프링 부트용 Spring Data Jpa 라이브러리
compile('com.h2database:h2'//h2 라이브러리
cs

 

5. JPA 설정 및 예제

 5.1. 도메인 설정 (Posts.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Getter
@NoArgsConstructor
@Entity
public class Posts{
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(length = 500, nullable = false)
    private String title;
    
    @Column(columnDefinition = "TEXT", nullable = false)
    private String content;
    
    private String author;
    
    @Builder
    public Posts(String title, String content, String author) {
        this.title = title;
        this.content = content;
        this.author = author;
    }
}
cs

- @NoArgsConstructor : 클래스에 대한 기본 생성자 메서드 생성

- @Entity : 테이블과 링크될 클래스를 지정하는 어노테이션이며, 언더스코어 네이밍으로 테이블 이름을 매칭

  (ex : PostsManager > posts_manager table)

 

- @Id : PK 필드

 

- @GenerateValue(strategy = GenerationType.IDENTITY) : 자동 인덱스 생성 설정

 

- @Column : 테이블의 컬럼을 나타내며 필요 옵션 추가 시 length, nullable, columnDefinition 등을 사용

  > null을 허용하지 않고 길이가 500인 title 컬럼을 생성 

  > null을 허용하지 않고 TEXT 타입인 content 컬럼을 생성

  > 필드에 Column 어노테이션을 붙이지 않아도 기본적으로 컬럼이 생성됨

 

- @Builder : 해당 클래스의 빌더 패턴 클래스 생성

  > build 패턴 사용시 보다 명시적인 객체 생성이 가능 (PostTestRepository.java 코드의 21번째 줄 참고)

 

 5.2. JpaRepository 설정 (PostsRepository.java)

1
2
3
public interface PostsRepository extends JpaRepository<Posts, Long>//Entity 클래스, PK 타입
 
}
cs

- extends JpaRepository<Entity.class, PK Type> : 기본적인 CRUD 메서드를 지원하는 Repository 인터페이스 생성

 > JpaRepository : DB Layer 접근자를 의미

 > Entity 클래스와 해당 Entity Repository는 같은 패키지에 위치해야함.

 

6. H2 설정 (src/main/resources/application.properties)

1
2
3
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.h2.console.enabled=true
cs

- spring.jpa.show-sql=true : 콘솔 내에서 쿼리 로그를 확인할 수 있도록 하는 설정

- spring.jpa.properties.hibernate.dialect : H2 형태의 쿼리 로그를 MySQL 버전으로 변경

- spring.h2.console.enabled=true : h2 웹 콘솔 사용 허용 (localhost:port/h2-console 으로 접속 가능)

 

7. Junit 테스트 (PostsRepositoryTest.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@RunWith(SpringRunner.class)
@SpringBootTest //별다른 설정없이 SpringBootTest를 사용할 경우 H2 데이터 베이스를 자동으로 실행
public class PostsRepositoryTest {
 
    @Autowired
    PostsRepository postsRepository;
    
    //After : 테스트 단위가 끝날때마다 수행되는 메서드를 지정하는 어노테이션
    @After
    public void cleanup() {
        postsRepository.deleteAll();
    }
    
    @Test
    public void 게시글저장_불러오기() {
        
        String title = "테스트 게시글";
        String content = "테스트 본문";
        
        //builder 클래스를 통해 생성자 생성 후 save (insert/update)
        postsRepository.save(Posts.builder()
                                .title(title)
                                .content(content)
                                .author("sksim@gmail.com")
                                .build());
        
        List<Posts> postsList = postsRepository.findAll();
        Posts posts = postsList.get(0);
        assertThat(posts.getTitle()).isEqualTo(title);
        assertThat(posts.getContent()).isEqualTo(content);
    }
}
cs

- @SpringBootTest : H2 데이터 베이스 자동 실행 

 

- postsRepository.save() : posts 테이블에 insert/update 쿼리 실행

  > id 값이 있다면 update, 없다면 insert

 

- postsRepository.findAll() : posts 테이블에 있는 모든 데이터를 조회

 

- assertThat, isEqualTo : assertJ에서 지원하는 테스트 메서드

 

8. H2 콘솔 접속 방법

 8.1. localhost:port/h2-console 을 입력하여 H2 웹 콘솔 접속 및 JDBC URL 입력 후 Connect

H2 웹 콘솔 접속 정보 입력

 

 8.2. DB 접속 및 Entity 객체와 매핑된 테이블 확인

H2 웹 콘솔 접속 성공

  * Junit 테스트 시 11번째 줄의 deleteAll()을 주석처리하면 posts 테이블에 데이터가 들어가는 것을 확인할 수 있음

반응형
반응형

* 이동욱 저자의 스프링 부트와 AWS로 혼자 구현하는 웹서비스 교재 참고

 

1. 개요

 - 롬복 설치 및 롬복을 사용하여 Dto 객체를 생성한다.

 - 테스트용 controller를 생성한다.

 - Junit을 통해 테스트한다.

 

2. 롬복 설치 및 이클립스 연동

 2.1. 롬복 설치 (gradle)

org.projectlombok:lombok 추가

  - gradle에 롬복 의존성을 추가하여 라이브러리를 다운받는다.

 

 2.2. 롬복 실행

  - 라이브러리가 다운받아졌으면 롬복이 설치된 경로(gradle Home)로 이동한다.

  - 그 후 관리자 권한으로 cmd를 실행한 후 jar파일을 실행한다.

롬복 설치 경로

 2.3. STS 연동

  - 롬복 install 창이 뜨면 Specify location 을 선택하여 STS 실행파일을 선택 후 install /Update 를 클릭한다.

   * 여기서 access 에러가 뜬다면 cmd를 관리자 권한으로 실행하면 된다.

롬복 연동

 2.4. STS 연동 완료

  - 다음과 같은 창이 출력되면 설치 및 연동이 완료된 것이다.

  - STS 및 이클립스를 실행중이라면 재시작 시 적용된다.

연동 완료

3. HelloController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.ssk.springboot.web;
 
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
 
import com.ssk.springboot.web.dto.HelloResponseDto;
 
@RestController
public class HelloController {
 
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
    
    @GetMapping("/hello/dto")
    public HelloResponseDto helloDto(@RequestParam("name"String name, @RequestParam("amount"int amount){
        return new HelloResponseDto(name,amount);
    }
}
 
 
cs

 - @RestController : Json을 반환하는 컨트롤러로 만든다. @ResponseBody를 메서드마다 선언했던 것과 동일하다.

 - @GetMapping : Get 방식을 지원한다.

 - @RequestParam : request 파라미터를 가져온다.

 

4. HelloResponseDto.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.ssk.springboot.web.dto;
 
import lombok.Getter;
import lombok.RequiredArgsConstructor;
 
@Getter
@RequiredArgsConstructor
public class HelloResponseDto {
 
    private final String name;
    private final int amount;
}
 
cs

 - @Getter : 선언된 필드에 대해 Getter를 자동 생성한다.

 - @RequiredArgsConstructor : final로 선언된 필드가 포함된 생성자를 생성한다.

   > HelloResponseDto(String name, String amount) 라는 생성자가 내부적으로 생성된 것이다.

 

5. HelloControllerTest 클래스 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@RunWith(SpringRunner.class//스프링 실행자를 JUnit 내에 저장된 실행자와 함께 실행
@WebMvcTest(controllers = HelloController.class// Mvc Test에 사용하는 어노테이션, 테스트 컨트롤러 리스트에 HelloController를 추가
public class HelloControllerTest {
    
    @Autowired
    private MockMvc mvc; //mvc 테스트용 객체
    
    @Test
    public void hello가_리턴된다() throws Exception{
        String hello = "hello";
        mvc.perform(get("/hello")) //hello로 get 통신
            .andExpect(status().isOk()) //200인지 검사
            .andExpect(content().string(hello)); //response 값이 hello 인지 검사
        
    }
    
    @Test
    public void helloDto가_리턴된다() throws Exception{
        String name = "hello";
        int amount = 1000;
        
        mvc.perform(get("/hello/dto")
                .param("name", name)
                .param("amount"String.valueOf(amount)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.name", is(name)))
                .andExpect(jsonPath("$.amount", is(amount)));
    }
}
cs

 - @RunWith(SpringRunner.class) : 스프링 테스트에 필요한 스프링 실행자인 SpringRunner를 실행시킨다.

 - @WebMvcTest(controllers = HelloController.class) : 스프링 MVC 테스트에 사용하는 어노테이션이다. 테스트 controller로 HelloController를 지정했다.

 - mvc.perform(get("/hello")) : hello로 get요청을 보낸다. perform 메서드는 메서드 체이닝이 지원되며 andExpect 같은 검증 메서드와 함께 사용한다.

 - param("name",name) : 요청 파라미터 값을 추가한다. 단 String 형태만 허용되기 때문에 amount 값을 변환했다.

 - jsonPath : Json 응답값을 필드별로 검증할 수 있는 메서드이다. $를 기준으로 필드명을 명시한다. 

 

6. Junit 실행을 통한 테스트

Junit 실행

 - @Test 어노테이션이 붙은 메서드의 테스트가 정상적으로 실행됨을 확인할 수 있다.

 

 

반응형
반응형

1. 개요

 - gradle 프로젝트를 생성한다.

 - build.gradle을 작성하여 의존성을 주입한다.

 

2. Gradle 프로젝트 생성

 2.1. new / Spring Starter Project 선택

Spring Starter Project

 2.2. 프로젝트 초기 설정 입력

프로젝트 초기 설정 입력

 - Type을 Gradle, Java Version을 8로 선택 및 프로젝트 초기 설정 입력 후 Next를 선택한다.

 

2.3. 스프링 부트 프로젝트 설정

스프링 부트 프로젝트 설정

 - Web / Spring Web을 선택하고, Spring Boot Version은 임의로 2.4.4를 선택한다. 스프링 부트 버전은 build.gradle에서 수정이 가능하다.

 

 2.4. gradle 프로젝트 생성 완료

프로젝트 구조

 - 다음과 같은 구조로 프로젝트가 생성되었다.

 

3. build.gradle 작성

 

 3.1. build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
buildscript{
    ext{
        springBootVersion = '2.1.7.RELEASE'
    }
    repositories{
        mavenCentral()
        jcenter()
    }
    dependencies{
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
 
group = 'com.ssk'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
 
 
repositories{
    mavenCentral()
}
 
dependencies{
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}
cs

 - build.gradle 파일은 말 그대로 gradle을 통해 빌드될 수 있도록 하는 설정파일이다.

 - 프로젝트 기본 설정, 의존성 주입, 플러그인, 레포지토리 설정 등의 정보가 들어있다.

 - ext는 전역변수를 설정하겠다는 의미이며, 10번째 라인을 보면 스프링 부트 그레들 플로그인의 2.1.7.RELEASE를 의존성으로 받겠다는 의미이다.

 - repositories는 저장소를 의미하며, mavenCentral은 메이븐 중앙 레포지토리, jcenter는 mavenCentral 저장소의 문제점을 개선한 레포지토리이다. 일반적으로 위처럼 이 두가지 저장소 정보를 넣어준다.

 - dependencies는 의존성을 추가하는 부분이다.

 - 13 ~ 16 라인의 플러그인들은 자바와 스프링을 사용하기 위한 필수 플러그인들이므로 필히 추가해야 한다.

 

 3.2. build.gradle 실행

build.gradle 실행

 - build.gradle 우클릭 / Gradle / Refresh Gradle Project를 선택하여 build.gradle을 실행한다.

 - 정상적으로 실행되었다면 프로젝트 라이브러리에 의존성이 추가된 것을 확인할 수 있다.

 

4. 에러 리포트

 4.1. could not run phased build action using connection to gradle distribution 에러

 

 첫번째 솔루션. project / properties / Gradle / 설정 변경

 - Gradle user home 및 java home 경로를 명시적으로 기입해준다.

 

 두번째 솔루션. build.gradle 소스 문제

  - 위 문제로도 해결이 되지 않아 코드 확인 중 plugin 관련 코드를 sourceCompatibility 아래에 적어놨던 것을 뒤늦게 확인했다. plugin 코드들을 sourceCompatibility 하위에 적어뒀다면 위 예제처럼 위로 올리면 해결된다.

반응형
반응형

1. 개요

 어느 날, 갑자기 SQLTimeoutException 에러가 특정 요청에서 간헐적으로 발생했다. 정확히는 월의 첫날 0시 00분부터 발생했다.

 

2. 오류 내용

### The error occurred while setting parametersSQLTimeoutException: ORA-01013: 사용자가 현재 작업의 취소를 요청했습니다.

 

3. 분석

 SQLTimeoutException 에러는 말 그대로 SQL 쿼리를 실행하기 위해 DB로 요청 후 wait Time을 초과하여 발생한 에러이다. 오라클 서버가 비지한 상태(ex - 배치)에서 DB 처리 요청이 들어간 것이다.

 하지만 위 시스템 내에 DB 요청 후 기다리는 wait Time이 따로 설정되어 있지 않았고, 요청을 보냈을 당시 DB에서 처리가 되지 않아 sqlTimeoutException을 떨군 것이었다.

 

mybatis의 설정파일에 waitTime의 기능을 하는 defaultStatementTimeout 설정을 추가해주었으며 코드는 다음과 같다.

1
2
3
    <settings>
        <setting name="defaultStatementTimeout" value="30"/> 
    </settings>
cs

 

4. 특이사항

 개발 서버에 위 현상이 발생하였다. 특정 쿼리에서만 발생하는 것 같아 mybatis 설정파일에서 defaultStatementTimeout을 세팅하지 않고 매퍼 파일 안에 다음과 같이 넣어주었다. 이렇게 하면 해당 쿼리에 대해서만 timeout 값이 적용된다. 방법은 아래와 같다.

1
<select id="id" parameterType="java.util.HashMap" resultType="test.dto" timeout = "60">
cs

하지만 작업을 진행하다보니 동일 문제가 발생하는 쿼리가 더 확인됐고, mybatis 설정파일에 defaultStatementTimeout을 설정하였다. 하지만 계속 sqlTimeoutException이 발생하였다.

db 관련 설정을 모두 확인해도 이상한점은 없었다.

이전처럼 매퍼 파일 안에 timeout을 설정했다.

된다!

 

이에 대한 원인 파악을 위해 구글링을 해 보았으나 찾지못했다.

혹시나해서 매퍼에 입력한 timeout값을 모두 지워보았다.

된다!!

 

결론.

timeout 값을 매퍼 파일 안에 각각 입력해줄경우 defaultStatementTimeout 값이 먹히지 않는다.

만약 defaultStatementTimeout 이 일하지 않을 경우 매퍼에 설정한 timeout값을 모두 지우자.

 

찾아보니 timeout값은 덮어씌워진다고한다. 그리고 간헐적으로 timeout값이 적용되는 것 같다.. 정확한 원인을 다시 찾아보도록 하겠다.

 

 >> 일반적인 mybatis 구조에서는 defaultStatementTimeout 이 적용되나, 필자가 맡은 프로젝트는 사내 플랫폼 기반 안에 mybatis가 접목된 구조라 해당 설정이 적용이 되지 않는다고 한다. 아마 플랫폼 코어 내에 특정 부분에서 mybatis에 대한 설정을 덮어씌우는 구간이 있는 것으로 추정된다.

 

결론

 모두 다 적용시키려면 defaultStatementTimeout를, 특정 쿼리 ID에만 적용시키려면 timeout을!

반응형
반응형
반응형

1. 개요

 maven 프로젝트에 스프링 시큐리티를 적용하던 도중, 특정 bean이 주입되지 않아 NullPointException 에러가 발생했다. 참고로 해당 Bean은 xml 설정파일을 통해 등록된 상태였다.

 결론부터 말하면 문제가 발생한 Bean(SqlSession)은 WebApplicationContext로 설정되어있었고, 해당 Bean을 호출하는 Bean(SpringSecurity)은 RootApplicationContext로 설정되어 있어서 발생한 문제였다.

그렇다면 RootApplicationContext, WebApplicationContext 는 무엇이며, 어떻게 이와같이 설정이 나뉘게된 것일까?


2. RootApplicationContext와 WebApplicationContext 

2.1. RootApplicationContext

말 그대로 최상위 ApplicationContext이다.WebApplicationContext의 부모 Context이며 자식에게 자신의 설정을 공유한다. 단, 자신은 자식인 WebApplicationContext의 설정에 접근하지 못한다.

 

2.2. WebApplicationContext

Servlet 단위의 ApplicationContext이다. RootApplicationContext의 자식 Context이며, 부모인 RootApplicationContext의 설정에 접근할 수 있다.

 

아래 이미지가 이를 잘 설명해주고 있다.

출처 : https://howtodoinjava.com/spring-mvc/contextloaderlistener-vs-dispatcherservlet/

 

나의 경우 스프링 시큐리티 관련 객체에서 SqlSession을 Autowired 받아 DB 조회를 하는 로직을 구현하였는데, 스프링 시큐리티 설정은 RootApplicationContext으로, SqlSession은 WebApplicationContext로 설정했었다.

 

즉, RootApplicationContext에서 WebApplicationContext에 있는 Bean인 SqlSession을 주입하려고 했던 것이다. 당연히 접근이 되지 않아 주입이 되지 않았고, NullPointException이 발생했던 것이었다.

 

그렇다면 어떤 설정이 RootApplicationContext와 WebApplicationContext로 나누게 한 것일까? 그게 바로 ContextLoaderListener이다.


3. ContextLoaderListener

ContextLoaderListener는 RootApplicationContext를 생성하는 클래스이다.

빨간 블록안에 contextConfigLocation 설정파일을 읽어 RootApplicationContext를 생성한다.

 

참고로 파란색 블록안에 contextConfigLocation 설정파일을 읽어 생성되는 것이 WebApplicationContext이다.

web.xml

 즉, applicationContext.xml과 security-context.xml을 로드하여 RootApplicationContext를 생성하고,

 servlet-context.xml과 mybatis-context.xml을 로드하여 WebApplicationContext를 생성했다.

 결과적으로 스프링 시큐리티 관련 bean은 rootApplicationContext에, sqlSession bean은 WebApplicationContext에 설정되었으며, 스프링 시큐리티 서비스 객체(rootApplicationContext)에서 sqlSession(WebApplicationContext)를 Autowired 하지 못해 발생한 문제였다.

 

 

ContextLoaderListener 설정으로 인해 의존 주입이 되지 않아 발생한 에러임을 확인하고 ContextLoaderListener에 대해 포스팅하려고 했으나, 오히려 이 부분에 대한 설명이 적은 것 같아 아쉽다. ㅠㅠ

 

반응형
반응형

1. 개요

 jenkins 자체에서 war파일을 만드는 것은 성공하였으나, 이 war 파일을 tomcat 서버에서 실행 시키는 과정에서 에러가 발생하고 있다. 에러 문구는 다음과 같다.

 

 Deployed application at context path /context but context failed to start instead of the expected "OK" message

 .....

 Build step 'Deploy war/ear to a container' marked build as failure

 

 확인결과 war파일을 tomcat container에 Deploy 하는 과정에서 에러가 발생하고 있음을 알 수 있고, 정확한 원인은 톰캣 로그를 확인해야 한다.

 

2. 확인

 Deploy 과정에서 발생한 로그를 확인해봐야 한다. 배포 과정의 로그가 담긴 tomcat 경로/logs/catalina.log를 확인하여 에러 코드를 확인해보았다.

 확인 결과 다음과 같은 에러 로그를 확인할 수 있었다.

 Unsupported major.minor version 52.0

 오우오우.. 빌드하려는 프로젝트의 컴파일 버전은 1.8(52.0)이나 tomcat에서는 그보다 낮은 jdk 버전으로 빌드를 시도하여 위 에러가 발생하였다. 즉, jdk 1.8은 지원안해요~ 이뜻이다.

 

3. 해결

 (tomcat마다 뭔가 설정을 해주지 않는 한) tomcat은 일반적으로 시스템 변수의 JAVA_HOME을 사용한다.

 시스템 변수의 JAVA_HOME을 직접 들어가서 확인해보면 낮은 버전의 JDK 버전이 설정되어 있을 것이다.

시스템 환경변수의 JAVA_HOME

 이를 jdk 1.8 버전으로 수정하면 된다.

 올바르게 수정됐는지 확인하고 싶다면 pc 재부팅 후 javac -version 명령어를 입력해보면 된다.

javac -version

 

반응형
반응형

1. 개요

 Jenkins와 tomcat 연동 및 빌드 과정에서 다음과 같은 에러가 발생했다.

 Server returned HTTP response code: 401 for URL ~~

 

2. 확인

 401 에러는 자격인증 실패 에러이다. 쉽게 말게 인증이 실패한건데, 로그를 자세히 보니 The username and password you provided are not correct 라는 문구가 보였다.

3. 해결

 jenkins 설정의 빌드 후 조치 / Deploy war/ear to a container 항목에 Contatiners를 새로 추가해주었다.

자격인증 추가

 

add 선택 후 Username와 Password를 설정한다.

자격인증 추가

Username와 Password를 모르겠다면 tomcat경로의 conf/tomcat-users.xml 파일에 기입된 username과 password를 입력하면 된다. 만약 주석처리 되어 있을 경우 다음과 같이 새로 추가해준다.

tomcat-user.xml

4. 결과

 해당 에러는 발생하지 않으며 정상 빌드됨을 확인할 수 있다.

반응형
반응형

1. 개요

 jenkins 에서 빌드 도중 다음과 같은 경고가 나타났다.

 1) Using platform encoding (MS949 actually) to copy filtered resources, i.e. build is platform dependent!

 2) File encoding has not been set, using platform encoding MS949, i.e. build is platform dependent!

 

2. 원인

 maven 빌드 시 인코딩 타입을 따로 지정하지 않아 발생한다.

 

3. 해결

 pom.xml에 노란색으로 표시된 프로퍼티를 추가한다.

 

반응형
반응형

1. 개요

 젠킨스와 github 연동 이후 webhook을 통해 자동 build를 테스트하고 있던 도중 다음과 같은 에러가 발생했다.

build error

 

2. 환경

 jenkins

 window 10

 tomcat 8.0.x

 

3. 해결

javax.servlet.http 는 tomcat 경로의 lib 폴더 안에 servlet-api.jar 에 존재한다.

tomcat을 설정하는 부분은 있으나 빌드하는 과정에서 해당 jar 파일을 못 읽어온다고 가정하고 maven에 servlet-api.jar 의존성을 추가하였다.

sevlet-api 추가

그 후 다시 빌드를 하니 해당 오류가 발생하지 않고 빌드가 성공했다는 메시지를 받을 수 있었다.

반응형
반응형

1. 개요

 서버에서 API 통신이나 HTTP 통신에 대한 응답 값으로 Json 형식의 문자열 데이터가 오는 경우가 있다. 이때 데이터의 특정 key에 해당하는 값에 접근하기 위해 String 클래스에서 제공하는 메서드를 사용할 수도 있으나, 데이터가 복잡해지고, Node 가 많아질 수록 데이터 조작 및 접근에 한계를 느끼게 된다.

 이를 해소할 수 있는 방안으로 문자열 데이터를 JsonObject로 변환하는 방식이 있다. 이를 사용해보자.

 

2. 로직

 간단한 구조에서는 아래 4가지만 기억하면 된다. 

 

 1) String 형식의 JSON 문자열

 2) JSONParser

 3) To Object

 4) To JSONObject

 

 위 4가지를 기억하고 아래 코드를 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    public static void jsonTest() throws ParseException{
        //1. Json 문자열
        String strJson = "{\"userId\":\"sim\", "
                        + "\"userPw\":\"simpw\","
                        + "\"userInfo\":{"
                            + "\"age\":50,"
                            + "\"sex\":\"male\""
                            + "}"
                        + "}";
        
        //2. Parser
        JSONParser jsonParser = new JSONParser();
        
        //3. To Object
        Object obj = jsonParser.parse(strJson);
        
        //4. To JsonObject
        JSONObject jsonObj = (JSONObject) obj;
        
        //print
        System.out.println(jsonObj.get("userId")); //sim
        System.out.println(jsonObj.get("userPw")); //simpw
        System.out.println(jsonObj.get("userInfo")); // {"sex":"male","age":50}
 
    }
cs

 1) Json 문자열을 준비한다. (3 line)

  - API를 통해 받아왔다고 가정하고 String 형식의 userId, userPw와 Object 형식의 userInfo 데이터를 준비한다.

  - Json 형식은 {key:value} 형식이며, key값은 큰따옴표(")로 묶여있다. Parser 는 이 큰따옴표를 통해 파싱 처리를 하기 때문에 키 값에 \" 문자열을 추가해주었다.

 

 2) JSONParser (12 line)

  - 문자열을 Json 형식에 맞게 Object로 파싱할 수 있는 Parser를 생성한다. 

 

 3) To Object (15 line)

  - jsonParser를 통해 Json 문자열을 Object 형식으로 파싱한다.

 

 4) To JSONObject (18 line)

  - Object 형식의 데이터를 JSONObject 형식으로 형변환한다.

 

3. 테스트 결과

 JSONObject 형 객체를 통해 String, Object 등의 모든 Json 형식의 데이터에 접근할 수 있다.

반응형

+ Recent posts