Cloud 기반 웹 DevOps 프로젝트 개발자 과정

문이빈·2023년 7월 12일
0

Java

----------Util List----------

Nation 클래스와 Type 열거형을 활용하여 국가 정보를 저장하고 관리
package sec01.stream;

import java.util.List;

public class Nation {
private final String name;
private final Type type;
private final double population;
private final int gdpRank;

public Nation(String name, Type type, double population, int gdpRank) {
	this.name = name; 
	this.type = type;
	this.population = population; 
	this.gdpRank = gdpRank;
}

// enum = 배열식으로 작성되는 객체, 여러가지 객체를 나열형으로 생성할 수 있음
/* 클래스 처럼 선언하지만 클래스는 아님 각 내용 안에 들어있는 것은 상수처럼 사용됨. 
   숫자로 인덱스가 인정된다.
   숫자를 직접 입려할 수도 있어서 메소드처럼 쓰기도 한다.*/
public enum Type { LAND,ISLAND }

public String getName() { return name; }
public Type getType() { return type; }
public boolean isIsland() { return getType() != Type.LAND; }
public double getPopulation() { return population; }
public int getGdpRank() { return gdpRank; }
public String toString() { return name; }

public static final List<Nation> nation = List.of(
		new Nation("ROK",            Nation.Type.LAND,     51.4, 11),
		new Nation("New Zealand",    Nation.Type.ISLAND,    4.5, 49),
		new Nation("USA",            Nation.Type.LAND,    318.9,  1),
		new Nation("China",          Nation.Type.LAND,   1355.7,  2),
		new Nation("Philiphine",     Nation.Type.ISLAND,  107.7, 36),
		new Nation("United Kingdom", Nation.Type.ISLAND,   63.7,  5),
		new Nation("Sri Lanka",      Nation.Type.ISLAND,   21.9, 63),
		new Nation("Morocco",        Nation.Type.LAND,     33.0, 60)
		);
}
  1. Nation 클래스에는 생성자와 getter 메소드들이 정의되어 있습니다. 또한, isIsland( ) 메소드는 국가가 섬에 위치한 국가인지 확인하는 데 사용됩니다.
  2. Type 열거형은 땅에 위치한 국가와 섬에 위치한 국가 두 가지 유형을 정의합니다.
    LAND와 ISLAND는 각각 배열 형태로 선언된 객체이며, 각 객체는 이름과 해당 유형에 대한 정보를 저장합니다.
  3. Nation 클래스에는 nation이라는 정적(final) 변수가 있으며, 이 변수는 Nation 객체의 리스트로 초기화됩니다.

----------Util Class----------

Util 클래스에는 두 개의 정적 메소드가 포함
package sec01.stream;

public class Util {
public static <T> void print (T t) {
	System.out.print(t+" ");
}
public static <T> void printWithParenthesis (T t) {
	System.out.print(" ("+t+") ");
	}
}
  1. print( ) 메소드 :
    이 메소드는 제네릭 타입 T를 매개변수로 받아서 해당 값을 출력합니다. System.out.print()를 사용하여 값을 출력하며, 출력 후에는 공백을 추가합니다.
  2. printWithParenthesis( ) 메소드 :
    이 메소드는 제네릭 타입 T를 매개변수로 받아서 값을 괄호로 감싼 형태로 출력합니다. System.out.print()를 사용하여 괄호와 값을 출력하며, 출력 후에는 공백을 추가합니다.
  • 두 메소드 모두 제네릭 타입 T를 사용하여 다양한 타입의 값을 처리할 수 있습니다.

  • 따라서, 주어진 코드는 다양한 타입의 값을 출력하고, 일부 값을 괄호로 감싸서 출력하는 데 사용할 수 있는 Util 클래스의 예시를 보여줍니다.

----------Array2StreamDemo----------

IntStream을 사용하여 정수 배열 ia에서 홀수를 필터링하고 정렬한 후에 출력

package sec02.stream;

import java.util.Arrays;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Array2StreamDemo {

public static void main(String[] args) {
	int[ ] ia = {2, 3, 5, 7, 11, 13};
    
	// 정수형 배열을 스트림으로 받기 Arrays.stream(ia);
	IntStream is = Arrays.stream(ia);
	
	String[ ] strings = {"The", "pen", "is", "mighter", "than",
			             "the", "sword"};
	
	// 문자열 배열 객체는 Stream.of(strings);로 받기
	Stream<String> ss = Stream.of(strings);
	
	double[ ] da = {1.2, 3.14, 5.8, 0.2};
	
	// double 배열에 있는 내용을 스트림으로 받기
	DoubleStream ds = DoubleStream.of(da);
	}
}

만약 
IntStream is = Arrays.stream(ia);
	  is.filter(i -> i % 2 == 1).sorted()
	            .forEach(x -> System.out.print(x + " "));
  1. Arrays.stream(ia)를 사용하여 정수 배열 ia를 IntStream으로 변환합니다.
  2. filter(i -> i % 2 == 1)를 호출하여 스트림의 요소를 필터링합니다.
    여기서는 홀수인 요소만을 유지합니다.
  3. sorted( )를 호출하여 필터링된 홀수 값들을 정렬합니다.
    정렬은 기본적으로 오름차순으로 수행됩니다.
  4. forEach(x -> System.out.print(x + " "))를 호출하여 정렬된 홀수 값을 반복하면서 각 값을 출력합니다.
    x -> System.out.print(x + " ") 람다 식은 각 요소를 공백으로 구분하여 출력합니다.
  • ia 배열에서 홀수를 찾아 정렬한 후 출력하는 예시를 보여줍니다.

----------Etc2StreamDemo----------

다양한 방법으로 IntStream과 Stream을 생성하는 예시

package sec02.stream;

import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Etc2StreamDemo {

public static void main(String[] args) {
	IntStream is1 = IntStream.iterate(1, x -> x + 2 );
	
	IntStream is2 = new Random().ints(0, 10);
	
	Stream<Double> ds = Stream.generate(Math::random);
	
	IntStream is3 = IntStream.range(1, 5);
	}
}
  1. IntStream.iterate(1, x -> x + 2)를 사용하여 1부터 시작하여 2씩 증가하는 무한한 정수 스트림을 생성합니다.
    is1 : 1부터 시작하여 2씩 증가하는 무한한 정수 스트림을 생성합니다.
  2. new Random().ints(0, 10)를 사용하여 0 이상 10 미만의 무작위 정수 스트림을 생성합니다.
    is2 : 0 이상 10 미만의 무작위 정수 스트림을 생성합니다.
  3. Stream.generate(Math::random)을 사용하여 0부터 1 사이의 무작위 Double 값을 생성하는 무한한 스트림을 생성합니다.
    ds : 0부터 1 사이의 무작위 Double 값을 생성하는 무한한 스트림을 생성합니다.
  4. IntStream.range(1, 5)를 사용하여 1부터 5 미만의 정수 스트림을 생성합니다.
    is3 : 1부터 5 미만의 정수 스트림을 생성합니다.

----------FilterDemo----------

package sec03.stream;

import java.util.stream.IntStream;
import java.util.stream.Stream;

import sec01.stream.Nation;
import sec01.stream.Util;

public class FilterDemo {

public static void main(String[] args) {
	Stream<String> s1 = Stream.of("a1", "b1", "b2", "c1", "c2", "c3");
	Stream<String> s2 = s1.filter(s -> s.startsWith("c"));
	Stream<String> s3 = s2.skip(1);
	System.out.print("문자열 스트림 : ");
	s3.forEach(Util::print);
	
	IntStream i1 = IntStream.of(1, 2, 1, 3, 3, 2, 4);
	IntStream i2 = i1.filter(i -> i%2 == 0);
	IntStream i3 = i2.distinct();      // sql distinct 와 같음 = 중복 1번만
	System.out.print("\n정수 스트림 : ");
	i3.forEach(Util::print);
	
	System.out.print("\n인구가 1억(100백만) 이상의 2개 나라 : ");
	Stream<Nation> n1 = Nation.nation.stream();
	Stream<Nation> n2 = n1.filter(p -> p.getPopulation() > 100.0);
	Stream<Nation> n3 = n2.limit(2);
	n3.forEach(Util::printWithParenthesis);
	}
}
  1. Stream<String> s1 = Stream.of("a1", "b1", "b2", "c1", "c2", "c3"); : 문자열 스트림 s1을 생성합니다.

  2. Stream<String> s2 = s1.filter(s -> s.startsWith("c")); : 를 호출하여 s1 스트림에서 "c"로 시작하는 문자열만 필터링하여 새로운 스트림 s2를 생성합니다.

  3. Stream<String> s3 = s2.skip(1); : s2.skip(1)을 호출하여 s2 스트림에서 첫 번째 요소를 건너뛰고 새로운 스트림 s3을 생성합니다

  4. s3.forEach(Util::print)를 호출하여 s3 스트림의 각 요소를 출력합니다.
    Util.print : 메소드는 각 요소를 출력하는 역할을 합니다.

  5. IntStream i1 = IntStream.of(1, 2, 1, 3, 3, 2, 4); : 사용하여 정수 스트림 i1을 생성합니다.

  6. IntStream i2 = i1.filter(i -> i%2 == 0); : 호출하여 i1 스트림에서 짝수만 필터링하여 새로운 스트림 i2를 생성합니다.

  7. IntStream i3 = i2.distinct(); : 호출하여 i2 스트림에서 중복을 제거한 새로운 스트림 i3을 생성합니다.

  8. i3.forEach(Util::print)를 호출하여 i3 스트림의 각 요소를 출력합니다.

  9. Nation.nation.stream( )을 사용하여 Nation 클래스의 nation 리스트로부터 스트림 n1을 생성합니다.

  10. n1.filter(p -> p.getPopulation() > 100.0)를 호출하여 n1 스트림에서 인구가 1억 이상인 국가만 필터링하여 새로운 스트림 n2를 생성합니다.

  11. n2.limit(2)를 호출하여 n2 스트림에서 최대 2개의 요소를 제한한 새로운 스트림 n3을 생성합니다.

  12. n3.forEach(Util::printWithParenthesis)를 호출하여 n3 스트림의 각 국가를 출력합니다. Util.printWithParenthesis 메소드는 각 국가를 괄호로 감싸서 출력하는 역할을 합니다.

따라서, 주어진 코드는 문자열, 정수, 그리고 Nation 객체들을 필터링하고 제한하여 출력하는 예시를 보여줍니다.


  • 스트림 파이프 라인
    스트림 연산의 결과가 Stream 타입이면 연속적으로 호출할 수 있다.
    스트림 연산의 연속 호출은 여러 개의 스틤이 연결되어 스틤 파이프라인을 형성한다.

느긋한 연산의 특성을 보여주는 예시

package sec03.stream;

import java.util.stream.IntStream;

public class Laziness1Demo {
public static void main(String[] args) {
	
	// 느긋한 연산만으로 연결 했으므로 아직 연산이 안되고 있음
	// 조급한 연산이 끼어 들어야 느긋한 연산이 실행됨
	IntStream is = IntStream.rangeClosed(1, 5); // 1~5 까지 범위 지정
	is.filter(x -> {
		System.out.println("filter : " + x);
		return x%2 == 0;//짝수
	}).map(x -> {
		System.out.println("map : " + x);
		return x*x;//제곱
	}).forEach(x-> System.out.println("forEach :" + x));
	}
}
  1. IntStream.rangeClosed(1, 5) 를 사용하여 1부터 5까지의 정수 범위를 생성한 후 is에 저장합니다.

  2. is.filter(x -> { ... }) 를 호출하여 is 스트림에서 짝수만 필터링하는 느긋한 연산을 수행합니다.
    여기서 filter( ) 메소드에 전달되는 람다식은 각 요소가 짝수인지 확인하고 true 또는 false를 반환합니다.

  3. is.map(x -> { ... }) 를 호출하여 is 스트림의 각 요소를 제곱하는 느긋한 연산을 수행합니다.
    여기서 map( ) 메소드에 전달되는 람다식은 각 요소를 제곱한 값을 반환합니다.

  4. is.forEach(x -> System.out.println("forEach: " + x)) 를 호출하여 is 스트림의 요소를 출력합니다.
    여기서 forEach( ) 메소드에 전달되는 람다식은 각 요소를 출력하는 역할을 합니다.
  • 이때, 느긋한 연산의 특성 때문에 실제로 스트림의 요소가 필터링되고 제곱되는 시점은 forEach() 메소드를 호출할 때입니다.
    필터링과 제곱 연산은 각 요소가 실제로 사용되기 직전까지 지연되어 실행되지 않습니다.

  • 느긋한 연산을 활용하여 필터링과 제곱 연산을 미리 설정하고, 실제 사용 시점에서 해당 연산들이 수행되는 것을 보여줍니다.

= 조급한 연산인 forEach 때문에 흘러감


순차 처리와 병렬 처리의 시간 차이

package sec03.stream;

import java.util.stream.IntStream;

public class ParallelDemo {

public static void main(String[] args) {
	long start, end, total;
	
    // 순차로 1억개
	IntStream sequantial = IntStream.rangeClosed(1, 100000000);
	start = System.currentTimeMillis(); // 시작시간
	total = sequantial.sum();
	end = System.currentTimeMillis();   // 끝 시간
	System.out.println("순차 처리 : " + (end - start));
    
	// 병렬로 1억개
	IntStream parallel = IntStream.rangeClosed(1, 100000000).parallel();
	start = System.currentTimeMillis();
	total = parallel.sum();
	end = System.currentTimeMillis();
	System.out.println("병렬 처리 : " + (end - start));
	}
}
  1. IntStream.rangeClosed(1, 100000000)를 사용하여 1부터 1억까지의 정수 범위를 생성한 후 sequential에 저장합니다.

  2. System.currentTimeMillis( )를 사용하여 현재 시간을 측정하여 start에 저장합니다.

  3. sequential.sum()을 호출하여 sequential 스트림의 모든 요소의 합을 계산합니다.

  4. System.currentTimeMillis()를 사용하여 현재 시간을 다시 측정하여 end에 저장합니다.

  5. end - start를 통해 순차 처리에 걸린 시간을 계산하고 출력합니다.

  6. IntStream.rangeClosed(1, 100000000).parallel()을 사용하여 1부터 1억까지의 정수 범위를 생성하고, 이를 병렬 처리할 수 있도록 parallel에 저장합니다.

  7. 앞서와 같은 방식으로 현재 시간을 측정하여 start와 end에 저장하고, 병렬 처리에 걸린 시간을 계산하여 출력합니다.

위 코드는 순차적으로 처리하는 경우와 병렬로 처리하는 경우를 비교하여 걸린 시간을 출력합니다.
병렬 처리는 여러 개의 스레드를 사용하여 작업을 분할하고 동시에 처리하기 때문에 순차 처리보다 빠를 수 있습니다.

순차보다 병렬이 더 빠름


Optional 클래스를 사용하여 값이 존재하지 않을 수 있는 상황을 처리하는 예시

package sec03.stream;

import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;

public class Optional1Demo {
    public static OptionalDouble divide(double x, double y) {
        return y == 0 ? OptionalDouble.empty() : OptionalDouble.of(x / y);
    }

public static void main(String[] args) {
	OptionalInt i = OptionalInt.of(100);
	OptionalDouble d = OptionalDouble.of(3.14);
	Optional<String> s = Optional.of("apple");
	System.out.println("1: " + i.getAsInt());
	System.out.println("2: " + d.getAsDouble());
	System.out.println("3: " + s.get());
	System.out.println("4: " + i.getAsInt());
	System.out.println("5: " + d.getAsDouble());
	System.out.println("6: " + s.get());
	System.out.println("7: " + divide(1.0, 2.0));
	System.out.println("8: " + divide(1.0, 0.0));
	}
}
  1. OptionalDouble divide(double x, double y) 메소드는 주어진 두 개의 double 값을 나누어 결과를 OptionalDouble 타입으로 반환합니다.
    만약 y 값이 0인 경우에는 값이 없음을 나타내기 위해 OptionalDouble.empty()를 반환합니다.

  2. OptionalInt.of(100)을 사용하여 100 값을 갖는 OptionalInt 객체 i를 생성합니다.

  3. OptionalDouble.of(3.14)를 사용하여 3.14 값을 갖는 OptionalDouble 객체 d를 생성합니다.

  4. Optional.of("apple")을 사용하여 "apple" 값을 갖는 Optional 객체 s를 생성합니다.

  5. i.getAsInt()을 호출하여 i 객체의 값을 int로 가져옵니다. 동일한 메소드를 두 번 호출하여도 같은 값이 반환됩니다.

  6. d.getAsDouble()을 호출하여 d 객체의 값을 double로 가져옵니다. 동일한 메소드를 두 번 호출하여도 같은 값이 반환됩니다.

  7. s.get()을 호출하여 s 객체의 값을 가져옵니다. 동일한 메소드를 두 번 호출하여도 같은 값이 반환됩니다.

  8. divide(1.0, 2.0)을 호출하여 1.0을 2.0으로 나눈 결과를 출력합니다.
    이 경우 OptionalDouble 객체가 반환되고, toString() 메소드에 의해 결과가 출력됩니다.

  9. divide(1.0, 0.0)을 호출하여 1.0을 0.0으로 나눈 결과를 출력합니다.
    이 경우 OptionalDouble.empty()가 반환되고, toString() 메소드에 의해 결과가 출력됩니다.
  • Optional 클래스는 값의 존재 여부를 나타내고,
  • OptionalInt, OptionalDouble 등은 각각 int, double 타입에 대한 Optional 클래스의 특화된 버전입니다.
  • Optional 객체를 사용하여 값이 없는 상황을 처리할 수 있으며, get( ) 메소드를 통해 값을 가져올 수 있습니다.
  • NoSuchElementException이 발생할 수 있으므로, isPresent() 메소드나 orElse() 메소드 등을 사용하여 값의 존재 여부를 확인하거나 기본값을 지정할 수 있습니다.

Optional 클래스를 사용하여 값의 존재 여부에 따라 처리를 수행하는 예시

package sec03.stream;

import java.util.Optional;

import sec01.stream.Util;

public class Optional2Demo {

public static void main(String[] args) {
	String s1 = "안녕"; // or String s1 = null;
	Optional<String> o = Optional.ofNullable(s1);
	
	if(s1 != null) 
		Util.print(s1);
	else
		Util.print("없음");
		
	if(o.isPresent()) 
		Util.print(o.get());
	else 
		Util.print("없음");
		
	String s2 = o.orElse("없음");
	Util.print(s2);
	
	o.ifPresentOrElse(Util::print, () -> System.out.println("없음"));
	}
}
  1. String s1 = "안녕"; 을 사용하여 문자열 "안녕"을 s1에 저장합니다. (또는 s1을 null로 설정)

  2. Optional.ofNullable(s1)을 사용하여 s1의 값을 갖는 Optional 객체 o를 생성합니다.

  3. if (s1 != null)을 사용하여 s1이 null이 아닌 경우 해당 값을 출력합니다.
    그렇지 않은 경우 "없음"을 출력합니다.

  4. if (o.isPresent())을 사용하여 o 객체가 값이 있는 경우 (isPresent( )가 true인 경우) 해당 값을 출력합니다.
    그렇지 않은 경우 "없음"을 출력합니다.

  5. o.orElse("없음")을 사용하여 o 객체의 값이 존재하는 경우 해당 값을 가져옵니다.
    그렇지 않은 경우 "없음"을 반환합니다.

  6. o.ifPresentOrElse(Util::print, () -> System.out.println("없음"))을 호출하여 o 객체의 값이 존재하는 경우 Util.print() 메소드를 호출하여 해당 값을 출력합니다.
    그렇지 않은 경우 () -> System.out.println("없음") 람다 식이 실행되어 "없음"을 출력합니다.
  • Optional 클래스는 값의 존재 여부를 나타내며,ofNullable() 메소드를 사용하여 null 값에 대해서도 처리할 수 있습니다.
  • isPresent() 메소드는 값의 존재 여부를 확인하고, get( ) 메소드를 사용하여 값에 접근할 수 있습니다.
  • orElse( ) 메소드는 값이 존재하지 않을 경우 기본값을 반환합니다.
  • ifPresentOrElse( ) 메소드는 값이 존재하는 경우 해당 값을 사용하고, 그렇지 않은 경우 실행할 람다 식을 지정할 수 있습니다.

문자열, 정수, 그리고 Nation 객체들을 필터링하고 제한하여 출력

package sec03.stream;

import java.util.stream.IntStream;
import java.util.stream.Stream;

import sec01.stream.Nation;
import sec01.stream.Util;

public class FilterDemo {

public static void main(String[] args) {
	Stream<String> s1 = Stream.of("a1", "b1", "b2", "c1", "c2", "c3");
	Stream<String> s2 = s1.filter(s -> s.startsWith("c"));
	Stream<String> s3 = s2.skip(1);
	System.out.print("문자열 스트림 : ");
	s3.forEach(Util::print);
	
	IntStream i1 = IntStream.of(1, 2, 1, 3, 3, 2, 4);
	IntStream i2 = i1.filter(i -> i%2 == 0);
	IntStream i3 = i2.distinct();      // sql distinct 와 같음 = 중복 1번만
	System.out.print("\n정수 스트림 : ");
	i3.forEach(Util::print);
	
	System.out.print("\n인구가 1억(100백만) 이상의 2개 나라 : ");
	Stream<Nation> n1 = Nation.nation.stream();
	Stream<Nation> n2 = n1.filter(p -> p.getPopulation() > 100.0);
	Stream<Nation> n3 = n2.limit(2);
	n3.forEach(Util::printWithParenthesis);
	}
}
  1. Stream.of("a1", "b1", "b2", "c1", "c2", "c3")를 사용하여 문자열 스트림 s1을 생성합니다.

  2. s1.filter(s -> s.startsWith("c"))를 호출하여 s1 스트림에서 "c"로 시작하는 문자열만 필터링하여 새로운 스트림 s2를 생성합니다.

  3. s2.skip(1)을 호출하여 s2 스트림에서 첫 번째 요소를 건너뛰고 새로운 스트림 s3을 생성합니다.

  4. s3.forEach(Util::print)를 호출하여 s3 스트림의 각 요소를 출력합니다. Util.print 메소드는 각 요소를 출력하는 역할을 합니다.

  5. IntStream.of(1, 2, 1, 3, 3, 2, 4)를 사용하여 정수 스트림 i1을 생성합니다.

  6. i1.filter(i -> i%2 == 0)를 호출하여 i1 스트림에서 짝수만 필터링하여 새로운 스트림 i2를 생성합니다.

  7. i2.distinct()를 호출하여 i2 스트림에서 중복을 제거한 새로운 스트림 i3을 생성합니다.

  8. i3.forEach(Util::print)를 호출하여 i3 스트림의 각 요소를 출력합니다.
    Util.print 메소드는 각 요소를 출력하는 역할을 합니다.

  9. Stream<Nation> n1 = Nation.nation.stream()을 사용하여 Nation 클래스의 nation 리스트로부터 스트림 n1을 생성합니다.

  10. n1.filter(p -> p.getPopulation() > 100.0)을 호출하여 n1 스트림에서 인구가 1억 이상인 국가만 필터링하여 새로운 스트림 n2를 생성합니다.

  11. n2.limit(2)를 호출하여 n2 스트림에서 최대 2개의 요소를 제한한 새로운 스트림 n3을 생성합니다.

  12. n3.forEach(Util::printWithParenthesis)를 호출하여 n3 스트림의 각 국가를 출력합니다. Util.printWithParenthesis 메소드는 각 국가를 괄호로 감싸서 출력하는 역할을 합니다.


flatMap() 메소드를 사용하여 스트림의 요소를 펼치는 예시

package sec03.stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import sec01.stream.Util;

public class Map3Demo {

public static void main(String[] args) {
	List<String> list1 = List.of("안녕, 자바!", "잘 가, C++");
	Stream<String> s1 = list1.stream();
	Stream<String> s2 = s1.flatMap(s -> Arrays.stream(s.split(" ")));
	s2.forEach(Util::printWithParenthesis);
	System.out.println();
	
	List<String> list2 = List.of("좋은 아침");
	List<String> list3 = List.of("안녕! 람다", "환영! 스트림");
	Stream<List<String>> s3 = Stream.of(list1, list2, list3);
	Stream<String> s4 = s3.flatMap(list -> {
		if(list.size() > 1)
			return list.stream();
		else
			return Stream.empty();
	});
	s4.forEach(Util::printWithParenthesis);
	}
}
  1. List.of("안녕, 자바!", "잘 가, C++")를 사용하여 문자열 리스트 list1을 생성합니다.

  2. list1.stream()을 호출하여 list1의 요소로 구성된 스트림 s1을 생성합니다.

  3. s1.flatMap(s -> Arrays.stream(s.split(" ")))을 호출하여 s1 스트림의 각 요소를 공백을 기준으로 분리하여 새로운 스트림 s2를 생성합니다.
    flatMap() 메소드는 각 요소를 분할한 결과를 하나의 스트림으로 펼칩니다.

  4. s2.forEach(Util::printWithParenthesis)를 호출하여 s2 스트림의 각 요소를 출력합니다.
    Util.printWithParenthesis 메소드는 각 요소를 괄호로 감싸서 출력하는 역할을 합니다.

  5. List.of("좋은 아침")를 사용하여 문자열 리스트 list2를 생성합니다.

  6. List.of("안녕! 람다", "환영! 스트림")을 사용하여 문자열 리스트 list3을 생성합니다.

  7. Stream.of(list1, list2, list3)을 호출하여 list1, list2, list3로 구성된 스트림 s3을 생성합니다.

  8. s3.flatMap(list -> { ... })를 호출하여 s3 스트림의 요소들을 처리합니다.
    flatMap() 메소드에 전달되는 람다식은 각 요소의 크기가 1보다 큰 경우 해당 리스트의 요소들로 구성된 스트림을 반환하고, 크기가 1 이하인 경우 Stream.empty()를 반환합니다.

  9. s4.forEach(Util::printWithParenthesis)를 호출하여 s4 스트림의 각 요소를 출력합니다. Util.printWithParenthesis 메소드는 각 요소를 괄호로 감싸서 출력하는 역할을 합니다.

s.split("")

s.split(" ") 띄어쓰기 하나 차이

if(list.size( ) > 2) 하면 나오지 않음.


Session 객체

Session이라는 객체를 만들어서 사용할건데
클라이언트와 서버가 연결되는 경우 연겨로간계를 설정하고 알고 있는 상태를 session이 연결되었다.
연결되어 있는 상태이면 서버가 그 클라이언트를 인정하는 상태가 됨
이름-값의 형태로 저장
세션 설정시간을 설정해 주기도 함(디폴트 값은 30분)
setAttribute가 있고, getAttribute가 있음
세션 종료 모든 세션 정보를 삭제(invalidate())
특정 세션만을 삭제(removeAttribute)
getAttributeNames() 모든 속성의 이름을 가져와라.

----------main.jsp----------
<title>Main</title>
<style type="text/css">
  *{margin: 0 auto;}
</style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
  <script type="text/javascript">
    $().ready(function(){
    	$('#logout').click(function(){
    	 	location.href = "./logout.do"
    	
    	  }
    	);
    });
  </script>
</head>
<body>
<%
//Object로 받아와서 String으로 캐스팅
  String uid = (String)session.getAttribute("uid");
  if(uid != null){
	  out.println(uid+"님 반갑습니다.");
	  %>
	  <button id="logout">로그아웃</button>
	  <%
  }else{
	  %>
	  
	  <script type="text/javascript">
	    alert("세션이 종료되었습니다.\n 다시 로그인 해주세요");
	    location.href = "./Login.do"
	  </script>
    <% }
         %>
</body>
</html>


----------MemberController----------
추가
case "/login.do":{ //아이디, 패스워드 받기 위해서 화면만 띄우기
			     com = new LogOutAction();
			     view = com.requestPro(request, resonse);
			     break;
			     }


jsp 파일 생성
----------LogOutAction----------

package member;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LogOutAction implements CommandAction {

	@Override
	public String requestPro(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 세션을 받아서
		  HttpSession session = request.getSession();
		  if(session.getAttribute("uid")!= null)
			  session.removeAttribute("uid");
		// 모두 삭제
		  session.invalidate();
		return "member/login.jsp";
	}
}

로그 아웃을 누르면 로그인 페이지로 돌아감


----------MemberDTO----------

package member.model;

public class MemberDTO {
    private String id;
    private String name;
    private String passwd;
    public String getId() {
	return id;
}
public void setId(String id) {
	this.id = id;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public String getPasswd() {
	return passwd;
}
public void setPasswd(String passwd) {
	this.passwd = passwd;
}

이렇게 작성됨

----------MemberController----------

추가

RequestDispatcher dispatcher =request.getRequestDispatcher(view);
    if(view.contains(".do")) {
    }else {
    dispatcher.forward(request, resonse);
 	   }
	}
}

----------LogOutAction----------

package member;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LogOutAction implements CommandAction {

@Override
public String requestPro(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	// 세션을 받아서
	  HttpSession session = request.getSession();
	  if(session.getAttribute("uid")!= null)
		  session.removeAttribute("uid");
	// 모두 삭제
	  session.invalidate();
	return "login.d0";
}

}

----------MemberDAO----------

package member.model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class MemberDAO {

//인스턴스 객체를 선언 private
private static MemberDAO instance = new MemberDAO();

private Connection getConnection() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection conn=
                DriverManager
                .getConnection("jdbc:mysql://localhost:3306/boarddb","root","1234");
        return conn;
    }
    private MemberDAO() {}

public static MemberDAO getInstance() {
	return instance;
}

public boolean loginAction(String id, String passwd) 
		       throws ClassNotFoundException, SQLException {
	boolean result = false;
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	try {
		String sql = "select count(*) from member where id=? and passwd=?";
		conn = getConnection();
		pstmt = conn.prepareStatement(sql);
		pstmt.setString(1, id);
		pstmt.setString(2, passwd);
		rs = pstmt.executeQuery();
		
		if(rs.next()) {// 결과를 받아온게 있으면
			int r = rs.getInt(1);
			if(r==0) result = false;
			else if (r==1) result = true;
		}
	}catch(Exception e) {
		System.out.println(e.getMessage());
	}finally {
		if(rs!=null)rs.close();
		if(pstmt!=null)pstmt.close();
		if(conn!=null)conn.close();
	}
	
	return result;		
}
public List<MemberDTO> getMemberList() 
		throws ClassNotFoundException, SQLException {
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	// 데이터베이스 연결
	// 쿼리 문 만들고
	// 데이터베이스에서 받아온 ResultSet을 while을 통해서 하나씩 읽어서 DTO에 저장하고
	// 리스트에 추가하고 리턴
	List<MemberDTO> list = null; // 선언
	try {
		conn = getConnection();
		String sql = "select id, name, passwd \n";
		       sql += "from member";
		pstmt = conn.prepareStatement(sql);
		rs = pstmt.executeQuery();
		list = new ArrayList<MemberDTO>(); // 생성
		// 여러개 가져오면 while
	    while(rs.next()) {
	    	// 하나의 레코드를 저장하기 위한 객체
	    	MemberDTO dto = new MemberDTO();
	    	// dto에 id을 저장하는데 setId, id정보는 rs에 있고 데이터베이스의 필드명이 id
	    	// rs.getString("필드명"), rs.getInt("필드명")
	    	dto.setId(rs.getString("id"));
	    	dto.setName(rs.getString("name"));
	    	dto.setPasswd(rs.getString("passwd"));
	    	list.add(dto);
	    }
	}catch(Exception e) {
		System.out.println(e.getMessage());
	}finally {
		if(rs!=null)rs.close();
		if(pstmt!=null)pstmt.close();
		if(conn!=null)conn.close();
    }
	return list;
	}
}

----------MemberListAtion----------

package member;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import member.model.MemberDAO;
import member.model.MemberDTO;

public class MemberListAtion implements CommandAction {

@Override
public String requestPro(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	// 데이터베이스에서 모든 회원정보를 받아와서
	MemberDAO dao = MemberDAO.getInstance();
	// 전손 후 가방인 DTO안에 넣어서 리스트 안에 저장
	List<MemberDTO> members = null;
	try {
		members = dao.getMemberList();
	} catch (ClassNotFoundException e) {
		System.out.println(e.getMessage());
	} catch (SQLException e) {
		System.out.println(e.getMessage());
	}
	request.setAttribute("members", members);
	return "member/list.jsp";
}

}

----------list----------

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri ="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%-- ctrl + shift + r => taglib --%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style type="text/css">
*{
  margin: 0 auto;}

</style>
<title>회원정보</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
</head>
<body>
  <h3 style="text-align: center;">회원리스트</h3>
    <c:choose>
      <c:when test="${members ==null or fn:length(members)==0 }">
        <table>
          <tbody>
            <tr>
              <td>아직 회원이 없습니다.</td>
            </tr>
          </tbody>
        </table>
      </c:when>
      <c:when test="${members == null or fn:length(members)>0}">
        <table>
          <tbody>
          
            <!-- 반복문 돌리기 forEach 자바의 확장형 for문과 같은 처리 방법
                 items에 들어가는 것은 내부에서 전달된 배열이나 list형태
                 var는 해당하는 리스트의 한개씩 받는 변수             -->
              <tr>
                <th>아이디</th><th>이름</th>
              </tr> 
                  
                <c:forEach var="member" items="${members}">
            
              <tr>
                <td>${member.id}</td><td>${member.name}</td>
              </tr>
                <td>${member.id}</td>
                <td>
                  <input type="hidden" value="${member.passwd}"/>
                </td>
            </c:forEach>
          </tbody>
        </table>
      </c:when>
    </c:choose>
</body>
</html>


웹 애플리케이션의 회원 로그인과 회원 리스트 기능을 구현하는 예시

1. login.jsp
로그인 화면을 구성하는 JSP 파일입니다.

2. LoginAction.java
로그인 액션을 처리하는 클래스입니다.

3. LoginProAction.java
로그인 처리 결과를 확인하고 세션을 설정하는 클래스입니다.

4. CommandAction.java
공통 메소드를 가지는 인터페이스입니다.

5. MemberController.java
클라이언트의 요청을 처리하고 각 액션을 호출하는 컨트롤러입니다.

6. LogOutAction.java
로그아웃 액션을 처리하는 클래스입니다.

7. MemberListAction.java
회원 리스트를 가져오는 액션을 처리하는 클래스입니다.

8. MemberDTO.java
회원 정보를 담는 DTO 클래스입니다.

9. MemberDAO.java
회원 정보를 데이터베이스에서 처리하는 DAO 클래스입니다.

10. main.jsp
메인 페이지를 구성하는 JSP 파일입니다.

11. list.jsp
회원 리스트를 출력하는 JSP 파일입니다.

12. top.jsp
상단 영역을 구성하는 JSP 파일입니다.

13. bottom.jsp
하단 영역을 구성하는 JSP 파일입니다.

이 코드는 MVC (Model-View-Controller) 패턴을 따르는 간단한 웹 애플리케이션의 예시입니다.

로그인 기능과 회원 리스트를 출력하는 기능이 구현되어 있으며, 각 기능은 해당하는 액션 클래스에서 처리됩니다.

컨트롤러는 클라이언트의 요청을 분석하고 액션 클래스를 호출하여 결과를 출력하는 역할을 수행합니다.

JSP 파일은 화면을 구성하는 데 사용되며, EL (Expression Language)과 JSTL (JSP Standard Tag Library)을 사용하여 데이터를 처리하고 출력합니다.
이 코드를 실행하려면 웹 애플리케이션 컨테이너 (예: Apache Tomcat)에 배포하고 해당 서버를 실행해야 합니다.
그러면 브라우저에서 http://localhost:8080/프로젝트명/주소 형식으로 애플리케이션에 접속할 수 있습니다.


----------login.jsp----------

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login</title>
<style type="text/css">
  *{margin: 0 auto;}
</style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script type="text/javascript">
    $().ready(function(){
    	$('#login').click(function(){
    	 	location.href = "./login.do"
    	  }
    	);
    });
    </script>
</head>
<body>
  <form action="/webBoard/loginAction.do" method="post">
    <table>
      <tbody>
      
        <tr>
          <th>아이디</th>
          <td><input type="text" name="id" size="10" required="required"></td>
        </tr>
        
        <tr>
          <th>비밀번호</th>
          <td><input type="password" name="passwd" size="10" required="required"></td>
        </tr>
        
        <tr>
          <td colspan="2">
            <input type="submit" value="전송">
          </td>
        </tr>
        
      </tbody>
    </table>
  </form>
</body>
</html>

----------LoginAction----------

package member;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginAction implements CommandAction {

@Override
public String requestPro(HttpServletRequest request, 
		                 HttpServletResponse response) throws ServletException,
                                                              IOException {
	// 데이터베이스를 통해서 로그인이 맞는지 확인하고 
	// 회원이 맞으면 main.jsp 보내고
	// 회원이 아니면 다시 로그인으로 보내기
	return "member/login.jsp";
	}
}

----------LoginProAction----------

package member;

import java.io.IOException;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import member.model.MemberDAO;

public class LoginProAction implements CommandAction {

@Override
public String requestPro(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	
	String id = request.getParameter("id");
	String passwd = request.getParameter("passwd");
	
	System.out.println("id:::"+id);
	System.out.println("passwd:::"+passwd);
    
	/* 
       Session이라는 객체를 만들어서 사용할건데
	   클라이언트와 서버가 연결되는 경우 연겨로간계를 설정하고 알고 있는 상태를 session이 연결되었다.
	   연결되어 있는 상태이면 서버가 그 클라이언트를 인정하는 상태가 됨
	   이름-값의 형태로 저장
	   세션 설정시간을 설정해 주기도 함(디폴트 값은 30분)
	   setAttribute가 있고, getAttribute가 있음
	   세션 종료 모든 세션 정보를 삭제(invalidate())
	   특정 세션만을 삭제(removeAttribute)
	   getAttributeNames() 모든 속성의 이름을 가져와라
	*/
    
	// 데이터베이스에 접근해서 결과를 받아오게...DAO
	
	/* 데이터베이스 일하는 객체 생성해서 거기에서 내가 시키고 싶은 메소드 호출
	   DAO 객체(인스턴스)를 얻고, 거기에서 아이디와 비밀번호가 맞는지 확인하는 메소드 호출 */
	
	/* 모델을 통해서 테이터베이스와 데이터 전송 객체를 사용해서 결과를 받기 */
	// login이 성공했을 때
	       HttpSession session = request.getSession(false);
	String view = null;
	MemberDAO dao = MemberDAO.getInstance();
	// 아이디, 비밀번호 맞는지 확인해, 라는 메소드를 실행
	try {
		boolean result = dao.loginAction(id, passwd);
		System.out.println(result);
		if(result) {
			// 세션을 설정
			session.setAttribute("uid", id);
			view  = "main.do";
		}else{
			session = null;
			view = "login.do";
	    }
	} catch (ClassNotFoundException e) {
		System.out.println(e.getMessage());
	} catch (SQLException e) {
		System.out.println(e.getMessage());
	}
	return view;
	}
}

----------CommandAction----------

package member;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 공통된 메소드를 쓰게 하려고 인터페이스 생성
public interface CommandAction {
    public String requestPro(HttpServletRequest request,
                             HttpServletResponse response)throws ServletException,
                                                                 IOException;
}

----------memberController----------

package member;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class memberController
 */
// @WebServlet("/member")
@WebServlet(
        name = "MemberController",
        urlPatterns = {"*.do"})
public class MemberController extends HttpServlet {
    private static final long serialVersionUID = 1L;
   
/**
 * @see HttpServlet#HttpServlet()
 */
public MemberController() {
    super();
    
}

/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 */
protected void doGet(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
//		response.getWriter().append("Served at: ").append(request.getContextPath());
	requestPro(request, response);
}

/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 */
protected void doPost(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
	requestPro(request, response);
}
 
public void requestPro(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	String view = null;
	CommandAction com = null;

	//해당 request를 받아서 해당 업무로직을 생성하고 호출할거임.
	String command = request.getRequestURI();
	if(command.indexOf(request.getContextPath())==0) {
		command = command.substring(request.getContextPath().length());
	}
//		System.out.println("command ::: "+command); 안쓰는게 좋음 log설정하는게 좋음.
	switch(command) {
	case "/login.do":{ //아이디, 패스워드 받기 위해서 화면만 띄우기
		com = new LoginAction();
		view = com.requestPro(request, response);
		break;
	}
	case "/loginAction.do":{//id,pw검증
		com = new LoginProAction();
		view = com.requestPro(request, response);
		break;
	}
	case "/logout.do":{ // 로그 아웃
	     com = new LogOutAction();
	     view = com.requestPro(request, response);
	     break;
	     }
	case "/memberlist.do":{ 
	     com = new MemberListAtion();
	     view = com.requestPro(request, response);
	     break;
	     }
	case "/main.do":
	{ 
		view = "member/main.jsp";
		break;
	}
	default:view = "member/main.jsp";
	}
//		com = new LoginAction();
//		view = com.requestPro(request, response);
//		System.out.println(view);
	
    //들어오면 원하는 기능에 해당되는 (비지니스 로직)파일로 보내면 일을하고 돌아와서 view로 리턴
	
	
	// view로 호출해서 전달하기 위한 객체
	System.out.println(view);
	RequestDispatcher dispatcher =request.getRequestDispatcher(view);
	if(view.contains(".do")) {
		response.sendRedirect(view);
	}else {
	  dispatcher.forward(request, response);
		}
	}
}

----------LogOutAction----------

package member;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LogOutAction implements CommandAction {

@Override
public String requestPro(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	// 세션을 받아서
	  HttpSession session = request.getSession(false);
	  if(session.getAttribute("uid")!= null)
		  session.removeAttribute("uid");
	// 모두 삭제
	  session.invalidate();
	  session = null;
	return "login.do";
	}
}

----------MemberListAtion----------

package member;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import member.model.MemberDAO;
import member.model.MemberDTO;

public class MemberListAtion implements CommandAction {

@Override
public String requestPro(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	// 데이터베이스에서 모든 회원정보를 받아와서
	MemberDAO dao = MemberDAO.getInstance();
	// 전손 후 가방인 DTO안에 넣어서 리스트 안에 저장
	List<MemberDTO> members = null;
	try {
		members = dao.getMemberList();
	} catch (ClassNotFoundException e) {
		System.out.println(e.getMessage());
	} catch (SQLException e) {
		System.out.println(e.getMessage());
	}
	request.setAttribute("members", members);
	return "member/list.jsp";
	}
}

----------MemberDTO----------

package member.model;

public class MemberDTO {
private String id;
private String name;
private String passwd;
public String getId() {
	return id;
}
public void setId(String id) {
	this.id = id;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public String getPasswd() {
	return passwd;
}
public void setPasswd(String passwd) {
	this.passwd = passwd;
	}
}

----------MemberDAO----------

package member.model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class MemberDAO {

//인스턴스 객체를 선언 private
private static MemberDAO instance = new MemberDAO();

private Connection getConnection() throws ClassNotFoundException, SQLException {
	Class.forName("com.mysql.cj.jdbc.Driver");
	Connection conn=
			DriverManager
			.getConnection("jdbc:mysql://localhost:3306/boarddb","root","1234");
	return conn;
}
private MemberDAO() {}

public static MemberDAO getInstance() {
	return instance;
}

public boolean loginAction(String id, String passwd) 
		       throws ClassNotFoundException, SQLException {
	boolean result = false;
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	try {
		String sql = "select count(*) from member where id=? and passwd=?";
		conn = getConnection();
		pstmt = conn.prepareStatement(sql);
		pstmt.setString(1, id);
		pstmt.setString(2, passwd);
		rs = pstmt.executeQuery();
		
		if(rs.next()) {// 결과를 받아온게 있으면
			int r = rs.getInt(1);
			if(r==0) result = false;
			else if (r==1) result = true;
		}
	}catch(Exception e) {
		System.out.println(e.getMessage());
	}finally {
		if(rs!=null)rs.close();
		if(pstmt!=null)pstmt.close();
		if(conn!=null)conn.close();
	}
	
	return result;		
}
public List<MemberDTO> getMemberList() 
		throws ClassNotFoundException, SQLException {
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	// 데이터베이스 연결
	// 쿼리 문 만들고
	// 데이터베이스에서 받아온 ResultSet을 while을 통해서 하나씩 읽어서 DTO에 저장하고
	// 리스트에 추가하고 리턴
	List<MemberDTO> list = null; // 선언
	try {
		conn = getConnection();
		String sql = "select id, name, passwd \n";
		       sql += "from member";
		pstmt = conn.prepareStatement(sql);
		rs = pstmt.executeQuery();
		list = new ArrayList<MemberDTO>(); // 생성
		// 여러개 가져오면 while
	    while(rs.next()) {
	    	// 하나의 레코드를 저장하기 위한 객체
	    	MemberDTO dto = new MemberDTO();
	    	// dto에 id을 저장하는데 setId, id정보는 rs에 있고 데이터베이스의 필드명이 id
	    	// rs.getString("필드명"), rs.getInt("필드명")
	    	dto.setId(rs.getString("id"));
	    	dto.setName(rs.getString("name"));
	    	dto.setPasswd(rs.getString("passwd"));
	    	list.add(dto);
	    }
	}catch(Exception e) {
		System.out.println(e.getMessage());
	}finally {
		if(rs!=null)rs.close();
		if(pstmt!=null)pstmt.close();
		if(conn!=null)conn.close();
    }
	return list;
	}
}

----------webBorad.webapp.member.main----------

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Main</title>
<style type="text/css">
  *{margin: 0 auto;}
</style>

</head>
<body>
<%@ include file="top.jsp" %>
  <div style="text-align: center;">
    <img alt="" src="images/tree-4.jpg">
  </div>
<%@ include file="bottom.jsp" %>
</body>
</html>

----------webBorad.webapp.member.list----------

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style type="text/css">
*{
width: 500;
margin: 0 auto;
}
</style>
<title>회원정보</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
</head>
<%@include file="top.jsp" %>
<body>
  <h3 style="text-align: center;">회원리스트</h3>
    <c:choose>
      <c:when test="${members ==null or fn:length(members)==0 }">
        <table>
          <tbody>
            <tr>
              <td>아직 회원이 없습니다.</td>
            </tr>
          </tbody>
        </table>
      </c:when>
      <c:when test="${members == null or fn:length(members)>0}">
        <table>
          <tbody>
          
            <!-- 반복문 돌리기 forEach 자바의 확장형 for문과 같은 처리 방법
                 items에 들어가는 것은 내부에서 전달된 배열이나 list형태
                 var는 해당하는 리스트의 한개씩 받는 변수             -->
              <tr>
                <th>아이디</th><th>이름</th>
              </tr> 
                  
                <c:forEach var="member" items="${members}">
            
              <tr>
                <td>${member.id}</td><td>${member.name}</td>
              </tr>
                <td>${member.id}</td>
                <td>
                  <input type="hidden" value="${member.passwd}"/>
                </td>
            </c:forEach>
          </tbody>
        </table>
      </c:when>
    </c:choose>
</body>
</html>

----------webBorad.webapp.member.top----------

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri ="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style type="text/css">
ul{
list-style-type: none;
}
li{
display: inline-block;
margin: 12px 30px 0 50px;
font-size: 13px;
}
.container li a:link{
text-decoration: none;
color: black;
}
.container li a:visited{
text-decoration: none;
color: black;
}
.container li a:active{
text-decoration: none;
color: black;
}
.container{
width: 500;
margin: 0 auto;
}
</style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
  <script type="text/javascript">
  $().ready(function(){
  	$('#logout').click(function(){
  	 	location.href = "./logout.do"
  	  }
  	);
  });
</script>
</head>
<c:choose>
  <c:when test="${uid==null or fn:length(uid)==0}">
    <script type="text/javascript">
      alert("세션이 없거나 종료되었습니다.\n 로그인 하시오")
      location.href = "./login.do"
    </script>
  </c:when>
  <c:when test="${uid!=null and fn:length(uid)>0}">
    <p style="text-align: right;"><c:out value="${uid}님 반갑습니다."/>
      <button id="logout">로그아웃</button>
    </p>

<div class="container">
  <ul>
    <li><a href="insertMem.do">회원등록</a></li>
    <li><a href="memberlist.do">회원리스트</a></li>
  </ul>
</div>
</c:when>
</c:choose>

----------webBorad.webapp.member.bottom----------

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<hr>
<div style="text-align: right;">좋은회사(주)</div>

</body>
</html>


회원 리스트 클릭

로그아웃을 크릭하면 로그인 화면으로 돌아감

0개의 댓글