// @Setter : setter 함수를 만들어주는 어노테이션
// @Getter : getter 함수를 만들어주는 어노테이션
// @ToString : toString 재정의 함수 자동으로 만들어주는 어노테이션
// @AllArgsConstructor : 모든 속성을 가진 생성자 자동 정의 어노테이션
먼저 실습을 하기 위해 아래와 같이 폴더를 구성합니다.
com.example.controllerexam 폴더 아래에 model 폴더를 생성합니다.
📂 model > Member.java
package com.example.controllerexam.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Setter
@Getter
@ToString
@AllArgsConstructor
public class Member {
// TODO : 속성, 생성자 함수(getter/setter)
String id; // 회원 id
String name; // 회원 이름
}
Lombok 어노테이션을 사용함으로써 코드가 간결해집니다.
📂 ObjectParamController.java
package com.example.controllerexam.controller.exam04;
import com.example.controllerexam.model.Member;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* packageName : com.example.controllerexam.controller.exam04
* fileName : ObjectParamController
* author : GGG
* date : 2023-10-05
* description : @ModelAttribute : 객체 형태로 변환하는 어노테이션
* 요약 :
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-10-05 GGG 최초 생성
*/
@Controller
@RequestMapping("/exam04")
public class ObjectParamController {
// TODO : URL TEST ) http://localhost:8000/exam04/object-param?id=junyeoke&name=lee
// @ModelAttribute : 객체의 속성명으로 jsp로 각각 전달
// Member 클래스의 속성명 == url의 매개변수명 : id, name
@GetMapping("/object-param")
public String getObjectParam(
@ModelAttribute Member member){
return "exam04/object_param.jsp";
}
}
@ModelAttribute는 사용자가 요청시 전달하는 값을 오브젝트 형태로 매핑해주는 어노테이션입니다.
Spring Boot는 2.7.16 버전 선택 -> jdk 11버전과 호환성이 좋음 // 최신 버전이면 3.x.x 버전을 선택하시면 됩니다.
Artifact 이 부분만 수정하면 됩니다.
Packaging은 War 선택
Java는 jdk 버전에 따라 선택해주시면 됩니다.
💡 스프링부트 라이브러리 추가
주로 사용하는 라이브러리 입니다. 그 외에는 프로젝트를 진행하면서 추가할 수 있습니다.
라이브러리를 추가하면 오른편에 세 가지가 추가된 것을 볼 수 있습니다.
generate 버튼을 누르면 압축파일로 다운로드가 됩니다.
다운받은 압축파일을 작업 폴더에 풀어주신후 인텔리제이로 프로젝트를 열어줍니다.
인텔리제이 내에서 다운로드가 실행됩니다. (시간 소요)
💡 프로젝트 구성
HelloworldApplication 은 메인함수가 있는 실행 클래스입니다.
💡 JSP 라이브러리 추가
✅ build.gradle 추가
스프링부트에서 JSP 라이브러리 추가 지원이 종료되어 수작업으로 라이브러리를 추가해주어야 합니다.
build.gradle를 찾아 더블클릭합니다.dpendencies 부분에 라이브러리를 수작업으로 추가해줍니다.
dependencies {
// jsp 라이브러리 추가
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper' // 추가
implementation 'javax.servlet:jstl' // 추가
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
그림에 표시된 아이콘을 눌러야 라이브러리 추가가 완료됩니다.
💡 MVC 디자인 패턴을 이용한 Java 코딩
설정파일을 담을 config 폴더와 MVC 디자인 패턴중 C인 controller 부분을 만들 폴더를 생성합니다.
컨트롤러는 일종의 tv리모컨 역할을 한다고 생각하면됩니다.
✅ JSP를 위한 설정파일
JSP를 위한 설정파일을 생성합니다.
설정파일은 config 폴더에 생성합니다.
package com.example.helloworld.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* packageName : com.example.HelloSpringBoot.config
* fileName : WebMvcConfig
* author : kangtaegyung
* date : 2023/07/29
* description : JSP 설정 파일
* 요약 :
* @Configuration : 어노테이션, 자바파일에 환경설정 기능 부여
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2023/07/29 kangtaegyung 최초 생성
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
}
✅ controller 만들기
실습을 위한 HelloWorldController 파일을 생성합니다.
파일은 controller 폴더에 생성합니다.
✔ Controller 어노테이션 추가
클래스 위에 @Controller 어노테이션을 추가해줍니다.
@Controller
public class HelloWorldController {
@GetMapping("/exam00/hello")
public String Hello(Model model){
return "/exam00/hello.jsp";
}
}
✅ 프로퍼티파일에 환경설정 값 추가
한글깨짐 방지를 위해 파일 인코딩을 UTF-8로 설정합니다.프로퍼티 파일안에 아래의 코드를 입력합니다.
# 서버 포트
server.port=8000
# jsp 파일 경로
spring.mvc.view.prefix=/WEB-INF/views/
# jsp 파일 확장자 정의
#spring.mvc.view.suffix=.jsp
# 자바 소스 수정시 자동 재시작
spring.devtools.restart.enabled=true
2) 새 프로젝트에서 이름을 지정하고 경로를 적절한 위치에 지정 하고 JDK는 11버전 Java도 11버전
패키지 생성은 War 파일로 지정하고 다음을 눌러줍니다.
3) dpendencies를 지정해줍니다. 스프링부트 버전은 2.7.16 으로 라이브러리는 사진과 같이 3개만 체크하고 생성합니다.
프로젝트 생성이 완료된 상태
✅ UTF-8 설정 : 한글 깨짐 방지
✅ 기타 설정
📖 요약
# SpringBoot 프로젝트 생성
1) 웹 제작(Spring initializer) : http://start.spring.io
- Project 빌드 : Gradle - Groovy
- spring boot 버전 : 2.7.16 선택
- spring Metadata : Artifact : 프로젝트 명 넣기 (예: helloworld)
- Packaging : War 선택
- Java : jdk 11 선택
- (오른쪽 화면) Dependencies : ADD Dependencies 버튼 클릭 : 라이브러리 추가
(1) Spring Boot DevTools
(2) Lombok
(3) Spring Web
- GENERATE 버튼 클릭 : zip 압축된 spring 프로젝트 파일 다운로드 됨
2) 인텔리제이 Ultimate(상용버전) : 위의 기능이 내장되어 있음
- 이름 : 프로젝트명 넣기 (예 : helloworld)
- 나머지는 위와 동일 Dependencies는 체크하기
# SpringBoot 환경 설정
1) 인텔리제이 툴 설정 : 에디터 - 파일 인코딩 - (우측화면) 프로퍼티 파일 인코딩 : UTF-8
명확한 Native에서 ASCII로 변환(체크!)
2) 빌드, 실행, 배포 - 컴파일러 - (우측화면) 프로젝트 자동빌드(체크)
3) 고급설정 - (우측화면) 컴파일러 - 개발된 애플리케이션이 현재... (체크)
스프링부트 프로젝트의 구조
✅ build.gradle jsp 라이브러리 추가
dependencies {
// TODO : jsp 라이브러리 추가 : 오른편 상단에 새로 생기는 아이콘 클릭!
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper' // 추가
implementation 'javax.servlet:jstl' // 추가
✅ application.properties : 스프링의 환경을 설정하는 파일
# TODO : 스프링의 환경을 설정하는 파일
# 서버 포트 : 스프링의 기본포트 (8080) -> 8000(변경)
server.port=8000
# jsp 파일 경로 지정 : jsp 폴더 경로 추가
spring.mvc.view.prefix=/WEB-INF/views/
# jsp 파일 확장자를 자동으로 붙여주는 기능 : 컨트롤러 : url -> 연결될 jsp : hello.jsp (확장자 자동으로 붙여줌)
#spring.mvc.view.suffix=.jsp
# 자바 소스가 수정되면 서버 자동 재시작을 함
spring.devtools.restart.enabled=true
✅ Java 폴더 -> ControllerExamApplication : 스프링부트 실행 파일
✅ config 폴더 -> WebMvcConfig : JSP를 사용하기 위한 설정 파일
package com.example.controllerexam.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* packageName : com.example.HelloSpringBoot.config
* fileName : WebMvcConfig
* author : kangtaegyung
* date : 2023/07/29
* description : JSP를 사용하기 위한 설정 파일
* 요약 :
* @Configuration : 어노테이션, 자바파일에 환경설정 기능 부여
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2023/07/29 kangtaegyung 최초 생성
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
}
✅ controller 폴더 -> HelloWorldController 파일 : url에 해당하는 jsp 파일로 연결해주는 파일
package com.example.controllerexam.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
/**
* packageName : com.example.helloworld.controller
* fileName : HelloWorldController
* author : GGG
* date : 2023-10-04
* description : Hello World Controller
* 요약 :
* url에 해당하는 jsp 파일로 연결하기
* @명칭 : 자바의 어노테이션이라고 하고, 주로 함수/클래스/변수 위에 붙여서 사용힘
* 작은 기능이 함수에 추가됨
* 목적 : 사용하면 코딩량이 획기적으로 줄어듦
* @Controller : 클래스에 컨트롤러 기능을 부여하는 어노테이션
* @GetMapping("url")함수() { return "jsp페이지명"; }
* => url이 웹브라우저 주소창에 입력되면 -> jsp 페이지가 화면에 출력됨
* <p>
* ===========================================================
* DATE AUTHOR NOTE
* —————————————————————————————
* 2023-10-04 GGG 최초 생성
*/
@Controller
public class HelloWorldController {
@GetMapping("/exam00/hello")
public String Hello(Model model){
return "/exam00/hello.jsp";
}
}
📖 연습문제
// TODO : 연습) url : "/exam00/hello2"
// => jsp : "/exam00/example01.jsp"
화면에 Hello JSP & Spring boot 출력해보세요!
@Controller
public class HelloWorldController {
// TODO : 연습) url : "/exam00/hello2"
// => jsp : "/exam00/example01.jsp" : 화면에 Hello JSP & Spring boot 출력
@GetMapping("/exam00/hello2")
public String Hello2(Model model){
return "/exam00/example01.jsp";
}
}
동작하고 있는 프로그램을 프로세스(Process)라고 합니다. 보통 1개의 프로세스는 한 가지의 일을 하지만, 스레드(thread)를 이용하면 한 프로세스 내에서 두 가지 또는 그 이상의 일을 동시에 할 수 있습니다.
* 프로세스 : 실행중인 프로그램
* 쓰레드 : 프로세스 안에 여러가지 작업들을 의미, 동시 실행 가능(병렬처리)
* 생성방법 ) 1) 인터페이스 상속 이용
* 2) 부모 클래스 상속 이용
간단한 예제를 통해 스레드를 구현해보겠습니다.
💡 Runnable 인터페이스 상속을 이용한 스레드 구현
public class BeepTask implements Runnable{
// TODO : 메서드 구현
// 쓰레드 작업을 실행시키는 함수
@Override
public void run() {
// TODO : 예제 : 삐소리를 들려 주는 코딩
// 멀티미디어 객체 가져오기
Toolkit toolkit = Toolkit.getDefaultToolkit();
for (int i = 0; i < 5; i++) {
toolkit.beep(); // 컴퓨터 삐소리
try {
// 공유 함수
Thread.sleep(500); // 0.5초 지연 후 삐 소리
} catch (Exception e) {
}
}
}
}
위의 예제는 스레드 작업 실행 시 윈도우 사운드인 비프음을 들려주는 코드입니다.
뒤에서 나올 예제에서 스레드 객체를 만들 때 스레드 클래스를 상속하여 만들기도 하지만 주로 Runnable 인터페이스를 사용합니다.
왜냐하면 스레드 클래스를 상속하면 스레드 클래스를 상속한 클래스가 다른 클래스를 상속할 수 없기 때문입니다.
위의 BeepTask 클래스는 Runnable 인터페이스를 사용하였습니다.
* description : 작업쓰레드 #1 : 삐소리
* main 함수 : 메인 쓰레드 : 화면출력 : 띵 글자 5번 출력
* 동시 실행
public class BeepTaskApplication {
public static void main(String[] args) {
// TODO : 1) 작업쓰레드 객체 생성
Runnable runnable = new BeepTask(); // 다형성
// TODO : 2) 쓰레드 생성자의 매개변수로 전달
Thread thread = new Thread(runnable);
// TODO : 3) 작업쓰레드 # 1 : 삐소리 실행(run() 실행됨)
thread.start();
// TODO : 4) 메인쓰레드 : 화면에 띵 글자 출력
for (int i = 0; i < 5; i++) {
System.out.println("띵");
try {
Thread.sleep(500); // 0.5 지연
} catch (Exception e){}
}
}
}
위의 BeepTaskApplication 클래스는 실행함수입니다.
메인 함수에서 다형성을 이용해 runnable 형태의 BeepTask 객체를 생성해주고,
스레드의 생성자(thread)의 매개변수로 runnable를 전달해줍니다.
그리고 작업스레드 #1을 실행하는 start함수를 이용해 실행시킵니다.
그리고 화면에 출력하기 위해 for 반복문을 사용하여 화면에 출력합니다. 여기서 예외처리를 통해 sleep 함수를 사용해 0.5초 지연을 시켜줍니다.
실행결과는 다음과 같습니다.
0.5초씩 지연되며 윈도우 비프음이 실행되며 '띵'이라는 글자가 출력됩니다.
띵 띵 띵 띵 띵
💡 Thread 클래스를 상속받아 스레드 구현
다음은 thread 클래스를 상속받아 스레드를 구현해보겠습니다.
public class BeepThread extends Thread{
// TODO : 쓰레드 작업을 실행시키는 함수
@Override
public void run() {
// TODO: beep 를 들려주는 코드
// 자바쪽 멀티미디어 객체 : 소리, 그림, 이미지 등등 다루는 객체
Toolkit toolkit = Toolkit.getDefaultToolkit();
for (int i = 0; i < 5; i++) {
toolkit.beep(); // 삐소리
try {
Thread.sleep(500); // 0.5 삐소리 지연
} catch (Exception e) {}
}
}
}
위의 BeepThread 클래스는 Thread 클래스를 상속받은 형태입니다.
run() 함수는 부모 클래스인 Thread 클래스의 run() 함수를 오버라이딩 하였습니다.
여기서 Toolkit은 JAVA 멀티미디어를 다루는 객체를 말합니다.
아래에 반복문을 통해 toolkit의 함수인 beep() 를 사용하여 윈도우 비프음을 실행시키고
예외처리를 통해 0.5초 지연을 해줍니다.
public class BeepThreadApplication {
public static void main(String[] args) {
// TODO : 1) 쓰레드 객체 생성
Thread thread = new BeepThread(); // 다형성
// TODO : 2) 쓰레드 실행 #1 : 내부적으로 run() 함수가 실행됨
thread.start();
// TODO : 3) main 쓰레드 작업 #2 : 화면 출력 (띵 * 5 출력)
for (int i = 0; i < 5; i++) {
System.out.println("띵");
try {
Thread.sleep(500); // 0.5초 지연
}catch (Exception e){}
}
}
}
위의 코드는 상속받은 스레드를 실행하는 클래스입니다.
먼저 메인 함수에서 스레드 객체를 생성해주고,
스레드 #1를 실행합니다.
그리고 for 반복문을 통해 화면에 출력해줍니다.
실행결과는 다음과 같습니다.
띵 // 윈도우 비프음과 동시에 실행됨
띵 // 윈도우 비프음과 동시에 실행됨
띵 // 윈도우 비프음과 동시에 실행됨
띵 // 윈도우 비프음과 동시에 실행됨
띵 // 윈도우 비프음과 동시에 실행됨
💡 요약
Thread 객체의 생성자로 Runnable 인터페이스를 구현한 객체를 전달하는 방법을 사용하면 Thread 클래스를 상속받아 구현한 것과 동일하게 작동합니다.
thread 객체가 Thread 클래스를 상속했을 경우에는 다른 클래스를 상속받을 수 없지만, 인터페이스를 사용한 경우에는 다른 클래스 상속이 가능하므로 좀 더 유연한 프로그램으로 만들 수 있습니다.
* description : 특수클래스 -> 중첩 클래스 : 클래스안에 클래스
* 요약 :
* 클래스의 3요소 : 속성, 생성자, 함수
* 멤버 클래스 - 일반 속성 클래스 : 외부 클래스를 생성해야 내부 클래스를 사용가능
* 정적 속성 클래스 : 외부 클래스 생성없이 바로 사용 가능
* 로컬 클래스 - 함수(메소드) 안의 클래스 : 함수를 실행해야 사용 가능
public class Outer {
// TODO : 클래스의 3요소 = 속성, 생성자, 함수
// 생성자
public Outer() {
System.out.println("외부 클래스가 생성됨");
}
// TODO : 일반 속성 (내부)클래스
public class Attr {
// 생성자
public Attr() {
System.out.println("Attr 내부 클래스가 생성됨");
}
int field1; // 속성
void method1() {
}
}
// TODO : 정적 속성(내부) 클래스
static class Share {
// 생성자
public Share() {
System.out.println("Share 정적 객체가 생성됨");
}
int filed1; // 일반 속성
static int field2; // 정적 속성
void method1(){}; // 일반 함수
static void method2(){
System.out.println("정작함수가 실행됨");
}; // 정적 함수
}
// TODO : 로컬 클래스 : 함수 안의 클래스
void method(){
// TODO : 내부 클래스
class Local{
// 생성자
public Local() {
System.out.println("Local 객체가 생성됨");
}
int field1; // 속성
void method1(){}; // 함수
}
// Local 객체 생성
Local local = new Local();
local.field1 = 3; // 내부클래스 속성
local.method1(); // 내부클래스 함수
}
}
중첩클래스의 사용
public class OuterApplication {
public static void main(String[] args) {
// TODO : 외부클래스 : Outer 객체 생성
Outer outer = new Outer();
// TODO : 1) 일반 속성 내부 클래스 객체 생성
// 사용법 : 외부클래스.내부클래스 객체변수 = 외부객체.new 내부생성자함수();
Outer.Attr attr = outer.new Attr();
attr.field1 = 3; // 내부 클래스의 속성
attr.method1(); // 내부 클래스의 함수
// TODO : 2) 정적(공유) 속성 내부 클래스 객체 생성 없음 : 바로 호출
// 사용법 : 외부클래스.내부클래스.속성, 외부클래스.내부클래스.함수()
Outer.Share.field2 = 3; // 공유 내부 클래스의 공유속성 호출
Outer.Share.method2(); // 공유 내부 클래스의 공유함수 호출
// TODO : 3) 로컬 클래스 : 함수 안의 클래스
outer.method(); // 안에서 클래스 자동 생성됨
}
}
실행결과
외부 클래스가 생성됨 Attr 내부 클래스가 생성됨 정작함수가 실행됨 Local 객체가 생성됨
// js : 함수의 매개변수로 함수를 넣을 수 있음, 리턴값도 함수 내보내기 가능
// java : 함수의 매개변수/리턴값으로 함수 사용 금지
// => 부가기능 추가 : 5가지 경우의 대표 함수(형태)를 만들어서 사용
// Runnable(실행) 함수 : 매개변수(x), 리턴값(x) 함수 예) void run()
// Supplier(공급자) 함수 : 매개변수(x), 리턴값(o) 함수 예) int get()
// Consumer(소비자) 함수 : 매개변수(o), 리턴값(x) 함수 예) void accept(int t)
// Function(일반) 함수 : 매개변수(o), 리턴값(o) 함수 예) int apply(int t)
// Predicate(논리(명제)) 함수 : 매개변수(o), 리턴값(o, 참/거짓) 함수 예) boolean apply(int t)
/**
* 1~100까지 중 10개의 랜덤 숫자 배열에 넣기 함수
* 제네릭 함수 : 제네릭을 매개변수에 사용하는 함수, 반환타입 앞에 <T>를 붙임
* T 클래스 : 대표 T : 임의의 어떤 클래스를 대표하는 클래스로 사용
* 제네릭 함수 : static <T> 반환타입 함수명(매개변수타입 매개변수명...) {}
*
* @param s
* @param list
* @param <T>
*/
static <T> void makeRandomList(Supplier<T> s, List<T> list) {
for (int i = 0; i < 10; i++) {
list.add(s.get()); // s.get() : 매개변수로 전달되는 생산자 함수를 대리하는 함수
}
}
/**
* List에 저장된 요소의 값이(i) 짝수인것만 화면에 출력
*
* @param p
* @param c
* @param list
* @param <T>
*/
static <T> void printEventNum(Predicate<T> p, Consumer<T> c, List<T> list) {
for (T i : list) {
// 명제 : 참/거짓이 있는 문장
if (p.test(i)) { // p.test(값) : 매개변수로 전달되는 논리(명제) 함수를 대리하는 함수
c.accept(i); // c.accept(값) : 매개변수로 전달되는 소비자 함수를 대리하는 함수
}
}
System.out.println(); // 줄바꿈
}
/**
* 1의 자리를 없앤 새로운 배열을 만들어서 List에 저장하는 함수(1의 자리는 0으로 변경)
* 제네릭 함수 : 함수의 리턴값 앞에 <T>, 제네릭표현식을 사용하는 함수
*
* @param f
* @param list
* @param <T>
* @return
*/
static <T> List<T> doSomething(Function<T, T> f, List<T> list) {
List<T> newList = new ArrayList<T>(list.size());
for (T i : list) {
newList.add(f.apply(i)); // p.apply(값) : 매개변수로 전달되는 일반 함수를 대리하는 함수
}
return newList;
}
public static void main(String[] args) {
Supplier<Integer> s = () -> (int)(Math.random()*100) + 1; // 1 ~ 100까지 랜덤
Consumer<Integer> c = i -> System.out.println(i + ","); // i 출력 함수
Predicate<Integer> p = i -> i % 2 == 0; // 2의 배수만 리턴하는 함수
Function<Integer, Integer> f = i -> i/10*10; // i의 값 중 1의 자리를 없애는 함수
// 예) 9.7 -> 90
// TODO : 결과 실행
List<Integer> list = new ArrayList<>();
// TODO : 정적 함수를 호출하면 마지막 매개변수(배열)에 값이 저장되어 리턴됨(화면출력됨)
makeRandomList(s, list);
System.out.println(list); // 결과출력 : 1 ~ 100까지 랜덤수가 화면출력됨
System.out.println("------------------------------------------------------");
printEventNum(p, c, list); // 결과 : 배열에 짝수인것만 화면에 출력
System.out.println("------------------------------------------------------");
List<Integer> list2 = doSomething(f, list);
System.out.println(list2); // 결과 : 일의 자리를 없앤 배열
}
* description : File 클래스 : 파일생성 또는 폴더 생성, 정보 보기 기능
public class FileApplication {
public static void main(String[] args) throws Exception {
// TODO : 1) 텍스트 파일을 읽어서 리스트 배열로 가져오기 : Files.readAllLines(Paths.get(경로))
List<String> lines
= Files.readAllLines(Paths.get("src/main/resources/file1.txt"));
System.out.println(lines); // 배열 출력
// TODO : 2) byte 파일을 읽어서 데이터 가져오기
byte[] bytes = Files.readAllBytes(Paths.get("src/main/resources/test1.db"));
System.out.println(Arrays.toString(bytes)); // 결과 출력
}
}
실행결과
[hello, how are you, nice to meet you] [10, 20, 30]
* description : 키보드로 부터 한 줄씩 문자열 얻어서 출력하기
* 요약 :
* System.in : 키보드로부터의 입력을 의미
* System.out : 모니터로 출력을 의미
public class KeyboardApplication {
public static void main(String[] args) throws Exception {
// TODO : 키보드 입력 -> byte 입력스트림에 넣기
InputStream inputStream = System.in;
// TODO : 보조스트림 적용 #1 : byte -> char 기반으로 변경
Reader reader = new InputStreamReader(inputStream);
// TODO : 보조스트림 적용 #2 : 버퍼 추가
// 보조기능 #1 + #2 가 적용된 스트림
// Scanner 객체가 위의 기능을 모두 가지고 있음
BufferedReader bufferedReader = new BufferedReader(reader);
// TODO : 무한 반복문
while (true){
String str = bufferedReader.readLine(); // 한 줄씩 읽기
if(str.equals("q") || str.equals("quite")) break; // q 이거나 quite 이면 종료
System.out.println(str);
}
bufferedReader.close();
}
}
실행결과
adasdada adasdada dadsada dadsada dsadsa dsadsa dfasf dfasf as as q <- q 입력시 종료