1 쿼리문

load data local infile 'C:/Users/JY/Desktop/1data.csv'
into table location 
fields terminated by ';'
lines terminated by '\n'
ignore 1 rows;​

2 데이터 (핵심)

     1) 아래 데이터는 구분자가 ;(세미콜론) 인데, 보통은 ,(콤마)로 되어 있다.

     2) 그리고 인터넷에 검색하면, 끝나는 구분자 '"' 를 제거하는 부분도 있는 데, 그게 필요한지 안한지는 csv 파일의 데이터를 보고 판단해야하기 때문에 적절히 쿼리문을 바꾸어 주어야한다.

 

3 데이터 넣는 것에 성공 시 다음과 같다

http://happinessoncode.com/2019/04/06/java-cipher-algorithm-mode-padding/

 

Java Cipher - 알고리즘, 운용 모드, 패딩의 이해

자바에서는 대칭키 알고리즘을 사용하여 데이터를 암호화/복호화할 때 javax.crypto.Cipher 클래스를 사용한다. 이 클래스의 인스턴스는 정적 메서드인 Cipher.getInstance()를 호출하여 가져올 수 있는데,

happinessoncode.com

 

암호화를 배운적이 없다보니, 상당히 난해하다. 설명은 못하겠고, 참고한 소스는 위의 링크에 있으며, 설명이 잘되있다.

 

1. 암호화 후 복호화 불가능한 암호화가 있고, 복호화 가능한 암호화가 있다.

2. 복호화하여 쓸 필요가 있어 복호화가 가능한 라이브러리를 찾아보니 AES256이 있다.

 

누가 만들어놓은 것을 가져온거라서 자세한 내용은 잘 모른다.

 

volatile 이라는 키워드라던가, synchronized 라던가 암호화 라이브러리에서 특히 많이 보이는 것 같던데 관련 부분을 읽어봐도 잘 이해는 안된다.

 

큰 과정은 이렇고, 비밀키가 노출이 되면 안된다.

1. 암호화 : 평문 + 비밀키 -> 암호문

2. 복호화 : 암호문 + 비밀키 -> 평문

 

 

 

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Component;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;

@Component
public class AES256Crypto {
	
	/*32 bit key : 32 �ڸ�*/
	final static String secretKey = "123kjasaldkvnasdlfqwerdfadsfasda";
	
	/*volatile : �޸𸮿� ������ �ε�*/
	private static volatile AES256Crypto INSTANCE;
	
	/*IV option : 16bit*/
	static String IV = "";
	
	/* ��ü �ν��Ͻ� �������� */
	public static AES256Crypto getInstance() {
		if(INSTANCE == null) {
			synchronized (AES256Crypto.class) {
				if(INSTANCE == null) {
					INSTANCE = new AES256Crypto();
				}
			}
		}
		return INSTANCE;
	}
	
	private AES256Crypto() {
        IV = secretKey.substring(0, 16);
    }
	
	public String encryptAES256(String plainText) 
			throws NoSuchAlgorithmException, 
			NoSuchPaddingException, 
			InvalidKeyException, 
			InvalidAlgorithmParameterException, 
			IllegalBlockSizeException, 
			BadPaddingException,
			UnsupportedEncodingException {
		byte[] key = secretKey.getBytes();
		SecretKey secretKey = new SecretKeySpec(key, "AES");
		
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(IV.getBytes()));
		
		byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
        String enStr = new String(Base64.encodeBase64(encrypted));
        
		return enStr;
	}
	
	public String decryptAES256(String encryptedText) 
			throws NoSuchAlgorithmException, 
			NoSuchPaddingException, 
			UnsupportedEncodingException, 
			IllegalBlockSizeException, 
			BadPaddingException, 
			InvalidKeyException, 
			InvalidAlgorithmParameterException {
		
		byte[] keyData = secretKey.getBytes();
        SecretKey secureKey = new SecretKeySpec(keyData, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secureKey, new IvParameterSpec(IV.getBytes("UTF-8")));
        byte[] byteStr = Base64.decodeBase64(encryptedText.getBytes());
        return new String(cipher.doFinal(byteStr), "UTF-8");
	}
}

쿠키 생성


1. 쿠키를 만드는 법은 아래 처럼 javax.servlet.http.Cookie 클래스 객체를 생성한 후, 인스턴스 생성시에 쿠키의 이름이 되는 "key" 값과, 쿠키의 값이되는 "value"를 넣어준다.

Cookie cookie = new Cookie("key", "value");

 

2. 1번의 과정만으로는 쿠키가 http 통신을 통해 생성되거나 전달되지 않는데, HttpServletRequest 객체에 실어서 전달해야 브라우저에 쿠키가 생성이 된다. 

HttpServletResponse response;
response.addCookie(new Cookie("key", "value"));

 

쿠키 읽기


1. 쿠키 읽는 방법

HttpServletRequest request;
request.getCookie();

for(int i = 0; i < this.cookies.length; i++) {
			if(cookies[i].getName().equals(name)) {
				return cookies[i].getValue();
			}
}

request 객체로 부터 getCookie() 메서드를 이용해서, Cookie[] 타입의 배열을 리턴 받아서 저장한다.

따라서, for 문에 돌아가는 cookies는 Cookie[] cookie 로 선언 된 객체다. 

배열이기 때문에, cookies[i].getName() 을 통해 모든 쿠키의 이름을 얻어 올 수 있고, cookies[i].getValue()를 통해 값을 얻을 수 있다.

 

 

 

 

필요해서 만든 클래스


: 반복적으로 사용해야하니 좀 더 사용하기 편하게 클래스를 만들어 보았다

: 쿠키로 저장할 때, bearer 토큰을 저장해야하는 작업이 있어서, AES256 으로 암호화 하여, 저장했다가, 서버에서 처리할 때, 쿠키를 읽어서 복호화 하는 반복되는 작업에 유용할 것 같아서 만들었다.

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

public class CookieUtil {
	
	private Cookie[] cookies;
	private Cookie cookie;
	
	public CookieUtil() {
		// TODO Auto-generated constructor stub
	}	
	// 객체 생성시에 request 객체를 받는 경우
    // 쿠키이름으로 쿠키 값을 얻을 때!
	public CookieUtil(HttpServletRequest request) {
		this.cookies = request.getCookies();
	}
		
    // 쿠키이름으로 쿠키 값을 얻는 메소드
	public String getValue(String name) {
		
		for(int i = 0; i < this.cookies.length; i++) {
			if(cookies[i].getName().equals(name)) {
				return cookies[i].getValue();
			}
		}
		return null;
	}
    
    // 쿠키 추가하는 메서드
	public CookieUtil addCookie(String key, String value) {
		this.cookie = new Cookie(key, value);
		return this;
	}
	
 	// 쿠키 추가후에 쿠키 만료일을 체이닝하는 메서드
	public CookieUtil setExpire(int period) {
		this.cookie.setMaxAge(period);
		return this;
	}
	
    // 쿠키 추가후에 HttpOnly 옵션을 체이닝하는 메서드
	public CookieUtil setHttpOnly(boolean setHttpOnly) {
		this.cookie.setHttpOnly(setHttpOnly);
		return this;
	}
	
    // 쿠키 생성을 마칠 때, 쿠키를 리턴하는 메서드
	public Cookie build() {
		return this.cookie;
	}
}

 

: 사용 예시

response.addCookie(cookieUtil.
						addCookie("refreshToken", refreshToken).
						setHttpOnly(true)
						.setExpire(60 * 60 * 8).build()
						);

ResponseEntity 로 api호출을 리턴 받은 후, getBody() 메서드로 json 데이터를 받았다.

JSONObject jsonObject = (JSONObject) jsonParser.parse(responseEntity.getBody());

 

이 때, jsonObject에서 get() 메서드로 해당 키 값을 주면, 값을 얻어 올 수 있다.

String result = (String) jsonObject.get("키 값");

 

만약, 해당 키 값이 json 배열형태라면, JSONArray를 사용해야하는데,

JSONArray jsonArray = (JSONArray) jsonObject.get(" jsonarray 에 해당하는 key 값");

JSONArray 에 담기면, key value 가 같이 ArrayList 형태로 담기는 데 다시, jsonArray에서 한개씩 꺼내어서 파싱해야한다.

 

"jsonkey" : [key: value] , [key: value] 이런 형태의 데이터가 있다면,

jsonParser를 통해서 jsonObject에 담으면, 해당 key 내부에 있는 배열 모두를 하나의 value 로 인식하여 들어가고,

JSONArray 에 jsonObject를 담으면, JSONArray index 첫번째, 두번째에 각각 [key : value] , [key : value] 형태로 담긴다.

 

 

 

 

 

빈 (Bean)


  • Spring IoC 컨테이너가 관리하는 자바 객체를 빈(Bean)이라고 함
  • 따라서, new 객체() 는 객체라고 부르지 빈(Bean) 이라고 부르지 않음
  • ApplicationContext.getBean() 으로 얻어질 수 있는 객체

빈 등록 방법


@Component 이 사용된 클래스들이 스캔되고, Bean으로 등록 된다.

@ComponentScan 이 사용된 패키지 이하의 모든 클래스 중에 @Component 가 사용된 클래스가 Bean으로 등록이 된다.

'Spring Framework > Annotation' 카테고리의 다른 글

[Spring] Annotation "@"  (0) 2021.01.05

Kakao Developers 페이지에서 가져온 내용

https://developers.kakao.com/docs/latest/ko/kakaologin/common

 

정리

1) 카카오 계정과 어플리케이션을 연결하고, 토큰을 발급 받아서 사용자를 해당 어플리케이션에 로그인 시킨다.

2) Access Token : 카카오 API 호출 권한 부여 토큰

   -> 로그인을 통해 발급

3) Refresh Token : Access Token 갱신

4) 해당 토큰으로 사용자정보를 얻은 다음 DB에 따로 가입처리를 해주어야함

 

인증 과정

 

정리

1) 인증서버에서 제공할 로그인 페이지 필요

2) 토큰을 생성 해주고 전달해주어야함

3) 구현해보려면, OAuth 2.0 서버의 사용자 DB / 어플리케이션 서버의 DB 이렇게 별도로 사용자 데이터베이스 필요

'API > OAuth2.0' 카테고리의 다른 글

OAuth 2.0 ?  (0) 2021.06.21

 

내 생각

 

   OAuth 2.0 서버를 만들어 보려는 이유는 인증서비스 제공이 어떻게 이루어지는지 이해해보려고 함이다.

요즘 없는 곳이 없는 카카오 소셜로그인 처럼 API 문서를 따라해보면, 나의 어플리케이션과 연동하는 것은 그리 어렵지않다.

 

하지만, 반대로 내가 인증서비스(OAuth 2.0) 서버를 구축하여, 서비스 제공자의 역할을 좀 더 자세히 알고 싶어서이다.

 


 

 

검색 해본 것

https://ko.wikipedia.org/wiki/OAuth

 

위키에서 OAuth를 검색해보니 관련 용어가 있어서 가져왔다.

 

  평소에 작업하면서 쓰는 용어는 인증 제공자로써 Service Provider 대신 IDP라고 쓰고, 위키에서 소비자라고 쓰는 부분은 어플리케이션 서비스 제공자로써 SP라고 쓰고 있어서 좀 헷갈리긴한다


OAuth에 관련된 용어들을 간략히 설명한다.

  • 사용자(user): 서비스 제공자와 소비자를 사용하는 계정을 가지고 있는 개인 -> 카카오계정 이용자
  • 소비자(consumer): Open API를 이용하여 개발된 OAuth를 사용하여 서비스 제공자에게 접근하는 웹사이트 또는 애플리케이션 -> 소셜로그인 연동을 하려고하는 개발자가 관리하는 웹사이트 또는 어플
  • 서비스 제공자(service provider): OAuth를 통해 접근을 지원하는 웹 애플리케이션(Open API를 제공하는 서비스)    -> 카카오 
  • 소비자 비밀번호(consumer secret) : 서비스 제공자에서 소비자가 자신임을 인증하기 위한 키 -> 내가 카카오와 서비스를 연동했다라는 인증키
  • 요청 토큰(request token) : 소비자가 사용자에게 접근권한을 인증받기 위해 필요한 정보가 담겨있으며 후에 접근 토큰으로 변환된다. -> 내 어플리케이션은 너희 카카오 인증서비스와 연결이 되있으니, 이 사용자가 카카오로그인을 성공하고나면 그 응답으로 인증받았다는 증거를 달라
  • 접근 토큰(access token) : 인증 후에 사용자가 서비스 제공자가 아닌 소비자를 통해서 보호된 자원에 접근하기 위한 키를 포함한 값.

 

정리

서비스 개발자가 카카오 인증과 연동을 해놓으면, 사용자는 카카오계정을 통해 로그인이 가능해진다.

로그인을 하면, 카카오 인증서버는 응답으로 토큰을 발행하고, 그 토큰으로 사용자가 인증을 받았다고 간주하고, 자신의 서비스에 로그인을 시킨다. 이 사용자에 대한 권한 관리는 별도로 어플리케이션에서 해주겠지만 인증주체가 외부에 있다는 것이 특징인것 같다.

 

 

 

'API > OAuth2.0' 카테고리의 다른 글

OAuth 2.0 인증 과정  (0) 2021.06.21

프로그래머스에 해쉬 문제 풀다가 조합공식에 넣을 중복되는 원소 갯수 체크하는 방법이 필요했음.

 

샘플 데이터의 카테고리 (headgear, eyewear) 별로 원소 갯수.

String str[][] = 
     {
     {"yellowhat", "headgear"}, 
     {"bluesunglasses", "eyewear"}, 
     {"green_turban", "headgear"}
     };

HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
        for(String[] str : clothes) {
        	hashMap.put(str[1], hashMap.getOrDefault(str[1], 0) + 1 );
        }
        System.out.println(hashMap);
        
        
for(Entry<String, Integer> str : hashMap.entrySet())
        {
        	System.out.println("value : " + str.getValue());
        }

 

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>compile</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <!-- myBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>2.7.0</version>
        </dependency>-->
        <!-- Test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

src/main/resource

user-mapper.xml (매퍼 , mapper namespace는 null 이 될 수 없음)

<?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="notEmpty">

</mapper>

 

src/main/mybatis-config.xml (마이바티스 config)

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>

    </configuration>

 

applicationContext.xml (DB 설정/ sqlSessionFactory / sqlSessionTemplate 설정)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- MariaDB 설정 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/todoapp?characterEncoding=UTF-8" />
        <property name="username" value="root" />
        <property name="password" value="1234" />
    </bean>

    <!-- Mapper 설정
        mapper 경로는 value = src/main/resources 폴더의 하위 경로를 작성 -->
    <!-- value는 값을 지정 ref는 이미 지정한 값을 가져오는 것 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:/config/mybatis/mybatis-config.xml" />
        <property name="mapperLocations" value="classpath*:/config/mybatis/mapper/*-mapper.xml" />
    </bean>

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
</beans>

1) web.xml 파일에 <context-param> 의 <param-value>에 내용을 추가함

DataSource DB 연결정보 / Mybatis 설정을 위한 mybatis-mapper.xml 추가

/WEB-INF/config/spring/application-datasource.xml  (DB)

/WEB-INF/config/mapper/mybatis-mapper.xml (mybatis)

<?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/applicationContext.xml
            /WEB-INF/config/spring/application-datasource.xml <!-- DB 설정 위치 -->
            /WEB-INF/config/mapper/mybatis-mapper.xml <!-- MyBatis Mapper 위치 -->
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>/WEB-INF/view/Login/main.jsp</welcome-file>
    </welcome-file-list>
</web-app>

 

2) pom.xml 변화 (마이바티스, mysql 커넥터, inject 애너테이션 사용가능하게 하는 라이브러리 등 추가) 

 	<!-- 롬복 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.18</version>
            <scope>provided</scope>
        </dependency>
        <!-- 마이바티스 라이브러리-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.2</version>
        </dependency>
        <!-- 마이바티스 : 스프링 라이브러리 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.0</version>
        </dependency>

        <!-- mysql 커넥터-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>

        <!-- 스프링 jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>

        <!-- 아파치 dbcp -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>2.8.0</version>
        </dependency>

        <!-- @inject 사용을 위한 -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

3) application-datasource.xml (spring xml을 생성하고 빈만 설정해주면 됨) - Mysql

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

    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/todoApp?characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="1234"/> </bean>
</beans>

 

 

4) mybatis-mapper.xml (spring 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:jdbc="http://www.springframework.org/schema/jdbc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!-- <property name="mapperLocations" value="classpath:/mapper/sql/*_SQL.xml" /> -->
    </bean>
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSession"/>
    </bean>
</beans>

sqlSession 이름으로 빈을 생성하고, 클래스는 SqlSessionFactoryBean 객체를 사용

프로퍼티이름은 dataSource 이며, dataSource Bean을 참조한다.

 

sqlSessionTemplate 이름으로 빈 생성, 클래스는 SqlSessionTemplate을 사용한다.

 

5) 아직 Mybatis를 사용하는 설정을 적용하지 않은 상태이며, DB 연결만 테스트를 해본 코드임

package com.todoapp.Login.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.inject.Inject;
import javax.sql.DataSource;
import java.sql.Connection;

@RestController
public class Login {

    @Inject
    private DataSource dataSource;

    @RequestMapping("/login")
    public String login()
    {
        try
        {
            Connection conn = (Connection) dataSource.getConnection();
            System.out.println("성공 : " + conn);
        }
        catch(Exception e)
        {
            System.out.println("실패 !");
            e.printStackTrace();
        }
        return "";
    }
}

6) 성공 메세지가 나옴

 

이걸로 몇일을 헤메다가 결국 이까지 해결하긴 했지만, 각각이 무엇인지 정확하게 이해한 것이 아니라서, Mybatis SQL 매핑하는 것까지 해보고 동작하는 과정을 자세하게 찾아보아야겠음.

 

설정하는 것이 이번에 총 세번째인데 할 때마다 다른 에러로 문제를 겪는 기분

 

 

2021 / 02 / 20 : 02:00 ~ 05:30  

> resources 적용이 안되는 문제로 고민

> 해결안되서 DB부터 설치

 

 

1. docker 설치 (windows / linux)에 맞게

2. 설치 된 후 docker 명령어로 mysql을 설치할 것 임

3. 원하는 버전을 설치하기 위해서는 태그 정보를 입력해주어야한다.

4. 아래에 5.6 5.7 같은게 버전이고, 큰 제목엔 지원하는 태그라고 되어 있다.

hub.docker.com/_/mysql

 

5. 그러면, 5.7 버전을 설치 해볼 것인데, 다르게말하면, mysql 이미지를 저장소에서 가져오겠다. 라는 뜻이다

 그 저장소 역할을 해주는 것이 docker hub 이며, repository (저장소)라고 한다.

 

6. 윈도우 기준으로 docker 설치가 되어 있다는 가정하게 설명을 적음.  명령은 똑같기 때문에 상관이 크게 없다.

 

7. cmd 창을 열고, docker라고 입력해보면, 명령어가 쫙 나열이 된다. 도커가 제대로 설치된 것이다.

8. 이미지를 다운받는 명령어는 다음과 같다

docker pull [options] name[:tag|@digest]

ex) docker pull mysql 이렇게만 입력해도 다운 받을 수 있다. 그러나, 이렇게 입력하면, 자동으로 태그는 latest 즉 최신 버전을 받아오게 된다. 그러한 이유 때문에 다음과 같이 입력해본다.

 

9. docker pull mysql:5.7

 

10. 이미지를 받는데 성공했다.

 

11. docker-compose 를 사용해서 서비스를 올릴 것이다.

원하는 경로에다 docker-compose.yml 파일을 만든다.

아래 내용을 적어놓고, 실행만 시켜주면되는데,

손봐야할 설정은

    MYSQL_ROOT_PASSWORD= 원하는 비번

    MYSQL_DATABASE=데이터베이스 이름

    ports: - 3307:3306 설정방법은 3307은 접속포트, 3306은 컨테이너 내부 포트이므로, 3307만 다른것으로 수정해주고, DB 접속시에 해당 IP+PORT로 접속하면된다.

    

volumes: 옵션에 

    로컬경로:이미지내부 경로 (db 데이터를 저장하기 위함이며, 이미지가 내려가면, 데이터가 날아가기 때문임)

    요즘 잘쓰지 않지만, CD-ROM과 비슷하다. CD-ROM에 있는 게임을 하다가, 세이브 데이터가 로컬에 없으면, CD-ROM은 기록이 불가능하기 때문에 다날아간다.

 

version: "3.7" # 파일 규격 버전
services: # 이 항목 밑에 실행하려는 컨테이너 들을 정의 ( 컴포즈에서 컨테이너 : 서비스 )
  db: # 서비스 명
    image: mysql:5.7 # 사용할 이미지
    restart: always
    command: --lower_case_table_names=1
    container_name: mysql5.7-test # 컨테이너 이름 설정
    ports:
      - "3307:3306" # 접근 포트 설정 (컨테이너 외부:컨테이너 내부)  <- 컨테이너 내부는 무조건 3306
    environment: # -e 옵션
      - MYSQL_DATABASE=todo
      - MYSQL_ROOT_PASSWORD=1234  # MYSQL 패스워드 설정 옵션
      - TZ=Asia/Seoul

    command: # 명령어 실행
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    volumes:
      - D:\mysql:/var/lib/mysql # -v 옵션 (다렉토리 마운트 설정)

12. 위파일이 만들어진 경로로 이동해서 docker-compose up -d 명령어로 실행시켜주거나, -d 명령은 빼고 실행해도된다. -d 옵션은 백그라운드다. 

 

13. 접속하면 이렇게 보인다.

 

 

egloos.zum.com/springmvc/v/504151

 

@MVC와 DispatcherServlet에 대해서

이전 장까지 MyBatis와 커넥션풀의 활용, 그리고 트랜잭션에 대해 상세히 알아보았습니다. 개인적으로 이 정도의 환경이라면 소, 중형 서비스 구축에는 문제없을 정도로 환상적인 제작환경이 구

egloos.zum.com

web.xml 수정
<url-pattern>/</url-pattern> 으로 수정
<?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">

    <!--ContextLoaderListener 등록 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- DispatcherServlet 등록 -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- DispatcherServlet 에 매핑 -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 한글처리 -->
    <filter>
        <filter-name>encodingFilter</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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

 

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

    <!-- Spring DispatcherServlet 장점
        기존엔 web.xml 에서 url 매핑을 전부 등록 해주었으나,
        DispatcherServlet이 해당 어플리케이션으로 들어오는 모든 요청을 핸들링해준다.
    -->
    <!-- 컨트롤러 찾기, 핸들러 매핑, 뷰 리졸버 셋팅 -->
    <annotation-driven/>
    <context:component-scan base-package="User.Controller"></context:component-scan>
    <context:component-scan base-package="User.*"></context:component-scan>

    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

</beans:beans>

 

applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 서비스, 레포지토리 설정 -->
</beans>
1. [Add Configuration] - 클릭

2. [+] 누른 후 - Tomcat Server - Local 선택

3. Port 지정 - [8090]

4. Deployment - Application context 설정 

이 설정은 URL : http://localhost:8090/{여기 주소를 말한다}

5. 연필 모양 눌러서 편집

6. Web Application: Archive

7. 실행 - 초록색 화살표 버튼

8. 결과

Maven Repogitory 은 "라이브러리" 저장소 입니다.

Maven 은 프로젝트에 필요한 라이브러리를 관리하기 편하게 프로젝트 구조를 잡아줍니다

 

1. 앞서 생성된 프로젝트를 [우클릭] - [Add Framework Support] 

2. [Maven] 체크 -> [OK] 

3. 폴더 및 파일 몇 개 추가가 되었습니다.

java 폴더에는 Java 파일을 생성하여 코딩하고,

resources 는 그 외의 파일들을 넣어서 관리합니다.

pom.xml 은 maven 저장소에서 라이브러리를 받아오기 위해 작성하는 XML 형식의 문서입니다.

 

4. 프로젝트 구조 설정 (project Structure) - [FILE] - [Project Structure]

[Mark as] :  폴더 모양을 눌러서 src 폴더를 아래 처럼 설정해줍니다.

 

1. [File] - [New] - [Project]

2. [Spring] - [v] Spring -> [Next] (그림에 빠졌으나 Spring MVC 선택할 것)

3. Project name : 이름 정하기 -> [FINISH]

4. 프로젝트 생성 완료

 

[Project] 와 [Module] 개념

Eclipse에서는 workspace 에 한개의 프로젝트를 생성하여 작업한다.

그러나, Intellij 에서는 Module 이라는 개념이 한 가지가 더 있다.

 

모듈당 한개의 프로젝트를 생성하여 하나의 윈도우 화면에서 여러개의 프로젝트를 관리할 수 있다.

 

[Eclipse]
workspace - Project A
[Intellij]
workspace
         - Module A - Project1
         - Module B - Project2
         - Module C - Project3

 

 

 

 

 

 

 

pom.xml

<!-- json bind -->
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.1</version>
</dependency>

 

servlet-context.xml

<beans:bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"

 

@ResponseBody
@RequestMapping(생략...)
public Map returnJson(@RequestBody HashMap<String, String> map)
{
	//@RequestBody로 JSON형식을 받을 수 있고
    for(Entry<String, String> entry : map.entrySet())
    {
    	System.out.println(String.format("key: %s, val: %s", entry.getKey(), entry.getValue()));
    }
    //결과를 여러개 담으려면?
    List<Map<String, String>> allrst = new ArrayList<Map<String,String>>();
    
    //첫번째 결과 생성
    Map<String, String> eachrst = null;
    eachrst = new HashMap<String, String>();
    eachrst.put("name", "홍길동");
    eachrst.put("age", "10");
    
    //첫번째 결과를 리스트에 저장
    allrst.add(eachrst);
    
    //두번째 결과 생성
    eachrst = new HashMap<String, String>();
    eachrst.put("name", "김길동");
    eachrst.put("age", "11");
	
    //두번쨰 결과 리스트에 저장
    allrst.add(eachrst);

	//@ResponseBody로 JSON형식을 리턴해줄 수 있다.
    Map<String, Object> result = new HashMap<String, Object>();
    result.put("result", allrst);    
    
    return result;
}

 

javascript 에서 비동기통신으로 요청 예


function test()
{
	fetch(url, {
    	method:"POST",
        headers:{
			"Content-Type" : "application/json;charset=utf-8"        
        },
        body: JSON.stringify({
        	전달 파라미터1 : 값,
            전달 파라미터2 : 값,
        })
    })
    .then(resp => resp.json())
    .then(function(res){
    	//요청한 응답을 res 파라미터로 리턴받음
    	var rst = res.result; //res의 첫 노드 이름이 result. 컨트롤러에서 arraylist 를 저장한 키
		
        //하나씩 꺼내는 방법
        rst.forEach(function(items){
			console.log("이름 : " + items.name + "\n나이 : " + items.age);
            
        })
    })
    .catch(err => console.log(err));
}

 

1. @RequestParam("파라미터") String id

    

    public String example (@RequestParam("id") String id)

   

    요청 : url?id=홍길동

    System.out.println(id); //홍길동

 

2. @RequestBody HashMap<String, String> map 으로받는 방법

    public String example(@RequestBody HashMap<String, String> map)

 

    요청 : url?id=홍길동&age=1&today=20210107

for(Entry<String, String> entry : map.entrySet())
{
	System.out.println(String.format("key: %s, val: %s", entry.getKey(), entry.getValue()));
}

key:  id val: 홍길동

key:  age  val: 1

key: today val: 20210107

1. Map 자료형에 값을 넣고, foreach 문으로 값을 출력하는 예시

Map<String, String> map = null;
map.put("이름", "홍길동");
map.put("나이", "1세");




		

Map 자료형은 <key, value>의 쌍으로 이루어진 자료형이다.

Map 객체에 put메서드를 이용하여, map.put("이름", "홍길동"); 으로 값을 객체에 넣을 수 있다.

중복을 허용하지 않는다. 정확히는 값의 중복이 아니라 "key" 값의 중복을 허용하지 않기때문에 같은 키 이름으로 다른값이 들어가면, 마지막에 들어간 값으로 덮어쓰기 된다.

 

2. 들어 있는 값을 출력하는 방법에는 여러가지가 있다.

     

// 01. entrySet()
for (Map.Entry<String, String> entry : map.entrySet()) {
		System.out.println(String.format("key : %s , value : %s", entry.getKey(), entry.getValue()));
}

// 02. keySet()
for(String key : map.keySet()){
	System.out.println("key : " + key + ", val : " + map.get(key));
}

// 03. entrySet.iterator()
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while(it.hasNext()){
	Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();
    System.out.println("key : " + entry.getkey()+ ", val : " + entry.getValue());
}

//04. KeySet().iterator
Iterator<String> it = map.keySet().iterator();
while(it.hasNext()){
	System.out.println("key : " + it.next() + ", val : " + map.key(it.next()));
}

'JAVA' 카테고리의 다른 글

array to ArrayList  (0) 2020.07.28
[JAVA] - 자바 Email 전송하기  (0) 2019.12.26
[JAVA] window builder - login  (0) 2019.11.18
[JAVA] WINDOW BUILDER  (0) 2019.11.18
[JAVA] 읽으면서 정리하기  (0) 2019.11.10